Skip to content

Commit 2ea7e05

Browse files
Apply general improvements to BlackSheep's documentation
1 parent 25d6f30 commit 2ea7e05

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1239
-973
lines changed

.github/workflows/main.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ jobs:
3333
steps:
3434
- uses: actions/checkout@v1
3535
with:
36-
fetch-depth: 1
3736
submodules: false
3837

3938
- name: Use Python ${{ matrix.python-version }}

README.md

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,6 @@
33
This repository contains the source code of the documentation that gets
44
published to [https://www.neoteroi.dev/](https://www.neoteroi.dev/).
55

6-
---
7-
8-
Work in progress. 🚧
9-
The code has been modified to unify different projects.
10-
11-
---
12-
136
## How to contribute
147

158
The documentation uses MkDocs and Material for MkDocs. For information on how

blacksheep/docs/anti-request-forgery.md

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,25 @@ requests.
77
Examples of such situations are:
88

99
- Cookies are automatically included in web requests, so if an application uses
10-
cookie-based authentication, credentials are sent automatically
10+
cookie-based authentication, credentials are sent automatically.
1111
- After a user signs in with Basic or Digest authentication, the browser
12-
automatically sends the credentials until the session ends
12+
automatically sends the credentials until the session ends.
1313

1414
If a web application uses cookie-based authentication or other features that
1515
cause credentials to be automatically included in web requests, it requires
1616
anti-forgery measures.
1717

1818
BlackSheep implements built-in support for anti-request-forgery validation, this
19-
page describes how to use the built-in solution.
19+
page describes how to use it.
2020

21-
!!! tip
22-
Applications that store access tokens (for example JWTs) in the HTML5
23-
storage and include them in `Authorization: Bearer {...}` headers, are not
24-
vulnerable to CSRF and do not require anti-forgery measures.
21+
/// admonition | Options using HTML5 Storage.
22+
type: tip
23+
24+
Applications that store access tokens (for example JWTs) in the HTML5
25+
storage and include them in `Authorization: Bearer {...}` headers, are not
26+
vulnerable to CSRF and do not require anti-forgery measures.
27+
28+
///
2529

2630
## How to use the built-in anti-forgery validation
2731

@@ -37,10 +41,10 @@ app = Application(show_error_details=True)
3741
use_anti_forgery(app)
3842
```
3943

40-
The call to `use_anti_forgery(app)` configures a middleware that can issue and
41-
validate anti-forgery tokens, and extensions for Jinja2 templates to render
42-
anti-forgery tokens in HTML templates. It is important to configure templating
43-
before anti-forgery because the latter configures the extensions on the Jinja2
44+
The `use_anti_forgery(app)` function configures middleware to issue and
45+
validate anti-forgery tokens, as well as extensions for Jinja2 templates to
46+
render these tokens in HTML templates. It is important to configure templating
47+
before enabling anti-forgery, as the latter sets up extensions in the Jinja2
4448
environment.
4549

4650
Consider an example having this folder structure:
@@ -61,7 +65,7 @@ from blacksheep import Application, FromForm, get, post, view
6165
from blacksheep.server.csrf import use_anti_forgery
6266

6367

64-
app = Application(show_error_details=True)
68+
app = Application()
6569

6670
use_anti_forgery(app)
6771

@@ -101,19 +105,23 @@ And `index.jinja` contains the following template:
101105
</html>
102106
```
103107

104-
The `{% af_input %}` custom tag is used to render an HTML input element containing an
105-
anti-forgery token. The built-in solution uses the Double-Token strategy: when
106-
an anti-forgery token is required to render HTML for a response, a corresponding
107-
HTTP-only cookie is configured for the response. The value of the cookie and the
108-
control parameter are matched in following requests for validation. Contextually,
109-
response headers are also set to protect the HTML view against click-jacking and to
110-
forbid iframes.
108+
The `{% af_input %}` tag renders an HTML input element containing an
109+
anti-forgery token. The built-in solution uses the Double-Token strategy. When
110+
an anti-forgery token is required to render HTML, a corresponding HTTP-only
111+
cookie is included in the response. The cookie's value and the control
112+
parameter are matched in subsequent requests for validation. Contextually,
113+
response headers are also set to protect the HTML view against click-jacking
114+
and to forbid iframes.
115+
116+
/// admonition | Alternative tags.
117+
type: tip
111118

112-
!!! tip "Alternative tags"
113-
In alternative to `{% af_input %}`, it is possible to use the tag
114-
`{% csrf_input %}` (like Django). However, `af_input` is recommended since
115-
the objective of the tag is to obtain an input element containing an
116-
anti-forgery token, not to achieve Cross-Site Request Forgery!
119+
In alternative to `{% af_input %}`, it is possible to use the tag
120+
`{% csrf_input %}` (like Django). However, `af_input` is recommended since
121+
the objective of the tag is to obtain an input element containing an
122+
anti-forgery token, not to achieve Cross-Site Request Forgery!
123+
124+
///
117125

118126
An example of a rendered view looks like the following:
119127

@@ -138,14 +146,18 @@ Validation is applied by default to all `DELETE PATCH POST PUT` web requests.
138146
Requests using other methods are not validated as they are not supposed to
139147
change the state and should execute read-only operations.
140148

141-
!!! danger "Important note about token generation"
142-
Tokens are signed using symmetric encryption. For your production
143-
environments, configure application secrets using environment variables
144-
as described in [data protection](../dataprotection/).
149+
/// admonition | Important note about token generation.
150+
type: danger
151+
152+
Tokens are signed using symmetric encryption. For your production environments,
153+
configure application secrets using environment variables as described in [data
154+
protection](dataprotection.md).
155+
156+
///
145157

146158
## How to send the anti-forgery token
147159

148-
The anti-forgery token can be sent to the server in one of these ways:
160+
The anti-forgery token can be sent to the server in one of the following ways:
149161

150162
| Location | Parameter Name |
151163
| -------------- | ---------------------------- |
@@ -226,8 +238,8 @@ async def create_example():
226238

227239
## Custom AntiForgeryHandler classes
228240

229-
The following example shows how to override methods of the `AntiForgeryHandler`
230-
class:
241+
The following example demonstrates how to override methods of the
242+
`AntiForgeryHandler`:
231243

232244
```python
233245
from blacksheep.server.csrf import AntiForgeryHandler, use_anti_forgery

blacksheep/docs/application.md

Lines changed: 55 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -41,25 +41,22 @@ trace, serving a page like the following:
4141

4242
![Internal server error page](./img/internal-server-error-page.png)
4343

44-
Consider using environmental variables to handle these kinds of settings that
45-
can vary across environments. For example:
44+
/// admonition | Use the `APP_SHOW_ERROR_DETAILS`.
45+
type: tip
4646

47-
```python
48-
import os
49-
from blacksheep import Application
50-
51-
app = Application(show_error_details=bool(os.environ.get("SHOW_ERROR_DETAILS", None)))
52-
53-
54-
@get("/")
55-
def crash_test():
56-
raise Exception("Crash test")
47+
Rather than using the `show_error_details` parameter, it is recommended to use
48+
the environment variable `APP_SHOW_ERROR_DETAILS` to control whether the
49+
application displays detailed error information. Setting
50+
`APP_SHOW_ERROR_DETAILS=1` or `APP_SHOW_ERROR_DETAILS=True` enables this
51+
feature.
52+
///
5753

58-
```
54+
/// admonition | Settings strategy
5955

60-
!!! info "Settings strategy"
61-
BlackSheep project templates include a strategy to handle application
62-
settings and configuration roots.
56+
BlackSheep project templates include a strategy to handle application
57+
settings and configuration roots. Refer to [_Getting started with the MVC project template_](./mvc-project-template.md)
58+
for more information.
59+
///
6360

6461
### Configuring exceptions handlers
6562

@@ -69,14 +66,13 @@ handling a web request and reaches the application, the application checks if
6966
there is a matching handler for that kind of exception. An exception handler is
7067
defined as a function with the following signature:
7168

72-
```python
69+
```python {hl_lines="3"}
7370
from blacksheep import Request, Response, text
7471

7572
async def exception_handler(self, request: Request, exc: Exception) -> Response:
7673
pass
7774
```
7875

79-
In the exception below
8076
```python
8177

8278
class CustomException(Exception):
@@ -114,7 +110,7 @@ specific handler for one of the descendant classes.
114110
It is also possible to register exception handlers using decorators, instead
115111
of interacting with `app.exceptions_handlers` dictionary:
116112

117-
```python
113+
```python {hl_lines="5"}
118114
class CustomException(Exception):
119115
pass
120116

@@ -131,8 +127,7 @@ To override how unhandled exceptions are handled, define a custom `Application`
131127
class overriding its `handle_internal_server_error` method, like in the
132128
following example:
133129

134-
```python
135-
130+
```python {hl_lines="5-6"}
136131
from blacksheep import Application, json
137132
from blacksheep.messages import Request
138133

@@ -165,7 +160,7 @@ create an HTTP `ClientSession` that will be disposed of when the application
165160
stops. Note how the instance of `ClientSession` is also bound to application
166161
services, so that it can be injected into request handlers that need it.
167162

168-
```python
163+
```python {linenums="1" hl_lines="9-10 16"}
169164
import asyncio
170165
from blacksheep import Application
171166
from blacksheep.client.pool import ClientConnectionPools
@@ -198,14 +193,22 @@ if __name__ == "__main__":
198193
uvicorn.run(app, host="127.0.0.1", port=44777, log_level="debug", lifespan="on")
199194
```
200195

201-
!!! info
202-
The method leverages `contextlib.asynccontextmanager`. What is defined
203-
before the `yield` statement executes when the application starts, and what
204-
is defined after the `yield` statement executes when the application stops.
196+
- The code before the `yield` statement (lines _11-16_) is executed when the
197+
application starts.
198+
- The code after the `yield` statement (lines _17-18_) is executed when the
199+
application stops.
200+
201+
/// admonition | @app.lifespan
202+
203+
This method leverages `contextlib.asynccontextmanager`. What is defined
204+
before the `yield` statement executes when the application starts, and what
205+
is defined after the `yield` statement executes when the application stops.
206+
207+
///
205208

206209
The following example illustrates how a `redis-py` [connection can be disposed
207210
of](https://redis.readthedocs.io/en/stable/examples/asyncio_examples.html)
208-
using the same method:
211+
using `@app.lifespan`:
209212

210213
```python
211214
import redis.asyncio as redis
@@ -231,31 +234,39 @@ async def configure_redis():
231234
await connection.close()
232235
```
233236

234-
!!! info "Example using Redis"
235-
The `BlackSheep-Examples` repository includes an example where `Redis` is
236-
used to store access tokens and refresh tokens obtained using
237-
`OpenID Connect`: [example](https://github.com/Neoteroi/BlackSheep-Examples/blob/main/oidc/scopes_redis_aad.py). For more information on `redis-py` and its async
238-
interface, refer to its [official documentation](https://redis.readthedocs.io/en/stable/examples/asyncio_examples.html).
239-
240237
### on_start
241238

242-
This event should be used to configure things such as new request handlers,
243-
and services registered in `app.services`, such as database connection pools,
239+
This event should be used to configure components such as new request handlers
240+
and services registered in `app.services`, including database connection pools
244241
and HTTP client sessions.
245242

246243
### after_start
247244

248-
This event should be used to configure things that must happen after request
249-
handlers are normalized. At this point, the application router contains information
250-
about actual routes handled by the web application, and routes can be inspected.
251-
For example, the built-in generation of OpenAPI Documentation generates the
252-
API specification file at this point.
245+
This event should be used to configure tasks that must occur after request
246+
handlers are normalized. At this stage, the application router contains
247+
information about the actual routes handled by the web application, allowing
248+
routes to be inspected. For example, the built-in OpenAPI documentation
249+
generation creates the API specification file at this point.
250+
251+
/// admonition | Example: inspecting routes.
252+
type: tip
253+
254+
An `after_start` callback that prints all routes registered in the application
255+
router:
256+
257+
```python
258+
@app.after_start
259+
async def after_start_print_routes(application: Application) -> None:
260+
print(application.router.routes)
261+
```
262+
///
253263

254264
### on_stop
255265

256-
This event should be used to fire callbacks that need to happen when the application
257-
is stopped. For example, disposing of services that require disposal, such as
258-
database connection pools, and HTTP client sessions using connection pools.
266+
This event should be used to trigger callbacks that need to run when the
267+
application stops. For example, it can be used to dispose of services that
268+
require cleanup, such as database connection pools and HTTP client sessions
269+
using connection pools.
259270

260271
### Application life cycle
261272

@@ -329,16 +340,6 @@ are fired, and the state of the application when they are executed.
329340
app.on_stop += on_stop
330341
```
331342

332-
!!! info
333-
For example, to define an `after_start` callback that logs all routes registered
334-
in the application router:
335-
336-
```python
337-
@app.after_start
338-
async def after_start_print_routes(application: Application) -> None:
339-
print(application.router.routes)
340-
```
341-
342343
## Next
343344

344-
Read about the details of [routing in BlackSheep](../routing).
345+
Read about the details of [routing in BlackSheep](routing.md).

blacksheep/docs/asgi.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
# ASGI Servers
22

3-
BlackSheep belongs to the category of
4-
[ASGI](https://asgi.readthedocs.io/en/latest/) web frameworks, so it requires
5-
an ASGI HTTP server to run, such as [uvicorn](http://www.uvicorn.org/), or
6-
[hypercorn](https://pgjones.gitlab.io/hypercorn/). All examples in this
7-
documentation use `Uvicorn`, but the framework has been tested also with
8-
`Hypercorn` and should work with any server that implements ASGI.
3+
BlackSheep is an [ASGI](https://asgi.readthedocs.io/en/latest/) web framework,
4+
which requires an ASGI HTTP server to run, such as
5+
[Uvicorn](http://www.uvicorn.org/), or
6+
[Hypercorn](https://pgjones.gitlab.io/hypercorn/). All examples in this
7+
documentation use `Uvicorn`, but the framework has also been tested with
8+
Hypercorn and should work with any server that implements the `ASGI`
9+
specification.
910

1011
### Uvicorn
1112

@@ -20,8 +21,10 @@ documentation use `Uvicorn`, but the framework has been tested also with
2021
<br />
2122
<div class="img-auto-width"></div>
2223
<p align="left">
23-
<a href="https://pgjones.gitlab.io/hypercorn/"><img width="270" src="https://pgjones.gitlab.io/hypercorn/_images/logo.png" alt="Hypercorn"></a>
24+
<a href="https://github.com/pgjones/hypercorn"><img width="270" src="https://raw.githubusercontent.com/pgjones/hypercorn/main/artwork/logo.png" alt="Hypercorn"></a>
2425
</p>
2526

27+
---
28+
2629
Many details, such as how to run the server in production, depend on the chosen
2730
ASGI server.

0 commit comments

Comments
 (0)