2010-07-02 15 views
6

Estoy tratando de enviar un mensaje POST con una carga útil puramente XML (creo) usando urllib2 en IronPython. Sin embargo, cada vez que lo envío, devuelve el código de error 400 (solicitud incorrecta).HTTP POST autenticado con carga útil XML usando Python urllib2

En realidad estoy tratando de imitar un Boxee eliminar llamado elemento de cola para la que los paquetes de datos reales se ve así (de 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> 

estoy usando el siguiente código Python para enviar el 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 

sin embargo, cada vez que corro esto, se devuelve un error 400 (Bad Request)
sé que la autenticación es correcta, porque lo uso en otros lugares en busca de la cola (y no me puedo imaginar que no es utilizado De lo contrario, ¿cómo sería? ¿a qué cuenta aplicar el cambio?)

Al observar la captura de red, ¿podría simplemente perder la adición de algunos encabezados a la solicitud? Probablemente sea algo simple, pero no sé lo suficiente sobre las solicitudes de python o HTTP para saber qué es qué.

Editar: Por cierto, estoy llamando el código de la siguiente manera (en realidad es dinámica, pero esta es la idea básica):

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

Un consejo. Intenta hacerlo funcionar usando curl en la línea de comando primero. Puedes capturar eso usando las opciones de depuración de curl y eso puede darte algunas pistas. También es posible que en python necesite forzar el encabezado de usuario-agente curl debido a que algunas interfaces HTTP programáticas rechazan agentes de usuario desconocidos, desafortunadamente. Otra posibilidad es que tenga que imitar la forma en que boxee proporciona cookies al servidor. –

+0

Hmmm, buenos puntos. Ignoré el agente de usuario y las cookies ya que el proceso de obtención funcionó bien sin él. Le dará una oportunidad. Gracias. –

+0

Intenté configurar una cuenta y probarla yo mismo, pero no puedo averiguar dónde en boxee.tv para activar esta solicitud normalmente, así puedo verla en Wireshark. –

Respuesta

0

Esto funcionó bien para mí:

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' 

Pero obtengo 400 Bad Request si trato de eliminar una ID de referencia que no está actualmente en la cola. Si está utilizando la misma ID de referencia que detectó en Wireshark, es muy probable que también le suceda lo mismo. Use

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

para asegurarse de que lo que está tratando de eliminar está realmente en la cola.