Skip to content

Instantly share code, notes, and snippets.

@wfrisch
Created February 1, 2024 09:15
Show Gist options
  • Save wfrisch/63d1163645fa01e3ab1296e752769359 to your computer and use it in GitHub Desktop.
Save wfrisch/63d1163645fa01e3ab1296e752769359 to your computer and use it in GitHub Desktop.
Deliberately broken HTTP server that responds with either a) false Content-Length or b) broken chunked encoding
#!/usr/bin/env python3
"""
Deliberately broken HTTP server that responds with either
- false Content-Length
- broken chunked encoding
both triggering ChunkedEncodingError in clients using `python-requests`:
- ChunkedEncodingError: Connection broken: IncompleteRead
- ChunkedEncodingError: Connection broken: InvalidChunkLength
"""
from http.server import BaseHTTPRequestHandler, HTTPServer
class BrokenHandler(BaseHTTPRequestHandler):
def do_GET(self):
routes = {
"/invalid-chunk-length": self.respond_invalid_chunk_length,
"/invalid-content-length": self.respond_invalid_content_length
}
if self.path in routes:
routes[self.path]()
else:
self.send_error(404, "Path not found.")
def respond_invalid_content_length(self):
content = "Hello, World!"
content_length = len(content) + 10 # error
self.send_response(200)
self.send_header('Content-Type', 'text/plain')
self.send_header('Content-Length', str(content_length))
self.end_headers()
self.wfile.write(content.encode())
def respond_invalid_chunk_length(self):
content = "Hello, World!"
self.send_response(200)
self.send_header('Content-type', 'text/plain')
self.send_header('Transfer-Encoding', 'chunked')
self.end_headers()
self.wfile.write(f"{len(content):X}\r\n".encode())
self.wfile.write(f"{content}\r\n".encode())
# erroneously omit the terminator chunk
# self.wfile.write(b"0\r\n\r\n")
def run(server_class=HTTPServer, handler_class=BrokenHandler,
port=8080):
server_address = ('', port)
httpd = server_class(server_address, handler_class)
print(f"Starting faulty HTTP server on port {port}...")
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
httpd.server_close()
if __name__ == '__main__':
run()
# vim:set expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment