Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 70e2847

Browse files
committed
document the requestline and close_connection attributes, use real booleans, and add tests (closes #23410)
Patch by Martin Panter.
1 parent e7a2f64 commit 70e2847

3 files changed

Lines changed: 61 additions & 10 deletions

File tree

Doc/library/http.server.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,18 @@ of which this module provides three different variants:
6464

6565
Contains the server instance.
6666

67+
.. attribute:: close_connection
68+
69+
Boolean that should be set before :meth:`handle_one_request` returns,
70+
indicating if another request may be expected, or if the connection should
71+
be shut down.
72+
73+
.. attribute:: requestline
74+
75+
Contains the string representation of the HTTP request line. The
76+
terminating CRLF is stripped. This attribute should be set by
77+
:meth:`handle_one_request`. If no valid request line was processed, it
78+
should be set to the empty string.
6779

6880
.. attribute:: command
6981

Lib/http/server.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ def parse_request(self):
273273
"""
274274
self.command = None # set in case of error on the first line
275275
self.request_version = version = self.default_request_version
276-
self.close_connection = 1
276+
self.close_connection = True
277277
requestline = str(self.raw_requestline, 'iso-8859-1')
278278
requestline = requestline.rstrip('\r\n')
279279
self.requestline = requestline
@@ -299,14 +299,14 @@ def parse_request(self):
299299
self.send_error(400, "Bad request version (%r)" % version)
300300
return False
301301
if version_number >= (1, 1) and self.protocol_version >= "HTTP/1.1":
302-
self.close_connection = 0
302+
self.close_connection = False
303303
if version_number >= (2, 0):
304304
self.send_error(505,
305305
"Invalid HTTP Version (%s)" % base_version_number)
306306
return False
307307
elif len(words) == 2:
308308
command, path = words
309-
self.close_connection = 1
309+
self.close_connection = True
310310
if command != 'GET':
311311
self.send_error(400,
312312
"Bad HTTP/0.9 request type (%r)" % command)
@@ -328,10 +328,10 @@ def parse_request(self):
328328

329329
conntype = self.headers.get('Connection', "")
330330
if conntype.lower() == 'close':
331-
self.close_connection = 1
331+
self.close_connection = True
332332
elif (conntype.lower() == 'keep-alive' and
333333
self.protocol_version >= "HTTP/1.1"):
334-
self.close_connection = 0
334+
self.close_connection = False
335335
# Examine the headers and look for an Expect directive
336336
expect = self.headers.get('Expect', "")
337337
if (expect.lower() == "100-continue" and
@@ -376,7 +376,7 @@ def handle_one_request(self):
376376
self.send_error(414)
377377
return
378378
if not self.raw_requestline:
379-
self.close_connection = 1
379+
self.close_connection = True
380380
return
381381
if not self.parse_request():
382382
# An error code has been sent, just exit
@@ -391,12 +391,12 @@ def handle_one_request(self):
391391
except socket.timeout as e:
392392
#a read or a write timed out. Discard this connection
393393
self.log_error("Request timed out: %r", e)
394-
self.close_connection = 1
394+
self.close_connection = True
395395
return
396396

397397
def handle(self):
398398
"""Handle multiple requests if necessary."""
399-
self.close_connection = 1
399+
self.close_connection = True
400400

401401
self.handle_one_request()
402402
while not self.close_connection:
@@ -478,9 +478,9 @@ def send_header(self, keyword, value):
478478

479479
if keyword.lower() == 'connection':
480480
if value.lower() == 'close':
481-
self.close_connection = 1
481+
self.close_connection = True
482482
elif value.lower() == 'keep-alive':
483-
self.close_connection = 0
483+
self.close_connection = False
484484

485485
def end_headers(self):
486486
"""Send the blank line ending the MIME headers."""

Lib/test/test_httpservers.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,13 +616,23 @@ def test_http_1_1(self):
616616
self.verify_expected_headers(result[1:-1])
617617
self.verify_get_called()
618618
self.assertEqual(result[-1], b'<html><body>Data</body></html>\r\n')
619+
self.assertEqual(self.handler.requestline, 'GET / HTTP/1.1')
620+
self.assertEqual(self.handler.command, 'GET')
621+
self.assertEqual(self.handler.path, '/')
622+
self.assertEqual(self.handler.request_version, 'HTTP/1.1')
623+
self.assertSequenceEqual(self.handler.headers.items(), ())
619624

620625
def test_http_1_0(self):
621626
result = self.send_typical_request(b'GET / HTTP/1.0\r\n\r\n')
622627
self.verify_http_server_response(result[0])
623628
self.verify_expected_headers(result[1:-1])
624629
self.verify_get_called()
625630
self.assertEqual(result[-1], b'<html><body>Data</body></html>\r\n')
631+
self.assertEqual(self.handler.requestline, 'GET / HTTP/1.0')
632+
self.assertEqual(self.handler.command, 'GET')
633+
self.assertEqual(self.handler.path, '/')
634+
self.assertEqual(self.handler.request_version, 'HTTP/1.0')
635+
self.assertSequenceEqual(self.handler.headers.items(), ())
626636

627637
def test_http_0_9(self):
628638
result = self.send_typical_request(b'GET / HTTP/0.9\r\n\r\n')
@@ -636,6 +646,12 @@ def test_with_continue_1_0(self):
636646
self.verify_expected_headers(result[1:-1])
637647
self.verify_get_called()
638648
self.assertEqual(result[-1], b'<html><body>Data</body></html>\r\n')
649+
self.assertEqual(self.handler.requestline, 'GET / HTTP/1.0')
650+
self.assertEqual(self.handler.command, 'GET')
651+
self.assertEqual(self.handler.path, '/')
652+
self.assertEqual(self.handler.request_version, 'HTTP/1.0')
653+
headers = (("Expect", "100-continue"),)
654+
self.assertSequenceEqual(self.handler.headers.items(), headers)
639655

640656
def test_with_continue_1_1(self):
641657
result = self.send_typical_request(b'GET / HTTP/1.1\r\nExpect: 100-continue\r\n\r\n')
@@ -645,6 +661,12 @@ def test_with_continue_1_1(self):
645661
self.verify_expected_headers(result[2:-1])
646662
self.verify_get_called()
647663
self.assertEqual(result[-1], b'<html><body>Data</body></html>\r\n')
664+
self.assertEqual(self.handler.requestline, 'GET / HTTP/1.1')
665+
self.assertEqual(self.handler.command, 'GET')
666+
self.assertEqual(self.handler.path, '/')
667+
self.assertEqual(self.handler.request_version, 'HTTP/1.1')
668+
headers = (("Expect", "100-continue"),)
669+
self.assertSequenceEqual(self.handler.headers.items(), headers)
648670

649671
def test_header_buffering_of_send_error(self):
650672

@@ -730,13 +752,30 @@ def test_request_length(self):
730752
result = self.send_typical_request(b'GET ' + b'x' * 65537)
731753
self.assertEqual(result[0], b'HTTP/1.1 414 Request-URI Too Long\r\n')
732754
self.assertFalse(self.handler.get_called)
755+
self.assertIsInstance(self.handler.requestline, str)
733756

734757
def test_header_length(self):
735758
# Issue #6791: same for headers
736759
result = self.send_typical_request(
737760
b'GET / HTTP/1.1\r\nX-Foo: bar' + b'r' * 65537 + b'\r\n\r\n')
738761
self.assertEqual(result[0], b'HTTP/1.1 400 Line too long\r\n')
739762
self.assertFalse(self.handler.get_called)
763+
self.assertEqual(self.handler.requestline, 'GET / HTTP/1.1')
764+
765+
def test_close_connection(self):
766+
# handle_one_request() should be repeatedly called until
767+
# it sets close_connection
768+
def handle_one_request():
769+
self.handler.close_connection = next(close_values)
770+
self.handler.handle_one_request = handle_one_request
771+
772+
close_values = iter((True,))
773+
self.handler.handle()
774+
self.assertRaises(StopIteration, next, close_values)
775+
776+
close_values = iter((False, False, True))
777+
self.handler.handle()
778+
self.assertRaises(StopIteration, next, close_values)
740779

741780
class SimpleHTTPRequestHandlerTestCase(unittest.TestCase):
742781
""" Test url parsing """

0 commit comments

Comments
 (0)