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)
Dove sono i cookie? (o le informazioni sulla sessione) – dsgdfg
@SDilmac quindi pensi che un gestore di cookie risolverà questo problema? –
Vero! Tutti i servizi Web che utilizzano cookie cos non possono salvare tutte le azioni del visitatore. – dsgdfg