function wrapOnCallHandler()

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);
    }
  };
}