From fb0460dd0bd84cb34a4e8ccff8c53f3cb17cde5d Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Wed, 25 Mar 2020 19:50:54 -0700 Subject: [PATCH 1/3] Experimental path_from_header feature, refs #712 --- datasette/app.py | 11 +++++++++++ docs/config.rst | 7 +++++++ tests/test_api.py | 1 + 3 files changed, 19 insertions(+) diff --git a/datasette/app.py b/datasette/app.py index 011002ee..33d41c41 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -136,6 +136,7 @@ CONFIG_OPTIONS = ( "Allow display of template debug information with ?_context=1", ), ConfigOption("base_url", "/", "Datasette URLs should use this base"), + ConfigOption("path_from_header", "", "HTTP header to override incoming path"), ) DEFAULT_CONFIG = {option.name: option.default for option in CONFIG_OPTIONS} @@ -739,6 +740,16 @@ class DatasetteRouter(AsgiRouter): self.ds = datasette super().__init__(routes) + async def __call__(self, scope, receive, send): + path_from_header = self.ds.config("path_from_header") + path = scope["path"] + raw_path = scope.get("raw_path") + if path_from_header: + raw_path = dict(scope["headers"])[path_from_header.encode("utf8")] + if raw_path: + path = raw_path.decode("ascii") + return await self.route_path(scope, receive, send, path) + async def route_path(self, scope, receive, send, path): # Strip off base_url if present before routing base_url = self.ds.config("base_url") diff --git a/docs/config.rst b/docs/config.rst index 4b12e74b..2c93a739 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -241,3 +241,10 @@ For example, if you are sending traffic from ``https://www.example.com/tools/dat You can do that like so:: datasette mydatabase.db --config base_url:/tools/datasette/ + +.. _path_from_header: + +path_from_header +---------------- + +See `issue #712 `__. diff --git a/tests/test_api.py b/tests/test_api.py index 7edd7ee6..481902bf 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1308,6 +1308,7 @@ def test_config_json(app_client): "hash_urls": False, "template_debug": False, "base_url": "/", + "path_from_header": "", } == response.json From 0f217b5e8d50070304b27a8788c01a5e75ddbdcd Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Wed, 25 Mar 2020 21:03:17 -0700 Subject: [PATCH 2/3] Apply path_from_header to entire scope, refs #712 --- datasette/app.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/datasette/app.py b/datasette/app.py index 33d41c41..c68e1cc5 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -742,13 +742,10 @@ class DatasetteRouter(AsgiRouter): async def __call__(self, scope, receive, send): path_from_header = self.ds.config("path_from_header") - path = scope["path"] - raw_path = scope.get("raw_path") if path_from_header: raw_path = dict(scope["headers"])[path_from_header.encode("utf8")] - if raw_path: - path = raw_path.decode("ascii") - return await self.route_path(scope, receive, send, path) + scope = dict(scope, raw_path=raw_path) + return await super().__call__(scope, receive, send) async def route_path(self, scope, receive, send, path): # Strip off base_url if present before routing From 7b205af0b53c92d17b69f8c95d70a24a0c06ebce Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Wed, 25 Mar 2020 21:09:00 -0700 Subject: [PATCH 3/3] Strip querystring from path_from_header, refs #712 --- datasette/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datasette/app.py b/datasette/app.py index c68e1cc5..965eb0c1 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -743,7 +743,7 @@ class DatasetteRouter(AsgiRouter): async def __call__(self, scope, receive, send): path_from_header = self.ds.config("path_from_header") if path_from_header: - raw_path = dict(scope["headers"])[path_from_header.encode("utf8")] + raw_path = dict(scope["headers"])[path_from_header.encode("utf8")].split(b"?")[0] scope = dict(scope, raw_path=raw_path) return await super().__call__(scope, receive, send)