0

I have a serverless api through sam that consists of aws::serverless:function's and using flask-lambda to consume requests. I have been able to consume normal rest requests but I have a use-case to take in 3 property values and multiple files so naturally I considered using form-data to do this.

Sample lambda below:

from flask import request, jsonify
from flask_lambda import FlaskLambda

app = FlaskLambda(__name__)


@app.route('/kits', methods=['POST'])
def lambda_handler():
    print(request.form['title'])
    print(request.form['description'])
    print(request.form['kitType'])
    return jsonify("success"), 201

After standing up the serverless api through sam local, I hit this endpoint through postman and the below error occurs as Flask tries to parse the form-data:

Traceback (most recent call last):
  File "/var/task/flask/app.py", line 2070, in wsgi_app
    response = self.full_dispatch_request()
  File "/var/task/flask/app.py", line 1515, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/var/task/flask/app.py", line 1513, in full_dispatch_request
    rv = self.dispatch_request()
  File "/var/task/flask/app.py", line 1499, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File "/var/task/app.py", line 15, in kits_post
    print(request.form['title'])
  File "/var/task/werkzeug/utils.py", line 97, in __get__
    value = self.fget(obj)  # type: ignore
  File "/var/task/werkzeug/wrappers/request.py", line 447, in form
    self._load_form_data()
  File "/var/task/flask/wrappers.py", line 113, in _load_form_data
    RequestBase._load_form_data(self)
  File "/var/task/werkzeug/wrappers/request.py", line 285, in _load_form_data
    data = parser.parse(
  File "/var/task/werkzeug/formparser.py", line 265, in parse
    return parse_func(self, stream, mimetype, content_length, options)
  File "/var/task/werkzeug/formparser.py", line 142, in wrapper
    return f(self, stream, *args, **kwargs)
  File "/var/task/werkzeug/formparser.py", line 292, in _parse_multipart
    form, files = parser.parse(stream, boundary, content_length)
  File "/var/task/werkzeug/formparser.py", line 459, in parse
    parser.receive_data(data)
  File "/var/task/werkzeug/sansio/multipart.py", line 138, in receive_data
    self.buffer.extend(data)
TypeError: 'str' object cannot be interpreted as an integer

I can't tell if there is misconfiguration in my sam template.yaml or if flask-lambda is just so out of date that this occurs for everyone.

Does anyone know why this is happening and how I can fix this?

NOTE: I do have the below set for BinaryMediaTypes on the API gateway configuration.

      BinaryMediaTypes:
        - '*~1*'  # converts to */* for any binary type
        - 'multipart/form-data'

1 Answers1

0

Werkzeug/Flask expect a different type of object for environ['wsgi.input'] than what flask-lambda is providing.

I resolved this by copying the flask-lambda module into my project and changing:

[...] import StringIO

#  ...

environ['wsgi.input'] = StringIO(event['body'] or '')

to

import io

#  ...

environ['wsgi.input'] = io.BytesIO((event['body'] or '').encode())

If you're using the original repo this is the relevant line.

I recommend this fork of a fork of flask-lambda but it has the same flaw.

(I'm using Python3.8, Flask==2.0.2, Werkzeug==2.0.3)

  • This fixed my issue too, but still have no idea why it was working before and why it does not now. There is no real change in neither flask nor flask-inject. Can you point out why this fix was needed? – Guigreg Aug 04 '23 at 10:52