Skip to content

Instantly share code, notes, and snippets.

@mjumbewu
Created October 12, 2016 17:04
Show Gist options
  • Save mjumbewu/bd4fe0642464e22e2d047fb27cabdfc1 to your computer and use it in GitHub Desktop.
Save mjumbewu/bd4fe0642464e22e2d047fb27cabdfc1 to your computer and use it in GitHub Desktop.
An extension to Python3's http.server module that allows creation of HTTPS servers. Inspired by @dergachev's even simpler https://gist.github.com/dergachev/7028596.
"""
An extension to Python3's http.server module that allows creation of HTTPS
servers. Inspired by @dergachev's https://gist.github.com/dergachev/7028596.
You can either use a separate certificate and key file:
python3 https_server.py -c server.crt -k server.key
Or generate a PEM file and use it as the certificate:
openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes
python https_server.py -c server.pem
"""
import argparse
from http.server import (HTTPServer, test,
CGIHTTPRequestHandler, SimpleHTTPRequestHandler)
from ssl import wrap_socket
def HTTPSServer_class_factory(certfile, keyfile=None):
"""
Create an HTTPSServer class that wraps an HTTPServer socket in an SSL
context. See https://docs.python.org/3/library/ssl.html#socket-creation
for more information.
"""
class CertifiedHTTPSServer (HTTPSServer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.socket = wrap_socket(self.socket, certfile=certfile, keyfile=keyfile, server_side=True)
return CertifiedHTTPSServer
if __name__ == '__main__':
# NOTE: Most of the following parser arguments are copied from http.server.
# The exceptions are --certfile and --keyfile, which affect which server
# class is passed to the test server function
parser = argparse.ArgumentParser()
parser.add_argument('--cgi', action='store_true',
help='Run as CGI Server')
parser.add_argument('--bind', '-b', default='', metavar='ADDRESS',
help='Specify alternate bind address '
'[default: all interfaces]')
parser.add_argument('port', action='store',
default=8000, type=int,
nargs='?',
help='Specify alternate port [default: 8000]')
parser.add_argument('--certfile', '-c', action='store', default=None,
nargs='?', help='Specify an SSL certificate to serve '
'requests over HTTPS [default: None]')
parser.add_argument('--keyfile', '-k', action='store', default=None,
nargs='?', help='Specify an SSL certificate to serve '
'requests over HTTPS [default: None]')
args = parser.parse_args()
if args.cgi:
handler_class = CGIHTTPRequestHandler
else:
handler_class = SimpleHTTPRequestHandler
if args.certfile:
server_class = HTTPSServer_class_factory(args.certfile, args.keyfile)
else:
server_class = HTTPServer
test(HandlerClass=handler_class, ServerClass=server_class, port=args.port, bind=args.bind)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment