-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add files middlewares * improve files middlewares and example * add tests for staticfiles and uploaded files middlewares * add docs for files middlewares * add uvicorn to test dependencies
- Loading branch information
1 parent
ccb2d65
commit 6ec6bd1
Showing
36 changed files
with
409 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Static and uploaded files | ||
|
||
The `StaticFilesMiddleware` and `UploadedFilesMiddleware` provide a way of serving | ||
static content and user uploaded files. | ||
|
||
There are two separate middlewares to allow distinct handling in the middleware | ||
pipeline. For example, you could set the uploaded files to be served after authorization, | ||
while the static files remain publicly accessible. | ||
|
||
## Usage | ||
|
||
First you need to activate the middlewares in the `settings.yaml` | ||
|
||
```yaml | ||
middleware: | ||
# ... | ||
- selva.web.middleware.files.StaticFilesMiddleware | ||
- selva.web.middleware.files.UploadedFilesMiddleware | ||
# ... | ||
``` | ||
|
||
After that, files located in the directories `resources/static` and `resources/uploads` | ||
will be served at `/static/` and `/uploads/`, respectively. | ||
|
||
## Static files mappings | ||
|
||
You can map specific paths to single static files in order to, for example, serve | ||
the favicon at `/favicon.ico` pointing to a file in `resources/static/`: | ||
|
||
```yaml | ||
middleware: | ||
- selva.web.middleware.files.StaticFilesMiddleware | ||
staticfiles: | ||
mappings: | ||
favicon.ico: my-icon.ico | ||
``` | ||
## Configuration options | ||
The available options to configure the `StaticFilesMiddleware` and `UploadedFilesMiddleware` | ||
are shown below: | ||
|
||
```yaml | ||
staticfiles: | ||
path: /static # (1) | ||
root: resources/static # (2) | ||
mappings: {} | ||
uploadedfiles: | ||
path: /uploads # (3) | ||
root: resources/uploads # (4) | ||
``` | ||
|
||
1. Path where static files are served | ||
2. Directory where static files are located | ||
3. Path where uploaded files are served | ||
4. Directory where uploaded files are located |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
middleware: | ||
- selva.web.middleware.files.StaticFilesMiddleware | ||
- selva.web.middleware.request_id.RequestIdMiddleware | ||
|
||
logging: | ||
root: info | ||
level: | ||
application: info | ||
format: console |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Lorem ipsum dolor sit amet. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from asgikit.responses import respond_text | ||
from selva.web import controller, get | ||
|
||
|
||
@controller | ||
class Controller: | ||
@get | ||
async def index(self, request): | ||
request.response.content_type = "text/html" | ||
await respond_text(request.response, "Lorem ipsum dolor sit amet") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
middleware: | ||
- selva.web.middleware.files.StaticFilesMiddleware | ||
- selva.web.middleware.files.UploadedFilesMiddleware | ||
staticfiles: | ||
mappings: | ||
favicon.ico: python.ico |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam congue feugiat tortor sit amet bibendum. Phasellus euismod risus eget lorem ornare, ac porta quam lobortis. Sed eget est at nulla scelerisque tincidunt. Aliquam condimentum purus id nisl vestibulum, nec eleifend magna interdum. Curabitur lacinia libero sed nisl mollis, et accumsan justo efficitur. Integer sit amet libero eget lorem varius faucibus vel quis sem. Duis consequat tempor orci eu porta. Sed ut metus porta, elementum nunc a, tincidunt massa. Sed volutpat tincidunt odio, vel venenatis est ultrices ut. Morbi et purus sed sapien elementum commodo. Sed rutrum odio vel magna dignissim laoreet. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
from abc import ABCMeta, abstractmethod | ||
from pathlib import Path | ||
from typing import Annotated | ||
|
||
from asgikit.requests import Request | ||
from asgikit.responses import respond_file | ||
|
||
from selva.configuration import Settings | ||
from selva.di import Inject | ||
from selva.web.middleware import CallNext, Middleware | ||
from selva.web.exception import HTTPNotFoundException | ||
|
||
|
||
class BaseFilesMiddleware(Middleware, metaclass=ABCMeta): | ||
settings: Annotated[Settings, Inject] | ||
settings_property: str | ||
|
||
path: str | ||
root: Path | ||
|
||
def initialize(self): | ||
settings = self.settings.get(self.settings_property) | ||
self.path = settings.path.lstrip("/") | ||
self.root = Path(settings.root).resolve() | ||
|
||
@abstractmethod | ||
def get_file_to_serve(self, request: Request) -> str | None: | ||
pass | ||
|
||
async def __call__(self, call_next: CallNext, request: Request): | ||
if file_to_serve := self.get_file_to_serve(request): | ||
file_to_serve = (self.root / file_to_serve).resolve() | ||
if not ( | ||
file_to_serve.is_file() and file_to_serve.is_relative_to(self.root) | ||
): | ||
raise HTTPNotFoundException() | ||
|
||
await respond_file(request.response, file_to_serve) | ||
else: | ||
await call_next(request) | ||
|
||
|
||
class UploadedFilesMiddleware(BaseFilesMiddleware): | ||
settings_property = "uploadedfiles" | ||
|
||
def get_file_to_serve(self, request: Request) -> str | None: | ||
request_path = request.path.lstrip("/") | ||
|
||
if request_path.startswith(self.path): | ||
return request_path.removeprefix(self.path).lstrip("/") | ||
|
||
return None | ||
|
||
|
||
class StaticFilesMiddleware(BaseFilesMiddleware): | ||
settings_property = "staticfiles" | ||
mappings: dict[str, str] | ||
|
||
def initialize(self): | ||
super().initialize() | ||
|
||
settings = self.settings.get(self.settings_property) | ||
self.mappings = { | ||
name.lstrip("/"): value.lstrip("/") | ||
for name, value in settings.get("mappings", {}).items() | ||
} | ||
|
||
def get_file_to_serve(self, request: Request) -> str | None: | ||
request_path = request.path.lstrip("/") | ||
|
||
if file_to_serve := self.mappings.get(request_path): | ||
return file_to_serve.lstrip("/") | ||
|
||
if request_path.startswith(self.path): | ||
return request_path.removeprefix(self.path).lstrip("/") | ||
|
||
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.