2011-06-10 69 views
7

我目前正在使用一段已被其他人編寫的代碼。它使用httplib向服務器發送請求。它提供了正確格式的所有數據 - 例如郵件正文,標題值等。Python httplib和POST

問題是,每次嘗試發送POST請求時,數據都在那裏 - 我可以看到它在客戶端,但是沒有任何東西到達服務器。我已經通讀了庫規範,使用情況似乎是正確的。

提取出庫的調用去如下:

import httplib 

conn = httplib.HTTPConnection('monkeylabs.pl', 80) 
conn.connect() 
request = conn.putrequest('POST', '/api/snippet/') 
headers = {} 
headers['Content-Type'] = 'application/json' 
headers['User-Agent'] = 'Envjs/1.618 (SpyderMonkey; U; Linux x86_64 2.6.38-10-generic; pl_PL.utf8; rv:2.7.1) Resig/20070309 PilotFish/1.3.pre03' 
headers['Accept'] = '*/*' 
for k in headers: 
    conn.putheader(k, headers[k]) 
conn.endheaders() 

conn.send('[{"id":"route"}]') 

resp = conn.getresponse() 
print resp.status 
print resp.reason 
print resp.read() 

conn.close() 

這是一些已知的問題,還是什麼?我正在使用Python 2.7。不知道如何檢查httplib的版本。

請不要建議將httplib換成別的東西,除非它真的類似(httplib2也許)。正如我所說,代碼不是我的,它的數量遠遠超過我剛剛發佈的數量。重構它會導致一個重大問題。我對任何可靠的解決方法感興趣。

編輯

調試輸出:

send: 'POST /api/snippet/ HTTP/1.1\r\nHost: monkeylabs.pl\r\nAccept-Encoding: identity\r\nContent-Type: application/json\r\nAccept: */*\r\nUser-Agent: Envjs/1.618 (SpyderMonkey; U; Linux x86_64 2.6.38-10-generic; pl_PL.utf8; rv:2.7.1) Resig/20070309 PilotFish/1.3.pre03\r\n\r\n[{"id":"route"}]' 
reply: 'HTTP/1.0 201 CREATED\r\n' 
header: Date: Fri, 10 Jun 2011 23:54:00 GMT 
header: Server: WSGIServer/0.1 Python/2.7.1+ 
header: Vary: Cookie 
header: Content-Type: application/json 
header: Content-Length: 0 
201 
CREATED 

注意,後答覆居然有關服務器的答覆,而不是請求本身,在這種情況下是空的談判的信息。主要的原因是請求體本身是空的,我可以得到一個日誌觀察:

[11/Jun/2011 01:54:00] "POST /api/snippet/ HTTP/1.1" 201 0 

而那些三行:

`` 
<QueryDict: {}> 
<QueryDict: {}> 

出來的:

print '`%s`' % request.raw_post_data 
print request.GET 
print request.POST 

上Django服務器。所以它似乎試圖發送主體,但最終不會發送它。

EDIT(2)

好吧,我花了轉儲,它確實告訴我,從瀏覽器發送的消息中有一個名爲「Content-Length的」額外的參數已經在被省略經常使用圖書館。傻我。

+2

順便說一句,如果你認爲你會被調試這個東西很多,安裝[Wireshark的(http://www.wireshark.org/ )並用它來窺探電線上的實際情況。 – Darien 2011-06-10 23:17:16

+0

謝謝,我在一開始並不信任,但實際上讓我找到了解決方案。再次感謝 – julkiewicz 2011-06-11 00:51:37

+0

服務器有:response.set_header('Access-Control-Allow-Origin','*')? – 2012-08-19 23:30:57

回答

5

嘗試添加:

conn.set_debuglevel(1) 

你的代碼,所以你可以看到什麼是真正發生的事情。

0

您是否檢查過httplib文檔? httplib的是一個標準的Python庫和Python也很良好,具有在線文檔:http://docs.python.org/library/httplib.html

從該頁面的例子:

>>> import httplib, urllib 
>>> params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0}) 
>>> headers = {"Content-type": "application/x-www-form-urlencoded", 
...   "Accept": "text/plain"} 
>>> conn = httplib.HTTPConnection("musi-cal.mojam.com:80") 
>>> conn.request("POST", "/cgi-bin/query", params, headers) 
>>> response = conn.getresponse() 
>>> print response.status, response.reason 
200 OK 
>>> data = response.read() 
>>> conn.close() 

你的例子似乎比這更多的工作,如果你讀API文檔 - 例如putrequest - 您會發現在您的示例中您使用的是錯誤的。具體來說,它默認會自動添加Accept標頭。

嘗試讓您的代碼更像功能性示例,同時嘗試理解您的代碼中使用的調用以及在工作示例中使用的調用。

+1

是的,我確實讀過API文檔,一切都很好。問題是它不好。通過其他各種方式發出的相同請求 - 比如說瀏覽器或其他庫,效果很好。刪除「接受」標題不會改變任何內容。你從API中複製的例子只是做了一些完全不同的事情。這不是一個POST,它不會嘗試上傳郵件正文。 – julkiewicz 2011-06-10 23:45:27

6

putrequest方法不會自動添加內容長度標題,您需要自己動手或使用request方法。

給你的代碼添加for以上循環:

headers['Content-Length'] = "%d"%(len('[{"id":"route"}]'))