Skip to content

Commit

Permalink
general improvements ✨
Browse files Browse the repository at this point in the history
Uses more features from Material for MkDocs
  • Loading branch information
RobertoPrevato authored Feb 6, 2022
1 parent 76e27e7 commit 88c227f
Show file tree
Hide file tree
Showing 21 changed files with 418 additions and 397 deletions.
130 changes: 63 additions & 67 deletions docs/application.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,11 @@ def crash_test():

```

> **Note:** BlackSheep project templates use a library to handle application
> settings and configuration roots, named [`roconfiguration`](https://github.com/RobertoPrevato/roconfiguration).
!!! 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.

### Configuring exceptions handlers

Expand Down Expand Up @@ -103,9 +106,9 @@ async def home(request):

```

Exceptions inheriting from `HTTPException` are mapped to handlers 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.

### Configuring exception handlers using decorators

Expand All @@ -123,8 +126,6 @@ async def handler_example(self, request, exc: CustomException):

```

> 🚀 New in version 1.0.4
---

## Application events
Expand All @@ -134,19 +135,20 @@ A BlackSheep application exposes three events: **on_start**, **after_start**,

### on_start
This event should be used to configure things such as new request handlers,
service registered in `app.services`.
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 examples, the built-in generation of OpenAPI Documentation generates the
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
DB Connection Pools, HTTP Connection Pools.
database connection pools, HTTP client sessions using connection pools.

### Application life cycle

Expand All @@ -155,92 +157,86 @@ are fired, and the state of the application when they are executed.

![App life cycle](./img/app-life-cycle.svg)

### Application events example
### How to register event handlers

```python
from blacksheep.server import Application
from blacksheep.server.responses import text
from blacksheep.messages import Request, Response
=== "Using decorators"
Event handlers can be registered using decorators.

```python
from blacksheep.server import Application
from blacksheep.server.responses import text
from blacksheep.messages import Request, Response

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

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

@get("/")
async def home(request: Request) -> Response:
return text("Example Async")

@get("/")
async def home(request: Request) -> Response:
return text("Example Async")

async def before_start(application: Application) -> None:
print("Before start")

@app.on_start
async def before_start(application: Application) -> None:
print("Before start")

async def after_start(application: Application) -> None:
print("After start")

@app.after_start
async def after_start(application: Application) -> None:
print("After start")

async def on_stop(application: Application) -> None:
print("On stop")

@app.on_stop
async def on_stop(application: Application) -> None:
print("On stop")

app.on_start += before_start
app.after_start += after_start
app.on_stop += on_stop
```
```

### Application events handled using decorators
=== "Using +="
In alternative to decorators, event handlers can be registered using ` += `:

Since version `1.0.9`, it is also possible to register event handlers using
decorators. The example above rewritten to use decorators looks as follows:
```python
from blacksheep.server import Application
from blacksheep.server.responses import text
from blacksheep.messages import Request, Response

```python
from blacksheep.server import Application
from blacksheep.server.responses import text
from blacksheep.messages import Request, Response

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

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

@get("/")
async def home(request: Request) -> Response:
return text("Example Async")

@get("/")
async def home(request: Request) -> Response:
return text("Example Async")


@app.on_start
async def before_start(application: Application) -> None:
print("Before start")


@app.after_start
async def after_start(application: Application) -> None:
print("After start")

async def before_start(application: Application) -> None:
print("Before start")

@app.on_stop
async def on_stop(application: Application) -> None:
print("On stop")

```

> 🚀 New in version 1.0.9
async def after_start(application: Application) -> None:
print("After start")

### Example: after_start callback to log all routes

To define an `after_start` callback that logs all routes registered in the
application router:
async def on_stop(application: Application) -> None:
print("On stop")

```python

async def after_start_print_routes(application: Application) -> None:
print(application.router.routes)
app.on_start += before_start
app.after_start += after_start
app.on_stop += on_stop
```

!!! info
For example, to define an `after_start` callback that logs all routes registered
in the application router:

app.after_start += after_start_print_routes

