Skip to content

Instantly share code, notes, and snippets.

@amotl
Forked from 1kastner/reflect.py
Last active March 26, 2024 08:04
Show Gist options
  • Save amotl/3ed38e461af743aeeade5a5a106c1296 to your computer and use it in GitHub Desktop.
Save amotl/3ed38e461af743aeeade5a5a106c1296 to your computer and use it in GitHub Desktop.
A simple HTTP server reflecting HTTP requests for inspection
#!/usr/bin/env python3
"""
httpd-reflector
A simple HTTP server reflecting HTTP requests for inspection.
It will print the contents of incoming HTTP requests to STDOUT
making it suitable for development and debugging purposes.
- Written by Nathan Hamiel (2010)
https://gist.github.com/huyng/814831
- Updated by 1kastner (2018)
https://gist.github.com/1kastner/e083f9e813c0464e6a2ec8910553e632
- Python3 compatibility
- Updated by Andreas Motl (2018)
https://gist.github.com/amotl/3ed38e461af743aeeade5a5a106c1296/edit
- Output improvements
- Add PATCH method
- Obtain listen address and port from command line
"""
from optparse import OptionParser
from http.server import HTTPServer, BaseHTTPRequestHandler
class RequestHandler(BaseHTTPRequestHandler):
def simple_request(self):
print("----- Request Start ----->")
self.print_detail('Method', self.command)
self.print_detail('Path', self.path)
print()
print("Headers:")
self.print_headers()
print("<----- Request End -----\n")
self.send_response(200)
self.end_headers()
def body_request(self):
content_length = int(self.headers.get('Content-Length', 0))
print("----- Request Start ----->")
self.print_detail('Method', self.command)
self.print_detail('Path', self.path)
print()
print("Headers:")
self.print_headers()
print()
print("Payload:")
print(self.rfile.read(content_length))
print("<----- Request End -----\n")
self.send_response(200)
self.end_headers()
@property
def column_width(self):
max_key_length = max([len(key) for key, value in self.headers.items()])
width = max_key_length + 2
return width
def print_headers(self):
for key in sorted(self.headers):
value = self.headers[key]
self.print_detail(key, value)
def print_detail(self, label, value):
label += ': '
entry = '{}{}'.format(label.ljust(self.column_width), value)
print(entry)
do_GET = simple_request
do_DELETE = simple_request
do_POST = body_request
do_PUT = body_request
do_PATCH = body_request
def run_server(address, port):
server_address = (address, int(port))
print('Listening on {}'.format(server_address))
server = HTTPServer(server_address, RequestHandler)
server.serve_forever()
if __name__ == "__main__":
parser = OptionParser()
parser.usage = """
Creates a HTTP server for debugging purposes"
Synopsis::
http-reflector.py --port=9876"""
parser.add_option("-a", "--address", dest="listen_address",
default='127.0.0.1', help="HTTP listen address")
parser.add_option("-p", "--port", dest="listen_port",
default=8080, help="HTTP listen port")
(options, args) = parser.parse_args()
run_server(options.listen_address, options.listen_port)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment