Skip to content

Commit c492b04

Browse files
authored
fix: streaming requests cannot access request data (GoogleCloudPlatform#245)
1 parent 21d9db1 commit c492b04

File tree

3 files changed

+62
-3
lines changed

3 files changed

+62
-3
lines changed

src/functions_framework/__init__.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,10 +294,13 @@ def _configure_app(app, function, signature_type):
294294
def read_request(response):
295295
"""
296296
Force the framework to read the entire request before responding, to avoid
297-
connection errors when returning prematurely.
297+
connection errors when returning prematurely. Skipped on streaming responses
298+
as these may continue to operate on the request after they are returned.
298299
"""
299300

300-
flask.request.get_data()
301+
if not response.is_streamed:
302+
flask.request.get_data()
303+
301304
return response
302305

303306

tests/test_functions.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
15+
import io
1616
import json
1717
import pathlib
1818
import re
@@ -490,6 +490,18 @@ def test_function_returns_none():
490490
assert resp.status_code == 500
491491

492492

493+
def test_function_returns_stream():
494+
source = TEST_FUNCTIONS_DIR / "http_streaming" / "main.py"
495+
target = "function"
496+
497+
client = create_app(target, source).test_client()
498+
resp = client.post("/", data="1\n2\n3\n4\n")
499+
500+
assert resp.status_code == 200
501+
assert resp.is_streamed
502+
assert resp.data.decode("utf-8") == "1.0\n3.0\n6.0\n10.0\n"
503+
504+
493505
def test_legacy_function_check_env(monkeypatch):
494506
source = TEST_FUNCTIONS_DIR / "http_check_env" / "main.py"
495507
target = "function"
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Copyright 2020 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Function used in Worker tests of handling HTTP functions."""
16+
17+
import flask
18+
19+
from flask import Response, stream_with_context
20+
21+
22+
def function(request):
23+
"""Test HTTP function that reads a stream of integers and returns a stream
24+
providing the sum of values read so far.
25+
26+
Args:
27+
request: The HTTP request which triggered this function. Must contain a
28+
stream of new line separated integers.
29+
30+
Returns:
31+
Value and status code defined for the given mode.
32+
33+
Raises:
34+
Exception: Thrown when requested in the incoming mode specification.
35+
"""
36+
print("INVOKED THE STREAM FUNCTION!!!")
37+
38+
def generate():
39+
sum_so_far = 0
40+
for line in request.stream:
41+
sum_so_far += float(line)
42+
yield (str(sum_so_far) + "\n").encode("utf-8")
43+
44+
return Response(stream_with_context(generate()))

0 commit comments

Comments
 (0)