def test_bad_cookie_header(self):
def cookiejar_from_cookie_headers(headers):
from mechanize import CookieJar, Request
c = CookieJar()
req = Request("http://www.example.com/")
r = FakeResponse(headers, "http://www.example.com/")
c.extract_cookies(r, req)
return c
# none of these bad headers should cause an exception to be raised
for headers in [
["Set-Cookie: "], # actually, nothing wrong with this
["Set-Cookie2: "], # ditto
# missing domain value
["Set-Cookie2: a=foo; path=/; Version=1; domain"],
# bad max-age
["Set-Cookie: b=foo; max-age=oops"],
# bad version
["Set-Cookie: b=foo; version=spam"],
]:
c = cookiejar_from_cookie_headers(headers)
# these bad cookies shouldn't be set
assert len(c) == 0
# cookie with invalid expires is treated as session cookie
headers = ["Set-Cookie: c=foo; expires=Foo Bar 12 33:22:11 2000"]
c = cookiejar_from_cookie_headers(headers)
cookie = c._cookies["www.example.com"]["/"]["c"]
assert cookie.expires is None
# cookie with unset path should have path=/
headers = ["Set-Cookie: c=foo; path; expires=Foo Bar 12 33:22:11 2000"]
c = cookiejar_from_cookie_headers(headers)
assert ('www.example.com' in c._cookies and
'/' in c._cookies['www.example.com'])
python类Request()的实例源码
def test_cookies_for_request(self):
from mechanize import CookieJar, Request
cj = CookieJar()
interact_netscape(cj, "http://example.com/", "short=path")
interact_netscape(cj, "http://example.com/longer/path", "longer=path")
for_short_path = cj.cookies_for_request(Request("http://example.com/"))
self.assertEquals([cookie.name for cookie in for_short_path],
["short"])
for_long_path = cj.cookies_for_request(
Request("http://example.com/longer/path"))
self.assertEquals([cookie.name for cookie in for_long_path],
["longer", "short"])
def test_firefox3_cookiejar_add_cookie_header(self):
try:
from mechanize import Firefox3CookieJar
except ImportError:
pass
else:
filename = self.mktemp()
hide_experimental_warnings()
try:
cj = Firefox3CookieJar(filename)
finally:
reset_experimental_warnings()
cj.connect()
# Session cookies (true .discard) and persistent cookies (false
# .discard) are stored differently. Check they both get sent.
year_plus_one = time.localtime(time.time())[0] + 1
expires = "expires=09-Nov-%d 23:12:40 GMT" % (year_plus_one, )
interact_netscape(cj, "http://www.foo.com/", "fooa=bar")
interact_netscape(cj, "http://www.foo.com/",
"foob=bar; %s" % expires)
ca, cb = cj
self.assert_(ca.discard)
self.assertFalse(cb.discard)
request = Request("http://www.foo.com/")
cj.add_cookie_header(request)
self.assertEquals(
request.get_header("Cookie"), "fooa=bar; foob=bar")
def test_gzip(self):
p = HTTPGzipProcessor()
url = "https://www.example.com/"
req = p.https_request(mechanize.Request(url))
self.assertIsNone(req.get_header('Accept-Encoding'))
p.request_gzip = True
req = p.https_request(mechanize.Request(url))
self.assertEqual(req.get_header('Accept-Encoding'), 'gzip')
req = mechanize.Request(url)
req.add_header('Accept-Encoding', 'moo, *')
req = p.https_request(req)
self.assertEqual(req.get_header('Accept-Encoding'), 'moo, *, gzip')
data = os.urandom(1024 * 1024)
cdata = b''.join(compress_readable_output(BytesIO(data)))
r = MockResponse(
url,
data=cdata,
info={
'Content-Encoding': 'gzip',
'Content-Length': str(len(cdata))
})
r = p.https_response(req, r)
self.assertEqual(r.read(), data)
h = r.info()
self.assertFalse(h.getheaders('content-encoding'))
self.assertFalse(h.getheaders('content-length'))
def test_add_host_header(self):
headers = []
def putheader(self_, header, value):
headers.append((header, value))
self.monkey_patch_httplib(putheader)
browser = self.make_browser()
request = mechanize.Request("http://example.com/")
browser.addheaders = [("Host", "myway.example.com")]
browser.open(request)
self.assertIn(("Host", "myway.example.com"), headers)
def test_pickle_cookie(self):
from mechanize._clientcookie import cookies_equal
cookiejar = mechanize.CookieJar()
url = "http://example.com/"
request = mechanize.Request(url)
response = mechanize._response.test_response(
headers=[("Set-Cookie", "spam=eggs")], url=url)
[cookie] = cookiejar.make_cookies(response, request)
def check_equality(b):
self.assertTrue(cookies_equal(cookie, b))
test_pickling(cookie, check_equality)
def test_request_headers_dict():
"""
The Request.headers dictionary is not a documented interface. It should
stay that way, because the complete set of headers are only accessible
through the .get_header(), .has_header(), .header_items() interface.
However, .headers pre-dates those methods, and so real code will be using
the dictionary.
The introduction in 2.4 of those methods was a mistake for the same reason:
code that previously saw all (urllib2 user)-provided headers in .headers
now sees only a subset (and the function interface is ugly and incomplete).
A better change would have been to replace .headers dict with a dict
subclass (or UserDict.DictMixin instance?) that preserved the .headers
interface and also provided access to the "unredirected" headers. It's
probably too late to fix that, though.
Check .capitalize() case normalization:
>>> url = "http://example.com"
>>> Request(url, headers={"Spam-eggs": "blah"}).headers["Spam-eggs"]
'blah'
>>> Request(url, headers={"spam-EggS": "blah"}).headers["Spam-eggs"]
'blah'
Currently, Request(url, "Spam-eggs").headers["Spam-Eggs"] raises KeyError,
but that could be changed in future.
"""
def test_request_headers_methods():
"""
Note the case normalization of header names here, to .capitalize()-case.
This should be preserved for backwards-compatibility. (In the HTTP case,
normalization to .title()-case is done by urllib2 before sending headers to
httplib).
>>> url = "http://example.com"
>>> r = Request(url, headers={"Spam-eggs": "blah"})
>>> r.has_header("Spam-eggs")
True
>>> r.header_items()
[('Spam-eggs', 'blah')]
>>> r.add_header("Foo-Bar", "baz")
>>> items = r.header_items()
>>> items.sort()
>>> items
[('Foo-bar', 'baz'), ('Spam-eggs', 'blah')]
Note that e.g. r.has_header("spam-EggS") is currently False, and
r.get_header("spam-EggS") returns None, but that could be changed in
future.
>>> r.has_header("Not-there")
False
>>> print r.get_header("Not-there")
None
>>> r.get_header("Not-there", "default")
'default'
"""
def add_ordered_mock_handlers(opener, meth_spec):
"""Create MockHandlers and add them to an OpenerDirector.
meth_spec: list of lists of tuples and strings defining methods to define
on handlers. eg:
[["http_error", "ftp_open"], ["http_open"]]
defines methods .http_error() and .ftp_open() on one handler, and
.http_open() on another. These methods just record their arguments and
return None. Using a tuple instead of a string causes the method to
perform some action (see MockHandler.handle()), eg:
[["http_error"], [("http_open", "return request")]]
defines .http_error() on one handler (which simply returns None), and
.http_open() on another handler, which returns a Request object.
"""
handlers = []
count = 0
for meths in meth_spec:
class MockHandlerSubclass(MockHandler):
pass
h = MockHandlerSubclass(meths)
h.handler_order += count
h.add_parent(opener)
count = count + 1
handlers.append(h)
opener.add_handler(h)
return handlers
def test_processors(self):
# *_request / *_response methods get called appropriately
o = OpenerDirector()
meth_spec = [
[("http_request", "return request"),
("http_response", "return response")],
[("http_request", "return request"),
("http_response", "return response")],
]
handlers = add_ordered_mock_handlers(o, meth_spec)
req = Request("http://example.com/")
r = o.open(req)
# processor methods are called on *all* handlers that define them,
# not just the first handler that handles the request
calls = [(handlers[0], "http_request"), (handlers[1], "http_request"),
(handlers[0], "http_response"),
(handlers[1], "http_response")]
self.assertEqual(len(o.calls), len(calls))
for i, (handler, name, args, kwds) in enumerate(o.calls):
if i < 2:
# *_request
self.assertEqual((handler, name), calls[i])
self.assertEqual(len(args), 1)
self.assertTrue(isinstance(args[0], Request))
else:
# *_response
self.assertEqual((handler, name), calls[i])
self.assertEqual(len(args), 2)
self.assertTrue(isinstance(args[0], Request))
# response from opener.open is None, because there's no
# handler that defines http_open to handle it
self.assertTrue(args[1] is None or
isinstance(args[1], MockResponse))
def test_raise_http_errors(self):
# HTTPDefaultErrorHandler should raise HTTPError if no error handler
# handled the error response
from mechanize import _response
h = mechanize.HTTPDefaultErrorHandler()
url = "http://example.com"
code = 500
msg = "Error"
request = mechanize.Request(url)
response = _response.test_response(url=url, code=code, msg=msg)
# case 1. it's not an HTTPError
try:
h.http_error_default(request, response, code, msg, response.info())
except mechanize.HTTPError as exc:
self.assert_(exc is not response)
self.assert_(exc.fp is response)
else:
self.assert_(False)
# case 2. response object is already an HTTPError, so just re-raise it
error = mechanize.HTTPError(url, code, msg, "fake headers", response)
try:
h.http_error_default(request, error, code, msg, error.info())
except mechanize.HTTPError as exc:
self.assert_(exc is error)
else:
self.assert_(False)
def test_cookies(self):
cj = MockCookieJar()
h = HTTPCookieProcessor(cj)
o = h.parent = MockOpener()
req = Request("http://example.com/")
r = MockResponse(200, "OK", {}, "")
newreq = h.http_request(req)
self.assertTrue(cj.ach_req is req is newreq)
self.assertEquals(req.get_origin_req_host(), "example.com")
self.assertFalse(cj.ach_u)
newr = h.http_response(req, r)
self.assertTrue(cj.ec_req is req)
self.assertTrue(cj.ec_r is r is newr)
self.assertFalse(cj.ec_u)
def test_proxy_no_proxy(self):
self.monkey_patch_environ("no_proxy", "python.org")
o = OpenerDirector()
ph = mechanize.ProxyHandler(dict(http="proxy.example.com"))
o.add_handler(ph)
req = Request("http://www.perl.org/")
self.assertEqual(req.get_host(), "www.perl.org")
r = o.open(req)
self.assertEqual(req.get_host(), "proxy.example.com")
req = Request("http://www.python.org")
self.assertEqual(req.get_host(), "www.python.org")
r = o.open(req)
if sys.version_info >= (2, 6):
# no_proxy environment variable not supported in python 2.5
self.assertEqual(req.get_host(), "www.python.org")
def test_proxy_https(self):
o = OpenerDirector()
ph = mechanize.ProxyHandler(dict(https='proxy.example.com:3128'))
o.add_handler(ph)
meth_spec = [[("https_open", "return response")]]
handlers = add_ordered_mock_handlers(o, meth_spec)
req = Request("https://www.example.com/")
self.assertEqual(req.get_host(), "www.example.com")
r = o.open(req)
self.assertEqual(req.get_host(), "proxy.example.com:3128")
self.assertEqual([(handlers[0], "https_open")],
[tup[0:2] for tup in o.calls])
def setUp(self):
self.get = Request("http://www.python.org/~jeremy/")
self.post = Request(
"http://www.python.org/~jeremy/",
"data",
headers={"X-Test": "test"})
def test_selector(self):
self.assertEqual("/~jeremy/", self.get.get_selector())
req = Request("http://www.python.org/")
self.assertEqual("/", req.get_selector())
def test_get_host_unquote(self):
req = Request("http://www.%70ython.org/")
self.assertEqual("www.python.org", req.get_host())
def get(self,url,headers={}):
"Mechanize Get request"
response = self.browser.open(mechanize.Request(url,headers=headers))
return response
def post(self,url,data=None,headers={}):
"Mechanize Post request"
response = self.browser.open(mechanize.Request(url=url, data= data, headers=headers))
return response
def add_cookie_header(self, request):
"""Add correct Cookie: header to request (mechanize.Request object).
The Cookie2 header is also added unless policy.hide_cookie2 is true.
The request object (usually a mechanize.Request instance) must support
the methods get_full_url, get_host, is_unverifiable, get_type,
has_header, get_header, header_items and add_unredirected_header, as
documented by urllib2.
"""
debug("add_cookie_header")
cookies = self.cookies_for_request(request)
attrs = self._cookie_attrs(cookies)
if attrs:
if not request.has_header("Cookie"):
request.add_unredirected_header("Cookie", "; ".join(attrs))
# if necessary, advertise that we know RFC 2965
if self._policy.rfc2965 and not self._policy.hide_cookie2:
for cookie in cookies:
if cookie.version != 1 and not request.has_header("Cookie2"):
request.add_unredirected_header("Cookie2", '$Version="1"')
break
self.clear_expired_cookies()