From b9581444f9706238d903e76ceb98fe3b2df0699f Mon Sep 17 00:00:00 2001 From: taoufik07 Date: Tue, 19 Feb 2019 14:44:23 +0100 Subject: [PATCH 1/4] Return 404 when static file is not found --- responder/api.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/responder/api.py b/responder/api.py index ac34de2..1d0afd8 100644 --- a/responder/api.py +++ b/responder/api.py @@ -104,7 +104,7 @@ class API: for _dir in (self.static_dir, self.templates_dir): os.makedirs(_dir, exist_ok=True) - self.whitenoise = WhiteNoise(application=self._default_wsgi_app) + self.whitenoise = WhiteNoise(application=self._notfound_wsgi_app) self.whitenoise.add_files(str(self.static_dir)) self.whitenoise.add_files( @@ -156,9 +156,14 @@ class API: ) #: A Requests session that is connected to the ASGI app. @staticmethod - def _default_wsgi_app(*args, **kwargs): + def _default_wsgi_app(environ, start_response): pass + @staticmethod + def _notfound_wsgi_app(environ, start_response): + start_response("404 NOT FOUND", [("Content-Type", "text/plain")]) + return [b"Not Found."] + @property def before_requests(self): def gen(): @@ -467,6 +472,8 @@ class API: if os.path.exists(index): with open(index, "r") as f: resp.text = f.read() + else: + resp.text = "Not found." def schema_response(self, req, resp): resp.status_code = status_codes.HTTP_200 From c0e9a6778da42cfe1d3a4635c58623e2e3b7c0df Mon Sep 17 00:00:00 2001 From: taoufik07 Date: Wed, 20 Feb 2019 23:19:38 +0100 Subject: [PATCH 2/4] Set static_response status if not found --- responder/api.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/responder/api.py b/responder/api.py index 1d0afd8..0dc4245 100644 --- a/responder/api.py +++ b/responder/api.py @@ -244,7 +244,7 @@ class API: async def _dispatch_ws(self, ws): route = self.path_matches_route(ws.url.path) route = self.routes.get(route) - # await self._dispatch(route, ws=ws) + try: try: # Run the view. @@ -255,7 +255,7 @@ class API: except TypeError as e: cont = True except Exception: - self.background( + await self.background( self.default_response, websocket=route.uses_websocket, error=True ) raise @@ -391,7 +391,7 @@ class API: # If it's async, await it. if hasattr(r, "send"): await r - except Exception as e: + except Exception: await self.background(self.default_response, req, resp, error=True) raise @@ -468,11 +468,11 @@ class API: def static_response(self, req, resp): index = (self.static_dir / "index.html").resolve() - resp.content = None if os.path.exists(index): with open(index, "r") as f: resp.text = f.read() else: + resp.status_code = status_codes.HTTP_404 resp.text = "Not found." def schema_response(self, req, resp): From 97da6a669438115464a097e3ff35d739f02bfeb3 Mon Sep 17 00:00:00 2001 From: taoufik07 Date: Thu, 21 Feb 2019 00:46:27 +0100 Subject: [PATCH 3/4] Format static_route --- responder/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/responder/api.py b/responder/api.py index 0dc4245..59bce2d 100644 --- a/responder/api.py +++ b/responder/api.py @@ -76,7 +76,7 @@ class API: self.version = version self.openapi_version = openapi self.static_dir = Path(os.path.abspath(static_dir)) - self.static_route = static_route + self.static_route = f"/{static_route.strip('/')}" self.templates_dir = Path(os.path.abspath(templates_dir)) self.built_in_templates_dir = Path( os.path.abspath(os.path.dirname(__file__) + "/templates") From e2f887ec5f57713c193caa24e2a3c4d98a863bf8 Mon Sep 17 00:00:00 2001 From: taoufik07 Date: Thu, 21 Feb 2019 00:51:31 +0100 Subject: [PATCH 4/4] Add tests --- tests/test_responder.py | 77 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/tests/test_responder.py b/tests/test_responder.py index 2c479f7..7048d1b 100644 --- a/tests/test_responder.py +++ b/tests/test_responder.py @@ -2,8 +2,10 @@ import concurrent import pytest import yaml +import random import responder import requests +import string import io from starlette.responses import PlainTextResponse @@ -603,3 +605,78 @@ def test_allowed_hosts(): api._session = None r = api.session(base_url="http://tenant2.;").get(api.url_for(get)) assert r.status_code == 200 + + +def create_asset(static_dir, name=None, parent_dir=None): + if name is None: + name = random.choices(string.ascii_letters, k=6) + # :3 + ext = random.choices(string.ascii_letters, k=2) + name = f"{name}.{ext}" + + if parent_dir is None: + parent_dir = static_dir + else: + parent_dir = static_dir.mkdir(parent_dir) + + asset = parent_dir.join(name) + asset.write("body { color: blue; }") + return asset + + +def test_staticfiles(tmpdir): + static_dir = tmpdir.mkdir("static") + + asset1 = create_asset(static_dir) + parent_dir = "css" + asset2 = create_asset(static_dir, name="asset2", parent_dir=parent_dir) + + api = responder.API(static_dir=str(static_dir)) + session = api.session() + + static_route = api.static_route + + # ok + r = session.get(f"{static_route}/{asset1.basename}") + assert r.status_code == api.status_codes.HTTP_200 + + r = session.get(f"{static_route}/{parent_dir}/{asset2.basename}") + assert r.status_code == api.status_codes.HTTP_200 + + # Asset not found + r = session.get(f"{static_route}/not_found.css") + assert r.status_code == api.status_codes.HTTP_404 + + # Not found on dir listing + r = session.get(f"{static_route}") + assert r.status_code == api.status_codes.HTTP_404 + + r = session.get(f"{static_route}/{parent_dir}") + assert r.status_code == api.status_codes.HTTP_404 + + +def test_staticfiles_custom_route(tmpdir): + static_dir = tmpdir.mkdir("static") + static_route = "custom/static/route/" + + asset = create_asset(static_dir) + + api = responder.API(static_dir=str(static_dir), static_route=static_route) + session = api.session() + + # Check + assert api.static_route == "/custom/static/route" + + static_route = api.static_route + + # ok + r = session.get(f"{static_route}/{asset.basename}") + assert r.status_code == api.status_codes.HTTP_200 + + # Asset not found + r = session.get(f"{static_route}/not_found.css") + assert r.status_code == api.status_codes.HTTP_404 + + # Not found on dir listing + r = session.get(f"{static_route}") + assert r.status_code == api.status_codes.HTTP_404