2014-10-01 157 views
4

我使用Python 2.7.5,Django的1.7,要求2.4.1,並做一些簡單的測試。但是,它看起來像我調用requests.post時,該方法是做一個GET。Python請求POST做GET?

我的代碼,跟一個REST的API。請注意,POST指令通過Hurl.it可與該有效載荷和終點:

def add_dummy_objective(self): 
    """ 
    To the bank 
    """ 
    payload = { 
     'displayName': { 
      'text': self._test_objective 
     }, 
     'description': { 
      'text': 'For testing of API Middleman' 
     }, 
     'genusTypeId': 'DEFAULT' 
    } 
    obj_url = self.host + self.bank_id + '/objectives/?proxyname=' + self._admin_key 
    req = requests.post(obj_url, data=json.dumps(payload), headers=self.headers) 
    return req.json() 

我設置了標題爲JSON:

self.headers = { 
    'Content-Type' : 'application/json' 
} 

而不是創建一個新的目標(如用POST預期),我得到了一個目標列表(我期望得到一個GET)。使用pdb,我看到:

(Pdb) req.request 
<PreparedRequest [GET]> 
(Pdb) req.request.method 
'GET' 

這是如何翻轉的?我已經使用了Python沒有問題之前請求庫,所以我不知道如果我失去了一些東西明顯,或者(和Django /採購的新版本),我必須設置其他參數?這是一個緩存問題嗎?任何調試技巧?我嘗試重新安裝請求,並將Django回滾到1.6.5,但沒有任何工作......一定很簡單。 - 謝謝!

======更新1個========

只是鞏固了一些調試信息的那馬亭這裏建議:

(Pdb) requests.post.__name__ 
'post' 

步入請求/ API。 PY>柱()定義:

(Pdb) l 
88   :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. 
89   :param \*\*kwargs: Optional arguments that ``request`` takes. 
90   """ 
91   import pdb 
92   pdb.set_trace() 
93 ->  return request('post', url, data=data, **kwargs) 

鑽孔向下進入請求()方法:

(Pdb) method 
'post' 
(Pdb) l 
43   >>> req = requests.request('GET', 'http://httpbin.org/get') 
44   <Response [200]> 
45   """ 
46   import pdb 
47   pdb.set_trace() 
48 ->  session = sessions.Session() 
49   return session.request(method=method, url=url, **kwargs) 

還有一層,在session.request:

(424)request() 
-> method = builtin_str(method) 
(Pdb) method 
'post' 
(Pdb) l 
419    :param cert: (optional) if String, path to ssl client cert file (.pem). 
420     If Tuple, ('cert', 'key') pair. 
421    """ 
422    import pdb 
423    pdb.set_trace() 
424 ->   method = builtin_str(method) 
425 
426    # Create the Request. 
427    req = Request(
428     method = method.upper(), 
429     url = url, 

下臺該方法,其中該請求實際上是由結束時,我的「製備」是一個POST,但我的RESP是GET:

(Pdb) prep 
<PreparedRequest [POST]> 
(Pdb) n 
-> return resp 
(Pdb) resp 
<Response [200]> 
(Pdb) resp.request 
<PreparedRequest [GET]> 
(Pdb) l 
449     'allow_redirects': allow_redirects, 
450    } 
451    send_kwargs.update(settings) 
452    resp = self.send(prep, **send_kwargs) 
453 
454 ->   return resp 
455 
456   def get(self, url, **kwargs): 
457    """Sends a GET request. Returns :class:`Response` object. 
458 
459    :param url: URL for the new :class:`Request` object. 
+0

您發佈的代碼將不*生成GET,它將生成POST。你是否100%確定你正在執行正確的代碼路徑? – 2014-10-01 19:42:04

+0

這是我的單元測試的一部分,我正在逐行執行,所以我99%肯定這是它遵循的代碼路徑 - 如果有其他方法檢查以消除1%,我是不知道如何,但會很樂意去做... – user 2014-10-01 19:46:32

+0

順便說一下,我同意並理解上面的代碼應該產生一個POST ...所以我認爲別的是錯的(1%)。如果我使用錯誤的代碼路徑,還有什麼其他方法可以找到我正在執行的路徑(除了pdb)? – user 2014-10-01 19:48:40

回答

9

需要明確的是,每當收到的請求重定向(有一定的status code),我們必須對請求執行某些轉換。

在這樣的情況下,當你看到一些很意外的最好的調試技巧是重試您的請求,但與allow_redirects=False。這將立即返回30倍響應。另外,您還可以檢查r.history,看看是否有隨訪任何30X響應。在這種情況下,你可能會看到類似

>>> r.request.method 
'GET' 
>>> r.history 
[<Response [302]>,] 
>>> r.history[0].request.method 
'POST' 

我們知道,這樣做可能會導致使用者意外的行爲(因爲它只是做給你),但它在網絡上操作的唯一正確途徑。

我希望這可以幫助你理解爲什麼發生超出了事實,這是一個重定向,並希望它可以讓你和其他工具,以在未來的調試此。

+0

感謝您的明確解釋!找到這個之後,我做了一些關於重定向的閱讀,並且更好地理解了爲什麼圖書館的行爲如此... – user 2014-10-02 14:54:55

6

感謝Martijn提供了一些調試技巧!這個問題是REST風格的API被重定向我從http://到https://,這引起了庫返回「第二」請求(GET)...