|
16 | 16 | # pylint: disable=protected-access |
17 | 17 | import typing as _typing |
18 | 18 | import functools as _functools |
| 19 | +import dataclasses as _dataclasses |
| 20 | +import json as _json |
19 | 21 |
|
20 | | -from flask import Request, Response |
| 22 | +from flask import Request, Response, make_response as _make_response, jsonify as _jsonify |
21 | 23 |
|
| 24 | +import firebase_functions.core as _core |
22 | 25 | import firebase_functions.options as _options |
23 | 26 | import firebase_functions.private.util as _util |
24 | | -from firebase_functions.https_fn import CallableRequest, _on_call_handler |
| 27 | +from firebase_functions.https_fn import CallableRequest, HttpsError, FunctionsErrorCode |
| 28 | + |
| 29 | +from functions_framework import logging as _logging |
25 | 30 |
|
26 | 31 | _C = _typing.Callable[[CallableRequest[_typing.Any]], _typing.Any] |
| 32 | +_C1 = _typing.Callable[[Request], Response] |
| 33 | +_C2 = _typing.Callable[[CallableRequest[_typing.Any]], _typing.Any] |
| 34 | + |
| 35 | + |
| 36 | +def _on_call_handler(func: _C2, request: Request) -> Response: |
| 37 | + try: |
| 38 | + if not _util.valid_on_call_request(request): |
| 39 | + _logging.error("Invalid request, unable to process.") |
| 40 | + raise HttpsError(FunctionsErrorCode.INVALID_ARGUMENT, "Bad Request") |
| 41 | + context: CallableRequest = CallableRequest( |
| 42 | + raw_request=request, |
| 43 | + data=_json.loads(request.data)["data"], |
| 44 | + ) |
| 45 | + |
| 46 | + instance_id = request.headers.get("Firebase-Instance-ID-Token") |
| 47 | + if instance_id is not None: |
| 48 | + # Validating the token requires an http request, so we don't do it. |
| 49 | + # If the user wants to use it for something, it will be validated then. |
| 50 | + # Currently, the only real use case for this token is for sending |
| 51 | + # pushes with FCM. In that case, the FCM APIs will validate the token. |
| 52 | + context = _dataclasses.replace( |
| 53 | + context, |
| 54 | + instance_id_token=request.headers.get( |
| 55 | + "Firebase-Instance-ID-Token"), |
| 56 | + ) |
| 57 | + result = _core._with_init(func)(context) |
| 58 | + return _jsonify(result=result) |
| 59 | + # Disable broad exceptions lint since we want to handle all exceptions here |
| 60 | + # and wrap as an HttpsError. |
| 61 | + # pylint: disable=broad-except |
| 62 | + except Exception as err: |
| 63 | + if not isinstance(err, HttpsError): |
| 64 | + _logging.error("Unhandled error: %s", err) |
| 65 | + err = HttpsError(FunctionsErrorCode.INTERNAL, "INTERNAL") |
| 66 | + status = err._http_error_code.status |
| 67 | + return _make_response(_jsonify(error=err._as_dict()), status) |
27 | 68 |
|
28 | 69 |
|
29 | 70 | @_util.copy_func_kwargs(_options.TaskQueueOptions) |
@@ -53,10 +94,7 @@ def on_task_dispatched_decorator(func: _C): |
53 | 94 |
|
54 | 95 | @_functools.wraps(func) |
55 | 96 | def on_task_dispatched_wrapped(request: Request) -> Response: |
56 | | - return _on_call_handler(func, |
57 | | - request, |
58 | | - enforce_app_check=False, |
59 | | - verify_token=False) |
| 97 | + return _on_call_handler(func, request) |
60 | 98 |
|
61 | 99 | _util.set_func_endpoint_attr( |
62 | 100 | on_task_dispatched_wrapped, |
|
0 commit comments