Skip to content

Commit 9f74407

Browse files
committed
Support sending response as binary data
1 parent 8faa373 commit 9f74407

6 files changed

Lines changed: 54 additions & 4 deletions

File tree

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,32 @@ def handler(ctx, data: io.BytesIO=None):
7777

7878
```
7979

80+
## Writing binary data from functions
81+
In order to write a binary response to your function pass a `bytes` object to the response_data
82+
83+
```python
84+
import io
85+
from PIL import Image, ImageDraw
86+
from fdk import response
87+
88+
89+
def handler(ctx, data: io.BytesIO=None):
90+
img = Image.new('RGB', (100, 30), color='red')
91+
d = ImageDraw.Draw(img)
92+
d.text((10, 10), "hello world", fill=(255, 255, 0))
93+
# write png image to memory
94+
output = io.BytesIO()
95+
img.save(output, format="PNG")
96+
# get the bytes of the image
97+
imgbytes = output.getvalue()
98+
99+
return response.Response(
100+
ctx, response_data=imgbytes,
101+
headers={"Content-Type": "image/png"}
102+
)
103+
```
104+
105+
80106

81107
## Unit testing your functions
82108

fdk/async_http/app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ async def handle_request(self, request, write_callback, stream_callback):
8080
headers = res.headers
8181
status = res.status
8282
response = HTTPResponse(
83-
body=body, status=status, headers=headers,
83+
body_bytes=body, status=status, headers=headers,
8484
)
8585
except CancelledError:
8686
response = None

fdk/event_handler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ async def pure_handler(request):
5353
headers=headers,
5454
status=status,
5555
content_type=headers.get(constants.CONTENT_TYPE),
56-
body_bytes=func_response.body(),
56+
body_bytes=func_response.body_bytes(),
5757
)
5858

5959
return pure_handler

fdk/response.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@
1414

1515
from fdk import context
1616
from fdk import constants
17+
from typing import Union
1718

1819

1920
class Response(object):
2021

2122
def __init__(self, ctx: context.InvokeContext,
22-
response_data: str=None,
23+
response_data: Union[str, bytes]=None,
2324
headers: dict=None,
24-
status_code: int=200):
25+
status_code: int=200,
26+
response_encoding: str="utf-8"):
2527
"""
2628
Creates an FDK-readable response object
2729
:param ctx: invoke context
@@ -32,10 +34,14 @@ def __init__(self, ctx: context.InvokeContext,
3234
:type headers: dict
3335
:param status_code: response code
3436
:type status_code: int
37+
:param response_encoding: response encoding for strings ("utf-8")
38+
:type response_encoding: str
3539
"""
3640
self.ctx = ctx
3741
self.status_code = status_code
3842
self.response_data = response_data if response_data else ""
43+
self.response_encoding = response_encoding
44+
3945
if headers is None:
4046
headers = {}
4147
headers.update({constants.FN_FDK_VERSION:
@@ -49,5 +55,12 @@ def status(self):
4955
def body(self):
5056
return self.response_data
5157

58+
def body_bytes(self):
59+
if isinstance(self.response_data, bytes) or \
60+
isinstance(self.response_data, bytearray):
61+
return self.response_data
62+
else:
63+
return str(self.response_data).encode(self.response_encoding)
64+
5265
def context(self):
5366
return self.ctx

fdk/tests/funcs.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,7 @@ def capture_request_ctx(ctx, **kwargs):
141141
global captured_context
142142
captured_context = ctx
143143
return response.Response(ctx, response_data="OK")
144+
145+
146+
def binary_result(ctx, **kwargs):
147+
return response.Response(ctx, response_data=bytes([1, 2, 3, 4, 5]))

fdk/tests/test_http_stream.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,3 +249,10 @@ async def test_encap_request_headers_gateway():
249249

250250
assert input_ctx.HTTPHeaders() == {"my-header": "foo",
251251
"funny-header": ["baz", "bob"]}
252+
253+
254+
@pytest.mark.asyncio
255+
async def test_bytes_response():
256+
call = await fixtures.setup_fn_call(funcs.binary_result)
257+
content, status, headers = await call
258+
assert content == bytes([1, 2, 3, 4, 5])

0 commit comments

Comments
 (0)