2010-07-02 76 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 

确定您要删除的内容实际上是否在队列中。

相关问题