Skip to content

Commit 566e4e7

Browse files
authored
Use HTTP/1.1 in linkcheck test webservers (#11392)
1 parent bef7fc2 commit 566e4e7

File tree

2 files changed

+53
-8
lines changed

2 files changed

+53
-8
lines changed

tests/test_build_linkcheck.py

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,40 @@
2828

2929

3030
class DefaultsHandler(http.server.BaseHTTPRequestHandler):
31+
protocol_version = "HTTP/1.1"
32+
3133
def do_HEAD(self):
3234
if self.path[1:].rstrip() == "":
3335
self.send_response(200, "OK")
36+
self.send_header("Content-Length", "0")
3437
self.end_headers()
3538
elif self.path[1:].rstrip() == "anchor.html":
3639
self.send_response(200, "OK")
40+
self.send_header("Content-Length", "0")
3741
self.end_headers()
3842
else:
3943
self.send_response(404, "Not Found")
44+
self.send_header("Content-Length", "0")
4045
self.end_headers()
4146

4247
def do_GET(self):
43-
self.do_HEAD()
4448
if self.path[1:].rstrip() == "":
45-
self.wfile.write(b"ok\n\n")
49+
content = b"ok\n\n"
4650
elif self.path[1:].rstrip() == "anchor.html":
4751
doc = '<!DOCTYPE html><html><body><a id="found"></a></body></html>'
48-
self.wfile.write(doc.encode('utf-8'))
52+
content = doc.encode("utf-8")
53+
else:
54+
content = b""
55+
56+
if content:
57+
self.send_response(200, "OK")
58+
self.send_header("Content-Length", str(len(content)))
59+
self.end_headers()
60+
self.wfile.write(content)
61+
else:
62+
self.send_response(404, "Not Found")
63+
self.send_header("Content-Length", "0")
64+
self.end_headers()
4965

5066

5167
@pytest.mark.sphinx('linkcheck', testroot='linkcheck', freshenv=True)
@@ -182,6 +198,8 @@ def test_anchors_ignored(app):
182198
@pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver-anchor', freshenv=True)
183199
def test_raises_for_invalid_status(app):
184200
class InternalServerErrorHandler(http.server.BaseHTTPRequestHandler):
201+
protocol_version = "HTTP/1.1"
202+
185203
def do_GET(self):
186204
self.send_error(500, "Internal Server Error")
187205

@@ -208,6 +226,8 @@ def custom_handler(valid_credentials=(), success_criteria=lambda _: True):
208226
del valid_credentials
209227

210228
class CustomHandler(http.server.BaseHTTPRequestHandler):
229+
protocol_version = "HTTP/1.1"
230+
211231
def authenticated(method):
212232
def method_if_authenticated(self):
213233
if expected_token is None:
@@ -216,6 +236,7 @@ def method_if_authenticated(self):
216236
return method(self)
217237
else:
218238
self.send_response(403, "Forbidden")
239+
self.send_header("Content-Length", "0")
219240
self.end_headers()
220241

221242
return method_if_authenticated
@@ -228,8 +249,10 @@ def do_HEAD(self):
228249
def do_GET(self):
229250
if success_criteria(self):
230251
self.send_response(200, "OK")
252+
self.send_header("Content-Length", "0")
231253
else:
232254
self.send_response(400, "Bad Request")
255+
self.send_header("Content-Length", "0")
233256
self.end_headers()
234257

235258
return CustomHandler
@@ -343,11 +366,14 @@ def check_headers(self):
343366

344367
def make_redirect_handler(*, support_head):
345368
class RedirectOnceHandler(http.server.BaseHTTPRequestHandler):
369+
protocol_version = "HTTP/1.1"
370+
346371
def do_HEAD(self):
347372
if support_head:
348373
self.do_GET()
349374
else:
350375
self.send_response(405, "Method Not Allowed")
376+
self.send_header("Content-Length", "0")
351377
self.end_headers()
352378

353379
def do_GET(self):
@@ -356,6 +382,7 @@ def do_GET(self):
356382
else:
357383
self.send_response(302, "Found")
358384
self.send_header("Location", "http://localhost:7777/?redirected=1")
385+
self.send_header("Content-Length", "0")
359386
self.end_headers()
360387

361388
def log_date_time_string(self):
@@ -433,13 +460,19 @@ def test_linkcheck_allowed_redirects(app, warning):
433460

434461

435462
class OKHandler(http.server.BaseHTTPRequestHandler):
463+
protocol_version = "HTTP/1.1"
464+
436465
def do_HEAD(self):
437466
self.send_response(200, "OK")
467+
self.send_header("Content-Length", "0")
438468
self.end_headers()
439469

440470
def do_GET(self):
441-
self.do_HEAD()
442-
self.wfile.write(b"ok\n")
471+
content = b"ok\n"
472+
self.send_response(200, "OK")
473+
self.send_header("Content-Length", str(len(content)))
474+
self.end_headers()
475+
self.wfile.write(content)
443476

444477

445478
@pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver-https', freshenv=True)
@@ -546,15 +579,21 @@ def test_connect_to_selfsigned_nonexistent_cert_file(app):
546579

547580

548581
class InfiniteRedirectOnHeadHandler(http.server.BaseHTTPRequestHandler):
582+
protocol_version = "HTTP/1.1"
583+
549584
def do_HEAD(self):
550585
self.send_response(302, "Found")
551586
self.send_header("Location", "http://localhost:7777/")
587+
self.send_header("Content-Length", "0")
552588
self.end_headers()
553589

554590
def do_GET(self):
591+
content = b"ok\n"
555592
self.send_response(200, "OK")
593+
self.send_header("Content-Length", str(len(content)))
556594
self.end_headers()
557-
self.wfile.write(b"ok\n")
595+
self.wfile.write(content)
596+
self.close_connection = True # we don't expect the client to read this response body
558597

559598

560599
@pytest.mark.sphinx('linkcheck', testroot='linkcheck-localserver', freshenv=True)
@@ -580,11 +619,14 @@ def test_TooManyRedirects_on_HEAD(app, monkeypatch):
580619

581620
def make_retry_after_handler(responses):
582621
class RetryAfterHandler(http.server.BaseHTTPRequestHandler):
622+
protocol_version = "HTTP/1.1"
623+
583624
def do_HEAD(self):
584625
status, retry_after = responses.pop(0)
585626
self.send_response(status)
586627
if retry_after:
587628
self.send_header('Retry-After', retry_after)
629+
self.send_header("Content-Length", "0")
588630
self.end_headers()
589631

590632
def log_date_time_string(self):
@@ -731,11 +773,14 @@ def test_limit_rate_bails_out_after_waiting_max_time(app):
731773

732774

733775
class ConnectionResetHandler(http.server.BaseHTTPRequestHandler):
776+
protocol_version = "HTTP/1.1"
777+
734778
def do_HEAD(self):
735-
self.connection.close()
779+
self.close_connection = True
736780

737781
def do_GET(self):
738782
self.send_response(200, "OK")
783+
self.send_header("Content-Length", "0")
739784
self.end_headers()
740785

741786

tests/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
class HttpServerThread(threading.Thread):
2020
def __init__(self, handler, *args, **kwargs):
2121
super().__init__(*args, **kwargs)
22-
self.server = http.server.HTTPServer(("localhost", 7777), handler)
22+
self.server = http.server.ThreadingHTTPServer(("localhost", 7777), handler)
2323

2424
def run(self):
2525
self.server.serve_forever(poll_interval=0.001)

0 commit comments

Comments
 (0)