slank / awsgi Goto Github PK
View Code? Open in Web Editor NEWA WSGI gateway for the AWS API Gateway/Lambda proxy integration
License: MIT License
A WSGI gateway for the AWS API Gateway/Lambda proxy integration
License: MIT License
I want to implements a download feature, when user request to download, lambda will get file content from s3, then response to api gateway.
Note: I want to download a binary file, eg: xxx.bin
Here is the code:
file = s3.get_file_content(bucket_name, key)
response = make_response(file['Body'].read())
response.headers.set('Content-Type', 'application/octet-stream')
response.headers.set(
'Content-Disposition', 'attachment', filename='%s' % key)
return response
@app.route(BASE_ROUTE, methods=['GET'])
def hello_world():
# event=request.environ['event']
print('--hello--')
# print(event)
return jsonify(message="hello world")
def handler(event, context):
print('---event--')
print(event)
print('---context--')
print(context)
return awsgi.response(app, event, context)
Above is my code structure, I was wondering how can I access the event and context inside the route.
I have a custom authenticated API gateway settings which returns a token inside the event, I want to ask that token across the flask application
Elastic Load Balancing supports Multi Value Headers under different keys
{
"requestContext": {
"elb": {
"targetGroupArn": "arn:aws:elasticloadbalancing:us-east-2:0123456789:targetgroup/spam/eggs"
}
},
"httpMethod": "GET",
"path": "/",
"multiValueQueryStringParameters": {},
"multiValueHeaders": {
"user-agent": [
"ELB-HealthChecker/2.0"
]
},
"body": "",
"isBase64Encoded": false
}
When my flask app hits an error, the app seems to always return a response code of 200 with a body
containing the relevant HTML to explain what error has occurred. I should be able to catch errors with @app.errorhandler(), but it does not seem to be working. Is this supported?
I would expect the response code to not be 200 if a 404 was thrown...
Invoking Container created from helloworldfunction:0.0.1-prod
Building image.................
Skip pulling image and use local one: helloworldfunction:rapid-1.27.2.
START RequestId: 8ebeeb37-1879-40fc-aed7-99902d8541a0 Version: $LATEST
'REQUEST_METHOD': event['httpMethod'], 121, in environe
END RequestId: 8ebeeb37-1879-40fc-aed7-99902d8541a0
REPORT RequestId: 8ebeeb37-1879-40fc-aed7-99902d8541a0 Init Duration: 0.11 ms Duration: 170.98 ms Billed Duration: 200 ms Memory Size: 128 MB Max Memory Used: 128 MB
{"errorMessage": "'httpMethod'", "errorType": "KeyError", "stackTrace": [" File \"/var/task/app.py\", line 6, in lambda_handler\n return awsgi.response(app, event, context)\n", " File \"/var/task/awsgi/__init__.py\", line 172, in
response\n output = app(environ(event, context), sr)\n", " File \"/var/task/awsgi/__init__.py\", line 121, in environ\n 'REQUEST_METHOD': event['httpMethod'],\n"]}sbhakunamatata@DESKTOP-KV7TUSU:/mnt/c/Users/Shrir/PycharmProjects
/jwtFlashRestTutorial$
Getting this error when doing sam local invoke while using awsgi
The lambdahandler:
def lambda_handler(event, context):
return awsgi.response(app, event, context)
creating flask app like:
from flask import Flask
app: Flask = Flask(__name__)
I am calling an endpoint i made to update a customer. When passing my json body i get a 400 Bad request. Seems like a json body that contains accent characters is not parsed correctly by the request object.
Note: when using flask without awsgi like so:
@app.route('/', methods=['POST'])
def test():
return request.get_json()
everything is working, but when i use awsgi
:
def lambda_handler(event, context):
return awsgi.response(app, event, context)
@bp.route('/<id>', methods=[METHOD])
def update_customer(id, query_params={}):
return request.get_json()
This throw me a BadRequest error and the error is on get_json
.
I don't really know what awsgi
is doing with the json body, but something is done incorrectly.
Hi - great library!
Any way to get it working with flask_compress?
#!/usr/bin/env python
import awsgi
from flask import Flask
from flask import jsonify
from flask_compress import Compress
app = Flask(__name__)
app.config['COMPRESS_MIN_SIZE'] = 0
Compress(app)
@app.route('/')
def index():
return jsonify(status=200, message='OK')
def lambda_handler(event, context):
return awsgi.response(app, event, context)
print(lambda_handler({
'body': None,
'httpMethod': 'GET',
'path': '/',
'queryStringParameters': {},
'headers': {
'host': 'localhost',
'x-forwarded-proto': 'http',
'Accept-Encoding': 'gzip'
}
}, None))
Fails with
Traceback (most recent call last):
File "./test_compress.py", line 31, in <module>
}, None))
File "./test_compress.py", line 18, in lambda_handler
return awsgi.response(app, event, context)
File "/Users/rog555/Library/Python/2.7/lib/python/site-packages/awsgi/__init__.py", line 22, in response
return sr.response(output)
File "/Users/rog555/Library/Python/2.7/lib/python/site-packages/awsgi/__init__.py", line 40, in response
'body': self.body.getvalue() + ''.join(map(convert_str, output)),
UnicodeDecodeError: 'ascii' codec can't decode byte 0x8b in position 1: ordinal not in range(128)
using aws-wsgi-0.0.7
I've been happily using awsgi
until encountering an issue when using API Gateway custom authorizers. The authorizer context, which allows your authorizer to pass custom data to the application (e.g. user ID, group membership, permissions, etc.), exists as a dictionary value in the Lambda event. It lives in event['requestContext']['authorizer']
, but this value is not passed by awsgi
to the application.
Since AWS could at any time add other bits of useful metadata to the Lambda event, would it make sense for awsgi
to just pass the AWS Lambda event to the application via the WSGI environ dictionary?
When lambdas are behind an ALB instead of API gateway, path and query parameters don't get unquoted.
(example issue here dougmoscrop/serverless-http#74)
I fixed this for myself with:
def lambda_handler(event, context):
"entrypoint for lambda"
params = event['queryStringParameters']
for key in params:
# todo: keys should probably be unquoted as well? didn't test
params[key] = url.parse.unquote(params[key])
event['path'] = urllib.parse.unquote(event['path'])
return awsgi.response(app, event, context, base64_content_types={"image/png", "image/x-icon", "image/vnd.microsoft.icon"})
Happy to submit a PR if useful, either adding docs or adding a kwarg to awsgi.response
. LMK.
Also, great project and thanks for your work.
Trying to integrate Flask with AWS Lambda through SAM. However, I am getting 404 Error when I hit the API.
Using Windows
, with Flask
, awsgi
, aws-cli
and aws-sam
. Python 3.11
.
My app.py
:
import awsgi
from flask import (
Flask,
jsonify,
)
app = Flask(__name__)
@app.route('/')
def index():
return {
"statusCode": 200,
"body": json.dumps({
"message": "hello world",
# "location": ip.text.replace("\n", "")
}),
}
def lambda_handler(event, context):
return awsgi.response(app, event, context)
Steps to reproduce:
sam build
sam deploy --guided
cURL https://**********.execute-api.us-east-1.amazonaws.com/Prod/bot/
Expected output"
{ "message": "hello world"}
What I get is 404 Error
.
If I run sam remote invoke HelloWorldFunction --stack-name sam-flask
, I get:
Invoking Lambda Function HelloWorldFunction
START RequestId: e0d920ad-cc19-4292-bf69-a1d148bfc98e Version: $LATEST
[ERROR] KeyError: 'httpMethod'
Traceback (most recent call last):
File "/var/task/app.py", line 21, in lambda_handler
return awsgi.response(app, event, context)
File "/var/task/awsgi/__init__.py", line 172, in response
output = app(environ(event, context), sr)
File "/var/task/awsgi/__init__.py", line 121, in environ
'REQUEST_METHOD': event['httpMethod'],END RequestId: e0d920ad-cc19-4292-bf69-a1d148bfc98e
REPORT RequestId: e0d920ad-cc19-4292-bf69-a1d148bfc98e Duration: 12.56 ms Billed Duration: 13 ms Memory Size: 128 MB Max Memory Used: 63 MB Init Duration: 557.31 ms
{"errorMessage": "'httpMethod'", "errorType": "KeyError", "requestId": "e0d920ad-cc19-4292-bf69-a1d148bfc98e", "stackTrace": [" File \"/var/task/app.py\", line 21, in lambda_handler\n return awsgi.response(app, event, context)\n", " File \"/var/task/awsgi/__init__.py\", line 172, in response\n output = app(environ(event, context), sr)\n", " File \"/var/task/awsgi/__init__.py\", line 121, in environ\n 'REQUEST_METHOD': event['httpMethod'],\n"]}
I feel it is something simple I am missing.
If I replace lambda_handler
with the tutorial code from AWS I get expected output.
This below is that code. So my AWS Lambda Proxy Resource is configured correctly for simple JSON but not for awsgi
.
def lambda_handler(event, context):
return {
"statusCode": 200,
"body": json.dumps({
"message": "hello world",
# "location": ip.text.replace("\n", "")
}),
}
What am I doing wrong? Can anyone help? I have been trying for a week now.
Getting the following error with 0.2.6
[ERROR] TypeError: argument of type 'NoneType' is not iterable
Traceback (most recent call last):
File "/var/task/app/app.py", line 21, in entrypoint
return awsgi.response(api, event, context)
File "/var/task/awsgi/__init__.py", line 172, in response
return sr.response(output)
File "/var/task/awsgi/__init__.py", line 94, in response
rv = super(StartResponse_GW, self).response(output)
File "/var/task/awsgi/__init__.py", line 88, in response
rv.update(self.build_body(headers, output))
File "/var/task/awsgi/__init__.py", line 69, in build_body
is_b64 = self.use_binary_response(headers, totalbody)
File "/var/task/awsgi/__init__.py", line 60, in use_binary_response
if ';' in content_type:
Appears directly related to #50
Hello everyone,
I am getting errors from my code below:
output = BytesIO()
writer = pd.ExcelWriter(output, engine='xlsxwriter')
df.to_excel(writer, startrow = 0, merge_cells = False, sheet_name = "results", index=False)
workbook = writer.book
worksheet = writer.sheets["results"]
worksheet.set_column(1, 20, 20)
writer.save()
output.seek(0)
return send_file(output, attachment_filename="test.xlsx", as_attachment=True)
The error message is
'utf-8' codec can't decode byte 0xb6 in position 14: invalid start byte: UnicodeDecodeError
Traceback (most recent call last):
File "/var/task/handler.py", line 60, in run
return awsgi.response(app, event, context)
File "/var/task/awsgi/__init__.py", line 22, in response
return sr.response(output)
File "/var/task/awsgi/__init__.py", line 41, in response
'body': self.body.getvalue() + ''.join(map(convert_str, output)),
File "/var/task/awsgi/__init__.py", line 9, in convert_str
return s.decode('utf-8') if isinstance(s, bytes) else s
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb6 in position 14: invalid start byte
With some research, I found the file __ init __.py line 9 should be updated
from:
return s.decode('utf-8') if isinstance(s, bytes) else s
to:
return s.decode('utf-8', 'ignore') if isinstance(s, bytes) else s
Tested the code above and it's now working correctly. The excel file is being download as expected.
May I make a pull request and submit this change?
Thank you
Getting error below since upgrading to 0.1.0:
[ERROR] TypeError: 'NoneType' object is not iterable
Traceback (most recent call last):
File "/var/task/lambda.py", line 11, in handler
return awsgi.response(app, event, context)
File "/var/task/vendor/awsgi/__init__.py", line 25, in response
sr = StartResponse(base64_content_types=base64_content_types)
File "/var/task/vendor/awsgi/__init__.py", line 41, in __init__
self.base64_content_types = set(base64_content_types) or set()
Hi,
I am trying to return a GZIP encoded response but getting the error :
{
"errorMessage": "'utf-8' codec can't decode byte 0x8b in position 1: invalid start byte",
"errorType": "UnicodeDecodeError",
"stackTrace": [
" File \"/var/task/lambda_handler.py\", line 75, in handler\n return awsgi.response(app, event, context)\n",
" File \"/var/task/awsgi/__init__.py\", line 22, in response\n return sr.response(output)\n",
" File \"/var/task/awsgi/__init__.py\", line 41, in response\n 'body': self.body.getvalue() + ''.join(map(convert_str, output)),\n",
" File \"/var/task/awsgi/__init__.py\", line 9, in convert_str\n return s.decode('utf-8') if isinstance(s, bytes) else s\n"
]
}
Is there any way to skip the response transformed in String ?
It would we nice, if we have a django example just like the flask example in documentaion
Current pip release is lacking way back than master. Can we make a release some time soon? Thanks
Hello there,
Is there a timeframe of when the package on PyPI will be updated to version 0.2.4? I encountered an issue when posting JSON data with non-English characters that was fixed in the latest commit. But that code is not included in version 0.2.3 of the package.
Flask seems to require wsgi.url_scheme
in the WSGI environ dict.
[ERROR] KeyError: 'wsgi.url_scheme'
Traceback (most recent call last):
File "/var/task/__main__.py", line 17, in main
return awsgi.response(app, event, context, base64_content_types={"image/png"})
File "/var/task/awsgi/__init__.py", line 26, in response
output = app(environ(event, context), sr)
File "/var/task/flask/app.py", line 2463, in __call__
return self.wsgi_app(environ, start_response)
File "/var/task/flask/app.py", line 2441, in wsgi_app
ctx = self.request_context(environ)
File "/var/task/flask/app.py", line 2358, in request_context
return RequestContext(self, environ)
File "/var/task/flask/ctx.py", line 292, in __init__
self.url_adapter = app.create_url_adapter(self.request)
File "/var/task/flask/app.py", line 2173, in create_url_adapter
subdomain=subdomain,
File "/var/task/werkzeug/routing.py", line 1502, in bind_to_environ
wsgi_server_name = get_host(environ).lower()
File "/var/task/werkzeug/wsgi.py", line 170, in get_host
if (environ["wsgi.url_scheme"], environ["SERVER_PORT"]) not in (
This is in violation of PEP 3333:
In addition to the CGI-defined variables, the environ dictionary ... must contain the following WSGI-defined variables:
We run a flask application as lambda behind an api gateway using awsgi. This flask application reads the body as json with flasks request.get_json(). This bails out with a JSON error:
Failed to decode JSON object: Expecting ',' delimiter: line X column Y (char Z)
This is caused because awsgi sets the CONTENT_LENGTH in the environ to len(event.get('body', '')) but it should set it to the len of the encoded bytes string.
Call that works as expected:
curl -v -X PATCH -H 'Content-Type: application/json' http://127.0.0.1:3000/utf8test -d '{"test": "Jagermeister"}'
Call that has this error as result:
curl -v -X PATCH -H 'Content-Type: application/json' http://127.0.0.1:3000/utf8test -d '{"test": "Jägermeister"}'
Hello,
This package works fine when I create Rest API for the Lambda function by using Amazon API Gateway or AWS SAM, but not with Http API type . It is very easy to notice this gap. To do this, just create an API that invoke the Lambda function with HTTP API type instead of REST API type.
The reason that make this package not working with HTTP API type is that HTTP APIs are newer and are built with the API Gateway version 2 API. So, the event json structure is different than the previous one. By the way, the http Method and the path are specified by the following paths:
For more details, please look into the following link (paragraph: Choosing an API type)
Using AWS Lambda with Amazon API Gateway
To deal with that, I think we have no choice, we should modify the function def environ (event, context) a bit. And here are my retrocompatible modifications:
def environ(event, context):
body = event.get('body', '') or ''
if event.get('isBase64Encoded', False):
body = b64decode(body)
# FIXME: Flag the encoding in the headers
body = convert_byte(body)
httpMethod = ''
path = ''
if 'httpMethod' in event and 'path' in event:
httpMethod = event['httpMethod']
path = event['path']
elif 'http' in event['requestContext']:
if 'method' in event['requestContext']['http']:
httpMethod = event['requestContext']['http']['method']
if 'path' in event['requestContext']['http']:
path = event['requestContext']['http']['path']
queryStringParameters = ''
if 'queryStringParameters' in event and event['queryStringParameters'] is not None:
queryStringParameters = urlencode(event['queryStringParameters'])
environ = {
'REQUEST_METHOD': httpMethod,
'SCRIPT_NAME': '',
'SERVER_NAME': '',
'SERVER_PORT': '',
'PATH_INFO': path ,
'QUERY_STRING':queryStringParameters,
'REMOTE_ADDR': '127.0.0.1',
'CONTENT_LENGTH': str(len(body)),
'HTTP': 'on',
'SERVER_PROTOCOL': 'HTTP/1.1',
'wsgi.version': (1, 0),
'wsgi.input': BytesIO(body),
'wsgi.errors': sys.stderr,
'wsgi.multithread': False,
'wsgi.multiprocess': False,
'wsgi.run_once': False,
'wsgi.url_scheme': '',
'awsgi.event': event,
'awsgi.context': context,
}
headers = event.get('headers', {}) or {}
for k, v in headers.items():
k = k.upper().replace('-', '_')
if k == 'CONTENT_TYPE':
environ['CONTENT_TYPE'] = v
elif k == 'HOST':
environ['SERVER_NAME'] = v
elif k == 'X_FORWARDED_FOR':
environ['REMOTE_ADDR'] = v.split(', ')[0]
elif k == 'X_FORWARDED_PROTO':
environ['wsgi.url_scheme'] = v
elif k == 'X_FORWARDED_PORT':
environ['SERVER_PORT'] = v
environ['HTTP_' + k] = v
return environ
Of course I've tested (locally with aws sam and in AWS console after deployment) that this code enhancement is working properly.
Best regards,
When the headers key has a value of None, a NoneType error is thrown on line 129 of init.py. Here is an example stacktrace:
[ERROR] AttributeError: 'NoneType' object has no attribute 'items'
Traceback (most recent call last):
File "/var/task/lambda_function.py", line 79, in lambda_handler
return awsgi.response(app, event, context)
File "/var/task/awsgi/__init__.py", line 159, in response
output = app(environ(event, context), sr)
File "/var/task/awsgi/__init__.py", line 129, in environ
for k, v in headers.items():
After looking at the code, I think it can be fixed by only entering line 129 (the for loop) if items is not None or has a non-zero length.
Please let me know if you have any questions or need more information.
There seems to be something lacking in either the API-Gateway setup docs or the awsgi docs. I have copied the code directly from the example and I cannot get it to work. I am using the aws sam cli for testing. I can get the generic un-styled Flask 404 response but nothing else.
As far as I can tell the lambda handler is handling, but the request is never handed to flask.
It doesn't look like there is support for the APIGW v2 event format yet. Is this something you'd be open to adding? Is someone already working on it?
Python 2 is dead and AWS Lambda support is ending soon.
I'm trying to host a Python/Django project on AWS Lambda. But when I connect to Django's admin, I get a 403 error:
Content-Type:application/x-www-form-urlencoded, URL cannot include query-string parameters (after '?'): '/admin/login/?next=/admin/'
NB: I did't have this problem with the Serverless framework
POST https://domain.tld/admin/login/?next=/admin/
Request headers
Host: domain.tld
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 138
Connection: keep-alive
Referer: https://domain.tld/admin/login/?next=/admin/
Cookie: csrftoken=A5r8Xxnv0x6EWHOYJEq3zZvMyGCoRWU5ozSfOXaArmWwD4LYFHuYEsStt4Bb9ugB
Upgrade-Insecure-Requests: 1
TE: Trailers
Response headers
HTTP/2.0 403 Forbidden
content-type: application/json
content-length: 155
date: Thu, 05 Sep 2019 14:32:22 GMT
x-amzn-requestid: 05341664-1cc7-4cc6-951d-8f229820d86b
x-amzn-errortype: IncompleteSignatureException
x-amz-apigw-id: fjFicHuZjoEFg3Q=
x-cache: Error from cloudfront
via: 1.1 xxx.cloudfront.net (CloudFront)
x-amz-cf-pop: CDG3-C2
x-amz-cf-id: Xdkmr_gSedl-l2jbkh-dlj8dJzR8ZwxPnkd2n49KWALfRboG5sJbMA==
X-Firefox-Spdy: h2
Response payload
{"message":"When Content-Type:application/x-www-form-urlencoded, URL cannot include query-string parameters (after '?'): '/admin/login/?next=/admin/'"}
app.py
import awsgi
from .wsgi import application
def lambda_handler(event, context):
return awsgi.response(application, event, context)
template.yaml
---
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: My project stack
Parameters:
AwsLocation:
Type: String
DatabaseUrl:
Type: String
Globals:
Function:
Timeout: 10
Runtime: python3.6
Resources:
SuggestionFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src/
Handler: project.app.lambda_handler
Policies:
- VPCAccessPolicy: {}
VpcConfig:
SecurityGroupIds:
- xxx
SubnetIds:
- xxx
- xxx
- xxx
Events:
Base:
Type: Api
Properties:
Path: /
Method: get
Proxy:
Type: Api
Properties:
Path: /{proxy+}
Method: get
Environment:
Variables:
AWS_LOCATION: !Ref AwsLocation
DATABASE_URL: !Ref DatabaseUrl
Outputs:
EndpointUrl:
Description: API Gateway endpoint URL
Value: !Sub https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/
python 3.6.3
django 2.0.2
awsgi 0.0.7
here my view is just trying to print POST
Traceback (most recent call last):
File "/var/task/django/core/handlers/exception.py", line 35, in inner
response = get_response(request)
File "/var/task/django/core/handlers/base.py", line 128, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/var/task/django/core/handlers/base.py", line 126, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/var/task/doer/views.py", line 126, in deploy_start
print(request.POST)
File "/var/task/django/core/handlers/wsgi.py", line 115, in _get_post
self._load_post_and_files()
File "/var/task/django/http/request.py", line 302, in _load_post_and_files
self._post, self._files = QueryDict(self.body, encoding=self._encoding), MultiValueDict()
File "/var/task/django/http/request.py", line 263, in body
self._body = self.read()
File "/var/task/django/http/request.py", line 322, in read
return self._stream.read(*args, **kwargs)
File "/var/task/django/core/handlers/wsgi.py", line 36, in read
result = self.buffer + self._read_limited()
TypeError: can't concat bytes to str
it seams django expects BytesIO for wsgi.input
After upgrading to version 0.2.6, I have the following issue on responses without a "Content-Type" header set:
[ERROR] TypeError: argument of type 'NoneType' is not iterable Traceback (most recent call last): File "/var/task/src/main/handler.py", line 262, in flask_handler return awsgi.response(app, event, context) File "dependencies/awsgi/__init__.py", line 172, in response return sr.response(output) File "dependencies/awsgi/__init__.py", line 94, in response rv = super(StartResponse_GW, self).response(output) File "dependencies/awsgi/__init__.py", line 88, in response rv.update(self.build_body(headers, output)) File "dependencies/awsgi/__init__.py", line 69, in build_body is_b64 = self.use_binary_response(headers, totalbody) File "dependencies/awsgi/__init__.py", line 60, in use_binary_response if ';' in content_type:
My case is an empty response with a 304 status code, so there is no content. The culprit seems to be this commit:
>>> ';' in None Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: argument of type 'NoneType' is not iterable
A fix would be to check for None
HTTP headers have some semantics that aren't compatible with a naive dict
.
Use wsgiref.headers.Headers
to handle this.
File "/var/task/index.py", line 7, in lambda_handler
return awsgi.response(app, event, context)
AttributeError: module 'awsgi' has no attribute 'response'
Hi,
I want to create a dummy .zip file and send the response with the function send_file.
memory_file = BytesIO()
with zipfile.ZipFile(memory_file, 'w') as zf:
zipinfo = zipfile.ZipInfo("test")
zipinfo.date_time = time.localtime(time.time())[:6]
zipinfo.compress_type = zipfile.ZIP_DEFLATED
zf.writestr(zipinfo, "this is test zip content")
memory_file.seek(0)
return send_file(memory_file, attachment_filename='capsule.zip', as_attachment=True)
To see if the .zip file is processed and sent correctly I send the GET request via my browser.
The .zip file is sent, i download it but when I want to see the archive of the .zip I cannot because the .zip file is corrupted.
I updated the line 41 in the init.py file
self.base64_content_types = set(base64_content_types or ["application/zip"]) or set()
I also tried doing the same thing without using AWSGI (using only python FlaskRESTful) and i had no issues.
Could you help me resolving this issue
Thanks
Since Lambda supported Python 3.6, I tried updating Flask's application to Python 3.6, but TypeError occurred.
must be str, not bytes: TypeError
Traceback (most recent call last):
File "/var/task/main.py", line 9, in lambda_handler
return awsgi.response(app, event, context)
File "/var/task/awsgi/__init__.py", line 14, in response
return sr.response(output)
File "/var/task/awsgi/__init__.py", line 35, in response
resp['body'] += chunk
TypeError: must be str, not bytes
resp['body'] is <class 'str'>, but output is <class 'bytes'>.
So, it has failed to combine strings.
I was not familiar with WSGI so I did not know how to concatenate it correctly, but I am glad that the error is resolved.
AWS Lambda Supports Python 3.6
https://aws.amazon.com/jp/about-aws/whats-new/2017/04/aws-lambda-supports-python-3-6/
I'm not sure what the proper solution for this is but,
If you set up custom API gateway domain with a base path mapping, then the path mapping and stage are added to the path flask receives. So instead of it dispatching on /foo/bar it dispatches on /v1/Prod/foo/bar.
If I go to https://qanda.llolo.lol/v1/Prod/foo/bar - then I get a 404 because it tries to send it to /v1/Prod/foo/bar instead of /foo/bar.
What's the best way to deal with this?
The flask util function redirect(url)
does not translate to a redirect in AWS Gateway. Using flask.Response( status=302, headers={"Location": url })
does work though (using the latest version). If someone can give me a hint on where to fix this, I might be able to add a PR. Thanks and cheers!
I'm not sure whether requestContext
is always provided from lambda event, but we have a use case where we're creating the event dict ourselves which did not contain a requestContext
. New code to support elb tries to access event['requestContext']
which fails in that case. Would be easy enough to use .get()
, I'll submit a PR.
In "use_binary_response", the header 'Content-Type' is read; however, HTTP headers are case insensitive (it fails in my case).
Can be fixed with something like this:
content_type = None
for item in headers.items():
if item[0].lower() == 'content-type':
content_type = item[1]
break
File "/var/task/vendor/awsgi/__init__.py", line 21, in response
output = app(environ(event, context), sr)
File "/var/task/vendor/flask/app.py", line 1997, in __call__
return self.wsgi_app(environ, start_response)
File "/var/task/vendor/flask/app.py", line 1977, in wsgi_app
ctx = self.request_context(environ)
File "/var/task/vendor/flask/app.py", line 1938, in request_context
return RequestContext(self, environ)
File "/var/task/vendor/flask/ctx.py", line 242, in __init__
self.url_adapter = app.create_url_adapter(self.request)
File "/var/task/vendor/flask/app.py", line 1765, in create_url_adapter
server_name=self.config['SERVER_NAME'])
File "/var/task/vendor/werkzeug/routing.py", line 1307, in bind_to_environ
wsgi_server_name = environ['SERVER_NAME']
KeyError: 'SERVER_NAME'
Using sam local start-api
I'd like to humbly acknowledge that I have not actively maintained this project for some time. I don't expect my time commitments to change any time soon, so I'd like to ask for some interested parties to maintain and eventually take ownership.
If you have the time and patience to maintain awsgi
, please use this issue to volunteer and discuss. Thanks.
Hi, I used awsgi to deploy a flask app on AWS Lambda, the run time is python2.7, then I got a type error:
Traceback (most recent call last):
File "/var/task/app.py", line 19, in lambda_handler
return awsgi.response(app, event, context, base64_content_types={"image/png"})
File "/var/task/awsgi/__init__.py", line 169, in response
return sr.response(output)
File "/var/task/awsgi/__init__.py", line 91, in response
rv = super().response(output)
TypeError: super() takes at least 1 argument (0 given)
so I edited the file as follows:
class StartResponse(object): # use new-style class in python2
...
rv = super(StartResponse_GW, self).response(output)
...
rv = super(StartResponse_ELB, self).response(output)
so now it can work in python2.7
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.