mirror of
https://github.com/fastapi/fastapi.git
synced 2025-12-25 07:08:11 -05:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
025b38df40 | ||
|
|
ac60cba75f | ||
|
|
94ee932351 | ||
|
|
cf760d6802 | ||
|
|
c65fdc4bed | ||
|
|
0ac9b3ee5c | ||
|
|
f2bd2c44e2 | ||
|
|
f0beab1778 | ||
|
|
95f2dc065e | ||
|
|
4e8080f290 | ||
|
|
fbbed6fe81 | ||
|
|
2d5a5d0d9e |
@@ -398,6 +398,7 @@ Used by Starlette:
|
||||
Used by FastAPI / Starlette:
|
||||
|
||||
* <a href="http://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - for the server that loads and serves your application.
|
||||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
|
||||
|
||||
You can install all of these with `pip install fastapi[all]`.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
By default, **FastAPI** will return the responses using Starlette's `JSONResponse`, putting the content you return from your *path operation* inside of that `JSONResponse`.
|
||||
By default, **FastAPI** will return the responses using a `JSONResponse`, putting the content you return from your *path operation* inside of that `JSONResponse`.
|
||||
|
||||
It will use the default status code or the one you set in your *path operation*.
|
||||
|
||||
@@ -12,7 +12,7 @@ But you also want it to accept new items. And when the items didn't exist before
|
||||
|
||||
To achieve that, import `JSONResponse`, and return your content there directly, setting the `status_code` that you want:
|
||||
|
||||
```Python hl_lines="2 20"
|
||||
```Python hl_lines="2 19"
|
||||
{!./src/additional_status_codes/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -23,8 +23,13 @@ To achieve that, import `JSONResponse`, and return your content there directly,
|
||||
|
||||
Make sure it has the data you want it to have, and that the values are valid JSON (if you are using `JSONResponse`).
|
||||
|
||||
!!! note "Technical Details"
|
||||
You could also use `from starlette.responses import JSONResponse`.
|
||||
|
||||
**FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette. The same with `status`.
|
||||
|
||||
## OpenAPI and API docs
|
||||
|
||||
If you return additional status codes and responses directly, they won't be included in the OpenAPI schema (the API docs), because FastAPI doesn't have a way to know before hand what you are going to return.
|
||||
If you return additional status codes and responses directly, they won't be included in the OpenAPI schema (the API docs), because FastAPI doesn't have a way to know beforehand what you are going to return.
|
||||
|
||||
But you can document that in your code, using: [Additional Responses](additional-responses.md){.internal-link target=_blank}.
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
!!! warning
|
||||
This is, more or less, an "advanced" chapter.
|
||||
|
||||
If you are just starting with **FastAPI** you might want to skip this chapter and come back to it later.
|
||||
|
||||
## Parameterized dependencies
|
||||
|
||||
All the dependencies we have seen are a fixed function or class.
|
||||
|
||||
@@ -25,13 +25,16 @@ And an `APIRoute` subclass to use that custom request class.
|
||||
|
||||
### Create a custom `GzipRequest` class
|
||||
|
||||
!!! tip
|
||||
This is a toy example to demonstrate how it works, if you need Gzip support, you can use the provided [`GzipMiddleware`](./middleware.md#gzipmiddleware){.internal-link target=_blank}.
|
||||
|
||||
First, we create a `GzipRequest` class, which will overwrite the `Request.body()` method to decompress the body in the presence of an appropriate header.
|
||||
|
||||
If there's no `gzip` in the header, it will not try to decompress the body.
|
||||
|
||||
That way, the same route class can handle gzip compressed or uncompressed requests.
|
||||
|
||||
```Python hl_lines="10 11 12 13 14 15 16 17"
|
||||
```Python hl_lines="8 9 10 11 12 13 14 15"
|
||||
{!./src/custom_request_and_route/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -45,7 +48,7 @@ This method returns a function. And that function is what will receive a request
|
||||
|
||||
Here we use it to create a `GzipRequest` from the original request.
|
||||
|
||||
```Python hl_lines="20 21 22 23 24 25 26 27 28"
|
||||
```Python hl_lines="18 19 20 21 22 23 24 25 26"
|
||||
{!./src/custom_request_and_route/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -79,13 +82,13 @@ We can also use this same approach to access the request body in an exception ha
|
||||
|
||||
All we need to do is handle the request inside a `try`/`except` block:
|
||||
|
||||
```Python hl_lines="15 17"
|
||||
```Python hl_lines="13 15"
|
||||
{!./src/custom_request_and_route/tutorial002.py!}
|
||||
```
|
||||
|
||||
If an exception occurs, the`Request` instance will still be in scope, so we can read and make use of the request body when handling the error:
|
||||
|
||||
```Python hl_lines="18 19 20"
|
||||
```Python hl_lines="16 17 18"
|
||||
{!./src/custom_request_and_route/tutorial002.py!}
|
||||
```
|
||||
|
||||
@@ -93,12 +96,12 @@ If an exception occurs, the`Request` instance will still be in scope, so we can
|
||||
|
||||
You can also set the `route_class` parameter of an `APIRouter`:
|
||||
|
||||
```Python hl_lines="28"
|
||||
```Python hl_lines="26"
|
||||
{!./src/custom_request_and_route/tutorial003.py!}
|
||||
```
|
||||
|
||||
In this example, the *path operations* under the `router` will use the custom `TimedRoute` class, and will have an extra `X-Response-Time` header in the response with the time it took to generate the response:
|
||||
|
||||
```Python hl_lines="15 16 17 18 19 20 21 22"
|
||||
```Python hl_lines="13 14 15 16 17 18 19 20"
|
||||
{!./src/custom_request_and_route/tutorial003.py!}
|
||||
```
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
!!! warning
|
||||
This is a rather advanced topic.
|
||||
|
||||
If you are starting with **FastAPI**, you might not need this.
|
||||
|
||||
By default, **FastAPI** will return the responses using Starlette's `JSONResponse`.
|
||||
By default, **FastAPI** will return the responses using `JSONResponse`.
|
||||
|
||||
You can override it by returning a `Response` directly as seen in [Return a Response directly](response-directly.md){.internal-link target=_blank}.
|
||||
|
||||
But if you return a `Response` directly, the data won't be automatically converted, and the documentation won't be automatically generated (for example, including the specific "media type", in the HTTP header `Content-Type`).
|
||||
But if you return a `Response` directly, the data won't be automatically converted, and the documentation won't be automatically generated (for example, including the specific "media type", in the HTTP header `Content-Type` as part of the generated OpenAPI).
|
||||
|
||||
But you can also declare the `Response` that you want to be used, in the *path operation decorator*.
|
||||
|
||||
@@ -18,19 +13,16 @@ And if that `Response` has a JSON media type (`application/json`), like is the c
|
||||
!!! note
|
||||
If you use a response class with no media type, FastAPI will expect your response to have no content, so it will not document the response format in its generated OpenAPI docs.
|
||||
|
||||
## Use `UJSONResponse`
|
||||
## Use `ORJSONResponse`
|
||||
|
||||
For example, if you are squeezing performance, you can install and use `ujson` and set the response to be Starlette's `UJSONResponse`.
|
||||
For example, if you are squeezing performance, you can install and use <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a> and set the response to be `ORJSONResponse`.
|
||||
|
||||
Import the `Response` class (sub-class) you want to use and declare it in the *path operation decorator*.
|
||||
|
||||
```Python hl_lines="2 7"
|
||||
{!./src/custom_response/tutorial001.py!}
|
||||
{!./src/custom_response/tutorial001b.py!}
|
||||
```
|
||||
|
||||
!!! note
|
||||
Notice that you import it directly from `starlette.responses`, not from `fastapi`.
|
||||
|
||||
!!! info
|
||||
The parameter `response_class` will also be used to define the "media type" of the response.
|
||||
|
||||
@@ -38,6 +30,9 @@ Import the `Response` class (sub-class) you want to use and declare it in the *p
|
||||
|
||||
And it will be documented as such in OpenAPI.
|
||||
|
||||
!!! tip
|
||||
The `ORJSONResponse` is currently only available in FastAPI, not in Starlette.
|
||||
|
||||
## HTML Response
|
||||
|
||||
To return a response with HTML directly from **FastAPI**, use `HTMLResponse`.
|
||||
@@ -49,9 +44,6 @@ To return a response with HTML directly from **FastAPI**, use `HTMLResponse`.
|
||||
{!./src/custom_response/tutorial002.py!}
|
||||
```
|
||||
|
||||
!!! note
|
||||
Notice that you import it directly from `starlette.responses`, not from `fastapi`.
|
||||
|
||||
!!! info
|
||||
The parameter `response_class` will also be used to define the "media type" of the response.
|
||||
|
||||
@@ -59,7 +51,7 @@ To return a response with HTML directly from **FastAPI**, use `HTMLResponse`.
|
||||
|
||||
And it will be documented as such in OpenAPI.
|
||||
|
||||
### Return a Starlette `Response`
|
||||
### Return a `Response`
|
||||
|
||||
As seen in [Return a Response directly](response-directly.md){.internal-link target=_blank}, you can also override the response directly in your *path operation*, by returning it.
|
||||
|
||||
@@ -89,14 +81,126 @@ For example, it could be something like:
|
||||
{!./src/custom_response/tutorial004.py!}
|
||||
```
|
||||
|
||||
In this example, the function `generate_html_response()` already generates a Starlette `Response` instead of the HTML in a `str`.
|
||||
In this example, the function `generate_html_response()` already generates and returns a `Response` instead of returning the HTML in a `str`.
|
||||
|
||||
By returning the result of calling `generate_html_response()`, you are already returning a `Response` that will override the default **FastAPI** behavior.
|
||||
|
||||
But as you passed the `HTMLResponse` in the `response_class`, **FastAPI** will know how to document it in OpenAPI and the interactive docs as HTML with `text/html`:
|
||||
But as you passed the `HTMLResponse` in the `response_class` too, **FastAPI** will know how to document it in OpenAPI and the interactive docs as HTML with `text/html`:
|
||||
|
||||
<img src="/img/tutorial/custom-response/image01.png">
|
||||
|
||||
## Available responses
|
||||
|
||||
Here are some of the available responses.
|
||||
|
||||
Have in mind that you can use `Response` to return anything else, or even create a custom sub-class.
|
||||
|
||||
!!! note "Technical Details"
|
||||
You could also use `from starlette.responses import HTMLResponse`.
|
||||
|
||||
**FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
|
||||
|
||||
### `Response`
|
||||
|
||||
The main `Response` class, all the other responses inherit from it.
|
||||
|
||||
You can return it directly.
|
||||
|
||||
It accepts the following parameters:
|
||||
|
||||
* `content` - A `str` or `bytes`.
|
||||
* `status_code` - An `int` HTTP status code.
|
||||
* `headers` - A `dict` of strings.
|
||||
* `media_type` - A `str` giving the media type. E.g. `"text/html"`.
|
||||
|
||||
FastAPI (actually Starlette) will automatically include a Content-Length header. It will also include a Content-Type header, based on the media_type and appending a charset for text types.
|
||||
|
||||
```Python hl_lines="1 18"
|
||||
{!./src/response_directly/tutorial002.py!}
|
||||
```
|
||||
|
||||
### `HTMLResponse`
|
||||
|
||||
Takes some text or bytes and returns an HTML response, as you read above.
|
||||
|
||||
### `PlainTextResponse`
|
||||
|
||||
Takes some text or bytes and returns an plain text response.
|
||||
|
||||
```Python hl_lines="2 7 9"
|
||||
{!./src/custom_response/tutorial005.py!}
|
||||
```
|
||||
|
||||
### `JSONResponse`
|
||||
|
||||
Takes some data and returns an `application/json` encoded response.
|
||||
|
||||
This is the default response used in **FastAPI**, as you read above.
|
||||
|
||||
### `ORJSONResponse`
|
||||
|
||||
A fast alternative JSON response using <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a>, as you read above.
|
||||
|
||||
### `UJSONResponse`
|
||||
|
||||
An alternative JSON response using <a href="https://github.com/ultrajson/ultrajson" class="external-link" target="_blank">`ujson`</a>.
|
||||
|
||||
!!! warning
|
||||
`ujson` is less careful than Python's built-in implementation in how it handles some edge-cases.
|
||||
|
||||
```Python hl_lines="2 7"
|
||||
{!./src/custom_response/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
It's possible that `ORJSONResponse` might be a faster alternative.
|
||||
|
||||
### `RedirectResponse`
|
||||
|
||||
Returns an HTTP redirect. Uses a 307 status code (Temporary Redirect) by default.
|
||||
|
||||
```Python hl_lines="2 9"
|
||||
{!./src/custom_response/tutorial006.py!}
|
||||
```
|
||||
|
||||
### `StreamingResponse`
|
||||
|
||||
Takes an async generator or a normal generator/iterator and streams the response body.
|
||||
|
||||
```Python hl_lines="2 14"
|
||||
{!./src/custom_response/tutorial007.py!}
|
||||
```
|
||||
|
||||
#### Using `StreamingResponse` with file-like objects
|
||||
|
||||
If you have a file-like object (e.g. the object returned by `open()`), you can return it in a `StreamingResponse`.
|
||||
|
||||
This includes many libraries to interact with cloud storage, video processing, and others.
|
||||
|
||||
```Python hl_lines="2 10 11"
|
||||
{!./src/custom_response/tutorial008.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
Notice that here as we are using standard `open()` that doesn't support `async` and `await`, we declare the path operation with normal `def`.
|
||||
|
||||
### `FileResponse`
|
||||
|
||||
Asynchronously streams a file as the response.
|
||||
|
||||
Takes a different set of arguments to instantiate than the other response types:
|
||||
|
||||
* `path` - The filepath to the file to stream.
|
||||
* `headers` - Any custom headers to include, as a dictionary.
|
||||
* `media_type` - A string giving the media type. If unset, the filename or path will be used to infer a media type.
|
||||
* `filename` - If set, this will be included in the response `Content-Disposition`.
|
||||
|
||||
File responses will include appropriate `Content-Length`, `Last-Modified` and `ETag` headers.
|
||||
|
||||
```Python hl_lines="2 10"
|
||||
{!./src/custom_response/tutorial009.py!}
|
||||
```
|
||||
|
||||
## Additional documentation
|
||||
|
||||
You can also declare the media type and many other details in OpenAPI using `responses`: [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}.
|
||||
|
||||
@@ -161,7 +161,7 @@ pip install aiofiles
|
||||
|
||||
### Serve the static files
|
||||
|
||||
* Import `StaticFiles` from Starlette.
|
||||
* Import `StaticFiles`.
|
||||
* "Mount" a `StaticFiles()` instance in a specific path.
|
||||
|
||||
```Python hl_lines="7 11"
|
||||
|
||||
97
docs/advanced/middleware.md
Normal file
97
docs/advanced/middleware.md
Normal file
@@ -0,0 +1,97 @@
|
||||
In the main tutorial you read how to add [Custom Middleware](../tutorial/middleware.md){.internal-link target=_blank} to your application.
|
||||
|
||||
And then you also read how to handle [CORS with the `CORSMiddleware`](../tutorial/cors.md){.internal-link target=_blank}.
|
||||
|
||||
In this section we'll see how to use other middlewares.
|
||||
|
||||
## Adding ASGI middlewares
|
||||
|
||||
As **FastAPI** is based on Starlette and implements the <abbr title="Asynchronous Server Gateway Interface">ASGI</abbr> specification, you can use any ASGI middleware.
|
||||
|
||||
A middleware doesn't have to be made for FastAPI or Starlette to work, as long as it follows the ASGI spec.
|
||||
|
||||
In general, ASGI middlewares are classes that expect to receive an ASGI app as the first argument.
|
||||
|
||||
So, in the documentation for third-party ASGI middlewares they will probably tell you to do something like:
|
||||
|
||||
```Python
|
||||
from unicorn import UnicornMiddleware
|
||||
|
||||
app = SomeASGIApp()
|
||||
|
||||
new_app = UnicornMiddleware(app, some_config="rainbow")
|
||||
```
|
||||
|
||||
But FastAPI (actually Starlette) provides a simpler way to do it that makes sure that the internal middlewares to handle server errors and custom exception handlers work properly.
|
||||
|
||||
For that, you use `app.add_middleware()` (as in the example for CORS).
|
||||
|
||||
```Python
|
||||
from fastapi import FastAPI
|
||||
from unicorn import UnicornMiddleware
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
app.add_middleware(UnicornMiddleware, some_config="rainbow")
|
||||
```
|
||||
|
||||
`app.add_middleware()` receives a middleware class as the first argument and any additional arguments to be passed to the middleware.
|
||||
|
||||
## Integrated middlewares
|
||||
|
||||
**FastAPI** includes several middlewares for common use cases, we'll see next how to use them.
|
||||
|
||||
!!! note "Technical Details"
|
||||
For the next examples, you could also use `from starlette.middleware.something import SomethingMiddleware`.
|
||||
|
||||
**FastAPI** provides several middlewares in `fastapi.middleware` just as a convenience for you, the developer. But most of the available middlewares come directly from Starlette.
|
||||
|
||||
## `HTTPSRedirectMiddleware`
|
||||
|
||||
Enforces that all incoming requests must either be `https` or `wss`.
|
||||
|
||||
Any incoming requests to `http` or `ws` will be redirected to the secure scheme instead.
|
||||
|
||||
```Python hl_lines="2 6"
|
||||
{!./src/advanced_middleware/tutorial001.py!}
|
||||
```
|
||||
|
||||
## `TrustedHostMiddleware`
|
||||
|
||||
Enforces that all incoming requests have a correctly set `Host` header, in order to guard against HTTP Host Header attacks.
|
||||
|
||||
```Python hl_lines="2 6 7 8"
|
||||
{!./src/advanced_middleware/tutorial002.py!}
|
||||
```
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `allowed_hosts` - A list of domain names that should be allowed as hostnames. Wildcard domains such as `*.example.com` are supported for matching subdomains to allow any hostname either use `allowed_hosts=["*"]` or omit the middleware.
|
||||
|
||||
If an incoming request does not validate correctly then a `400` response will be sent.
|
||||
|
||||
## `GZipMiddleware`
|
||||
|
||||
Handles GZip responses for any request that includes `"gzip"` in the `Accept-Encoding` header.
|
||||
|
||||
The middleware will handle both standard and streaming responses.
|
||||
|
||||
```Python hl_lines="2 6 7 8"
|
||||
{!./src/advanced_middleware/tutorial002.py!}
|
||||
```
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `minimum_size` - Do not GZip responses that are smaller than this minimum size in bytes. Defaults to `500`.
|
||||
|
||||
## Other middlewares
|
||||
|
||||
There are many other ASGI middlewares.
|
||||
|
||||
For example:
|
||||
|
||||
* <a href="https://docs.sentry.io/platforms/python/asgi/" class="external-link" target="_blank">Sentry</a>
|
||||
* <a href="https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py" class="external-link" target="_blank">Uvicorn's `ProxyHeadersMiddleware`</a>
|
||||
* <a href="https://github.com/florimondmanca/msgpack-asgi" class="external-link" target="_blank">MessagePack</a>
|
||||
|
||||
To see other available middlewares check <a href="https://www.starlette.io/middleware/" class="external-link" target="_blank">Starlette's Middleware docs</a> and the <a href="https://github.com/florimondmanca/awesome-asgi" class="external-link" target="_blank">ASGI Awesome List</a>.
|
||||
@@ -18,7 +18,7 @@ You can declare a parameter of type `Response` in your *path operation function*
|
||||
|
||||
And then you can set the `status_code` in that *temporal* response object.
|
||||
|
||||
```Python hl_lines="2 11 14"
|
||||
```Python hl_lines="1 9 12"
|
||||
{!./src/response_change_status_code/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
You can declare a parameter of type `Response` in your *path operation function*.
|
||||
|
||||
And then you can set headers in that *temporal* response object.
|
||||
And then you can set cookies in that *temporal* response object.
|
||||
|
||||
```Python hl_lines="2 8 9"
|
||||
```Python hl_lines="1 8 9"
|
||||
{!./src/response_cookies/tutorial002.py!}
|
||||
```
|
||||
|
||||
@@ -37,4 +37,11 @@ Then set Cookies in it, and then return it:
|
||||
|
||||
### More info
|
||||
|
||||
!!! note "Technical Details"
|
||||
You could also use `from starlette.responses import Response` or `from starlette.responses import JSONResponse`.
|
||||
|
||||
**FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
|
||||
|
||||
And as the `Response` can be used frequently to set headers and cookies, **FastAPI** also provides it at `fastapi.Response`.
|
||||
|
||||
To see all the available parameters and options, check the <a href="https://www.starlette.io/responses/#set-cookie" class="external-link" target="_blank">documentation in Starlette</a>.
|
||||
|
||||
@@ -2,20 +2,20 @@ When you create a **FastAPI** *path operation* you can normally return any data
|
||||
|
||||
By default, **FastAPI** would automatically convert that return value to JSON using the `jsonable_encoder` explained in [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}.
|
||||
|
||||
Then, behind the scenes, it would put that JSON-compatible data (e.g. a `dict`) inside of a Starlette `JSONResponse` that would be used to send the response to the client.
|
||||
Then, behind the scenes, it would put that JSON-compatible data (e.g. a `dict`) inside of a `JSONResponse` that would be used to send the response to the client.
|
||||
|
||||
But you can return a `JSONResponse` directly from your *path operations*.
|
||||
|
||||
It might be useful, for example, to return custom headers or cookies.
|
||||
|
||||
## Starlette `Response`
|
||||
## Return a `Response`
|
||||
|
||||
In fact, you can return any <a href="https://www.starlette.io/responses/" class="external-link" target="_blank">Starlette `Response`</a> or any sub-class of it.
|
||||
In fact, you can return any `Response` or any sub-class of it.
|
||||
|
||||
!!! tip
|
||||
`JSONResponse` itself is a sub-class of `Response`.
|
||||
|
||||
And when you return a Starlette `Response`, **FastAPI** will pass it directly.
|
||||
And when you return a `Response`, **FastAPI** will pass it directly.
|
||||
|
||||
It won't do any data conversion with Pydantic models, it won't convert the contents to any type, etc.
|
||||
|
||||
@@ -33,8 +33,10 @@ For those cases, you can use the `jsonable_encoder` to convert your data before
|
||||
{!./src/response_directly/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note
|
||||
Notice that you import it directly from `starlette.responses`, not from `fastapi`.
|
||||
!!! note "Technical Details"
|
||||
You could also use `from starlette.responses import JSONResponse`.
|
||||
|
||||
**FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
|
||||
|
||||
## Returning a custom `Response`
|
||||
|
||||
@@ -42,13 +44,11 @@ The example above shows all the parts you need, but it's not very useful yet, as
|
||||
|
||||
Now, let's see how you could use that to return a custom response.
|
||||
|
||||
Let's say you want to return a response that is not available in the default <a href="https://www.starlette.io/responses/" class="external-link" target="_blank">Starlette `Response`s</a>.
|
||||
Let's say that you want to return an <a href="https://en.wikipedia.org/wiki/XML" class="external-link" target="_blank">XML</a> response.
|
||||
|
||||
Let's say that you want to return <a href="https://en.wikipedia.org/wiki/XML" class="external-link" target="_blank">XML</a>.
|
||||
You could put your XML content in a string, put it in a `Response`, and return it:
|
||||
|
||||
You could put your XML content in a string, put it in a Starlette Response, and return it:
|
||||
|
||||
```Python hl_lines="2 20"
|
||||
```Python hl_lines="1 18"
|
||||
{!./src/response_directly/tutorial002.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ You can declare a parameter of type `Response` in your *path operation function*
|
||||
|
||||
And then you can set headers in that *temporal* response object.
|
||||
|
||||
```Python hl_lines="2 8 9"
|
||||
```Python hl_lines="1 7 8"
|
||||
{!./src/response_headers/tutorial002.py!}
|
||||
```
|
||||
|
||||
@@ -26,6 +26,13 @@ Create a response as described in [Return a Response Directly](response-directly
|
||||
{!./src/response_headers/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note "Technical Details"
|
||||
You could also use `from starlette.responses import Response` or `from starlette.responses import JSONResponse`.
|
||||
|
||||
**FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
|
||||
|
||||
And as the `Response` can be used frequently to set headers and cookies, **FastAPI** also provides it at `fastapi.Response`.
|
||||
|
||||
## Custom Headers
|
||||
|
||||
Have in mind that custom proprietary headers can be added <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">using the 'X-' prefix</a>.
|
||||
|
||||
@@ -34,7 +34,7 @@ Use a dependency to check if the username and password are correct.
|
||||
|
||||
For this, use the Python standard module <a href="https://docs.python.org/3/library/secrets.html" class="external-link" target="_blank">`secrets`</a> to check the username and password:
|
||||
|
||||
```Python hl_lines="1 13 14 15"
|
||||
```Python hl_lines="1 11 12 13"
|
||||
{!./src/security/tutorial007.py!}
|
||||
```
|
||||
|
||||
@@ -100,6 +100,6 @@ That way, using `secrets.compare_digest()` in your application code, it will be
|
||||
|
||||
After detecting that the credentials are incorrect, return an `HTTPException` with a status code 401 (the same returned when no credentials are provided) and add the header `WWW-Authenticate` to make the browser show the login prompt again:
|
||||
|
||||
```Python hl_lines="16 17 18 19 20"
|
||||
```Python hl_lines="15 16 17 18 19"
|
||||
{!./src/security/tutorial007.py!}
|
||||
```
|
||||
|
||||
@@ -54,7 +54,7 @@ They are normally used to declare specific security permissions, for example:
|
||||
|
||||
First, let's quickly see the parts that change from the examples in the main **Tutorial - User Guide** for [OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. Now using OAuth2 scopes:
|
||||
|
||||
```Python hl_lines="2 5 9 13 48 66 107 109 110 111 112 113 114 115 116 117 123 124 125 126 130 131 132 133 134 135 136 141 155"
|
||||
```Python hl_lines="2 5 9 13 47 65 106 108 109 110 111 112 113 114 115 116 122 123 124 125 129 130 131 132 133 134 135 140 154"
|
||||
{!./src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -66,7 +66,7 @@ The first change is that now we are declaring the OAuth2 security scheme with tw
|
||||
|
||||
The `scopes` parameter receives a `dict` with each scope as a key and the description as the value:
|
||||
|
||||
```Python hl_lines="64 65 66 67"
|
||||
```Python hl_lines="63 64 65 66"
|
||||
{!./src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -91,7 +91,7 @@ And we return the scopes as part of the JWT token.
|
||||
|
||||
But in your application, for security, you should make sure you only add the scopes that the user is actually able to have, or the ones you have predefined.
|
||||
|
||||
```Python hl_lines="156"
|
||||
```Python hl_lines="155"
|
||||
{!./src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -116,7 +116,7 @@ In this case, it requires the scope `me` (it could require more than one scope).
|
||||
|
||||
We are doing it here to demonstrate how **FastAPI** handles scopes declared at different levels.
|
||||
|
||||
```Python hl_lines="5 141 168"
|
||||
```Python hl_lines="5 140 167"
|
||||
{!./src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -141,7 +141,7 @@ We also declare a special parameter of type `SecurityScopes`, imported from `fas
|
||||
|
||||
This `SecurityScopes` class is similar to `Request` (`Request` was used to get the request object directly).
|
||||
|
||||
```Python hl_lines="9 107"
|
||||
```Python hl_lines="9 106"
|
||||
{!./src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -157,7 +157,7 @@ We create an `HTTPException` that we can re-use (`raise`) later at several point
|
||||
|
||||
In this exception, we include the scopes required (if any) as a string separated by spaces (using `scope_str`). We put that string containing the scopes in in the `WWW-Authenticate` header (this is part of the spec).
|
||||
|
||||
```Python hl_lines="107 109 110 111 112 113 114 115 116 117"
|
||||
```Python hl_lines="106 108 109 110 111 112 113 114 115 116"
|
||||
{!./src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -175,7 +175,7 @@ Instead of, for example, a `dict`, or something else, as it could break the appl
|
||||
|
||||
We also verify that we have a user with that username, and if not, we raise that same exception we created before.
|
||||
|
||||
```Python hl_lines="48 118 119 120 121 122 123 124 125 126 127 128 129"
|
||||
```Python hl_lines="47 117 118 119 120 121 122 123 124 125 126 127 128"
|
||||
{!./src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -185,7 +185,7 @@ We now verify that all the scopes required, by this dependency and all the depen
|
||||
|
||||
For this, we use `security_scopes.scopes`, that contains a `list` with all these scopes as `str`.
|
||||
|
||||
```Python hl_lines="130 131 132 133 134 135 136"
|
||||
```Python hl_lines="129 130 131 132 133 134 135"
|
||||
{!./src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ You can use any template engine you want with **FastAPI**.
|
||||
|
||||
A common election is Jinja2, the same one used by Flask and other tools.
|
||||
|
||||
Starlette has utilities to configure it easily that you can use directly in your **FastAPI** application.
|
||||
There are utilities to configure it easily that you can use directly in your **FastAPI** application (provided by Starlette).
|
||||
|
||||
## Install dependencies
|
||||
|
||||
@@ -20,18 +20,23 @@ pip install aiofiles
|
||||
|
||||
## Using `Jinja2Templates`
|
||||
|
||||
* Import `Jinja2Templates` form Starlette.
|
||||
* Import `Jinja2Templates`.
|
||||
* Create a `templates` object that you can re-use later.
|
||||
* Declare a `Request` parameter in the *path operation* that will return a template.
|
||||
* Use the `templates` you created to render and return a `TemplateResponse`, passing the `request` as one of the key-value pairs in the Jinja2 "context".
|
||||
|
||||
```Python hl_lines="4 11 15 16"
|
||||
```Python hl_lines="3 10 14 15"
|
||||
{!./src/templates/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note
|
||||
Notice that you have to pass the `request` as part of the key-value pairs in the context for Jinja2. So, you also have to declare it in your *path operation*.
|
||||
|
||||
!!! note "Technical Details"
|
||||
You could also use `from starlette.templating import Jinja2Templates`.
|
||||
|
||||
**FastAPI** provides the same `starlette.templating` as `fastapi.templating` just as a convenience for you, the developer. But most of the available responses come directly from Starlette. The same with `Request` and `StaticFiles`.
|
||||
|
||||
## Writing templates
|
||||
|
||||
Then you can write a template at `templates/item.html` with:
|
||||
|
||||
@@ -15,7 +15,7 @@ But there are situations where you might need to access the `Request` object dir
|
||||
|
||||
As **FastAPI** is actually **Starlette** underneath, with a layer of several tools on top, you can use Starlette's <a href="https://www.starlette.io/requests/" class="external-link" target="_blank">`Request`</a> object directly when you need to.
|
||||
|
||||
It would also mean that if you get data from the `Request` object directly (for example, read the body) it won't be validated, converted or annotated (with OpenAPI, for the automatic documentation) by FastAPI.
|
||||
It would also mean that if you get data from the `Request` object directly (for example, read the body) it won't be validated, converted or documented (with OpenAPI, for the automatic API user interface) by FastAPI.
|
||||
|
||||
Although any other parameter declared normally (for example, the body with a Pydantic model) would still be validated, converted, annotated, etc.
|
||||
|
||||
@@ -27,24 +27,14 @@ Let's imagine you want to get the client's IP address/host inside of your *path
|
||||
|
||||
For that you need to access the request directly.
|
||||
|
||||
### Import the `Request`
|
||||
|
||||
First, import the `Request` class from Starlette:
|
||||
|
||||
```Python hl_lines="2"
|
||||
```Python hl_lines="1 7 8"
|
||||
{!./src/using_request_directly/tutorial001.py!}
|
||||
```
|
||||
|
||||
### Declare the `Request` parameter
|
||||
|
||||
Then declare a *path operation function* parameter with the type being the `Request` class:
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!./src/using_request_directly/tutorial001.py!}
|
||||
```
|
||||
By declaring a *path operation function* parameter with the type being the `Request` **FastAPI** will know to pass the `Request` in that parameter.
|
||||
|
||||
!!! tip
|
||||
Note that in this case, we are declaring a path parameter besides the request parameter.
|
||||
Note that in this case, we are declaring a path parameter beside the request parameter.
|
||||
|
||||
So, the path parameter will be extracted, validated, converted to the specified type and annotated with OpenAPI.
|
||||
|
||||
@@ -53,3 +43,8 @@ Then declare a *path operation function* parameter with the type being the `Requ
|
||||
## `Request` documentation
|
||||
|
||||
You can read more details about the <a href="https://www.starlette.io/requests/" class="external-link" target="_blank">`Request` object in the official Starlette documentation site</a>.
|
||||
|
||||
!!! note "Technical Details"
|
||||
You could also use `from starlette.requests import Request`.
|
||||
|
||||
**FastAPI** provides it directly just as a convenience for you, the developer. But it comes directly from Starlette.
|
||||
|
||||
@@ -23,7 +23,7 @@ In production you would have one of the options above.
|
||||
|
||||
But it's the simplest way to focus on the server-side of WebSockets and have a working example:
|
||||
|
||||
```Python hl_lines="2 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 42 43 44"
|
||||
```Python hl_lines="2 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 41 42 43"
|
||||
{!./src/websockets/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -31,18 +31,20 @@ But it's the simplest way to focus on the server-side of WebSockets and have a w
|
||||
|
||||
In your **FastAPI** application, create a `websocket`:
|
||||
|
||||
```Python hl_lines="3 47 48"
|
||||
```Python hl_lines="1 46 47"
|
||||
{!./src/websockets/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
In this example we are importing `WebSocket` from `starlette.websockets` to use it in the type declaration in the WebSocket route function.
|
||||
!!! note "Technical Details"
|
||||
You could also use `from starlette.websockets import WebSocket`.
|
||||
|
||||
**FastAPI** provides the same `WebSocket` directly just as a convenience for you, the developer. But it comes directly from Starlette.
|
||||
|
||||
## Await for messages and send messages
|
||||
|
||||
In your WebSocket route you can `await` for messages and send messages.
|
||||
|
||||
```Python hl_lines="49 50 51 52 53"
|
||||
```Python hl_lines="48 49 50 51 52"
|
||||
{!./src/websockets/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -61,7 +63,7 @@ In WebSocket endpoints you can import from `fastapi` and use:
|
||||
|
||||
They work the same way as for other FastAPI endpoints/*path operations*:
|
||||
|
||||
```Python hl_lines="55 56 57 58 59 60 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78"
|
||||
```Python hl_lines="53 54 55 56 57 58 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76"
|
||||
{!./src/websockets/tutorial002.py!}
|
||||
```
|
||||
|
||||
@@ -76,7 +78,6 @@ They work the same way as for other FastAPI endpoints/*path operations*:
|
||||
|
||||
To learn more about the options, check Starlette's documentation for:
|
||||
|
||||
* <a href="https://www.starlette.io/applications/" class="external-link" target="_blank">Applications (`websocket_route`)</a>.
|
||||
* <a href="https://www.starlette.io/websockets/" class="external-link" target="_blank">The `WebSocket` class</a>.
|
||||
* <a href="https://www.starlette.io/endpoints/#websocketendpoint" class="external-link" target="_blank">Class-based WebSocket handling</a>.
|
||||
|
||||
|
||||
35
docs/advanced/wsgi.md
Normal file
35
docs/advanced/wsgi.md
Normal file
@@ -0,0 +1,35 @@
|
||||
You can mount WSGI applications as you saw with [Sub Applications - Behind a Proxy, Mounts](./sub-applications-proxy.md){.internal-link target=_blank}.
|
||||
|
||||
For that, you can use the `WSGIMiddleware` and use it to wrap your WSGI application, for example, Flask, Django, etc.
|
||||
|
||||
## Using `WSGIMiddleware`
|
||||
|
||||
You need to import `WSGIMiddleware`.
|
||||
|
||||
Then wrap the WSGI (e.g. Flask) app with the middleware.
|
||||
|
||||
And then mount that under a path.
|
||||
|
||||
```Python hl_lines="1 3 22"
|
||||
{!./src/wsgi/tutorial001.py!}
|
||||
```
|
||||
|
||||
## Check it
|
||||
|
||||
Now, every request under the path `/v1/` will be handled by the Flask application.
|
||||
|
||||
And the rest will be handled by **FastAPI**.
|
||||
|
||||
If you run it with Uvicorn and go to <a href="http://localhost:8000/v1/" class="external-link" target="_blank">http://localhost:8000/v1/</a> you will see the response from Flask:
|
||||
|
||||
```txt
|
||||
Hello, World from Flask!
|
||||
```
|
||||
|
||||
And if you go to <a href="http://localhost:8000/v2" class="external-link" target="_blank">http://localhost:8000/v2</a> you will see the response from FastAPI:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"message": "Hello World"
|
||||
}
|
||||
```
|
||||
@@ -1,4 +1,98 @@
|
||||
You can use <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a> for deployment. It has several advantages like security, replicability, development simplicity, etc.
|
||||
Deploying a **FastAPI** application is relatively easy.
|
||||
|
||||
There are several ways to do it depending on your specific use case and the tools that you use.
|
||||
|
||||
You will see more about some of the ways to do it in the next sections.
|
||||
|
||||
## FastAPI versions
|
||||
|
||||
**FastAPI** is already being used in production in many applications and systems. And the test coverage is kept at 100%. But its development is still moving quickly.
|
||||
|
||||
New features are added frequently, bugs are fixed regularly, and the code is still continuously improving.
|
||||
|
||||
That's why the current versions are still `0.x.x`, this reflects that each version could potentially have breaking changes. This follows the <a href="https://semver.org/" class="external-link" target="_blank">Semantic Versioning</a> conventions.
|
||||
|
||||
You can create production applications with **FastAPI** right now (and you have probably been doing it for some time), you just have to make sure that you use a version that works correctly with the rest of your code.
|
||||
|
||||
### Pin your `fastapi` version
|
||||
|
||||
The first thing you should do is to "pin" the version of **FastAPI** you are using to the specific latest version that you know works correctly for your application.
|
||||
|
||||
For example, let's say you are using version `0.45.0` in your app.
|
||||
|
||||
If you use a `requirements.txt` file you could specify the version with:
|
||||
|
||||
```txt
|
||||
fastapi==0.45.0
|
||||
```
|
||||
|
||||
that would mean that you would use exactly the version `0.45.0`.
|
||||
|
||||
Or you could also pin it with:
|
||||
|
||||
```txt
|
||||
fastapi>=0.45.0,<0.46.0
|
||||
```
|
||||
|
||||
that would mean that you would use the versions `0.45.0` or above, but less than `0.46.0`, for example, a version `0.45.2` would still be accepted.
|
||||
|
||||
If you use any other tool to manage your installations, like Poetry, Pipenv, or others, they all have a way that you can use to define specific versions for your packages.
|
||||
|
||||
### Available versions
|
||||
|
||||
You can see the available versions (e.g. to check what is the current latest) in the [Release Notes](release-notes.md){.internal-link target=_blank}.
|
||||
|
||||
### About versions
|
||||
|
||||
Following the Semantic Versioning conventions, any version below `1.0.0` could potentially add breaking changes.
|
||||
|
||||
FastAPI also follows the convention that any "PATCH" version change is for bug fixes and non-breaking changes.
|
||||
|
||||
!!! tip
|
||||
The "PATCH" is the last number, for example, in `0.2.3`, the PATCH version is `3`.
|
||||
|
||||
So, you should be able to pin to a version like:
|
||||
|
||||
```txt
|
||||
fastapi>=0.45.0,<0.46.0
|
||||
```
|
||||
|
||||
Breaking changes and new features are added in "MINOR" versions.
|
||||
|
||||
!!! tip
|
||||
The "MINOR" is the number in the middle, for example, in `0.2.3`, the MINOR version is `2`.
|
||||
|
||||
### Upgrading the FastAPI versions
|
||||
|
||||
You should add tests for your app.
|
||||
|
||||
With **FastAPI** it's very easy (thanks to Starlette), check the docs: [Testing](tutorial/testing.md){.internal-link target=_blank}
|
||||
|
||||
After you have tests, then you can upgrade the **FastAPI** version to a more recent one, and make sure that all your code is working correctly by running your tests.
|
||||
|
||||
If everything is working, or after you make the necessary changes, and all your tests are passing, then you can pin your `fastapi` to that new recent version.
|
||||
|
||||
### About Starlette
|
||||
|
||||
You shouldn't pin the version of `starlette`.
|
||||
|
||||
Different versions of **FastAPI** will use a specific newer version of Starlette.
|
||||
|
||||
So, you can just let **FastAPI** use the correct Starlette version.
|
||||
|
||||
### About Pydantic
|
||||
|
||||
Pydantic includes the tests for **FastAPI** with its own tests, so new versions of Pydantic (above `1.0.0`) are always compatible with FastAPI.
|
||||
|
||||
You can pin Pydantic to any version above `1.0.0` that works for you and below `2.0.0`.
|
||||
|
||||
For example:
|
||||
|
||||
```txt
|
||||
pydantic>=1.2.0,<2.0.0
|
||||
```
|
||||
|
||||
## Docker
|
||||
|
||||
In this section you'll see instructions and links to guides to know how to:
|
||||
|
||||
@@ -7,11 +101,7 @@ In this section you'll see instructions and links to guides to know how to:
|
||||
* Set up a Docker Swarm mode cluster with automatic HTTPS, even on a simple $5 USD/month server. In about **20 min**.
|
||||
* Generate and deploy a full **FastAPI** application, using your Docker Swarm cluster, with HTTPS, etc. In about **10 min**.
|
||||
|
||||
---
|
||||
|
||||
You can also easily use **FastAPI** in a standard server directly too (without Docker).
|
||||
|
||||
## Docker
|
||||
You can use <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a> for deployment. It has several advantages like security, replicability, development simplicity, etc.
|
||||
|
||||
If you are using Docker, you can use the official Docker image:
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 30 KiB |
@@ -398,6 +398,7 @@ Used by Starlette:
|
||||
Used by FastAPI / Starlette:
|
||||
|
||||
* <a href="http://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - for the server that loads and serves your application.
|
||||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
|
||||
|
||||
You can install all of these with `pip install fastapi[all]`.
|
||||
|
||||
|
||||
@@ -1,5 +1,31 @@
|
||||
## Latest changes
|
||||
|
||||
## 0.52.0
|
||||
|
||||
* Add new high-performance JSON response class using `orjson`. New docs: [Custom Response - HTML, Stream, File, others: `ORJSONResponse`](https://fastapi.tiangolo.com/advanced/custom-response/#use-orjsonresponse). PR [#1065](https://github.com/tiangolo/fastapi/pull/1065).
|
||||
|
||||
## 0.51.0
|
||||
|
||||
* Re-export utils from Starlette:
|
||||
* This allows using things like `from fastapi.responses import JSONResponse` instead of `from starlette.responses import JSONResponse`.
|
||||
* It's mainly syntax sugar, a convenience for developer experience.
|
||||
* Now `Request`, `Response`, `WebSocket`, `status` can be imported directly from `fastapi` as in `from fastapi import Response`. This is because those are frequently used, to use the request directly, to set headers and cookies, to get status codes, etc.
|
||||
* Documentation changes in many places, but new docs and noticeable improvements:
|
||||
* [Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/).
|
||||
* [Advanced Middleware](https://fastapi.tiangolo.com/advanced/middleware/).
|
||||
* [Including WSGI - Flask, Django, others](https://fastapi.tiangolo.com/advanced/wsgi/).
|
||||
* PR [#1064](https://github.com/tiangolo/fastapi/pull/1064).
|
||||
|
||||
## 0.50.0
|
||||
|
||||
* Add link to Release Notes from docs about pinning versions for deployment. PR [#1058](https://github.com/tiangolo/fastapi/pull/1058).
|
||||
* Upgrade code to use the latest version of Starlette, including:
|
||||
* Several bug fixes.
|
||||
* Optional redirects of slashes, with or without ending in `/`.
|
||||
* Events for routers, `"startup"`, and `"shutdown"`.
|
||||
* PR [#1057](https://github.com/tiangolo/fastapi/pull/1057).
|
||||
* Add docs about pinning FastAPI versions for deployment: [Deployment: FastAPI versions](https://fastapi.tiangolo.com/deployment/#fastapi-versions). PR [#1056](https://github.com/tiangolo/fastapi/pull/1056).
|
||||
|
||||
## 0.49.2
|
||||
|
||||
* Fix links in release notes. PR [#1052](https://github.com/tiangolo/fastapi/pull/1052) by [@sattosan](https://github.com/sattosan).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import JSONResponse
|
||||
from pydantic import BaseModel
|
||||
from starlette.responses import JSONResponse
|
||||
|
||||
|
||||
class Item(BaseModel):
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import FileResponse
|
||||
from pydantic import BaseModel
|
||||
from starlette.responses import FileResponse
|
||||
|
||||
|
||||
class Item(BaseModel):
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import JSONResponse
|
||||
from pydantic import BaseModel
|
||||
from starlette.responses import JSONResponse
|
||||
|
||||
|
||||
class Item(BaseModel):
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import FileResponse
|
||||
from pydantic import BaseModel
|
||||
from starlette.responses import FileResponse
|
||||
|
||||
|
||||
class Item(BaseModel):
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from fastapi import Body, FastAPI
|
||||
from starlette.responses import JSONResponse
|
||||
from starlette.status import HTTP_201_CREATED
|
||||
from fastapi import Body, FastAPI, status
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@@ -17,4 +16,4 @@ async def upsert_item(item_id: str, name: str = Body(None), size: int = Body(Non
|
||||
else:
|
||||
item = {"name": name, "size": size}
|
||||
items[item_id] = item
|
||||
return JSONResponse(status_code=HTTP_201_CREATED, content=item)
|
||||
return JSONResponse(status_code=status.HTTP_201_CREATED, content=item)
|
||||
|
||||
11
docs/src/advanced_middleware/tutorial001.py
Normal file
11
docs/src/advanced_middleware/tutorial001.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
app.add_middleware(HTTPSRedirectMiddleware)
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def main():
|
||||
return {"message": "Hello World"}
|
||||
13
docs/src/advanced_middleware/tutorial002.py
Normal file
13
docs/src/advanced_middleware/tutorial002.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.trustedhost import TrustedHostMiddleware
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
app.add_middleware(
|
||||
TrustedHostMiddleware, allowed_hosts=["example.com", "*.example.com"]
|
||||
)
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def main():
|
||||
return {"message": "Hello World"}
|
||||
11
docs/src/advanced_middleware/tutorial003.py
Normal file
11
docs/src/advanced_middleware/tutorial003.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.gzip import GZipMiddleware
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
app.add_middleware(GZipMiddleware, minimum_size=1000)
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def main():
|
||||
return "somebigcontent"
|
||||
@@ -1,4 +1,4 @@
|
||||
from starlette.testclient import TestClient
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from .main import app
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from starlette.testclient import TestClient
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from .main_b import app
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.testclient import TestClient
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.testclient import TestClient
|
||||
from starlette.websockets import WebSocket
|
||||
from fastapi.testclient import TestClient
|
||||
from fastapi.websockets import WebSocket
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.testclient import TestClient
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.middleware.cors import CORSMiddleware
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@@ -17,3 +17,8 @@ app.add_middleware(
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def main():
|
||||
return {"message": "Hello World"}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import gzip
|
||||
from typing import Callable, List
|
||||
|
||||
from fastapi import Body, FastAPI
|
||||
from fastapi import Body, FastAPI, Request, Response
|
||||
from fastapi.routing import APIRoute
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import Response
|
||||
|
||||
|
||||
class GzipRequest(Request):
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
from typing import Callable, List
|
||||
|
||||
from fastapi import Body, FastAPI, HTTPException
|
||||
from fastapi import Body, FastAPI, HTTPException, Request, Response
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from fastapi.routing import APIRoute
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import Response
|
||||
|
||||
|
||||
class ValidationErrorLoggingRoute(APIRoute):
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import time
|
||||
from typing import Callable
|
||||
|
||||
from fastapi import APIRouter, FastAPI
|
||||
from fastapi import APIRouter, FastAPI, Request, Response
|
||||
from fastapi.routing import APIRoute
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import Response
|
||||
|
||||
|
||||
class TimedRoute(APIRoute):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.responses import UJSONResponse
|
||||
from fastapi.responses import UJSONResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
9
docs/src/custom_response/tutorial001b.py
Normal file
9
docs/src/custom_response/tutorial001b.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import ORJSONResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/items/", response_class=ORJSONResponse)
|
||||
async def read_items():
|
||||
return [{"item_id": "Foo"}]
|
||||
@@ -1,5 +1,5 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.responses import HTMLResponse
|
||||
from fastapi.responses import HTMLResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.responses import HTMLResponse
|
||||
from fastapi.responses import HTMLResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.responses import HTMLResponse
|
||||
from fastapi.responses import HTMLResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
9
docs/src/custom_response/tutorial005.py
Normal file
9
docs/src/custom_response/tutorial005.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import PlainTextResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/", response_class=PlainTextResponse)
|
||||
async def main():
|
||||
return "Hello World"
|
||||
9
docs/src/custom_response/tutorial006.py
Normal file
9
docs/src/custom_response/tutorial006.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import RedirectResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/typer")
|
||||
async def read_typer():
|
||||
return RedirectResponse("https://typer.tiangolo.com")
|
||||
14
docs/src/custom_response/tutorial007.py
Normal file
14
docs/src/custom_response/tutorial007.py
Normal file
@@ -0,0 +1,14 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import StreamingResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
async def fake_video_streamer():
|
||||
for i in range(10):
|
||||
yield b"some fake video bytes"
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def main():
|
||||
return StreamingResponse(fake_video_streamer())
|
||||
11
docs/src/custom_response/tutorial008.py
Normal file
11
docs/src/custom_response/tutorial008.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import StreamingResponse
|
||||
|
||||
some_file_path = "large-video-file.mp4"
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def main():
|
||||
file_like = open(some_file_path, mode="rb")
|
||||
return StreamingResponse(file_like, media_type="video/mp4")
|
||||
10
docs/src/custom_response/tutorial009.py
Normal file
10
docs/src/custom_response/tutorial009.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import FileResponse
|
||||
|
||||
some_file_path = "large-video-file.mp4"
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def main():
|
||||
return FileResponse(some_file_path)
|
||||
@@ -1,5 +1,5 @@
|
||||
from fastapi import Depends, FastAPI
|
||||
from starlette.testclient import TestClient
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ from fastapi.openapi.docs import (
|
||||
get_swagger_ui_html,
|
||||
get_swagger_ui_oauth2_redirect_html,
|
||||
)
|
||||
from starlette.staticfiles import StaticFiles
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
app = FastAPI(docs_url=None, redoc_url=None)
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import JSONResponse
|
||||
from fastapi import FastAPI, Request
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
|
||||
class UnicornException(Exception):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from fastapi.responses import PlainTextResponse
|
||||
from starlette.exceptions import HTTPException as StarletteHTTPException
|
||||
from starlette.responses import PlainTextResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi import FastAPI, Request, status
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from fastapi.responses import JSONResponse
|
||||
from pydantic import BaseModel
|
||||
from starlette import status
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import JSONResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import time
|
||||
|
||||
from fastapi import FastAPI
|
||||
from starlette.requests import Request
|
||||
from fastapi import FastAPI, Request
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from fastapi import APIRouter, FastAPI
|
||||
from fastapi.responses import JSONResponse
|
||||
from pydantic import BaseModel, HttpUrl
|
||||
from starlette.responses import JSONResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
from typing import Set
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi import FastAPI, status
|
||||
from pydantic import BaseModel
|
||||
from starlette.status import HTTP_201_CREATED
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@@ -15,6 +14,6 @@ class Item(BaseModel):
|
||||
tags: Set[str] = []
|
||||
|
||||
|
||||
@app.post("/items/", response_model=Item, status_code=HTTP_201_CREATED)
|
||||
@app.post("/items/", response_model=Item, status_code=status.HTTP_201_CREATED)
|
||||
async def create_item(*, item: Item):
|
||||
return item
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from typing import List
|
||||
|
||||
from fastapi import FastAPI, File, UploadFile
|
||||
from starlette.responses import HTMLResponse
|
||||
from fastapi.responses import HTMLResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.responses import Response
|
||||
from starlette.status import HTTP_201_CREATED
|
||||
from fastapi import FastAPI, Response, status
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@@ -11,5 +9,5 @@ tasks = {"foo": "Listen to the Bar Fighters"}
|
||||
def get_or_create_task(task_id: str, response: Response):
|
||||
if task_id not in tasks:
|
||||
tasks[task_id] = "This didn't exist before"
|
||||
response.status_code = HTTP_201_CREATED
|
||||
response.status_code = status.HTTP_201_CREATED
|
||||
return tasks[task_id]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.responses import JSONResponse
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.responses import Response
|
||||
from fastapi import FastAPI, Response
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ from datetime import datetime
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.responses import JSONResponse
|
||||
from pydantic import BaseModel
|
||||
from starlette.responses import JSONResponse
|
||||
|
||||
|
||||
class Item(BaseModel):
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.responses import Response
|
||||
from fastapi import FastAPI, Response
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.responses import JSONResponse
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.responses import Response
|
||||
from fastapi import FastAPI, Response
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.status import HTTP_201_CREATED
|
||||
from fastapi import FastAPI, status
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.post("/items/", status_code=HTTP_201_CREATED)
|
||||
@app.post("/items/", status_code=status.HTTP_201_CREATED)
|
||||
async def create_item(name: str):
|
||||
return {"name": name}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from fastapi import Depends, FastAPI, HTTPException
|
||||
from fastapi import Depends, FastAPI, HTTPException, status
|
||||
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
||||
from pydantic import BaseModel
|
||||
from starlette.status import HTTP_401_UNAUTHORIZED
|
||||
|
||||
fake_users_db = {
|
||||
"johndoe": {
|
||||
@@ -58,7 +57,7 @@ async def get_current_user(token: str = Depends(oauth2_scheme)):
|
||||
user = fake_decode_token(token)
|
||||
if not user:
|
||||
raise HTTPException(
|
||||
status_code=HTTP_401_UNAUTHORIZED,
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Invalid authentication credentials",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import jwt
|
||||
from fastapi import Depends, FastAPI, HTTPException
|
||||
from fastapi import Depends, FastAPI, HTTPException, status
|
||||
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
||||
from jwt import PyJWTError
|
||||
from passlib.context import CryptContext
|
||||
from pydantic import BaseModel
|
||||
from starlette.status import HTTP_401_UNAUTHORIZED
|
||||
|
||||
# to get a string like this run:
|
||||
# openssl rand -hex 32
|
||||
@@ -89,7 +88,7 @@ def create_access_token(*, data: dict, expires_delta: timedelta = None):
|
||||
|
||||
async def get_current_user(token: str = Depends(oauth2_scheme)):
|
||||
credentials_exception = HTTPException(
|
||||
status_code=HTTP_401_UNAUTHORIZED,
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Could not validate credentials",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
@@ -118,7 +117,7 @@ async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends(
|
||||
user = authenticate_user(fake_users_db, form_data.username, form_data.password)
|
||||
if not user:
|
||||
raise HTTPException(
|
||||
status_code=HTTP_401_UNAUTHORIZED,
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Incorrect username or password",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@ from datetime import datetime, timedelta
|
||||
from typing import List
|
||||
|
||||
import jwt
|
||||
from fastapi import Depends, FastAPI, HTTPException, Security
|
||||
from fastapi import Depends, FastAPI, HTTPException, Security, status
|
||||
from fastapi.security import (
|
||||
OAuth2PasswordBearer,
|
||||
OAuth2PasswordRequestForm,
|
||||
@@ -11,7 +11,6 @@ from fastapi.security import (
|
||||
from jwt import PyJWTError
|
||||
from passlib.context import CryptContext
|
||||
from pydantic import BaseModel, ValidationError
|
||||
from starlette.status import HTTP_401_UNAUTHORIZED
|
||||
|
||||
# to get a string like this run:
|
||||
# openssl rand -hex 32
|
||||
@@ -111,7 +110,7 @@ async def get_current_user(
|
||||
else:
|
||||
authenticate_value = f"Bearer"
|
||||
credentials_exception = HTTPException(
|
||||
status_code=HTTP_401_UNAUTHORIZED,
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Could not validate credentials",
|
||||
headers={"WWW-Authenticate": authenticate_value},
|
||||
)
|
||||
@@ -130,7 +129,7 @@ async def get_current_user(
|
||||
for scope in security_scopes.scopes:
|
||||
if scope not in token_data.scopes:
|
||||
raise HTTPException(
|
||||
status_code=HTTP_401_UNAUTHORIZED,
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Not enough permissions",
|
||||
headers={"WWW-Authenticate": authenticate_value},
|
||||
)
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import secrets
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException
|
||||
from fastapi import Depends, FastAPI, HTTPException, status
|
||||
from fastapi.security import HTTPBasic, HTTPBasicCredentials
|
||||
from starlette.status import HTTP_401_UNAUTHORIZED
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@@ -14,7 +13,7 @@ def get_current_username(credentials: HTTPBasicCredentials = Depends(security)):
|
||||
correct_password = secrets.compare_digest(credentials.password, "swordfish")
|
||||
if not (correct_username and correct_password):
|
||||
raise HTTPException(
|
||||
status_code=HTTP_401_UNAUTHORIZED,
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Incorrect email or password",
|
||||
headers={"WWW-Authenticate": "Basic"},
|
||||
)
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
from typing import List
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException
|
||||
from fastapi import Depends, FastAPI, HTTPException, Request, Response
|
||||
from sqlalchemy.orm import Session
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import Response
|
||||
|
||||
from . import crud, models, schemas
|
||||
from .database import SessionLocal, engine
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.staticfiles import StaticFiles
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.requests import Request
|
||||
from starlette.staticfiles import StaticFiles
|
||||
from starlette.templating import Jinja2Templates
|
||||
from fastapi import FastAPI, Request
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.templating import Jinja2Templates
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.requests import Request
|
||||
from fastapi import FastAPI, Request
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.responses import HTMLResponse
|
||||
from starlette.websockets import WebSocket
|
||||
from fastapi import FastAPI, WebSocket
|
||||
from fastapi.responses import HTMLResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
from fastapi import Cookie, Depends, FastAPI, Header
|
||||
from starlette.responses import HTMLResponse
|
||||
from starlette.status import WS_1008_POLICY_VIOLATION
|
||||
from starlette.websockets import WebSocket
|
||||
from fastapi import Cookie, Depends, FastAPI, Header, WebSocket, status
|
||||
from fastapi.responses import HTMLResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@@ -56,7 +54,7 @@ async def get_cookie_or_client(
|
||||
websocket: WebSocket, session: str = Cookie(None), x_client: str = Header(None)
|
||||
):
|
||||
if session is None and x_client is None:
|
||||
await websocket.close(code=WS_1008_POLICY_VIOLATION)
|
||||
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
|
||||
return session or x_client
|
||||
|
||||
|
||||
|
||||
22
docs/src/wsgi/tutorial001.py
Normal file
22
docs/src/wsgi/tutorial001.py
Normal file
@@ -0,0 +1,22 @@
|
||||
from flask import Flask, escape, request
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.wsgi import WSGIMiddleware
|
||||
|
||||
flask_app = Flask(__name__)
|
||||
|
||||
|
||||
@flask_app.route("/")
|
||||
def flask_main():
|
||||
name = request.args.get("name", "World")
|
||||
return f"Hello, {escape(name)} from Flask!"
|
||||
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/v2")
|
||||
def read_main():
|
||||
return {"message": "Hello World"}
|
||||
|
||||
|
||||
app.mount("/v1", WSGIMiddleware(flask_app))
|
||||
@@ -32,9 +32,9 @@ So, for everything to work correctly, it's better to specify explicitly the allo
|
||||
|
||||
## Use `CORSMiddleware`
|
||||
|
||||
You can configure it in your **FastAPI** application using Starlette's <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">`CORSMiddleware`</a>.
|
||||
You can configure it in your **FastAPI** application using the `CORSMiddleware`.
|
||||
|
||||
* Import it from Starlette.
|
||||
* Import `CORSMiddleware`.
|
||||
* Create a list of allowed origins (as strings).
|
||||
* Add it as a "middleware" to your **FastAPI** application.
|
||||
|
||||
@@ -44,12 +44,39 @@ You can also specify if your backend allows:
|
||||
* Specific HTTP methods (`POST`, `PUT`) or all of them with the wildcard `"*"`.
|
||||
* Specific HTTP headers or all of them with the wildcard `"*"`.
|
||||
|
||||
```Python hl_lines="2 6 7 8 9 10 11 13 14 15 16 17 18 19"
|
||||
```Python hl_lines="2 6 7 8 9 10 11 13 14 15 16 17 18 19"
|
||||
{!./src/cors/tutorial001.py!}
|
||||
```
|
||||
|
||||
The default parameters used by the `CORSMiddleware` implementation are restrictive by default, so you'll need to explicitly enable particular origins, methods, or headers, in order for browsers to be permitted to use them in a Cross-Domain context.
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `allow_origins` - A list of origins that should be permitted to make cross-origin requests. E.g. `['https://example.org', 'https://www.example.org']`. You can use `['*']` to allow any origin.
|
||||
* `allow_origin_regex` - A regex string to match against origins that should be permitted to make cross-origin requests. eg. `'https://.*\.example\.org'`.
|
||||
* `allow_methods` - A list of HTTP methods that should be allowed for cross-origin requests. Defaults to `['GET']`. You can use `['*']` to allow all standard methods.
|
||||
* `allow_headers` - A list of HTTP request headers that should be supported for cross-origin requests. Defaults to `[]`. You can use `['*']` to allow all headers. The `Accept`, `Accept-Language`, `Content-Language` and `Content-Type` headers are always allowed for CORS requests.
|
||||
* `allow_credentials` - Indicate that cookies should be supported for cross-origin requests. Defaults to `False`.
|
||||
* `expose_headers` - Indicate any response headers that should be made accessible to the browser. Defaults to `[]`.
|
||||
* `max_age` - Sets a maximum time in seconds for browsers to cache CORS responses. Defaults to `60`.
|
||||
|
||||
The middleware responds to two particular types of HTTP request...
|
||||
|
||||
### CORS preflight requests
|
||||
|
||||
These are any `OPTIONS` request with `Origin` and `Access-Control-Request-Method` headers.
|
||||
|
||||
In this case the middleware will intercept the incoming request and respond with appropriate CORS headers, and either a `200` or `400` response for informational purposes.
|
||||
|
||||
### Simple requests
|
||||
|
||||
Any request with an `Origin` header. In this case the middleware will pass the request through as normal, but will include appropriate CORS headers on the response.
|
||||
|
||||
## More info
|
||||
|
||||
For more details of what you can specify in `CORSMiddleware`, check <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette's `CORSMiddleware` docs</a>.
|
||||
|
||||
For more info about <abbr title="Cross-Origin Resource Sharing">CORS</abbr>, check the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">Mozilla CORS documentation</a>.
|
||||
|
||||
!!! note "Technical Details"
|
||||
You could also use `from starlette.middleware.cors import CORSMiddleware`.
|
||||
|
||||
**FastAPI** provides several middlewares in `fastapi.middleware` just as a convenience for you, the developer. But most of the available middlewares come directly from Starlette.
|
||||
|
||||
@@ -90,7 +90,7 @@ And you want to handle this exception globally with FastAPI.
|
||||
|
||||
You could add a custom exception handler with `@app.exception_handler()`:
|
||||
|
||||
```Python hl_lines="6 7 8 14 15 16 17 18 24"
|
||||
```Python hl_lines="5 6 7 13 14 15 16 17 18 24"
|
||||
{!./src/handling_errors/tutorial003.py!}
|
||||
```
|
||||
|
||||
@@ -104,6 +104,11 @@ So, you will receive a clean error, with an HTTP status code of `418` and a JSON
|
||||
{"message": "Oops! yolo did something. There goes a rainbow..."}
|
||||
```
|
||||
|
||||
!!! note "Technical Details"
|
||||
You could also use `from starlette.requests import Request` and `from starlette.responses import JSONResponse`.
|
||||
|
||||
**FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette. The same with `Request`.
|
||||
|
||||
## Override the default exception handlers
|
||||
|
||||
**FastAPI** has some default exception handlers.
|
||||
@@ -172,17 +177,22 @@ The same way, you can override the `HTTPException` handler.
|
||||
|
||||
For example, you could want to return a plain text response instead of JSON for these errors:
|
||||
|
||||
```Python hl_lines="1 3 9 10 11 22"
|
||||
```Python hl_lines="3 4 9 10 11 22"
|
||||
{!./src/handling_errors/tutorial004.py!}
|
||||
```
|
||||
|
||||
!!! note "Technical Details"
|
||||
You could also use `from starlette.responses import PlainTextResponse`.
|
||||
|
||||
**FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
|
||||
|
||||
### Use the `RequestValidationError` body
|
||||
|
||||
The `RequestValidationError` contains the `body` it received with invalid data.
|
||||
|
||||
You could use it while developing your app to log the body and debug it, return it to the user, etc.
|
||||
|
||||
```Python hl_lines="16"
|
||||
```Python hl_lines="14"
|
||||
{!./src/handling_errors/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -231,7 +241,7 @@ So, you can keep raising **FastAPI**'s `HTTPException` as normally in your code.
|
||||
|
||||
But when you register an exception handler, you should register it for Starlette's `HTTPException`.
|
||||
|
||||
This way, if any part of Starlette's internal code, or a Starlette extension or plug-in, raises an `HTTPException`, your handler will be able to catch and handle it.
|
||||
This way, if any part of Starlette's internal code, or a Starlette extension or plug-in, raises a Starlette `HTTPException`, your handler will be able to catch and handle it.
|
||||
|
||||
In this example, to be able to have both `HTTPException`s in the same code, Starlette's exceptions is renamed to `StarletteHTTPException`:
|
||||
|
||||
|
||||
@@ -9,6 +9,11 @@ A "middleware" is a function that works with every **request** before it is proc
|
||||
* It can do something to that **response** or run any needed code.
|
||||
* Then it returns the **response**.
|
||||
|
||||
!!! note "Technical Details"
|
||||
If you have dependencies with `yield`, the exit code will run *after* the middleware.
|
||||
|
||||
If there were any background tasks (documented later), they will run *after* all the middleware.
|
||||
|
||||
## Create a middleware
|
||||
|
||||
To create a middleware you use the decorator `@app.middleware("http")` on top of a function.
|
||||
@@ -21,7 +26,7 @@ The middleware function receives:
|
||||
* Then it returns the `response` generated by the corresponding *path operation*.
|
||||
* You can then modify further the `response` before returning it.
|
||||
|
||||
```Python hl_lines="9 10 12 15"
|
||||
```Python hl_lines="8 9 11 14"
|
||||
{!./src/middleware/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -30,6 +35,11 @@ The middleware function receives:
|
||||
|
||||
But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) using the parameter `expose_headers` documented in <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette's CORS docs</a>.
|
||||
|
||||
!!! note "Technical Details"
|
||||
You could also use `from starlette.requests import Request`.
|
||||
|
||||
**FastAPI** provides it as a convenience for you, the developer. But it comes directly from Starlette.
|
||||
|
||||
### Before and after the `response`
|
||||
|
||||
You can add code to be run with the `request`, before any *path operation* receives it.
|
||||
@@ -38,19 +48,12 @@ And also after the `response` is generated, before returning it.
|
||||
|
||||
For example, you could add a custom header `X-Process-Time` containing the time in seconds that it took to process the request and generate a response:
|
||||
|
||||
```Python hl_lines="11 13 14"
|
||||
```Python hl_lines="10 12 13"
|
||||
{!./src/middleware/tutorial001.py!}
|
||||
```
|
||||
|
||||
## Starlette's Middleware
|
||||
## Other middlewares
|
||||
|
||||
You can also add any other <a href="https://www.starlette.io/middleware/" class="external-link" target="_blank">Starlette Middleware</a>.
|
||||
You can later read more about other middlewares in the [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}.
|
||||
|
||||
These are classes instead of plain functions.
|
||||
|
||||
Including:
|
||||
|
||||
* `CORSMiddleware` (described in the next section).
|
||||
* `GZipMiddleware`.
|
||||
* `SentryMiddleware`.
|
||||
* ...and others.
|
||||
You will read about how to handle <abbr title="Cross-Origin Resource Sharing">CORS</abbr> with a middleware in the next section.
|
||||
|
||||
@@ -9,14 +9,19 @@ You can define the (HTTP) `status_code` to be used in the response of your *path
|
||||
|
||||
You can pass directly the `int` code, like `404`.
|
||||
|
||||
But if you don't remember what each number code is for, you can use the shortcut constants from `starlette`:
|
||||
But if you don't remember what each number code is for, you can use the shortcut constants in `status`:
|
||||
|
||||
```Python hl_lines="5 18"
|
||||
```Python hl_lines="3 17"
|
||||
{!./src/path_operation_configuration/tutorial001.py!}
|
||||
```
|
||||
|
||||
That status code will be used in the response and will be added to the OpenAPI schema.
|
||||
|
||||
!!! note "Technical Details"
|
||||
You could also use `from starlette import status`.
|
||||
|
||||
**FastAPI** provides the same `starlette.status` as `fastapi.status` just as a convenience for you, the developer. But it comes directly from Starlette.
|
||||
|
||||
## Tags
|
||||
|
||||
You can add tags to your *path operation*, pass the parameter `tags` with a `list` of `str` (commonly just one `str`):
|
||||
|
||||
@@ -132,6 +132,11 @@ You will receive, as declared, a `list` of `bytes` or `UploadFile`s.
|
||||
|
||||
So, whenever Swagger UI supports multi-file uploads, or any other tools that supports OpenAPI, they will be compatible with **FastAPI**.
|
||||
|
||||
!!! note "Technical Details"
|
||||
You could also use `from starlette.responses import HTMLResponse`.
|
||||
|
||||
**FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
|
||||
|
||||
## Recap
|
||||
|
||||
Use `File` to declare files to be uploaded as input parameters (as form data).
|
||||
|
||||
@@ -64,9 +64,9 @@ Let's see the previous example again:
|
||||
|
||||
But you don't have to memorize what each of these codes mean.
|
||||
|
||||
You can use the convenience variables from `starlette.status`.
|
||||
You can use the convenience variables from `fastapi.status`.
|
||||
|
||||
```Python hl_lines="2 7"
|
||||
```Python hl_lines="1 6"
|
||||
{!./src/response_status_code/tutorial002.py!}
|
||||
```
|
||||
|
||||
@@ -74,6 +74,11 @@ They are just a convenience, they hold the same number, but that way you can use
|
||||
|
||||
<img src="/img/tutorial/response-status-code/image02.png">
|
||||
|
||||
!!! note "Technical Details"
|
||||
You could also use `from starlette import status`.
|
||||
|
||||
**FastAPI** provides the same `starlette.status` as `fastapi.status` just as a convenience for you, the developer. But it comes directly from Starlette.
|
||||
|
||||
## Changing the default
|
||||
|
||||
Later, in the **Advanced User Guide**, you will see how to return a different status code than the default you are declaring here.
|
||||
|
||||
@@ -86,7 +86,7 @@ And another utility to verify if a received password matches the hash stored.
|
||||
|
||||
And another one to authenticate and return a user.
|
||||
|
||||
```Python hl_lines="7 39 56 57 60 61 70 71 72 73 74 75 76"
|
||||
```Python hl_lines="7 48 55 56 59 60 69 70 71 72 73 74 75"
|
||||
{!./src/security/tutorial004.py!}
|
||||
```
|
||||
|
||||
@@ -115,7 +115,7 @@ Define a Pydantic Model that will be used in the token endpoint for the response
|
||||
|
||||
Create a utility function to generate a new access token.
|
||||
|
||||
```Python hl_lines="3 6 13 14 15 29 30 31 79 80 81 82 83 84 85 86 87"
|
||||
```Python hl_lines="3 6 12 13 14 28 29 30 78 79 80 81 82 83 84 85 86"
|
||||
{!./src/security/tutorial004.py!}
|
||||
```
|
||||
|
||||
@@ -127,7 +127,7 @@ Decode the received token, verify it, and return the current user.
|
||||
|
||||
If the token is invalid, return an HTTP error right away.
|
||||
|
||||
```Python hl_lines="90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107"
|
||||
```Python hl_lines="89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106"
|
||||
{!./src/security/tutorial004.py!}
|
||||
```
|
||||
|
||||
@@ -137,7 +137,7 @@ Create a `timedelta` with the expiration time of the token.
|
||||
|
||||
Create a real JWT access token and return it.
|
||||
|
||||
```Python hl_lines="116 117 118 119 120 121 122 123 124 125 126 127 128 129"
|
||||
```Python hl_lines="115 116 117 118 119 120 121 122 123 124 125 126 127 128"
|
||||
{!./src/security/tutorial004.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ Now let's use the utilities provided by **FastAPI** to handle this.
|
||||
|
||||
First, import `OAuth2PasswordRequestForm`, and use it as a dependency with `Depends` for the path `/token`:
|
||||
|
||||
```Python hl_lines="2 75"
|
||||
```Python hl_lines="2 74"
|
||||
{!./src/security/tutorial003.py!}
|
||||
```
|
||||
|
||||
@@ -88,7 +88,7 @@ If there is no such user, we return an error saying "incorrect username or passw
|
||||
|
||||
For the error, we use the exception `HTTPException`:
|
||||
|
||||
```Python hl_lines="1 76 77 78"
|
||||
```Python hl_lines="1 75 76 77"
|
||||
{!./src/security/tutorial003.py!}
|
||||
```
|
||||
|
||||
@@ -116,7 +116,7 @@ If your database is stolen, the thief won't have your users' plaintext passwords
|
||||
|
||||
So, the thief won't be able to try to use those same passwords in another system (as many users use the same password everywhere, this would be dangerous).
|
||||
|
||||
```Python hl_lines="79 80 81 82"
|
||||
```Python hl_lines="78 79 80 81"
|
||||
{!./src/security/tutorial003.py!}
|
||||
```
|
||||
|
||||
@@ -154,7 +154,7 @@ For this simple example, we are going to just be completely insecure and return
|
||||
|
||||
But for now, let's focus on the specific details we need.
|
||||
|
||||
```Python hl_lines="84"
|
||||
```Python hl_lines="83"
|
||||
{!./src/security/tutorial003.py!}
|
||||
```
|
||||
|
||||
@@ -179,7 +179,7 @@ Both of these dependencies will just return an HTTP error if the user doesn't ex
|
||||
|
||||
So, in our endpoint, we will only get a user if the user exists, was correctly authenticated, and is active:
|
||||
|
||||
```Python hl_lines="57 58 59 60 61 62 63 64 65 68 69 70 71 88"
|
||||
```Python hl_lines="56 57 58 59 60 61 62 63 64 65 67 68 69 70 88"
|
||||
{!./src/security/tutorial003.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -626,7 +626,7 @@ A "middleware" is basically a function that is always executed for each request,
|
||||
|
||||
The middleware we'll add (just a function) will create a new SQLAlchemy `SessionLocal` for each request, add it to the request and then close it once the request is finished.
|
||||
|
||||
```Python hl_lines="16 17 18 19 20 21 22 23 24"
|
||||
```Python hl_lines="14 15 16 17 18 19 20 21 22"
|
||||
{!./src/sql_databases/sql_app/alt_main.py!}
|
||||
```
|
||||
|
||||
@@ -639,7 +639,7 @@ The middleware we'll add (just a function) will create a new SQLAlchemy `Session
|
||||
|
||||
### About `request.state`
|
||||
|
||||
<a href="https://www.starlette.io/requests/#other-state" class="external-link" target="_blank">`request.state` is a property of each Starlette `Request` object</a>. It is there to store arbitrary objects attached to the request itself, like the database session in this case.
|
||||
`request.state` is a property of each `Request` object. It is there to store arbitrary objects attached to the request itself, like the database session in this case. You can read more about it in <a href="https://www.starlette.io/requests/#other-state" class="external-link" target="_blank">Starlette's docs about `Request` state</a>.
|
||||
|
||||
For us in this case, it helps us ensure a single database session is used through all the request, and then closed afterwards (in the middleware).
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
You can serve static files automatically from a directory using <a href="https://www.starlette.io/staticfiles/" class="external-link" target="_blank">Starlette's Static Files</a>.
|
||||
You can serve static files automatically from a directory using `StaticFiles`.
|
||||
|
||||
## Install `aiofiles`
|
||||
|
||||
@@ -10,13 +10,18 @@ pip install aiofiles
|
||||
|
||||
## Use `StaticFiles`
|
||||
|
||||
* Import `StaticFiles` from Starlette.
|
||||
* Import `StaticFiles`.
|
||||
* "Mount" a `StaticFiles()` instance in a specific path.
|
||||
|
||||
```Python hl_lines="2 6"
|
||||
{!./src/static_files/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note "Technical Details"
|
||||
You could also use `from starlette.staticfiles import StaticFiles`.
|
||||
|
||||
**FastAPI** provides the same `starlette.staticfiles` as `fastapi.staticfiles` just as a convenience for you, the developer. But it actually comes directly from Starlette.
|
||||
|
||||
### What is "Mounting"
|
||||
|
||||
"Mounting" means adding a complete "independent" application in a specific path, that then takes care of handling all the sub-paths.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Thanks to <a href="https://www.starlette.io/testclient/" class="external-link" target="_blank">Starlette's TestClient</a>, testing **FastAPI** applications is easy and enjoyable.
|
||||
Thanks to <a href="https://www.starlette.io/testclient/" class="external-link" target="_blank">Starlette</a>, testing **FastAPI** applications is easy and enjoyable.
|
||||
|
||||
It is based on <a href="http://docs.python-requests.org" class="external-link" target="_blank">Requests</a>, so it's very familiar and intuitive.
|
||||
|
||||
@@ -6,7 +6,7 @@ With it, you can use <a href="https://docs.pytest.org/" class="external-link" ta
|
||||
|
||||
## Using `TestClient`
|
||||
|
||||
Import `TestClient` from `starlette.testclient`.
|
||||
Import `TestClient`.
|
||||
|
||||
Create a `TestClient` passing to it your **FastAPI**.
|
||||
|
||||
@@ -16,7 +16,7 @@ Use the `TestClient` object the same way as you do with `requests`.
|
||||
|
||||
Write simple `assert` statements with the standard Python expressions that you need to check (again, standard `pytest`).
|
||||
|
||||
```Python hl_lines="2 12 15 16 17 18"
|
||||
```Python hl_lines="2 12 15 16 17 18"
|
||||
{!./src/app_testing/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -27,6 +27,11 @@ Write simple `assert` statements with the standard Python expressions that you n
|
||||
|
||||
This allows you to use `pytest` directly without complications.
|
||||
|
||||
!!! note "Technical Details"
|
||||
You could also use `from starlette.testclient import TestClient`.
|
||||
|
||||
**FastAPI** provides the same `starlette.testclient` as `fastapi.testclient` just as a convenience for you, the developer. But it comes directly from Starlette.
|
||||
|
||||
## Separating tests
|
||||
|
||||
In a real application, you probably would have your tests in a different file.
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
|
||||
|
||||
__version__ = "0.49.2"
|
||||
__version__ = "0.52.0"
|
||||
|
||||
from starlette.background import BackgroundTasks
|
||||
from starlette import status
|
||||
|
||||
from .applications import FastAPI
|
||||
from .background import BackgroundTasks
|
||||
from .datastructures import UploadFile
|
||||
from .exceptions import HTTPException
|
||||
from .param_functions import (
|
||||
@@ -18,4 +19,7 @@ from .param_functions import (
|
||||
Query,
|
||||
Security,
|
||||
)
|
||||
from .requests import Request
|
||||
from .responses import Response
|
||||
from .routing import APIRouter
|
||||
from .websockets import WebSocket
|
||||
|
||||
@@ -18,8 +18,8 @@ from fastapi.params import Depends
|
||||
from fastapi.utils import warning_response_model_skip_defaults_deprecated
|
||||
from starlette.applications import Starlette
|
||||
from starlette.datastructures import State
|
||||
from starlette.exceptions import ExceptionMiddleware, HTTPException
|
||||
from starlette.middleware.errors import ServerErrorMiddleware
|
||||
from starlette.exceptions import HTTPException
|
||||
from starlette.middleware import Middleware
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import HTMLResponse, JSONResponse, Response
|
||||
from starlette.routing import BaseRoute
|
||||
@@ -29,9 +29,9 @@ from starlette.types import Receive, Scope, Send
|
||||
class FastAPI(Starlette):
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
debug: bool = False,
|
||||
routes: List[BaseRoute] = None,
|
||||
template_directory: str = None,
|
||||
title: str = "FastAPI",
|
||||
description: str = "",
|
||||
version: str = "0.1.0",
|
||||
@@ -42,19 +42,28 @@ class FastAPI(Starlette):
|
||||
redoc_url: Optional[str] = "/redoc",
|
||||
swagger_ui_oauth2_redirect_url: Optional[str] = "/docs/oauth2-redirect",
|
||||
swagger_ui_init_oauth: Optional[dict] = None,
|
||||
middleware: Sequence[Middleware] = None,
|
||||
exception_handlers: Dict[Union[int, Type[Exception]], Callable] = None,
|
||||
on_startup: Sequence[Callable] = None,
|
||||
on_shutdown: Sequence[Callable] = None,
|
||||
**extra: Dict[str, Any],
|
||||
) -> None:
|
||||
self.default_response_class = default_response_class
|
||||
self._debug = debug
|
||||
self.state = State()
|
||||
self.router: routing.APIRouter = routing.APIRouter(
|
||||
routes, dependency_overrides_provider=self
|
||||
routes,
|
||||
dependency_overrides_provider=self,
|
||||
on_startup=on_startup,
|
||||
on_shutdown=on_shutdown,
|
||||
)
|
||||
self.exception_middleware = ExceptionMiddleware(self.router, debug=debug)
|
||||
self.error_middleware = ServerErrorMiddleware(
|
||||
self.exception_middleware, debug=debug
|
||||
self.exception_handlers = (
|
||||
{} if exception_handlers is None else dict(exception_handlers)
|
||||
)
|
||||
|
||||
self.user_middleware = [] if middleware is None else list(middleware)
|
||||
self.middleware_stack = self.build_middleware_stack()
|
||||
|
||||
self.title = title
|
||||
self.description = description
|
||||
self.version = version
|
||||
|
||||
1
fastapi/background.py
Normal file
1
fastapi/background.py
Normal file
@@ -0,0 +1 @@
|
||||
from starlette.background import BackgroundTasks # noqa
|
||||
@@ -1,7 +1,8 @@
|
||||
from typing import Any, Callable
|
||||
|
||||
from starlette.concurrency import iterate_in_threadpool # noqa
|
||||
from starlette.concurrency import run_in_threadpool
|
||||
from starlette.concurrency import run_in_threadpool # noqa
|
||||
from starlette.concurrency import run_until_first_complete # noqa
|
||||
|
||||
asynccontextmanager_error_message = """
|
||||
FastAPI's contextmanager_in_threadpool require Python 3.7 or above,
|
||||
|
||||
1
fastapi/middleware/__init__.py
Normal file
1
fastapi/middleware/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from starlette.middleware import Middleware
|
||||
1
fastapi/middleware/cors.py
Normal file
1
fastapi/middleware/cors.py
Normal file
@@ -0,0 +1 @@
|
||||
from starlette.middleware.cors import CORSMiddleware # noqa
|
||||
1
fastapi/middleware/gzip.py
Normal file
1
fastapi/middleware/gzip.py
Normal file
@@ -0,0 +1 @@
|
||||
from starlette.middleware.gzip import GZipMiddleware # noqa
|
||||
1
fastapi/middleware/httpsredirect.py
Normal file
1
fastapi/middleware/httpsredirect.py
Normal file
@@ -0,0 +1 @@
|
||||
from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware # noqa
|
||||
1
fastapi/middleware/trustedhost.py
Normal file
1
fastapi/middleware/trustedhost.py
Normal file
@@ -0,0 +1 @@
|
||||
from starlette.middleware.trustedhost import TrustedHostMiddleware # noqa
|
||||
1
fastapi/middleware/wsgi.py
Normal file
1
fastapi/middleware/wsgi.py
Normal file
@@ -0,0 +1 @@
|
||||
from starlette.middleware.wsgi import WSGIMiddleware # noqa
|
||||
1
fastapi/requests.py
Normal file
1
fastapi/requests.py
Normal file
@@ -0,0 +1 @@
|
||||
from starlette.requests import Request # noqa
|
||||
23
fastapi/responses.py
Normal file
23
fastapi/responses.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from typing import Any
|
||||
|
||||
from starlette.responses import FileResponse # noqa
|
||||
from starlette.responses import HTMLResponse # noqa
|
||||
from starlette.responses import JSONResponse # noqa
|
||||
from starlette.responses import PlainTextResponse # noqa
|
||||
from starlette.responses import RedirectResponse # noqa
|
||||
from starlette.responses import Response # noqa
|
||||
from starlette.responses import StreamingResponse # noqa
|
||||
from starlette.responses import UJSONResponse # noqa
|
||||
|
||||
try:
|
||||
import orjson
|
||||
except ImportError: # pragma: nocover
|
||||
orjson = None # type: ignore
|
||||
|
||||
|
||||
class ORJSONResponse(JSONResponse):
|
||||
media_type = "application/json"
|
||||
|
||||
def render(self, content: Any) -> bytes:
|
||||
assert orjson is not None, "orjson must be installed to use ORJSONResponse"
|
||||
return orjson.dumps(content)
|
||||
@@ -29,6 +29,7 @@ from starlette.concurrency import run_in_threadpool
|
||||
from starlette.exceptions import HTTPException
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import JSONResponse, Response
|
||||
from starlette.routing import Mount # noqa
|
||||
from starlette.routing import (
|
||||
compile_path,
|
||||
get_name,
|
||||
@@ -346,9 +347,15 @@ class APIRouter(routing.Router):
|
||||
dependency_overrides_provider: Any = None,
|
||||
route_class: Type[APIRoute] = APIRoute,
|
||||
default_response_class: Type[Response] = None,
|
||||
on_startup: Sequence[Callable] = None,
|
||||
on_shutdown: Sequence[Callable] = None,
|
||||
) -> None:
|
||||
super().__init__(
|
||||
routes=routes, redirect_slashes=redirect_slashes, default=default
|
||||
routes=routes,
|
||||
redirect_slashes=redirect_slashes,
|
||||
default=default,
|
||||
on_startup=on_startup,
|
||||
on_shutdown=on_shutdown,
|
||||
)
|
||||
self.dependency_overrides_provider = dependency_overrides_provider
|
||||
self.route_class = route_class
|
||||
@@ -552,6 +559,10 @@ class APIRouter(routing.Router):
|
||||
self.add_websocket_route(
|
||||
prefix + route.path, route.endpoint, name=route.name
|
||||
)
|
||||
for handler in router.on_startup:
|
||||
self.add_event_handler("startup", handler)
|
||||
for handler in router.on_shutdown:
|
||||
self.add_event_handler("shutdown", handler)
|
||||
|
||||
def get(
|
||||
self,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user