Details
-
Task
-
Resolution: Done
-
Not Evaluated
-
None
-
None
-
None
Description
This task documents a local web server setup for use when developing with Qt for WebAssembly. The requirements are:
- Small and modifiable implementation. Easy to use.
- Use secure sockets. Many new web features now require a secure context. “localhost” (over http) is in some cases considered a secure context, but may not always be so.
- Serve from “localhost”, but also from the machine’s public ip, which enables access from other devices.
- Ability to set custom headers (e.g. for enabling threading/SharedArrayBuffer)
This approach uses mkcert to generate certificates, and python’s HTTPServer (ssl enabled as suggested by piware.de) with a modification to set additional headers.
Note: Please evaluate the security implications of installing a certificate authority and running a web server on a public IP as it applies to your setup before using this solution.
1. Install mkcert and install the certificate authority: See https://blog.filippo.io/mkcert-valid-https-certificates-for-localhost/
brew install mkcert mkcert -install
The CA can be installed on other devices: Run “mkcert” to print the location of the CA, then install the rootCA.pem file (e.g. email it to yourself and open it on the device)
2. Run pyserver.py (code provided below):
./pyserver 8005
The script will
- Generate certificates for “localhost” and the current public ip
- Serve the current directory on “localhost” and the current public ip, at the given port
- Set required extra headers
(edit the script as needed)
#!/usr/local/bin/python3 import os import socket import ssl import sys import threading from http.server import HTTPServer, SimpleHTTPRequestHandler from subprocess import call certdir = os.path.expanduser('~') class MyHTTPRequestHandler(SimpleHTTPRequestHandler): def end_headers(self): # send addtitional headers self.send_header("Cross-Origin-Opener-Policy", "same-origin") self.send_header("Cross-Origin-Embedder-Policy", "require-corp") SimpleHTTPRequestHandler.end_headers(self) # serve cwd from https/addr:port, with certificates from certdir def serve(addr, port): httpd = HTTPServer((addr, port), MyHTTPRequestHandler) httpd.socket = ssl.wrap_socket(httpd.socket, certfile= certdir + "localhost+1.pem", keyfile=certdir + "localhost+1-key.pem", server_side=True) thread = threading.Thread(target = httpd.serve_forever) thread.deamon = False thread.start() # get (public) local ip and determine which port to use localHostIp = socket.gethostbyname(socket.gethostname()) port = int(sys.argv[1]) if len(sys.argv) > 1 else 8000 # generate certificates for local ip print(f"Creating certificates in {certdir}\n") call(f'mkcert localhost {localHostIp}', cwd=certdir, shell=True) # serve on localhost and local ip print(f"Serving at localhost:{port}") serve("localhost", port) print(f"Serving at {localHostIp}:{port}") serve(localHostIp, port)