2010-07-02 5 views
6

Ich versuche, eine POST-Nachricht mit einer reinen XML-Nutzlast (denke ich) mit irllib2 in IronPython zu senden. Jedes Mal, wenn ich es sende, wird jedoch der Fehlercode 400 (ungültige Anforderung) zurückgegeben.Authentifizierter HTTP POST mit XML-Payload mit Python urllib2

Ich bin eigentlich ein Boxee entfernen Warteschlangenelement Aufruf mimick versuchen, für die die eigentlichen Datenpakete wie folgt aussehen (von 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> 

mir den folgenden Python-Code mit der Post schicken :

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 

Jedes Mal, wenn ich dies ausführen, gibt es Fehler 400 (Bad Request)
ich weiß, dass die Authentifizierung korrekt ist, weil ich es (an anderer Stelle verwenden, um die Warteschlange zu holen, und ich kann es sich nicht vorstellen, ist nicht verwendet sonst wie wäre es nicht w, welches Konto, um die Änderung zu übernehmen?)

Mit Blick auf die Netzwerk-Capture, könnte ich einfach fehlen einige Header zur Anfrage hinzufügen? Wahrscheinlich etwas einfaches, aber ich weiß einfach nicht genug über Python oder HTTP-Anfragen, um zu wissen, was was ist.

bearbeiten: Übrigens, ich bin den Code Aufruf wie folgt (es ist tatsächlich dynamisch, aber das ist die Grundidee):

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

Ein Tipp. Versuchen Sie es zuerst mit curl in der Befehlszeile zu arbeiten. Sie können das mit den Debug-Optionen von curl aufnehmen und das könnte Ihnen Hinweise geben. Es ist auch möglich, dass Sie in Python den curl-User-Agent-Header fälschen müssen, da einige programmatische HTTP-Schnittstellen leider unbekannte Benutzeragenten ablehnen. Eine andere Möglichkeit ist, dass Sie die Art und Weise nachahmen, wie boxee Cookies an den Server zurückgibt. –

+0

Hmmm, gute Punkte. Ich habe den User-Agent und die Cookies ignoriert, da der get-Prozess ohne ihn funktioniert hat. Werde es versuchen. Vielen Dank. –

+0

Ich habe versucht, ein Konto einzurichten und dies selbst zu testen, aber ich kann nicht herausfinden, wo auf boxee.tv diese Anfrage normalerweise auslösen, so dass ich es in Wireshark sehen kann. –

Antwort

0

Das ist für mich gut funktioniert:

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' 

Aber ich bekomme 400 Bad Request, wenn ich versuche, eine Verweis-ID zu entfernen, die nicht in der Warteschlange ist. Wenn Sie die gleiche Referral-ID verwenden, die Sie bei Wireshark gefunden haben, ist dies wahrscheinlich auch für Sie der Fall. Verwenden Sie

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

, um sicherzustellen, dass das, was Sie versuchen zu entfernen, tatsächlich in der Warteschlange ist.