Skip to content

Commit

Permalink
Update the documentation for v2
Browse files Browse the repository at this point in the history
  • Loading branch information
RobertoPrevato authored Nov 19, 2023
1 parent 031b307 commit 42e426e
Show file tree
Hide file tree
Showing 38 changed files with 1,809 additions and 718 deletions.
8 changes: 5 additions & 3 deletions docs/about.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ The name _BlackSheep_ was chosen for two reasons:
intentional
rebelliousness_](https://idioms.thefreedictionary.com/the+black+sheep) -
especially for the choice of giving so much importance to _dependency
injection_ (which is not very popular in Python community), asynchronous
coding and type annotations (which are still debated upon in Python
community), and for being a Python web framework inspired by ASP.NET Core.
injection_ (which is not very popular in Python community, or _was not_
popular when BlackSheep was started), asynchronous coding and type
annotations (which are still debated upon in Python community, or _were_
debated upon when BlackSheep was started), and for being a Python web
framework inspired by ASP.NET Core.
* as a tribute to the song _The Sinking Belle (Black Sheep)_ of the album
[_Altar_](https://en.wikipedia.org/wiki/Altar_(album)), by Boris and
Sunn O))).
44 changes: 16 additions & 28 deletions docs/anti-request-forgery.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# Preventing Cross-Site Request Forgery (XSRF/CSRF)

Cross-site request forgery, also known as XSRF or CSRF, is a kind of attack that
exploits situations in which browsers automatically include credentials in web requests.
exploits situations in which browsers automatically include credentials in web
requests.

Example of such situations are:

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

If a web application uses cookie based authentication or other features that
cause credentials to be automatically included in web requests, it requires
Expand All @@ -27,18 +28,13 @@ page describes how to use the built-in solution.
To enable anti-forgery validation, use the module `blacksheep.server.csrf`:

```python
from blacksheep import Application, FromForm
from blacksheep import Application
from blacksheep.server.csrf import use_anti_forgery
from blacksheep.server.templating import use_templates
from jinja2 import PackageLoader


app = Application(show_error_details=True)

use_templates(app, PackageLoader("app", "views"))

use_anti_forgery(app)

```

The call to `use_anti_forgery(app)` configures a middleware that can issue and
Expand All @@ -54,43 +50,39 @@ Consider an example having this folder structure:
├── app
│   ├── __init__.py
│   └── views
│   └── index.html
│   └── index.jinja
└── server.py
```

Where `server.py` contains the following code:

```python
from blacksheep import Application, FromForm
from blacksheep import Application, FromForm, get, post, view
from blacksheep.server.csrf import use_anti_forgery
from blacksheep.server.templating import use_templates
from jinja2 import PackageLoader


app = Application(show_error_details=True)

render = use_templates(app, PackageLoader("app", "views"))

use_anti_forgery(app)


@app.router.get("/")
async def home(request):
return render("index", {}, request=request)
@get("/")
def home(request):
return view("index", {}, request=request)


class CreateUserInput:
def __init__(self, username: str, **kwargs):
self.username = username


@app.router.post("/user")
@post("/user")
async def create_user(data: FromForm[CreateUserInput]):
"""Calls to this endpoint require an anti-forgery token."""
return {"example": True, "username": data.value.username}
```

And `index.html` contains the following template:
And `index.jinja` contains the following template:

```html
<!DOCTYPE html>
Expand Down Expand Up @@ -171,7 +163,7 @@ To use custom parameter names, refer to the `AntiForgeryHandler` class in
│   ├── __init__.py
│   └── views
│   └── home
│      └── index.html
│      └── index.jinja
└── server.py
```

Expand All @@ -181,13 +173,9 @@ To use custom parameter names, refer to the `AntiForgeryHandler` class in
from blacksheep import Application, FromForm
from blacksheep.server.controllers import Controller, get, post
from blacksheep.server.csrf import use_anti_forgery
from blacksheep.server.templating import use_templates
from jinja2 import PackageLoader

app = Application(show_error_details=True)

use_templates(app, PackageLoader("app", "views"))

use_anti_forgery(app)


Expand All @@ -207,7 +195,7 @@ class Home(Controller):
return {"example": True, "username": data.value.username}
```

`index.html` (like in the previous example).
`index.jinja` (like in the previous example).

