2015-08-06 10 views
8

Ho un URL che sto colpendo su un sito che può essere spostato, e quando l'endpoint viene spostato, ho bisogno dei parametri POST/GET per essere riapplicati . Cosa mi manca per garantire che questo gestore faccia questo?Python 2.7 - Il gestore di reindirizzamento non passa i parametri su re-direct

class RedirectHandler(urllib2.HTTPRedirectHandler): 


    def http_error_301(self, req, fp, code, msg, headers): 
     result = urllib2.HTTPRedirectHandler.http_error_301(
      self, req, fp, code, msg, headers) 
     result.status = code 
     return result 

    def http_error_302(self, req, fp, code, msg, headers): 
     result = urllib2.HTTPRedirectHandler.http_error_302(
      self, req, fp, code, msg, headers) 
     result.status = code 
     return result 

Quando guardo il traffico attraverso violinista, mi accorgo che il token, che viene utilizzato per l'autenticazione viene scartato.

(si prega di notare che non posso usare le richieste per questa soluzione, deve essere libreria standard solo)

Grazie

+0

Dove sono i cookie? (o le informazioni sulla sessione) – dsgdfg

+0

@SDilmac quindi pensi che un gestore di cookie risolverà questo problema? –

+0

Vero! Tutti i servizi Web che utilizzano cookie cos non possono salvare tutte le azioni del visitatore. – dsgdfg

risposta

2

La storia di HTTP 1.0 e 1.1 codici di stato 302, 303 e 307 è un poco complicato. Fondamentalmente si vede l'atteso e documented comportamento (si può anche guardare this answer per la descrizione più):

L'implementazione predefinita di questo metodo non seguire rigorosamente RFC 2616, che dice che 301 e 302 risposte alle POST richieste non deve essere automaticamente reindirizzato senza conferma da parte dell'utente. In realtà, i browser consentono il reindirizzamento automatico di queste risposte, modificando lo POST in un GET e l'implementazione predefinita riproduce questo comportamento.

E tu vai nel modo giusto, ma sostituisci i metodi sbagliati. Ecco la fonte di urllib2.HTTPRedirectHandler.redirect_request:

def redirect_request(self, req, fp, code, msg, headers, newurl): 
    """Return a Request or None in response to a redirect. 
    ... 
    Return None if you can't but another Handler might. 
    """ 
    m = req.get_method() 
    if (code in (301, 302, 303, 307) and m in ("GET", "HEAD") 
     or code in (301, 302, 303) and m == "POST"): 
     # ... 
     newurl = newurl.replace(' ', '%20') 
     newheaders = dict((k,v) for k,v in req.headers.items() 
          if k.lower() not in ("content-length", "content-type") 
         ) 
     return Request(newurl, 
         headers=newheaders, 
         origin_req_host=req.get_origin_req_host(), 
         unverifiable=True) 
    else: 
     raise HTTPError(req.get_full_url(), code, msg, headers, fp) 

Diverse osservazioni qui. Non passa data, quindi la nuova richiesta è GET. Filtra le intestazioni content-length e content-type, che sono necessarie per un corretto POST. In effetti, nel mio esempio req.headers è un dict vuoto, quindi ho fatto ricorso a req.header_items() (vedere unredirected_hdrs). Inoltre non gestisce POST e il reindirizzamento 307.

Ecco una corretta implementazione del redirector per il reindirizzamento POST e 302. Ecco anche la simulazione completa CherryPy (fare prima pip install cherrypy).

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 


import urllib2 
from urllib2 import HTTPRedirectHandler, Request 

import cherrypy 


config = { 
    'global' : { 
    'server.socket_host' : '127.0.0.1', 
    'server.socket_port' : 8080, 
    'server.thread_pool' : 8 
    } 
} 


class RedirectHandler(HTTPRedirectHandler): 

    def redirect_request(self, req, fp, code, msg, headers, newurl): 
     if code == 302 and req.get_method() == 'POST': 
     return Request(newurl, headers=dict(req.header_items()), data=req.data, 
      origin_req_host=req.get_origin_req_host(), unverifiable=True) 
     else: 
     return HTTPRedirectHandler.redirect_request(self, req, fp, code, msg, 
      headers, newurl) 


class App: 

    @cherrypy.expose 
    def index(self): 
    opener = urllib2.build_opener(RedirectHandler()) 
    return opener.open('http://localhost:8080/redirect', data='foo=bar') 

    @cherrypy.expose 
    def redirect(self, **kwargs): 
    print('Before redirect {0}'.format(kwargs)) 
    raise cherrypy.HTTPRedirect('/target', 302) 

    @cherrypy.expose 
    def target(self, **kwargs): 
    return 'Target received {0} {1}'.format(cherrypy.request.method, kwargs) 


if __name__ == '__main__': 
    cherrypy.quickstart(App(), '/', config) 
+0

Grazie per la risposta, metterò alla prova questo e tornerò da te! –

Problemi correlati