pythonflask

How to handle malformed API request in Flask?


There is quite an old game (that no longer works) that has to make some API calls in order to be playable. I am creating a Flask mock server to handle those requests, however it turned out that the requests are not compliant with HTTP standard and are malformed. For example:

Get /config.php http/1.1

to which flask reports code 400, message Bad request version ('http/1.1').

After searching for various solutions, here is what I tried (and none worked):

  1. before_request
  2. Python decorator
  3. wsgi_app middleware

Here is my code:

from flask import Flask, request
from functools import wraps

app = Flask(__name__)

class RequestMiddleware:
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        print('Middleware', environ['REQUEST_METHOD'], environ['SERVER_PROTOCOL'])
        return self.app(environ, start_response)

def RequestDecorator(view):
    @wraps(view)
    def decorated(*args, **kwargs):
        print('Decorator', args, kwargs)

        return view(*args, **kwargs)

    return decorated

@app.before_request
def RequestHook():
    print('Before request: url: %s, path: %s' % (request.url, request.path))

app.wsgi_app = RequestMiddleware(app.wsgi_app)

@app.route("/config.php", methods=["GET"])
@RequestDecorator
def get_config():
    return ("{}", 200)

Example output:

Middleware GET HTTP/1.1
Before request: url: http://localhost/config.php, path: /config.php
Decorator () {}
"GET /config.php HTTP/1.1" 200 -
code 400, message Bad request version ('http/1.1')
"Get /config.php http/1.1" 400 -

Malformed request is not getting output from any of the solutions. My goal was to intercept the request before it is rejected in order to string replace Get to GET and http/1.1 to HTTP/1.1. Is it even possible?


Solution

  • Flask uses Werkzeug which in turn uses Python's http.server to parse HTTP requests.

    So the error is actually thrown by Python's http.server.BaseHTTPRequestHandler @ Line 311.

    Only way to get around this error is by monkey patching certain methods. If you let me know the version number of Werkzeug that you're running, I'll update my answer with a patch.