Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion blacksheep/docs/sessions.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ sequenceDiagram
Client->>Server: HTTP Request (Cookie: session ID)
Server->>Store: Retrieve session data using session ID
Store-->>Server: Session data
Server-->>Client: HTTP Response (may update Set-Cookie)
Server-->>Client: HTTP Response
```

In this scenario, Session ID is exchanged between client and server via
Expand Down Expand Up @@ -137,6 +137,36 @@ Before version `2.4.0`, BlackSheep offered built-in support only for sessions
stored entirely on the client side, in cookies. Using sessions with a different
store required custom code.

/// admonition | Cookies and cross-site request forgery.
type: danger

When you store sessions in cookies on the client side, web applications must
implement [Anti-Forgery validation](anti-request-forgery.md) to prevent
Cross-Site Request Forgery (XSRF/CSRF).

**Why?**

Cookies are sent automatically by browsers with every request to your
domain, making your app vulnerable to Cross-Site Request Forgery (CSRF)
attacks, if information in cookies is used to authenticate requests and your
application does not implement [Anti-Forgery
validation](anti-request-forgery.md).

**How?**

Common anti-forgery mechanisms include:

- CSRF tokens: Generate a unique token per session/request and require it in
forms or headers.
- SameSite cookies: Set your session cookie with `SameSite=Strict` or
`SameSite=Lax` to limit cross-site requests.
- Custom headers: For APIs, use and require a custom header (e.g.,
`X-Session-ID`) that browsers do not send cross-origin. In a user-defined
`SessionStore` type, you can rely on a custom request and response header to
exchange information with clients —updating your client code accordingly.

///

## Enabling sessions, with custom store

Starting from `2.4.0`, the built-in classes for sessions include support for
Expand Down
57 changes: 52 additions & 5 deletions blacksheep/docs/static-files.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Serving static files
F# Serving static files

This page covers:

Expand Down Expand Up @@ -28,21 +28,22 @@ When serving files this way, a match-all route ("*") is configured in the
application router for `GET` and `HEAD`, and files are read from the configured
folder upon web requests.


It is also possible to serve static files from sub-folders:

```python
app.serve_files("app/static")
```

Enable file discovery (in such case, requests for directories will generate an
HTML response with a list of files):
To enable file discovery, add the `discovery=True` parameter. In such case,
requests for directories will generate an HTML response with a list of files:

```python
app.serve_files("app/static", discovery=True)
```

BlackSheep also supports serving static files from multiple folders, and
specifying a prefix for the route path:
Serving static files from multiple folders is supported, using a different path
for each folder:

```python
app = Application()
Expand All @@ -52,6 +53,52 @@ app.serve_files("app/images", root_path="images")
app.serve_files("app/videos", root_path="videos")
```

### Route paths and folder names

By default, when you serve files from a folder, the folder name is **not**
included in the route at which files are served. For example, if you have a
file `test.txt` in your `static` directory and you use:

```python
app.serve_files("static")
```

the file will be accessible at `http://localhost/test.txt` (not
`http://localhost/static/test.txt`).

If you want the files to be accessible under a specific route path (such as
`/static/`), use the `root_path` parameter:

```python
app.serve_files("static", root_path="static")
```

With this configuration, `test.txt` will be accessible at `http://localhost/static/test.txt`.

### Serving single files

If you need to serve single files, it is possible to use the `file` function
like in the following example.

```python
from blacksheep import Application, get
from blacksheep.server.responses import file, ContentDispositionType


app = Application()


@get("/favicon.ico")
def favicon_icon():
# Note: the file is read asynchronously and served in chunks,
# even though this function itself is synchronous
return file(
"path-to-your/favicon.ico", # ← local path
"image/vnd.microsoft.icon",
content_disposition=ContentDispositionType.INLINE,
)
```

## File extensions

Only files with a configured extension are served to the client. By default,
Expand Down