Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Emit PNDisconnectedUnexpectedlyCategory #438

Merged
merged 2 commits into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
501 changes: 150 additions & 351 deletions dist/web/pubnub.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/web/pubnub.min.js

Large diffs are not rendered by default.

18 changes: 13 additions & 5 deletions dist/web/pubnub.worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,15 @@
const clients = getClients();
if (clients.length === 0)
return;
failure(clients, error);
let fetchError = error;
if (typeof error === 'string') {
const errorMessage = error.toLowerCase();
if (errorMessage.includes('timeout') || !errorMessage.includes('cancel'))
fetchError = new Error(error);
else if (errorMessage.includes('cancel'))
fetchError = new DOMException('Aborted', 'AbortError');
}
failure(clients, fetchError);
});
}))();
};
Expand All @@ -564,7 +572,7 @@
delete serviceRequests[requestId];
// Abort request if possible.
if (controller)
controller.abort();
controller.abort('Cancel request');
}
};
/**
Expand Down Expand Up @@ -1081,12 +1089,12 @@
message = error.message;
name = error.name;
}
if (name === 'AbortError') {
if (message.toLowerCase().includes('timeout'))
type = 'TIMEOUT';
else if (name === 'AbortError' || message.toLowerCase().includes('cancel')) {
message = 'Request aborted';
type = 'ABORTED';
}
else if (message === 'Request timeout')
type = 'TIMEOUT';
return {
type: 'request-process-error',
clientIdentifier: '',
Expand Down
4 changes: 2 additions & 2 deletions dist/web/pubnub.worker.min.js

Large diffs are not rendered by default.

34 changes: 23 additions & 11 deletions lib/core/components/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.AbstractRequest = void 0;
const transport_request_1 = require("../types/transport-request");
const pubnub_error_1 = require("../../errors/pubnub-error");
const uuid_1 = __importDefault(require("./uuid"));
const pubnub_api_error_1 = require("../../errors/pubnub-api-error");
/**
* Base REST API request class.
*
Expand Down Expand Up @@ -62,10 +64,12 @@ class AbstractRequest {
}
/**
* Abort request if possible.
*
* @param [reason] Information about why request has been cancelled.
*/
abort() {
abort(reason) {
if (this && this.cancellationController)
this.cancellationController.abort();
this.cancellationController.abort(reason);
}
/**
* Target REST API endpoint operation type.
Expand All @@ -84,11 +88,11 @@ class AbstractRequest {
/**
* Parse service response.
*
* @param _response - Raw service response which should be parsed.
* @param response - Raw service response which should be parsed.
*/
parse(_response) {
parse(response) {
return __awaiter(this, void 0, void 0, function* () {
throw Error('Should be implemented by subclass.');
return this.deserializeResponse(response);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻

});
}
/**
Expand Down Expand Up @@ -160,21 +164,29 @@ class AbstractRequest {
*
* @param response - Transparent response object with headers and body information.
*
* @returns Deserialized data or `undefined` in case of `JSON.parse(..)` error.
* @returns Deserialized service response data.
*
* @throws {Error} if received service response can't be processed (has unexpected content-type or can't be parsed as
* JSON).
*/
deserializeResponse(response) {
const responseText = AbstractRequest.decoder.decode(response.body);
const contentType = response.headers['content-type'];
let parsedJson;
if (!contentType || (contentType.indexOf('javascript') === -1 && contentType.indexOf('json') === -1))
return undefined;
const json = AbstractRequest.decoder.decode(response.body);
throw new pubnub_error_1.PubNubError('Service response error, check status for details', (0, pubnub_error_1.createMalformedResponseError)(responseText, response.status));
try {
const parsedJson = JSON.parse(json);
return parsedJson;
parsedJson = JSON.parse(responseText);
}
catch (error) {
console.error('Error parsing JSON response:', error);
return undefined;
throw new pubnub_error_1.PubNubError('Service response error, check status for details', (0, pubnub_error_1.createMalformedResponseError)(responseText, response.status));
}
// Throw and exception in case of client / server error.
if ('status' in parsedJson && typeof parsedJson.status === 'number' && parsedJson.status >= 400) {
throw pubnub_api_error_1.PubNubAPIError.create(response);
}
return parsedJson;
}
}
exports.AbstractRequest = AbstractRequest;
Expand Down
14 changes: 8 additions & 6 deletions lib/core/components/subscription-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.SubscriptionManager = void 0;
const reconnection_manager_1 = require("./reconnection_manager");
const categories_1 = __importDefault(require("../constants/categories"));
const deduping_manager_1 = require("./deduping_manager");
const categories_2 = __importDefault(require("../constants/categories"));
const deduping_manager_1 = require("./deduping_manager");
/**
* Subscription loop manager.
*
Expand Down Expand Up @@ -256,13 +256,15 @@ class SubscriptionManager {
this.reconnectionManager.startPolling();
this.listenerManager.announceStatus(status);
}
else if (status.category === categories_2.default.PNBadRequestCategory) {
this.stopHeartbeatTimer();
this.listenerManager.announceStatus(status);
else if (status.category === categories_2.default.PNBadRequestCategory ||
status.category == categories_2.default.PNMalformedResponseCategory) {
const category = this.isOnline ? categories_1.default.PNDisconnectedUnexpectedlyCategory : status.category;
this.isOnline = false;
this.disconnect();
this.listenerManager.announceStatus(Object.assign(Object.assign({}, status), { category }));
}
else {
else
this.listenerManager.announceStatus(status);
}
return;
}
if (this.storedTimetoken) {
Expand Down
8 changes: 8 additions & 0 deletions lib/core/constants/categories.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ var StatusCategory;
* Some API endpoints respond with request processing status w/o useful data.
*/
StatusCategory["PNAcknowledgmentCategory"] = "PNAcknowledgmentCategory";
/**
* PubNub service or intermediate "actor" returned unexpected response.
*
* There can be few sources of unexpected return with success code:
* - proxy server / VPN;
* - Wi-Fi hotspot authorization page.
*/
StatusCategory["PNMalformedResponseCategory"] = "PNMalformedResponseCategory";
/**
* Something strange happened; please check the logs.
*/
Expand Down
10 changes: 1 addition & 9 deletions lib/core/endpoints/access_manager/audit.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AuditRequest = void 0;
const pubnub_error_1 = require("../../../errors/pubnub-error");
const pubnub_api_error_1 = require("../../../errors/pubnub-api-error");
const request_1 = require("../../components/request");
const operations_1 = __importDefault(require("../../constants/operations"));
// --------------------------------------------------------
Expand Down Expand Up @@ -54,13 +52,7 @@ class AuditRequest extends request_1.AbstractRequest {
}
parse(response) {
return __awaiter(this, void 0, void 0, function* () {
const serviceResponse = this.deserializeResponse(response);
if (!serviceResponse) {
throw new pubnub_error_1.PubNubError('Service response error, check status for details', (0, pubnub_error_1.createValidationError)('Unable to deserialize service response'));
}
else if (serviceResponse.status >= 400)
throw pubnub_api_error_1.PubNubAPIError.create(response);
return serviceResponse.payload;
return this.deserializeResponse(response).payload;
});
}
get path() {
Expand Down
10 changes: 1 addition & 9 deletions lib/core/endpoints/access_manager/grant.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GrantRequest = void 0;
const pubnub_error_1 = require("../../../errors/pubnub-error");
const pubnub_api_error_1 = require("../../../errors/pubnub-api-error");
const request_1 = require("../../components/request");
const operations_1 = __importDefault(require("../../constants/operations"));
// --------------------------------------------------------
Expand Down Expand Up @@ -96,13 +94,7 @@ class GrantRequest extends request_1.AbstractRequest {
}
parse(response) {
return __awaiter(this, void 0, void 0, function* () {
const serviceResponse = this.deserializeResponse(response);
if (!serviceResponse) {
throw new pubnub_error_1.PubNubError('Service response error, check status for details', (0, pubnub_error_1.createValidationError)('Unable to deserialize service response'));
}
else if (serviceResponse.status >= 400)
throw pubnub_api_error_1.PubNubAPIError.create(response);
return serviceResponse.payload;
return this.deserializeResponse(response).payload;
});
}
get path() {
Expand Down
10 changes: 1 addition & 9 deletions lib/core/endpoints/access_manager/grant_token.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GrantTokenRequest = void 0;
const pubnub_error_1 = require("../../../errors/pubnub-error");
const pubnub_api_error_1 = require("../../../errors/pubnub-api-error");
const transport_request_1 = require("../../types/transport-request");
const request_1 = require("../../components/request");
const operations_1 = __importDefault(require("../../constants/operations"));
Expand Down Expand Up @@ -77,13 +75,7 @@ class GrantTokenRequest extends request_1.AbstractRequest {
}
parse(response) {
return __awaiter(this, void 0, void 0, function* () {
const serviceResponse = this.deserializeResponse(response);
if (!serviceResponse) {
throw new pubnub_error_1.PubNubError('Service response error, check status for details', (0, pubnub_error_1.createValidationError)('Unable to deserialize service response'));
}
else if (serviceResponse.status >= 400)
throw pubnub_api_error_1.PubNubAPIError.create(response);
return serviceResponse.data.token;
return this.deserializeResponse(response).data.token;
});
}
get path() {
Expand Down
13 changes: 4 additions & 9 deletions lib/core/endpoints/access_manager/revoke_token.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RevokeTokenRequest = void 0;
const pubnub_error_1 = require("../../../errors/pubnub-error");
const pubnub_api_error_1 = require("../../../errors/pubnub-api-error");
const transport_request_1 = require("../../types/transport-request");
const request_1 = require("../../components/request");
const operations_1 = __importDefault(require("../../constants/operations"));
Expand Down Expand Up @@ -47,14 +45,11 @@ class RevokeTokenRequest extends request_1.AbstractRequest {
return "token can't be empty";
}
parse(response) {
const _super = Object.create(null, {
parse: { get: () => super.parse }
});
return __awaiter(this, void 0, void 0, function* () {
const serviceResponse = this.deserializeResponse(response);
if (!serviceResponse) {
throw new pubnub_error_1.PubNubError('Service response error, check status for details', (0, pubnub_error_1.createValidationError)('Unable to deserialize service response'));
}
else if (serviceResponse.status >= 400)
throw pubnub_api_error_1.PubNubAPIError.create(response);
return {};
return _super.parse.call(this, response).then(() => ({}));
});
}
get path() {
Expand Down
13 changes: 4 additions & 9 deletions lib/core/endpoints/actions/add_message_action.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AddMessageActionRequest = void 0;
const pubnub_error_1 = require("../../../errors/pubnub-error");
const pubnub_api_error_1 = require("../../../errors/pubnub-api-error");
const transport_request_1 = require("../../types/transport-request");
const request_1 = require("../../components/request");
const operations_1 = __importDefault(require("../../constants/operations"));
Expand Down Expand Up @@ -56,14 +54,11 @@ class AddMessageActionRequest extends request_1.AbstractRequest {
return 'Action.type value exceed maximum length of 15';
}
parse(response) {
const _super = Object.create(null, {
parse: { get: () => super.parse }
});
return __awaiter(this, void 0, void 0, function* () {
const serviceResponse = this.deserializeResponse(response);
if (!serviceResponse) {
throw new pubnub_error_1.PubNubError('Service response error, check status for details', (0, pubnub_error_1.createValidationError)('Unable to deserialize service response'));
}
else if (serviceResponse.status >= 400)
throw pubnub_api_error_1.PubNubAPIError.create(response);
return { data: serviceResponse.data };
return _super.parse.call(this, response).then(({ data }) => ({ data }));
});
}
get path() {
Expand Down
7 changes: 0 additions & 7 deletions lib/core/endpoints/actions/get_message_actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GetMessageActionsRequest = void 0;
const pubnub_error_1 = require("../../../errors/pubnub-error");
const pubnub_api_error_1 = require("../../../errors/pubnub-api-error");
const request_1 = require("../../components/request");
const operations_1 = __importDefault(require("../../constants/operations"));
const utils_1 = require("../../utils");
Expand All @@ -46,11 +44,6 @@ class GetMessageActionsRequest extends request_1.AbstractRequest {
parse(response) {
return __awaiter(this, void 0, void 0, function* () {
const serviceResponse = this.deserializeResponse(response);
if (!serviceResponse) {
throw new pubnub_error_1.PubNubError('Service response error, check status for details', (0, pubnub_error_1.createValidationError)('Unable to deserialize service response'));
}
else if (serviceResponse.status >= 400)
throw pubnub_api_error_1.PubNubAPIError.create(response);
let start = null;
let end = null;
if (serviceResponse.data.length > 0) {
Expand Down
13 changes: 4 additions & 9 deletions lib/core/endpoints/actions/remove_message_action.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RemoveMessageAction = void 0;
const pubnub_error_1 = require("../../../errors/pubnub-error");
const pubnub_api_error_1 = require("../../../errors/pubnub-api-error");
const transport_request_1 = require("../../types/transport-request");
const request_1 = require("../../components/request");
const operations_1 = __importDefault(require("../../constants/operations"));
Expand Down Expand Up @@ -50,14 +48,11 @@ class RemoveMessageAction extends request_1.AbstractRequest {
return 'Missing action timetoken';
}
parse(response) {
const _super = Object.create(null, {
parse: { get: () => super.parse }
});
return __awaiter(this, void 0, void 0, function* () {
const serviceResponse = this.deserializeResponse(response);
if (!serviceResponse) {
throw new pubnub_error_1.PubNubError('Service response error, check status for details', (0, pubnub_error_1.createValidationError)('Unable to deserialize service response'));
}
else if (serviceResponse.status >= 400)
throw pubnub_api_error_1.PubNubAPIError.create(response);
return { data: serviceResponse.data };
return _super.parse.call(this, response).then(({ data }) => ({ data }));
});
}
get path() {
Expand Down
13 changes: 4 additions & 9 deletions lib/core/endpoints/channel_groups/add_channels.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AddChannelGroupChannelsRequest = void 0;
const pubnub_error_1 = require("../../../errors/pubnub-error");
const pubnub_api_error_1 = require("../../../errors/pubnub-api-error");
const request_1 = require("../../components/request");
const operations_1 = __importDefault(require("../../constants/operations"));
const utils_1 = require("../../utils");
Expand Down Expand Up @@ -47,14 +45,11 @@ class AddChannelGroupChannelsRequest extends request_1.AbstractRequest {
return 'Missing channels';
}
parse(response) {
const _super = Object.create(null, {
parse: { get: () => super.parse }
});
return __awaiter(this, void 0, void 0, function* () {
const serviceResponse = this.deserializeResponse(response);
if (!serviceResponse) {
throw new pubnub_error_1.PubNubError('Service response error, check status for details', (0, pubnub_error_1.createValidationError)('Unable to deserialize service response'));
}
else if (serviceResponse.status >= 400)
throw pubnub_api_error_1.PubNubAPIError.create(response);
return {};
return _super.parse.call(this, response).then((_) => ({}));
});
}
get path() {
Expand Down
13 changes: 4 additions & 9 deletions lib/core/endpoints/channel_groups/delete_group.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DeleteChannelGroupRequest = void 0;
const pubnub_error_1 = require("../../../errors/pubnub-error");
const pubnub_api_error_1 = require("../../../errors/pubnub-api-error");
const request_1 = require("../../components/request");
const operations_1 = __importDefault(require("../../constants/operations"));
const utils_1 = require("../../utils");
Expand All @@ -44,14 +42,11 @@ class DeleteChannelGroupRequest extends request_1.AbstractRequest {
return 'Missing Channel Group';
}
parse(response) {
const _super = Object.create(null, {
parse: { get: () => super.parse }
});
return __awaiter(this, void 0, void 0, function* () {
const serviceResponse = this.deserializeResponse(response);
if (!serviceResponse) {
throw new pubnub_error_1.PubNubError('Service response error, check status for details', (0, pubnub_error_1.createValidationError)('Unable to deserialize service response'));
}
else if (serviceResponse.status >= 400)
throw pubnub_api_error_1.PubNubAPIError.create(response);
return {};
return _super.parse.call(this, response).then((_) => ({}));
});
}
get path() {
Expand Down
Loading
Loading