123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- #!/usr/local/bin/python3.8
- """
- A Simple Python HTTP server that echos the request in the response.
- """
- import socket
- import argparse
- from six.moves.urllib import parse
- import email.message
- try:
- from email.generator import BytesGenerator
- except ImportError:
- # BBB Python 2 compatibility
- from email.generator import Generator as BytesGenerator
- from six.moves import BaseHTTPServer
- parser = argparse.ArgumentParser(
- description=__doc__, formatter_class=argparse.ArgumentDefaultsHelpFormatter
- )
- parser.add_argument(
- "--address",
- "-a",
- default="0.0.0.0",
- help="Hostname or IP address to accept requests on.",
- )
- parser.add_argument(
- "--port",
- "-p",
- help="Port to accept requests on. "
- "If not specified, use the first available port after 8000.",
- )
- class EchoHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
- """
- A Simple Python HTTP server that echos the request in the response.
- """
- def do_GET(self):
- """
- Echo a request without a body.
- """
- message = self.get_message()
- self.send_head()
- BytesGenerator(self.wfile).flatten(message, unixfrom=False)
- do_HEAD = do_GET
- do_OPTIONS = do_GET
- do_DELETE = do_GET
- def do_POST(self):
- """
- Echo a request with a body.
- """
- message = self.get_message()
- message.set_payload(self.rfile.read(int(self.headers["Content-Length"])))
- self.send_head()
- BytesGenerator(self.wfile).flatten(message, unixfrom=False)
- do_PUT = do_POST
- do_PATCH = do_POST
- def send_head(self):
- """
- Send all the basic, required headers.
- """
- self.send_response(200)
- self.send_header("Content-Type", "text/rfc822-headers; charset=UTF-8")
- self.send_header("Last-Modified", self.date_time_string())
- self.end_headers()
- def get_message(self):
- """
- Assemble the basic message including query parameters.
- """
- message = email.message.Message()
- message["Method"] = self.command
- message["Path"] = self.path
- server_url = parse.SplitResult(
- "http",
- "{0}:{1}".format(self.server.server_name, self.server.server_port),
- "",
- "",
- "",
- )
- request_url = parse.urlsplit(server_url.geturl() + self.path)
- for header, value in parse.parse_qs(request_url.query).items():
- message.add_header(header, value[0])
- return message
- def main(args=None, default_port=8000):
- """
- Run the echo HTTP server.
- """
- args = parser.parse_args(args)
- port = args.port
- if port is None:
- port = default_port
- bound = False
- while not bound:
- try:
- httpd = BaseHTTPServer.HTTPServer(
- (args.address, port), EchoHTTPRequestHandler
- )
- except socket.error:
- port += 1
- if port > 65535:
- raise ValueError("No available port found")
- else:
- bound = True
- else:
- httpd = BaseHTTPServer.HTTPServer(
- (args.address, int(port)), EchoHTTPRequestHandler
- )
- print("Echoing HTTP at http://{0}:{1} ...".format(args.address, port))
- httpd.serve_forever()
- if __name__ == "__main__":
- main()
|