diff --git a/README.md b/README.md index 89f3474d..9ba5d8e3 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,29 @@ curl localhost:8080 # Output: Hello world! ``` +### Quickstart: Error handling + +The framework includes an error handler that is similar to the +[`flask.Flask.errorhandler`](https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.errorhandler) +function, which allows you to handle specific error types with a decorator: + +```python +import functions_framework + + +@functions_framework.errorhandler(ZeroDivisionError) +def handle_zero_division(e): + return "I'm a teapot", 418 + + +def function(request): + 1 / 0 + return "Success", 200 +``` + +This function will catch the `ZeroDivisionError` and return a different +response instead. + ### Quickstart: Build a Deployable Container 1. Install [Docker](https://store.docker.com/search?type=edition&offering=community) and the [`pack` tool](https://buildpacks.io/docs/install-pack/). diff --git a/src/functions_framework/__init__.py b/src/functions_framework/__init__.py index d86714e2..81b18225 100644 --- a/src/functions_framework/__init__.py +++ b/src/functions_framework/__init__.py @@ -228,6 +228,8 @@ def create_app(target=None, source=None, signature_type=None): # 5. Create the application app = flask.Flask(target, template_folder=template_folder) app.config["MAX_CONTENT_LENGTH"] = MAX_CONTENT_LENGTH + global errorhandler + errorhandler = app.errorhandler # 6. Execute the module, within the application context with app.app_context(): diff --git a/tests/test_functions.py b/tests/test_functions.py index b73988db..f408a786 100644 --- a/tests/test_functions.py +++ b/tests/test_functions.py @@ -359,3 +359,16 @@ def test_legacy_function_returns_none(monkeypatch): assert resp.status_code == 200 assert resp.data == b"OK" + + +def test_errorhandler(monkeypatch): + source = TEST_FUNCTIONS_DIR / "errorhandler" / "main.py" + target = "function" + + monkeypatch.setenv("ENTRY_POINT", target) + + client = create_app(target, source).test_client() + resp = client.get("/") + + assert resp.status_code == 418 + assert resp.data == b"I'm a teapot" diff --git a/tests/test_functions/errorhandler/main.py b/tests/test_functions/errorhandler/main.py new file mode 100644 index 00000000..588ef4ef --- /dev/null +++ b/tests/test_functions/errorhandler/main.py @@ -0,0 +1,25 @@ +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import functions_framework + + +@functions_framework.errorhandler(ZeroDivisionError) +def handle_zero_division(e): + return "I'm a teapot", 418 + + +def function(request): + 1 / 0 + return "Success", 200