Skip to content

Instantly share code, notes, and snippets.

@cosmosgenius
Created September 20, 2020 10:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cosmosgenius/0329af7a4732777ba92e647a71efbbb4 to your computer and use it in GitHub Desktop.
Save cosmosgenius/0329af7a4732777ba92e647a71efbbb4 to your computer and use it in GitHub Desktop.
Python3 request dump http.server
#!/usr/bin/env python3
import os
import contextlib
import sys
import socket
from functools import partial
import logging
from http.server import (
BaseHTTPRequestHandler,
CGIHTTPRequestHandler,
SimpleHTTPRequestHandler,
ThreadingHTTPServer,
)
msg = """
Method: {method}
Path: {path}
----- Start Headers -----
{headers}
------ End Headers ------
------ Start Body -------
{body}
------ End Body ---------
"""
class DumpSimpleHTTPRequestHandler(SimpleHTTPRequestHandler):
def do_POST(self):
content_length = int(
self.headers["Content-Length"]
) # <--- Gets the size of data
post_data = self.rfile.read(content_length) # <--- Gets the data itself
logging.info(
msg.format(
method="POST",
path=str(self.path),
headers=str(self.headers),
body=post_data.decode("utf-8"),
)
)
return super().do_GET()
def do_GET(self):
logging.info(
msg.format(
method="GET",
path=str(self.path),
headers=str(self.headers),
body="",
)
)
return super().do_GET()
def _get_best_family(*address):
infos = socket.getaddrinfo(
*address,
type=socket.SOCK_STREAM,
flags=socket.AI_PASSIVE,
)
family, type, proto, canonname, sockaddr = next(iter(infos))
return family, sockaddr
def test(
HandlerClass=BaseHTTPRequestHandler,
ServerClass=ThreadingHTTPServer,
protocol="HTTP/1.0",
port=8000,
bind=None,
):
"""Test the HTTP request handler class.
This runs an HTTP server on port 8000 (or the port argument).
"""
ServerClass.address_family, addr = _get_best_family(bind, port)
HandlerClass.protocol_version = protocol
with ServerClass(addr, HandlerClass) as httpd:
host, port = httpd.socket.getsockname()[:2]
url_host = f"[{host}]" if ":" in host else host
print(f"Serving HTTP on {host} port {port} " f"(http://{url_host}:{port}/) ...")
try:
httpd.serve_forever()
except KeyboardInterrupt:
print("\nKeyboard interrupt received, exiting.")
sys.exit(0)
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--cgi", action="store_true", help="Run as CGI Server")
parser.add_argument(
"--bind",
"-b",
metavar="ADDRESS",
help="Specify alternate bind address " "[default: all interfaces]",
)
parser.add_argument(
"--directory",
"-d",
default=os.getcwd(),
help="Specify alternative directory " "[default:current directory]",
)
parser.add_argument(
"port",
action="store",
default=8000,
type=int,
nargs="?",
help="Specify alternate port [default: 8000]",
)
args = parser.parse_args()
if args.cgi:
handler_class = CGIHTTPRequestHandler
else:
handler_class = partial(DumpSimpleHTTPRequestHandler, directory=args.directory)
logging.basicConfig(level=logging.INFO)
# ensure dual-stack is not disabled; ref #38907
class DualStackServer(ThreadingHTTPServer):
def server_bind(self):
# suppress exception when protocol is IPv4
with contextlib.suppress(Exception):
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
return super().server_bind()
test(
HandlerClass=handler_class,
ServerClass=DualStackServer,
port=args.port,
bind=args.bind,
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment