cod*_*000 8 python urllib urllib2 python-2.7
我有一个网址,我正在一个可以移动的网站上,当移动端点时,我需要重新应用POST/GET参数.我错过了什么来确保这个处理程序这样做?
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
Run Code Online (Sandbox Code Playgroud)
当我通过fiddler观察流量时,我注意到用于身份验证的令牌被丢弃了.
(请注意我不能使用此解决方案的请求,它必须只是标准库)
谢谢
关于 HTTP 1.0 和 1.1 状态代码 302、303 和 307 的故事有点复杂。基本上,您会看到预期的和记录的行为(您也可以查看此答案以获取更详细的描述):
此方法的默认实现并不严格遵循RFC 2616,该 RFC 2616 规定,
POST未经用户确认,不得自动重定向对请求的 301 和 302 响应。实际上,浏览器确实允许自动重定向这些响应,将 更改POST为 aGET,并且默认实现会重现此行为。
你走的是正确的路,但却覆盖了错误的方法。这是以下的来源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)
Run Code Online (Sandbox Code Playgroud)
这里有几点观察。它没有通过data,因此新的请求是GET。它过滤掉content-length和content-type标头,这是正确的POST. 事实上,在我的例子中req.headers是一个空字典,所以我求助于req.header_items()(参见参考资料unredirected_hdrs)。而且不处理POST307重定向。
下面是 POST 和 302 重定向的正确重定向处理程序实现。这里还有完整的 CherryPy 模拟(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)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
570 次 |
| 最近记录: |