Tornado - JSON Output sent as Response to be wrapped in dictionary

I came across this section in the docs :

RequestHandler.write(chunk)

Writes the given chunk to the output buffer.

To write the output to the network, use the flush() method below.

If the given chunk is a dictionary, we write it as JSON and set the Content-Type of the response to be application/json. (if you want to send JSON as a different Content-Type, call set_header after calling write()).

Note that lists are not converted to JSON because of a potential cross-site security vulnerability. All JSON output should be wrapped in a dictionary. More details at http://haacked.com/archive/2009/06/25/json-hijacking.aspx/ and https://github.com/facebook/tornado/issues/1009

So I have a few questions related to this:

  1. What does it mean by this?

If the given chunk is a dictionary, we write it as JSON.

  1. What does it mean by this?

Note that lists are not converted to JSON because of a potential cross-site security vulnerability.

  1. What does it mean by this? And here, what does it mean by JSON output? And why to wrap it in a dictionary?

All JSON output should be wrapped in a dictionary.

  1. This has two subparts :

    a. What is the best way to send JSON responses from Tornado to client?

    b. What is a better way to send responses? If not JSON, then what is? And if it JSON, then just mention the answer to subpart (a).

Please try to answer all the parts and their subparts in numbered manner so that I can understand them properly.

Answers


  1. What does it mean by this?

    If the given chunk is a dictionary, we write it as JSON.

It means, that if you pass dict to write it will we be automatically json encoded. Method write can handle dict, byte, unicode_type (simplifying it is str).

  1. What does it mean by this?

    Note that lists are not converted to JSON because of a potential cross-site security vulnerability.

Assume that you provide some service and with request /example/my_service/user_data.json and JSON response.

If top level object would be an array like:

["John Smith", "email@mail"]

Then attacker could redefine Array's constructor and then add script tag with /example/my_service/user_data.json, that gets evaluated immediately - array is created with attacker's constructor. This is because standalone array is valid javascript code.

Since standalone objects, except empty one, are not valid JS, so if you return

{"name": "John Smith", "email":"email@mail"}

Attacker end up with SyntaxError: missing ; before statement or something similar.

More info http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx/

  1. What does it mean by this? And here, what does it mean by JSON output? And why to wrap it in a dictionary?

    All JSON output should be wrapped in a dictionary.

As you read above, it becomes pretty clear, top-level element in JSON should not be an array. Moreover Tornado will raise error if you pass list.Of course you can bypass this safety, simply passing string (json dumps before wirte), but it is not wise:

self.write('["this", "is", "wrong"]')
  1. a. What is the best way to send JSON responses from Tornado to client?

    b. What is a better way to send responses? If not JSON, then what is? And if it JSON, then just mention the answer to subpart (a).

I use, if possible, json or xml as a response. But I am not using Tornado's mechanism for that, I pass already encoded object - string to write. The reason is, that it's the cleanest way to override Tornado's encoders and use e.g. ujson.

edit

Worth noting that modern browsers should not vulnerable.


Need Your Help

Android game - simulate object rotation along its path

android animation vector opengl-es

I'm reading this awesome Beginning Android Games book, and I'm trying now to implement some tests myself.