diff --git a/django_signposting/middleware.py b/django_signposting/middleware.py index 57ca303..05e44fb 100644 --- a/django_signposting/middleware.py +++ b/django_signposting/middleware.py @@ -41,6 +41,7 @@ class SignpostingMiddleware: response["Link"] = " , ".join(link_snippets) + class HtmlSignpostingMiddleware(SignpostingMiddleware): def __init__(self, get_response: Callable[[HttpRequest], HttpResponse]): self.get_response = get_response @@ -50,15 +51,15 @@ class HtmlSignpostingMiddleware(SignpostingMiddleware): if not hasattr(response, "_signposts"): return response - + # Adding Signposts via HTML is only supported for HTML responses if not response.headers["Content-Type"].startswith("text/html"): return response - + content = response.content.decode("utf-8") soup = BeautifulSoup(content, "html.parser") - # Html should have a root element + # Html should have a root element if not soup.html: raise Exception("Could not find HTML root element") @@ -67,7 +68,6 @@ class HtmlSignpostingMiddleware(SignpostingMiddleware): head_tag = soup.new_tag("head") soup.html.insert(0, head_tag) - # BUild links for each signpost and add them to the html for signpost in response._signposts: link_tag = soup.new_tag("link") @@ -79,13 +79,12 @@ class HtmlSignpostingMiddleware(SignpostingMiddleware): # Override the original content with the new HTML response.content = soup.prettify().encode("utf-8") - response['Content-Length'] = len(response.content) - + response["Content-Length"] = len(response.content) + return response class JsonLdSignpostingParserMiddleware(MiddlewareMixin): - def process_response( self, request: HttpRequest, response: HttpResponse ) -> HttpResponse: diff --git a/tests/test_html_signposting_middleware.py b/tests/test_html_signposting_middleware.py index 78991ba..f20dea3 100644 --- a/tests/test_html_signposting_middleware.py +++ b/tests/test_html_signposting_middleware.py @@ -4,10 +4,10 @@ from django_signposting.middleware import HtmlSignpostingMiddleware from signposting import LinkRel, Signpost import pytest -def assert_links_exist(response: HttpResponse, signposts: list[Signpost]=None): + +def assert_links_exist(response: HttpResponse, signposts: list[Signpost] = None): if signposts is None: signposts = response._signposts - soup = BeautifulSoup(response.content.decode("utf-8"), "html.parser") for signpost in signposts: @@ -16,61 +16,58 @@ def assert_links_exist(response: HttpResponse, signposts: list[Signpost]=None): assert len(soup.find_all("link")) == len(signposts) + def test_middleware_no_signposting(): response = HttpResponse("") response.status_code = 200 middleware = HtmlSignpostingMiddleware(lambda request: response) response = middleware(None) - + assert_links_exist(response, []) def test_middleware_no_html(): response = JsonResponse({"hello": "world"}) response.status_code = 200 - response._signpost = [ - Signpost(LinkRel.author, "http://example.com") - ] + response._signpost = [Signpost(LinkRel.author, "http://example.com")] middleware = HtmlSignpostingMiddleware(lambda request: response) middleware(None) assert_links_exist(response, []) + def test_middleware_malformed_html(): response = HttpResponse("Hello world") response.status_code = 200 response.content_type = "text/html" - response._signposts = [ - Signpost(LinkRel.author, "http://example.com") - ] + response._signposts = [Signpost(LinkRel.author, "http://example.com")] middleware = HtmlSignpostingMiddleware(lambda request: response) with pytest.raises(Exception): middleware(None) + def test_middleware_signposting_without_head(): response = HttpResponse("") response.status_code = 200 - response._signposts = [ - Signpost(LinkRel.author, "http://example.com") - ] + response._signposts = [Signpost(LinkRel.author, "http://example.com")] middleware = HtmlSignpostingMiddleware(lambda request: response) middleware(None) assert_links_exist(response) + def test_middleware_signposting(): response = HttpResponse("") response.status_code = 200 - response._signposts = [ - Signpost(LinkRel.author, "http://example.com") - ] + response._signposts = [Signpost(LinkRel.author, "http://example.com")] middleware = HtmlSignpostingMiddleware(lambda request: response) middleware(None) assert_links_exist(response) + def test_middleware_multiple_signposts(): response = HttpResponse("") response.status_code = 200 @@ -88,9 +85,7 @@ def test_middleware_multiple_signposts(): def test_middleware_signpost_with_content_type(): response = HttpResponse("") response.status_code = 200 - response._signposts = [ - Signpost(LinkRel.item, "http://example.com", "text/json") - ] + response._signposts = [Signpost(LinkRel.item, "http://example.com", "text/json")] middleware = HtmlSignpostingMiddleware(lambda request: response) response = middleware(None) @@ -100,9 +95,7 @@ def test_middleware_signpost_with_content_type(): def test_middleware_ignore_error_responses(): response = HttpResponse("") response.status_code = 400 - response._signposts = [ - Signpost(LinkRel.author, "http://example.com") - ] + response._signposts = [Signpost(LinkRel.author, "http://example.com")] middleware = HtmlSignpostingMiddleware(lambda request: response) response = middleware(None) @@ -112,11 +105,8 @@ def test_middleware_ignore_error_responses(): def test_middleware_type_link(): response = HttpResponse("") response.status_code = 200 - response._signposts = [ - Signpost(LinkRel.type, "http://schema.org/Dataset") - ] + response._signposts = [Signpost(LinkRel.type, "http://schema.org/Dataset")] middleware = HtmlSignpostingMiddleware(lambda request: response) response = middleware(None) assert_links_exist(response) -