2013-03-20 18 views
6

Próbuję złożyć zamówienie put użyciu ASyncHTTPClient tornado tak:Tornado PUT Zapytanie Brakujące Ciało

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) 

Jednak, gdy wniosek trafia do pożądanego punktu końcowego, nie wydaje się mieć ciało, mimo wspomniane ciało jest odpowiednio zakodowane i zdefiniowane powyżej. Czy jest coś, co tu widzę?


+0

Skąd importujesz 'HTTPRequest' z? A także w jaki sposób tworzysz instancję 'client' – aychedee

+1

HTTPRequest pochodzi z tornado.httpclient, a klient jest aliasem dla tornado.httpclient.ASyncHTTPClient. Zaktualizuję pytanie, aby to wyjaśnić! –

+0

Nie widzę niczego złego w kodzie, który tu masz. Może być subtelny błąd w kodzie obsługi? – aychedee

Odpowiedz

4

Jeśli drugi koniec spodziewa JSON, prawdopodobnie trzeba ustawić "Content-Type" nagłówek. Spróbuj tego:

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) 

ten sposób, nagłówek informuje serwer wysyłasz JSON, a ciało jest ciągiem znaków, które mogą być analizowane jako JSON.

+1

To działa, dziękuję! –

2

Kwestia jest prawdopodobnie na drugim końcu.
Poniższy test z wykorzystaniem Tornado 2.4.1 daje oczekiwany wynik.

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() 

wyjście Log:

$ 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 
+1

Dzięki! Zaczynam podejrzewać coś podobnego, a przeprowadzenie tego testu pomogło mi to potwierdzić. –

0

to jest prośba o przesłanie postu z oczekiwaniem na JSON! Wypróbuj to:

@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)