PageRenderTime 21ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/External.LCA_RESTRICTED/Languages/CPython/27/Lib/test/test_httplib.py

http://github.com/IronLanguages/main
Python | 447 lines | 438 code | 5 blank | 4 comment | 4 complexity | 19bf685e27b907c1ffe908958817154d MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. import httplib
  2. import array
  3. import httplib
  4. import StringIO
  5. import socket
  6. import errno
  7. import unittest
  8. TestCase = unittest.TestCase
  9. from test import test_support
  10. HOST = test_support.HOST
  11. class FakeSocket:
  12. def __init__(self, text, fileclass=StringIO.StringIO):
  13. self.text = text
  14. self.fileclass = fileclass
  15. self.data = ''
  16. def sendall(self, data):
  17. self.data += ''.join(data)
  18. def makefile(self, mode, bufsize=None):
  19. if mode != 'r' and mode != 'rb':
  20. raise httplib.UnimplementedFileMode()
  21. return self.fileclass(self.text)
  22. class EPipeSocket(FakeSocket):
  23. def __init__(self, text, pipe_trigger):
  24. # When sendall() is called with pipe_trigger, raise EPIPE.
  25. FakeSocket.__init__(self, text)
  26. self.pipe_trigger = pipe_trigger
  27. def sendall(self, data):
  28. if self.pipe_trigger in data:
  29. raise socket.error(errno.EPIPE, "gotcha")
  30. self.data += data
  31. def close(self):
  32. pass
  33. class NoEOFStringIO(StringIO.StringIO):
  34. """Like StringIO, but raises AssertionError on EOF.
  35. This is used below to test that httplib doesn't try to read
  36. more from the underlying file than it should.
  37. """
  38. def read(self, n=-1):
  39. data = StringIO.StringIO.read(self, n)
  40. if data == '':
  41. raise AssertionError('caller tried to read past EOF')
  42. return data
  43. def readline(self, length=None):
  44. data = StringIO.StringIO.readline(self, length)
  45. if data == '':
  46. raise AssertionError('caller tried to read past EOF')
  47. return data
  48. class HeaderTests(TestCase):
  49. def test_auto_headers(self):
  50. # Some headers are added automatically, but should not be added by
  51. # .request() if they are explicitly set.
  52. class HeaderCountingBuffer(list):
  53. def __init__(self):
  54. self.count = {}
  55. def append(self, item):
  56. kv = item.split(':')
  57. if len(kv) > 1:
  58. # item is a 'Key: Value' header string
  59. lcKey = kv[0].lower()
  60. self.count.setdefault(lcKey, 0)
  61. self.count[lcKey] += 1
  62. list.append(self, item)
  63. for explicit_header in True, False:
  64. for header in 'Content-length', 'Host', 'Accept-encoding':
  65. conn = httplib.HTTPConnection('example.com')
  66. conn.sock = FakeSocket('blahblahblah')
  67. conn._buffer = HeaderCountingBuffer()
  68. body = 'spamspamspam'
  69. headers = {}
  70. if explicit_header:
  71. headers[header] = str(len(body))
  72. conn.request('POST', '/', body, headers)
  73. self.assertEqual(conn._buffer.count[header.lower()], 1)
  74. def test_putheader(self):
  75. conn = httplib.HTTPConnection('example.com')
  76. conn.sock = FakeSocket(None)
  77. conn.putrequest('GET','/')
  78. conn.putheader('Content-length',42)
  79. self.assertTrue('Content-length: 42' in conn._buffer)
  80. def test_ipv6host_header(self):
  81. # Default host header on IPv6 transaction should wrapped by [] if
  82. # its actual IPv6 address
  83. expected = 'GET /foo HTTP/1.1\r\nHost: [2001::]:81\r\n' \
  84. 'Accept-Encoding: identity\r\n\r\n'
  85. conn = httplib.HTTPConnection('[2001::]:81')
  86. sock = FakeSocket('')
  87. conn.sock = sock
  88. conn.request('GET', '/foo')
  89. self.assertTrue(sock.data.startswith(expected))
  90. expected = 'GET /foo HTTP/1.1\r\nHost: [2001:102A::]\r\n' \
  91. 'Accept-Encoding: identity\r\n\r\n'
  92. conn = httplib.HTTPConnection('[2001:102A::]')
  93. sock = FakeSocket('')
  94. conn.sock = sock
  95. conn.request('GET', '/foo')
  96. self.assertTrue(sock.data.startswith(expected))
  97. class BasicTest(TestCase):
  98. def test_status_lines(self):
  99. # Test HTTP status lines
  100. body = "HTTP/1.1 200 Ok\r\n\r\nText"
  101. sock = FakeSocket(body)
  102. resp = httplib.HTTPResponse(sock)
  103. resp.begin()
  104. self.assertEqual(resp.read(), 'Text')
  105. self.assertTrue(resp.isclosed())
  106. body = "HTTP/1.1 400.100 Not Ok\r\n\r\nText"
  107. sock = FakeSocket(body)
  108. resp = httplib.HTTPResponse(sock)
  109. self.assertRaises(httplib.BadStatusLine, resp.begin)
  110. def test_bad_status_repr(self):
  111. exc = httplib.BadStatusLine('')
  112. self.assertEqual(repr(exc), '''BadStatusLine("\'\'",)''')
  113. def test_partial_reads(self):
  114. # if we have a lenght, the system knows when to close itself
  115. # same behaviour than when we read the whole thing with read()
  116. body = "HTTP/1.1 200 Ok\r\nContent-Length: 4\r\n\r\nText"
  117. sock = FakeSocket(body)
  118. resp = httplib.HTTPResponse(sock)
  119. resp.begin()
  120. self.assertEqual(resp.read(2), 'Te')
  121. self.assertFalse(resp.isclosed())
  122. self.assertEqual(resp.read(2), 'xt')
  123. self.assertTrue(resp.isclosed())
  124. def test_host_port(self):
  125. # Check invalid host_port
  126. for hp in ("www.python.org:abc", "www.python.org:"):
  127. self.assertRaises(httplib.InvalidURL, httplib.HTTP, hp)
  128. for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b",
  129. 8000),
  130. ("www.python.org:80", "www.python.org", 80),
  131. ("www.python.org", "www.python.org", 80),
  132. ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)):
  133. http = httplib.HTTP(hp)
  134. c = http._conn
  135. if h != c.host:
  136. self.fail("Host incorrectly parsed: %s != %s" % (h, c.host))
  137. if p != c.port:
  138. self.fail("Port incorrectly parsed: %s != %s" % (p, c.host))
  139. def test_response_headers(self):
  140. # test response with multiple message headers with the same field name.
  141. text = ('HTTP/1.1 200 OK\r\n'
  142. 'Set-Cookie: Customer="WILE_E_COYOTE";'
  143. ' Version="1"; Path="/acme"\r\n'
  144. 'Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";'
  145. ' Path="/acme"\r\n'
  146. '\r\n'
  147. 'No body\r\n')
  148. hdr = ('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"'
  149. ', '
  150. 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"')
  151. s = FakeSocket(text)
  152. r = httplib.HTTPResponse(s)
  153. r.begin()
  154. cookies = r.getheader("Set-Cookie")
  155. if cookies != hdr:
  156. self.fail("multiple headers not combined properly")
  157. def test_read_head(self):
  158. # Test that the library doesn't attempt to read any data
  159. # from a HEAD request. (Tickles SF bug #622042.)
  160. sock = FakeSocket(
  161. 'HTTP/1.1 200 OK\r\n'
  162. 'Content-Length: 14432\r\n'
  163. '\r\n',
  164. NoEOFStringIO)
  165. resp = httplib.HTTPResponse(sock, method="HEAD")
  166. resp.begin()
  167. if resp.read() != "":
  168. self.fail("Did not expect response from HEAD request")
  169. def test_send_file(self):
  170. expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \
  171. 'Accept-Encoding: identity\r\nContent-Length:'
  172. body = open(__file__, 'rb')
  173. conn = httplib.HTTPConnection('example.com')
  174. sock = FakeSocket(body)
  175. conn.sock = sock
  176. conn.request('GET', '/foo', body)
  177. self.assertTrue(sock.data.startswith(expected))
  178. def test_send(self):
  179. expected = 'this is a test this is only a test'
  180. conn = httplib.HTTPConnection('example.com')
  181. sock = FakeSocket(None)
  182. conn.sock = sock
  183. conn.send(expected)
  184. self.assertEqual(expected, sock.data)
  185. sock.data = ''
  186. conn.send(array.array('c', expected))
  187. self.assertEqual(expected, sock.data)
  188. sock.data = ''
  189. conn.send(StringIO.StringIO(expected))
  190. self.assertEqual(expected, sock.data)
  191. def test_chunked(self):
  192. chunked_start = (
  193. 'HTTP/1.1 200 OK\r\n'
  194. 'Transfer-Encoding: chunked\r\n\r\n'
  195. 'a\r\n'
  196. 'hello worl\r\n'
  197. '1\r\n'
  198. 'd\r\n'
  199. )
  200. sock = FakeSocket(chunked_start + '0\r\n')
  201. resp = httplib.HTTPResponse(sock, method="GET")
  202. resp.begin()
  203. self.assertEqual(resp.read(), 'hello world')
  204. resp.close()
  205. for x in ('', 'foo\r\n'):
  206. sock = FakeSocket(chunked_start + x)
  207. resp = httplib.HTTPResponse(sock, method="GET")
  208. resp.begin()
  209. try:
  210. resp.read()
  211. except httplib.IncompleteRead, i:
  212. self.assertEqual(i.partial, 'hello world')
  213. self.assertEqual(repr(i),'IncompleteRead(11 bytes read)')
  214. self.assertEqual(str(i),'IncompleteRead(11 bytes read)')
  215. else:
  216. self.fail('IncompleteRead expected')
  217. finally:
  218. resp.close()
  219. def test_chunked_head(self):
  220. chunked_start = (
  221. 'HTTP/1.1 200 OK\r\n'
  222. 'Transfer-Encoding: chunked\r\n\r\n'
  223. 'a\r\n'
  224. 'hello world\r\n'
  225. '1\r\n'
  226. 'd\r\n'
  227. )
  228. sock = FakeSocket(chunked_start + '0\r\n')
  229. resp = httplib.HTTPResponse(sock, method="HEAD")
  230. resp.begin()
  231. self.assertEqual(resp.read(), '')
  232. self.assertEqual(resp.status, 200)
  233. self.assertEqual(resp.reason, 'OK')
  234. self.assertTrue(resp.isclosed())
  235. def test_negative_content_length(self):
  236. sock = FakeSocket('HTTP/1.1 200 OK\r\n'
  237. 'Content-Length: -1\r\n\r\nHello\r\n')
  238. resp = httplib.HTTPResponse(sock, method="GET")
  239. resp.begin()
  240. self.assertEqual(resp.read(), 'Hello\r\n')
  241. resp.close()
  242. def test_incomplete_read(self):
  243. sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\n')
  244. resp = httplib.HTTPResponse(sock, method="GET")
  245. resp.begin()
  246. try:
  247. resp.read()
  248. except httplib.IncompleteRead as i:
  249. self.assertEqual(i.partial, 'Hello\r\n')
  250. self.assertEqual(repr(i),
  251. "IncompleteRead(7 bytes read, 3 more expected)")
  252. self.assertEqual(str(i),
  253. "IncompleteRead(7 bytes read, 3 more expected)")
  254. else:
  255. self.fail('IncompleteRead expected')
  256. finally:
  257. resp.close()
  258. def test_epipe(self):
  259. sock = EPipeSocket(
  260. "HTTP/1.0 401 Authorization Required\r\n"
  261. "Content-type: text/html\r\n"
  262. "WWW-Authenticate: Basic realm=\"example\"\r\n",
  263. b"Content-Length")
  264. conn = httplib.HTTPConnection("example.com")
  265. conn.sock = sock
  266. self.assertRaises(socket.error,
  267. lambda: conn.request("PUT", "/url", "body"))
  268. resp = conn.getresponse()
  269. self.assertEqual(401, resp.status)
  270. self.assertEqual("Basic realm=\"example\"",
  271. resp.getheader("www-authenticate"))
  272. def test_filenoattr(self):
  273. # Just test the fileno attribute in the HTTPResponse Object.
  274. body = "HTTP/1.1 200 Ok\r\n\r\nText"
  275. sock = FakeSocket(body)
  276. resp = httplib.HTTPResponse(sock)
  277. self.assertTrue(hasattr(resp,'fileno'),
  278. 'HTTPResponse should expose a fileno attribute')
  279. # Test lines overflowing the max line size (_MAXLINE in http.client)
  280. def test_overflowing_status_line(self):
  281. self.skipTest("disabled for HTTP 0.9 support")
  282. body = "HTTP/1.1 200 Ok" + "k" * 65536 + "\r\n"
  283. resp = httplib.HTTPResponse(FakeSocket(body))
  284. self.assertRaises((httplib.LineTooLong, httplib.BadStatusLine), resp.begin)
  285. def test_overflowing_header_line(self):
  286. body = (
  287. 'HTTP/1.1 200 OK\r\n'
  288. 'X-Foo: bar' + 'r' * 65536 + '\r\n\r\n'
  289. )
  290. resp = httplib.HTTPResponse(FakeSocket(body))
  291. self.assertRaises(httplib.LineTooLong, resp.begin)
  292. def test_overflowing_chunked_line(self):
  293. body = (
  294. 'HTTP/1.1 200 OK\r\n'
  295. 'Transfer-Encoding: chunked\r\n\r\n'
  296. + '0' * 65536 + 'a\r\n'
  297. 'hello world\r\n'
  298. '0\r\n'
  299. )
  300. resp = httplib.HTTPResponse(FakeSocket(body))
  301. resp.begin()
  302. self.assertRaises(httplib.LineTooLong, resp.read)
  303. class OfflineTest(TestCase):
  304. def test_responses(self):
  305. self.assertEqual(httplib.responses[httplib.NOT_FOUND], "Not Found")
  306. class SourceAddressTest(TestCase):
  307. def setUp(self):
  308. self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  309. self.port = test_support.bind_port(self.serv)
  310. self.source_port = test_support.find_unused_port()
  311. self.serv.listen(5)
  312. self.conn = None
  313. def tearDown(self):
  314. if self.conn:
  315. self.conn.close()
  316. self.conn = None
  317. self.serv.close()
  318. self.serv = None
  319. def testHTTPConnectionSourceAddress(self):
  320. self.conn = httplib.HTTPConnection(HOST, self.port,
  321. source_address=('', self.source_port))
  322. self.conn.connect()
  323. self.assertEqual(self.conn.sock.getsockname()[1], self.source_port)
  324. @unittest.skipIf(not hasattr(httplib, 'HTTPSConnection'),
  325. 'httplib.HTTPSConnection not defined')
  326. def testHTTPSConnectionSourceAddress(self):
  327. self.conn = httplib.HTTPSConnection(HOST, self.port,
  328. source_address=('', self.source_port))
  329. # We don't test anything here other the constructor not barfing as
  330. # this code doesn't deal with setting up an active running SSL server
  331. # for an ssl_wrapped connect() to actually return from.
  332. class TimeoutTest(TestCase):
  333. PORT = None
  334. def setUp(self):
  335. self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  336. TimeoutTest.PORT = test_support.bind_port(self.serv)
  337. self.serv.listen(5)
  338. def tearDown(self):
  339. self.serv.close()
  340. self.serv = None
  341. def testTimeoutAttribute(self):
  342. '''This will prove that the timeout gets through
  343. HTTPConnection and into the socket.
  344. '''
  345. # default -- use global socket timeout
  346. self.assertTrue(socket.getdefaulttimeout() is None)
  347. socket.setdefaulttimeout(30)
  348. try:
  349. httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT)
  350. httpConn.connect()
  351. finally:
  352. socket.setdefaulttimeout(None)
  353. self.assertEqual(httpConn.sock.gettimeout(), 30)
  354. httpConn.close()
  355. # no timeout -- do not use global socket default
  356. self.assertTrue(socket.getdefaulttimeout() is None)
  357. socket.setdefaulttimeout(30)
  358. try:
  359. httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT,
  360. timeout=None)
  361. httpConn.connect()
  362. finally:
  363. socket.setdefaulttimeout(None)
  364. self.assertEqual(httpConn.sock.gettimeout(), None)
  365. httpConn.close()
  366. # a value
  367. httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, timeout=30)
  368. httpConn.connect()
  369. self.assertEqual(httpConn.sock.gettimeout(), 30)
  370. httpConn.close()
  371. class HTTPSTimeoutTest(TestCase):
  372. # XXX Here should be tests for HTTPS, there isn't any right now!
  373. def test_attributes(self):
  374. # simple test to check it's storing it
  375. if hasattr(httplib, 'HTTPSConnection'):
  376. h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30)
  377. self.assertEqual(h.timeout, 30)
  378. def test_main(verbose=None):
  379. test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest,
  380. HTTPSTimeoutTest, SourceAddressTest)
  381. if __name__ == '__main__':
  382. test_main()