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