diff --git a/agraffe/__init__.py b/agraffe/__init__.py index 1e1a8b5..f2ada9f 100644 --- a/agraffe/__init__.py +++ b/agraffe/__init__.py @@ -1,6 +1,6 @@ """ Agraffe, build API with ASGI in Serverless services (e.g AWS lambda, Google Cloud Functions and Azure Functions). """ # noqa: E501 -__version__ = "0.4.0" +__version__ = "0.5.0" import asyncio from enum import Enum diff --git a/agraffe/services/google_cloud_functions.py b/agraffe/services/google_cloud_functions.py index 084695a..35b1b0a 100644 --- a/agraffe/services/google_cloud_functions.py +++ b/agraffe/services/google_cloud_functions.py @@ -49,7 +49,7 @@ async def receive(self) -> Message: return { 'type': 'http.request', 'body': self.request.get_data( - cache=False, as_text=False, parse_form_data=True + cache=False, as_text=False, parse_form_data=False ) or b'', 'more_body': False, diff --git a/example/aws/app.py b/example/aws/app.py index b2686a0..4b12fa1 100644 --- a/example/aws/app.py +++ b/example/aws/app.py @@ -1,6 +1,6 @@ from typing import Optional -from fastapi import Cookie, FastAPI, Header, HTTPException +from fastapi import Cookie, FastAPI, Header, HTTPException, Form, File, UploadFile from fastapi.responses import PlainTextResponse, Response from models import Item @@ -60,3 +60,32 @@ def image(): content=b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x0c\x00\x00\x00\x0c\x08\x02\x00\x00\x00\xd9\x17\xcb\xb0\x00\x00\x00\x16IDATx\x9ccLIIa \x04\x98\x08\xaa\x18U4\x00\x8a\x00\x1c\xa2\x01D2\xdd\xa6B\x00\x00\x00\x00IEND\xaeB`\x82', media_type='image/png' ) + + +@app.post('/form') +def form(token: str = Form(...)): + return { + 'token': token + } + + +@app.post('/file') +async def file(file: bytes = File(...)): + return {'file_size': len(file)} + + +@app.post('/uploadfile') +async def uploadfile(file: UploadFile = File(...)): + return {'filename': file.filename} + + +@app.post('/file_and_form') +async def file_and_form( + file: bytes = File(...), fileb: UploadFile = File(...), token: str = Form(...) +): + return { + 'file_size': len(file), + 'token': token, + 'fileb_content_type': fileb.content_type, + 'filename': fileb.filename + } diff --git a/example/aws/package.json b/example/aws/package.json index 07cdc48..d4f86ab 100644 --- a/example/aws/package.json +++ b/example/aws/package.json @@ -8,7 +8,7 @@ "sls": "sls" }, "dependencies": { - "serverless": "^2.57.0" + "serverless": "^3.1.1" }, "devDependencies": { "serverless-python-requirements": "^5.1.0" diff --git a/example/aws/requirements.txt b/example/aws/requirements.txt index 7c17514..a393cca 100644 --- a/example/aws/requirements.txt +++ b/example/aws/requirements.txt @@ -2,4 +2,5 @@ fastapi==0.68.1 pydantic==1.8.2 starlette==0.14.2 typing-extensions==3.7.4.3 -agraffe==0.4.0 +python-multipart==0.0.5 +agraffe==0.5.0 diff --git a/example/aws/serverless_http.yml b/example/aws/serverless_http.yml index 1146ad8..f43f7af 100644 --- a/example/aws/serverless_http.yml +++ b/example/aws/serverless_http.yml @@ -46,6 +46,18 @@ functions: - httpApi: path: /image method: GET + - httpApi: + path: /form + method: POST + - httpApi: + path: /file + method: POST + - httpApi: + path: /uploadfile + method: POST + - httpApi: + path: /file_and_form + method: POST plugins: diff --git a/example/aws/serverless_rest.yml b/example/aws/serverless_rest.yml index 58e2f35..eb84308 100644 --- a/example/aws/serverless_rest.yml +++ b/example/aws/serverless_rest.yml @@ -50,6 +50,18 @@ functions: - http: path: /image method: get + - http: + path: /form + method: post + - http: + path: /file + method: post + - http: + path: /uploadfile + method: post + - http: + path: /file_and_form + method: post plugins: - serverless-python-requirements diff --git a/example/azure/app.py b/example/azure/app.py index b2686a0..4b12fa1 100644 --- a/example/azure/app.py +++ b/example/azure/app.py @@ -1,6 +1,6 @@ from typing import Optional -from fastapi import Cookie, FastAPI, Header, HTTPException +from fastapi import Cookie, FastAPI, Header, HTTPException, Form, File, UploadFile from fastapi.responses import PlainTextResponse, Response from models import Item @@ -60,3 +60,32 @@ def image(): content=b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x0c\x00\x00\x00\x0c\x08\x02\x00\x00\x00\xd9\x17\xcb\xb0\x00\x00\x00\x16IDATx\x9ccLIIa \x04\x98\x08\xaa\x18U4\x00\x8a\x00\x1c\xa2\x01D2\xdd\xa6B\x00\x00\x00\x00IEND\xaeB`\x82', media_type='image/png' ) + + +@app.post('/form') +def form(token: str = Form(...)): + return { + 'token': token + } + + +@app.post('/file') +async def file(file: bytes = File(...)): + return {'file_size': len(file)} + + +@app.post('/uploadfile') +async def uploadfile(file: UploadFile = File(...)): + return {'filename': file.filename} + + +@app.post('/file_and_form') +async def file_and_form( + file: bytes = File(...), fileb: UploadFile = File(...), token: str = Form(...) +): + return { + 'file_size': len(file), + 'token': token, + 'fileb_content_type': fileb.content_type, + 'filename': fileb.filename + } diff --git a/example/azure/file/__init__.py b/example/azure/file/__init__.py new file mode 100644 index 0000000..55df101 --- /dev/null +++ b/example/azure/file/__init__.py @@ -0,0 +1 @@ +from entry_point import main diff --git a/example/azure/file/function.json b/example/azure/file/function.json new file mode 100644 index 0000000..005cbf6 --- /dev/null +++ b/example/azure/file/function.json @@ -0,0 +1,18 @@ +{ + "scriptFile": "__init__.py", + "bindings": [ + { + "authLevel": "Anonymous", + "type": "httpTrigger", + "direction": "in", + "name": "req", + "methods": ["post"], + "route": "file" + }, + { + "type": "http", + "direction": "out", + "name": "$return" + } + ] +} diff --git a/example/azure/file_and_form/__init__.py b/example/azure/file_and_form/__init__.py new file mode 100644 index 0000000..55df101 --- /dev/null +++ b/example/azure/file_and_form/__init__.py @@ -0,0 +1 @@ +from entry_point import main diff --git a/example/azure/file_and_form/function.json b/example/azure/file_and_form/function.json new file mode 100644 index 0000000..1da4610 --- /dev/null +++ b/example/azure/file_and_form/function.json @@ -0,0 +1,18 @@ +{ + "scriptFile": "__init__.py", + "bindings": [ + { + "authLevel": "Anonymous", + "type": "httpTrigger", + "direction": "in", + "name": "req", + "methods": ["post"], + "route": "file_and_form" + }, + { + "type": "http", + "direction": "out", + "name": "$return" + } + ] +} diff --git a/example/azure/form/__init__.py b/example/azure/form/__init__.py new file mode 100644 index 0000000..55df101 --- /dev/null +++ b/example/azure/form/__init__.py @@ -0,0 +1 @@ +from entry_point import main diff --git a/example/azure/form/function.json b/example/azure/form/function.json new file mode 100644 index 0000000..8cb9d3d --- /dev/null +++ b/example/azure/form/function.json @@ -0,0 +1,18 @@ +{ + "scriptFile": "__init__.py", + "bindings": [ + { + "authLevel": "Anonymous", + "type": "httpTrigger", + "direction": "in", + "name": "req", + "methods": ["post"], + "route": "form" + }, + { + "type": "http", + "direction": "out", + "name": "$return" + } + ] +} diff --git a/example/azure/requirements.txt b/example/azure/requirements.txt index 7c17514..a393cca 100644 --- a/example/azure/requirements.txt +++ b/example/azure/requirements.txt @@ -2,4 +2,5 @@ fastapi==0.68.1 pydantic==1.8.2 starlette==0.14.2 typing-extensions==3.7.4.3 -agraffe==0.4.0 +python-multipart==0.0.5 +agraffe==0.5.0 diff --git a/example/azure/uploadfile/__init__.py b/example/azure/uploadfile/__init__.py new file mode 100644 index 0000000..55df101 --- /dev/null +++ b/example/azure/uploadfile/__init__.py @@ -0,0 +1 @@ +from entry_point import main diff --git a/example/azure/uploadfile/function.json b/example/azure/uploadfile/function.json new file mode 100644 index 0000000..c5b287b --- /dev/null +++ b/example/azure/uploadfile/function.json @@ -0,0 +1,18 @@ +{ + "scriptFile": "__init__.py", + "bindings": [ + { + "authLevel": "Anonymous", + "type": "httpTrigger", + "direction": "in", + "name": "req", + "methods": ["post"], + "route": "uploadfile" + }, + { + "type": "http", + "direction": "out", + "name": "$return" + } + ] +} diff --git a/example/gcp/app.py b/example/gcp/app.py index b2686a0..4b12fa1 100644 --- a/example/gcp/app.py +++ b/example/gcp/app.py @@ -1,6 +1,6 @@ from typing import Optional -from fastapi import Cookie, FastAPI, Header, HTTPException +from fastapi import Cookie, FastAPI, Header, HTTPException, Form, File, UploadFile from fastapi.responses import PlainTextResponse, Response from models import Item @@ -60,3 +60,32 @@ def image(): content=b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x0c\x00\x00\x00\x0c\x08\x02\x00\x00\x00\xd9\x17\xcb\xb0\x00\x00\x00\x16IDATx\x9ccLIIa \x04\x98\x08\xaa\x18U4\x00\x8a\x00\x1c\xa2\x01D2\xdd\xa6B\x00\x00\x00\x00IEND\xaeB`\x82', media_type='image/png' ) + + +@app.post('/form') +def form(token: str = Form(...)): + return { + 'token': token + } + + +@app.post('/file') +async def file(file: bytes = File(...)): + return {'file_size': len(file)} + + +@app.post('/uploadfile') +async def uploadfile(file: UploadFile = File(...)): + return {'filename': file.filename} + + +@app.post('/file_and_form') +async def file_and_form( + file: bytes = File(...), fileb: UploadFile = File(...), token: str = Form(...) +): + return { + 'file_size': len(file), + 'token': token, + 'fileb_content_type': fileb.content_type, + 'filename': fileb.filename + } diff --git a/example/gcp/requirements.txt b/example/gcp/requirements.txt index 7c17514..a393cca 100644 --- a/example/gcp/requirements.txt +++ b/example/gcp/requirements.txt @@ -2,4 +2,5 @@ fastapi==0.68.1 pydantic==1.8.2 starlette==0.14.2 typing-extensions==3.7.4.3 -agraffe==0.4.0 +python-multipart==0.0.5 +agraffe==0.5.0