Câu chuyện về HTTP 1.0 và 1.1 mã trạng thái 302, 303 và 307 là một ít phức tạp. Về cơ bản bạn thấy các mong đợi và documented hành vi (bạn cũng có thể nhìn vào this answer cho mô tả dài hơn):
Việc thực hiện mặc định của phương pháp này không đúng theo RFC 2616, mà nói rằng 301 và 302 phản ứng với POST
yêu cầu phải không được tự động chuyển hướng mà không cần người dùng xác nhận. Trên thực tế, trình duyệt cho phép tự động chuyển hướng các phản hồi này, thay đổi POST
thành GET
và triển khai mặc định sẽ tái tạo hành vi này.
Và bạn đi đúng cách, nhưng ghi đè các phương pháp sai. Đây là nguồn của 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)
Một số quan sát ở đây. Nó không vượt qua data
, do đó yêu cầu mới là GET
. Bộ lọc sẽ lọc ra các tiêu đề content-length
và content-type
, được yêu cầu cho đúng POST
. Nếu thực tế, trong ví dụ của tôi req.headers
là một dict trống, vì vậy tôi đã sử dụng số req.header_items()
(xem unredirected_hdrs
). Hơn nữa, không xử lý các chuyển hướng POST
và 307.
Dưới đây là cách thực hiện trình xử lý chuyển hướng chính xác cho chuyển hướng POST và 302. Đây cũng là mô phỏng CherryPy hoàn chỉnh (làm pip install cherrypy
trước).
#!/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)
Địa chỉ cookie của bạn ở đâu? (hoặc thông tin phiên của bạn) – dsgdfg
@SDilmac để bạn cho rằng trình xử lý cookie sẽ giải quyết vấn đề này? –
True! Tất cả các dịch vụ web sử dụng cookie cos không thể lưu tất cả các hành động của khách truy cập. – dsgdfg