```
```python
@app.after_start
async def after_start_print_routes(application: Application) -> None:
print(application.router.routes)
```

## Next
Read about the details of [routing in BlackSheep](../routing).
57 changes: 29 additions & 28 deletions docs/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,9 @@ describes:
* How to use the built-in support for JWT Bearer authentication.
* How to read the user's context in request handlers.

> **Note:** the word "user" is usually used only to refer to human users, while
> the word "service" is used to describe non-human clients. In Java and .NET, a
> common word to describe a generic client is "principal".
> ❗ using JWT Bearer and OpenID integrations requires more dependencies: use
> `pip install blacksheep[full]` to use these features
!!! warning
Using JWT Bearer and OpenID integrations requires more dependencies: use
`pip install blacksheep[full]` to use these features

## Underlying library
The authentication and authorization logic implemented for BlackSheep was
Expand All @@ -34,6 +31,11 @@ Examples of common strategies to identify users in web applications include:
The next paragraphs explain first how to use the built-in support for JWT
Bearer tokens, and how to write a custom authentication handler.

!!! info
The word "user" is usually used only to refer to human users, while
the word "service" is used to describe non-human clients. In Java and .NET, a
common word to describe a generic client is "principal".

## OIDC

BlackSheep implements built-in support for OpenID Connect authentication,
Expand Down Expand Up @@ -145,16 +147,15 @@ def example():

```

> 🚀 New in version 1.2.1
The built-in handler for JWT Bearer authentication does not support JWTs signed
with symmetric keys. Support for symmetric keys might be added in the future,
inside **[guardpost](https://github.com/Neoteroi/guardpost)** library.

> 💡 It is possible to configure several JWTBearerAuthentication handlers,
> for applications that need to support more than one identity provider. For
> example, for applications that need to support sign-in through Auth0, Azure
> Active Directory, Azure Active Directory B2C.
!!! info
💡 It is possible to configure several JWTBearerAuthentication handlers,
for applications that need to support more than one identity provider. For
example, for applications that need to support sign-in through Auth0, Azure
Active Directory, Azure Active Directory B2C.

## Writing a custom authentication handler

Expand Down Expand Up @@ -241,31 +242,31 @@ Kowalski"}

_The application has been started on port 44555 (e.g. `uvicorn server:app --port=44555`)._

## Reading user's context from the request
## Reading user's context
The example below show how the user's identity can be read from the web
request

*Directly from the request:*
=== "Using binders (recommended)"

```python
```python
from guardpost.authentication import Identity

@get("/")
async def for_anybody(request: Request):
user = request.identity
# user can be None or an instance of Identity (set in the authentication
# handler)
```

*Using binders*:
@get("/")
async def for_anybody(user: Optional[Identity]):
...
```

```python
from guardpost.authentication import Identity
=== "Directly from the request"

```python

@get("/")
async def for_anybody(user: Optional[Identity]):
...
```
@get("/")
async def for_anybody(request: Request):
user = request.identity
# user can be None or an instance of Identity (set in the authentication
# handler)
```

## Next
While authentication deals with identifying users, authorization deals with
Expand Down
5 changes: 3 additions & 2 deletions docs/binders.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ Binding happens implicitly when parameters in the request handler's signature
are not annotated with types, or are **not** annotated with types that inherit
from `BoundValue` class, defined in `blacksheep.server.bindings`.

> **Note:** a parameter with name "request" is always bound to the instance of
> the `Request` of the web request.
!!! warning
A parameter with name "request" is always bound to the instance of
the `Request` of the web request.

### Explicit binding
Binders can be defined explicitly, using type annotations and classes from
Expand Down
8 changes: 4 additions & 4 deletions docs/controllers.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ in subclasses of `Controller` and they remove the need to import functions.
| **view_async** | Returns a view rendered asynchronously. |
| **file** | Returns a binary file response with given content type and optional file name, for download (attachment) (default HTTP 200 OK). This method supports both call with bytes, or a generator yielding chunks. |


For information on how to use these methods, refer to the type annotations
provided in the code.

![Type hints](../img/type-hints.png)

> **Note:** using an IDE like JetBrains PyCharm, or Visual Studio Code (as in
> the screenshot above), enables automatic completion and hints thanks to type
> annotations.
!!! info
Using an IDE like JetBrains PyCharm, or Visual Studio Code (as in
the screenshot above), enables automatic completion and hints thanks to type
annotations.

### on_request and on_response

Expand Down
2 changes: 1 addition & 1 deletion docs/css/extra.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
background-color: #333;
}

.p + .n, .o + .n {
.p + .n, .o + .n, .highlight .kc, .highlight .n {
color: deeppink;
}

Expand Down
2 changes: 0 additions & 2 deletions docs/dataprotection.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ This page documents:
* How to handle secrets
* Examples use of data protection

> 🚀 New in version 1.2.1
## How to handle secrets

Symmetric encryption is used to sign and encrypt information in several
Expand Down
Loading

0 comments on commit 88c227f

Please sign in to comment.