Торнадо поставил запрос на пропажу тела


Я пытаюсь сделать запрос put, используя tornado ASyncHTTPClient, например:

  data = { 'text': 'important text',
           'timestamp': 'an iso timestamp' }

  request = tornado.httpclient.HTTPRequest(URL, method = 'PUT', body = urllib.urlencode(data))

  response = yield Task(tornado.httpclient.ASyncHTTPClient().fetch, request)
Однако, когда запрос достигает желаемой конечной точки, он, по-видимому, не имеет тела, несмотря на то, что это тело было правильно закодировано и определено выше. Есть ли что-то, что я упускаю из виду?
3 6

3 ответа:

Если другой конец ожидает JSON, вам, вероятно, нужно установить заголовок "Content-Type". Попробуйте это:

data = { 'text': 'important text',
       'timestamp': 'an iso timestamp' }

headers = {'Content-Type': 'application/json; charset=UTF-8'}

request = tornado.httpclient.HTTPRequest(URL, method = 'PUT', headers = headers, body = simplejson.dumps(data))

response = yield Task(tornado.httpclient.ASyncHTTPClient().fetch, request)

Таким образом, заголовок сообщает серверу, что вы отправляете JSON, а тело-это строка, которая может быть проанализирована как JSON.

Вопрос, вероятно, на другом конце.
Следующий тест с использованием Tornado 2.4.1 дает ожидаемый результат.

import logging
import urllib

from tornado.ioloop import IOLoop
from tornado.web import Application, RequestHandler, asynchronous
from tornado.httpclient import HTTPRequest, AsyncHTTPClient
from tornado import gen, options

log = logging.getLogger()
options.parse_command_line()

class PutBodyTest(RequestHandler):
    @asynchronous
    @gen.engine
    def get(self):
        data = {
            'text': 'important text',
            'timestamp': 'a timestamp'
        }
        req = HTTPRequest(
            'http://localhost:8888/put_body_test',
            method='PUT',
            body=urllib.urlencode(data)
        )
        res = yield gen.Task(AsyncHTTPClient().fetch, req)
        self.finish()

    def put(self):
        log.debug(self.request.body)

application = Application([
    (r"/put_body_test", PutBodyTest),
])

if __name__ == "__main__":
    application.listen(8888)
    IOLoop.instance().start()

Вывод журнала:

$ python put_test.py --logging=debug
[D 130322 11:45:24 put_test:30] text=important+text&timestamp=a+timestamp
[I 130322 11:45:24 web:1462] 200 PUT /put_body_test (127.0.0.1) 0.37ms
[I 130322 11:45:24 web:1462] 200 GET /put_body_test (::1) 9.76ms

Это post-запрос с ожиданием JSON! Попробуйте это:

    @gen.coroutine
    def post(self):
        http_client = AsyncHTTPClient()
        http_client = tornado.httpclient.AsyncHTTPClient()

        URL = "http://localhost:1338/api/getPositionScanByDateRange"
        data = {"startDate":"2017-10-31 18:30:00","endDate":"2018-02-08 12:09:14","groupId":3} #A dictionary of your post data
        headers = {'Content-Type': 'application/json; charset=UTF-8'}

        record = yield http_client.fetch(URL, method = 'POST', headers = headers, body = json.dumps(data))

        if record.error:
            response = record.error
        else:
            response = record.body
        self.set_header('Content-Type', 'application/json')
        self.finish(response)