flask-restful: Bad Request on GET with header Content-Type

I have a simple GET request on an endpoint returning a list of entity.

This query gives me back a 400 Bad request error :

curl -s -D - http://localhost:5000/workdays -H 'Content-Type: application/json'
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json
Content-Length: 98
Date: Wed, 30 Sep 2015 20:13:44 GMT

{
    "message": "The browser (or proxy) sent a request that this server could not understand."
}

If I remove the Content-Type header, there is no error. Is it not overkill to reject a GET request with a content type header ?

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 31 (11 by maintainers)

Commits related to this issue

Most upvoted comments

IMO since GETs should not have a body, the header Content-Type can be safely ignored.

I’ve created a middleware to do so:

import logging
logger = logging.getLogger(__name__)

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

    def __call__(self, environ, start_response):
        if environ['REQUEST_METHOD'] == 'GET':
            try:
                del environ['CONTENT_TYPE']
            except KeyError:
                pass
            else:
                logger.debug('Remove header "Content-Type" from GET request')
        return self.app(environ, start_response)

I’m leaning towards the following:

  • Don’t remove Content-Type headers. HTTP Spec never says that Content-Type must not be included on bodyless requests.
  • Stop blowing up if header is provided 😃

Still have this issue and I request to open this and fix this.

Admittedly, if location is set to 'args' the request doesn’t blow up:

...
    parser = reqparse.RequestParser()
    parser.add_argument("place_holder", type=int, required=False, location='args')
    parser.parse_args()
...

I will use this as a short term fix. I’ve been thinking about moving the parsing over to webargs anyways.

@phillip-martin location='args' seems to be the solution.

In that case, I’d completely expect Restful to pitch a fit because there isn’t a JSON body included with the GET request (and there never should be either). So, the issue isn’t really sending a GET with a Content-Type, it’s attempting to parse an non-existent content body.

I ran into this with requests when working on an API at work, ultimately it comes down to the fact that JSON libraries in Python don’t seem to be okay with '' (meaning, no content) as a JSON body. I’m actually unsure if '' is considered valid JSON or not (I’d have to dig through the RFC to be 100%).

Has anyone else experienced this since it was closed? I was able to reproduce this on a fresh install of Python 2.7.10 Restful 0.3.5 and Flask 0.10.1.

from flask import Flask
from flask_restful import Resource, Api, reqparse


app = Flask(__name__)
api = Api(app)


@app.route('/')
def good():
    return '{"status": "OK!"}'


class TestResource(Resource):
    def get(self):
        return {'status': "OK!"}

@app.route('/parse')
def parse():
    parser = reqparse.RequestParser()
    parser.add_argument("place_holder", type=int, required=False)
    parser.parse_args()
    return '{"status": "OK!"}'


api.add_resource(TestResource, '/test')


if __name__ == "__main__":
    app.run(debug=True)

Testing:

curl -s -D - http://localhost:5000 -H 'Content-Type: application/json'
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 17
Server: Werkzeug/0.11.10 Python/2.7.10
Date: Thu, 28 Jul 2016 20:14:01 GMT

{"status": "OK!"}
curl -s -D - http://localhost:5000/test -H 'Content-Type: application/json'
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 24
Server: Werkzeug/0.11.10 Python/2.7.10
Date: Thu, 28 Jul 2016 20:14:40 GMT

{
    "status": "OK!"
}
curl -s -D - http://localhost:5000/parse -H 'Content-Type: application/json'
HTTP/1.0 400 BAD REQUEST
Content-Type: text/html
Content-Length: 177
Server: Werkzeug/0.11.10 Python/2.7.10
Date: Thu, 28 Jul 2016 20:15:05 GMT

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>400 Bad Request</title>
<h1>Bad Request</h1>
<p>Failed to decode JSON object: No JSON object could be decoded</p>

It all goes wrong on this line - parser.parse_args(). #556 is the same issue. Just to be safe I attempted the same with the latest master. Same thing.