Skip to content

Instantly share code, notes, and snippets.

@Alexufo
Last active April 24, 2024 18:44
Show Gist options
  • Save Alexufo/2303bff77f0a16ba83568f0260b8cf47 to your computer and use it in GitHub Desktop.
Save Alexufo/2303bff77f0a16ba83568f0260b8cf47 to your computer and use it in GitHub Desktop.
Simple Python https server example py 3.10+ ( multithread, wasm, gzip )
import http.server
import http.cookiejar
import io
import socket
from http import HTTPStatus
import ssl
import os
import zlib
server_address = ('0.0.0.0', 4443)
hostname = socket.gethostname()
local_ip = socket.gethostbyname(hostname)
print("Open https://localhost:4443/samples/idengine_sample_wasm/sample.html")
print(f'Open https://{local_ip}:4443/samples/idengine_sample_wasm/sample.html')
class CORSHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
extensions_map = {
'': 'application/octet-stream',
'.manifest': 'text/cache-manifest',
'.html': 'text/html',
'.png': 'image/png',
'.jpg': 'image/jpg',
'.svg': 'image/svg+xml',
'.css': 'text/css',
'.js': 'application/x-javascript',
'.wasm': 'application/wasm',
'.json': 'application/json',
'.xml': 'application/xml',
}
def do_GET(self):
"""Serve a GET request."""
if f := self.send_head():
try:
if hasattr(f, "read"):
self.copyfile(f, self.wfile)
else:
for data in f:
self.wfile.write(data)
finally:
f.close()
def send_head(self):
path = self.translate_path(self.path)
f = None
try:
f = open(path, 'rb')
except OSError:
self.send_error(HTTPStatus.NOT_FOUND, "File not found")
return None
ctype = self.guess_type(path)
try:
fs = os.fstat(f.fileno())
content_length = fs[6]
self.send_response(HTTPStatus.OK)
self.send_header("Content-type", ctype)
self.send_header("Content-Length", str(content_length))
self.end_headers()
return f
except:
f.close()
raise
def end_headers(self):
# Include additional response headers here. CORS for example:
self.send_header('Access-Control-Allow-Origin', '*')
http.server.SimpleHTTPRequestHandler.end_headers(self)
httpd = http.server.ThreadingHTTPServer(server_address, CORSHTTPRequestHandler)
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.check_hostname = False
ctx.load_cert_chain(certfile='localhost.pem') # with key inside
httpd.socket = ctx.wrap_socket(httpd.socket, server_side=True)
httpd.serve_forever()
@mocksoul
Copy link

This one a well as prev gist lacks ssl handshake timeouts, thus httpd.timeout = 123 will not work
to fix:

you need to subclass HTTPServer:

class MHTTPServer(http.server.HTTPServer):
    def get_request(self):
        newsock, client = self.socket.accept()
        newsock.settimeout(self.timeout)
        newsock.do_handshake()
        return newsock, client

ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.check_hostname = False
ctx.load_cert_chain(certfile='localhost.pem')  # with key inside
httpd = MHTTPServer(server_address, hdl)
httpd.timeout = 5
httpd.socket = ctx.wrap_socket(
    httpd.socket, server_side=True,
    do_handshake_on_connect=False
)
httpd.serve_forever()

@Alexufo
Copy link
Author

Alexufo commented Mar 10, 2023

@mocksoul why are handshake timeouts so important?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment