4

I'm attempting to make a curl request to my python api that is using the AWS package Chalice.

When I try to access the app.current_request.json_body a JSON Parse error is thrown. Cannot figure out why this is happening. My JSON is formatted properly as far as I can tell.

Here is the curl request:

(echo -n '{"data": "test"}') |
curl -H "Content-Type: application/json"  -d @-  $URL

Here is the python Chalice code:

app = Chalice(app_name='predictor')

@app.route('/', methods=['POST'], content_types=['application/json'])
def index():
    try:
        body = app.current_request.json_body
    except Exception as e:
        return  {'error':  str(e)}

When I invoke the route using the above curl request I get the following error:

{"error": "BadRequestError: Error Parsing JSON"}

Note: When I remove the .json_body from the app.current_request. I no longer get the error.

Any thoughts?

Nicholas Porter
  • 2,588
  • 2
  • 23
  • 37
  • I don't use `chalice` but what actually is `app.current_request`? Is it some object where you have to call methods to get any useful insight or is it, itself, JSON-like? – roganjosh Oct 13 '18 at 05:51
  • `app.current_request` has a lot of request properties that you can read from such as `.method`. The only thing they mention in the documentation about `json_body` is this: "json_body: The parsed JSON body (json.loads(raw_body)). This value will only be non-None if the Content-Type header is application/json, which is the default content type value in chalice." – Nicholas Porter Oct 13 '18 at 05:55
  • Chalice is a class. – Nicholas Porter Oct 13 '18 at 05:57
  • Huh. Is there anything to be gleaned from the traceback if you remove the `try/except`? I'm familiar with Flask but not Chalice. – roganjosh Oct 13 '18 at 05:58
  • If I remove the try/except it still throws the error when it tries to access the `json_body`. So strange, hard to find examples too. – Nicholas Porter Oct 13 '18 at 06:00
  • It will obviously still throw the error, but I wondered if it gave any more info on what exactly the error is i.e. where the JSON parser gets upset – roganjosh Oct 13 '18 at 06:01
  • No that is the only information provides about the error. – Nicholas Porter Oct 13 '18 at 06:03
  • What does print(app.current_request) output? You'll want to look at the headers and the raw body to verify that the request data is what you actually expect. Your code looks correct to me. – dmulter Oct 13 '18 at 16:34
  • 1
    There must have been something wrong about the curl request format because when I make the request using this syntax `-d '{"data": "TEST"}'` the `.json_body` is defined as the sent payload. – Nicholas Porter Oct 15 '18 at 23:33
  • Actually I tested your exact code with the exact curl command you provided, and everything works fine. – dmulter Feb 22 '20 at 14:40
  • I am experiencing a similar issue. When I use `parse_qs(app.current_request.raw_body.decode())` to print out the received content, it shows an empty object `{}`. I am uncertain why the body sent from the gateway to the lambda function is empty. I suspect that there may be a problem with the default gateway settings provided by Chalice. – ExistMe Aug 28 '23 at 15:27

2 Answers2

4

The documentation indeed indicates that the problem is Content-Type:

The default behavior of a view function supports a request body of application/json. When a request is made with a Content-Type of application/json, the app.current_request.json_body attribute is automatically set for you. This value is the parsed JSON body.

You can also configure a view function to support other content types. You can do this by specifying the content_types parameter value to your app.route function. This parameter is a list of acceptable content types.

It suggests that changing the Content-Type might make json_body work, but I didn't manage to have any success with it.

However using app.current_request.raw_body.decode() instead of app.current_request.json_body solves the problem.

Community
  • 1
  • 1
BanzaiTokyo
  • 1,376
  • 4
  • 17
  • 33
0

I was having the same problem whilst writing a feature test using the Chalice test client. I had to set the content type in both the decorator and the request I built with the client.

My route is configured as below:

@app.route("/allocate", methods=["POST"], content_types=["application/json"])
def allocate():
  ...
  line = OrderLine(**app.current_request.json_body)
  ...

And the test:

client.http.post(
    "/allocate",
    body=json.dumps({...}),
    headers = {"Content-Type": "application/json"},
  )

Hopefully this is useful to someone!