From f1116b524f8c5a86a3c3902c7e52cd922bc670c9 Mon Sep 17 00:00:00 2001 From: Jake Howard Date: Thu, 28 Nov 2019 12:13:56 +0000 Subject: [PATCH 1/3] Return as soon as we have a port for the current hostname, rather than once all are enumerated --- router.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/router.py b/router.py index 663076f..b6e6794 100644 --- a/router.py +++ b/router.py @@ -6,16 +6,15 @@ import requests -def get_routes(): - routes = {} +def get_route_for_hostname(hostname): for process in psutil.process_iter(attrs=["environ"]): - try: - host = process.info["environ"]["VIRTUAL_HOST"] - port = process.info["environ"]["PORT"] - routes[host] = port - except: - pass - return routes + process_env = process.info["environ"] + if ( + process_env + and process_env.get("VIRTUAL_HOST") == hostname + and "PORT" in process_env + ): + return process_env["PORT"] app = Flask(__name__, static_folder=None) @@ -25,14 +24,14 @@ def get_routes(): @app.endpoint("proxy") def proxy(path): - routes = get_routes() hostname = urlparse(request.base_url).hostname - if hostname not in routes: + upstream_port = get_route_for_hostname(hostname) + if not upstream_port: app.logger.warn(f"No backend for {hostname}") abort(502) path = request.full_path if request.args else request.path - target_url = f"http://localhost:{routes[hostname]}{path}" + target_url = f"http://localhost:{upstream_port}{path}" app.logger.info(f"Routing request to backend - {request.method} {hostname}{path}") downstream_response = requests.request( From 768b732f0282cfc1847cc81be5c2aeb89955a57a Mon Sep 17 00:00:00 2001 From: Jake Howard Date: Thu, 30 Apr 2020 15:53:05 +0100 Subject: [PATCH 2/3] Allow specifying multiple virtual hosts --- README.md | 6 ++++++ crab/router.py | 8 +++----- tests/test_router.py | 10 ++++++++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a5d7b51..c3e6335 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,12 @@ You can set this environment variable in the `.env` file for your project e.g. VIRTUAL_HOST=mywebsite.localhost ``` +You can also specify multiple hostnames: + +``` +VIRTUAL_HOST=mywebsite.localhost,myotherwebsite.localhost +``` + Then you can start (or restart) your project, visit `http://mywebsite.localhost:8080` in your browser, and the traffic will magically be routed to the right place. (Note that at least Chrome automatically routes everything with the TLD `.localhost` to 127.0.0.1. Other browsers may or may not follow this standard). diff --git a/crab/router.py b/crab/router.py index 24a7aaa..32c9f34 100644 --- a/crab/router.py +++ b/crab/router.py @@ -10,11 +10,9 @@ def get_route_for_hostname(hostname): for process in psutil.process_iter(attrs=["environ"]): process_env = process.info["environ"] - if ( - process_env - and process_env.get("VIRTUAL_HOST") == hostname - and "PORT" in process_env - ): + if not process_env or "PORT" not in process_env: + continue + if hostname in process_env.get("VIRTUAL_HOST", "").split(","): return process_env["PORT"] diff --git a/tests/test_router.py b/tests/test_router.py index f2bf21a..43ea9e7 100644 --- a/tests/test_router.py +++ b/tests/test_router.py @@ -13,3 +13,13 @@ def test_get_routes(self): self.assertEqual(get_route_for_hostname("test.localhost"), "1234") self.assertIsNone(get_route_for_hostname("not-test.localhost")) subproc.terminate() + + def test_multiple_routes(self): + with subprocess.Popen( + ["sleep", "5"], + env={**os.environ, "VIRTUAL_HOST": "test.localhost,other-test.localhost", "PORT": "1234"}, + ) as subproc: + self.assertEqual(get_route_for_hostname("test.localhost"), "1234") + self.assertEqual(get_route_for_hostname("other-test.localhost"), "1234") + self.assertIsNone(get_route_for_hostname("not-test.localhost")) + subproc.terminate() From 5c4883b1122959233ea79c83005801e009309783 Mon Sep 17 00:00:00 2001 From: Jake Howard Date: Thu, 30 Apr 2020 15:56:04 +0100 Subject: [PATCH 3/3] Run black over tests --- tests/test_router.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/test_router.py b/tests/test_router.py index 43ea9e7..7b87dc6 100644 --- a/tests/test_router.py +++ b/tests/test_router.py @@ -17,7 +17,11 @@ def test_get_routes(self): def test_multiple_routes(self): with subprocess.Popen( ["sleep", "5"], - env={**os.environ, "VIRTUAL_HOST": "test.localhost,other-test.localhost", "PORT": "1234"}, + env={ + **os.environ, + "VIRTUAL_HOST": "test.localhost,other-test.localhost", + "PORT": "1234", + }, ) as subproc: self.assertEqual(get_route_for_hostname("test.localhost"), "1234") self.assertEqual(get_route_for_hostname("other-test.localhost"), "1234")