diff --git a/CHANGELOG.md b/CHANGELOG.md index d0226093..a2036832 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Support `cloudevent` signature type ([#55], [#56]) +## [1.6.0] - 2020-08-19 +### Changed +- Add legacy GCF Python 3.7 behavior ([#77]) + +### Added +- Improve documentation around Dockerfiles ([#70]) + +## [1.5.0] - 2020-07-06 ### Changed - Framework will consume entire request before responding ([#66]) @@ -74,6 +82,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [Unreleased]: https://github.com/GoogleCloudPlatform/functions-framework-python/compare/v2.0.0...HEAD [2.0.0]: https://github.com/GoogleCloudPlatform/functions-framework-python/releases/tag/v2.0.0 +[1.6.0]: https://github.com/GoogleCloudPlatform/functions-framework-python/releases/tag/v1.6.0 +[1.5.0]: https://github.com/GoogleCloudPlatform/functions-framework-python/releases/tag/v1.5.0 [1.4.4]: https://github.com/GoogleCloudPlatform/functions-framework-python/releases/tag/v1.4.4 [1.4.3]: https://github.com/GoogleCloudPlatform/functions-framework-python/releases/tag/v1.4.3 [1.4.2]: https://github.com/GoogleCloudPlatform/functions-framework-python/releases/tag/v1.4.2 @@ -86,7 +96,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [1.0.1]: https://github.com/GoogleCloudPlatform/functions-framework-python/releases/tag/v1.0.1 [1.0.0]: https://github.com/GoogleCloudPlatform/functions-framework-python/releases/tag/v1.0.0 +[#77]: https://github.com/GoogleCloudPlatform/functions-framework-python/pull/77 [#76]: https://github.com/GoogleCloudPlatform/functions-framework-python/pull/76 +[#70]: https://github.com/GoogleCloudPlatform/functions-framework-python/pull/70 [#66]: https://github.com/GoogleCloudPlatform/functions-framework-python/pull/66 [#61]: https://github.com/GoogleCloudPlatform/functions-framework-python/pull/61 [#56]: https://github.com/GoogleCloudPlatform/functions-framework-python/pull/56 diff --git a/src/functions_framework/__init__.py b/src/functions_framework/__init__.py index f89e05ee..575c93d9 100644 --- a/src/functions_framework/__init__.py +++ b/src/functions_framework/__init__.py @@ -233,6 +233,19 @@ def create_app(target=None, source=None, signature_type=None): with app.app_context(): spec.loader.exec_module(source_module) + # Handle legacy GCF Python 3.7 behavior + if os.environ.get("ENTRY_POINT"): + os.environ["FUNCTION_TRIGGER_TYPE"] = signature_type + os.environ["FUNCTION_NAME"] = os.environ.get("K_SERVICE", target) + app.make_response_original = app.make_response + + def handle_none(rv): + if rv is None: + rv = "OK" + return app.make_response_original(rv) + + app.make_response = handle_none + # Extract the target function from the source file try: function = getattr(source_module, target) diff --git a/tests/test_functions.py b/tests/test_functions.py index f03569b0..9f2686e4 100644 --- a/tests/test_functions.py +++ b/tests/test_functions.py @@ -11,6 +11,8 @@ # 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 os import pathlib import re import time @@ -318,3 +320,42 @@ def test_flask_current_app_is_available(): resp = client.get("/") assert resp.status_code == 200 + + +def test_function_returns_none(): + source = TEST_FUNCTIONS_DIR / "returns_none" / "main.py" + target = "function" + + client = create_app(target, source).test_client() + resp = client.get("/") + + assert resp.status_code == 500 + + +def test_legacy_function_check_env(monkeypatch): + source = TEST_FUNCTIONS_DIR / "http_check_env" / "main.py" + target = "function" + + monkeypatch.setenv("ENTRY_POINT", target) + + client = create_app(target, source).test_client() + resp = client.post("/", json={"mode": "FUNCTION_TRIGGER_TYPE"}) + assert resp.status_code == 200 + assert resp.data == b"http" + + resp = client.post("/", json={"mode": "FUNCTION_NAME"}) + assert resp.status_code == 200 + assert resp.data.decode("utf-8") == target + + +def test_legacy_function_returns_none(monkeypatch): + source = TEST_FUNCTIONS_DIR / "returns_none" / "main.py" + target = "function" + + monkeypatch.setenv("ENTRY_POINT", target) + + client = create_app(target, source).test_client() + resp = client.get("/") + + assert resp.status_code == 200 + assert resp.data == b"OK" diff --git a/tests/test_functions/returns_none/main.py b/tests/test_functions/returns_none/main.py new file mode 100644 index 00000000..f6a4acaa --- /dev/null +++ b/tests/test_functions/returns_none/main.py @@ -0,0 +1,27 @@ +# 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. + + +def function(request): + """Test HTTP function when using legacy GCF behavior. + + The function returns None, which should be a 200 response. + + Args: + request: The HTTP request which triggered this function. + + Returns: + None. + """ + return None