Skip to content

Commit f718023

Browse files
authored
Using the new HttpClient in messaging module (#301)
* Using the new http client in FCM module * Added isJson property to HttpResponse * Renamed isJson to contentJson * Made isJson() a method
1 parent f1423e3 commit f718023

File tree

5 files changed

+153
-187
lines changed

5 files changed

+153
-187
lines changed

src/messaging/messaging-api-request.ts

Lines changed: 56 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,15 @@
1515
*/
1616

1717
import {FirebaseApp} from '../firebase-app';
18-
import {HttpMethod, SignedApiRequestHandler} from '../utils/api-request';
19-
import {FirebaseError, FirebaseMessagingError, MessagingClientErrorCode} from '../utils/error';
18+
import {HttpMethod, AuthorizedHttpClient, HttpRequestConfig, HttpError} from '../utils/api-request';
19+
import {FirebaseMessagingError, MessagingClientErrorCode} from '../utils/error';
2020

2121
import * as validator from '../utils/validator';
2222

2323
// FCM backend constants
24-
const FIREBASE_MESSAGING_PORT = 443;
2524
const FIREBASE_MESSAGING_TIMEOUT = 10000;
2625
const FIREBASE_MESSAGING_HTTP_METHOD: HttpMethod = 'POST';
2726
const FIREBASE_MESSAGING_HEADERS = {
28-
'Content-Type': 'application/json',
2927
'Sdk-Version': 'Node/Admin/<XXX_SDK_VERSION_XXX>',
3028
'access_token_auth': 'true',
3129
};
@@ -35,7 +33,7 @@ const FIREBASE_MESSAGING_HEADERS = {
3533
* Class that provides a mechanism to send requests to the Firebase Cloud Messaging backend.
3634
*/
3735
export class FirebaseMessagingRequestHandler {
38-
private signedApiRequestHandler: SignedApiRequestHandler;
36+
private readonly httpClient: AuthorizedHttpClient;
3937

4038
/**
4139
* @param {object} response The response to check for errors.
@@ -84,7 +82,7 @@ export class FirebaseMessagingRequestHandler {
8482
* @constructor
8583
*/
8684
constructor(app: FirebaseApp) {
87-
this.signedApiRequestHandler = new SignedApiRequestHandler(app);
85+
this.httpClient = new AuthorizedHttpClient(app);
8886
}
8987

9088
/**
@@ -96,76 +94,70 @@ export class FirebaseMessagingRequestHandler {
9694
* @return {Promise<object>} A promise that resolves with the response.
9795
*/
9896
public invokeRequestHandler(host: string, path: string, requestData: object): Promise<object> {
99-
return this.signedApiRequestHandler.sendRequest(
100-
host,
101-
FIREBASE_MESSAGING_PORT,
102-
path,
103-
FIREBASE_MESSAGING_HTTP_METHOD,
104-
requestData,
105-
FIREBASE_MESSAGING_HEADERS,
106-
FIREBASE_MESSAGING_TIMEOUT,
107-
).then((response) => {
97+
const request: HttpRequestConfig = {
98+
method: FIREBASE_MESSAGING_HTTP_METHOD,
99+
url: `https://${host}${path}`,
100+
data: requestData,
101+
headers: FIREBASE_MESSAGING_HEADERS,
102+
timeout: FIREBASE_MESSAGING_TIMEOUT,
103+
};
104+
return this.httpClient.send(request).then((response) => {
108105
// Send non-JSON responses to the catch() below where they will be treated as errors.
109-
if (typeof response === 'string') {
110-
return Promise.reject({
111-
error: response,
112-
statusCode: 200,
113-
});
106+
if (!response.isJson()) {
107+
throw new HttpError(response);
114108
}
115109

116110
// Check for backend errors in the response.
117-
const errorCode = FirebaseMessagingRequestHandler.getErrorCode(response);
111+
const errorCode = FirebaseMessagingRequestHandler.getErrorCode(response.data);
118112
if (errorCode) {
119-
return Promise.reject({
120-
error: response,
121-
statusCode: 200,
122-
});
113+
throw new HttpError(response);
123114
}
124115

125116
// Return entire response.
126-
return response;
117+
return response.data;
127118
})
128-
.catch((response: { statusCode: number, error: string | object }) => {
129-
// Re-throw the error if it already has the proper format.
130-
if (response instanceof FirebaseError) {
131-
throw response;
132-
} else if (response.error instanceof FirebaseError) {
133-
throw response.error;
134-
}
135-
136-
// Add special handling for non-JSON responses.
137-
if (typeof response.error === 'string') {
138-
let error;
139-
switch (response.statusCode) {
140-
case 400:
141-
error = MessagingClientErrorCode.INVALID_ARGUMENT;
142-
break;
143-
case 401:
144-
case 403:
145-
error = MessagingClientErrorCode.AUTHENTICATION_ERROR;
146-
break;
147-
case 500:
148-
error = MessagingClientErrorCode.INTERNAL_ERROR;
149-
break;
150-
case 503:
151-
error = MessagingClientErrorCode.SERVER_UNAVAILABLE;
152-
break;
153-
default:
154-
// Treat non-JSON responses with unexpected status codes as unknown errors.
155-
error = MessagingClientErrorCode.UNKNOWN_ERROR;
156-
}
157-
158-
throw new FirebaseMessagingError({
159-
code: error.code,
160-
message: `${ error.message } Raw server response: "${ response.error }". Status code: ` +
161-
`${ response.statusCode }.`,
162-
});
119+
.catch((err) => {
120+
if (err instanceof HttpError) {
121+
this.handleHttpError(err);
163122
}
123+
// Re-throw the error if it already has the proper format.
124+
throw err;
125+
});
126+
}
164127

128+
private handleHttpError(err: HttpError) {
129+
if (err.response.isJson()) {
165130
// For JSON responses, map the server response to a client-side error.
166-
const errorCode = FirebaseMessagingRequestHandler.getErrorCode(response.error);
167-
const errorMessage = FirebaseMessagingRequestHandler.getErrorMessage(response.error);
168-
throw FirebaseMessagingError.fromServerError(errorCode, errorMessage, response.error);
131+
const json = err.response.data;
132+
const errorCode = FirebaseMessagingRequestHandler.getErrorCode(json);
133+
const errorMessage = FirebaseMessagingRequestHandler.getErrorMessage(json);
134+
throw FirebaseMessagingError.fromServerError(errorCode, errorMessage, json);
135+
}
136+
137+
// Non-JSON response
138+
let error: {code: string, message: string};
139+
switch (err.response.status) {
140+
case 400:
141+
error = MessagingClientErrorCode.INVALID_ARGUMENT;
142+
break;
143+
case 401:
144+
case 403:
145+
error = MessagingClientErrorCode.AUTHENTICATION_ERROR;
146+
break;
147+
case 500:
148+
error = MessagingClientErrorCode.INTERNAL_ERROR;
149+
break;
150+
case 503:
151+
error = MessagingClientErrorCode.SERVER_UNAVAILABLE;
152+
break;
153+
default:
154+
// Treat non-JSON responses with unexpected status codes as unknown errors.
155+
error = MessagingClientErrorCode.UNKNOWN_ERROR;
156+
}
157+
throw new FirebaseMessagingError({
158+
code: error.code,
159+
message: `${ error.message } Raw server response: "${ err.response.text }". Status code: ` +
160+
`${ err.response.status }.`,
169161
});
170162
}
171163
}

src/utils/api-request.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ export interface HttpResponse {
5454
readonly text: string;
5555
/** Response data as a parsed JSON object. */
5656
readonly data: any;
57+
/**
58+
* Indicates if the response content is JSON-formatted or not. If true, data field can be used
59+
* to retrieve the content as a parsed JSON object.
60+
*/
61+
isJson(): boolean;
5762
}
5863

5964
interface LowLevelResponse {
@@ -98,7 +103,7 @@ class DefaultHttpResponse implements HttpResponse {
98103
}
99104

100105
get data(): any {
101-
if (typeof this.parsedData !== 'undefined') {
106+
if (this.isJson()) {
102107
return this.parsedData;
103108
}
104109
throw new FirebaseAppError(
@@ -108,6 +113,10 @@ class DefaultHttpResponse implements HttpResponse {
108113
`request: "${ this.request }."`,
109114
);
110115
}
116+
117+
public isJson(): boolean {
118+
return typeof this.parsedData !== 'undefined';
119+
}
111120
}
112121

113122
export class HttpError extends Error {

0 commit comments

Comments
 (0)