Skip to content

Instantly share code, notes, and snippets.

@dusekdan
Last active December 28, 2023 12:46
Show Gist options
  • Save dusekdan/15244097799fe32a33a4380a4741ea76 to your computer and use it in GitHub Desktop.
Save dusekdan/15244097799fe32a33a4380a4741ea76 to your computer and use it in GitHub Desktop.
Simple HTTPS Server in Python for quick testing

Simple HTTPS Server in Python for quick testing

We got used to running python -m http.server command to quickly spin up a local http server that we could grab some files over. A lot of use cases these days require HTTPS to be used, however, so some of the quick and dirty testing operations now turn a bit more painful. This is a ready-made script that spins up a simple http server with SSL/TLS on, using the self-signed certificate.

If file cert.pem is not detected, script will try to create it during startup. It will contain both certificate and private key, and the private key is not passphrase protected. While it is acceptable for testing locally quickly, it is completely unreasonable and unacceptable for anything even remotely exposed to real life scenarios.

If you wan't to generate your own own cert.pem, or need to regenerate the new one (default expiration is set to 365 days), run the following command:

openssl req -newkey rsa:2048 -x509 -days 365 -nodes -out cert.pem -keyout cert.pem

To start the server

python serve.py

import os, ssl
from http.server import ThreadingHTTPServer, SimpleHTTPRequestHandler
def start_server(bind_to_name: str = "localhost",
bind_to_port: int = 4443,
cert_file: str = "cert.pem"
) -> None:
"""
Start a local HTTPS server with provided cert file.
The `cert.pem` file is expected to contain both certificate information
and private key.
To generate certificate, run the following command:
`openssl req -newkey rsa:2048 -x509 -days 365 -nodes -out cert.pem -keyout cert.pem`
This will create a cert.pem file that will contain both certificate and the
server's private key. The private key is not passphrase protected and so
it is unencrypted. In real life, you only want to do things like this for
quick and dirty testing purposes. Do not do this in real life (production).
When you visit the website in browser, an information about not trusting
the connection will appear. This is understandable, since you have just
generated the key and no browser-recognized certificate authority is
recognizing you, as someone who can be trusted. If you want or need to
get rid of the warning, you will need to import the certificate into your
browser's or computer's trust store. Google how to do it based on your
platform.
Args:
`bind_to_name` (str): server address, you input this into browser
`bind_to_port` (str): port number over which you will access the server
`cert_file` (str): path to file that contains private key and the cert.
Returns:
None
"""
httpd = ThreadingHTTPServer((bind_to_name, bind_to_port), SimpleHTTPRequestHandler)
context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain(certfile=cert_file)
httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
print(f"Starting server @ https://{bind_to_name}:{bind_to_port}")
httpd.serve_forever()
def _attempt_certfile_generation() -> None:
"""
Attempts to generate the cert.pem file for your convenience.
"""
cert_out_file = "cert.pem"
if os.path.exists(cert_out_file):
print(f"Certificate file ({cert_out_file}) detected.")
print("Certificate file will not be created. If you need one see")
print("comments in the serve.py file on how to create it.")
return
command = 'openssl req -newkey rsa:2048 -x509 -days 365 -nodes -out cert2.pem -keyout cert2.pem'
os.system(command)
if __name__ == '__main__':
if os.path.exists("cert.pem"):
start_server()
_attempt_certfile_generation()
start_server("localhost", 4443, "cert.pem")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment