2010-07-02 17 views
6

Sto provando a inviare un messaggio POST con un payload puramente XML (credo) utilizzando urllib2 in IronPython. Tuttavia, ogni volta che lo invio, restituisce il codice di errore 400 (Richiesta non valida).POST HTTP autenticato con payload XML utilizzando Python urllib2

In realtà sto cercando di mimare un Boxee rimuovere chiamata elemento della coda per il quale i pacchetti di dati effettivi si presenta così (da 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> 

Sto utilizzando il seguente codice python per inviare il 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 

Tuttavia, ogni volta che ho eseguito questo, restituisce l'errore 400 (Richiesta non valida)
so che l'autenticazione è corretto perché lo uso altrove per andare a prendere la coda (e non riesco a immaginare che non è utilizzato , altrimenti come sarebbe no w quale account per applicare la modifica a?)

Guardando alla cattura della rete, potrei semplicemente mancare aggiungendo alcune intestazioni alla richiesta? Probabilmente qualcosa di semplice, ma non ne so abbastanza delle richieste di Python o HTTP per sapere cosa è cosa.

Edit: BTW, sto chiamando il codice come segue (in realtà è dinamica, ma questa è l'idea di base):

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

Un consiglio. Prova a farlo funzionare prima usando curl sulla riga di comando. Puoi catturarlo usando le opzioni di debug di Curl e questo potrebbe darti qualche indizio. È anche possibile che in python sia necessario forgiare l'intestazione User-Agent di arricciatura perché alcune interfacce HTTP programmatiche rifiutano i programmi utente sconosciuti, sfortunatamente. Un'altra possibilità è quella di imitare il modo in cui boxee fornisce i cookie al server. –

+0

Hmmm, buoni punti. Ho ignorato l'agente utente e i cookie poiché il processo di acquisizione funzionava correttamente senza di esso. Darà un colpo. Grazie. –

+0

Ho provato a creare un account e a testarlo da solo, ma non riesco a capire dove su boxee.tv attivare questa richiesta normalmente così posso vederlo in Wireshark. –

risposta

0

Questo ha funzionato bene per me:

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' 

Ma ottengo 400 Bad Request se provo a rimuovere un ID referral che non è attualmente in coda. Se stai usando lo stesso ID di riferimento che hai rilevato da Wireshark, è molto probabile che ciò che sta accadendo anche a te. Utilizzare

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

per assicurarsi che ciò che si sta tentando di rimuovere sia effettivamente in coda.