## Rendering anti-forgery tokens without input elements

Expand All @@ -231,7 +219,7 @@ from blacksheep.server.csrf import ignore_anti_forgery


@ignore_anti_forgery()
@app.router.post("/example")
@post("/example")
async def create_example():
"""This endpoint does not require an anti-forgery token."""
```
Expand Down
36 changes: 17 additions & 19 deletions docs/application.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ request handlers, producing a `HTTP 500 Internal Server Error` response. To see
this in practice, start an application like the following:

```python
from blacksheep import Application
from blacksheep import Application, get

app = Application()
get = app.router.get


@get("/")
Expand Down Expand Up @@ -50,7 +49,6 @@ import os
from blacksheep import Application

app = Application(show_error_details=bool(os.environ.get("SHOW_ERROR_DETAILS", None)))
get = app.router.get


@get("/")
Expand All @@ -59,11 +57,9 @@ def crash_test():

```

!!! info
BlackSheep project templates use a library to handle application
settings and configuration roots. Consider using
[`essentials-configuration`](https://github.com/Neoteroi/essentials-configuration)
for this.
!!! info "Settings strategy"
BlackSheep project templates include a strategy to handle application
settings and configuration roots.

### Configuring exceptions handlers

Expand All @@ -74,7 +70,7 @@ matching handler for that kind of exception. An exception handler is defined as
a function with the following signature:

```python
from blacksheep import Request, Response
from blacksheep import Request, Response, text

async def exception_handler(self, request: Request, exc: Exception) -> Response:
pass
Expand All @@ -90,24 +86,24 @@ async def exception_handler(self, request, exc: CustomException):
nonlocal app
assert self is app
assert isinstance(exc, CustomException)
return Response(200, content=TextContent('Called'))
return text("Called")


# Register the exception handler for the CustomException type:
app.exceptions_handlers[CustomException] = exception_handler


@app.router.get(b'/')
@get('/')
async def home(request):
# of course, the exception can be risen at any point
# for example in the business logic layer
raise CustomException()

```

Exceptions inheriting from `HTTPException` can be mapped to handlers by their type or by
their status code, using `int` keys; while user defined exceptions are mapped to handlers
by their type.
Exceptions inheriting from `HTTPException` can be mapped to handlers by their
type or by their status code, using `int` keys; while user defined exceptions
are mapped to handlers by their type.

When an exception handler is registered for a type of exception, all subclasses
are also handled by that handler. It is however possible to define a more
Expand Down Expand Up @@ -190,7 +186,7 @@ async def register_http_client():
print("HTTP client disposed")


@app.router.get("/")
@router.get("/")
async def home(http_client: ClientSession):
print(http_client)
return {"ok": True, "client_instance_id": id(http_client)}
Expand Down Expand Up @@ -241,18 +237,21 @@ async def configure_redis():
interface, refer to its [official documentation](https://redis.readthedocs.io/en/stable/examples/asyncio_examples.html).

### on_start

This event should be used to configure things such as new request handlers,
and service registered in `app.services`, such as database connection pools,
HTTP client sessions.

### after_start

This event should be used to configure things that must happen after request
handlers are normalized. At this point, the application router contains information
about actual routes handled by the web application, and routes can be inspected.
For example, the built-in generation of OpenAPI Documentation generates the
API specification file at this point.

### on_stop

This event should be used to fire callbacks that need to happen when the application
is stopped. For example, disposing of services that require disposal, such as
database connection pools, HTTP client sessions using connection pools.
Expand All @@ -270,11 +269,10 @@ are fired, and the state of the application when they are executed.
Event handlers can be registered using decorators.

```python
from blacksheep import Application, Request, Response, text
from blacksheep import Application, Request, Response, text, get


app = Application()
get = app.router.get


@get("/")
Expand Down Expand Up @@ -302,11 +300,10 @@ are fired, and the state of the application when they are executed.
In alternative to decorators, event handlers can be registered using ` += `:

```python
from blacksheep import Application, Request, Response, text
from blacksheep import Application, Request, Response, text, get


app = Application()
get = app.router.get


@get("/")
Expand Down Expand Up @@ -342,4 +339,5 @@ are fired, and the state of the application when they are executed.
```

## Next

Read about the details of [routing in BlackSheep](../routing).
Loading

0 comments on commit 42e426e

Please sign in to comment.