0

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.

Anirban Roy Das
  • 262
  • 4
  • 14

1 Answers1

2
  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.

Community
  • 1
  • 1
kwarunek
  • 12,141
  • 4
  • 43
  • 48
  • Thanks man. So what happens when I use the escape.json_encode(response) and then do self.write(response), given the fact my response is itself a dictionary. So it is json encoded now, so what will happen now? Which if statements in https://github.com/tornadoweb/tornado/blob/master/tornado/web.py#L692 does it satisfy? – Anirban Roy Das Jan 16 '16 at 11:35
  • Also why is it a benefit to use ujson (or any other 3rd party json library) when tornado provides its in-house json module? What are the pros and cons? – Anirban Roy Das Jan 16 '16 at 11:38
  • `json_encode` serialize objcet to json, it returns string with encoded object, so write will treat that like string. – kwarunek Jan 16 '16 at 11:52
  • And what is the benefit of using the 3rd party json module? – Anirban Roy Das Jan 16 '16 at 11:58
  • why `ujson`? I use it with high-load json-rpc apps with large objects, it is only matter of performance http://blog.dataweave.in/post/87589606893/json-vs-simplejson-vs-ultrajson. But as usual it is not for free http://mod16.org/hurfdurf/?p=266, https://github.com/esnme/ultrajson/issues/134 – kwarunek Jan 16 '16 at 11:59