From 779633b19541daf4557e378dbfabf2079a7cfb67 Mon Sep 17 00:00:00 2001 From: Wim De Clercq Date: Fri, 17 Feb 2023 15:01:44 +0100 Subject: [PATCH] Use default redirect when nothing matches. Issue #86 --- tests/test_handler.py | 13 +++++++++---- urihandler/handler.py | 39 ++++++++++++++++++++++++++++----------- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/tests/test_handler.py b/tests/test_handler.py index 222841c..84fbaee 100644 --- a/tests/test_handler.py +++ b/tests/test_handler.py @@ -40,10 +40,10 @@ def test_redirect_with_mime_match(self, urihandler): def test_redirect_with_mime_no_match(self, urihandler): req = testing.DummyRequest(accept="application/pdf") req.host_url = "http://test.urihandler.org" - with pytest.raises(HTTPNotAcceptable): - urihandler.handle("http://test.urihandler.org/foobar/18", req) + res = urihandler.handle("http://test.urihandler.org/foobar/18", req) + assert res == "http://localhost:5555/foobar/18" - def test_redirect_default_mime(self, urihandler): + def test_redirect_default_set(self, urihandler): req = testing.DummyRequest() req.host_url = "http://test.urihandler.org" res = urihandler.handle("http://test.urihandler.org/pdf_default/18", req) @@ -54,12 +54,17 @@ def test_redirect_default_mime(self, urihandler): res = urihandler.handle("http://test.urihandler.org/pdf_default/18", req) assert res == "http://localhost:5555/pdf_default/18.json" - def test_redirect_no_default_mime(self, urihandler): + def test_redirect_no_default(self, urihandler): req = testing.DummyRequest() req.host_url = "http://test.urihandler.org" with pytest.raises(HTTPNotAcceptable): urihandler.handle("http://test.urihandler.org/mime_no_default/18", req) + req = testing.DummyRequest(accept="application/pdf") + req.host_url = "http://test.urihandler.org" + with pytest.raises(HTTPNotAcceptable): + urihandler.handle("http://test.urihandler.org/mime_no_default/18", req) + def test_unanchored_redirect(self, urihandler): req = testing.DummyRequest() req.host_url = "http://test.urihandler.org" diff --git a/urihandler/handler.py b/urihandler/handler.py index b300d39..5035da0 100644 --- a/urihandler/handler.py +++ b/urihandler/handler.py @@ -34,22 +34,39 @@ def handle(self, uri, request): if m: redirect = u["redirect"] if isinstance(redirect, dict): - if isinstance(request.accept, AcceptNoHeader): - redirect = redirect.get("default") - if not redirect: - raise HTTPNotAcceptable() - else: - for mime, redirect in redirect.items(): - if mime in request.accept: - break - else: - # No matching mime was found. - raise HTTPNotAcceptable() + redirect = self._get_redirect_based_on_accept_header( + request.accept, redirect + ) redirect = redirect.format(**m.groupdict()) log.debug(f"Match found. Redirecting to {redirect}.") return redirect return None + def _get_redirect_based_on_accept_header(self, accept_header, redirect_rule): + """ + Return the redirect rule based on accept header. + + At its core it simply looks for a matching mime between accept header + and the configured mime type redirects. But exceptions apply. + + If there is no accept header specified or if no matching mime is found, + the default will be returned. If default is not set, HTTP 406 gets raised. + """ + default = redirect_rule.get("default") + if isinstance(accept_header, AcceptNoHeader): + if not default: + raise HTTPNotAcceptable() + return default + + for mime, redirect in redirect_rule.items(): + if mime in accept_header: + return redirect + + if not default: + raise HTTPNotAcceptable() + + return default + def _build_uri_handler(registry, handlerconfig): """