in src/common/providers/https.ts [768:830]
function wrapOnCallHandler<Req = any, Res = any>(
options: CallableOptions,
handler: v1CallableHandler | v2CallableHandler<Req, Res>
): (req: Request, res: express.Response) => Promise<void> {
return async (req: Request, res: express.Response): Promise<void> => {
try {
if (!isValidRequest(req)) {
logger.error('Invalid request, unable to process.');
throw new HttpsError('invalid-argument', 'Bad Request');
}
const context: CallableContext = { rawRequest: req };
const tokenStatus = await checkTokens(req, context);
if (tokenStatus.auth === 'INVALID') {
throw new HttpsError('unauthenticated', 'Unauthenticated');
}
if (tokenStatus.app === 'INVALID' && !options.allowInvalidAppCheckToken) {
throw new HttpsError('unauthenticated', 'Unauthenticated');
}
const instanceId = req.header('Firebase-Instance-ID-Token');
if (instanceId) {
// Validating the token requires an http request, so we don't do it.
// If the user wants to use it for something, it will be validated then.
// Currently, the only real use case for this token is for sending
// pushes with FCM. In that case, the FCM APIs will validate the token.
context.instanceIdToken = req.header('Firebase-Instance-ID-Token');
}
const data: Req = decode(req.body.data);
let result: Res;
if (handler.length === 2) {
result = await handler(data, context);
} else {
const arg: CallableRequest<Req> = {
...context,
data,
};
// For some reason the type system isn't picking up that the handler
// is a one argument function.
result = await (handler as any)(arg);
}
// Encode the result as JSON to preserve types like Dates.
result = encode(result);
// If there was some result, encode it in the body.
const responseBody: HttpResponseBody = { result };
res.status(200).send(responseBody);
} catch (err) {
if (!(err instanceof HttpsError)) {
// This doesn't count as an 'explicit' error.
logger.error('Unhandled error', err);
err = new HttpsError('internal', 'INTERNAL');
}
const { status } = err.httpErrorCode;
const body = { error: err.toJSON() };
res.status(status).send(body);
}
};
}