2010-07-02 74 views
6

我正嘗試使用IronPython中的urllib2發送純粹的XML負載(我認爲)的POST消息。但是,每次我發送它時,都會返回錯誤代碼400(錯誤請求)。使用Python對XML負載進行身份驗證HTTP POST urllib2

我實際上是試圖模擬天生一個Boxee的刪除隊列項呼籲其實際的數據包看起來像這樣(從Wireshark的):

POST /action/add HTTP/1.1 
User-Agent: curl/7.16.3 (Windows build 7600; en-US; beta) boxee/0.9.21.11487 
Host: app.boxee.tv 
Accept: */* 
Accept-Encoding: deflate, gzip 
Cookie: boxee_ping_version=9; X-Mapping-oompknoc=76D730BC9E858725098BF13AEFE32EB5; boxee_app=e01e36e85d368d4112fe4d1b6587b1fd 
Connection: keep-alive 
Content-Type: text/xml 
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 
Accept-Language: en-us,en;q=0.5 
Keep-Alive: 300 
Connection: keep-alive 
Content-Length: 53 

<message type="dequeue" referral="3102296"></message> 

我使用下面的Python代碼發送POST :

def PostProtectedPage(theurl, username, password, postdata): 

    req = urllib2.Request(theurl, data=postdata) 
    req.add_header('Content-Type', 'text/xml') 
    try: 
     handle = urllib2.urlopen(req) 
    except IOError, e:     # here we are assuming we fail 
     pass 
    else:        # If we don't fail then the page isn't protected 
     print "This page isn't protected by authentication." 
     sys.exit(1) 

    if not hasattr(e, 'code') or e.code != 401:     # we got an error - but not a 401 error 
     print "This page isn't protected by authentication." 
     print 'But we failed for another reason.' 
     sys.exit(1) 

    authline = e.headers.get('www-authenticate', '')    # this gets the www-authenticat line from the headers - which has the authentication scheme and realm in it 
    if not authline: 
     print 'A 401 error without an authentication response header - very weird.' 
     sys.exit(1) 

    authobj = re.compile(r'''(?:\s*www-authenticate\s*:)?\s*(\w*)\s+realm=['"](\w+)['"]''', re.IGNORECASE)   # this regular expression is used to extract scheme and realm 
    matchobj = authobj.match(authline) 
    if not matchobj:          # if the authline isn't matched by the regular expression then something is wrong 
     print 'The authentication line is badly formed.' 
     sys.exit(1) 
    scheme = matchobj.group(1) 
    realm = matchobj.group(2) 
    if scheme.lower() != 'basic': 
     print 'This example only works with BASIC authentication.' 
     sys.exit(1) 

    base64string = base64.encodestring('%s:%s' % (username, password))[:-1] 
    authheader = "Basic %s" % base64string 
    req.add_header("Authorization", authheader) 
    try: 
     handle = urllib2.urlopen(req) 
    except IOError, e:     # here we shouldn't fail if the username/password is right 
     print "It looks like the username or password is wrong." 
     print e 
     sys.exit(1) 
    thepage = handle.read() 
    return thepage 

但是,每當我運行它,它會返回錯誤400(無效請求)
我知道驗證是正確的,因爲我用它在其他地方獲取隊列(我無法想象它不會使用,否則它會怎麼樣哪個帳戶應用更改?)

看看網絡捕獲,我可以簡單地缺少添加一些頭到請求?可能有些簡單,但我對python或HTTP請求知之甚少。

編輯:BTW,我打電話的代碼如下所示(它實際上是動態的,但是這是基本的想法):

PostProtectedPage("http://app.boxee.tv/action/add", "user", "pass", "<message type=\"dequeue\" referral=\"3102296\"></message>") 
+1

一個提示。嘗試讓它在命令行中首先使用curl工作。你可以使用curl的調試選項來捕獲它,這可能會給你一些線索。在python中也可能需要僞造curl用戶代理頭,因爲一些程序化的HTTP接口拒絕未知的用戶代理。 另一種可能性是您需要模仿boxee向服務器提供Cookies的方式。 – 2010-07-02 13:56:11

+0

嗯,好點。我忽略了用戶代理和cookie,因爲沒有它,get過程運行良好。會給它一個鏡頭。謝謝。 – 2010-07-02 14:26:19

+0

我試着自己建立一個帳戶並進行測試,但我無法弄清楚boxee.tv上的哪個地方能正常觸發這個請求,所以我可以在Wireshark中看到它。 – 2011-05-23 16:17:18

回答

0

這對我來說工作得很好:

curl -v -A 'curl/7.16.3 (Windows build 7600; en-US; beta) boxee/0.9.21.11487' \ 
-H 'Content-Type: text/xml' -u "USER:PASS" \ 
--data '<message type="dequeue" referral="12573293"></message>' \ 
'http://app.boxee.tv/action/add' 

但是,如果我嘗試刪除當前不在隊列中的引用ID,我會得到400 Bad Request。如果您使用的是Wireshark中檢測到的同一個推薦ID,那很可能是您正在發生的事情。使用

wget -nv -m -nd --user=USER --password=PASS http://app.boxee.tv/api/get_queue 

確定您要刪除的內容實際上是否在隊列中。

相關問題