From 6ff93bfe45530b271dbed64e753c31e6c1807d3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Battocchia?= <matias@riseup.net> Date: Tue, 8 Aug 2023 14:39:02 -0300 Subject: [PATCH] de/serializing based on content type and accept headers --- .github/workflows/publish.yml | 24 ++++++++++++++++++ src/deserve.py | 48 +++++++++++++++++++++++++---------- 2 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..4208347 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,24 @@ +name: Upload Python package + +on: + release: + types: [published] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + - name: Install dependencies + run: | + pip install flit + - name: Build and publish package + run: | + flit publish + env: + FLIT_USERNAME: __token__ + FLIT_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} diff --git a/src/deserve.py b/src/deserve.py index 707c2cd..9e53d47 100644 --- a/src/deserve.py +++ b/src/deserve.py @@ -1,25 +1,24 @@ """Deserve is a nanoframework for serving ML models""" -__version__ = '0.1' +__version__ = '0.2' import json import sys -async def desend(send, response, status=200): - payload = json.dumps(response).encode() +async def desend(send, body, content, status=200): await send({ 'type': 'http.response.start', 'status': status, 'headers': [ - (b'content-type', b'application/json'), - (b'content-length', str(len(payload)).encode()), + (b'content-type', content), + (b'content-length', str(len(body)).encode()), ], }) await send({ 'type': 'http.response.body', - 'body': payload, + 'body': body, }) def deserve(app): @@ -28,24 +27,45 @@ async def wrapper(scope, receive, send): # if scope['type'] != 'http': # return # - # if (b'content-type', b'application/json') not in scope['headers']: - # return + + headers = dict(scope['headers']) + content = headers.get(b'content-type', b'') + accept = headers.get(b'accept', b'') event = await receive() # if event['type'] != 'http.request': # return - try: - request = json.loads(event['body']) if event['body'] else None + if b'text/' in content: + request = event['body'].decode() + elif b'image/' in content or b'audio/' in content: + request = event['body'] + else: + try: + request = json.loads(event['body']) + except json.JSONDecodeError as e: + if content == b'application/json': + return await desend( + send, + json.dumps({ 'error': f'JSON decode error. {e}' }).encode(), + content, + status=400 + ) - except json.JSONDecodeError as e: - response = { 'error': f'JSON decode error. {e}' } - return await desend(send, response, 400) + request = event['body'] response = await app(request) - await desend(send, response) + if b'text/' in accept: + await desend(send, response.encode(), content=accept) + elif b'image/' in accept or b'audio/' in accept: + await desend(send, response, content=accept) + else: + if accept == b'application/json' or type(response) not in [bytes, bytearray]: + await desend(send, json.dumps(response).encode(), content=accept) + else: + await desend(send, response, content=b'application/octet-stream') return wrapper