Last active
January 19, 2018 00:36
-
-
Save Naddiseo/a94f1c434dedd1c836bb3ec1ec3b6ec5 to your computer and use it in GitHub Desktop.
Caddy frontend for django manage.py.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import sys | |
HERE = os.path.dirname(__file__) | |
# Stolen from a SO answer | |
def get_free_port(): | |
import socket | |
import contextlib | |
with contextlib.closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s: | |
s.bind(('localhost', 0)) | |
return s.getsockname()[1] | |
# Mostly stolen from some of the runserver internals | |
def runserver_to_caddy_args(): | |
import re | |
from django.core.management.commands.runserver import Command, naiveip_re | |
ret_args = [] | |
argv = list(sys.argv) | |
cmd = Command() | |
parser = cmd.create_parser(argv[0], argv[1]) | |
options = parser.parse_args(argv[2:]) | |
use_ipv6 = options.use_ipv6 | |
if not options.addrport: | |
addr = '' | |
port = cmd.default_port | |
else: | |
m = re.match(naiveip_re, options.addrport) | |
if m is None: | |
raise Exception(f"{options.addrport} is not valid port or addr:port") | |
addr, _ipv4, _ipv6, _fqdn, port = m.groups() | |
if not port.isdigit(): | |
raise Exception(f"{port} is not valid port") | |
if addr: | |
if _ipv6: | |
addr = addr[1:-1] | |
use_ipv6 = True | |
elif use_ipv6 and not _fqdn: | |
raise Exception(f"{addr} is not a valid ipv6 address") | |
if not addr: | |
addr = '::1' if use_ipv6 else '127.0.0.1' | |
free_local_port = get_free_port() | |
new_addrport = f'localhost:{free_local_port}' | |
# replace the command line address | |
if options.addrport: | |
try: | |
# Replace if possible | |
argv[argv.index(options.addrport)] = new_addrport | |
except ValueError: | |
# .index can raise ValueError, in which case we will ignore | |
pass | |
else: | |
argv.append(new_addrport) | |
crt_path = os.path.join(HERE, 'etc', 'localhost.crt') | |
key_path = os.path.join(HERE, 'etc', 'localhost.key') | |
ret_args.extend(('-host', addr)) | |
ret_args.extend(('-port', port)) | |
ret_args.extend(( | |
f'proxy / {new_addrport}', | |
f'tls {crt_path} {key_path}', | |
)) | |
ret_args.extend(('log stdout',)) | |
return ret_args, argv | |
def main(*args): | |
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' | |
from django.core import management | |
args = list(args) | |
if 'runserver' in args and os.environ.get('RUN_MAIN') == 'true': | |
import subprocess | |
import atexit | |
caddy_args, args = runserver_to_caddy_args() | |
p = subprocess.Popen( | |
['caddy', *caddy_args], | |
cwd = os.getcwd(), | |
env = os.environ, | |
stdout = sys.stdout, | |
stderr = sys.stderr, | |
) | |
def kill(): | |
print("KILLING") | |
p.kill() | |
atexit.register(kill) | |
management.execute_from_command_line(*args) | |
if __name__ == '__main__': | |
main(*sys.argv) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment