Merge remote-tracking branch 'upstream/master'

This commit is contained in:
HexMix 2025-11-25 11:01:56 +08:00
commit 444cac07cf
228 changed files with 7129 additions and 4102 deletions

1
.github/labeler.yml vendored
View File

@ -17,6 +17,7 @@ lang-all:
- docs/*/docs/** - docs/*/docs/**
- all-globs-to-all-files: - all-globs-to-all-files:
- '!docs/en/docs/**' - '!docs/en/docs/**'
- '!docs/*/**/_*.md'
- '!fastapi/**' - '!fastapi/**'
- '!pyproject.toml' - '!pyproject.toml'

View File

@ -21,7 +21,7 @@ jobs:
outputs: outputs:
docs: ${{ steps.filter.outputs.docs }} docs: ${{ steps.filter.outputs.docs }}
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
# For pull requests it's not necessary to checkout the code but for the main branch it is # For pull requests it's not necessary to checkout the code but for the main branch it is
- uses: dorny/paths-filter@v3 - uses: dorny/paths-filter@v3
id: filter id: filter
@ -32,12 +32,9 @@ jobs:
- docs/** - docs/**
- docs_src/** - docs_src/**
- requirements-docs.txt - requirements-docs.txt
- requirements-docs-insiders.txt
- pyproject.toml - pyproject.toml
- mkdocs.yml - mkdocs.yml
- mkdocs.insiders.yml - mkdocs.env.yml
- mkdocs.maybe-insiders.yml
- mkdocs.no-insiders.yml
- .github/workflows/build-docs.yml - .github/workflows/build-docs.yml
- .github/workflows/deploy-docs.yml - .github/workflows/deploy-docs.yml
- scripts/mkdocs_hooks.py - scripts/mkdocs_hooks.py
@ -48,7 +45,7 @@ jobs:
outputs: outputs:
langs: ${{ steps.show-langs.outputs.langs }} langs: ${{ steps.show-langs.outputs.langs }}
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v6 uses: actions/setup-python@v6
with: with:
@ -63,12 +60,6 @@ jobs:
pyproject.toml pyproject.toml
- name: Install docs extras - name: Install docs extras
run: uv pip install -r requirements-docs.txt run: uv pip install -r requirements-docs.txt
# Install MkDocs Material Insiders here just to put it in the cache for the rest of the steps
- name: Install Material for MkDocs Insiders
if: ( github.event_name != 'pull_request' || github.secret_source == 'Actions' )
run: uv pip install -r requirements-docs-insiders.txt
env:
TOKEN: ${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}
- name: Verify Docs - name: Verify Docs
run: python ./scripts/docs.py verify-docs run: python ./scripts/docs.py verify-docs
- name: Export Language Codes - name: Export Language Codes
@ -90,7 +81,7 @@ jobs:
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT" run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v6 uses: actions/setup-python@v6
with: with:
@ -105,11 +96,6 @@ jobs:
pyproject.toml pyproject.toml
- name: Install docs extras - name: Install docs extras
run: uv pip install -r requirements-docs.txt run: uv pip install -r requirements-docs.txt
- name: Install Material for MkDocs Insiders
if: ( github.event_name != 'pull_request' || github.secret_source == 'Actions' )
run: uv pip install -r requirements-docs-insiders.txt
env:
TOKEN: ${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}
- name: Update Languages - name: Update Languages
run: python ./scripts/docs.py update-languages run: python ./scripts/docs.py update-languages
- uses: actions/cache@v4 - uses: actions/cache@v4

View File

@ -24,7 +24,7 @@ jobs:
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT" run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v6 uses: actions/setup-python@v6
with: with:

View File

@ -23,7 +23,7 @@ jobs:
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT" run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v6 uses: actions/setup-python@v6
with: with:

View File

@ -20,7 +20,7 @@ jobs:
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT" run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v6 uses: actions/setup-python@v6
with: with:

View File

@ -24,6 +24,8 @@ jobs:
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT" run: echo "$GITHUB_CONTEXT"
# pin to actions/checkout@v5 for compatibility with latest-changes
# Ref: https://github.com/actions/checkout/issues/2313
- uses: actions/checkout@v5 - uses: actions/checkout@v5
with: with:
# To allow latest-changes to commit to the main branch # To allow latest-changes to commit to the main branch
@ -34,7 +36,7 @@ jobs:
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }}
with: with:
limit-access-to-actor: true limit-access-to-actor: true
- uses: tiangolo/latest-changes@0.4.0 - uses: tiangolo/latest-changes@0.4.1
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
latest_changes_file: docs/en/docs/release-notes.md latest_changes_file: docs/en/docs/release-notes.md

View File

@ -28,7 +28,7 @@ jobs:
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT" run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v6 uses: actions/setup-python@v6
with: with:

View File

@ -24,7 +24,7 @@ jobs:
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT" run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v6 uses: actions/setup-python@v6
with: with:

88
.github/workflows/pre-commit.yml vendored Normal file
View File

@ -0,0 +1,88 @@
name: pre-commit
on:
pull_request:
types:
- opened
- synchronize
env:
IS_FORK: ${{ github.event.pull_request.head.repo.full_name != github.repository }}
jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v5
name: Checkout PR for own repo
if: env.IS_FORK == 'false'
with:
# To be able to commit it needs more than the last commit
ref: ${{ github.head_ref }}
# A token other than the default GITHUB_TOKEN is needed to be able to trigger CI
token: ${{ secrets.PRE_COMMIT }}
# pre-commit lite ci needs the default checkout configs to work
- uses: actions/checkout@v5
name: Checkout PR for fork
if: env.IS_FORK == 'true'
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.14"
- name: Setup uv
uses: astral-sh/setup-uv@v7
with:
cache-dependency-glob: |
requirements**.txt
pyproject.toml
uv.lock
- name: Install Dependencies
run: |
uv venv
uv pip install -r requirements.txt
- name: Run pre-commit
id: precommit
run: |
# Fetch the base branch for comparison
git fetch origin ${{ github.base_ref }}
uvx pre-commit run --from-ref origin/${{ github.base_ref }} --to-ref HEAD --show-diff-on-failure
continue-on-error: true
- name: Commit and push changes
if: env.IS_FORK == 'false'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add -A
if git diff --staged --quiet; then
echo "No changes to commit"
else
git commit -m "🎨 Auto format"
git push
fi
- uses: pre-commit-ci/lite-action@v1.1.0
if: env.IS_FORK == 'true'
with:
msg: 🎨 Auto format
- name: Error out on pre-commit errors
if: steps.precommit.outcome == 'failure'
run: exit 1
# https://github.com/marketplace/actions/alls-green#why
pre-commit-alls-green: # This job does nothing and is only used for the branch protection
if: always()
needs:
- pre-commit
runs-on: ubuntu-latest
steps:
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@release/v1
with:
jobs: ${{ toJSON(needs) }}

View File

@ -20,7 +20,7 @@ jobs:
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT" run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v6 uses: actions/setup-python@v6
with: with:

View File

@ -21,7 +21,7 @@ jobs:
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT" run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions/setup-python@v6 - uses: actions/setup-python@v6
with: with:
python-version: '3.9' python-version: '3.9'

View File

@ -24,7 +24,7 @@ jobs:
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT" run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v6 uses: actions/setup-python@v6
with: with:

View File

@ -22,7 +22,7 @@ jobs:
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT" run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v6 uses: actions/setup-python@v6
with: with:

View File

@ -23,7 +23,7 @@ jobs:
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT" run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v6 uses: actions/setup-python@v6
with: with:
@ -65,7 +65,7 @@ jobs:
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT" run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v6 uses: actions/setup-python@v6
with: with:
@ -111,7 +111,7 @@ jobs:
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT" run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions/setup-python@v6 - uses: actions/setup-python@v6
with: with:
python-version: '3.8' python-version: '3.8'

View File

@ -19,7 +19,7 @@ jobs:
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT" run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v6 uses: actions/setup-python@v6
with: with:

View File

@ -42,7 +42,7 @@ jobs:
env: env:
GITHUB_CONTEXT: ${{ toJson(github) }} GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT" run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v6 uses: actions/setup-python@v6
with: with:

3
.gitignore vendored
View File

@ -28,3 +28,6 @@ archive.zip
# macOS # macOS
.DS_Store .DS_Store
# Ignore while the setup still depends on requirements.txt files
uv.lock

View File

@ -1,9 +1,7 @@
# See https://pre-commit.com for more information # See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks # See https://pre-commit.com/hooks.html for more hooks
default_language_version:
python: python3.10
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0 rev: v6.0.0
hooks: hooks:
- id: check-added-large-files - id: check-added-large-files
@ -13,13 +11,19 @@ repos:
- --unsafe - --unsafe
- id: end-of-file-fixer - id: end-of-file-fixer
- id: trailing-whitespace - id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.14.2 rev: v0.14.3
hooks: hooks:
- id: ruff - id: ruff
args: args:
- --fix - --fix
- id: ruff-format - id: ruff-format
ci: - repo: local
autofix_commit_msg: 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks hooks:
autoupdate_commit_msg: ⬆ [pre-commit.ci] pre-commit autoupdate - id: local-script
language: unsupported
name: local script
entry: uv run ./scripts/docs.py add-permalinks-pages
args:
- --update-existing
files: ^docs/en/docs/.*\.md$

View File

@ -45,6 +45,11 @@ The key features are:
## Sponsors ## Sponsors
<!-- sponsors --> <!-- sponsors -->
### Keystone Sponsor
<a href="https://fastapicloud.com" target="_blank" title="FastAPI Cloud. By the same team behind FastAPI. You code. We Cloud."><img src="https://fastapi.tiangolo.com/img/sponsors/fastapicloud.png"></a>
### Gold and Silver Sponsors
<a href="https://blockbee.io?ref=fastapi" target="_blank" title="BlockBee Cryptocurrency Payment Gateway"><img src="https://fastapi.tiangolo.com/img/sponsors/blockbee.png"></a> <a href="https://blockbee.io?ref=fastapi" target="_blank" title="BlockBee Cryptocurrency Payment Gateway"><img src="https://fastapi.tiangolo.com/img/sponsors/blockbee.png"></a>
<a href="https://github.com/scalar/scalar/?utm_source=fastapi&utm_medium=website&utm_campaign=main-badge" target="_blank" title="Scalar: Beautiful Open-Source API References from Swagger/OpenAPI files"><img src="https://fastapi.tiangolo.com/img/sponsors/scalar.svg"></a> <a href="https://github.com/scalar/scalar/?utm_source=fastapi&utm_medium=website&utm_campaign=main-badge" target="_blank" title="Scalar: Beautiful Open-Source API References from Swagger/OpenAPI files"><img src="https://fastapi.tiangolo.com/img/sponsors/scalar.svg"></a>
@ -55,6 +60,7 @@ The key features are:
<a href="https://www.coderabbit.ai/?utm_source=fastapi&utm_medium=badge&utm_campaign=fastapi" target="_blank" title="Cut Code Review Time & Bugs in Half with CodeRabbit"><img src="https://fastapi.tiangolo.com/img/sponsors/coderabbit.png"></a> <a href="https://www.coderabbit.ai/?utm_source=fastapi&utm_medium=badge&utm_campaign=fastapi" target="_blank" title="Cut Code Review Time & Bugs in Half with CodeRabbit"><img src="https://fastapi.tiangolo.com/img/sponsors/coderabbit.png"></a>
<a href="https://subtotal.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=open-source" target="_blank" title="The Gold Standard in Retail Account Linking"><img src="https://fastapi.tiangolo.com/img/sponsors/subtotal.svg"></a> <a href="https://subtotal.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=open-source" target="_blank" title="The Gold Standard in Retail Account Linking"><img src="https://fastapi.tiangolo.com/img/sponsors/subtotal.svg"></a>
<a href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi" target="_blank" title="Deploy enterprise applications at startup speed"><img src="https://fastapi.tiangolo.com/img/sponsors/railway.png"></a> <a href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi" target="_blank" title="Deploy enterprise applications at startup speed"><img src="https://fastapi.tiangolo.com/img/sponsors/railway.png"></a>
<a href="https://serpapi.com/?utm_source=fastapi_website" target="_blank" title="SerpApi: Web Search API"><img src="https://fastapi.tiangolo.com/img/sponsors/serpapi.png"></a>
<a href="https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display" target="_blank" title="Pay as you go for market data"><img src="https://fastapi.tiangolo.com/img/sponsors/databento.svg"></a> <a href="https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display" target="_blank" title="Pay as you go for market data"><img src="https://fastapi.tiangolo.com/img/sponsors/databento.svg"></a>
<a href="https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship" target="_blank" title="SDKs for your API | Speakeasy"><img src="https://fastapi.tiangolo.com/img/sponsors/speakeasy.png"></a> <a href="https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship" target="_blank" title="SDKs for your API | Speakeasy"><img src="https://fastapi.tiangolo.com/img/sponsors/speakeasy.png"></a>
<a href="https://www.svix.com/" target="_blank" title="Svix - Webhooks as a service"><img src="https://fastapi.tiangolo.com/img/sponsors/svix.svg"></a> <a href="https://www.svix.com/" target="_blank" title="Svix - Webhooks as a service"><img src="https://fastapi.tiangolo.com/img/sponsors/svix.svg"></a>
@ -446,6 +452,58 @@ For a more complete example including more features, see the <a href="https://fa
* **Cookie Sessions** * **Cookie Sessions**
* ...and more. * ...and more.
### Deploy your app (optional)
You can optionally deploy your FastAPI app to <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>, go and join the waiting list if you haven't. 🚀
If you already have a **FastAPI Cloud** account (we invited you from the waiting list 😉), you can deploy your application with one command.
Before deploying, make sure you are logged in:
<div class="termy">
```console
$ fastapi login
You are logged in to FastAPI Cloud 🚀
```
</div>
Then deploy your app:
<div class="termy">
```console
$ fastapi deploy
Deploying to FastAPI Cloud...
✅ Deployment successful!
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
```
</div>
That's it! Now you can access your app at that URL. ✨
#### About FastAPI Cloud
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** is built by the same author and team behind **FastAPI**.
It streamlines the process of **building**, **deploying**, and **accessing** an API with minimal effort.
It brings the same **developer experience** of building apps with FastAPI to **deploying** them to the cloud. 🎉
FastAPI Cloud is the primary sponsor and funding provider for the *FastAPI and friends* open source projects. ✨
#### Deploy to other cloud providers
FastAPI is open source and based on standards. You can deploy FastAPI apps to any cloud provider you choose.
Follow your cloud provider's guides to deploy FastAPI apps with them. 🤓
## Performance ## Performance
Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*) Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)

View File

@ -70,12 +70,22 @@ Wenn Sie das hier alles verstanden haben, wissen Sie bereits, wie diese Sicherhe
Sie benötigen diese technischen Details höchstwahrscheinlich nicht. Sie benötigen diese technischen Details höchstwahrscheinlich nicht.
Diese Details sind hauptsächlich nützlich, wenn Sie eine FastAPI-Anwendung haben, die älter als 0.118.0 ist, und Sie auf Probleme mit Abhängigkeiten mit `yield` stoßen. Diese Details sind hauptsächlich nützlich, wenn Sie eine FastAPI-Anwendung haben, die älter als 0.121.0 ist, und Sie auf Probleme mit Abhängigkeiten mit `yield` stoßen.
/// ///
Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben, hier ist eine Zusammenfassung der Änderungen. Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben, hier ist eine Zusammenfassung der Änderungen.
### Abhängigkeiten mit `yield` und `scope` { #dependencies-with-yield-and-scope }
In Version 0.121.0 hat FastAPI Unterstützung für `Depends(scope="function")` für Abhängigkeiten mit `yield` hinzugefügt.
Mit `Depends(scope="function")` wird der Exit-Code nach `yield` direkt nach dem Ende der *Pfadoperation-Funktion* ausgeführt, bevor die Response an den Client gesendet wird.
Und bei Verwendung von `Depends(scope="request")` (dem Default) wird der Exit-Code nach `yield` ausgeführt, nachdem die Response gesendet wurde.
Mehr dazu finden Sie in der Dokumentation zu [Abhängigkeiten mit `yield` Frühes Beenden und `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope).
### Abhängigkeiten mit `yield` und `StreamingResponse`, Technische Details { #dependencies-with-yield-and-streamingresponse-technical-details } ### Abhängigkeiten mit `yield` und `StreamingResponse`, Technische Details { #dependencies-with-yield-and-streamingresponse-technical-details }
Vor FastAPI 0.118.0 wurde bei Verwendung einer Abhängigkeit mit `yield` der Exit-Code nach der *Pfadoperation-Funktion* ausgeführt, aber unmittelbar bevor die Response gesendet wurde. Vor FastAPI 0.118.0 wurde bei Verwendung einer Abhängigkeit mit `yield` der Exit-Code nach der *Pfadoperation-Funktion* ausgeführt, aber unmittelbar bevor die Response gesendet wurde.

View File

@ -184,6 +184,51 @@ Wenn Sie in dem Code der *Pfadoperation-Funktion* irgendeine Exception auslösen
/// ///
## Frühes Beenden und `scope` { #early-exit-and-scope }
Normalerweise wird der Exit-Code von Abhängigkeiten mit `yield` ausgeführt **nachdem die Response** an den Client gesendet wurde.
Wenn Sie aber wissen, dass Sie die Abhängigkeit nach der Rückkehr aus der *Pfadoperation-Funktion* nicht mehr benötigen, können Sie `Depends(scope="function")` verwenden, um FastAPI mitzuteilen, dass es die Abhängigkeit nach der Rückkehr aus der *Pfadoperation-Funktion* schließen soll, jedoch **bevor** die **Response gesendet wird**.
{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *}
`Depends()` erhält einen `scope`-Parameter, der sein kann:
* `"function"`: startet die Abhängigkeit vor der *Pfadoperation-Funktion*, die den Request bearbeitet, beendet die Abhängigkeit nach dem Ende der *Pfadoperation-Funktion*, aber **bevor** die Response an den Client zurückgesendet wird. Die Abhängigkeitsfunktion wird also **um** die *Pfadoperation-**Funktion*** **herum** ausgeführt.
* `"request"`: startet die Abhängigkeit vor der *Pfadoperation-Funktion*, die den Request bearbeitet (ähnlich wie bei `"function"`), beendet sie jedoch **nachdem** die Response an den Client zurückgesendet wurde. Die Abhängigkeitsfunktion wird also **um** den **Request**- und Response-Zyklus **herum** ausgeführt.
Wenn nicht angegeben und die Abhängigkeit `yield` hat, hat sie standardmäßig einen `scope` von `"request"`.
### `scope` für Unterabhängigkeiten { #scope-for-sub-dependencies }
Wenn Sie eine Abhängigkeit mit `scope="request"` (dem Default) deklarieren, muss jede Unterabhängigkeit ebenfalls einen `scope` von `"request"` haben.
Eine Abhängigkeit mit `scope` von `"function"` kann jedoch Abhängigkeiten mit `scope` von `"function"` und `scope` von `"request"` haben.
Das liegt daran, dass jede Abhängigkeit in der Lage sein muss, ihren Exit-Code vor den Unterabhängigkeiten auszuführen, da sie diese während ihres Exit-Codes möglicherweise noch verwenden muss.
```mermaid
sequenceDiagram
participant client as Client
participant dep_req as Abhängigkeit scope="request"
participant dep_func as Abhängigkeit scope="function"
participant operation as Pfadoperation
client ->> dep_req: Startet den Request
Note over dep_req: Führt den Code bis zum yield aus
dep_req ->> dep_func: Reicht Abhängigkeit weiter
Note over dep_func: Führt den Code bis zum yield aus
dep_func ->> operation: Führt Pfadoperation mit Abhängigkeit aus
operation ->> dep_func: Kehrt aus Pfadoperation zurück
Note over dep_func: Führt Code nach yield aus
Note over dep_func: ✅ Abhängigkeit geschlossen
dep_func ->> client: Sendet Response an Client
Note over client: Response gesendet
Note over dep_req: Führt Code nach yield aus
Note over dep_req: ✅ Abhängigkeit geschlossen
```
## Abhängigkeiten mit `yield`, `HTTPException`, `except` und Hintergrundtasks { #dependencies-with-yield-httpexception-except-and-background-tasks } ## Abhängigkeiten mit `yield`, `HTTPException`, `except` und Hintergrundtasks { #dependencies-with-yield-httpexception-except-and-background-tasks }
Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben. Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben.

View File

@ -1,11 +1,11 @@
tiangolo: tiangolo:
login: tiangolo login: tiangolo
count: 782 count: 794
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
url: https://github.com/tiangolo url: https://github.com/tiangolo
dependabot: dependabot:
login: dependabot login: dependabot
count: 117 count: 126
avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4
url: https://github.com/apps/dependabot url: https://github.com/apps/dependabot
alejsdev: alejsdev:
@ -15,7 +15,7 @@ alejsdev:
url: https://github.com/alejsdev url: https://github.com/alejsdev
pre-commit-ci: pre-commit-ci:
login: pre-commit-ci login: pre-commit-ci
count: 45 count: 49
avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4 avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4
url: https://github.com/apps/pre-commit-ci url: https://github.com/apps/pre-commit-ci
github-actions: github-actions:
@ -25,7 +25,7 @@ github-actions:
url: https://github.com/apps/github-actions url: https://github.com/apps/github-actions
Kludex: Kludex:
login: Kludex login: Kludex
count: 24 count: 25
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4
url: https://github.com/Kludex url: https://github.com/Kludex
dmontagu: dmontagu:
@ -33,36 +33,36 @@ dmontagu:
count: 17 count: 17
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4 avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4
url: https://github.com/dmontagu url: https://github.com/dmontagu
YuriiMotov:
login: YuriiMotov
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
url: https://github.com/YuriiMotov
nilslindemann:
login: nilslindemann
count: 14
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
url: https://github.com/nilslindemann
euri10: euri10:
login: euri10 login: euri10
count: 13 count: 13
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4 avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
url: https://github.com/euri10 url: https://github.com/euri10
nilslindemann: svlandeg:
login: nilslindemann login: svlandeg
count: 13 count: 13
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4
url: https://github.com/nilslindemann url: https://github.com/svlandeg
kantandane: kantandane:
login: kantandane login: kantandane
count: 13 count: 13
avatarUrl: https://avatars.githubusercontent.com/u/3978368?u=cccc199291f991a73b1ebba5abc735a948e0bd16&v=4 avatarUrl: https://avatars.githubusercontent.com/u/3978368?u=cccc199291f991a73b1ebba5abc735a948e0bd16&v=4
url: https://github.com/kantandane url: https://github.com/kantandane
svlandeg:
login: svlandeg
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4
url: https://github.com/svlandeg
zhaohan-dong: zhaohan-dong:
login: zhaohan-dong login: zhaohan-dong
count: 11 count: 11
avatarUrl: https://avatars.githubusercontent.com/u/65422392?u=8260f8781f50248410ebfa4c9bf70e143fe5c9f2&v=4 avatarUrl: https://avatars.githubusercontent.com/u/65422392?u=8260f8781f50248410ebfa4c9bf70e143fe5c9f2&v=4
url: https://github.com/zhaohan-dong url: https://github.com/zhaohan-dong
YuriiMotov:
login: YuriiMotov
count: 10
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
url: https://github.com/YuriiMotov
mariacamilagl: mariacamilagl:
login: mariacamilagl login: mariacamilagl
count: 9 count: 9
@ -158,6 +158,11 @@ prostomarkeloff:
count: 3 count: 3
avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=6918e39a1224194ba636e897461a02a20126d7ad&v=4 avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=6918e39a1224194ba636e897461a02a20126d7ad&v=4
url: https://github.com/prostomarkeloff url: https://github.com/prostomarkeloff
frankie567:
login: frankie567
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=f3e79acfe4ed207e15c2145161a8a9759925fcd2&v=4
url: https://github.com/frankie567
nsidnev: nsidnev:
login: nsidnev login: nsidnev
count: 3 count: 3
@ -191,7 +196,7 @@ Serrones:
uriyyo: uriyyo:
login: uriyyo login: uriyyo
count: 3 count: 3
avatarUrl: https://avatars.githubusercontent.com/u/32038156?u=0c68019beb28381ce5205a838937c61e0fe3fee2&v=4 avatarUrl: https://avatars.githubusercontent.com/u/32038156?u=c26ca9b821fcf6499b84db75f553d4980bf8d023&v=4
url: https://github.com/uriyyo url: https://github.com/uriyyo
andrew222651: andrew222651:
login: andrew222651 login: andrew222651
@ -261,7 +266,7 @@ Nimitha-jagadeesha:
lucaromagnoli: lucaromagnoli:
login: lucaromagnoli login: lucaromagnoli
count: 3 count: 3
avatarUrl: https://avatars.githubusercontent.com/u/38782977?u=e66396859f493b4ddcb3a837a1b2b2039c805417&v=4 avatarUrl: https://avatars.githubusercontent.com/u/38782977?u=15df02e806a2293af40ac619fba11dbe3c0c4fd4&v=4
url: https://github.com/lucaromagnoli url: https://github.com/lucaromagnoli
salmantec: salmantec:
login: salmantec login: salmantec
@ -328,11 +333,6 @@ svalouch:
count: 2 count: 2
avatarUrl: https://avatars.githubusercontent.com/u/54674660?v=4 avatarUrl: https://avatars.githubusercontent.com/u/54674660?v=4
url: https://github.com/svalouch url: https://github.com/svalouch
frankie567:
login: frankie567
count: 2
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=f3e79acfe4ed207e15c2145161a8a9759925fcd2&v=4
url: https://github.com/frankie567
marier-nico: marier-nico:
login: marier-nico login: marier-nico
count: 2 count: 2
@ -346,7 +346,7 @@ Dustyposa:
aviramha: aviramha:
login: aviramha login: aviramha
count: 2 count: 2
avatarUrl: https://avatars.githubusercontent.com/u/41201924?u=6883cc4fc13a7b2e60d4deddd4be06f9c5287880&v=4 avatarUrl: https://avatars.githubusercontent.com/u/41201924?u=ce5d3ea7037c2e6b3f82eff87e2217d4fb63214b&v=4
url: https://github.com/aviramha url: https://github.com/aviramha
iwpnd: iwpnd:
login: iwpnd login: iwpnd

View File

@ -381,6 +381,10 @@ Articles:
title: 'Tutorial de FastAPI, ¿el mejor framework de Python?' title: 'Tutorial de FastAPI, ¿el mejor framework de Python?'
Podcasts: Podcasts:
English: English:
- author: Behind the Commit
author_link: https://www.youtube.com/@BehindtheCommit
link: https://youtu.be/iaDRYUQ0OMM
title: Why FastAPI Became Pythons FastestGrowing Framework Chat with Sebastián Ramírez
- author: Real Python - author: Real Python
author_link: https://realpython.com/ author_link: https://realpython.com/
link: https://realpython.com/podcasts/rpp/72/ link: https://realpython.com/podcasts/rpp/72/
@ -399,6 +403,10 @@ Podcasts:
title: FastAPI on PythonBytes title: FastAPI on PythonBytes
Talks: Talks:
English: English:
- author: Sebastián Ramírez (tiangolo)
author_link: https://x.com/tiangolo
link: https://www.youtube.com/watch?v=mwvmfl8nN_U
title: 'Keynote: Behind the scenes of FastAPI and friends for developers and builders — Sebastián Ramírez'
- author: Jeny Sadadia - author: Jeny Sadadia
author_link: https://github.com/JenySadadia author_link: https://github.com/JenySadadia
link: https://www.youtube.com/watch?v=uZdTe8_Z6BQ link: https://www.youtube.com/watch?v=uZdTe8_Z6BQ

View File

@ -14,6 +14,9 @@ sponsors:
- login: coderabbitai - login: coderabbitai
avatarUrl: https://avatars.githubusercontent.com/u/132028505?v=4 avatarUrl: https://avatars.githubusercontent.com/u/132028505?v=4
url: https://github.com/coderabbitai url: https://github.com/coderabbitai
- login: greptileai
avatarUrl: https://avatars.githubusercontent.com/u/140149887?v=4
url: https://github.com/greptileai
- login: subtotal - login: subtotal
avatarUrl: https://avatars.githubusercontent.com/u/176449348?v=4 avatarUrl: https://avatars.githubusercontent.com/u/176449348?v=4
url: https://github.com/subtotal url: https://github.com/subtotal
@ -41,9 +44,9 @@ sponsors:
- login: permitio - login: permitio
avatarUrl: https://avatars.githubusercontent.com/u/71775833?v=4 avatarUrl: https://avatars.githubusercontent.com/u/71775833?v=4
url: https://github.com/permitio url: https://github.com/permitio
- - login: marvin-robot - - login: BoostryJP
avatarUrl: https://avatars.githubusercontent.com/u/41086007?u=b9fcab402d0cd0aec738b6574fe60855cb0cd36d&v=4 avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4
url: https://github.com/marvin-robot url: https://github.com/BoostryJP
- login: mercedes-benz - login: mercedes-benz
avatarUrl: https://avatars.githubusercontent.com/u/34240465?v=4 avatarUrl: https://avatars.githubusercontent.com/u/34240465?v=4
url: https://github.com/mercedes-benz url: https://github.com/mercedes-benz
@ -53,9 +56,9 @@ sponsors:
- login: LambdaTest-Inc - login: LambdaTest-Inc
avatarUrl: https://avatars.githubusercontent.com/u/171592363?u=96606606a45fa170427206199014f2a5a2a4920b&v=4 avatarUrl: https://avatars.githubusercontent.com/u/171592363?u=96606606a45fa170427206199014f2a5a2a4920b&v=4
url: https://github.com/LambdaTest-Inc url: https://github.com/LambdaTest-Inc
- login: BoostryJP - login: requestly
avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4 avatarUrl: https://avatars.githubusercontent.com/u/12287519?v=4
url: https://github.com/BoostryJP url: https://github.com/requestly
- login: acsone - login: acsone
avatarUrl: https://avatars.githubusercontent.com/u/7601056?v=4 avatarUrl: https://avatars.githubusercontent.com/u/7601056?v=4
url: https://github.com/acsone url: https://github.com/acsone
@ -71,27 +74,39 @@ sponsors:
- - login: mainframeindustries - - login: mainframeindustries
avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4 avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4
url: https://github.com/mainframeindustries url: https://github.com/mainframeindustries
- login: yasyf
avatarUrl: https://avatars.githubusercontent.com/u/709645?u=f36736b3c6a85f578886ecc42a740e7b436e7a01&v=4
url: https://github.com/yasyf
- - login: alixlahuec - - login: alixlahuec
avatarUrl: https://avatars.githubusercontent.com/u/29543316?u=44357eb2a93bccf30fb9d389b8befe94a3d00985&v=4 avatarUrl: https://avatars.githubusercontent.com/u/29543316?u=44357eb2a93bccf30fb9d389b8befe94a3d00985&v=4
url: https://github.com/alixlahuec url: https://github.com/alixlahuec
- login: Partho
avatarUrl: https://avatars.githubusercontent.com/u/2034301?u=ce195ac36835cca0cdfe6dd6e897bd38873a1524&v=4
url: https://github.com/Partho
- - login: primer-io - - login: primer-io
avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4 avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4
url: https://github.com/primer-io url: https://github.com/primer-io
- - login: nilslindemann - login: xsalagarcia
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 avatarUrl: https://avatars.githubusercontent.com/u/66035908?v=4
url: https://github.com/nilslindemann url: https://github.com/xsalagarcia
- login: upciti - - login: upciti
avatarUrl: https://avatars.githubusercontent.com/u/43346262?v=4 avatarUrl: https://avatars.githubusercontent.com/u/43346262?v=4
url: https://github.com/upciti url: https://github.com/upciti
- login: thisisfixer - login: GonnaFlyMethod
avatarUrl: https://avatars.githubusercontent.com/u/14433035?u=076d52a5b7891c764904af9f462bfb45428e25df&v=4 avatarUrl: https://avatars.githubusercontent.com/u/60840539?u=edf70b373fd4f1a83d3eb7c6802f4b6addb572cf&v=4
url: https://github.com/thisisfixer url: https://github.com/GonnaFlyMethod
- login: ChargeStorm
avatarUrl: https://avatars.githubusercontent.com/u/26000165?v=4
url: https://github.com/ChargeStorm
- login: DanielYang59
avatarUrl: https://avatars.githubusercontent.com/u/80093591?u=63873f701c7c74aac83c906800a1dddc0bc8c92f&v=4
url: https://github.com/DanielYang59
- login: nilslindemann
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
url: https://github.com/nilslindemann
- - login: samuelcolvin - - login: samuelcolvin
avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4 avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4
url: https://github.com/samuelcolvin url: https://github.com/samuelcolvin
- login: vincentkoc
avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4
url: https://github.com/vincentkoc
- login: otosky - login: otosky
avatarUrl: https://avatars.githubusercontent.com/u/42260747?u=69d089387c743d89427aa4ad8740cfb34045a9e0&v=4 avatarUrl: https://avatars.githubusercontent.com/u/42260747?u=69d089387c743d89427aa4ad8740cfb34045a9e0&v=4
url: https://github.com/otosky url: https://github.com/otosky
@ -101,6 +116,9 @@ sponsors:
- login: roboflow - login: roboflow
avatarUrl: https://avatars.githubusercontent.com/u/53104118?v=4 avatarUrl: https://avatars.githubusercontent.com/u/53104118?v=4
url: https://github.com/roboflow url: https://github.com/roboflow
- login: dudikbender
avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4
url: https://github.com/dudikbender
- login: ehaca - login: ehaca
avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=cec1a3e0643b785288ae8260cc295a85ab344995&v=4 avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=cec1a3e0643b785288ae8260cc295a85ab344995&v=4
url: https://github.com/ehaca url: https://github.com/ehaca
@ -113,21 +131,15 @@ sponsors:
- login: Leay15 - login: Leay15
avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4 avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4
url: https://github.com/Leay15 url: https://github.com/Leay15
- login: kaoru0310
avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4
url: https://github.com/kaoru0310
- login: DelfinaCare
avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4
url: https://github.com/DelfinaCare
- login: Karine-Bauch - login: Karine-Bauch
avatarUrl: https://avatars.githubusercontent.com/u/90465103?u=7feb1018abb1a5631cfd9a91fea723d1ceb5f49b&v=4 avatarUrl: https://avatars.githubusercontent.com/u/90465103?u=7feb1018abb1a5631cfd9a91fea723d1ceb5f49b&v=4
url: https://github.com/Karine-Bauch url: https://github.com/Karine-Bauch
- login: jugeeem - login: jugeeem
avatarUrl: https://avatars.githubusercontent.com/u/116043716?u=ae590d79c38ac79c91b9c5caa6887d061e865a3d&v=4 avatarUrl: https://avatars.githubusercontent.com/u/116043716?u=ae590d79c38ac79c91b9c5caa6887d061e865a3d&v=4
url: https://github.com/jugeeem url: https://github.com/jugeeem
- login: dudikbender - login: connorpark24
avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4 avatarUrl: https://avatars.githubusercontent.com/u/142128990?u=09b84a4beb1f629b77287a837bcf3729785cdd89&v=4
url: https://github.com/dudikbender url: https://github.com/connorpark24
- login: patsatsia - login: patsatsia
avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4 avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4
url: https://github.com/patsatsia url: https://github.com/patsatsia
@ -140,9 +152,12 @@ sponsors:
- login: chickenandstats - login: chickenandstats
avatarUrl: https://avatars.githubusercontent.com/u/79477966?u=ae2b894aa954070db1d7830dab99b49eba4e4567&v=4 avatarUrl: https://avatars.githubusercontent.com/u/79477966?u=ae2b894aa954070db1d7830dab99b49eba4e4567&v=4
url: https://github.com/chickenandstats url: https://github.com/chickenandstats
- login: dodo5522 - login: kaoru0310
avatarUrl: https://avatars.githubusercontent.com/u/1362607?u=9bf1e0e520cccc547c046610c468ce6115bbcf9f&v=4 avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4
url: https://github.com/dodo5522 url: https://github.com/kaoru0310
- login: DelfinaCare
avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4
url: https://github.com/DelfinaCare
- login: knallgelb - login: knallgelb
avatarUrl: https://avatars.githubusercontent.com/u/2358812?u=c48cb6362b309d74cbf144bd6ad3aed3eb443e82&v=4 avatarUrl: https://avatars.githubusercontent.com/u/2358812?u=c48cb6362b309d74cbf144bd6ad3aed3eb443e82&v=4
url: https://github.com/knallgelb url: https://github.com/knallgelb
@ -170,9 +185,12 @@ sponsors:
- login: Ryandaydev - login: Ryandaydev
avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4 avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4
url: https://github.com/Ryandaydev url: https://github.com/Ryandaydev
- login: vincentkoc - login: jaredtrog
avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4 avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4
url: https://github.com/vincentkoc url: https://github.com/jaredtrog
- login: oliverxchen
avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4
url: https://github.com/oliverxchen
- login: jstanden - login: jstanden
avatarUrl: https://avatars.githubusercontent.com/u/63288?u=c3658d57d2862c607a0e19c2101c3c51876e36ad&v=4 avatarUrl: https://avatars.githubusercontent.com/u/63288?u=c3658d57d2862c607a0e19c2101c3c51876e36ad&v=4
url: https://github.com/jstanden url: https://github.com/jstanden
@ -197,6 +215,9 @@ sponsors:
- login: mintuhouse - login: mintuhouse
avatarUrl: https://avatars.githubusercontent.com/u/769950?u=ecfbd79a97d33177e0d093ddb088283cf7fe8444&v=4 avatarUrl: https://avatars.githubusercontent.com/u/769950?u=ecfbd79a97d33177e0d093ddb088283cf7fe8444&v=4
url: https://github.com/mintuhouse url: https://github.com/mintuhouse
- login: dodo5522
avatarUrl: https://avatars.githubusercontent.com/u/1362607?u=9bf1e0e520cccc547c046610c468ce6115bbcf9f&v=4
url: https://github.com/dodo5522
- login: wdwinslow - login: wdwinslow
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=371272f2c69e680e0559a7b0a57385e83a5dc728&v=4 avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=371272f2c69e680e0559a7b0a57385e83a5dc728&v=4
url: https://github.com/wdwinslow url: https://github.com/wdwinslow
@ -212,18 +233,15 @@ sponsors:
- login: mjohnsey - login: mjohnsey
avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4 avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4
url: https://github.com/mjohnsey url: https://github.com/mjohnsey
- login: enguy-hub
avatarUrl: https://avatars.githubusercontent.com/u/16822912?u=2c45f9e7f427b2f2f3b023d7fdb0d44764c92ae8&v=4
url: https://github.com/enguy-hub
- login: ashi-agrawal - login: ashi-agrawal
avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4 avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4
url: https://github.com/ashi-agrawal url: https://github.com/ashi-agrawal
- login: RaamEEIL - login: RaamEEIL
avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4 avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4
url: https://github.com/RaamEEIL url: https://github.com/RaamEEIL
- login: jaredtrog
avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4
url: https://github.com/jaredtrog
- login: oliverxchen
avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4
url: https://github.com/oliverxchen
- login: ternaus - login: ternaus
avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=513a26b02a39e7a28d587cd37c6cc877ea368e6e&v=4 avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=513a26b02a39e7a28d587cd37c6cc877ea368e6e&v=4
url: https://github.com/ternaus url: https://github.com/ternaus
@ -242,7 +260,10 @@ sponsors:
- - login: manoelpqueiroz - - login: manoelpqueiroz
avatarUrl: https://avatars.githubusercontent.com/u/23669137?u=b12e84b28a84369ab5b30bd5a79e5788df5a0756&v=4 avatarUrl: https://avatars.githubusercontent.com/u/23669137?u=b12e84b28a84369ab5b30bd5a79e5788df5a0756&v=4
url: https://github.com/manoelpqueiroz url: https://github.com/manoelpqueiroz
- - login: pawamoy - - login: ceb10n
avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4
url: https://github.com/ceb10n
- login: pawamoy
avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4 avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4
url: https://github.com/pawamoy url: https://github.com/pawamoy
- login: siavashyj - login: siavashyj
@ -260,9 +281,9 @@ sponsors:
- login: hgalytoby - login: hgalytoby
avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=6cc9028f3db63f8f60ad21c17b1ce4b88c4e2e60&v=4 avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=6cc9028f3db63f8f60ad21c17b1ce4b88c4e2e60&v=4
url: https://github.com/hgalytoby url: https://github.com/hgalytoby
- login: nisutec - login: johnl28
avatarUrl: https://avatars.githubusercontent.com/u/25281462?u=e562484c451fdfc59053163f64405f8eb262b8b0&v=4 avatarUrl: https://avatars.githubusercontent.com/u/54412955?u=47dd06082d1c39caa90c752eb55566e4f3813957&v=4
url: https://github.com/nisutec url: https://github.com/johnl28
- login: hoenie-ams - login: hoenie-ams
avatarUrl: https://avatars.githubusercontent.com/u/25708487?u=cda07434f0509ac728d9edf5e681117c0f6b818b&v=4 avatarUrl: https://avatars.githubusercontent.com/u/25708487?u=cda07434f0509ac728d9edf5e681117c0f6b818b&v=4
url: https://github.com/hoenie-ams url: https://github.com/hoenie-ams
@ -278,33 +299,21 @@ sponsors:
- login: petercool - login: petercool
avatarUrl: https://avatars.githubusercontent.com/u/37613029?u=75aa8c6729e6e8f85a300561c4dbeef9d65c8797&v=4 avatarUrl: https://avatars.githubusercontent.com/u/37613029?u=75aa8c6729e6e8f85a300561c4dbeef9d65c8797&v=4
url: https://github.com/petercool url: https://github.com/petercool
- login: JulioPeixoto
avatarUrl: https://avatars.githubusercontent.com/u/96303574?u=27d4614350cae33653f1be35cb47c92a12627ac9&v=4
url: https://github.com/JulioPeixoto
- login: johnl28
avatarUrl: https://avatars.githubusercontent.com/u/54412955?u=47dd06082d1c39caa90c752eb55566e4f3813957&v=4
url: https://github.com/johnl28
- login: PunRabbit - login: PunRabbit
avatarUrl: https://avatars.githubusercontent.com/u/70463212?u=1a835cfbc99295a60c8282f6aa6199d1b42241a5&v=4 avatarUrl: https://avatars.githubusercontent.com/u/70463212?u=1a835cfbc99295a60c8282f6aa6199d1b42241a5&v=4
url: https://github.com/PunRabbit url: https://github.com/PunRabbit
- login: PelicanQ - login: PelicanQ
avatarUrl: https://avatars.githubusercontent.com/u/77930606?v=4 avatarUrl: https://avatars.githubusercontent.com/u/77930606?v=4
url: https://github.com/PelicanQ url: https://github.com/PelicanQ
- login: miguelgr
avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4
url: https://github.com/miguelgr
- login: WillHogan
avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=8a80356e3e7d5a417157aba7ea565dabc8678327&v=4
url: https://github.com/WillHogan
- login: my3 - login: my3
avatarUrl: https://avatars.githubusercontent.com/u/1825270?v=4 avatarUrl: https://avatars.githubusercontent.com/u/1825270?v=4
url: https://github.com/my3 url: https://github.com/my3
- login: Alisa-lisa - login: danielunderwood
avatarUrl: https://avatars.githubusercontent.com/u/4137964?u=e7e393504f554f4ff15863a1e01a5746863ef9ce&v=4 avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4
url: https://github.com/Alisa-lisa url: https://github.com/danielunderwood
- login: moonape1226 - login: rangulvers
avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 avatarUrl: https://avatars.githubusercontent.com/u/5235430?u=e254d4af4ace5a05fa58372ae677c7d26f0d5a53&v=4
url: https://github.com/moonape1226 url: https://github.com/rangulvers
- login: ddanier - login: ddanier
avatarUrl: https://avatars.githubusercontent.com/u/113563?u=ed1dc79de72f93bd78581f88ebc6952b62f472da&v=4 avatarUrl: https://avatars.githubusercontent.com/u/113563?u=ed1dc79de72f93bd78581f88ebc6952b62f472da&v=4
url: https://github.com/ddanier url: https://github.com/ddanier
@ -314,24 +323,18 @@ sponsors:
- login: slafs - login: slafs
avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4
url: https://github.com/slafs url: https://github.com/slafs
- login: ceb10n
avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4
url: https://github.com/ceb10n
- login: tochikuji - login: tochikuji
avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4 avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4
url: https://github.com/tochikuji url: https://github.com/tochikuji
- login: xncbf - login: miguelgr
avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=a80a7bb349555b277645632ed66639ff43400614&v=4 avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4
url: https://github.com/xncbf url: https://github.com/miguelgr
- login: DMantis - login: WillHogan
avatarUrl: https://avatars.githubusercontent.com/u/9536869?u=652dd0d49717803c0cbcbf44f7740e53cf2d4892&v=4 avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=8a80356e3e7d5a417157aba7ea565dabc8678327&v=4
url: https://github.com/DMantis url: https://github.com/WillHogan
- login: hard-coders - login: hard-coders
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4 avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
url: https://github.com/hard-coders url: https://github.com/hard-coders
- login: supdann
avatarUrl: https://avatars.githubusercontent.com/u/9986994?u=9671810f4ae9504c063227fee34fd47567ff6954&v=4
url: https://github.com/supdann
- login: mntolia - login: mntolia
avatarUrl: https://avatars.githubusercontent.com/u/10390224?v=4 avatarUrl: https://avatars.githubusercontent.com/u/10390224?v=4
url: https://github.com/mntolia url: https://github.com/mntolia
@ -344,12 +347,9 @@ sponsors:
- login: joshuatz - login: joshuatz
avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4 avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4
url: https://github.com/joshuatz url: https://github.com/joshuatz
- login: danielunderwood - login: nisutec
avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4 avatarUrl: https://avatars.githubusercontent.com/u/25281462?u=e562484c451fdfc59053163f64405f8eb262b8b0&v=4
url: https://github.com/danielunderwood url: https://github.com/nisutec
- login: rangulvers
avatarUrl: https://avatars.githubusercontent.com/u/5235430?u=e254d4af4ace5a05fa58372ae677c7d26f0d5a53&v=4
url: https://github.com/rangulvers
- login: sdevkota - login: sdevkota
avatarUrl: https://avatars.githubusercontent.com/u/5250987?u=4ed9a120c89805a8aefda1cbdc0cf6512e64d1b4&v=4 avatarUrl: https://avatars.githubusercontent.com/u/5250987?u=4ed9a120c89805a8aefda1cbdc0cf6512e64d1b4&v=4
url: https://github.com/sdevkota url: https://github.com/sdevkota
@ -365,39 +365,45 @@ sponsors:
- login: harsh183 - login: harsh183
avatarUrl: https://avatars.githubusercontent.com/u/7780198?v=4 avatarUrl: https://avatars.githubusercontent.com/u/7780198?v=4
url: https://github.com/harsh183 url: https://github.com/harsh183
- - login: KOZ39 - login: moonape1226
avatarUrl: https://avatars.githubusercontent.com/u/38822500?u=9dfc0a697df1c9628f08e20dc3fb17b1afc4e5a7&v=4 avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4
url: https://github.com/KOZ39 url: https://github.com/moonape1226
- login: rwxd - login: xncbf
avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=cd04a39e3655923be4f25c2ba8a5a07b3da3230a&v=4 avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=a80a7bb349555b277645632ed66639ff43400614&v=4
url: https://github.com/rwxd url: https://github.com/xncbf
- login: morzan1001 - login: DMantis
avatarUrl: https://avatars.githubusercontent.com/u/9536869?u=652dd0d49717803c0cbcbf44f7740e53cf2d4892&v=4
url: https://github.com/DMantis
- - login: morzan1001
avatarUrl: https://avatars.githubusercontent.com/u/47593005?u=c30ab7230f82a12a9b938dcb54f84a996931409a&v=4 avatarUrl: https://avatars.githubusercontent.com/u/47593005?u=c30ab7230f82a12a9b938dcb54f84a996931409a&v=4
url: https://github.com/morzan1001 url: https://github.com/morzan1001
- login: azharthegeek
avatarUrl: https://avatars.githubusercontent.com/u/51288109?u=0987b2a9f39c21ccb071b6bdce0fc60d8492f8e8&v=4
url: https://github.com/azharthegeek
- login: Olegt0rr
avatarUrl: https://avatars.githubusercontent.com/u/25399456?u=3e87b5239a2f4600975ba13be73054f8567c6060&v=4
url: https://github.com/Olegt0rr
- login: larsyngvelundin - login: larsyngvelundin
avatarUrl: https://avatars.githubusercontent.com/u/34173819?u=74958599695bf83ac9f1addd935a51548a10c6b0&v=4 avatarUrl: https://avatars.githubusercontent.com/u/34173819?u=74958599695bf83ac9f1addd935a51548a10c6b0&v=4
url: https://github.com/larsyngvelundin url: https://github.com/larsyngvelundin
- login: andrecorumba - login: andrecorumba
avatarUrl: https://avatars.githubusercontent.com/u/37807517?u=9b9be3b41da9bda60957da9ef37b50dbf65baa61&v=4 avatarUrl: https://avatars.githubusercontent.com/u/37807517?u=9b9be3b41da9bda60957da9ef37b50dbf65baa61&v=4
url: https://github.com/andrecorumba url: https://github.com/andrecorumba
- login: ChenPu2002 - login: KOZ39
avatarUrl: https://avatars.githubusercontent.com/u/113831763?v=4 avatarUrl: https://avatars.githubusercontent.com/u/38822500?u=9dfc0a697df1c9628f08e20dc3fb17b1afc4e5a7&v=4
url: https://github.com/ChenPu2002 url: https://github.com/KOZ39
- login: rwxd
avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=cd04a39e3655923be4f25c2ba8a5a07b3da3230a&v=4
url: https://github.com/rwxd
- login: hippoley
avatarUrl: https://avatars.githubusercontent.com/u/135493401?u=1164ef48a645a7c12664fabc1638fbb7e1c459b0&v=4
url: https://github.com/hippoley
- login: CoderDeltaLAN - login: CoderDeltaLAN
avatarUrl: https://avatars.githubusercontent.com/u/152043745?u=4ff541efffb7d134e60c5fcf2dd1e343f90bb782&v=4 avatarUrl: https://avatars.githubusercontent.com/u/152043745?u=4ff541efffb7d134e60c5fcf2dd1e343f90bb782&v=4
url: https://github.com/CoderDeltaLAN url: https://github.com/CoderDeltaLAN
- login: aghents - login: chris1ding1
avatarUrl: https://avatars.githubusercontent.com/u/60949885?u=d8616ddf22cf998a712cdceefd6a0256a178fe9d&v=4 avatarUrl: https://avatars.githubusercontent.com/u/194386334?u=5500604b50e35ed8a5aeb82ce34aa5d3ee3f88c7&v=4
url: https://github.com/aghents url: https://github.com/chris1ding1
- login: 0ne-stone - login: onestn
avatarUrl: https://avatars.githubusercontent.com/u/62360849?u=746dd21c34e7e06eefb11b03e8bb01aaae3c2a4f&v=4 avatarUrl: https://avatars.githubusercontent.com/u/62360849?u=746dd21c34e7e06eefb11b03e8bb01aaae3c2a4f&v=4
url: https://github.com/0ne-stone url: https://github.com/onestn
- login: Rubinskiy
avatarUrl: https://avatars.githubusercontent.com/u/62457878?u=f2e35ed3d196a99cfadb5a29a91950342af07e34&v=4
url: https://github.com/Rubinskiy
- login: nayasinghania - login: nayasinghania
avatarUrl: https://avatars.githubusercontent.com/u/74111380?u=752e99a5e139389fdc0a0677122adc08438eb076&v=4 avatarUrl: https://avatars.githubusercontent.com/u/74111380?u=752e99a5e139389fdc0a0677122adc08438eb076&v=4
url: https://github.com/nayasinghania url: https://github.com/nayasinghania
@ -407,6 +413,9 @@ sponsors:
- login: andreagrandi - login: andreagrandi
avatarUrl: https://avatars.githubusercontent.com/u/636391?u=13d90cb8ec313593a5b71fbd4e33b78d6da736f5&v=4 avatarUrl: https://avatars.githubusercontent.com/u/636391?u=13d90cb8ec313593a5b71fbd4e33b78d6da736f5&v=4
url: https://github.com/andreagrandi url: https://github.com/andreagrandi
- login: Olegt0rr
avatarUrl: https://avatars.githubusercontent.com/u/25399456?u=3e87b5239a2f4600975ba13be73054f8567c6060&v=4
url: https://github.com/Olegt0rr
- login: msserpa - login: msserpa
avatarUrl: https://avatars.githubusercontent.com/u/6334934?u=82c4489eb1559d88d2990d60001901b14f722bbb&v=4 avatarUrl: https://avatars.githubusercontent.com/u/6334934?u=82c4489eb1559d88d2990d60001901b14f722bbb&v=4
url: https://github.com/msserpa url: https://github.com/msserpa

View File

@ -1,3 +1,7 @@
keystone:
- url: https://fastapicloud.com
title: FastAPI Cloud. By the same team behind FastAPI. You code. We Cloud.
img: https://fastapi.tiangolo.com/img/sponsors/fastapicloud.png
gold: gold:
- url: https://blockbee.io?ref=fastapi - url: https://blockbee.io?ref=fastapi
title: BlockBee Cryptocurrency Payment Gateway title: BlockBee Cryptocurrency Payment Gateway
@ -26,6 +30,9 @@ gold:
- url: https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi - url: https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi
title: Deploy enterprise applications at startup speed title: Deploy enterprise applications at startup speed
img: https://fastapi.tiangolo.com/img/sponsors/railway.png img: https://fastapi.tiangolo.com/img/sponsors/railway.png
- url: https://serpapi.com/?utm_source=fastapi_website
title: "SerpApi: Web Search API"
img: https://fastapi.tiangolo.com/img/sponsors/serpapi.png
silver: silver:
- url: https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display - url: https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display
title: Pay as you go for market data title: Pay as you go for market data

View File

@ -1,81 +1,86 @@
- name: full-stack-fastapi-template - name: full-stack-fastapi-template
html_url: https://github.com/fastapi/full-stack-fastapi-template html_url: https://github.com/fastapi/full-stack-fastapi-template
stars: 38085 stars: 38779
owner_login: fastapi owner_login: fastapi
owner_html_url: https://github.com/fastapi owner_html_url: https://github.com/fastapi
- name: Hello-Python - name: Hello-Python
html_url: https://github.com/mouredev/Hello-Python html_url: https://github.com/mouredev/Hello-Python
stars: 32243 stars: 32726
owner_login: mouredev owner_login: mouredev
owner_html_url: https://github.com/mouredev owner_html_url: https://github.com/mouredev
- name: serve - name: serve
html_url: https://github.com/jina-ai/serve html_url: https://github.com/jina-ai/serve
stars: 21754 stars: 21779
owner_login: jina-ai owner_login: jina-ai
owner_html_url: https://github.com/jina-ai owner_html_url: https://github.com/jina-ai
- name: HivisionIDPhotos - name: HivisionIDPhotos
html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos
stars: 19400 stars: 20028
owner_login: Zeyi-Lin owner_login: Zeyi-Lin
owner_html_url: https://github.com/Zeyi-Lin owner_html_url: https://github.com/Zeyi-Lin
- name: sqlmodel - name: sqlmodel
html_url: https://github.com/fastapi/sqlmodel html_url: https://github.com/fastapi/sqlmodel
stars: 16859 stars: 17038
owner_login: fastapi owner_login: fastapi
owner_html_url: https://github.com/fastapi owner_html_url: https://github.com/fastapi
- name: Douyin_TikTok_Download_API - name: Douyin_TikTok_Download_API
html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API
stars: 14452 stars: 14786
owner_login: Evil0ctal owner_login: Evil0ctal
owner_html_url: https://github.com/Evil0ctal owner_html_url: https://github.com/Evil0ctal
- name: fastapi-best-practices - name: fastapi-best-practices
html_url: https://github.com/zhanymkanov/fastapi-best-practices html_url: https://github.com/zhanymkanov/fastapi-best-practices
stars: 13613 stars: 13968
owner_login: zhanymkanov owner_login: zhanymkanov
owner_html_url: https://github.com/zhanymkanov owner_html_url: https://github.com/zhanymkanov
- name: machine-learning-zoomcamp
html_url: https://github.com/DataTalksClub/machine-learning-zoomcamp
stars: 12171
owner_login: DataTalksClub
owner_html_url: https://github.com/DataTalksClub
- name: fastapi_mcp - name: fastapi_mcp
html_url: https://github.com/tadata-org/fastapi_mcp html_url: https://github.com/tadata-org/fastapi_mcp
stars: 10624 stars: 10976
owner_login: tadata-org owner_login: tadata-org
owner_html_url: https://github.com/tadata-org owner_html_url: https://github.com/tadata-org
- name: awesome-fastapi - name: awesome-fastapi
html_url: https://github.com/mjhea0/awesome-fastapi html_url: https://github.com/mjhea0/awesome-fastapi
stars: 10415 stars: 10618
owner_login: mjhea0 owner_login: mjhea0
owner_html_url: https://github.com/mjhea0 owner_html_url: https://github.com/mjhea0
- name: FastUI
html_url: https://github.com/pydantic/FastUI
stars: 8879
owner_login: pydantic
owner_html_url: https://github.com/pydantic
- name: XHS-Downloader
html_url: https://github.com/JoeanAmier/XHS-Downloader
stars: 8824
owner_login: JoeanAmier
owner_html_url: https://github.com/JoeanAmier
- name: SurfSense - name: SurfSense
html_url: https://github.com/MODSetter/SurfSense html_url: https://github.com/MODSetter/SurfSense
stars: 8257 stars: 10243
owner_login: MODSetter owner_login: MODSetter
owner_html_url: https://github.com/MODSetter owner_html_url: https://github.com/MODSetter
- name: FileCodeBox - name: XHS-Downloader
html_url: https://github.com/vastsa/FileCodeBox html_url: https://github.com/JoeanAmier/XHS-Downloader
stars: 7367 stars: 9062
owner_login: vastsa owner_login: JoeanAmier
owner_html_url: https://github.com/vastsa owner_html_url: https://github.com/JoeanAmier
- name: FastUI
html_url: https://github.com/pydantic/FastUI
stars: 8892
owner_login: pydantic
owner_html_url: https://github.com/pydantic
- name: polar - name: polar
html_url: https://github.com/polarsource/polar html_url: https://github.com/polarsource/polar
stars: 7291 stars: 8084
owner_login: polarsource owner_login: polarsource
owner_html_url: https://github.com/polarsource owner_html_url: https://github.com/polarsource
- name: FileCodeBox
html_url: https://github.com/vastsa/FileCodeBox
stars: 7494
owner_login: vastsa
owner_html_url: https://github.com/vastsa
- name: nonebot2 - name: nonebot2
html_url: https://github.com/nonebot/nonebot2 html_url: https://github.com/nonebot/nonebot2
stars: 7065 stars: 7128
owner_login: nonebot owner_login: nonebot
owner_html_url: https://github.com/nonebot owner_html_url: https://github.com/nonebot
- name: hatchet - name: hatchet
html_url: https://github.com/hatchet-dev/hatchet html_url: https://github.com/hatchet-dev/hatchet
stars: 6070 stars: 6155
owner_login: hatchet-dev owner_login: hatchet-dev
owner_html_url: https://github.com/hatchet-dev owner_html_url: https://github.com/hatchet-dev
- name: serge - name: serge
@ -85,27 +90,27 @@
owner_html_url: https://github.com/serge-chat owner_html_url: https://github.com/serge-chat
- name: fastapi-users - name: fastapi-users
html_url: https://github.com/fastapi-users/fastapi-users html_url: https://github.com/fastapi-users/fastapi-users
stars: 5599 stars: 5683
owner_login: fastapi-users owner_login: fastapi-users
owner_html_url: https://github.com/fastapi-users owner_html_url: https://github.com/fastapi-users
- name: strawberry - name: strawberry
html_url: https://github.com/strawberry-graphql/strawberry html_url: https://github.com/strawberry-graphql/strawberry
stars: 4422 stars: 4452
owner_login: strawberry-graphql owner_login: strawberry-graphql
owner_html_url: https://github.com/strawberry-graphql owner_html_url: https://github.com/strawberry-graphql
- name: chatgpt-web-share - name: chatgpt-web-share
html_url: https://github.com/chatpire/chatgpt-web-share html_url: https://github.com/chatpire/chatgpt-web-share
stars: 4301 stars: 4296
owner_login: chatpire owner_login: chatpire
owner_html_url: https://github.com/chatpire owner_html_url: https://github.com/chatpire
- name: poem - name: poem
html_url: https://github.com/poem-web/poem html_url: https://github.com/poem-web/poem
stars: 4197 stars: 4235
owner_login: poem-web owner_login: poem-web
owner_html_url: https://github.com/poem-web owner_html_url: https://github.com/poem-web
- name: dynaconf - name: dynaconf
html_url: https://github.com/dynaconf/dynaconf html_url: https://github.com/dynaconf/dynaconf
stars: 4144 stars: 4174
owner_login: dynaconf owner_login: dynaconf
owner_html_url: https://github.com/dynaconf owner_html_url: https://github.com/dynaconf
- name: atrilabs-engine - name: atrilabs-engine
@ -115,42 +120,42 @@
owner_html_url: https://github.com/Atri-Labs owner_html_url: https://github.com/Atri-Labs
- name: Kokoro-FastAPI - name: Kokoro-FastAPI
html_url: https://github.com/remsky/Kokoro-FastAPI html_url: https://github.com/remsky/Kokoro-FastAPI
stars: 3739 stars: 3875
owner_login: remsky owner_login: remsky
owner_html_url: https://github.com/remsky owner_html_url: https://github.com/remsky
- name: logfire - name: logfire
html_url: https://github.com/pydantic/logfire html_url: https://github.com/pydantic/logfire
stars: 3614 stars: 3717
owner_login: pydantic owner_login: pydantic
owner_html_url: https://github.com/pydantic owner_html_url: https://github.com/pydantic
- name: LitServe - name: LitServe
html_url: https://github.com/Lightning-AI/LitServe html_url: https://github.com/Lightning-AI/LitServe
stars: 3578 stars: 3615
owner_login: Lightning-AI owner_login: Lightning-AI
owner_html_url: https://github.com/Lightning-AI owner_html_url: https://github.com/Lightning-AI
- name: datamodel-code-generator - name: datamodel-code-generator
html_url: https://github.com/koxudaxi/datamodel-code-generator html_url: https://github.com/koxudaxi/datamodel-code-generator
stars: 3496 stars: 3554
owner_login: koxudaxi owner_login: koxudaxi
owner_html_url: https://github.com/koxudaxi owner_html_url: https://github.com/koxudaxi
- name: farfalle
html_url: https://github.com/rashadphz/farfalle
stars: 3459
owner_login: rashadphz
owner_html_url: https://github.com/rashadphz
- name: fastapi-admin
html_url: https://github.com/fastapi-admin/fastapi-admin
stars: 3456
owner_login: fastapi-admin
owner_html_url: https://github.com/fastapi-admin
- name: huma - name: huma
html_url: https://github.com/danielgtaylor/huma html_url: https://github.com/danielgtaylor/huma
stars: 3447 stars: 3521
owner_login: danielgtaylor owner_login: danielgtaylor
owner_html_url: https://github.com/danielgtaylor owner_html_url: https://github.com/danielgtaylor
- name: fastapi-admin
html_url: https://github.com/fastapi-admin/fastapi-admin
stars: 3497
owner_login: fastapi-admin
owner_html_url: https://github.com/fastapi-admin
- name: farfalle
html_url: https://github.com/rashadphz/farfalle
stars: 3476
owner_login: rashadphz
owner_html_url: https://github.com/rashadphz
- name: tracecat - name: tracecat
html_url: https://github.com/TracecatHQ/tracecat html_url: https://github.com/TracecatHQ/tracecat
stars: 3254 stars: 3310
owner_login: TracecatHQ owner_login: TracecatHQ
owner_html_url: https://github.com/TracecatHQ owner_html_url: https://github.com/TracecatHQ
- name: opyrator - name: opyrator
@ -160,336 +165,331 @@
owner_html_url: https://github.com/ml-tooling owner_html_url: https://github.com/ml-tooling
- name: docarray - name: docarray
html_url: https://github.com/docarray/docarray html_url: https://github.com/docarray/docarray
stars: 3107 stars: 3108
owner_login: docarray owner_login: docarray
owner_html_url: https://github.com/docarray owner_html_url: https://github.com/docarray
- name: fastapi-realworld-example-app - name: fastapi-realworld-example-app
html_url: https://github.com/nsidnev/fastapi-realworld-example-app html_url: https://github.com/nsidnev/fastapi-realworld-example-app
stars: 2936 stars: 2945
owner_login: nsidnev owner_login: nsidnev
owner_html_url: https://github.com/nsidnev owner_html_url: https://github.com/nsidnev
- name: uvicorn-gunicorn-fastapi-docker - name: uvicorn-gunicorn-fastapi-docker
html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker
stars: 2804 stars: 2809
owner_login: tiangolo owner_login: tiangolo
owner_html_url: https://github.com/tiangolo owner_html_url: https://github.com/tiangolo
- name: best-of-web-python - name: devpush
html_url: https://github.com/ml-tooling/best-of-web-python html_url: https://github.com/hunvreus/devpush
stars: 2610 stars: 2784
owner_login: ml-tooling owner_login: hunvreus
owner_html_url: https://github.com/ml-tooling owner_html_url: https://github.com/hunvreus
- name: mcp-context-forge - name: mcp-context-forge
html_url: https://github.com/IBM/mcp-context-forge html_url: https://github.com/IBM/mcp-context-forge
stars: 2572 stars: 2763
owner_login: IBM owner_login: IBM
owner_html_url: https://github.com/IBM owner_html_url: https://github.com/IBM
- name: best-of-web-python
html_url: https://github.com/ml-tooling/best-of-web-python
stars: 2630
owner_login: ml-tooling
owner_html_url: https://github.com/ml-tooling
- name: fastapi-react - name: fastapi-react
html_url: https://github.com/Buuntu/fastapi-react html_url: https://github.com/Buuntu/fastapi-react
stars: 2451 stars: 2464
owner_login: Buuntu owner_login: Buuntu
owner_html_url: https://github.com/Buuntu owner_html_url: https://github.com/Buuntu
- name: RasaGPT
html_url: https://github.com/paulpierre/RasaGPT
stars: 2441
owner_login: paulpierre
owner_html_url: https://github.com/paulpierre
- name: FastAPI-template - name: FastAPI-template
html_url: https://github.com/s3rius/FastAPI-template html_url: https://github.com/s3rius/FastAPI-template
stars: 2424 stars: 2453
owner_login: s3rius owner_login: s3rius
owner_html_url: https://github.com/s3rius owner_html_url: https://github.com/s3rius
- name: RasaGPT
html_url: https://github.com/paulpierre/RasaGPT
stars: 2444
owner_login: paulpierre
owner_html_url: https://github.com/paulpierre
- name: sqladmin - name: sqladmin
html_url: https://github.com/aminalaee/sqladmin html_url: https://github.com/aminalaee/sqladmin
stars: 2357 stars: 2423
owner_login: aminalaee owner_login: aminalaee
owner_html_url: https://github.com/aminalaee owner_html_url: https://github.com/aminalaee
- name: nextpy - name: nextpy
html_url: https://github.com/dot-agent/nextpy html_url: https://github.com/dot-agent/nextpy
stars: 2324 stars: 2325
owner_login: dot-agent owner_login: dot-agent
owner_html_url: https://github.com/dot-agent owner_html_url: https://github.com/dot-agent
- name: supabase-py - name: supabase-py
html_url: https://github.com/supabase/supabase-py html_url: https://github.com/supabase/supabase-py
stars: 2236 stars: 2292
owner_login: supabase owner_login: supabase
owner_html_url: https://github.com/supabase owner_html_url: https://github.com/supabase
- name: 30-Days-of-Python - name: 30-Days-of-Python
html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python
stars: 2210 stars: 2214
owner_login: codingforentrepreneurs owner_login: codingforentrepreneurs
owner_html_url: https://github.com/codingforentrepreneurs owner_html_url: https://github.com/codingforentrepreneurs
- name: Yuxi-Know
html_url: https://github.com/xerrors/Yuxi-Know
stars: 2212
owner_login: xerrors
owner_html_url: https://github.com/xerrors
- name: langserve - name: langserve
html_url: https://github.com/langchain-ai/langserve html_url: https://github.com/langchain-ai/langserve
stars: 2171 stars: 2191
owner_login: langchain-ai owner_login: langchain-ai
owner_html_url: https://github.com/langchain-ai owner_html_url: https://github.com/langchain-ai
- name: fastapi-utils - name: fastapi-utils
html_url: https://github.com/fastapiutils/fastapi-utils html_url: https://github.com/fastapiutils/fastapi-utils
stars: 2164 stars: 2185
owner_login: fastapiutils owner_login: fastapiutils
owner_html_url: https://github.com/fastapiutils owner_html_url: https://github.com/fastapiutils
- name: solara - name: solara
html_url: https://github.com/widgetti/solara html_url: https://github.com/widgetti/solara
stars: 2102 stars: 2111
owner_login: widgetti owner_login: widgetti
owner_html_url: https://github.com/widgetti owner_html_url: https://github.com/widgetti
- name: Yuxi-Know
html_url: https://github.com/xerrors/Yuxi-Know
stars: 1995
owner_login: xerrors
owner_html_url: https://github.com/xerrors
- name: mangum - name: mangum
html_url: https://github.com/Kludex/mangum html_url: https://github.com/Kludex/mangum
stars: 1989 stars: 2011
owner_login: Kludex owner_login: Kludex
owner_html_url: https://github.com/Kludex owner_html_url: https://github.com/Kludex
- name: python-week-2022
html_url: https://github.com/rochacbruno/python-week-2022
stars: 1816
owner_login: rochacbruno
owner_html_url: https://github.com/rochacbruno
- name: agentkit - name: agentkit
html_url: https://github.com/BCG-X-Official/agentkit html_url: https://github.com/BCG-X-Official/agentkit
stars: 1789 stars: 1826
owner_login: BCG-X-Official owner_login: BCG-X-Official
owner_html_url: https://github.com/BCG-X-Official owner_html_url: https://github.com/BCG-X-Official
- name: python-week-2022
html_url: https://github.com/rochacbruno/python-week-2022
stars: 1815
owner_login: rochacbruno
owner_html_url: https://github.com/rochacbruno
- name: manage-fastapi - name: manage-fastapi
html_url: https://github.com/ycd/manage-fastapi html_url: https://github.com/ycd/manage-fastapi
stars: 1780 stars: 1787
owner_login: ycd owner_login: ycd
owner_html_url: https://github.com/ycd owner_html_url: https://github.com/ycd
- name: ormar - name: ormar
html_url: https://github.com/collerek/ormar html_url: https://github.com/collerek/ormar
stars: 1777 stars: 1780
owner_login: collerek owner_login: collerek
owner_html_url: https://github.com/collerek owner_html_url: https://github.com/collerek
- name: vue-fastapi-admin
html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin
stars: 1758
owner_login: mizhexiaoxiao
owner_html_url: https://github.com/mizhexiaoxiao
- name: openapi-python-client - name: openapi-python-client
html_url: https://github.com/openapi-generators/openapi-python-client html_url: https://github.com/openapi-generators/openapi-python-client
stars: 1707 stars: 1731
owner_login: openapi-generators owner_login: openapi-generators
owner_html_url: https://github.com/openapi-generators owner_html_url: https://github.com/openapi-generators
- name: piccolo - name: piccolo
html_url: https://github.com/piccolo-orm/piccolo html_url: https://github.com/piccolo-orm/piccolo
stars: 1695 stars: 1711
owner_login: piccolo-orm owner_login: piccolo-orm
owner_html_url: https://github.com/piccolo-orm owner_html_url: https://github.com/piccolo-orm
- name: vue-fastapi-admin
html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin
stars: 1695
owner_login: mizhexiaoxiao
owner_html_url: https://github.com/mizhexiaoxiao
- name: fastapi-cache - name: fastapi-cache
html_url: https://github.com/long2ice/fastapi-cache html_url: https://github.com/long2ice/fastapi-cache
stars: 1653 stars: 1677
owner_login: long2ice owner_login: long2ice
owner_html_url: https://github.com/long2ice owner_html_url: https://github.com/long2ice
- name: slowapi
html_url: https://github.com/laurentS/slowapi
stars: 1669
owner_login: laurentS
owner_html_url: https://github.com/laurentS
- name: langchain-serve - name: langchain-serve
html_url: https://github.com/jina-ai/langchain-serve html_url: https://github.com/jina-ai/langchain-serve
stars: 1635 stars: 1632
owner_login: jina-ai owner_login: jina-ai
owner_html_url: https://github.com/jina-ai owner_html_url: https://github.com/jina-ai
- name: termpair - name: termpair
html_url: https://github.com/cs01/termpair html_url: https://github.com/cs01/termpair
stars: 1624 stars: 1621
owner_login: cs01 owner_login: cs01
owner_html_url: https://github.com/cs01 owner_html_url: https://github.com/cs01
- name: slowapi - name: FastAPI-boilerplate
html_url: https://github.com/laurentS/slowapi html_url: https://github.com/benavlabs/FastAPI-boilerplate
stars: 1620 stars: 1596
owner_login: laurentS owner_login: benavlabs
owner_html_url: https://github.com/laurentS owner_html_url: https://github.com/benavlabs
- name: coronavirus-tracker-api - name: coronavirus-tracker-api
html_url: https://github.com/ExpDev07/coronavirus-tracker-api html_url: https://github.com/ExpDev07/coronavirus-tracker-api
stars: 1576 stars: 1573
owner_login: ExpDev07 owner_login: ExpDev07
owner_html_url: https://github.com/ExpDev07 owner_html_url: https://github.com/ExpDev07
- name: fastapi-crudrouter - name: fastapi-crudrouter
html_url: https://github.com/awtkns/fastapi-crudrouter html_url: https://github.com/awtkns/fastapi-crudrouter
stars: 1546 stars: 1553
owner_login: awtkns owner_login: awtkns
owner_html_url: https://github.com/awtkns owner_html_url: https://github.com/awtkns
- name: FastAPI-boilerplate
html_url: https://github.com/benavlabs/FastAPI-boilerplate
stars: 1516
owner_login: benavlabs
owner_html_url: https://github.com/benavlabs
- name: awesome-fastapi-projects - name: awesome-fastapi-projects
html_url: https://github.com/Kludex/awesome-fastapi-projects html_url: https://github.com/Kludex/awesome-fastapi-projects
stars: 1481 stars: 1485
owner_login: Kludex owner_login: Kludex
owner_html_url: https://github.com/Kludex owner_html_url: https://github.com/Kludex
- name: fastapi-pagination - name: fastapi-pagination
html_url: https://github.com/uriyyo/fastapi-pagination html_url: https://github.com/uriyyo/fastapi-pagination
stars: 1453 stars: 1473
owner_login: uriyyo owner_login: uriyyo
owner_html_url: https://github.com/uriyyo owner_html_url: https://github.com/uriyyo
- name: bracket - name: bracket
html_url: https://github.com/evroon/bracket html_url: https://github.com/evroon/bracket
stars: 1415 stars: 1470
owner_login: evroon owner_login: evroon
owner_html_url: https://github.com/evroon owner_html_url: https://github.com/evroon
- name: awesome-python-resources
html_url: https://github.com/DjangoEx/awesome-python-resources
stars: 1413
owner_login: DjangoEx
owner_html_url: https://github.com/DjangoEx
- name: fastapi-boilerplate
html_url: https://github.com/teamhide/fastapi-boilerplate
stars: 1406
owner_login: teamhide
owner_html_url: https://github.com/teamhide
- name: budgetml
html_url: https://github.com/ebhy/budgetml
stars: 1346
owner_login: ebhy
owner_html_url: https://github.com/ebhy
- name: fastapi-amis-admin
html_url: https://github.com/amisadmin/fastapi-amis-admin
stars: 1342
owner_login: amisadmin
owner_html_url: https://github.com/amisadmin
- name: fastapi-langgraph-agent-production-ready-template - name: fastapi-langgraph-agent-production-ready-template
html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template
stars: 1334 stars: 1456
owner_login: wassim249 owner_login: wassim249
owner_html_url: https://github.com/wassim249 owner_html_url: https://github.com/wassim249
- name: fastapi-boilerplate
html_url: https://github.com/teamhide/fastapi-boilerplate
stars: 1424
owner_login: teamhide
owner_html_url: https://github.com/teamhide
- name: awesome-python-resources
html_url: https://github.com/DjangoEx/awesome-python-resources
stars: 1420
owner_login: DjangoEx
owner_html_url: https://github.com/DjangoEx
- name: fastapi-amis-admin
html_url: https://github.com/amisadmin/fastapi-amis-admin
stars: 1363
owner_login: amisadmin
owner_html_url: https://github.com/amisadmin
- name: fastcrud
html_url: https://github.com/benavlabs/fastcrud
stars: 1362
owner_login: benavlabs
owner_html_url: https://github.com/benavlabs
- name: budgetml
html_url: https://github.com/ebhy/budgetml
stars: 1345
owner_login: ebhy
owner_html_url: https://github.com/ebhy
- name: fastapi-tutorial - name: fastapi-tutorial
html_url: https://github.com/liaogx/fastapi-tutorial html_url: https://github.com/liaogx/fastapi-tutorial
stars: 1303 stars: 1315
owner_login: liaogx owner_login: liaogx
owner_html_url: https://github.com/liaogx owner_html_url: https://github.com/liaogx
- name: fastapi_best_architecture - name: fastapi_best_architecture
html_url: https://github.com/fastapi-practices/fastapi_best_architecture html_url: https://github.com/fastapi-practices/fastapi_best_architecture
stars: 1276 stars: 1311
owner_login: fastapi-practices owner_login: fastapi-practices
owner_html_url: https://github.com/fastapi-practices owner_html_url: https://github.com/fastapi-practices
- name: fastcrud
html_url: https://github.com/benavlabs/fastcrud
stars: 1272
owner_login: benavlabs
owner_html_url: https://github.com/benavlabs
- name: fastapi-code-generator - name: fastapi-code-generator
html_url: https://github.com/koxudaxi/fastapi-code-generator html_url: https://github.com/koxudaxi/fastapi-code-generator
stars: 1253 stars: 1270
owner_login: koxudaxi owner_login: koxudaxi
owner_html_url: https://github.com/koxudaxi owner_html_url: https://github.com/koxudaxi
- name: prometheus-fastapi-instrumentator - name: prometheus-fastapi-instrumentator
html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator
stars: 1246 stars: 1264
owner_login: trallnag owner_login: trallnag
owner_html_url: https://github.com/trallnag owner_html_url: https://github.com/trallnag
- name: bolt-python
html_url: https://github.com/slackapi/bolt-python
stars: 1221
owner_login: slackapi
owner_html_url: https://github.com/slackapi
- name: bedrock-chat - name: bedrock-chat
html_url: https://github.com/aws-samples/bedrock-chat html_url: https://github.com/aws-samples/bedrock-chat
stars: 1220 stars: 1243
owner_login: aws-samples owner_login: aws-samples
owner_html_url: https://github.com/aws-samples owner_html_url: https://github.com/aws-samples
- name: bolt-python
html_url: https://github.com/slackapi/bolt-python
stars: 1238
owner_login: slackapi
owner_html_url: https://github.com/slackapi
- name: fastapi_production_template - name: fastapi_production_template
html_url: https://github.com/zhanymkanov/fastapi_production_template html_url: https://github.com/zhanymkanov/fastapi_production_template
stars: 1202 stars: 1209
owner_login: zhanymkanov owner_login: zhanymkanov
owner_html_url: https://github.com/zhanymkanov owner_html_url: https://github.com/zhanymkanov
- name: fastapi-scaff - name: fastapi-scaff
html_url: https://github.com/atpuxiner/fastapi-scaff html_url: https://github.com/atpuxiner/fastapi-scaff
stars: 1193 stars: 1200
owner_login: atpuxiner owner_login: atpuxiner
owner_html_url: https://github.com/atpuxiner owner_html_url: https://github.com/atpuxiner
- name: langchain-extract - name: langchain-extract
html_url: https://github.com/langchain-ai/langchain-extract html_url: https://github.com/langchain-ai/langchain-extract
stars: 1164 stars: 1173
owner_login: langchain-ai owner_login: langchain-ai
owner_html_url: https://github.com/langchain-ai owner_html_url: https://github.com/langchain-ai
- name: fastapi-alembic-sqlmodel-async - name: fastapi-alembic-sqlmodel-async
html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async
stars: 1149 stars: 1162
owner_login: jonra1993 owner_login: jonra1993
owner_html_url: https://github.com/jonra1993 owner_html_url: https://github.com/jonra1993
- name: odmantic - name: odmantic
html_url: https://github.com/art049/odmantic html_url: https://github.com/art049/odmantic
stars: 1133 stars: 1137
owner_login: art049 owner_login: art049
owner_html_url: https://github.com/art049 owner_html_url: https://github.com/art049
- name: restish - name: restish
html_url: https://github.com/rest-sh/restish html_url: https://github.com/rest-sh/restish
stars: 1122 stars: 1129
owner_login: rest-sh owner_login: rest-sh
owner_html_url: https://github.com/rest-sh owner_html_url: https://github.com/rest-sh
- name: runhouse - name: kubetorch
html_url: https://github.com/run-house/runhouse html_url: https://github.com/run-house/kubetorch
stars: 1047 stars: 1065
owner_login: run-house owner_login: run-house
owner_html_url: https://github.com/run-house owner_html_url: https://github.com/run-house
- name: flock - name: flock
html_url: https://github.com/Onelevenvy/flock html_url: https://github.com/Onelevenvy/flock
stars: 1027 stars: 1039
owner_login: Onelevenvy owner_login: Onelevenvy
owner_html_url: https://github.com/Onelevenvy owner_html_url: https://github.com/Onelevenvy
- name: authx - name: authx
html_url: https://github.com/yezz123/authx html_url: https://github.com/yezz123/authx
stars: 999 stars: 1017
owner_login: yezz123 owner_login: yezz123
owner_html_url: https://github.com/yezz123 owner_html_url: https://github.com/yezz123
- name: autollm - name: autollm
html_url: https://github.com/viddexa/autollm html_url: https://github.com/viddexa/autollm
stars: 999 stars: 997
owner_login: viddexa owner_login: viddexa
owner_html_url: https://github.com/viddexa owner_html_url: https://github.com/viddexa
- name: lanarky - name: lanarky
html_url: https://github.com/ajndkr/lanarky html_url: https://github.com/ajndkr/lanarky
stars: 995 stars: 993
owner_login: ajndkr owner_login: ajndkr
owner_html_url: https://github.com/ajndkr owner_html_url: https://github.com/ajndkr
- name: titiler
html_url: https://github.com/developmentseed/titiler
stars: 952
owner_login: developmentseed
owner_html_url: https://github.com/developmentseed
- name: energy-forecasting
html_url: https://github.com/iusztinpaul/energy-forecasting
stars: 946
owner_login: iusztinpaul
owner_html_url: https://github.com/iusztinpaul
- name: secure
html_url: https://github.com/TypeError/secure
stars: 944
owner_login: TypeError
owner_html_url: https://github.com/TypeError
- name: langcorn
html_url: https://github.com/msoedov/langcorn
stars: 934
owner_login: msoedov
owner_html_url: https://github.com/msoedov
- name: RuoYi-Vue3-FastAPI - name: RuoYi-Vue3-FastAPI
html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI
stars: 930 stars: 974
owner_login: insistence owner_login: insistence
owner_html_url: https://github.com/insistence owner_html_url: https://github.com/insistence
- name: aktools - name: aktools
html_url: https://github.com/akfamily/aktools html_url: https://github.com/akfamily/aktools
stars: 916 stars: 972
owner_login: akfamily owner_login: akfamily
owner_html_url: https://github.com/akfamily owner_html_url: https://github.com/akfamily
- name: titiler
html_url: https://github.com/developmentseed/titiler
stars: 965
owner_login: developmentseed
owner_html_url: https://github.com/developmentseed
- name: secure
html_url: https://github.com/TypeError/secure
stars: 953
owner_login: TypeError
owner_html_url: https://github.com/TypeError
- name: energy-forecasting
html_url: https://github.com/iusztinpaul/energy-forecasting
stars: 949
owner_login: iusztinpaul
owner_html_url: https://github.com/iusztinpaul
- name: every-pdf - name: every-pdf
html_url: https://github.com/DDULDDUCK/every-pdf html_url: https://github.com/DDULDDUCK/every-pdf
stars: 907 stars: 942
owner_login: DDULDDUCK owner_login: DDULDDUCK
owner_html_url: https://github.com/DDULDDUCK owner_html_url: https://github.com/DDULDDUCK
- name: marker-api - name: langcorn
html_url: https://github.com/adithya-s-k/marker-api html_url: https://github.com/msoedov/langcorn
stars: 903 stars: 933
owner_login: adithya-s-k owner_login: msoedov
owner_html_url: https://github.com/adithya-s-k owner_html_url: https://github.com/msoedov
- name: fastapi-observability - name: fastapi-observability
html_url: https://github.com/blueswen/fastapi-observability html_url: https://github.com/blueswen/fastapi-observability
stars: 902 stars: 923
owner_login: blueswen owner_login: blueswen
owner_html_url: https://github.com/blueswen owner_html_url: https://github.com/blueswen
- name: fastapi-do-zero
html_url: https://github.com/dunossauro/fastapi-do-zero
stars: 900
owner_login: dunossauro
owner_html_url: https://github.com/dunossauro

View File

@ -776,7 +776,7 @@ pablocm83:
d2a-raudenaerde: d2a-raudenaerde:
login: d2a-raudenaerde login: d2a-raudenaerde
count: 7 count: 7
avatarUrl: https://avatars.githubusercontent.com/u/5213150?v=4 avatarUrl: https://avatars.githubusercontent.com/u/5213150?u=e6d0ef65c571c7e544fc1c7ec151c7c0a72fb6bb&v=4
url: https://github.com/d2a-raudenaerde url: https://github.com/d2a-raudenaerde
valentinDruzhinin: valentinDruzhinin:
login: valentinDruzhinin login: valentinDruzhinin
@ -1206,7 +1206,7 @@ akagaeng:
phamquanganh31101998: phamquanganh31101998:
login: phamquanganh31101998 login: phamquanganh31101998
count: 3 count: 3
avatarUrl: https://avatars.githubusercontent.com/u/43257497?u=36fa4ee689415d869a98453083a7c4213d2136ee&v=4 avatarUrl: https://avatars.githubusercontent.com/u/43257497?u=6b3419ea9e318c356c42a973fb947682590bd8d3&v=4
url: https://github.com/phamquanganh31101998 url: https://github.com/phamquanganh31101998
peebbv6364: peebbv6364:
login: peebbv6364 login: peebbv6364
@ -1806,7 +1806,7 @@ MrL8199:
ivintoiu: ivintoiu:
login: ivintoiu login: ivintoiu
count: 2 count: 2
avatarUrl: https://avatars.githubusercontent.com/u/1853336?u=5e3d0977f44661fb9712fa297cc8f7608ea6ce48&v=4 avatarUrl: https://avatars.githubusercontent.com/u/1853336?u=b537c905ad08b69993de8796fb235c8d4d47f039&v=4
url: https://github.com/ivintoiu url: https://github.com/ivintoiu
TechnoService2: TechnoService2:
login: TechnoService2 login: TechnoService2
@ -1841,7 +1841,7 @@ NavesSapnis:
eqsdxr: eqsdxr:
login: eqsdxr login: eqsdxr
count: 2 count: 2
avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=d7aaffb29f542b647cf0f6b0e05722490863658a&v=4
url: https://github.com/eqsdxr url: https://github.com/eqsdxr
syedasamina56: syedasamina56:
login: syedasamina56 login: syedasamina56

View File

@ -1,6 +1,6 @@
nilslindemann: nilslindemann:
login: nilslindemann login: nilslindemann
count: 122 count: 124
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
url: https://github.com/nilslindemann url: https://github.com/nilslindemann
jaystone776: jaystone776:
@ -103,6 +103,11 @@ pablocm83:
count: 8 count: 8
avatarUrl: https://avatars.githubusercontent.com/u/28315068?u=3310fbb05bb8bfc50d2c48b6cb64ac9ee4a14549&v=4 avatarUrl: https://avatars.githubusercontent.com/u/28315068?u=3310fbb05bb8bfc50d2c48b6cb64ac9ee4a14549&v=4
url: https://github.com/pablocm83 url: https://github.com/pablocm83
tiangolo:
login: tiangolo
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
url: https://github.com/tiangolo
ptt3199: ptt3199:
login: ptt3199 login: ptt3199
count: 7 count: 7
@ -118,11 +123,6 @@ batlopes:
count: 6 count: 6
avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4 avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4
url: https://github.com/batlopes url: https://github.com/batlopes
tiangolo:
login: tiangolo
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
url: https://github.com/tiangolo
lucasbalieiro: lucasbalieiro:
login: lucasbalieiro login: lucasbalieiro
count: 6 count: 6

View File

@ -70,12 +70,22 @@ If you understood all this, you already know how those utility tools for securit
You most probably don't need these technical details. You most probably don't need these technical details.
These details are useful mainly if you had a FastAPI application older than 0.118.0 and you are facing issues with dependencies with `yield`. These details are useful mainly if you had a FastAPI application older than 0.121.0 and you are facing issues with dependencies with `yield`.
/// ///
Dependencies with `yield` have evolved over time to account for the different use cases and to fix some issues, here's a summary of what has changed. Dependencies with `yield` have evolved over time to account for the different use cases and to fix some issues, here's a summary of what has changed.
### Dependencies with `yield` and `scope` { #dependencies-with-yield-and-scope }
In version 0.121.0, FastAPI added support for `Depends(scope="function")` for dependencies with `yield`.
Using `Depends(scope="function")`, the exit code after `yield` is executed right after the *path operation function* is finished, before the response is sent back to the client.
And when using `Depends(scope="request")` (the default), the exit code after `yield` is executed after the response is sent.
You can read more about it in the docs for [Dependencies with `yield` - Early exit and `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope).
### Dependencies with `yield` and `StreamingResponse`, Technical Details { #dependencies-with-yield-and-streamingresponse-technical-details } ### Dependencies with `yield` and `StreamingResponse`, Technical Details { #dependencies-with-yield-and-streamingresponse-technical-details }
Before FastAPI 0.118.0, if you used a dependency with `yield`, it would run the exit code after the *path operation function* returned but right before sending the response. Before FastAPI 0.118.0, if you used a dependency with `yield`, it would run the exit code after the *path operation function* returned but right before sending the response.
@ -134,7 +144,7 @@ This was changed in version 0.110.0 to fix unhandled memory consumption from for
### Background Tasks and Dependencies with `yield`, Technical Details { #background-tasks-and-dependencies-with-yield-technical-details } ### Background Tasks and Dependencies with `yield`, Technical Details { #background-tasks-and-dependencies-with-yield-technical-details }
Before FastAPI 0.106.0, raising exceptions after `yield` was not possible, the exit code in dependencies with `yield` was executed *after* the response was sent, so [Exception Handlers](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} would have already run. Before FastAPI 0.106.0, raising exceptions after `yield` was not possible, the exit code in dependencies with `yield` was executed *after* the response was sent, so [Exception Handlers](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} would have already run.
This was designed this way mainly to allow using the same objects "yielded" by dependencies inside of background tasks, because the exit code would be executed after the background tasks were finished. This was designed this way mainly to allow using the same objects "yielded" by dependencies inside of background tasks, because the exit code would be executed after the background tasks were finished.

View File

@ -64,7 +64,7 @@ If you want to learn more about HTTPS, check the guide [About HTTPS](../deployme
/// ///
### How Proxy Forwarded Headers Work ### How Proxy Forwarded Headers Work { #how-proxy-forwarded-headers-work }
Here's a visual representation of how the **proxy** adds forwarded headers between the client and the **application server**: Here's a visual representation of how the **proxy** adds forwarded headers between the client and the **application server**:
@ -228,7 +228,7 @@ Passing the `root_path` to `FastAPI` would be the equivalent of passing the `--r
Keep in mind that the server (Uvicorn) won't use that `root_path` for anything else than passing it to the app. Keep in mind that the server (Uvicorn) won't use that `root_path` for anything else than passing it to the app.
But if you go with your browser to <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000/app</a> you will see the normal response: But if you go with your browser to <a href="http://127.0.0.1:8000/app" class="external-link" target="_blank">http://127.0.0.1:8000/app</a> you will see the normal response:
```JSON ```JSON
{ {

View File

@ -1,3 +1,11 @@
/* Fira Code, including characters used by Rich output, like the "heavy right-pointing angle bracket ornament", not included in Google Fonts */
@import url(https://cdn.jsdelivr.net/npm/firacode@6.2.0/distr/fira_code.css);
/* Override default code font in Material for MkDocs to Fira Code */
:root {
--md-code-font: "Fira Code", monospace;
}
.termynal-comment { .termynal-comment {
color: #4a968f; color: #4a968f;
font-style: italic; font-style: italic;

View File

@ -20,7 +20,7 @@
/* font-size: 18px; */ /* font-size: 18px; */
font-size: 15px; font-size: 15px;
/* font-family: 'Fira Mono', Consolas, Menlo, Monaco, 'Courier New', Courier, monospace; */ /* font-family: 'Fira Mono', Consolas, Menlo, Monaco, 'Courier New', Courier, monospace; */
font-family: 'Roboto Mono', 'Fira Mono', Consolas, Menlo, Monaco, 'Courier New', Courier, monospace; font-family: var(--md-code-font-family), 'Roboto Mono', 'Fira Mono', Consolas, Menlo, Monaco, 'Courier New', Courier, monospace;
border-radius: 4px; border-radius: 4px;
padding: 75px 45px 35px; padding: 75px 45px 35px;
position: relative; position: relative;

View File

@ -4,13 +4,21 @@ You can use virtually **any cloud provider** to deploy your FastAPI application.
In most of the cases, the main cloud providers have guides to deploy FastAPI with them. In most of the cases, the main cloud providers have guides to deploy FastAPI with them.
## FastAPI Cloud { #fastapi-cloud }
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** is built by the same author and team behind **FastAPI**.
It streamlines the process of **building**, **deploying**, and **accessing** an API with minimal effort.
It brings the same **developer experience** of building apps with FastAPI to **deploying** them to the cloud. 🎉
FastAPI Cloud is the primary sponsor and funding provider for the *FastAPI and friends* open source projects. ✨
## Cloud Providers - Sponsors { #cloud-providers-sponsors } ## Cloud Providers - Sponsors { #cloud-providers-sponsors }
Some cloud providers ✨ [**sponsor FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, this ensures the continued and healthy **development** of FastAPI and its **ecosystem**. Some other cloud providers ✨ [**sponsor FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨ too. 🙇
And it shows their true commitment to FastAPI and its **community** (you), as they not only want to provide you a **good service** but also want to make sure you have a **good and healthy framework**, FastAPI. 🙇 You might also want to consider them to follow their guides and try their services:
You might want to try their services and follow their guides:
* <a href="https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi" class="external-link" target="_blank">Render</a> * <a href="https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi" class="external-link" target="_blank">Render</a>
* <a href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi" class="external-link" target="_blank">Railway</a> * <a href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi" class="external-link" target="_blank">Railway</a>

View File

@ -0,0 +1,65 @@
# FastAPI Cloud { #fastapi-cloud }
You can deploy your FastAPI app to <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a> with **one command**, go and join the waiting list if you haven't. 🚀
## Login { #login }
Make sure you already have a **FastAPI Cloud** account (we invited you from the waiting list 😉).
Then log in:
<div class="termy">
```console
$ fastapi login
You are logged in to FastAPI Cloud 🚀
```
</div>
## Deploy { #deploy }
Now deploy your app, with **one command**:
<div class="termy">
```console
$ fastapi deploy
Deploying to FastAPI Cloud...
✅ Deployment successful!
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
```
</div>
That's it! Now you can access your app at that URL. ✨
## About FastAPI Cloud { #about-fastapi-cloud }
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** is built by the same author and team behind **FastAPI**.
It streamlines the process of **building**, **deploying**, and **accessing** an API with minimal effort.
It brings the same **developer experience** of building apps with FastAPI to **deploying** them to the cloud. 🎉
It will also take care of most of the things you would need when deploying an app, like:
* HTTPS
* Replication, with autoscaling based on requests
* etc.
FastAPI Cloud is the primary sponsor and funding provider for the *FastAPI and friends* open source projects. ✨
## Deploy to other cloud providers { #deploy-to-other-cloud-providers }
FastAPI is open source and based on standards. You can deploy FastAPI apps to any cloud provider you choose.
Follow your cloud provider's guides to deploy FastAPI apps with them. 🤓
## Deploy your own server { #deploy-your-own-server }
I will also teach you later in this **Deployment** guide all the details, so you can understand what is going on, what needs to happen, or how to deploy FastAPI apps on your own, also with your own servers. 🤓

View File

@ -16,6 +16,8 @@ There are several ways to do it depending on your specific use case and the tool
You could **deploy a server** yourself using a combination of tools, you could use a **cloud service** that does part of the work for you, or other possible options. You could **deploy a server** yourself using a combination of tools, you could use a **cloud service** that does part of the work for you, or other possible options.
For example, we, the team behind FastAPI, built <a href="https://fastapicloud.com" class="external-link" target="_blank">**FastAPI Cloud**</a>, to make deploying FastAPI apps to the cloud as streamlined as possible, with the same developer experience of working with FastAPI.
I will show you some of the main concepts you should probably keep in mind when deploying a **FastAPI** application (although most of it applies to any other type of web application). I will show you some of the main concepts you should probably keep in mind when deploying a **FastAPI** application (although most of it applies to any other type of web application).
You will see more details to keep in mind and some of the techniques to do it in the next sections. ✨ You will see more details to keep in mind and some of the techniques to do it in the next sections. ✨

View File

@ -0,0 +1,17 @@
# Use Old 403 Authentication Error Status Codes { #use-old-403-authentication-error-status-codes }
Before FastAPI version `0.122.0`, when the integrated security utilities returned an error to the client after a failed authentication, they used the HTTP status code `403 Forbidden`.
Starting with FastAPI version `0.122.0`, they use the more appropriate HTTP status code `401 Unauthorized`, and return a sensible `WWW-Authenticate` header in the response, following the HTTP specifications, <a href="https://datatracker.ietf.org/doc/html/rfc7235#section-3.1" class="external-link" target="_blank">RFC 7235</a>, <a href="https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized" class="external-link" target="_blank">RFC 9110</a>.
But if for some reason your clients depend on the old behavior, you can revert to it by overriding the method `make_not_authenticated_error` in your security classes.
For example, you can create a subclass of `HTTPBearer` that returns a `403 Forbidden` error instead of the default `401 Unauthorized` error:
{* ../../docs_src/authentication_error_status_code/tutorial001_an_py39.py hl[9:13] *}
/// tip
Notice that the function returns the exception instance, it doesn't raise it. The raising is done in the rest of the internal code.
///

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -52,14 +52,20 @@ The key features are:
<!-- sponsors --> <!-- sponsors -->
{% if sponsors %} ### Keystone Sponsor
{% for sponsor in sponsors.keystone -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor -%}
### Gold and Silver Sponsors
{% for sponsor in sponsors.gold -%} {% for sponsor in sponsors.gold -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a> <a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor -%} {% endfor -%}
{%- for sponsor in sponsors.silver -%} {%- for sponsor in sponsors.silver -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a> <a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor %} {% endfor %}
{% endif %}
<!-- /sponsors --> <!-- /sponsors -->
@ -444,6 +450,58 @@ For a more complete example including more features, see the <a href="https://fa
* **Cookie Sessions** * **Cookie Sessions**
* ...and more. * ...and more.
### Deploy your app (optional) { #deploy-your-app-optional }
You can optionally deploy your FastAPI app to <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>, go and join the waiting list if you haven't. 🚀
If you already have a **FastAPI Cloud** account (we invited you from the waiting list 😉), you can deploy your application with one command.
Before deploying, make sure you are logged in:
<div class="termy">
```console
$ fastapi login
You are logged in to FastAPI Cloud 🚀
```
</div>
Then deploy your app:
<div class="termy">
```console
$ fastapi deploy
Deploying to FastAPI Cloud...
✅ Deployment successful!
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
```
</div>
That's it! Now you can access your app at that URL. ✨
#### About FastAPI Cloud { #about-fastapi-cloud }
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** is built by the same author and team behind **FastAPI**.
It streamlines the process of **building**, **deploying**, and **accessing** an API with minimal effort.
It brings the same **developer experience** of building apps with FastAPI to **deploying** them to the cloud. 🎉
FastAPI Cloud is the primary sponsor and funding provider for the *FastAPI and friends* open source projects. ✨
#### Deploy to other cloud providers { #deploy-to-other-cloud-providers }
FastAPI is open source and based on standards. You can deploy FastAPI apps to any cloud provider you choose.
Follow your cloud provider's guides to deploy FastAPI apps with them. 🤓
## Performance { #performance } ## Performance { #performance }
Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*) Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)

View File

@ -7,8 +7,115 @@ hide:
## Latest Changes ## Latest Changes
## 0.122.0
### Fixes
* 🐛 Use `401` status code in security classes when credentials are missing. PR [#13786](https://github.com/fastapi/fastapi/pull/13786) by [@YuriiMotov](https://github.com/YuriiMotov).
* If your code depended on these classes raising the old (less correct) `403` status code, check the new docs about how to override the classes, to use the same old behavior: [Use Old 403 Authentication Error Status Codes](https://fastapi.tiangolo.com/how-to/authentication-error-status-code/).
### Internal ### Internal
* 🔧 Configure labeler to exclude files that start from underscore for `lang-all` label. PR [#14213](https://github.com/fastapi/fastapi/pull/14213) by [@YuriiMotov](https://github.com/YuriiMotov).
* 👷 Add pre-commit config with local script for permalinks. PR [#14398](https://github.com/fastapi/fastapi/pull/14398) by [@tiangolo](https://github.com/tiangolo).
* 💄 Use font Fira Code to fix display of Rich panels in docs in Windows. PR [#14387](https://github.com/fastapi/fastapi/pull/14387) by [@tiangolo](https://github.com/tiangolo).
* 👷 Add custom pre-commit CI. PR [#14397](https://github.com/fastapi/fastapi/pull/14397) by [@tiangolo](https://github.com/tiangolo).
* ⬆ Bump actions/checkout from 5 to 6. PR [#14381](https://github.com/fastapi/fastapi/pull/14381) by [@dependabot[bot]](https://github.com/apps/dependabot).
* 👷 Upgrade `latest-changes` GitHub Action and pin `actions/checkout@v5`. PR [#14403](https://github.com/fastapi/fastapi/pull/14403) by [@svlandeg](https://github.com/svlandeg).
* 🛠️ Add `add-permalinks` and `add-permalinks-page` to `scripts/docs.py`. PR [#14033](https://github.com/fastapi/fastapi/pull/14033) by [@YuriiMotov](https://github.com/YuriiMotov).
* 🔧 Upgrade Material for MkDocs and remove insiders. PR [#14375](https://github.com/fastapi/fastapi/pull/14375) by [@tiangolo](https://github.com/tiangolo).
## 0.121.3
### Refactors
* ♻️ Make the result of `Depends()` and `Security()` hashable, as a workaround for other tools interacting with these internal parts. PR [#14372](https://github.com/fastapi/fastapi/pull/14372) by [@tiangolo](https://github.com/tiangolo).
### Upgrades
* ⬆️ Bump Starlette to <`0.51.0`. PR [#14282](https://github.com/fastapi/fastapi/pull/14282) by [@musicinmybrain](https://github.com/musicinmybrain).
### Docs
* 📝 Add missing hash part. PR [#14369](https://github.com/fastapi/fastapi/pull/14369) by [@nilslindemann](https://github.com/nilslindemann).
* 📝 Fix typos in code comments. PR [#14364](https://github.com/fastapi/fastapi/pull/14364) by [@Edge-Seven](https://github.com/Edge-Seven).
* 📝 Add docs for using FastAPI Cloud. PR [#14359](https://github.com/fastapi/fastapi/pull/14359) by [@tiangolo](https://github.com/tiangolo).
## 0.121.2
### Fixes
* 🐛 Fix handling of JSON Schema attributes named "$ref". PR [#14349](https://github.com/fastapi/fastapi/pull/14349) by [@tiangolo](https://github.com/tiangolo).
### Docs
* 📝 Add EuroPython talk & podcast episode with Sebastián Ramírez. PR [#14260](https://github.com/fastapi/fastapi/pull/14260) by [@clytaemnestra](https://github.com/clytaemnestra).
* ✏️ Fix links and add missing permalink in docs. PR [#14217](https://github.com/fastapi/fastapi/pull/14217) by [@YuriiMotov](https://github.com/YuriiMotov).
### Translations
* 🌐 Update Portuguese translations with LLM prompt. PR [#14228](https://github.com/fastapi/fastapi/pull/14228) by [@ceb10n](https://github.com/ceb10n).
* 🔨 Add Portuguese translations LLM prompt. PR [#14208](https://github.com/fastapi/fastapi/pull/14208) by [@ceb10n](https://github.com/ceb10n).
* 🌐 Sync Russian docs. PR [#14331](https://github.com/fastapi/fastapi/pull/14331) by [@YuriiMotov](https://github.com/YuriiMotov).
* 🌐 Sync German docs. PR [#14317](https://github.com/fastapi/fastapi/pull/14317) by [@nilslindemann](https://github.com/nilslindemann).
## 0.121.1
### Fixes
* 🐛 Fix `Depends(func, scope='function')` for top level (parameterless) dependencies. PR [#14301](https://github.com/fastapi/fastapi/pull/14301) by [@luzzodev](https://github.com/luzzodev).
### Docs
* 📝 Upate docs for advanced dependencies with `yield`, noting the changes in 0.121.0, adding `scope`. PR [#14287](https://github.com/fastapi/fastapi/pull/14287) by [@tiangolo](https://github.com/tiangolo).
### Internal
* ⬆ Bump ruff from 0.13.2 to 0.14.3. PR [#14276](https://github.com/fastapi/fastapi/pull/14276) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14289](https://github.com/fastapi/fastapi/pull/14289) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
## 0.121.0
### Features
* ✨ Add support for dependencies with scopes, support `scope="request"` for dependencies with `yield` that exit before the response is sent. PR [#14262](https://github.com/fastapi/fastapi/pull/14262) by [@tiangolo](https://github.com/tiangolo).
* New docs: [Dependencies with `yield` - Early exit and `scope`](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#early-exit-and-scope).
### Internal
* 👥 Update FastAPI People - Contributors and Translators. PR [#14273](https://github.com/fastapi/fastapi/pull/14273) by [@tiangolo](https://github.com/tiangolo).
* 👥 Update FastAPI People - Sponsors. PR [#14274](https://github.com/fastapi/fastapi/pull/14274) by [@tiangolo](https://github.com/tiangolo).
* 👥 Update FastAPI GitHub topic repositories. PR [#14280](https://github.com/fastapi/fastapi/pull/14280) by [@tiangolo](https://github.com/tiangolo).
* ⬆ Bump mkdocs-macros-plugin from 1.4.0 to 1.4.1. PR [#14277](https://github.com/fastapi/fastapi/pull/14277) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump mkdocstrings[python] from 0.26.1 to 0.30.1. PR [#14279](https://github.com/fastapi/fastapi/pull/14279) by [@dependabot[bot]](https://github.com/apps/dependabot).
## 0.120.4
### Fixes
* 🐛 Fix security schemes in OpenAPI when added at the top level app. PR [#14266](https://github.com/fastapi/fastapi/pull/14266) by [@YuriiMotov](https://github.com/YuriiMotov).
## 0.120.3
### Refactors
* ♻️ Reduce internal cyclic recursion in dependencies, from 2 functions calling each other to 1 calling itself. PR [#14256](https://github.com/fastapi/fastapi/pull/14256) by [@tiangolo](https://github.com/tiangolo).
* ♻️ Refactor internals of dependencies, simplify code and remove `get_param_sub_dependant`. PR [#14255](https://github.com/fastapi/fastapi/pull/14255) by [@tiangolo](https://github.com/tiangolo).
* ♻️ Refactor internals of dependencies, simplify using dataclasses. PR [#14254](https://github.com/fastapi/fastapi/pull/14254) by [@tiangolo](https://github.com/tiangolo).
### Docs
* 📝 Update note for untranslated pages. PR [#14257](https://github.com/fastapi/fastapi/pull/14257) by [@YuriiMotov](https://github.com/YuriiMotov).
## 0.120.2
### Fixes
* 🐛 Fix separation of schemas with nested models introduced in 0.119.0. PR [#14246](https://github.com/fastapi/fastapi/pull/14246) by [@tiangolo](https://github.com/tiangolo).
### Internal
* 🔧 Add sponsor: SerpApi. PR [#14248](https://github.com/fastapi/fastapi/pull/14248) by [@tiangolo](https://github.com/tiangolo).
* ⬆ Bump actions/download-artifact from 5 to 6. PR [#14236](https://github.com/fastapi/fastapi/pull/14236) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump actions/download-artifact from 5 to 6. PR [#14236](https://github.com/fastapi/fastapi/pull/14236) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14237](https://github.com/fastapi/fastapi/pull/14237) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14237](https://github.com/fastapi/fastapi/pull/14237) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* ⬆ Bump actions/upload-artifact from 4 to 5. PR [#14235](https://github.com/fastapi/fastapi/pull/14235) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump actions/upload-artifact from 4 to 5. PR [#14235](https://github.com/fastapi/fastapi/pull/14235) by [@dependabot[bot]](https://github.com/apps/dependabot).

View File

@ -184,6 +184,51 @@ If you raise any exception in the code from the *path operation function*, it wi
/// ///
## Early exit and `scope` { #early-exit-and-scope }
Normally the exit code of dependencies with `yield` is executed **after the response** is sent to the client.
But if you know that you won't need to use the dependency after returning from the *path operation function*, you can use `Depends(scope="function")` to tell FastAPI that it should close the dependency after the *path operation function* returns, but **before** the **response is sent**.
{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *}
`Depends()` receives a `scope` parameter that can be:
* `"function"`: start the dependency before the *path operation function* that handles the request, end the dependency after the *path operation function* ends, but **before** the response is sent back to the client. So, the dependency function will be executed **around** the *path operation **function***.
* `"request"`: start the dependency before the *path operation function* that handles the request (similar to when using `"function"`), but end **after** the response is sent back to the client. So, the dependency function will be executed **around** the **request** and response cycle.
If not specified and the dependency has `yield`, it will have a `scope` of `"request"` by default.
### `scope` for sub-dependencies { #scope-for-sub-dependencies }
When you declare a dependency with a `scope="request"` (the default), any sub-dependency needs to also have a `scope` of `"request"`.
But a dependency with `scope` of `"function"` can have dependencies with `scope` of `"function"` and `scope` of `"request"`.
This is because any dependency needs to be able to run its exit code before the sub-dependencies, as it might need to still use them during its exit code.
```mermaid
sequenceDiagram
participant client as Client
participant dep_req as Dep scope="request"
participant dep_func as Dep scope="function"
participant operation as Path Operation
client ->> dep_req: Start request
Note over dep_req: Run code up to yield
dep_req ->> dep_func: Pass dependency
Note over dep_func: Run code up to yield
dep_func ->> operation: Run path operation with dependency
operation ->> dep_func: Return from path operation
Note over dep_func: Run code after yield
Note over dep_func: ✅ Dependency closed
dep_func ->> client: Send response to client
Note over client: Response sent
Note over dep_req: Run code after yield
Note over dep_req: ✅ Dependency closed
```
## Dependencies with `yield`, `HTTPException`, `except` and Background Tasks { #dependencies-with-yield-httpexception-except-and-background-tasks } ## Dependencies with `yield`, `HTTPException`, `except` and Background Tasks { #dependencies-with-yield-httpexception-except-and-background-tasks }
Dependencies with `yield` have evolved over time to cover different use cases and fix some issues. Dependencies with `yield` have evolved over time to cover different use cases and fix some issues.

View File

@ -143,6 +143,42 @@ And there are dozens of alternatives, all based on OpenAPI. You could easily add
You could also use it to generate code automatically, for clients that communicate with your API. For example, frontend, mobile or IoT applications. You could also use it to generate code automatically, for clients that communicate with your API. For example, frontend, mobile or IoT applications.
### Deploy your app (optional) { #deploy-your-app-optional }
You can optionally deploy your FastAPI app to <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>, go and join the waiting list if you haven't. 🚀
If you already have a **FastAPI Cloud** account (we invited you from the waiting list 😉), you can deploy your application with one command.
Before deploying, make sure you are logged in:
<div class="termy">
```console
$ fastapi login
You are logged in to FastAPI Cloud 🚀
```
</div>
Then deploy your app:
<div class="termy">
```console
$ fastapi deploy
Deploying to FastAPI Cloud...
✅ Deployment successful!
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
```
</div>
That's it! Now you can access your app at that URL. ✨
## Recap, step by step { #recap-step-by-step } ## Recap, step by step { #recap-step-by-step }
### Step 1: import `FastAPI` { #step-1-import-fastapi } ### Step 1: import `FastAPI` { #step-1-import-fastapi }
@ -314,6 +350,26 @@ You can also return Pydantic models (you'll see more about that later).
There are many other objects and models that will be automatically converted to JSON (including ORMs, etc). Try using your favorite ones, it's highly probable that they are already supported. There are many other objects and models that will be automatically converted to JSON (including ORMs, etc). Try using your favorite ones, it's highly probable that they are already supported.
### Step 6: Deploy it { #step-6-deploy-it }
Deploy your app to **<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** with one command: `fastapi deploy`. 🎉
#### About FastAPI Cloud { #about-fastapi-cloud }
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** is built by the same author and team behind **FastAPI**.
It streamlines the process of **building**, **deploying**, and **accessing** an API with minimal effort.
It brings the same **developer experience** of building apps with FastAPI to **deploying** them to the cloud. 🎉
FastAPI Cloud is the primary sponsor and funding provider for the *FastAPI and friends* open source projects. ✨
#### Deploy to other cloud providers { #deploy-to-other-cloud-providers }
FastAPI is open source and based on standards. You can deploy FastAPI apps to any cloud provider you choose.
Follow your cloud provider's guides to deploy FastAPI apps with them. 🤓
## Recap { #recap } ## Recap { #recap }
* Import `FastAPI`. * Import `FastAPI`.
@ -321,3 +377,4 @@ There are many other objects and models that will be automatically converted to
* Write a **path operation decorator** using decorators like `@app.get("/")`. * Write a **path operation decorator** using decorators like `@app.get("/")`.
* Define a **path operation function**; for example, `def root(): ...`. * Define a **path operation function**; for example, `def root(): ...`.
* Run the development server using the command `fastapi dev`. * Run the development server using the command `fastapi dev`.
* Optionally deploy your app with `fastapi deploy`.

View File

@ -1,6 +1,5 @@
# Define this here and not in the main mkdocs.yml file because that one is auto # Define this here and not in the main mkdocs.yml file because that one is auto
# updated and written, and the script would remove the env var # updated and written, and the script would remove the env var
INHERIT: !ENV [INSIDERS_FILE, '../en/mkdocs.no-insiders.yml']
markdown_extensions: markdown_extensions:
pymdownx.highlight: pymdownx.highlight:
linenums: !ENV [LINENUMS, false] linenums: !ENV [LINENUMS, false]

View File

@ -1,10 +0,0 @@
plugins:
social:
cards_layout_options:
logo: ../en/docs/img/icon-white.svg
typeset:
markdown_extensions:
material.extensions.preview:
targets:
include:
- "*"

View File

@ -1,4 +1,4 @@
INHERIT: ../en/mkdocs.maybe-insiders.yml INHERIT: ../en/mkdocs.env.yml
site_name: FastAPI site_name: FastAPI
site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production
site_url: https://fastapi.tiangolo.com/ site_url: https://fastapi.tiangolo.com/
@ -52,6 +52,10 @@ theme:
repo_name: fastapi/fastapi repo_name: fastapi/fastapi
repo_url: https://github.com/fastapi/fastapi repo_url: https://github.com/fastapi/fastapi
plugins: plugins:
social:
cards_layout_options:
logo: ../en/docs/img/icon-white.svg
typeset:
search: null search: null
macros: macros:
include_yaml: include_yaml:
@ -192,6 +196,7 @@ nav:
- Deployment: - Deployment:
- deployment/index.md - deployment/index.md
- deployment/versions.md - deployment/versions.md
- deployment/fastapicloud.md
- deployment/https.md - deployment/https.md
- deployment/manually.md - deployment/manually.md
- deployment/concepts.md - deployment/concepts.md
@ -210,6 +215,7 @@ nav:
- how-to/custom-docs-ui-assets.md - how-to/custom-docs-ui-assets.md
- how-to/configure-swagger-ui.md - how-to/configure-swagger-ui.md
- how-to/testing-database.md - how-to/testing-database.md
- how-to/authentication-error-status-code.md
- Reference (Code API): - Reference (Code API):
- reference/index.md - reference/index.md
- reference/fastapi.md - reference/fastapi.md
@ -252,6 +258,10 @@ nav:
- management.md - management.md
- release-notes.md - release-notes.md
markdown_extensions: markdown_extensions:
material.extensions.preview:
targets:
include:
- "*"
abbr: null abbr: null
attr_list: null attr_list: null
footnotes: null footnotes: null

View File

@ -3,6 +3,13 @@
{% block announce %} {% block announce %}
<div class="announce-wrapper"> <div class="announce-wrapper">
<div id="announce-left"> <div id="announce-left">
<div class="item">
<a class="announce-link" href="https://fastapicloud.com" target="_blank">
<span class="twemoji">
{% include ".icons/material/cloud-arrow-up.svg" %}
</span> Join the <strong>FastAPI Cloud</strong> waiting list 🚀
</a>
</div>
<div class="item"> <div class="item">
<a class="announce-link" href="https://x.com/fastapi" target="_blank"> <a class="announce-link" href="https://x.com/fastapi" target="_blank">
<span class="twemoji"> <span class="twemoji">
@ -80,6 +87,12 @@
<img class="sponsor-image" src="/img/sponsors/railway-banner.png" /> <img class="sponsor-image" src="/img/sponsors/railway-banner.png" />
</a> </a>
</div> </div>
<div class="item">
<a title="SerpApi: Web Search API" style="display: block; position: relative;" href="https://serpapi.com/?utm_source=fastapi_website" target="_blank">
<span class="sponsor-badge">sponsor</span>
<img class="sponsor-image" src="/img/sponsors/serpapi-banner.png" />
</a>
</div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -1,7 +1,9 @@
/// warning /// warning
The current page still doesn't have a translation for this language. This page hasnt been translated into your language yet. 🌍
But you can help translating it: [Contributing](https://fastapi.tiangolo.com/contributing/){.internal-link target=_blank}. Were currently switching to an automated translation system 🤖, which will help keep all translations complete and up to date.
Learn more: [Contributing Translations](https://fastapi.tiangolo.com/contributing/#translations){.internal-link target=_blank}
/// ///

503
docs/pt/docs/_llm-test.md Normal file
View File

@ -0,0 +1,503 @@
# Arquivo de teste de LLM { #llm-test-file }
Este documento testa se o <abbr title="Large Language Model Modelo de Linguagem de Grande Porte">LLM</abbr>, que traduz a documentação, entende o `general_prompt` em `scripts/translate.py` e o prompt específico do idioma em `docs/{language code}/llm-prompt.md`. O prompt específico do idioma é anexado ao `general_prompt`.
Os testes adicionados aqui serão vistos por todos os autores dos prompts específicos de idioma.
Use da seguinte forma:
* Tenha um prompt específico do idioma `docs/{language code}/llm-prompt.md`.
* Faça uma tradução nova deste documento para o seu idioma de destino (veja, por exemplo, o comando `translate-page` do `translate.py`). Isso criará a tradução em `docs/{language code}/docs/_llm-test.md`.
* Verifique se está tudo certo na tradução.
* Se necessário, melhore seu prompt específico do idioma, o prompt geral ou o documento em inglês.
* Em seguida, corrija manualmente os problemas restantes na tradução, para que fique uma boa tradução.
* Retraduzir, tendo a boa tradução no lugar. O resultado ideal seria que o LLM não fizesse mais mudanças na tradução. Isso significa que o prompt geral e o seu prompt específico do idioma estão tão bons quanto possível (às vezes fará algumas mudanças aparentemente aleatórias, a razão é que <a href="https://doublespeak.chat/#/handbook#deterministic-output" class="external-link" target="_blank">LLMs não são algoritmos determinísticos</a>).
Os testes:
## Trechos de código { #code-snippets}
//// tab | Teste
Este é um trecho de código: `foo`. E este é outro trecho de código: `bar`. E mais um: `baz quux`.
////
//// tab | Informações
O conteúdo dos trechos de código deve ser deixado como está.
Veja a seção `### Content of code snippets` no prompt geral em `scripts/translate.py`.
////
## Citações { #quotes }
//// tab | Teste
Ontem, meu amigo escreveu: "Se você soletrar incorretamente corretamente, você a soletrou incorretamente". Ao que respondi: "Correto, mas 'incorrectly' está incorretamente não '"incorrectly"'".
/// note | Nota
O LLM provavelmente vai traduzir isso errado. O interessante é apenas se ele mantém a tradução corrigida ao retraduzir.
///
////
//// tab | Informações
O autor do prompt pode escolher se deseja converter aspas neutras em aspas tipográficas. Também é aceitável deixá-las como estão.
Veja, por exemplo, a seção `### Quotes` em `docs/de/llm-prompt.md`.
////
## Citações em trechos de código { #quotes-in-code-snippets}
//// tab | Teste
`pip install "foo[bar]"`
Exemplos de literais de string em trechos de código: `"this"`, `'that'`.
Um exemplo difícil de literais de string em trechos de código: `f"I like {'oranges' if orange else "apples"}"`
Pesado: `Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"`
////
//// tab | Informações
... No entanto, as aspas dentro de trechos de código devem permanecer como estão.
////
## Blocos de código { #code-blocks }
//// tab | Teste
Um exemplo de código Bash...
```bash
# Imprimir uma saudação ao universo
echo "Hello universe"
```
...e um exemplo de código de console...
```console
$ <font color="#4E9A06">fastapi</font> run <u style="text-decoration-style:solid">main.py</u>
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting server
Searching for package file structure
```
...e outro exemplo de código de console...
```console
// Crie um diretório "Code"
$ mkdir code
// Entre nesse diretório
$ cd code
```
...e um exemplo de código Python...
```Python
wont_work() # Isto não vai funcionar 😱
works(foo="bar") # Isto funciona 🎉
```
...e é isso.
////
//// tab | Informações
O código em blocos de código não deve ser modificado, com exceção dos comentários.
Veja a seção `### Content of code blocks` no prompt geral em `scripts/translate.py`.
////
## Abas e caixas coloridas { #tabs-and-colored-boxes }
//// tab | Teste
/// info | Informação
Algum texto
///
/// note | Nota
Algum texto
///
/// note | Detalhes Técnicos
Algum texto
///
/// check | Verifique
Algum texto
///
/// tip | Dica
Algum texto
///
/// warning | Atenção
Algum texto
///
/// danger | Cuidado
Algum texto
///
////
//// tab | Informações
Abas e blocos `Info`/`Note`/`Warning`/etc. devem ter a tradução do seu título adicionada após uma barra vertical (`|`).
Veja as seções `### Special blocks` e `### Tab blocks` no prompt geral em `scripts/translate.py`.
////
## Links da Web e internos { #web-and-internal-links }
//// tab | Teste
O texto do link deve ser traduzido, o endereço do link deve permanecer inalterado:
* [Link para o título acima](#code-snippets)
* [Link interno](index.md#installation){.internal-link target=_blank}
* <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">Link externo</a>
* <a href="https://fastapi.tiangolo.com/css/styles.css" class="external-link" target="_blank">Link para um estilo</a>
* <a href="https://fastapi.tiangolo.com/js/logic.js" class="external-link" target="_blank">Link para um script</a>
* <a href="https://fastapi.tiangolo.com/img/foo.jpg" class="external-link" target="_blank">Link para uma imagem</a>
O texto do link deve ser traduzido, o endereço do link deve apontar para a tradução:
* <a href="https://fastapi.tiangolo.com/pt/" class="external-link" target="_blank">Link do FastAPI</a>
////
//// tab | Informações
Os links devem ser traduzidos, mas seus endereços devem permanecer inalterados. Uma exceção são links absolutos para páginas da documentação do FastAPI. Nesse caso, devem apontar para a tradução.
Veja a seção `### Links` no prompt geral em `scripts/translate.py`.
////
## Elementos HTML "abbr" { #html-abbr-elements }
//// tab | Teste
Aqui estão algumas coisas envolvidas em elementos HTML "abbr" (algumas são inventadas):
### O abbr fornece uma frase completa { #the-abbr-gives-a-full-phrase }
* <abbr title="Getting Things Done Fazer as Coisas">GTD</abbr>
* <abbr title="menos que"><code>lt</code></abbr>
* <abbr title="XML Web Token Token Web XML">XWT</abbr>
* <abbr title="Parallel Server Gateway Interface Interface de Gateway de Servidor Paralelo">PSGI</abbr>
### O abbr fornece uma explicação { #the-abbr-gives-an-explanation }
* <abbr title="Um grupo de máquinas configuradas para estarem conectadas e trabalharem juntas de alguma forma.">cluster</abbr>
* <abbr title="Um método de aprendizado de máquina que usa redes neurais artificiais com numerosas camadas ocultas entre as camadas de entrada e saída, desenvolvendo assim uma estrutura interna abrangente">Aprendizado Profundo</abbr>
### O abbr fornece uma frase completa e uma explicação { #the-abbr-gives-a-full-phrase-and-an-explanation }
* <abbr title="Mozilla Developer Network Rede de Desenvolvedores da Mozilla: documentação para desenvolvedores, escrita pelo pessoal do Firefox">MDN</abbr>
* <abbr title="Input/Output Entrada/Saída: leitura ou escrita em disco, comunicações de rede.">I/O</abbr>.
////
//// tab | Informações
Os atributos "title" dos elementos "abbr" são traduzidos seguindo algumas instruções específicas.
As traduções podem adicionar seus próprios elementos "abbr" que o LLM não deve remover. Por exemplo, para explicar palavras em inglês.
Veja a seção `### HTML abbr elements` no prompt geral em `scripts/translate.py`.
////
## Títulos { #headings }
//// tab | Teste
### Desenvolver uma aplicação web - um tutorial { #develop-a-webapp-a-tutorial }
Olá.
### Anotações de tipo e -anotações { #type-hints-and-annotations }
Olá novamente.
### Super- e subclasses { #super-and-subclasses }
Olá novamente.
////
//// tab | Informações
A única regra rígida para títulos é que o LLM deixe a parte do hash dentro de chaves inalterada, o que garante que os links não quebrem.
Veja a seção `### Headings` no prompt geral em `scripts/translate.py`.
Para algumas instruções específicas do idioma, veja, por exemplo, a seção `### Headings` em `docs/de/llm-prompt.md`.
////
## Termos usados na documentação { #terms-used-in-the-docs }
//// tab | Teste
* você
* seu
* por exemplo
* etc.
* `foo` como um `int`
* `bar` como uma `str`
* `baz` como uma `list`
* o Tutorial - Guia do Usuário
* o Guia do Usuário Avançado
* a documentação do SQLModel
* a documentação da API
* a documentação automática
* Ciência de Dados
* Aprendizado Profundo
* Aprendizado de Máquina
* Injeção de Dependências
* autenticação HTTP Basic
* HTTP Digest
* formato ISO
* o padrão JSON Schema
* o JSON schema
* a definição do schema
* Fluxo de Senha
* Mobile
* descontinuado
* projetado
* inválido
* dinamicamente
* padrão
* padrão predefinido
* sensível a maiúsculas e minúsculas
* não sensível a maiúsculas e minúsculas
* servir a aplicação
* servir a página
* o app
* a aplicação
* a requisição
* a resposta
* a resposta de erro
* a operação de rota
* o decorador de operação de rota
* a função de operação de rota
* o corpo
* o corpo da requisição
* o corpo da resposta
* o corpo JSON
* o corpo do formulário
* o corpo do arquivo
* o corpo da função
* o parâmetro
* o parâmetro de corpo
* o parâmetro de path
* o parâmetro de query
* o parâmetro de cookie
* o parâmetro de header
* o parâmetro de formulário
* o parâmetro da função
* o evento
* o evento de inicialização
* a inicialização do servidor
* o evento de encerramento
* o evento de lifespan
* o manipulador
* o manipulador de eventos
* o manipulador de exceções
* tratar
* o modelo
* o modelo Pydantic
* o modelo de dados
* o modelo de banco de dados
* o modelo de formulário
* o objeto de modelo
* a classe
* a classe base
* a classe pai
* a subclasse
* a classe filha
* a classe irmã
* o método de classe
* o cabeçalho
* os cabeçalhos
* o cabeçalho de autorização
* o cabeçalho `Authorization`
* o cabeçalho encaminhado
* o sistema de injeção de dependências
* a dependência
* o dependable
* o dependant
* limitado por I/O
* limitado por CPU
* concorrência
* paralelismo
* multiprocessamento
* a env var
* a variável de ambiente
* o `PATH`
* a variável `PATH`
* a autenticação
* o provedor de autenticação
* a autorização
* o formulário de autorização
* o provedor de autorização
* o usuário se autentica
* o sistema autentica o usuário
* a CLI
* a interface de linha de comando
* o servidor
* o cliente
* o provedor de nuvem
* o serviço de nuvem
* o desenvolvimento
* as etapas de desenvolvimento
* o dict
* o dicionário
* a enumeração
* o enum
* o membro do enum
* o codificador
* o decodificador
* codificar
* decodificar
* a exceção
* lançar
* a expressão
* a instrução
* o frontend
* o backend
* a discussão do GitHub
* a issue do GitHub
* o desempenho
* a otimização de desempenho
* o tipo de retorno
* o valor de retorno
* a segurança
* o esquema de segurança
* a tarefa
* a tarefa em segundo plano
* a função da tarefa
* o template
* o mecanismo de template
* a anotação de tipo
* a anotação de tipo
* o worker de servidor
* o worker do Uvicorn
* o Worker do Gunicorn
* o processo worker
* a classe de worker
* a carga de trabalho
* a implantação
* implantar
* o SDK
* o kit de desenvolvimento de software
* o `APIRouter`
* o `requirements.txt`
* o Bearer Token
* a alteração com quebra de compatibilidade
* o bug
* o botão
* o chamável
* o código
* o commit
* o gerenciador de contexto
* a corrotina
* a sessão do banco de dados
* o disco
* o domínio
* o mecanismo
* o X falso
* o método HTTP GET
* o item
* a biblioteca
* o lifespan
* o bloqueio
* o middleware
* a aplicação mobile
* o módulo
* a montagem
* a rede
* a origem
* a sobrescrita
* a carga útil
* o processador
* a propriedade
* o proxy
* o pull request
* a consulta
* a RAM
* a máquina remota
* o código de status
* a string
* a tag
* o framework web
* o curinga
* retornar
* validar
////
//// tab | Informações
Esta é uma lista não completa e não normativa de termos (principalmente) técnicos vistos na documentação. Pode ser útil para o autor do prompt descobrir para quais termos o LLM precisa de uma ajudinha. Por exemplo, quando ele continua revertendo uma boa tradução para uma tradução subótima. Ou quando tem problemas para conjugar/declinar um termo no seu idioma.
Veja, por exemplo, a seção `### List of English terms and their preferred German translations` em `docs/de/llm-prompt.md`.
////

View File

@ -1,3 +1,3 @@
# Sobre # Sobre { #about }
Sobre o FastAPI, seus padrões, inspirações e muito mais. 🤓 Sobre o FastAPI, seu design, inspiração e mais. 🤓

View File

@ -1,6 +1,6 @@
# Retornos Adicionais no OpenAPI # Retornos Adicionais no OpenAPI { #additional-responses-in-openapi }
/// warning | Aviso /// warning | Atenção
Este é um tema bem avançado. Este é um tema bem avançado.
@ -14,7 +14,7 @@ Essas respostas adicionais serão incluídas no esquema do OpenAPI, e também ap
Porém para as respostas adicionais, você deve garantir que está retornando um `Response` como por exemplo o `JSONResponse` diretamente, junto com o código de status e o conteúdo. Porém para as respostas adicionais, você deve garantir que está retornando um `Response` como por exemplo o `JSONResponse` diretamente, junto com o código de status e o conteúdo.
## Retorno Adicional com `model` ## Retorno Adicional com `model` { #additional-response-with-model }
Você pode fornecer o parâmetro `responses` aos seus *decoradores de caminho*. Você pode fornecer o parâmetro `responses` aos seus *decoradores de caminho*.
@ -49,7 +49,7 @@ O local correto é:
/// ///
O retorno gerado no OpenAI para esta *operação de caminho* será: O retorno gerado no OpenAPI para esta *operação de rota* será:
```JSON hl_lines="3-12" ```JSON hl_lines="3-12"
{ {
@ -169,11 +169,11 @@ Os esquemas são referenciados em outro local dentro do esquema OpenAPI:
} }
``` ```
## Media types adicionais para o retorno principal ## Media types adicionais para o retorno principal { #additional-media-types-for-the-main-response }
Você pode utilizar o mesmo parâmetro `responses` para adicionar diferentes media types para o mesmo retorno principal. Você pode utilizar o mesmo parâmetro `responses` para adicionar diferentes media types para o mesmo retorno principal.
Por exemplo, você pode adicionar um media type adicional de `image/png`, declarando que a sua *operação de caminho* pode retornar um objeto JSON (com o media type `application/json`) ou uma imagem PNG: Por exemplo, você pode adicionar um media type adicional de `image/png`, declarando que a sua *operação de rota* pode retornar um objeto JSON (com o media type `application/json`) ou uma imagem PNG:
{* ../../docs_src/additional_responses/tutorial002.py hl[19:24,28] *} {* ../../docs_src/additional_responses/tutorial002.py hl[19:24,28] *}
@ -191,7 +191,7 @@ Porém se você especificou uma classe de retorno com o valor `None` como media
/// ///
## Combinando informações ## Combinando informações { #combining-information }
Você também pode combinar informações de diferentes lugares, incluindo os parâmetros `response_model`, `status_code`, e `responses`. Você também pode combinar informações de diferentes lugares, incluindo os parâmetros `response_model`, `status_code`, e `responses`.
@ -209,9 +209,9 @@ Isso será combinado e incluído em seu OpenAPI, e disponibilizado na documenta
<img src="/img/tutorial/additional-responses/image01.png"> <img src="/img/tutorial/additional-responses/image01.png">
## Combinar retornos predefinidos e personalizados ## Combinar retornos predefinidos e personalizados { #combine-predefined-responses-and-custom-ones }
Você pode querer possuir alguns retornos predefinidos que são aplicados para diversas *operações de caminho*, porém você deseja combinar com retornos personalizados que são necessários para cada *operação de caminho*. Você pode querer possuir alguns retornos predefinidos que são aplicados para diversas *operações de rota*, porém você deseja combinar com retornos personalizados que são necessários para cada *operação de rota*.
Para estes casos, você pode utilizar a técnica do Python de "desempacotamento" de um `dict` utilizando `**dict_to_unpack`: Para estes casos, você pode utilizar a técnica do Python de "desempacotamento" de um `dict` utilizando `**dict_to_unpack`:
@ -233,15 +233,15 @@ Aqui, o `new_dict` terá todos os pares de chave-valor do `old_dict` mais o novo
} }
``` ```
Você pode utilizar essa técnica para reutilizar alguns retornos predefinidos nas suas *operações de caminho* e combiná-las com personalizações adicionais. Você pode utilizar essa técnica para reutilizar alguns retornos predefinidos nas suas *operações de rota* e combiná-las com personalizações adicionais.
Por exemplo: Por exemplo:
{* ../../docs_src/additional_responses/tutorial004.py hl[13:17,26] *} {* ../../docs_src/additional_responses/tutorial004.py hl[13:17,26] *}
## Mais informações sobre retornos OpenAPI ## Mais informações sobre retornos OpenAPI { #more-information-about-openapi-responses }
Para verificar exatamente o que você pode incluir nos retornos, você pode conferir estas seções na especificação do OpenAPI: Para verificar exatamente o que você pode incluir nos retornos, você pode conferir estas seções na especificação do OpenAPI:
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responsesObject" class="external-link" target="_blank">Objeto de Retorno OpenAPI</a>, inclui o `Response Object`. * <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object" class="external-link" target="_blank">Objeto de Retorno OpenAPI</a>, inclui o `Response Object`.
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responseObject" class="external-link" target="_blank">Objeto de Retorno OpenAPI</a>, você pode incluir qualquer coisa dele diretamente em cada retorno dentro do seu parâmetro `responses`. Incluindo `description`, `headers`, `content` (dentro dele que você declara diferentes media types e esquemas JSON), e `links`. * <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object" class="external-link" target="_blank">Objeto de Retorno OpenAPI</a>, você pode incluir qualquer coisa dele diretamente em cada retorno dentro do seu parâmetro `responses`. Incluindo `description`, `headers`, `content` (dentro dele que você declara diferentes media types e esquemas JSON), e `links`.

View File

@ -1,22 +1,22 @@
# Códigos de status adicionais # Códigos de status adicionais { #additional-status-codes }
Por padrão, o **FastAPI** retornará as respostas utilizando o `JSONResponse`, adicionando o conteúdo do retorno da sua *operação de caminho* dentro do `JSONResponse`. Por padrão, o **FastAPI** retornará as respostas utilizando o `JSONResponse`, adicionando o conteúdo do retorno da sua *operação de rota* dentro do `JSONResponse`.
Ele usará o código de status padrão ou o que você definir na sua *operação de caminho*. Ele usará o código de status padrão ou o que você definir na sua *operação de rota*.
## Códigos de status adicionais ## Códigos de status adicionais { #additional-status-codes_1 }
Caso você queira retornar códigos de status adicionais além do código principal, você pode fazer isso retornando um `Response` diretamente, como por exemplo um `JSONResponse`, e definir os códigos de status adicionais diretamente. Caso você queira retornar códigos de status adicionais além do código principal, você pode fazer isso retornando um `Response` diretamente, como por exemplo um `JSONResponse`, e definir os códigos de status adicionais diretamente.
Por exemplo, vamos dizer que você deseja ter uma *operação de caminho* que permita atualizar itens, e retornar um código de status HTTP 200 "OK" quando for bem sucedido. Por exemplo, vamos dizer que você deseja ter uma *operação de rota* que permita atualizar itens, e retornar um código de status HTTP 200 "OK" quando for bem sucedido.
Mas você também deseja aceitar novos itens. E quando os itens não existiam, ele os cria, e retorna o código de status HTTP 201 "Created. Mas você também deseja aceitar novos itens. E quando os itens não existiam, ele os cria, e retorna o código de status HTTP 201 "Created".
Para conseguir isso, importe `JSONResponse` e retorne o seu conteúdo diretamente, definindo o `status_code` que você deseja: Para conseguir isso, importe `JSONResponse` e retorne o seu conteúdo diretamente, definindo o `status_code` que você deseja:
{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} {* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *}
/// warning | Aviso /// warning | Atenção
Quando você retorna um `Response` diretamente, como no exemplo acima, ele será retornado diretamente. Quando você retorna um `Response` diretamente, como no exemplo acima, ele será retornado diretamente.
@ -26,7 +26,7 @@ Garanta que ele tenha toda informação que você deseja, e que os valores sejam
/// ///
/// note | Detalhes técnicos /// note | Detalhes Técnicos
Você também pode utilizar `from starlette.responses import JSONResponse`. Você também pode utilizar `from starlette.responses import JSONResponse`.
@ -34,7 +34,7 @@ O **FastAPI** disponibiliza o `starlette.responses` como `fastapi.responses` ape
/// ///
## OpenAPI e documentação da API ## OpenAPI e documentação da API { #openapi-and-api-docs }
Se você retorna códigos de status adicionais e retornos diretamente, eles não serão incluídos no esquema do OpenAPI (a documentação da API), porque o FastAPI não tem como saber de antemão o que será retornado. Se você retorna códigos de status adicionais e retornos diretamente, eles não serão incluídos no esquema do OpenAPI (a documentação da API), porque o FastAPI não tem como saber de antemão o que será retornado.

View File

@ -1,6 +1,6 @@
# Dependências avançadas # Dependências avançadas { #advanced-dependencies }
## Dependências parametrizadas ## Dependências parametrizadas { #parameterized-dependencies }
Todas as dependências que vimos até agora são funções ou classes fixas. Todas as dependências que vimos até agora são funções ou classes fixas.
@ -10,7 +10,7 @@ Vamos imaginar que queremos ter uma dependência que verifica se o parâmetro de
Porém nós queremos poder parametrizar o conteúdo fixo. Porém nós queremos poder parametrizar o conteúdo fixo.
## Uma instância "chamável" ## Uma instância "chamável" { #a-callable-instance }
Em Python existe uma maneira de fazer com que uma instância de uma classe seja um "chamável". Em Python existe uma maneira de fazer com que uma instância de uma classe seja um "chamável".
@ -22,7 +22,7 @@ Para fazer isso, nós declaramos o método `__call__`:
Neste caso, o `__call__` é o que o **FastAPI** utilizará para verificar parâmetros adicionais e sub dependências, e isso é o que será chamado para passar o valor ao parâmetro na sua *função de operação de rota* posteriormente. Neste caso, o `__call__` é o que o **FastAPI** utilizará para verificar parâmetros adicionais e sub dependências, e isso é o que será chamado para passar o valor ao parâmetro na sua *função de operação de rota* posteriormente.
## Parametrizar a instância ## Parametrizar a instância { #parameterize-the-instance }
E agora, nós podemos utilizar o `__init__` para declarar os parâmetros da instância que podemos utilizar para "parametrizar" a dependência: E agora, nós podemos utilizar o `__init__` para declarar os parâmetros da instância que podemos utilizar para "parametrizar" a dependência:
@ -30,7 +30,7 @@ E agora, nós podemos utilizar o `__init__` para declarar os parâmetros da inst
Neste caso, o **FastAPI** nunca tocará ou se importará com o `__init__`, nós vamos utilizar diretamente em nosso código. Neste caso, o **FastAPI** nunca tocará ou se importará com o `__init__`, nós vamos utilizar diretamente em nosso código.
## Crie uma instância ## Crie uma instância { #create-an-instance }
Nós poderíamos criar uma instância desta classe com: Nós poderíamos criar uma instância desta classe com:
@ -38,7 +38,7 @@ Nós poderíamos criar uma instância desta classe com:
E deste modo nós podemos "parametrizar" a nossa dependência, que agora possui `"bar"` dentro dele, como o atributo `checker.fixed_content`. E deste modo nós podemos "parametrizar" a nossa dependência, que agora possui `"bar"` dentro dele, como o atributo `checker.fixed_content`.
## Utilize a instância como dependência ## Utilize a instância como dependência { #use-the-instance-as-a-dependency }
Então, nós podemos utilizar este `checker` em um `Depends(checker)`, no lugar de `Depends(FixedContentQueryChecker)`, porque a dependência é a instância, `checker`, e não a própria classe. Então, nós podemos utilizar este `checker` em um `Depends(checker)`, no lugar de `Depends(FixedContentQueryChecker)`, porque a dependência é a instância, `checker`, e não a própria classe.
@ -63,3 +63,101 @@ Nos capítulos sobre segurança, existem funções utilitárias que são impleme
Se você entendeu tudo isso, você já sabe como essas funções utilitárias para segurança funcionam por debaixo dos panos. Se você entendeu tudo isso, você já sabe como essas funções utilitárias para segurança funcionam por debaixo dos panos.
/// ///
## Dependências com `yield`, `HTTPException`, `except` e Tarefas em Segundo Plano { #dependencies-with-yield-httpexception-except-and-background-tasks }
/// warning | Atenção
Muito provavelmente você não precisa desses detalhes técnicos.
Esses detalhes são úteis principalmente se você tinha uma aplicação FastAPI anterior à versão 0.121.0 e está enfrentando problemas com dependências com `yield`.
///
Dependências com `yield` evoluíram ao longo do tempo para contemplar diferentes casos de uso e corrigir alguns problemas, aqui está um resumo do que mudou.
### Dependências com `yield` e `scope` { #dependencies-with-yield-and-scope }
Na versão 0.121.0, o FastAPI adicionou suporte a `Depends(scope="function")` para dependências com `yield`.
Usando `Depends(scope="function")`, o código de saída após o `yield` é executado logo depois que a *função de operação de rota* termina, antes de a response ser enviada de volta ao cliente.
E ao usar `Depends(scope="request")` (o padrão), o código de saída após o `yield` é executado depois que a response é enviada.
Você pode ler mais na documentação em [Dependências com `yield` - Saída antecipada e `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope).
### Dependências com `yield` e `StreamingResponse`, Detalhes Técnicos { #dependencies-with-yield-and-streamingresponse-technical-details }
Antes do FastAPI 0.118.0, se você usasse uma dependência com `yield`, o código de saída (após o `yield`) rodaria depois que a *função de operação de rota* retornasse, mas logo antes de enviar a resposta.
A intenção era evitar manter recursos por mais tempo que o necessário, esperando a resposta percorrer a rede.
Essa mudança também significava que, se você retornasse um `StreamingResponse`, o código de saída da dependência com `yield` já teria sido executado.
Por exemplo, se você tivesse uma sessão de banco de dados em uma dependência com `yield`, o `StreamingResponse` não conseguiria usar essa sessão enquanto transmite dados, porque a sessão já teria sido fechada no código de saída após o `yield`.
Esse comportamento foi revertido na versão 0.118.0, para que o código de saída após o `yield` seja executado depois que a resposta for enviada.
/// info | Informação
Como você verá abaixo, isso é muito semelhante ao comportamento antes da versão 0.106.0, mas com várias melhorias e correções de bugs para casos extremos.
///
#### Casos de uso com código de saída antecipado { #use-cases-with-early-exit-code }
Há alguns casos de uso, com condições específicas, que poderiam se beneficiar do comportamento antigo de executar o código de saída das dependências com `yield` antes de enviar a resposta.
Por exemplo, imagine que você tem código que usa uma sessão de banco de dados em uma dependência com `yield` apenas para verificar um usuário, mas a sessão de banco de dados nunca é usada novamente na *função de operação de rota*, somente na dependência, e a resposta demora a ser enviada, como um `StreamingResponse` que envia dados lentamente, mas por algum motivo não usa o banco de dados.
Nesse caso, a sessão de banco de dados seria mantida até que a resposta termine de ser enviada, mas se você não a usa, então não seria necessário mantê-la.
Veja como poderia ser:
{* ../../docs_src/dependencies/tutorial013_an_py310.py *}
O código de saída, o fechamento automático da `Session` em:
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *}
...seria executado depois que a resposta terminar de enviar os dados lentos:
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *}
Mas como `generate_stream()` não usa a sessão do banco de dados, não é realmente necessário manter a sessão aberta enquanto envia a resposta.
Se você tiver esse caso específico usando SQLModel (ou SQLAlchemy), você poderia fechar explicitamente a sessão depois que não precisar mais dela:
{* ../../docs_src/dependencies/tutorial014_an_py310.py ln[24:28] hl[28] *}
Dessa forma a sessão liberaria a conexão com o banco de dados, para que outras requisições pudessem usá-la.
Se você tiver um caso diferente que precise sair antecipadamente de uma dependência com `yield`, por favor crie uma <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">Pergunta no GitHub Discussions</a> com o seu caso específico e por que você se beneficiaria de ter o fechamento antecipado para dependências com `yield`.
Se houver casos de uso convincentes para fechamento antecipado em dependências com `yield`, considerarei adicionar uma nova forma de optar por esse fechamento antecipado.
### Dependências com `yield` e `except`, Detalhes Técnicos { #dependencies-with-yield-and-except-technical-details }
Antes do FastAPI 0.110.0, se você usasse uma dependência com `yield`, e então capturasse uma exceção com `except` nessa dependência, e você não relançasse a exceção, a exceção seria automaticamente levantada/encaminhada para quaisquer tratadores de exceção ou para o tratador de erro interno do servidor.
Isso foi alterado na versão 0.110.0 para corrigir consumo de memória não tratado decorrente de exceções encaminhadas sem um tratador (erros internos do servidor), e para torná-lo consistente com o comportamento do código Python regular.
### Tarefas em Segundo Plano e Dependências com `yield`, Detalhes Técnicos { #background-tasks-and-dependencies-with-yield-technical-details }
Antes do FastAPI 0.106.0, lançar exceções após o `yield` não era possível, o código de saída em dependências com `yield` era executado depois que a resposta era enviada, então [Tratadores de Exceções](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} já teriam sido executados.
Isso foi projetado assim principalmente para permitir o uso dos mesmos objetos "yielded" por dependências dentro de tarefas em segundo plano, porque o código de saída seria executado depois que as tarefas em segundo plano fossem concluídas.
Isso foi alterado no FastAPI 0.106.0 com a intenção de não manter recursos enquanto se espera a resposta percorrer a rede.
/// tip | Dica
Além disso, uma tarefa em segundo plano normalmente é um conjunto de lógica independente que deve ser tratado separadamente, com seus próprios recursos (por exemplo, sua própria conexão de banco de dados).
Assim, desta forma você provavelmente terá um código mais limpo.
///
Se você costumava depender desse comportamento, agora você deve criar os recursos para tarefas em segundo plano dentro da própria tarefa em segundo plano, e usar internamente apenas dados que não dependam dos recursos de dependências com `yield`.
Por exemplo, em vez de usar a mesma sessão de banco de dados, você criaria uma nova sessão de banco de dados dentro da tarefa em segundo plano, e obteria os objetos do banco de dados usando essa nova sessão. E então, em vez de passar o objeto do banco de dados como parâmetro para a função da tarefa em segundo plano, você passaria o ID desse objeto e então obteria o objeto novamente dentro da função da tarefa em segundo plano.

View File

@ -1,4 +1,4 @@
# Testes Assíncronos # Testes Assíncronos { #async-tests }
Você já viu como testar as suas aplicações **FastAPI** utilizando o `TestClient` que é fornecido. Até agora, você viu apenas como escrever testes síncronos, sem utilizar funções `async`. Você já viu como testar as suas aplicações **FastAPI** utilizando o `TestClient` que é fornecido. Até agora, você viu apenas como escrever testes síncronos, sem utilizar funções `async`.
@ -6,11 +6,11 @@ Ser capaz de utilizar funções assíncronas em seus testes pode ser útil, por
Vamos ver como nós podemos fazer isso funcionar. Vamos ver como nós podemos fazer isso funcionar.
## pytest.mark.anyio ## pytest.mark.anyio { #pytest-mark-anyio }
Se quisermos chamar funções assíncronas em nossos testes, as nossas funções de teste precisam ser assíncronas. O AnyIO oferece um plugin bem legal para isso, que nos permite especificar que algumas das nossas funções de teste precisam ser chamadas de forma assíncrona. Se quisermos chamar funções assíncronas em nossos testes, as nossas funções de teste precisam ser assíncronas. O AnyIO oferece um plugin bem legal para isso, que nos permite especificar que algumas das nossas funções de teste precisam ser chamadas de forma assíncrona.
## HTTPX ## HTTPX { #httpx }
Mesmo que a sua aplicação **FastAPI** utilize funções normais com `def` no lugar de `async def`, ela ainda é uma aplicação `async` por baixo dos panos. Mesmo que a sua aplicação **FastAPI** utilize funções normais com `def` no lugar de `async def`, ela ainda é uma aplicação `async` por baixo dos panos.
@ -18,7 +18,7 @@ O `TestClient` faz algumas mágicas para invocar a aplicação FastAPI assíncro
O `TestClient` é baseado no <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>, e felizmente nós podemos utilizá-lo diretamente para testar a API. O `TestClient` é baseado no <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>, e felizmente nós podemos utilizá-lo diretamente para testar a API.
## Exemplo ## Exemplo { #example }
Para um exemplos simples, vamos considerar uma estrutura de arquivos semelhante ao descrito em [Bigger Applications](../tutorial/bigger-applications.md){.internal-link target=_blank} e [Testing](../tutorial/testing.md){.internal-link target=_blank}: Para um exemplos simples, vamos considerar uma estrutura de arquivos semelhante ao descrito em [Bigger Applications](../tutorial/bigger-applications.md){.internal-link target=_blank} e [Testing](../tutorial/testing.md){.internal-link target=_blank}:
@ -38,7 +38,7 @@ O arquivo `test_main.py` teria os testes para para o arquivo `main.py`, ele pode
{* ../../docs_src/async_tests/test_main.py *} {* ../../docs_src/async_tests/test_main.py *}
## Executá-lo ## Executá-lo { #run-it }
Você pode executar os seus testes normalmente via: Você pode executar os seus testes normalmente via:
@ -52,7 +52,7 @@ $ pytest
</div> </div>
## Em Detalhes ## Em Detalhes { #in-detail }
O marcador `@pytest.mark.anyio` informa ao pytest que esta função de teste deve ser invocada de maneira assíncrona: O marcador `@pytest.mark.anyio` informa ao pytest que esta função de teste deve ser invocada de maneira assíncrona:
@ -82,18 +82,18 @@ Note que nós estamos utilizando async/await com o novo `AsyncClient` - a requis
/// ///
/// warning | Aviso /// warning | Atenção
Se a sua aplicação depende dos eventos de vida útil (*lifespan*), o `AsyncClient` não acionará estes eventos. Para garantir que eles são acionados, utilize o `LifespanManager` do <a href="https://github.com/florimondmanca/asgi-lifespan#usage" class="external-link" target="_blank">florimondmanca/asgi-lifespan</a>. Se a sua aplicação depende de eventos de lifespan, o `AsyncClient` não acionará estes eventos. Para garantir que eles são acionados, utilize o `LifespanManager` do <a href="https://github.com/florimondmanca/asgi-lifespan#usage" class="external-link" target="_blank">florimondmanca/asgi-lifespan</a>.
/// ///
## Outras Chamadas de Funções Assíncronas ## Outras Chamadas de Funções Assíncronas { #other-asynchronous-function-calls }
Como a função de teste agora é assíncrona, você pode chamar (e `esperar`) outras funções `async` além de enviar requisições para a sua aplicação FastAPI em seus testes, exatamente como você as chamaria em qualquer outro lugar do seu código. Como a função de teste agora é assíncrona, você pode chamar (e `await`) outras funções `async` além de enviar requisições para a sua aplicação FastAPI em seus testes, exatamente como você as chamaria em qualquer outro lugar do seu código.
/// tip | Dica /// tip | Dica
Se você se deparar com um `RuntimeError: Task attached to a different loop` ao integrar funções assíncronas em seus testes (e.g. ao utilizar o <a href="https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop" class="external-link" target="_blank">MotorClient do MongoDB</a>) Lembre-se de instanciar objetos que precisam de um loop de eventos (*event loop*) apenas em funções assíncronas, e.g. um *"callback"* `'@app.on_event("startup")`. Se você se deparar com um `RuntimeError: Task attached to a different loop` ao integrar funções assíncronas em seus testes (e.g. ao utilizar o <a href="https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop" class="external-link" target="_blank">MotorClient do MongoDB</a>) Lembre-se de instanciar objetos que precisam de um loop de eventos (*event loop*) apenas em funções assíncronas, e.g. um callback `@app.on_event("startup")`.
/// ///

View File

@ -1,34 +1,131 @@
# Atrás de um Proxy # Atrás de um Proxy { #behind-a-proxy }
Em algumas situações, você pode precisar usar um servidor **proxy** como Traefik ou Nginx com uma configuração que adiciona um prefixo de caminho extra que não é visto pela sua aplicação. Em muitas situações, você usaria um **proxy** como Traefik ou Nginx na frente da sua aplicação FastAPI.
Esses proxies podem lidar com certificados HTTPS e outras coisas.
## Headers Encaminhados pelo Proxy { #proxy-forwarded-headers }
Um **proxy** na frente da sua aplicação normalmente definiria alguns headers dinamicamente antes de enviar as requisições para o seu **servidor**, para informar ao servidor que a requisição foi **encaminhada** pelo proxy, informando a URL original (pública), incluindo o domínio, que está usando HTTPS, etc.
O programa do **servidor** (por exemplo, **Uvicorn** via **CLI do FastAPI**) é capaz de interpretar esses headers e então repassar essas informações para a sua aplicação.
Mas, por segurança, como o servidor não sabe que está atrás de um proxy confiável, ele não interpretará esses headers.
/// note | Detalhes Técnicos
Os headers do proxy são:
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For" class="external-link" target="_blank">X-Forwarded-For</a>
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto" class="external-link" target="_blank">X-Forwarded-Proto</a>
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host" class="external-link" target="_blank">X-Forwarded-Host</a>
///
### Ativar headers encaminhados pelo proxy { #enable-proxy-forwarded-headers }
Você pode iniciar a CLI do FastAPI com a opção de linha de comando `--forwarded-allow-ips` e informar os endereços IP que devem ser confiáveis para ler esses headers encaminhados.
Se você definir como `--forwarded-allow-ips="*"`, ele confiará em todos os IPs de entrada.
Se o seu **servidor** estiver atrás de um **proxy** confiável e somente o proxy falar com ele, isso fará com que ele aceite seja qual for o IP desse **proxy**.
<div class="termy">
```console
$ fastapi run --forwarded-allow-ips="*"
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
### Redirecionamentos com HTTPS { #redirects-with-https }
Por exemplo, suponha que você defina uma *operação de rota* `/items/`:
{* ../../docs_src/behind_a_proxy/tutorial001_01.py hl[6] *}
Se o cliente tentar ir para `/items`, por padrão, ele seria redirecionado para `/items/`.
Mas antes de definir a opção de linha de comando `--forwarded-allow-ips`, poderia redirecionar para `http://localhost:8000/items/`.
Mas talvez sua aplicação esteja hospedada em `https://mysuperapp.com`, e o redirecionamento deveria ser para `https://mysuperapp.com/items/`.
Ao definir `--proxy-headers`, agora o FastAPI conseguirá redirecionar para o local correto. 😎
```
https://mysuperapp.com/items/
```
/// tip | Dica
Se você quiser saber mais sobre HTTPS, confira o tutorial [Sobre HTTPS](../deployment/https.md){.internal-link target=_blank}.
///
### Como funcionam os headers encaminhados pelo proxy { #how-proxy-forwarded-headers-work }
Aqui está uma representação visual de como o **proxy** adiciona headers encaminhados entre o cliente e o **servidor da aplicação**:
```mermaid
sequenceDiagram
participant Client
participant Proxy as Proxy/Load Balancer
participant Server as FastAPI Server
Client->>Proxy: HTTPS Request<br/>Host: mysuperapp.com<br/>Path: /items
Note over Proxy: Proxy adds forwarded headers
Proxy->>Server: HTTP Request<br/>X-Forwarded-For: [client IP]<br/>X-Forwarded-Proto: https<br/>X-Forwarded-Host: mysuperapp.com<br/>Path: /items
Note over Server: Server interprets headers<br/>(if --forwarded-allow-ips is set)
Server->>Proxy: HTTP Response<br/>with correct HTTPS URLs
Proxy->>Client: HTTPS Response
```
O **proxy** intercepta a requisição original do cliente e adiciona os headers especiais de encaminhamento (`X-Forwarded-*`) antes de repassar a requisição para o **servidor da aplicação**.
Esses headers preservam informações sobre a requisição original que, de outra forma, seriam perdidas:
* X-Forwarded-For: o endereço IP original do cliente
* X-Forwarded-Proto: o protocolo original (`https`)
* X-Forwarded-Host: o host original (`mysuperapp.com`)
Quando a **CLI do FastAPI** é configurada com `--forwarded-allow-ips`, ela confia nesses headers e os utiliza, por exemplo, para gerar as URLs corretas em redirecionamentos.
## Proxy com um prefixo de path removido { #proxy-with-a-stripped-path-prefix }
Você pode ter um proxy que adiciona um prefixo de path à sua aplicação.
Nesses casos, você pode usar `root_path` para configurar sua aplicação. Nesses casos, você pode usar `root_path` para configurar sua aplicação.
O `root_path` é um mecanismo fornecido pela especificação ASGI (que o FastAPI utiliza, através do Starlette). O `root_path` é um mecanismo fornecido pela especificação ASGI (na qual o FastAPI é construído, através do Starlette).
O `root_path` é usado para lidar com esses casos específicos. O `root_path` é usado para lidar com esses casos específicos.
E também é usado internamente ao montar sub-aplicações. E também é usado internamente ao montar sub-aplicações.
## Proxy com um prefixo de caminho removido Ter um proxy com um prefixo de path removido, nesse caso, significa que você poderia declarar um path em `/app` no seu código, mas então você adiciona uma camada no topo (o proxy) que colocaria sua aplicação **FastAPI** sob um path como `/api/v1`.
Ter um proxy com um prefixo de caminho removido, nesse caso, significa que você poderia declarar um caminho em `/app` no seu código, mas então, você adiciona uma camada no topo (o proxy) que colocaria sua aplicação **FastAPI** sob um caminho como `/api/v1`. Nesse caso, o path original `/app` seria servido em `/api/v1/app`.
Nesse caso, o caminho original `/app` seria servido em `/api/v1/app`.
Embora todo o seu código esteja escrito assumindo que existe apenas `/app`. Embora todo o seu código esteja escrito assumindo que existe apenas `/app`.
{* ../../docs_src/behind_a_proxy/tutorial001.py hl[6] *} {* ../../docs_src/behind_a_proxy/tutorial001.py hl[6] *}
E o proxy estaria **"removendo"** o **prefixo do caminho** dinamicamente antes de transmitir a solicitação para o servidor da aplicação (provavelmente Uvicorn via CLI do FastAPI), mantendo sua aplicação convencida de que está sendo servida em `/app`, para que você não precise atualizar todo o seu código para incluir o prefixo `/api/v1`. E o proxy estaria **"removendo"** o **prefixo de path** dinamicamente antes de transmitir a solicitação para o servidor da aplicação (provavelmente Uvicorn via CLI do FastAPI), mantendo sua aplicação convencida de que está sendo servida em `/app`, para que você não precise atualizar todo o seu código para incluir o prefixo `/api/v1`.
Até aqui, tudo funcionaria normalmente. Até aqui, tudo funcionaria normalmente.
Mas então, quando você abre a interface de documentação integrada (o frontend), ele esperaria obter o OpenAPI schema em `/openapi.json`, em vez de `/api/v1/openapi.json`. Mas então, quando você abre a interface de documentação integrada (o frontend), ela esperaria obter o OpenAPI schema em `/openapi.json`, em vez de `/api/v1/openapi.json`.
Então, o frontend (que roda no navegador) tentaria acessar `/openapi.json` e não conseguiria obter o OpenAPI schema. Então, o frontend (que roda no navegador) tentaria acessar `/openapi.json` e não conseguiria obter o OpenAPI schema.
Como temos um proxy com um prefixo de caminho de `/api/v1` para nossa aplicação, o frontend precisa buscar o OpenAPI schema em `/api/v1/openapi.json`. Como temos um proxy com um prefixo de path de `/api/v1` para nossa aplicação, o frontend precisa buscar o OpenAPI schema em `/api/v1/openapi.json`.
```mermaid ```mermaid
graph LR graph LR
@ -47,7 +144,7 @@ O IP `0.0.0.0` é comumente usado para significar que o programa escuta em todos
/// ///
A interface de documentação também precisaria do OpenAPI schema para declarar que API `server` está localizado em `/api/v1` (atrás do proxy). Por exemplo: A interface de documentação também precisaria do OpenAPI schema para declarar que este `server` da API está localizado em `/api/v1` (atrás do proxy). Por exemplo:
```JSON hl_lines="4-8" ```JSON hl_lines="4-8"
{ {
@ -64,16 +161,16 @@ A interface de documentação também precisaria do OpenAPI schema para declarar
} }
``` ```
Neste exemplo, o "Proxy" poderia ser algo como **Traefik**. E o servidor seria algo como CLI do FastAPI com **Uvicorn**, executando sua aplicação FastAPI. Neste exemplo, o "Proxy" poderia ser algo como **Traefik**. E o servidor seria algo como a CLI do FastAPI com **Uvicorn**, executando sua aplicação FastAPI.
### Fornecendo o `root_path` ### Fornecendo o `root_path` { #providing-the-root-path }
Para conseguir isso, você pode usar a opção de linha de comando `--root-path` assim: Para conseguir isso, você pode usar a opção de linha de comando `--root-path` assim:
<div class="termy"> <div class="termy">
```console ```console
$ fastapi run main.py --root-path /api/v1 $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) <span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
``` ```
@ -90,11 +187,11 @@ E a opção de linha de comando `--root-path` fornece esse `root_path`.
/// ///
### Verificando o `root_path` atual ### Verificando o `root_path` atual { #checking-the-current-root-path }
Você pode obter o `root_path` atual usado pela sua aplicação para cada solicitação, ele faz parte do dicionário `scope` (que faz parte da especificação ASGI). Você pode obter o `root_path` atual usado pela sua aplicação para cada solicitação, ele faz parte do dicionário `scope` (que faz parte da especificação ASGI).
Aqui estamos incluindo ele na mensagem apenas para fins de demonstração. Aqui estamos incluindo-o na mensagem apenas para fins de demonstração.
{* ../../docs_src/behind_a_proxy/tutorial001.py hl[8] *} {* ../../docs_src/behind_a_proxy/tutorial001.py hl[8] *}
@ -103,7 +200,7 @@ Então, se você iniciar o Uvicorn com:
<div class="termy"> <div class="termy">
```console ```console
$ fastapi run main.py --root-path /api/v1 $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) <span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
``` ```
@ -119,15 +216,15 @@ A resposta seria algo como:
} }
``` ```
### Configurando o `root_path` na aplicação FastAPI ### Configurando o `root_path` na aplicação FastAPI { #setting-the-root-path-in-the-fastapi-app }
Alternativamente, se você não tiver uma maneira de fornecer uma opção de linha de comando como `--root-path` ou equivalente, você pode definir o parâmetro `--root-path` ao criar sua aplicação FastAPI: Alternativamente, se você não tiver uma maneira de fornecer uma opção de linha de comando como `--root-path` ou equivalente, você pode definir o parâmetro `root_path` ao criar sua aplicação FastAPI:
{* ../../docs_src/behind_a_proxy/tutorial002.py hl[3] *} {* ../../docs_src/behind_a_proxy/tutorial002.py hl[3] *}
Passar o `root_path`h para `FastAPI` seria o equivalente a passar a opção de linha de comando `--root-path` para Uvicorn ou Hypercorn. Passar o `root_path` para `FastAPI` seria o equivalente a passar a opção de linha de comando `--root-path` para Uvicorn ou Hypercorn.
### Sobre `root_path` ### Sobre `root_path` { #about-root-path }
Tenha em mente que o servidor (Uvicorn) não usará esse `root_path` para nada além de passá-lo para a aplicação. Tenha em mente que o servidor (Uvicorn) não usará esse `root_path` para nada além de passá-lo para a aplicação.
@ -144,19 +241,19 @@ Portanto, ele não esperará ser acessado em `http://127.0.0.1:8000/api/v1/app`.
O Uvicorn esperará que o proxy acesse o Uvicorn em `http://127.0.0.1:8000/app`, e então seria responsabilidade do proxy adicionar o prefixo extra `/api/v1` no topo. O Uvicorn esperará que o proxy acesse o Uvicorn em `http://127.0.0.1:8000/app`, e então seria responsabilidade do proxy adicionar o prefixo extra `/api/v1` no topo.
## Sobre proxies com um prefixo de caminho removido ## Sobre proxies com um prefixo de path removido { #about-proxies-with-a-stripped-path-prefix }
Tenha em mente que um proxy com prefixo de caminho removido é apenas uma das maneiras de configurá-lo. Tenha em mente que um proxy com prefixo de path removido é apenas uma das maneiras de configurá-lo.
Provavelmente, em muitos casos, o padrão será que o proxy não tenha um prefixo de caminho removido. Provavelmente, em muitos casos, o padrão será que o proxy não tenha um prefixo de path removido.
Em um caso como esse (sem um prefixo de caminho removido), o proxy escutaria em algo como `https://myawesomeapp.com`, e então se o navegador acessar `https://myawesomeapp.com/api/v1/app` e seu servidor (por exemplo, Uvicorn) escutar em `http://127.0.0.1:8000` o proxy (sem um prefixo de caminho removido) acessaria o Uvicorn no mesmo caminho: `http://127.0.0.1:8000/api/v1/app`. Em um caso como esse (sem um prefixo de path removido), o proxy escutaria em algo como `https://myawesomeapp.com`, e então, se o navegador acessar `https://myawesomeapp.com/api/v1/app` e seu servidor (por exemplo, Uvicorn) escutar em `http://127.0.0.1:8000`, o proxy (sem um prefixo de path removido) acessaria o Uvicorn no mesmo path: `http://127.0.0.1:8000/api/v1/app`.
## Testando localmente com Traefik ## Testando localmente com Traefik { #testing-locally-with-traefik }
Você pode facilmente executar o experimento localmente com um prefixo de caminho removido usando <a href="https://docs.traefik.io/" class="external-link" target="_blank">Traefik</a>. Você pode facilmente executar o experimento localmente com um prefixo de path removido usando <a href="https://docs.traefik.io/" class="external-link" target="_blank">Traefik</a>.
<a href="https://github.com/containous/traefik/releases" class="external-link" target="_blank">Faça o download do Traefik.</a>, Ele é um único binário e você pode extrair o arquivo compactado e executá-lo diretamente do terminal. <a href="https://github.com/containous/traefik/releases" class="external-link" target="_blank">Faça o download do Traefik</a>, ele é um único binário, você pode extrair o arquivo compactado e executá-lo diretamente do terminal.
Então, crie um arquivo `traefik.toml` com: Então, crie um arquivo `traefik.toml` com:
@ -203,9 +300,9 @@ Agora crie esse outro arquivo `routes.toml`:
url = "http://127.0.0.1:8000" url = "http://127.0.0.1:8000"
``` ```
Esse arquivo configura o Traefik para usar o prefixo de caminho `/api/v1`. Esse arquivo configura o Traefik para usar o prefixo de path `/api/v1`.
E então ele redirecionará suas solicitações para seu Uvicorn rodando em `http://127.0.0.1:8000`. E então o Traefik redirecionará suas solicitações para seu Uvicorn rodando em `http://127.0.0.1:8000`.
Agora inicie o Traefik: Agora inicie o Traefik:
@ -224,14 +321,14 @@ E agora inicie sua aplicação, usando a opção `--root-path`:
<div class="termy"> <div class="termy">
```console ```console
$ fastapi run main.py --root-path /api/v1 $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) <span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
``` ```
</div> </div>
### Verifique as respostas ### Verifique as respostas { #check-the-responses }
Agora, se você for ao URL com a porta para o Uvicorn: <a href="http://127.0.0.1:8000/app" class="external-link" target="_blank">http://127.0.0.1:8000/app</a>, você verá a resposta normal: Agora, se você for ao URL com a porta para o Uvicorn: <a href="http://127.0.0.1:8000/app" class="external-link" target="_blank">http://127.0.0.1:8000/app</a>, você verá a resposta normal:
@ -248,7 +345,7 @@ Perceba que, mesmo acessando em `http://127.0.0.1:8000/app`, ele mostra o `root_
/// ///
E agora abra o URL com a porta para o Traefik, incluindo o prefixo de caminho: <a href="http://127.0.0.1:9999/api/v1/app" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/app</a>. E agora abra o URL com a porta para o Traefik, incluindo o prefixo de path: <a href="http://127.0.0.1:9999/api/v1/app" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/app</a>.
Obtemos a mesma resposta: Obtemos a mesma resposta:
@ -259,19 +356,19 @@ Obtemos a mesma resposta:
} }
``` ```
mas desta vez no URL com o prefixo de caminho fornecido pelo proxy: `/api/v1`. mas desta vez no URL com o prefixo de path fornecido pelo proxy: `/api/v1`.
Claro, a ideia aqui é que todos acessariam a aplicação através do proxy, então a versão com o prefixo de caminho `/api/v1` é a "correta". Claro, a ideia aqui é que todos acessariam a aplicação através do proxy, então a versão com o prefixo de path `/api/v1` é a "correta".
E a versão sem o prefixo de caminho (`http://127.0.0.1:8000/app`), fornecida diretamente pelo Uvicorn, seria exclusivamente para o _proxy_ (Traefik) acessá-la. E a versão sem o prefixo de path (`http://127.0.0.1:8000/app`), fornecida diretamente pelo Uvicorn, seria exclusivamente para o _proxy_ (Traefik) acessá-la.
Isso demonstra como o Proxy (Traefik) usa o prefixo de caminho e como o servidor (Uvicorn) usa o `root_path` da opção `--root-path`. Isso demonstra como o Proxy (Traefik) usa o prefixo de path e como o servidor (Uvicorn) usa o `root_path` da opção `--root-path`.
### Verifique a interface de documentação ### Verifique a interface de documentação { #check-the-docs-ui }
Mas aqui está a parte divertida. ✨ Mas aqui está a parte divertida. ✨
A maneira "oficial" de acessar a aplicação seria através do proxy com o prefixo de caminho que definimos. Então, como esperaríamos, se você tentar a interface de documentação servida diretamente pelo Uvicorn, sem o prefixo de caminho no URL, ela não funcionará, porque espera ser acessada através do proxy. A maneira "oficial" de acessar a aplicação seria através do proxy com o prefixo de path que definimos. Então, como esperaríamos, se você tentar a interface de documentação servida diretamente pelo Uvicorn, sem o prefixo de path no URL, ela não funcionará, porque espera ser acessada através do proxy.
Você pode verificar em <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>: Você pode verificar em <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>:
@ -287,9 +384,9 @@ Exatamente como queríamos. ✔️
Isso porque o FastAPI usa esse `root_path` para criar o `server` padrão no OpenAPI com o URL fornecido pelo `root_path`. Isso porque o FastAPI usa esse `root_path` para criar o `server` padrão no OpenAPI com o URL fornecido pelo `root_path`.
## Servidores adicionais ## Servidores adicionais { #additional-servers }
/// warning | Aviso /// warning | Atenção
Este é um caso de uso mais avançado. Sinta-se à vontade para pular. Este é um caso de uso mais avançado. Sinta-se à vontade para pular.
@ -297,7 +394,7 @@ Este é um caso de uso mais avançado. Sinta-se à vontade para pular.
Por padrão, o **FastAPI** criará um `server` no OpenAPI schema com o URL para o `root_path`. Por padrão, o **FastAPI** criará um `server` no OpenAPI schema com o URL para o `root_path`.
Mas você também pode fornecer outros `servers` alternativos, por exemplo, se quiser que a *mesma* interface de documentação interaja com ambientes de staging e produção. Mas você também pode fornecer outros `servers` alternativos, por exemplo, se quiser que a mesma interface de documentação interaja com ambientes de staging e produção.
Se você passar uma lista personalizada de `servers` e houver um `root_path` (porque sua API está atrás de um proxy), o **FastAPI** inserirá um "server" com esse `root_path` no início da lista. Se você passar uma lista personalizada de `servers` e houver um `root_path` (porque sua API está atrás de um proxy), o **FastAPI** inserirá um "server" com esse `root_path` no início da lista.
@ -346,7 +443,7 @@ A interface de documentação interagirá com o servidor que você selecionar.
/// ///
### Desabilitar servidor automático de `root_path` ### Desabilitar servidor automático de `root_path` { #disable-automatic-server-from-root-path }
Se você não quiser que o **FastAPI** inclua um servidor automático usando o `root_path`, você pode usar o parâmetro `root_path_in_servers=False`: Se você não quiser que o **FastAPI** inclua um servidor automático usando o `root_path`, você pode usar o parâmetro `root_path_in_servers=False`:
@ -354,8 +451,8 @@ Se você não quiser que o **FastAPI** inclua um servidor automático usando o `
e então ele não será incluído no OpenAPI schema. e então ele não será incluído no OpenAPI schema.
## Montando uma sub-aplicação ## Montando uma sub-aplicação { #mounting-a-sub-application }
Se você precisar montar uma sub-aplicação (como descrito em [Sub Aplicações - Montagens](sub-applications.md){.internal-link target=_blank}) enquanto também usa um proxy com `root_path`, você pode fazer isso normalmente, como esperaria. Se você precisar montar uma sub-aplicação (como descrito em [Sub-aplicações - Montagens](sub-applications.md){.internal-link target=_blank}) enquanto também usa um proxy com `root_path`, você pode fazer isso normalmente, como esperaria.
O FastAPI usará internamente o `root_path` de forma inteligente, então tudo funcionará. ✨ O FastAPI usará internamente o `root_path` de forma inteligente, então tudo funcionará. ✨

View File

@ -1,4 +1,4 @@
# Resposta Personalizada - HTML, Stream, File e outras # Resposta Personalizada - HTML, Stream, File e outras { #custom-response-html-stream-file-others }
Por padrão, o **FastAPI** irá retornar respostas utilizando `JSONResponse`. Por padrão, o **FastAPI** irá retornar respostas utilizando `JSONResponse`.
@ -8,9 +8,9 @@ Mas se você retornar uma `Response` diretamente (ou qualquer subclasse, como `J
Mas você também pode declarar a `Response` que você deseja utilizar (e.g. qualquer subclasse de `Response`), em um *decorador de operação de rota* utilizando o parâmetro `response_class`. Mas você também pode declarar a `Response` que você deseja utilizar (e.g. qualquer subclasse de `Response`), em um *decorador de operação de rota* utilizando o parâmetro `response_class`.
Os conteúdos que você retorna em sua *função de operador de rota* serão colocados dentro dessa `Response`. Os conteúdos que você retorna em sua *função de operação de rota* serão colocados dentro dessa `Response`.
E se a `Response` tiver um media type JSON (`application/json`), como é o caso com `JSONResponse` e `UJSONResponse`, os dados que você retornar serão automaticamente convertidos (e filtrados) com qualquer `response_model` do Pydantic que for declarado em sua *função de operador de rota*. E se a `Response` tiver um media type JSON (`application/json`), como é o caso com `JSONResponse` e `UJSONResponse`, os dados que você retornar serão automaticamente convertidos (e filtrados) com qualquer `response_model` do Pydantic que for declarado no decorador de operação de rota.
/// note | Nota /// note | Nota
@ -18,7 +18,7 @@ Se você utilizar uma classe de Resposta sem media type, o FastAPI esperará que
/// ///
## Utilizando `ORJSONResponse` ## Utilizando `ORJSONResponse` { #use-orjsonresponse }
Por exemplo, se você precisa bastante de performance, você pode instalar e utilizar o <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a> e definir a resposta para ser uma `ORJSONResponse`. Por exemplo, se você precisa bastante de performance, você pode instalar e utilizar o <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a> e definir a resposta para ser uma `ORJSONResponse`.
@ -48,7 +48,7 @@ A `ORJSONResponse` está disponível apenas no FastAPI, e não no Starlette.
/// ///
## Resposta HTML ## Resposta HTML { #html-response }
Para retornar uma resposta com HTML diretamente do **FastAPI**, utilize `HTMLResponse`. Para retornar uma resposta com HTML diretamente do **FastAPI**, utilize `HTMLResponse`.
@ -67,7 +67,7 @@ E será documentado como tal no OpenAPI.
/// ///
### Retornando uma `Response` ### Retornando uma `Response` { #return-a-response }
Como visto em [Retornando uma Resposta Diretamente](response-directly.md){.internal-link target=_blank}, você também pode sobrescrever a resposta diretamente na sua *operação de rota*, ao retornar ela. Como visto em [Retornando uma Resposta Diretamente](response-directly.md){.internal-link target=_blank}, você também pode sobrescrever a resposta diretamente na sua *operação de rota*, ao retornar ela.
@ -75,7 +75,7 @@ O mesmo exemplo de antes, retornando uma `HTMLResponse`, poderia parecer com:
{* ../../docs_src/custom_response/tutorial003.py hl[2,7,19] *} {* ../../docs_src/custom_response/tutorial003.py hl[2,7,19] *}
/// warning | Aviso /// warning | Atenção
Uma `Response` retornada diretamente em sua *função de operação de rota* não será documentada no OpenAPI (por exemplo, o `Content-Type` não será documentado) e não será visível na documentação interativa automática. Uma `Response` retornada diretamente em sua *função de operação de rota* não será documentada no OpenAPI (por exemplo, o `Content-Type` não será documentado) e não será visível na documentação interativa automática.
@ -87,13 +87,13 @@ Obviamente, o cabeçalho `Content-Type`, o código de status, etc, virão do obj
/// ///
### Documentar no OpenAPI e sobrescrever `Response` ### Documentar no OpenAPI e sobrescrever `Response` { #document-in-openapi-and-override-response }
Se você deseja sobrescrever a resposta dentro de uma função, mas ao mesmo tempo documentar o "media type" no OpenAPI, você pode utilizar o parâmetro `response_class` E retornar um objeto `Response`. Se você deseja sobrescrever a resposta dentro de uma função, mas ao mesmo tempo documentar o "media type" no OpenAPI, você pode utilizar o parâmetro `response_class` E retornar um objeto `Response`.
A `response_class` será usada apenas para documentar o OpenAPI da *operação de rota*, mas sua `Response` será usada como foi definida. A `response_class` será usada apenas para documentar o OpenAPI da *operação de rota*, mas sua `Response` será usada como foi definida.
##### Retornando uma `HTMLResponse` diretamente #### Retornando uma `HTMLResponse` diretamente { #return-an-htmlresponse-directly }
Por exemplo, poderia ser algo como: Por exemplo, poderia ser algo como:
@ -107,7 +107,7 @@ Mas se você passasse uma `HTMLResponse` em `response_class` também, o **FastAP
<img src="/img/tutorial/custom-response/image01.png"> <img src="/img/tutorial/custom-response/image01.png">
## Respostas disponíveis ## Respostas disponíveis { #available-responses }
Aqui estão algumas dos tipos de resposta disponíveis. Aqui estão algumas dos tipos de resposta disponíveis.
@ -121,7 +121,7 @@ O **FastAPI** provê a mesma `starlette.responses` como `fastapi.responses` apen
/// ///
### `Response` ### `Response` { #response }
A classe principal de respostas, todas as outras respostas herdam dela. A classe principal de respostas, todas as outras respostas herdam dela.
@ -138,23 +138,23 @@ O FastAPI (Starlette, na verdade) irá incluir o cabeçalho Content-Length autom
{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *} {* ../../docs_src/response_directly/tutorial002.py hl[1,18] *}
### `HTMLResponse` ### `HTMLResponse` { #htmlresponse }
Usa algum texto ou sequência de bytes e retorna uma resposta HTML. Como você leu acima. Usa algum texto ou sequência de bytes e retorna uma resposta HTML. Como você leu acima.
### `PlainTextResponse` ### `PlainTextResponse` { #plaintextresponse }
Usa algum texto ou sequência de bytes para retornar uma resposta de texto não formatado. Usa algum texto ou sequência de bytes para retornar uma resposta de texto não formatado.
{* ../../docs_src/custom_response/tutorial005.py hl[2,7,9] *} {* ../../docs_src/custom_response/tutorial005.py hl[2,7,9] *}
### `JSONResponse` ### `JSONResponse` { #jsonresponse }
Pega alguns dados e retorna uma resposta com codificação `application/json`. Pega alguns dados e retorna uma resposta com codificação `application/json`.
É a resposta padrão utilizada no **FastAPI**, como você leu acima. É a resposta padrão utilizada no **FastAPI**, como você leu acima.
### `ORJSONResponse` ### `ORJSONResponse` { #orjsonresponse }
Uma alternativa mais rápida de resposta JSON utilizando o <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a>, como você leu acima. Uma alternativa mais rápida de resposta JSON utilizando o <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a>, como você leu acima.
@ -164,7 +164,7 @@ Essa resposta requer a instalação do pacote `orjson`, com o comando `pip insta
/// ///
### `UJSONResponse` ### `UJSONResponse` { #ujsonresponse }
Uma alternativa de resposta JSON utilizando a biblioteca <a href="https://github.com/ultrajson/ultrajson" class="external-link" target="_blank">`ujson`</a>. Uma alternativa de resposta JSON utilizando a biblioteca <a href="https://github.com/ultrajson/ultrajson" class="external-link" target="_blank">`ujson`</a>.
@ -174,7 +174,7 @@ Essa resposta requer a instalação do pacote `ujson`, com o comando `pip instal
/// ///
/// warning | Aviso /// warning | Atenção
`ujson` é menos cauteloso que a implementação nativa do Python na forma que os casos especiais são tratados `ujson` é menos cauteloso que a implementação nativa do Python na forma que os casos especiais são tratados
@ -188,7 +188,7 @@ Essa resposta requer a instalação do pacote `ujson`, com o comando `pip instal
/// ///
### `RedirectResponse` ### `RedirectResponse` { #redirectresponse }
Retorna um redirecionamento HTTP. Utiliza o código de status 307 (Redirecionamento Temporário) por padrão. Retorna um redirecionamento HTTP. Utiliza o código de status 307 (Redirecionamento Temporário) por padrão.
@ -212,26 +212,24 @@ Você também pode utilizar o parâmetro `status_code` combinado com o parâmetr
{* ../../docs_src/custom_response/tutorial006c.py hl[2,7,9] *} {* ../../docs_src/custom_response/tutorial006c.py hl[2,7,9] *}
### `StreamingResponse` ### `StreamingResponse` { #streamingresponse }
Recebe uma gerador assíncrono ou um gerador/iterador comum e retorna o corpo da requisição continuamente (stream). Recebe um gerador assíncrono ou um gerador/iterador comum e retorna o corpo da resposta de forma contínua (stream).
{* ../../docs_src/custom_response/tutorial007.py hl[2,14] *} {* ../../docs_src/custom_response/tutorial007.py hl[2,14] *}
#### Utilizando `StreamingResponse` com objetos semelhantes a arquivos #### Utilizando `StreamingResponse` com objetos semelhantes a arquivos { #using-streamingresponse-with-file-like-objects }
Se você tiver um objeto semelhante a um arquivo (e.g. o objeto retornado por `open()`), você pode criar uma função geradora para iterar sobre esse objeto. Se você tiver um objeto <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">semelhante a um arquivo</a> (e.g. o objeto retornado por `open()`), você pode criar uma função geradora para iterar sobre esse objeto.
Dessa forma, você não precisa ler todo o arquivo na memória primeiro, e você pode passar essa função geradora para `StreamingResponse` e retorná-la. Dessa forma, você não precisa ler todo o arquivo na memória primeiro, e você pode passar essa função geradora para `StreamingResponse` e retorná-la.
Isso inclui muitas bibliotecas que interagem com armazenamento em nuvem, processamento de vídeos, entre outras. Isso inclui muitas bibliotecas que interagem com armazenamento em nuvem, processamento de vídeos, entre outras.
```{ .python .annotate hl_lines="2 10-12 14" } {* ../../docs_src/custom_response/tutorial008.py hl[2,10:12,14] *}
{!../../docs_src/custom_response/tutorial008.py!}
```
1. Essa é a função geradora. É definida como "função geradora" porque contém declarações `yield` nela. 1. Essa é a função geradora. É definida como "função geradora" porque contém declarações `yield` nela.
2. Ao utilizar o bloco `with`, nós garantimos que o objeto semelhante a um arquivo é fechado após a função geradora ser finalizada. Isto é, após a resposta terminar de ser enivada. 2. Ao utilizar o bloco `with`, nós garantimos que o objeto semelhante a um arquivo é fechado após a função geradora ser finalizada. Isto é, após a resposta terminar de ser enviada.
3. Essa declaração `yield from` informa a função para iterar sobre essa coisa nomeada de `file_like`. E então, para cada parte iterada, fornece essa parte como se viesse dessa função geradora (`iterfile`). 3. Essa declaração `yield from` informa a função para iterar sobre essa coisa nomeada de `file_like`. E então, para cada parte iterada, fornece essa parte como se viesse dessa função geradora (`iterfile`).
Então, é uma função geradora que transfere o trabalho de "geração" para alguma outra coisa interna. Então, é uma função geradora que transfere o trabalho de "geração" para alguma outra coisa interna.
@ -244,10 +242,10 @@ Perceba que aqui estamos utilizando o `open()` da biblioteca padrão que não su
/// ///
### `FileResponse` ### `FileResponse` { #fileresponse }
Envia um arquivo de forma assíncrona e contínua (stream). Envia um arquivo de forma assíncrona e contínua (stream).
*
Recebe um conjunto de argumentos do construtor diferente dos outros tipos de resposta: Recebe um conjunto de argumentos do construtor diferente dos outros tipos de resposta:
* `path` - O caminho do arquivo que será transmitido * `path` - O caminho do arquivo que será transmitido
@ -265,7 +263,7 @@ Você também pode usar o parâmetro `response_class`:
Nesse caso, você pode retornar o caminho do arquivo diretamente da sua *função de operação de rota*. Nesse caso, você pode retornar o caminho do arquivo diretamente da sua *função de operação de rota*.
## Classe de resposta personalizada ## Classe de resposta personalizada { #custom-response-class }
Você pode criar sua própria classe de resposta, herdando de `Response` e usando essa nova classe. Você pode criar sua própria classe de resposta, herdando de `Response` e usando essa nova classe.
@ -273,7 +271,7 @@ Por exemplo, vamos supor que você queira utilizar o <a href="https://github.com
Vamos supor também que você queira retornar um JSON indentado e formatado, então você quer utilizar a opção `orjson.OPT_INDENT_2` do orjson. Vamos supor também que você queira retornar um JSON indentado e formatado, então você quer utilizar a opção `orjson.OPT_INDENT_2` do orjson.
Você poderia criar uma classe `CustomORJSONResponse`. A principal coisa a ser feita é sobrecarregar o método render da classe Response, `Response.render(content)`, que retorna o conteúdo em bytes, para retornar o conteúdo que você deseja: Você poderia criar uma classe `CustomORJSONResponse`. A principal coisa a ser feita é sobrecarregar o método render da classe Response, `Response.render(content)`, que retorna o conteúdo em bytes:
{* ../../docs_src/custom_response/tutorial009c.py hl[9:14,17] *} {* ../../docs_src/custom_response/tutorial009c.py hl[9:14,17] *}
@ -293,7 +291,7 @@ Agora em vez de retornar:
Obviamente, você provavelmente vai encontrar maneiras muito melhores de se aproveitar disso do que a formatação de JSON. 😉 Obviamente, você provavelmente vai encontrar maneiras muito melhores de se aproveitar disso do que a formatação de JSON. 😉
## Classe de resposta padrão ## Classe de resposta padrão { #default-response-class }
Quando você criar uma instância da classe **FastAPI** ou um `APIRouter` você pode especificar qual classe de resposta utilizar por padrão. Quando você criar uma instância da classe **FastAPI** ou um `APIRouter` você pode especificar qual classe de resposta utilizar por padrão.
@ -309,6 +307,6 @@ Você ainda pode substituir `response_class` em *operações de rota* como antes
/// ///
## Documentação adicional ## Documentação adicional { #additional-documentation }
Você também pode declarar o media type e muitos outros detalhes no OpenAPI utilizando `responses`: [Retornos Adicionais no OpenAPI](additional-responses.md){.internal-link target=_blank}. Você também pode declarar o media type e muitos outros detalhes no OpenAPI utilizando `responses`: [Retornos Adicionais no OpenAPI](additional-responses.md){.internal-link target=_blank}.

View File

@ -1,4 +1,4 @@
# Usando Dataclasses # Usando Dataclasses { #using-dataclasses }
FastAPI é construído em cima do **Pydantic**, e eu tenho mostrado como usar modelos Pydantic para declarar requisições e respostas. FastAPI é construído em cima do **Pydantic**, e eu tenho mostrado como usar modelos Pydantic para declarar requisições e respostas.
@ -28,7 +28,7 @@ Mas se você tem um monte de dataclasses por aí, este é um truque legal para u
/// ///
## Dataclasses em `response_model` ## Dataclasses em `response_model` { #dataclasses-in-response-model }
Você também pode usar `dataclasses` no parâmetro `response_model`: Você também pode usar `dataclasses` no parâmetro `response_model`:
@ -40,7 +40,7 @@ Dessa forma, seu esquema aparecerá na interface de documentação da API:
<img src="/img/tutorial/dataclasses/image01.png"> <img src="/img/tutorial/dataclasses/image01.png">
## Dataclasses em Estruturas de Dados Aninhadas ## Dataclasses em Estruturas de Dados Aninhadas { #dataclasses-in-nested-data-structures }
Você também pode combinar `dataclasses` com outras anotações de tipo para criar estruturas de dados aninhadas. Você também pode combinar `dataclasses` com outras anotações de tipo para criar estruturas de dados aninhadas.
@ -48,9 +48,7 @@ Em alguns casos, você ainda pode ter que usar a versão do Pydantic das `datacl
Nesse caso, você pode simplesmente trocar as `dataclasses` padrão por `pydantic.dataclasses`, que é um substituto direto: Nesse caso, você pode simplesmente trocar as `dataclasses` padrão por `pydantic.dataclasses`, que é um substituto direto:
```{ .python .annotate hl_lines="1 5 8-11 14-17 23-25 28" } {* ../../docs_src/dataclasses/tutorial003.py hl[1,5,8:11,14:17,23:25,28] *}
{!../../docs_src/dataclasses/tutorial003.py!}
```
1. Ainda importamos `field` das `dataclasses` padrão. 1. Ainda importamos `field` das `dataclasses` padrão.
@ -86,12 +84,12 @@ Você pode combinar `dataclasses` com outras anotações de tipo em muitas combi
Confira as dicas de anotação no código acima para ver mais detalhes específicos. Confira as dicas de anotação no código acima para ver mais detalhes específicos.
## Saiba Mais ## Saiba Mais { #learn-more }
Você também pode combinar `dataclasses` com outros modelos Pydantic, herdar deles, incluí-los em seus próprios modelos, etc. Você também pode combinar `dataclasses` com outros modelos Pydantic, herdar deles, incluí-los em seus próprios modelos, etc.
Para saber mais, confira a <a href="https://docs.pydantic.dev/latest/concepts/dataclasses/" class="external-link" target="_blank">documentação do Pydantic sobre dataclasses</a>. Para saber mais, confira a <a href="https://docs.pydantic.dev/latest/concepts/dataclasses/" class="external-link" target="_blank">documentação do Pydantic sobre dataclasses</a>.
## Versão ## Versão { #version }
Isso está disponível desde a versão `0.67.0` do FastAPI. 🔖 Isso está disponível desde a versão `0.67.0` do FastAPI. 🔖

View File

@ -1,65 +1,64 @@
# Eventos de vida útil # Eventos de lifespan { #lifespan-events }
Você pode definir a lógica (código) que poderia ser executada antes da aplicação **inicializar**. Isso significa que esse código será executado **uma vez**, **antes** da aplicação **começar a receber requisições**. Você pode definir a lógica (código) que deve ser executada antes da aplicação **inicializar**. Isso significa que esse código será executado **uma vez**, **antes** de a aplicação **começar a receber requisições**.
Do mesmo modo, você pode definir a lógica (código) que será executada quando a aplicação estiver sendo **encerrada**. Nesse caso, este código será executado **uma vez**, **depois** de ter possivelmente tratado **várias requisições**. Da mesma forma, você pode definir a lógica (código) que deve ser executada quando a aplicação estiver **encerrando**. Nesse caso, esse código será executado **uma vez**, **depois** de possivelmente ter tratado **várias requisições**.
Por conta desse código ser executado antes da aplicação **começar** a receber requisições, e logo após **terminar** de lidar com as requisições, ele cobre toda a **vida útil** (_lifespan_) da aplicação (o termo "vida útil" será importante em um segundo 😉). Como esse código é executado antes de a aplicação **começar** a receber requisições e logo depois que ela **termina** de lidar com as requisições, ele cobre todo o **lifespan** da aplicação (a palavra "lifespan" será importante em um segundo 😉).
Pode ser muito útil para configurar **recursos** que você precisa usar por toda aplicação, e que são **compartilhados** entre as requisições, e/ou que você precisa **limpar** depois. Por exemplo, o pool de uma conexão com o banco de dados ou carregamento de um modelo compartilhado de aprendizado de máquina (_machine learning_). Isso pode ser muito útil para configurar **recursos** que você precisa usar por toda a aplicação, e que são **compartilhados** entre as requisições e/ou que você precisa **limpar** depois. Por exemplo, um pool de conexões com o banco de dados ou o carregamento de um modelo de machine learning compartilhado.
## Caso de uso ## Caso de uso { #use-case }
Vamos iniciar com um exemplo de **caso de uso** e então ver como resolvê-lo com isso. Vamos começar com um exemplo de **caso de uso** e então ver como resolvê-lo com isso.
Vamos imaginar que você tem alguns **modelos de _machine learning_** que deseja usar para lidar com as requisições. 🤖 Vamos imaginar que você tem alguns **modelos de machine learning** que deseja usar para lidar com as requisições. 🤖
Os mesmos modelos são compartilhados entre as requisições, então não é um modelo por requisição, ou um por usuário ou algo parecido. Os mesmos modelos são compartilhados entre as requisições, então não é um modelo por requisição, ou um por usuário, ou algo parecido.
Vamos imaginar que o carregamento do modelo pode **demorar bastante tempo**, porque ele tem que ler muitos **dados do disco**. Então você não quer fazer isso a cada requisição. Vamos imaginar que o carregamento do modelo pode **demorar bastante tempo**, porque ele precisa ler muitos **dados do disco**. Então você não quer fazer isso a cada requisição.
Você poderia carregá-lo no nível mais alto do módulo/arquivo, mas isso também poderia significaria **carregar o modelo** mesmo se você estiver executando um simples teste automatizado, então esse teste poderia ser **lento** porque teria que esperar o carregamento do modelo antes de ser capaz de executar uma parte independente do código. Você poderia carregá-lo no nível mais alto do módulo/arquivo, mas isso também significaria **carregar o modelo** mesmo se você estivesse executando um teste automatizado simples; então esse teste poderia ser **lento** porque teria que esperar o carregamento do modelo antes de conseguir executar uma parte independente do código.
É isso que vamos resolver: vamos carregar o modelo antes de as requisições serem tratadas, mas apenas um pouco antes de a aplicação começar a receber requisições, não enquanto o código estiver sendo carregado.
Isso é que nós iremos resolver, vamos carregar o modelo antes das requisições serem manuseadas, mas apenas um pouco antes da aplicação começar a receber requisições, não enquanto o código estiver sendo carregado. ## Lifespan { #lifespan }
## Vida útil (_Lifespan_) Você pode definir essa lógica de *inicialização* e *encerramento* usando o parâmetro `lifespan` da aplicação `FastAPI`, e um "gerenciador de contexto" (vou mostrar o que é isso em um segundo).
Você pode definir essa lógica de *inicialização* e *encerramento* usando os parâmetros de `lifespan` da aplicação `FastAPI`, e um "gerenciador de contexto" (te mostrarei o que é isso a seguir). Vamos começar com um exemplo e depois ver em detalhes.
Vamos iniciar com um exemplo e ver isso detalhadamente. Nós criamos uma função assíncrona `lifespan()` com `yield` assim:
Nós criamos uma função assíncrona chamada `lifespan()` com `yield` como este:
{* ../../docs_src/events/tutorial003.py hl[16,19] *} {* ../../docs_src/events/tutorial003.py hl[16,19] *}
Aqui nós estamos simulando a *inicialização* custosa do carregamento do modelo colocando a (falsa) função de modelo no dicionário com modelos de _machine learning_ antes do `yield`. Este código será executado **antes** da aplicação **começar a receber requisições**, durante a *inicialização*. Aqui estamos simulando a operação de *inicialização* custosa de carregar o modelo, colocando a (falsa) função do modelo no dicionário com modelos de machine learning antes do `yield`. Esse código será executado **antes** de a aplicação **começar a receber requisições**, durante a *inicialização*.
E então, logo após o `yield`, descarregaremos o modelo. Esse código será executado **após** a aplicação **terminar de lidar com as requisições**, pouco antes do *encerramento*. Isso poderia, por exemplo, liberar recursos como memória ou GPU. E então, logo após o `yield`, descarregamos o modelo. Esse código será executado **depois** de a aplicação **terminar de lidar com as requisições**, pouco antes do *encerramento*. Isso poderia, por exemplo, liberar recursos como memória ou uma GPU.
/// tip | Dica /// tip | Dica
O `shutdown` aconteceria quando você estivesse **encerrando** a aplicação. O `shutdown` aconteceria quando você estivesse **encerrando** a aplicação.
Talvez você precise inicializar uma nova versão, ou apenas cansou de executá-la. 🤷 Talvez você precise iniciar uma nova versão, ou apenas cansou de executá-la. 🤷
/// ///
### Função _lifespan_ ### Função lifespan { #lifespan-function }
A primeira coisa a notar, é que estamos definindo uma função assíncrona com `yield`. Isso é muito semelhante à Dependências com `yield`. A primeira coisa a notar é que estamos definindo uma função assíncrona com `yield`. Isso é muito semelhante a Dependências com `yield`.
{* ../../docs_src/events/tutorial003.py hl[14:19] *} {* ../../docs_src/events/tutorial003.py hl[14:19] *}
A primeira parte da função, antes do `yield`, será executada **antes** da aplicação inicializar. A primeira parte da função, antes do `yield`, será executada **antes** de a aplicação iniciar.
E a parte posterior do `yield` irá executar **após** a aplicação ser encerrada. E a parte posterior ao `yield` será executada **depois** de a aplicação ter terminado.
### Gerenciador de Contexto Assíncrono ### Gerenciador de contexto assíncrono { #async-context-manager }
Se você verificar, a função está decorada com um `@asynccontextmanager`. Se você verificar, a função está decorada com um `@asynccontextmanager`.
Que converte a função em algo chamado de "**Gerenciador de Contexto Assíncrono**". Isso converte a função em algo chamado "**gerenciador de contexto assíncrono**".
{* ../../docs_src/events/tutorial003.py hl[1,13] *} {* ../../docs_src/events/tutorial003.py hl[1,13] *}
@ -70,97 +69,97 @@ with open("file.txt") as file:
file.read() file.read()
``` ```
Nas versões mais recentes de Python, há também um **gerenciador de contexto assíncrono**. Você o usaria com `async with`: Em versões mais recentes do Python, há também um **gerenciador de contexto assíncrono**. Você o usaria com `async with`:
```Python ```Python
async with lifespan(app): async with lifespan(app):
await do_stuff() await do_stuff()
``` ```
Quando você cria um gerenciador de contexto ou um gerenciador de contexto assíncrono como mencionado acima, o que ele faz é que, antes de entrar no bloco `with`, ele irá executar o código anterior ao `yield`, e depois de sair do bloco `with`, ele irá executar o código depois do `yield`. Quando você cria um gerenciador de contexto ou um gerenciador de contexto assíncrono como acima, o que ele faz é: antes de entrar no bloco `with`, ele executa o código antes do `yield`, e após sair do bloco `with`, ele executa o código depois do `yield`.
No nosso exemplo de código acima, nós não usamos ele diretamente, mas nós passamos para o FastAPI para ele usá-lo. No nosso exemplo de código acima, não o usamos diretamente, mas passamos para o FastAPI para que ele o use.
O parâmetro `lifespan` da aplicação `FastAPI` usa um **Gerenciador de Contexto Assíncrono**, então nós podemos passar nosso novo gerenciador de contexto assíncrono do `lifespan` para ele. O parâmetro `lifespan` da aplicação `FastAPI` aceita um **gerenciador de contexto assíncrono**, então podemos passar para ele nosso novo gerenciador de contexto assíncrono `lifespan`.
{* ../../docs_src/events/tutorial003.py hl[22] *} {* ../../docs_src/events/tutorial003.py hl[22] *}
## Eventos alternativos (deprecados) ## Eventos alternativos (descontinuados) { #alternative-events-deprecated }
/// warning | Aviso /// warning | Atenção
A maneira recomendada para lidar com a *inicialização* e o *encerramento* é usando o parâmetro `lifespan` da aplicação `FastAPI` como descrito acima. A forma recomendada de lidar com a *inicialização* e o *encerramento* é usando o parâmetro `lifespan` da aplicação `FastAPI`, como descrito acima. Se você fornecer um parâmetro `lifespan`, os manipuladores de eventos `startup` e `shutdown` não serão mais chamados. É tudo `lifespan` ou tudo por eventos, não ambos.
Você provavelmente pode pular essa parte. Você provavelmente pode pular esta parte.
/// ///
Existe uma forma alternativa para definir a execução dessa lógica durante *inicialização* e durante *encerramento*. Existe uma forma alternativa de definir essa lógica para ser executada durante a *inicialização* e durante o *encerramento*.
Você pode definir manipuladores de eventos (funções) que precisam ser executadas antes da aplicação inicializar, ou quando a aplicação estiver encerrando. Você pode definir manipuladores de eventos (funções) que precisam ser executados antes de a aplicação iniciar ou quando a aplicação estiver encerrando.
Essas funções podem ser declaradas com `async def` ou `def` normal. Essas funções podem ser declaradas com `async def` ou `def` normal.
### Evento `startup` ### Evento `startup` { #startup-event }
Para adicionar uma função que deve rodar antes da aplicação iniciar, declare-a com o evento `"startup"`: Para adicionar uma função que deve rodar antes de a aplicação iniciar, declare-a com o evento `"startup"`:
{* ../../docs_src/events/tutorial001.py hl[8] *} {* ../../docs_src/events/tutorial001.py hl[8] *}
Nesse caso, a função de manipulação de evento `startup` irá inicializar os itens do "banco de dados" (só um `dict`) com alguns valores. Nesse caso, a função de manipulador do evento `startup` inicializará os itens do "banco de dados" (apenas um `dict`) com alguns valores.
Você pode adicionar mais que uma função de manipulação de evento. Você pode adicionar mais de uma função de manipulador de eventos.
E sua aplicação não irá começar a receber requisições até que todos os manipuladores de eventos de `startup` sejam concluídos. E sua aplicação não começará a receber requisições até que todos os manipuladores de eventos `startup` sejam concluídos.
### Evento `shutdown` ### Evento `shutdown` { #shutdown-event }
Para adicionar uma função que deve ser executada quando a aplicação estiver encerrando, declare ela com o evento `"shutdown"`: Para adicionar uma função que deve ser executada quando a aplicação estiver encerrando, declare-a com o evento `"shutdown"`:
{* ../../docs_src/events/tutorial002.py hl[6] *} {* ../../docs_src/events/tutorial002.py hl[6] *}
Aqui, a função de manipulação de evento `shutdown` irá escrever uma linha de texto `"Application shutdown"` no arquivo `log.txt`. Aqui, a função de manipulador do evento `shutdown` escreverá uma linha de texto `"Application shutdown"` no arquivo `log.txt`.
/// info | Informação /// info | Informação
Na função `open()`, o `mode="a"` significa "acrescentar", então, a linha irá ser adicionada depois de qualquer coisa que esteja naquele arquivo, sem sobrescrever o conteúdo anterior. Na função `open()`, o `mode="a"` significa "acrescentar", então a linha será adicionada depois do que já estiver naquele arquivo, sem sobrescrever o conteúdo anterior.
/// ///
/// tip | Dica /// tip | Dica
Perceba que nesse caso nós estamos usando a função padrão do Python `open()` que interage com um arquivo. Perceba que, nesse caso, estamos usando a função padrão do Python `open()` que interage com um arquivo.
Então, isso envolve I/O (input/output), que exige "esperar" que coisas sejam escritas em disco. Então, isso envolve I/O (input/output), que requer "esperar" que as coisas sejam escritas em disco.
Mas `open()` não usa `async` e `await`. Mas `open()` não usa `async` e `await`.
Então, nós declaramos uma função de manipulação de evento com o padrão `def` ao invés de `async def`. Assim, declaramos a função de manipulador de evento com `def` padrão em vez de `async def`.
/// ///
### `startup` e `shutdown` juntos ### `startup` e `shutdown` juntos { #startup-and-shutdown-together }
Há uma grande chance que a lógica para sua *inicialização* e *encerramento* esteja conectada, você pode querer iniciar alguma coisa e então finalizá-la, adquirir um recurso e então liberá-lo, etc. Há uma grande chance de que a lógica para sua *inicialização* e *encerramento* esteja conectada, você pode querer iniciar alguma coisa e então finalizá-la, adquirir um recurso e então liberá-lo, etc.
Fazendo isso em funções separadas que não compartilham lógica ou variáveis entre elas é mais difícil já que você precisa armazenar os valores em variáveis globais ou truques parecidos. Fazer isso em funções separadas que não compartilham lógica ou variáveis entre si é mais difícil, pois você precisaria armazenar valores em variáveis globais ou truques semelhantes.
Por causa disso, agora é recomendado em vez disso usar o `lifespan` como explicado acima. Por causa disso, agora é recomendado usar o `lifespan`, como explicado acima.
## Detalhes técnicos ## Detalhes técnicos { #technical-details }
um detalhe técnico para nerds curiosos. 🤓 Apenas um detalhe técnico para nerds curiosos. 🤓
Por baixo, na especificação técnica ASGI, essa é a parte do <a href="https://asgi.readthedocs.io/en/latest/specs/lifespan.html" class="external-link" target="_blank">Protocolo Lifespan</a>, e define eventos chamados `startup` e `shutdown`. Por baixo, na especificação técnica do ASGI, isso é parte do <a href="https://asgi.readthedocs.io/en/latest/specs/lifespan.html" class="external-link" target="_blank">Protocolo Lifespan</a>, e define eventos chamados `startup` e `shutdown`.
/// info | Informação /// info | Informação
Você pode ler mais sobre o manipulador `lifespan` do Starlette na <a href="https://www.starlette.dev/lifespan/" class="external-link" target="_blank">Documentação do Lifespan Starlette</a>. Você pode ler mais sobre os manipuladores de `lifespan` do Starlette na <a href="https://www.starlette.dev/lifespan/" class="external-link" target="_blank">Documentação do Lifespan do Starlette</a>.
Incluindo como manipular estado do lifespan que pode ser usado em outras áreas do seu código. Incluindo como lidar com estado do lifespan que pode ser usado em outras áreas do seu código.
/// ///
## Sub Aplicações ## Sub Aplicações { #sub-applications }
🚨 Tenha em mente que esses eventos de lifespan (de inicialização e desligamento) irão somente ser executados para a aplicação principal, não para [Sub Aplicações - Montagem](sub-applications.md){.internal-link target=_blank}. 🚨 Tenha em mente que esses eventos de lifespan (inicialização e encerramento) serão executados apenas para a aplicação principal, não para [Sub Aplicações - Montagem](sub-applications.md){.internal-link target=_blank}.

View File

@ -1,115 +1,76 @@
# Generate Clients # Gerando SDKs { #generating-sdks }
Como o **FastAPI** é baseado na especificação **OpenAPI**, você obtém compatibilidade automática com muitas ferramentas, incluindo a documentação automática da API (fornecida pelo Swagger UI). Como o **FastAPI** é baseado na especificação **OpenAPI**, suas APIs podem ser descritas em um formato padrão que muitas ferramentas entendem.
Uma vantagem particular que nem sempre é óbvia é que você pode **gerar clientes** (às vezes chamados de <abbr title="Software Development Kits">**SDKs**</abbr>) para a sua API, para muitas **linguagens de programação** diferentes. Isso facilita gerar **documentação** atualizada, bibliotecas clientes (<abbr title="Software Development Kits Kits de Desenvolvimento de Software">**SDKs**</abbr>) em várias linguagens e **testes** ou **fluxos de trabalho de automação** que permanecem em sincronia com o seu código.
## Geradores de Clientes OpenAPI Neste guia, você aprenderá como gerar um **SDK em TypeScript** para o seu backend FastAPI.
Existem muitas ferramentas para gerar clientes a partir do **OpenAPI**. ## Geradores de SDK de código aberto { #open-source-sdk-generators }
Uma ferramenta comum é o <a href="https://openapi-generator.tech/" class="external-link" target="_blank">OpenAPI Generator</a>. Uma opção versátil é o <a href="https://openapi-generator.tech/" class="external-link" target="_blank">OpenAPI Generator</a>, que suporta **muitas linguagens de programação** e pode gerar SDKs a partir da sua especificação OpenAPI.
Se voce está construindo um **frontend**, uma alternativa muito interessante é o <a href="https://github.com/hey-api/openapi-ts" class="external-link" target="_blank">openapi-ts</a>. Para **clientes TypeScript**, o <a href="https://heyapi.dev/" class="external-link" target="_blank">Hey API</a> é uma solução feita sob medida, oferecendo uma experiência otimizada para o ecossistema TypeScript.
## Geradores de Clientes e SDKs - Patrocinadores Você pode descobrir mais geradores de SDK em <a href="https://openapi.tools/#sdk" class="external-link" target="_blank">OpenAPI.Tools</a>.
Existem também alguns geradores de clientes e SDKs baseados na OpenAPI (FastAPI) **patrocinados por empresas**, em alguns casos eles podem oferecer **recursos adicionais** além de SDKs/clientes gerados de alta qualidade. /// tip | Dica
Alguns deles também ✨ [**patrocinam o FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, isso garante o **desenvolvimento** contínuo e saudável do FastAPI e seu **ecossistema**. O FastAPI gera automaticamente especificações **OpenAPI 3.1**, então qualquer ferramenta que você usar deve suportar essa versão.
E isso mostra o verdadeiro compromisso deles com o FastAPI e sua **comunidade** (você), pois eles não apenas querem fornecer um **bom serviço**, mas também querem garantir que você tenha um **framework bom e saudável**, o FastAPI. 🙇 ///
## Geradores de SDK dos patrocinadores do FastAPI { #sdk-generators-from-fastapi-sponsors }
Esta seção destaca soluções **financiadas por investimento** e **com suporte de empresas** que patrocinam o FastAPI. Esses produtos fornecem **funcionalidades adicionais** e **integrações** além de SDKs gerados com alta qualidade.
Ao ✨ [**patrocinar o FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, essas empresas ajudam a garantir que o framework e seu **ecossistema** continuem saudáveis e **sustentáveis**.
O patrocínio também demonstra um forte compromisso com a **comunidade** FastAPI (você), mostrando que elas se importam não apenas em oferecer um **ótimo serviço**, mas também em apoiar um **framework robusto e próspero**, o FastAPI. 🙇
Por exemplo, você pode querer experimentar: Por exemplo, você pode querer experimentar:
* <a href="https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship" class="external-link" target="_blank">Speakeasy</a> * <a href="https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship" class="external-link" target="_blank">Speakeasy</a>
* <a href="https://www.stainlessapi.com/?utm_source=fastapi&utm_medium=referral" class="external-link" target="_blank">Stainless</a> * <a href="https://www.stainless.com/?utm_source=fastapi&utm_medium=referral" class="external-link" target="_blank">Stainless</a>
* <a href="https://developers.liblab.com/tutorials/sdk-for-fastapi/?utm_source=fastapi" class="external-link" target="_blank">liblab</a> * <a href="https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi" class="external-link" target="_blank">liblab</a>
Existem também várias outras empresas que oferecem serviços semelhantes que você pode pesquisar e encontrar online. 🤓 Algumas dessas soluções também podem ser open source ou oferecer planos gratuitos, para que você possa testá-las sem compromisso financeiro. Outros geradores comerciais de SDK estão disponíveis e podem ser encontrados online. 🤓
## Gerar um Cliente Frontend TypeScript ## Crie um SDK em TypeScript { #create-a-typescript-sdk }
Vamos começar com um aplicativo **FastAPI** simples: Vamos começar com uma aplicação FastAPI simples:
{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *} {* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *}
Note que as *operações de rota* definem os modelos que usam para o corpo da requisição e o corpo da resposta, usando os modelos `Item` e `ResponseMessage`. Note que as *operações de rota* definem os modelos que usam para o corpo da requisição e o corpo da resposta, usando os modelos `Item` e `ResponseMessage`.
### Documentação da API ### Documentação da API { #api-docs }
Se você acessar a documentação da API, verá que ela tem os **schemas** para os dados a serem enviados nas requisições e recebidos nas respostas: Se você for para `/docs`, verá que ela tem os **schemas** para os dados a serem enviados nas requisições e recebidos nas respostas:
<img src="/img/tutorial/generate-clients/image01.png"> <img src="/img/tutorial/generate-clients/image01.png">
Você pode ver esses schemas porque eles foram declarados com os modelos no app. Você pode ver esses schemas porque eles foram declarados com os modelos no app.
Essas informações estão disponíveis no **OpenAPI schema** do app e são mostradas na documentação da API (pelo Swagger UI). Essas informações estão disponíveis no **schema OpenAPI** do app e são mostradas na documentação da API.
E essas mesmas informações dos modelos que estão incluídas no OpenAPI são o que pode ser usado para **gerar o código do cliente**. E essas mesmas informações dos modelos que estão incluídas no OpenAPI são o que pode ser usado para **gerar o código do cliente**.
### Gerar um Cliente TypeScript ### Hey API { #hey-api }
Agora que temos o app com os modelos, podemos gerar o código do cliente para o frontend. Depois que tivermos uma aplicação FastAPI com os modelos, podemos usar o Hey API para gerar um cliente TypeScript. A forma mais rápida é via npx.
#### Instalar o `openapi-ts` ```sh
npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client
Você pode instalar o `openapi-ts` no seu código frontend com:
<div class="termy">
```console
$ npm install @hey-api/openapi-ts --save-dev
---> 100%
``` ```
</div> Isso gerará um SDK TypeScript em `./src/client`.
#### Gerar o Código do Cliente Você pode aprender como <a href="https://heyapi.dev/openapi-ts/get-started" class="external-link" target="_blank">instalar `@hey-api/openapi-ts`</a> e ler sobre o <a href="https://heyapi.dev/openapi-ts/output" class="external-link" target="_blank">resultado gerado</a> no site deles.
Para gerar o código do cliente, você pode usar a aplicação de linha de comando `openapi-ts` que agora está instalada. ### Usando o SDK { #using-the-sdk }
Como ela está instalada no projeto local, você provavelmente não conseguiria chamar esse comando diretamente, mas você o colocaria no seu arquivo `package.json`. Agora você pode importar e usar o código do cliente. Poderia ser assim, observe que você obtém preenchimento automático para os métodos:
Poderia ser assim:
```JSON hl_lines="7"
{
"name": "frontend-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"generate-client": "openapi-ts --input http://localhost:8000/openapi.json --output ./src/client --client axios"
},
"author": "",
"license": "",
"devDependencies": {
"@hey-api/openapi-ts": "^0.27.38",
"typescript": "^4.6.2"
}
}
```
Depois de ter esse script NPM `generate-client` lá, você pode executá-lo com:
<div class="termy">
```console
$ npm run generate-client
frontend-app@1.0.0 generate-client /home/user/code/frontend-app
> openapi-ts --input http://localhost:8000/openapi.json --output ./src/client --client axios
```
</div>
Esse comando gerará o código em `./src/client` e usará o `axios` (a biblioteca HTTP frontend) internamente.
### Experimente o Código do Cliente
Agora você pode importar e usar o código do cliente, ele poderia ser assim, observe que você obtém preenchimento automático para os métodos:
<img src="/img/tutorial/generate-clients/image02.png"> <img src="/img/tutorial/generate-clients/image02.png">
@ -119,7 +80,7 @@ Você também obterá preenchimento automático para o corpo a ser enviado:
/// tip | Dica /// tip | Dica
Observe o preenchimento automático para `name` e `price`, que foi definido no aplicativo FastAPI, no modelo `Item`. Observe o preenchimento automático para `name` e `price`, que foi definido na aplicação FastAPI, no modelo `Item`.
/// ///
@ -131,17 +92,17 @@ O objeto de resposta também terá preenchimento automático:
<img src="/img/tutorial/generate-clients/image05.png"> <img src="/img/tutorial/generate-clients/image05.png">
## App FastAPI com Tags ## Aplicação FastAPI com Tags { #fastapi-app-with-tags }
Em muitos casos seu app FastAPI será maior, e você provavelmente usará tags para separar diferentes grupos de *operações de rota*. Em muitos casos, sua aplicação FastAPI será maior, e você provavelmente usará tags para separar diferentes grupos de *operações de rota*.
Por exemplo, você poderia ter uma seção para **items** e outra seção para **users**, e elas poderiam ser separadas por tags: Por exemplo, você poderia ter uma seção para **items** e outra seção para **users**, e elas poderiam ser separadas por tags:
{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *} {* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *}
### Gerar um Cliente TypeScript com Tags ### Gere um cliente TypeScript com Tags { #generate-a-typescript-client-with-tags }
Se você gerar um cliente para um app FastAPI usando tags, normalmente também separará o código do cliente com base nas tags. Se você gerar um cliente para uma aplicação FastAPI usando tags, normalmente também separará o código do cliente com base nas tags.
Dessa forma, você poderá ter as coisas ordenadas e agrupadas corretamente para o código do cliente: Dessa forma, você poderá ter as coisas ordenadas e agrupadas corretamente para o código do cliente:
@ -152,33 +113,33 @@ Nesse caso você tem:
* `ItemsService` * `ItemsService`
* `UsersService` * `UsersService`
### Nomes dos Métodos do Cliente ### Nomes dos métodos do cliente { #client-method-names }
Agora os nomes dos métodos gerados como `createItemItemsPost` não parecem muito "limpos": Agora os nomes dos métodos gerados como `createItemItemsPost` não parecem muito “limpos”:
```TypeScript ```TypeScript
ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) ItemsService.createItemItemsPost({name: "Plumbus", price: 5})
``` ```
...isto ocorre porque o gerador de clientes usa o **operation ID** interno do OpenAPI para cada *operação de rota*. ...isso ocorre porque o gerador de clientes usa o **ID de operação** interno do OpenAPI para cada *operação de rota*.
O OpenAPI exige que cada operation ID seja único em todas as *operações de rota*, então o FastAPI usa o **nome da função**, o **caminho** e o **método/operacao HTTP** para gerar esse operation ID, porque dessa forma ele pode garantir que os operation IDs sejam únicos. O OpenAPI exige que cada ID de operação seja único em todas as *operações de rota*, então o FastAPI usa o **nome da função**, o **path** e o **método/operação HTTP** para gerar esse ID de operação, porque dessa forma ele pode garantir que os IDs de operação sejam únicos.
Mas eu vou te mostrar como melhorar isso a seguir. 🤓 Mas eu vou te mostrar como melhorar isso a seguir. 🤓
### IDs de Operação Personalizados e Melhores Nomes de Método ## IDs de operação personalizados e nomes de métodos melhores { #custom-operation-ids-and-better-method-names }
Você pode **modificar** a maneira como esses IDs de operação são **gerados** para torná-los mais simples e ter **nomes de método mais simples** nos clientes. Você pode **modificar** a maneira como esses IDs de operação são **gerados** para torná-los mais simples e ter **nomes de método mais simples** nos clientes.
Neste caso, você terá que garantir que cada ID de operação seja **único** de alguma outra maneira. Neste caso, você terá que garantir que cada ID de operação seja **único** de alguma outra maneira.
Por exemplo, você poderia garantir que cada *operação de rota* tenha uma tag, e então gerar o ID da operação com base na **tag** e no **nome** da *operação de rota* (o nome da função). Por exemplo, você poderia garantir que cada *operação de rota* tenha uma tag, e então gerar o ID de operação com base na **tag** e no **nome** da *operação de rota* (o nome da função).
### Função Personalizada para Gerar IDs de Operação Únicos ### Função personalizada para gerar IDs exclusivos { #custom-generate-unique-id-function }
O FastAPI usa um **ID único** para cada *operação de rota*, ele é usado para o **ID da operação** e também para os nomes de quaisquer modelos personalizados necessários, para requisições ou respostas. O FastAPI usa um **ID exclusivo** para cada *operação de rota*, ele é usado para o **ID de operação** e também para os nomes de quaisquer modelos personalizados necessários, para requisições ou respostas.
Você pode personalizar essa função. Ela recebe uma `APIRoute` e gera uma string. Você pode personalizar essa função. Ela recebe uma `APIRoute` e retorna uma string.
Por exemplo, aqui está usando a primeira tag (você provavelmente terá apenas uma tag) e o nome da *operação de rota* (o nome da função). Por exemplo, aqui está usando a primeira tag (você provavelmente terá apenas uma tag) e o nome da *operação de rota* (o nome da função).
@ -186,15 +147,15 @@ Você pode então passar essa função personalizada para o **FastAPI** como o p
{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *} {* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *}
### Gerar um Cliente TypeScript com IDs de Operação Personalizados ### Gere um cliente TypeScript com IDs de operação personalizados { #generate-a-typescript-client-with-custom-operation-ids }
Agora, se você gerar o cliente novamente, verá que ele tem os nomes dos métodos melhorados: Agora, se você gerar o cliente novamente, verá que ele tem os nomes dos métodos melhorados:
<img src="/img/tutorial/generate-clients/image07.png"> <img src="/img/tutorial/generate-clients/image07.png">
Como você pode ver, os nomes dos métodos agora têm a tag e, em seguida, o nome da função. Agora eles não incluem informações do caminho da URL e da operação HTTP. Como você pode ver, os nomes dos métodos agora têm a tag e, em seguida, o nome da função. Agora eles não incluem informações do path da URL e da operação HTTP.
### Pré-processar a Especificação OpenAPI para o Gerador de Clientes ### Pré-processar a especificação OpenAPI para o gerador de clientes { #preprocess-the-openapi-specification-for-the-client-generator }
O código gerado ainda tem algumas **informações duplicadas**. O código gerado ainda tem algumas **informações duplicadas**.
@ -202,7 +163,7 @@ Nós já sabemos que esse método está relacionado aos **items** porque essa pa
Provavelmente ainda queremos mantê-lo para o OpenAPI em geral, pois isso garantirá que os IDs de operação sejam **únicos**. Provavelmente ainda queremos mantê-lo para o OpenAPI em geral, pois isso garantirá que os IDs de operação sejam **únicos**.
Mas para o cliente gerado, poderíamos **modificar** os IDs de operação do OpenAPI logo antes de gerar os clientes, apenas para tornar esses nomes de método mais **simples**. Mas para o cliente gerado, poderíamos **modificar** os IDs de operação do OpenAPI logo antes de gerar os clientes, apenas para tornar esses nomes de método mais agradáveis e **limpos**.
Poderíamos baixar o JSON do OpenAPI para um arquivo `openapi.json` e então poderíamos **remover essa tag prefixada** com um script como este: Poderíamos baixar o JSON do OpenAPI para um arquivo `openapi.json` e então poderíamos **remover essa tag prefixada** com um script como este:
@ -218,44 +179,30 @@ Poderíamos baixar o JSON do OpenAPI para um arquivo `openapi.json` e então pod
Com isso, os IDs de operação seriam renomeados de coisas como `items-get_items` para apenas `get_items`, dessa forma o gerador de clientes pode gerar nomes de métodos mais simples. Com isso, os IDs de operação seriam renomeados de coisas como `items-get_items` para apenas `get_items`, dessa forma o gerador de clientes pode gerar nomes de métodos mais simples.
### Gerar um Cliente TypeScript com o OpenAPI Pré-processado ### Gere um cliente TypeScript com o OpenAPI pré-processado { #generate-a-typescript-client-with-the-preprocessed-openapi }
Agora, como o resultado final está em um arquivo `openapi.json`, você modificaria o `package.json` para usar esse arquivo local, por exemplo: Como o resultado final está agora em um arquivo `openapi.json`, você precisa atualizar o local de entrada:
```JSON hl_lines="7" ```sh
{ npx @hey-api/openapi-ts -i ./openapi.json -o src/client
"name": "frontend-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"generate-client": "openapi-ts --input ./openapi.json --output ./src/client --client axios"
},
"author": "",
"license": "",
"devDependencies": {
"@hey-api/openapi-ts": "^0.27.38",
"typescript": "^4.6.2"
}
}
``` ```
Depois de gerar o novo cliente, você teria agora **nomes de métodos "limpos"**, com todo o **preenchimento automático**, **erros em linha**, etc: Depois de gerar o novo cliente, você terá agora **nomes de métodos “limpos”**, com todo o **preenchimento automático**, **erros em linha**, etc:
<img src="/img/tutorial/generate-clients/image08.png"> <img src="/img/tutorial/generate-clients/image08.png">
## Benefícios ## Benefícios { #benefits }
Ao usar os clientes gerados automaticamente, você teria **preenchimento automático** para: Ao usar os clientes gerados automaticamente, você terá **preenchimento automático** para:
* Métodos. * Métodos.
* Corpo de requisições, parâmetros da query, etc. * Corpos de requisições, parâmetros de query, etc.
* Corpo de respostas. * Corpos de respostas.
Você também teria **erros em linha** para tudo. Você também terá **erros em linha** para tudo.
E sempre que você atualizar o código do backend, e **regenerar** o frontend, ele teria quaisquer novas *operações de rota* disponíveis como métodos, as antigas removidas, e qualquer outra alteração seria refletida no código gerado. 🤓 E sempre que você atualizar o código do backend e **regenerar** o frontend, ele terá quaisquer novas *operações de rota* disponíveis como métodos, as antigas removidas, e qualquer outra alteração será refletida no código gerado. 🤓
Isso também significa que se algo mudar, será **refletido** no código do cliente automaticamente. E se você **construir** o cliente, ele dará erro se houver alguma **incompatibilidade** nos dados usados. Isso também significa que, se algo mudou, será **refletido** no código do cliente automaticamente. E se você **construir** o cliente, ele falhará caso haja qualquer **incompatibilidade** nos dados usados.
Então, você **detectaria vários erros** muito cedo no ciclo de desenvolvimento, em vez de ter que esperar que os erros apareçam para seus usuários finais em produção e então tentar depurar onde está o problema. ✨ Assim, você **detectará muitos erros** muito cedo no ciclo de desenvolvimento, em vez de ter que esperar que os erros apareçam para seus usuários finais em produção e então tentar depurar onde está o problema. ✨

View File

@ -1,10 +1,10 @@
# Guia de Usuário Avançado # Guia de Usuário Avançado { #advanced-user-guide }
## Recursos Adicionais ## Recursos Adicionais { #additional-features }
O [Tutorial - Guia de Usuário](../tutorial/index.md){.internal-link target=_blank} deve ser o suficiente para dar a você um tour por todos os principais recursos do **FastAPI**. O [Tutorial - Guia de Usuário](../tutorial/index.md){.internal-link target=_blank} deve ser o suficiente para dar a você um tour por todos os principais recursos do **FastAPI**.
Na próxima seção você verá outras opções, configurações, e recursos adicionais. Nas próximas seções você verá outras opções, configurações, e recursos adicionais.
/// tip | Dica /// tip | Dica
@ -14,14 +14,8 @@ E é possível que para seu caso de uso, a solução esteja em uma delas.
/// ///
## Leia o Tutorial primeiro ## Leia o Tutorial primeiro { #read-the-tutorial-first }
Você ainda pode usar a maior parte dos recursos no **FastAPI** com o conhecimento do [Tutorial - Guia de Usuário](../tutorial/index.md){.internal-link target=_blank}. Você ainda pode usar a maior parte dos recursos no **FastAPI** com o conhecimento do [Tutorial - Guia de Usuário](../tutorial/index.md){.internal-link target=_blank}.
E as próximas seções assumem que você já leu ele, e que você conhece suas ideias principais. E as próximas seções assumem que você já leu ele, e que você conhece suas ideias principais.
## Curso TestDriven.io
Se você gostaria de fazer um curso avançado-iniciante para complementar essa seção da documentação, você pode querer conferir: <a href="https://testdriven.io/courses/tdd-fastapi/" class="external-link" target="_blank">Test-Driven Development com FastAPI e Docker</a> por **TestDriven.io**.
Eles estão atualmente doando 10% de todos os lucros para o desenvolvimento do **FastAPI**. 🎉 😄

View File

@ -1,4 +1,4 @@
# Middleware Avançado # Middleware Avançado { #advanced-middleware }
No tutorial principal você leu como adicionar [Middleware Personalizado](../tutorial/middleware.md){.internal-link target=_blank} à sua aplicação. No tutorial principal você leu como adicionar [Middleware Personalizado](../tutorial/middleware.md){.internal-link target=_blank} à sua aplicação.
@ -6,9 +6,9 @@ E então você também leu como lidar com [CORS com o `CORSMiddleware`](../tutor
Nesta seção, veremos como usar outros middlewares. Nesta seção, veremos como usar outros middlewares.
## Adicionando middlewares ASGI ## Adicionando middlewares ASGI { #adding-asgi-middlewares }
Como o **FastAPI** é baseado no Starlette e implementa a especificação <abbr title="Asynchronous Server Gateway Interface">ASGI</abbr>, você pode usar qualquer middleware ASGI. Como o **FastAPI** é baseado no Starlette e implementa a especificação <abbr title="Asynchronous Server Gateway Interface Interface de Gateway de Servidor Assíncrona">ASGI</abbr>, você pode usar qualquer middleware ASGI.
O middleware não precisa ser feito para o FastAPI ou Starlette para funcionar, desde que siga a especificação ASGI. O middleware não precisa ser feito para o FastAPI ou Starlette para funcionar, desde que siga a especificação ASGI.
@ -39,19 +39,19 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow")
`app.add_middleware()` recebe uma classe de middleware como o primeiro argumento e quaisquer argumentos adicionais a serem passados para o middleware. `app.add_middleware()` recebe uma classe de middleware como o primeiro argumento e quaisquer argumentos adicionais a serem passados para o middleware.
## Middlewares Integrados ## Middlewares Integrados { #integrated-middlewares }
**FastAPI** inclui vários middlewares para casos de uso comuns, veremos a seguir como usá-los. **FastAPI** inclui vários middlewares para casos de uso comuns, veremos a seguir como usá-los.
/// note | Detalhes Técnicos /// note | Detalhes Técnicos
Para o próximo exemplo, você também poderia usar `from starlette.middleware.something import SomethingMiddleware`. Para os próximos exemplos, você também poderia usar `from starlette.middleware.something import SomethingMiddleware`.
**FastAPI** fornece vários middlewares em `fastapi.middleware` apenas como uma conveniência para você, o desenvolvedor. Mas a maioria dos middlewares disponíveis vem diretamente do Starlette. **FastAPI** fornece vários middlewares em `fastapi.middleware` apenas como uma conveniência para você, o desenvolvedor. Mas a maioria dos middlewares disponíveis vem diretamente do Starlette.
/// ///
## `HTTPSRedirectMiddleware` ## `HTTPSRedirectMiddleware` { #httpsredirectmiddleware }
Garante que todas as requisições devem ser `https` ou `wss`. Garante que todas as requisições devem ser `https` ou `wss`.
@ -59,7 +59,7 @@ Qualquer requisição para `http` ou `ws` será redirecionada para o esquema seg
{* ../../docs_src/advanced_middleware/tutorial001.py hl[2,6] *} {* ../../docs_src/advanced_middleware/tutorial001.py hl[2,6] *}
## `TrustedHostMiddleware` ## `TrustedHostMiddleware` { #trustedhostmiddleware }
Garante que todas as requisições recebidas tenham um cabeçalho `Host` corretamente configurado, a fim de proteger contra ataques de cabeçalho de host HTTP. Garante que todas as requisições recebidas tenham um cabeçalho `Host` corretamente configurado, a fim de proteger contra ataques de cabeçalho de host HTTP.
@ -68,10 +68,11 @@ Garante que todas as requisições recebidas tenham um cabeçalho `Host` correta
Os seguintes argumentos são suportados: Os seguintes argumentos são suportados:
* `allowed_hosts` - Uma lista de nomes de domínio que são permitidos como nomes de host. Domínios com coringa, como `*.example.com`, são suportados para corresponder a subdomínios. Para permitir qualquer nome de host, use `allowed_hosts=["*"]` ou omita o middleware. * `allowed_hosts` - Uma lista de nomes de domínio que são permitidos como nomes de host. Domínios com coringa, como `*.example.com`, são suportados para corresponder a subdomínios. Para permitir qualquer nome de host, use `allowed_hosts=["*"]` ou omita o middleware.
* `www_redirect` - Se definido como True, as requisições para versões sem www dos hosts permitidos serão redirecionadas para suas versões com www. O padrão é `True`.
Se uma requisição recebida não for validada corretamente, uma resposta `400` será enviada. Se uma requisição recebida não for validada corretamente, uma resposta `400` será enviada.
## `GZipMiddleware` ## `GZipMiddleware` { #gzipmiddleware }
Gerencia respostas GZip para qualquer requisição que inclua `"gzip"` no cabeçalho `Accept-Encoding`. Gerencia respostas GZip para qualquer requisição que inclua `"gzip"` no cabeçalho `Accept-Encoding`.
@ -84,7 +85,7 @@ Os seguintes argumentos são suportados:
* `minimum_size` - Não comprima respostas menores que este tamanho mínimo em bytes. O padrão é `500`. * `minimum_size` - Não comprima respostas menores que este tamanho mínimo em bytes. O padrão é `500`.
* `compresslevel` - Usado durante a compressão GZip. É um inteiro variando de 1 a 9. O padrão é `9`. Um valor menor resulta em uma compressão mais rápida, mas em arquivos maiores, enquanto um valor maior resulta em uma compressão mais lenta, mas em arquivos menores. * `compresslevel` - Usado durante a compressão GZip. É um inteiro variando de 1 a 9. O padrão é `9`. Um valor menor resulta em uma compressão mais rápida, mas em arquivos maiores, enquanto um valor maior resulta em uma compressão mais lenta, mas em arquivos menores.
## Outros middlewares ## Outros middlewares { #other-middlewares }
Há muitos outros middlewares ASGI. Há muitos outros middlewares ASGI.

View File

@ -1,29 +1,29 @@
# Callbacks na OpenAPI # Callbacks na OpenAPI { #openapi-callbacks }
Você poderia criar uma API com uma *operação de rota* que poderia acionar uma solicitação a uma *API externa* criada por outra pessoa (provavelmente o mesmo desenvolvedor que estaria *usando* sua API). Você poderia criar uma API com uma *operação de rota* que poderia acionar uma solicitação a uma *API externa* criada por outra pessoa (provavelmente o mesmo desenvolvedor que estaria *usando* sua API).
O processo que acontece quando seu aplicativo de API chama a *API externa* é chamado de "callback". Porque o software que o desenvolvedor externo escreveu envia uma solicitação para sua API e então sua API *chama de volta*, enviando uma solicitação para uma *API externa* (que provavelmente foi criada pelo mesmo desenvolvedor). O processo que acontece quando sua aplicação de API chama a *API externa* é chamado de "callback". Porque o software que o desenvolvedor externo escreveu envia uma solicitação para sua API e então sua API *chama de volta*, enviando uma solicitação para uma *API externa* (que provavelmente foi criada pelo mesmo desenvolvedor).
Nesse caso, você poderia querer documentar como essa API externa *deveria* ser. Que *operação de rota* ela deveria ter, que corpo ela deveria esperar, que resposta ela deveria retornar, etc. Nesse caso, você poderia querer documentar como essa API externa *deveria* ser. Que *operação de rota* ela deveria ter, que corpo ela deveria esperar, que resposta ela deveria retornar, etc.
## Um aplicativo com callbacks ## Um aplicativo com callbacks { #an-app-with-callbacks }
Vamos ver tudo isso com um exemplo. Vamos ver tudo isso com um exemplo.
Imagine que você tem um aplicativo que permite criar faturas. Imagine que você desenvolve um aplicativo que permite criar faturas.
Essas faturas terão um `id`, `title` (opcional), `customer` e `total`. Essas faturas terão um `id`, `title` (opcional), `customer` e `total`.
O usuário da sua API (um desenvolvedor externo) criará uma fatura em sua API com uma solicitação POST. O usuário da sua API (um desenvolvedor externo) criará uma fatura na sua API com uma solicitação POST.
Então sua API irá (vamos imaginar): Então sua API irá (vamos imaginar):
* Enviar uma solicitação de pagamento para o desenvolvedor externo. * Enviar a fatura para algum cliente do desenvolvedor externo.
* Coletar o dinheiro. * Coletar o dinheiro.
* Enviar a notificação de volta para o usuário da API (o desenvolvedor externo). * Enviar a notificação de volta para o usuário da API (o desenvolvedor externo).
* Isso será feito enviando uma solicitação POST (de *sua API*) para alguma *API externa* fornecida por esse desenvolvedor externo (este é o "callback"). * Isso será feito enviando uma solicitação POST (de *sua API*) para alguma *API externa* fornecida por esse desenvolvedor externo (este é o "callback").
## O aplicativo **FastAPI** normal ## O aplicativo **FastAPI** normal { #the-normal-fastapi-app }
Vamos primeiro ver como o aplicativo da API normal se pareceria antes de adicionar o callback. Vamos primeiro ver como o aplicativo da API normal se pareceria antes de adicionar o callback.
@ -39,11 +39,11 @@ O parâmetro de consulta `callback_url` usa um tipo Pydantic <a href="https://do
/// ///
A única coisa nova é o argumento `callbacks=invoices_callback_router.routes` no decorador da *operação de rota*. Veremos o que é isso a seguir. A única novidade é o `callbacks=invoices_callback_router.routes` como argumento do decorador da *operação de rota*. Veremos o que é isso a seguir.
## Documentando o callback ## Documentando o callback { #documenting-the-callback }
O código real do callback dependerá muito do seu próprio aplicativo de API. O código real do callback dependerá muito da sua própria aplicação de API.
E provavelmente variará muito de um aplicativo para o outro. E provavelmente variará muito de um aplicativo para o outro.
@ -58,7 +58,7 @@ Mas possivelmente a parte mais importante do callback é garantir que o usuário
Então, o que faremos a seguir é adicionar o código para documentar como essa *API externa* deve ser para receber o callback de *sua API*. Então, o que faremos a seguir é adicionar o código para documentar como essa *API externa* deve ser para receber o callback de *sua API*.
A documentação aparecerá na interface do Swagger em `/docs` em sua API, e permitirá que os desenvolvedores externos saibam como construir a *API externa*. A documentação aparecerá na Swagger UI em `/docs` na sua API, e permitirá que os desenvolvedores externos saibam como construir a *API externa*.
Esse exemplo não implementa o callback em si (que poderia ser apenas uma linha de código), apenas a parte da documentação. Esse exemplo não implementa o callback em si (que poderia ser apenas uma linha de código), apenas a parte da documentação.
@ -66,11 +66,11 @@ Esse exemplo não implementa o callback em si (que poderia ser apenas uma linha
O callback real é apenas uma solicitação HTTP. O callback real é apenas uma solicitação HTTP.
Quando implementando o callback por você mesmo, você pode usar algo como <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a> ou <a href="https://requests.readthedocs.io/" class="external-link" target="_blank">Requisições</a>. Ao implementar o callback por conta própria, você pode usar algo como <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a> ou <a href="https://requests.readthedocs.io/" class="external-link" target="_blank">Requests</a>.
/// ///
## Escrevendo o código de documentação do callback ## Escreva o código de documentação do callback { #write-the-callback-documentation-code }
Esse código não será executado em seu aplicativo, nós só precisamos dele para *documentar* como essa *API externa* deveria ser. Esse código não será executado em seu aplicativo, nós só precisamos dele para *documentar* como essa *API externa* deveria ser.
@ -80,37 +80,37 @@ Então vamos usar esse mesmo conhecimento para documentar como a *API externa* d
/// tip | Dica /// tip | Dica
Quando escrever o código para documentar um callback, pode ser útil imaginar que você é aquele *desenvolvedor externo*. E que você está atualmente implementando a *API externa*, não *sua API*. Ao escrever o código para documentar um callback, pode ser útil imaginar que você é aquele *desenvolvedor externo*. E que você está atualmente implementando a *API externa*, não *sua API*.
Adotar temporariamente esse ponto de vista (do *desenvolvedor externo*) pode ajudar a sentir que é mais óbvio onde colocar os parâmetros, o modelo Pydantic para o corpo, para a resposta, etc. para essa *API externa*. Adotar temporariamente esse ponto de vista (do *desenvolvedor externo*) pode ajudar a perceber mais facilmente onde colocar os parâmetros, o modelo Pydantic para o corpo, para a resposta, etc. para essa *API externa*.
/// ///
### Criar um `APIRouter` para o callback ### Crie um `APIRouter` de callback { #create-a-callback-apirouter }
Primeiramente crie um novo `APIRouter` que conterá um ou mais callbacks. Primeiro crie um novo `APIRouter` que conterá um ou mais callbacks.
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[3,25] *} {* ../../docs_src/openapi_callbacks/tutorial001.py hl[3,25] *}
### Crie a *operação de rota* do callback ### Crie a *operação de rota* do callback { #create-the-callback-path-operation }
Para criar a *operação de rota* do callback, use o mesmo `APIRouter` que você criou acima. Para criar a *operação de rota* do callback, use o mesmo `APIRouter` que você criou acima.
Ele deve parecer exatamente como uma *operação de rota* normal do FastAPI: Ela deve parecer exatamente como uma *operação de rota* normal do FastAPI:
* Ele provavelmente deveria ter uma declaração do corpo que deveria receber, por exemplo. `body: InvoiceEvent`. * Ela provavelmente deveria ter uma declaração do corpo que deveria receber, por exemplo, `body: InvoiceEvent`.
* E também deveria ter uma declaração de um código de status de resposta, por exemplo. `response_model=InvoiceEventReceived`. * E também poderia ter uma declaração da resposta que deveria retornar, por exemplo, `response_model=InvoiceEventReceived`.
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[16:18,21:22,28:32] *} {* ../../docs_src/openapi_callbacks/tutorial001.py hl[16:18,21:22,28:32] *}
Há 2 diferenças principais de uma *operação de rota* normal: Há 2 diferenças principais de uma *operação de rota* normal:
* Ela não necessita ter nenhum código real, porque seu aplicativo nunca chamará esse código. Ele é usado apenas para documentar a *API externa*. Então, a função poderia ter apenas `pass`. * Ela não necessita ter nenhum código real, porque seu aplicativo nunca chamará esse código. Ele é usado apenas para documentar a *API externa*. Então, a função poderia ter apenas `pass`.
* A *rota* pode conter uma <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">expressão OpenAPI 3</a> (veja mais abaixo) onde pode usar variáveis com parâmetros e partes da solicitação original enviada para *sua API*. * O *path* pode conter uma <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">expressão OpenAPI 3</a> (veja mais abaixo) em que pode usar variáveis com parâmetros e partes da solicitação original enviada para *sua API*.
### A expressão do caminho do callback ### A expressão do path do callback { #the-callback-path-expression }
A *rota* do callback pode ter uma <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">expressão OpenAPI 3</a> que pode conter partes da solicitação original enviada para *sua API*. O *path* do callback pode ter uma <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">expressão OpenAPI 3</a> que pode conter partes da solicitação original enviada para *sua API*.
Nesse caso, é a `str`: Nesse caso, é a `str`:
@ -163,11 +163,11 @@ Perceba como a URL de callback usada contém a URL recebida como um parâmetro d
/// ///
### Adicionar o roteador de callback ### Adicione o roteador de callback { #add-the-callback-router }
Nesse ponto você tem a(s) *operação de rota de callback* necessária(s) (a(s) que o *desenvolvedor externo* deveria implementar na *API externa*) no roteador de callback que você criou acima. Nesse ponto você tem a(s) *operação(ões) de rota de callback* necessária(s) (a(s) que o *desenvolvedor externo* deveria implementar na *API externa*) no roteador de callback que você criou acima.
Agora use o parâmetro `callbacks` no decorador da *operação de rota de sua API* para passar o atributo `.routes` (que é na verdade apenas uma `list` de rotas/*operações de rota*) do roteador de callback que você criou acima: Agora use o parâmetro `callbacks` no decorador da *operação de rota da sua API* para passar o atributo `.routes` (que é na verdade apenas uma `list` de rotas/*operações de path*) do roteador de callback:
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[35] *} {* ../../docs_src/openapi_callbacks/tutorial001.py hl[35] *}
@ -177,7 +177,7 @@ Perceba que você não está passando o roteador em si (`invoices_callback_route
/// ///
### Verifique a documentação ### Verifique a documentação { #check-the-docs }
Agora você pode iniciar seu aplicativo e ir para <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>. Agora você pode iniciar seu aplicativo e ir para <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.

View File

@ -1,4 +1,4 @@
# Webhooks OpenAPI # Webhooks OpenAPI { #openapi-webhooks }
Existem situações onde você deseja informar os **usuários** da sua API que a sua aplicação pode chamar a aplicação *deles* (enviando uma requisição) com alguns dados, normalmente para **notificar** algum tipo de **evento**. Existem situações onde você deseja informar os **usuários** da sua API que a sua aplicação pode chamar a aplicação *deles* (enviando uma requisição) com alguns dados, normalmente para **notificar** algum tipo de **evento**.
@ -6,7 +6,7 @@ Isso significa que no lugar do processo normal de seus usuários enviarem requis
Isso normalmente é chamado de **webhook**. Isso normalmente é chamado de **webhook**.
## Etapas dos Webhooks ## Etapas dos webhooks { #webhooks-steps }
Normalmente, o processo é que **você define** em seu código qual é a mensagem que você irá mandar, o **corpo da sua requisição**. Normalmente, o processo é que **você define** em seu código qual é a mensagem que você irá mandar, o **corpo da sua requisição**.
@ -16,7 +16,7 @@ E os **seus usuários** definem de alguma forma (em algum painel por exemplo) a
Toda a **lógica** sobre como cadastrar as URLs para os webhooks e o código para enviar de fato as requisições cabe a você definir. Você escreve da maneira que você desejar no **seu próprio código**. Toda a **lógica** sobre como cadastrar as URLs para os webhooks e o código para enviar de fato as requisições cabe a você definir. Você escreve da maneira que você desejar no **seu próprio código**.
## Documentando webhooks com o FastAPI e OpenAPI ## Documentando webhooks com o FastAPI e OpenAPI { #documenting-webhooks-with-fastapi-and-openapi }
Com o **FastAPI**, utilizando o OpenAPI, você pode definir os nomes destes webhooks, os tipos das operações HTTP que a sua aplicação pode enviar (e.g. `POST`, `PUT`, etc.) e os **corpos** da requisição que a sua aplicação enviaria. Com o **FastAPI**, utilizando o OpenAPI, você pode definir os nomes destes webhooks, os tipos das operações HTTP que a sua aplicação pode enviar (e.g. `POST`, `PUT`, etc.) e os **corpos** da requisição que a sua aplicação enviaria.
@ -28,7 +28,7 @@ Webhooks estão disponíveis a partir do OpenAPI 3.1.0, e possui suporte do Fast
/// ///
## Uma aplicação com webhooks ## Uma aplicação com webhooks { #an-app-with-webhooks }
Quando você cria uma aplicação com o **FastAPI**, existe um atributo chamado `webhooks`, que você utilizar para defini-los da mesma maneira que você definiria as suas **operações de rotas**, utilizando por exemplo `@app.webhooks.post()`. Quando você cria uma aplicação com o **FastAPI**, existe um atributo chamado `webhooks`, que você utilizar para defini-los da mesma maneira que você definiria as suas **operações de rotas**, utilizando por exemplo `@app.webhooks.post()`.
@ -42,11 +42,11 @@ O objeto `app.webhooks` é na verdade apenas um `APIRouter`, o mesmo tipo que vo
/// ///
Note que utilizando webhooks você não está de fato declarando uma **rota** (como `/items/`), o texto que informa é apenas um **identificador** do webhook (o nome do evento), por exemplo em `@app.webhooks.post("new-subscription")`, o nome do webhook é `new-subscription`. Note que utilizando webhooks você não está de fato declarando um *path* (como `/items/`), o texto que informa é apenas um **identificador** do webhook (o nome do evento), por exemplo em `@app.webhooks.post("new-subscription")`, o nome do webhook é `new-subscription`.
Isto porque espera-se que os **seus usuários** definam o verdadeiro **caminho da URL** onde eles desejam receber a requisição do webhook de algum outra maneira. (e.g. um painel). Isto porque espera-se que os **seus usuários** definam o verdadeiro **URL path** onde eles desejam receber a requisição do webhook de algum outra maneira. (e.g. um painel).
### Confira a documentação ### Confira a documentação { #check-the-docs }
Agora você pode iniciar a sua aplicação e ir até <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>. Agora você pode iniciar a sua aplicação e ir até <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.

View File

@ -1,8 +1,8 @@
# Configuração Avançada da Operação de Rota # Configuração Avançada da Operação de Rota { #path-operation-advanced-configuration }
## operationId do OpenAPI ## operationId do OpenAPI { #openapi-operationid }
/// warning | Aviso /// warning | Atenção
Se você não é um "especialista" no OpenAPI, você provavelmente não precisa disso. Se você não é um "especialista" no OpenAPI, você provavelmente não precisa disso.
@ -14,13 +14,13 @@ Você precisa ter certeza que ele é único para cada operação.
{* ../../docs_src/path_operation_advanced_configuration/tutorial001.py hl[6] *} {* ../../docs_src/path_operation_advanced_configuration/tutorial001.py hl[6] *}
### Utilizando o nome da *função de operação de rota* como o operationId ### Utilizando o nome da *função de operação de rota* como o operationId { #using-the-path-operation-function-name-as-the-operationid }
Se você quiser utilizar o nome das funções da sua API como `operationId`s, você pode iterar sobre todos esses nomes e sobrescrever o `operationId` em cada *operação de rota* utilizando o `APIRoute.name` dela. Se você quiser utilizar o nome das funções da sua API como `operationId`s, você pode iterar sobre todos esses nomes e sobrescrever o `operationId` em cada *operação de rota* utilizando o `APIRoute.name` dela.
Você deve fazer isso depois de adicionar todas as suas *operações de rota*. Você deve fazer isso depois de adicionar todas as suas *operações de rota*.
{* ../../docs_src/path_operation_advanced_configuration/tutorial002.py hl[2,12:21,24] *} {* ../../docs_src/path_operation_advanced_configuration/tutorial002.py hl[2, 12:21, 24] *}
/// tip | Dica /// tip | Dica
@ -28,7 +28,7 @@ Se você chamar `app.openapi()` manualmente, os `operationId`s devem ser atualiz
/// ///
/// warning | Aviso /// warning | Atenção
Se você fizer isso, você tem que ter certeza de que cada uma das suas *funções de operação de rota* tem um nome único. Se você fizer isso, você tem que ter certeza de que cada uma das suas *funções de operação de rota* tem um nome único.
@ -36,13 +36,13 @@ Mesmo que elas estejam em módulos (arquivos Python) diferentes.
/// ///
## Excluir do OpenAPI ## Excluir do OpenAPI { #exclude-from-openapi }
Para excluir uma *operação de rota* do esquema OpenAPI gerado (e por consequência, dos sistemas de documentação automáticos), utilize o parâmetro `include_in_schema` e defina ele como `False`: Para excluir uma *operação de rota* do esquema OpenAPI gerado (e por consequência, dos sistemas de documentação automáticos), utilize o parâmetro `include_in_schema` e defina ele como `False`:
{* ../../docs_src/path_operation_advanced_configuration/tutorial003.py hl[6] *} {* ../../docs_src/path_operation_advanced_configuration/tutorial003.py hl[6] *}
## Descrição avançada a partir de docstring ## Descrição avançada a partir de docstring { #advanced-description-from-docstring }
Você pode limitar as linhas utilizadas a partir de uma docstring de uma *função de operação de rota* para o OpenAPI. Você pode limitar as linhas utilizadas a partir de uma docstring de uma *função de operação de rota* para o OpenAPI.
@ -52,7 +52,7 @@ Ele não será mostrado na documentação, mas outras ferramentas (como o Sphinx
{* ../../docs_src/path_operation_advanced_configuration/tutorial004.py hl[19:29] *} {* ../../docs_src/path_operation_advanced_configuration/tutorial004.py hl[19:29] *}
## Respostas Adicionais ## Respostas Adicionais { #additional-responses }
Você provavelmente já viu como declarar o `response_model` e `status_code` para uma *operação de rota*. Você provavelmente já viu como declarar o `response_model` e `status_code` para uma *operação de rota*.
@ -62,11 +62,11 @@ Você também pode declarar respostas adicionais, com seus modelos, códigos de
Existe um capítulo inteiro da nossa documentação sobre isso, você pode ler em [Retornos Adicionais no OpenAPI](additional-responses.md){.internal-link target=_blank}. Existe um capítulo inteiro da nossa documentação sobre isso, você pode ler em [Retornos Adicionais no OpenAPI](additional-responses.md){.internal-link target=_blank}.
## Extras do OpenAPI ## Extras do OpenAPI { #openapi-extra }
Quando você declara uma *operação de rota* na sua aplicação, o **FastAPI** irá gerar os metadados relevantes da *operação de rota* automaticamente para serem incluídos no esquema do OpenAPI. Quando você declara uma *operação de rota* na sua aplicação, o **FastAPI** irá gerar os metadados relevantes da *operação de rota* automaticamente para serem incluídos no esquema do OpenAPI.
/// note | Nota /// note | Detalhes Técnicos
Na especificação do OpenAPI, isso é chamado de um <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object" class="external-link" target="_blank">Objeto de Operação</a>. Na especificação do OpenAPI, isso é chamado de um <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object" class="external-link" target="_blank">Objeto de Operação</a>.
@ -88,7 +88,7 @@ Caso você só precise declarar respostas adicionais, uma forma conveniente de f
Você pode estender o esquema do OpenAPI para uma *operação de rota* utilizando o parâmetro `openapi_extra`. Você pode estender o esquema do OpenAPI para uma *operação de rota* utilizando o parâmetro `openapi_extra`.
### Extensões do OpenAPI ### Extensões do OpenAPI { #openapi-extensions }
Esse parâmetro `openapi_extra` pode ser útil, por exemplo, para declarar [Extensões do OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions): Esse parâmetro `openapi_extra` pode ser útil, por exemplo, para declarar [Extensões do OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions):
@ -129,7 +129,7 @@ E se você olhar o esquema OpenAPI resultante (na rota `/openapi.json` da sua AP
} }
``` ```
### Esquema de *operação de rota* do OpenAPI personalizado ### Esquema de *operação de rota* do OpenAPI personalizado { #custom-openapi-path-operation-schema }
O dicionário em `openapi_extra` vai ter todos os seus níveis mesclados dentro do esquema OpenAPI gerado automaticamente para a *operação de rota*. O dicionário em `openapi_extra` vai ter todos os seus níveis mesclados dentro do esquema OpenAPI gerado automaticamente para a *operação de rota*.
@ -139,39 +139,39 @@ Por exemplo, você poderia optar por ler e validar a requisição com seu própr
Você pode fazer isso com `openapi_extra`: Você pode fazer isso com `openapi_extra`:
{* ../../docs_src/path_operation_advanced_configuration/tutorial006.py hl[19:36,39:40] *} {* ../../docs_src/path_operation_advanced_configuration/tutorial006.py hl[19:36, 39:40] *}
Nesse exemplo, nós não declaramos nenhum modelo do Pydantic. Na verdade, o corpo da requisição não está nem mesmo <abbr title="convertido de um formato plano, como bytes, para objetos Python">analisado</abbr> como JSON, ele é lido diretamente como `bytes` e a função `magic_data_reader()` seria a responsável por analisar ele de alguma forma. Nesse exemplo, nós não declaramos nenhum modelo do Pydantic. Na verdade, o corpo da requisição não está nem mesmo <abbr title="convertido de um formato plano, como bytes, para objetos Python">analisado</abbr> como JSON, ele é lido diretamente como `bytes` e a função `magic_data_reader()` seria a responsável por analisar ele de alguma forma.
De toda forma, nós podemos declarar o esquema esperado para o corpo da requisição. De toda forma, nós podemos declarar o esquema esperado para o corpo da requisição.
### Tipo de conteúdo do OpenAPI personalizado ### Tipo de conteúdo do OpenAPI personalizado { #custom-openapi-content-type }
Utilizando esse mesmo truque, você pode utilizar um modelo Pydantic para definir o esquema JSON que é então incluído na seção do esquema personalizado do OpenAPI na *operação de rota*. Utilizando esse mesmo truque, você pode utilizar um modelo Pydantic para definir o JSON Schema que é então incluído na seção do esquema personalizado do OpenAPI na *operação de rota*.
E você pode fazer isso até mesmo quando os dados da requisição não seguem o formato JSON. E você pode fazer isso até mesmo quando os dados da requisição não seguem o formato JSON.
Por exemplo, nesta aplicação nós não usamos a funcionalidade integrada ao FastAPI de extrair o esquema JSON dos modelos Pydantic nem a validação automática do JSON. Na verdade, estamos declarando o tipo do conteúdo da requisição como YAML, em vez de JSON: Por exemplo, nesta aplicação nós não usamos a funcionalidade integrada ao FastAPI de extrair o JSON Schema dos modelos Pydantic nem a validação automática do JSON. Na verdade, estamos declarando o tipo do conteúdo da requisição como YAML, em vez de JSON:
//// tab | Pydantic v2 //// tab | Pydantic v2
{* ../../docs_src/path_operation_advanced_configuration/tutorial007.py hl[17:22,24] *} {* ../../docs_src/path_operation_advanced_configuration/tutorial007.py hl[17:22, 24] *}
//// ////
//// tab | Pydantic v1 //// tab | Pydantic v1
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py hl[17:22,24] *} {* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py hl[17:22, 24] *}
//// ////
/// info | Informação /// info | Informação
Na versão 1 do Pydantic, o método para obter o esquema JSON de um modelo é `Item.schema()`, na versão 2 do Pydantic, o método é `Item.model_json_schema()` Na versão 1 do Pydantic, o método para obter o JSON Schema de um modelo é `Item.schema()`, na versão 2 do Pydantic, o método é `Item.model_json_schema()`.
/// ///
Entretanto, mesmo que não utilizemos a funcionalidade integrada por padrão, ainda estamos usando um modelo Pydantic para gerar um esquema JSON manualmente para os dados que queremos receber no formato YAML. Entretanto, mesmo que não utilizemos a funcionalidade integrada por padrão, ainda estamos usando um modelo Pydantic para gerar um JSON Schema manualmente para os dados que queremos receber no formato YAML.
Então utilizamos a requisição diretamente, e extraímos o corpo como `bytes`. Isso significa que o FastAPI não vai sequer tentar analisar o corpo da requisição como JSON. Então utilizamos a requisição diretamente, e extraímos o corpo como `bytes`. Isso significa que o FastAPI não vai sequer tentar analisar o corpo da requisição como JSON.
@ -195,7 +195,7 @@ Na versão 1 do Pydantic, o método para analisar e validar um objeto era `Item.
/// ///
///tip | Dica /// tip | Dica
Aqui reutilizamos o mesmo modelo do Pydantic. Aqui reutilizamos o mesmo modelo do Pydantic.

View File

@ -1,10 +1,10 @@
# Retorno - Altere o Código de Status # Retorno - Altere o Código de Status { #response-change-status-code }
Você provavelmente leu anteriormente que você pode definir um [Código de Status do Retorno](../tutorial/response-status-code.md){.internal-link target=_blank} padrão. Você provavelmente leu anteriormente que você pode definir um [Código de Status do Retorno](../tutorial/response-status-code.md){.internal-link target=_blank} padrão.
Porém em alguns casos você precisa retornar um código de status diferente do padrão. Porém em alguns casos você precisa retornar um código de status diferente do padrão.
## Caso de uso ## Caso de uso { #use-case }
Por exemplo, imagine que você deseja retornar um código de status HTTP de "OK" `200` por padrão. Por exemplo, imagine que você deseja retornar um código de status HTTP de "OK" `200` por padrão.
@ -14,7 +14,7 @@ Mas você ainda quer ser capaz de filtrar e converter o dado que você retornar
Para estes casos, você pode utilizar um parâmetro `Response`. Para estes casos, você pode utilizar um parâmetro `Response`.
## Use um parâmetro `Response` ## Use um parâmetro `Response` { #use-a-response-parameter }
Você pode declarar um parâmetro do tipo `Response` em sua *função de operação de rota* (assim como você pode fazer para cookies e headers). Você pode declarar um parâmetro do tipo `Response` em sua *função de operação de rota* (assim como você pode fazer para cookies e headers).

View File

@ -1,12 +1,12 @@
# Cookies de Resposta # Cookies de Resposta { #response-cookies }
## Usando um parâmetro `Response` ## Use um parâmetro `Response` { #use-a-response-parameter }
Você pode declarar um parâmetro do tipo `Response` na sua *função de operação de rota*. Você pode declarar um parâmetro do tipo `Response` na sua *função de operação de rota*.
E então você pode definir cookies nesse objeto de resposta *temporário*. E então você pode definir cookies nesse objeto de resposta *temporário*.
{* ../../docs_src/response_cookies/tutorial002.py hl[1,8:9] *} {* ../../docs_src/response_cookies/tutorial002.py hl[1, 8:9] *}
Em seguida, você pode retornar qualquer objeto que precise, como normalmente faria (um `dict`, um modelo de banco de dados, etc). Em seguida, você pode retornar qualquer objeto que precise, como normalmente faria (um `dict`, um modelo de banco de dados, etc).
@ -16,11 +16,11 @@ E se você declarou um `response_model`, ele ainda será usado para filtrar e co
Você também pode declarar o parâmetro `Response` em dependências e definir cookies (e cabeçalhos) nelas. Você também pode declarar o parâmetro `Response` em dependências e definir cookies (e cabeçalhos) nelas.
## Retornando uma `Response` diretamente ## Retorne uma `Response` diretamente { #return-a-response-directly }
Você também pode criar cookies ao retornar uma `Response` diretamente no seu código. Você também pode criar cookies ao retornar uma `Response` diretamente no seu código.
Para fazer isso, você pode criar uma resposta como descrito em [Retornando uma Resposta Diretamente](response-directly.md){.internal-link target=_blank}. Para fazer isso, você pode criar uma resposta como descrito em [Retorne uma Resposta Diretamente](response-directly.md){.internal-link target=_blank}.
Então, defina os cookies nela e a retorne: Então, defina os cookies nela e a retorne:
@ -36,7 +36,7 @@ E também que você não esteja enviando nenhum dado que deveria ter sido filtra
/// ///
### Mais informações ### Mais informações { #more-info }
/// note | Detalhes Técnicos /// note | Detalhes Técnicos

View File

@ -1,4 +1,4 @@
# Retornando uma Resposta Diretamente # Retornando uma Resposta Diretamente { #return-a-response-directly }
Quando você cria uma *operação de rota* no **FastAPI** você pode retornar qualquer dado nela: um dicionário (`dict`), uma lista (`list`), um modelo do Pydantic ou do seu banco de dados, etc. Quando você cria uma *operação de rota* no **FastAPI** você pode retornar qualquer dado nela: um dicionário (`dict`), uma lista (`list`), um modelo do Pydantic ou do seu banco de dados, etc.
@ -10,7 +10,7 @@ Mas você pode retornar a `JSONResponse` diretamente nas suas *operações de ro
Pode ser útil para retornar cabeçalhos e cookies personalizados, por exemplo. Pode ser útil para retornar cabeçalhos e cookies personalizados, por exemplo.
## Retornando uma `Response` ## Retornando uma `Response` { #return-a-response }
Na verdade, você pode retornar qualquer `Response` ou subclasse dela. Na verdade, você pode retornar qualquer `Response` ou subclasse dela.
@ -26,7 +26,7 @@ Ele não vai fazer conversões de dados com modelos do Pydantic, não irá conve
Isso te dá bastante flexibilidade. Você pode retornar qualquer tipo de dado, sobrescrever qualquer declaração e validação nos dados, etc. Isso te dá bastante flexibilidade. Você pode retornar qualquer tipo de dado, sobrescrever qualquer declaração e validação nos dados, etc.
## Utilizando o `jsonable_encoder` em uma `Response` ## Utilizando o `jsonable_encoder` em uma `Response` { #using-the-jsonable-encoder-in-a-response }
Como o **FastAPI** não realiza nenhuma mudança na `Response` que você retorna, você precisa garantir que o conteúdo dela está pronto para uso. Como o **FastAPI** não realiza nenhuma mudança na `Response` que você retorna, você precisa garantir que o conteúdo dela está pronto para uso.
@ -44,23 +44,22 @@ Você também pode utilizar `from starlette.responses import JSONResponse`.
/// ///
## Retornando uma `Response` ## Retornando uma `Response` personalizada { #returning-a-custom-response }
O exemplo acima mostra todas as partes que você precisa, mas ainda não é muito útil, já que você poderia ter retornado o `item` diretamente, e o **FastAPI** colocaria em uma `JSONResponse` para você, convertendo em um `dict`, etc. Tudo isso por padrão. O exemplo acima mostra todas as partes que você precisa, mas ainda não é muito útil, já que você poderia ter retornado o `item` diretamente, e o **FastAPI** colocaria em uma `JSONResponse` para você, convertendo em um `dict`, etc. Tudo isso por padrão.
Agora, vamos ver como você pode usar isso para retornar uma resposta personalizada. Agora, vamos ver como você pode usar isso para retornar uma resposta personalizada.
Vamos dizer quer retornar uma resposta <a href="https://pt.wikipedia.org/wiki/XML" class="external-link" target="_blank">XML</a>. Vamos dizer que você quer retornar uma resposta <a href="https://en.wikipedia.org/wiki/XML" class="external-link" target="_blank">XML</a>.
Você pode colocar o seu conteúdo XML em uma string, colocar em uma `Response`, e retorná-lo: Você pode colocar o seu conteúdo XML em uma string, colocar em uma `Response`, e retorná-lo:
{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *} {* ../../docs_src/response_directly/tutorial002.py hl[1,18] *}
## Notas ## Notas { #notes }
Quando você retorna uma `Response` diretamente os dados não são validados, convertidos (serializados) ou documentados automaticamente. Quando você retorna uma `Response` diretamente os dados não são validados, convertidos (serializados) ou documentados automaticamente.
Mas você ainda pode documentar como descrito em [Retornos Adicionais no OpenAPI Mas você ainda pode documentar como descrito em [Retornos Adicionais no OpenAPI](additional-responses.md){.internal-link target=_blank}.
](additional-responses.md){.internal-link target=_blank}.
Você pode ver nas próximas seções como usar/declarar essas `Responses` customizadas enquanto mantém a conversão e documentação automática dos dados. Você pode ver nas próximas seções como usar/declarar essas `Responses` customizadas enquanto mantém a conversão e documentação automática dos dados.

View File

@ -1,12 +1,12 @@
# Cabeçalhos de resposta # Cabeçalhos de resposta { #response-headers }
## Usando um parâmetro `Response` ## Use um parâmetro `Response` { #use-a-response-parameter }
Você pode declarar um parâmetro do tipo `Response` na sua *função de operação de rota* (assim como você pode fazer para cookies). Você pode declarar um parâmetro do tipo `Response` na sua *função de operação de rota* (assim como você pode fazer para cookies).
Então você pode definir os cabeçalhos nesse objeto de resposta *temporário*. Então você pode definir os cabeçalhos nesse objeto de resposta *temporário*.
{* ../../docs_src/response_headers/tutorial002.py hl[1,7:8] *} {* ../../docs_src/response_headers/tutorial002.py hl[1, 7:8] *}
Em seguida você pode retornar qualquer objeto que precisar, da maneira que faria normalmente (um `dict`, um modelo de banco de dados, etc.). Em seguida você pode retornar qualquer objeto que precisar, da maneira que faria normalmente (um `dict`, um modelo de banco de dados, etc.).
@ -16,7 +16,7 @@ Se você declarou um `response_model`, ele ainda será utilizado para filtrar e
Você também pode declarar o parâmetro `Response` em dependências e definir cabeçalhos (e cookies) nelas. Você também pode declarar o parâmetro `Response` em dependências e definir cabeçalhos (e cookies) nelas.
## Retornar uma `Response` diretamente ## Retorne uma `Response` diretamente { #return-a-response-directly }
Você também pode adicionar cabeçalhos quando retornar uma `Response` diretamente. Você também pode adicionar cabeçalhos quando retornar uma `Response` diretamente.
@ -24,7 +24,7 @@ Crie uma resposta conforme descrito em [Retornar uma resposta diretamente](respo
{* ../../docs_src/response_headers/tutorial001.py hl[10:12] *} {* ../../docs_src/response_headers/tutorial001.py hl[10:12] *}
/// note | Detalhes técnicos /// note | Detalhes Técnicos
Você também pode usar `from starlette.responses import Response` ou `from starlette.responses import JSONResponse`. Você também pode usar `from starlette.responses import Response` ou `from starlette.responses import JSONResponse`.
@ -34,8 +34,8 @@ E como a `Response` pode ser usada frequentemente para definir cabeçalhos e coo
/// ///
## Cabeçalhos personalizados ## Cabeçalhos personalizados { #custom-headers }
Tenha em mente que cabeçalhos personalizados proprietários podem ser adicionados <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">usando o prefixo 'X-'</a>. Tenha em mente que cabeçalhos personalizados proprietários podem ser adicionados <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">usando o prefixo `X-`</a>.
Porém, se voce tiver cabeçalhos personalizados que deseja que um cliente no navegador possa ver, você precisa adicioná-los às suas configurações de CORS (saiba mais em [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), usando o parâmetro `expose_headers` descrito na <a href="https://www.starlette.dev/middleware/#corsmiddleware" class="external-link" target="_blank">documentação de CORS do Starlette</a>. Porém, se voce tiver cabeçalhos personalizados que deseja que um cliente no navegador possa ver, você precisa adicioná-los às suas configurações de CORS (saiba mais em [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), usando o parâmetro `expose_headers` descrito na <a href="https://www.starlette.dev/middleware/#corsmiddleware" class="external-link" target="_blank">documentação de CORS do Starlette</a>.

View File

@ -1,10 +1,10 @@
# HTTP Basic Auth # HTTP Basic Auth { #http-basic-auth }
Para os casos mais simples, você pode utilizar o HTTP Basic Auth. Para os casos mais simples, você pode utilizar o HTTP Basic Auth.
No HTTP Basic Auth, a aplicação espera um cabeçalho que contém um usuário e uma senha. No HTTP Basic Auth, a aplicação espera um cabeçalho que contém um usuário e uma senha.
Caso ela não receba, ela retorna um erro HTTP 401 "Unauthorized" (*Não Autorizado*). Caso ela não receba, ela retorna um erro HTTP 401 "Unauthorized".
E retorna um cabeçalho `WWW-Authenticate` com o valor `Basic`, e um parâmetro opcional `realm`. E retorna um cabeçalho `WWW-Authenticate` com o valor `Basic`, e um parâmetro opcional `realm`.
@ -12,7 +12,7 @@ Isso sinaliza ao navegador para mostrar o prompt integrado para um usuário e se
Então, quando você digitar o usuário e senha, o navegador os envia automaticamente no cabeçalho. Então, quando você digitar o usuário e senha, o navegador os envia automaticamente no cabeçalho.
## HTTP Basic Auth Simples ## HTTP Basic Auth Simples { #simple-http-basic-auth }
* Importe `HTTPBasic` e `HTTPBasicCredentials`. * Importe `HTTPBasic` e `HTTPBasicCredentials`.
* Crie um "esquema `security`" utilizando `HTTPBasic`. * Crie um "esquema `security`" utilizando `HTTPBasic`.
@ -22,11 +22,11 @@ Então, quando você digitar o usuário e senha, o navegador os envia automatica
{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *} {* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *}
Quando você tentar abrir a URL pela primeira vez (ou clicar no botão "Executar" nos documentos) o navegador vai pedir pelo seu usuário e senha: Quando você tentar abrir a URL pela primeira vez (ou clicar no botão "Executar" na documentação) o navegador vai pedir pelo seu usuário e senha:
<img src="/img/tutorial/security/image12.png"> <img src="/img/tutorial/security/image12.png">
## Verifique o usuário ## Verifique o usuário { #check-the-username }
Aqui está um exemplo mais completo. Aqui está um exemplo mais completo.
@ -52,7 +52,7 @@ if not (credentials.username == "stanleyjobson") or not (credentials.password ==
Porém, ao utilizar o `secrets.compare_digest()`, isso estará seguro contra um tipo de ataque chamado "timing attacks" (ataques de temporização). Porém, ao utilizar o `secrets.compare_digest()`, isso estará seguro contra um tipo de ataque chamado "timing attacks" (ataques de temporização).
### Ataques de Temporização ### Ataques de Temporização { #timing-attacks }
Mas o que é um "timing attack" (ataque de temporização)? Mas o que é um "timing attack" (ataque de temporização)?
@ -80,19 +80,19 @@ if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish":
O Python terá que comparar todo o `stanleyjobso` tanto em `stanleyjobsox` como em `stanleyjobson` antes de perceber que as strings não são a mesma. Então isso levará alguns microssegundos a mais para retornar "Usuário ou senha incorretos". O Python terá que comparar todo o `stanleyjobso` tanto em `stanleyjobsox` como em `stanleyjobson` antes de perceber que as strings não são a mesma. Então isso levará alguns microssegundos a mais para retornar "Usuário ou senha incorretos".
#### O tempo para responder ajuda os invasores #### O tempo para responder ajuda os invasores { #the-time-to-answer-helps-the-attackers }
Neste ponto, ao perceber que o servidor demorou alguns microssegundos a mais para enviar o retorno "Usuário ou senha incorretos", os invasores irão saber que eles acertaram _alguma coisa_, algumas das letras iniciais estavam certas. Neste ponto, ao perceber que o servidor demorou alguns microssegundos a mais para enviar o retorno "Usuário ou senha incorretos", os invasores irão saber que eles acertaram _alguma coisa_, algumas das letras iniciais estavam certas.
E eles podem tentar de novo sabendo que provavelmente é algo mais parecido com `stanleyjobsox` do que com `johndoe`. E eles podem tentar de novo sabendo que provavelmente é algo mais parecido com `stanleyjobsox` do que com `johndoe`.
#### Um ataque "profissional" #### Um ataque "profissional" { #a-professional-attack }
Claro, os invasores não tentariam tudo isso de forma manual, eles escreveriam um programa para fazer isso, possivelmente com milhares ou milhões de testes por segundo. E obteriam apenas uma letra a mais por vez. Claro, os invasores não tentariam tudo isso de forma manual, eles escreveriam um programa para fazer isso, possivelmente com milhares ou milhões de testes por segundo. E obteriam apenas uma letra a mais por vez.
Mas fazendo isso, em alguns minutos ou horas os invasores teriam adivinhado o usuário e senha corretos, com a "ajuda" da nossa aplicação, apenas usando o tempo levado para responder. Mas fazendo isso, em alguns minutos ou horas os invasores teriam adivinhado o usuário e senha corretos, com a "ajuda" da nossa aplicação, apenas usando o tempo levado para responder.
#### Corrija com o `secrets.compare_digest()` #### Corrija com o `secrets.compare_digest()` { #fix-it-with-secrets-compare-digest }
Mas em nosso código já estamos utilizando o `secrets.compare_digest()`. Mas em nosso código já estamos utilizando o `secrets.compare_digest()`.
@ -100,8 +100,7 @@ Resumindo, levará o mesmo tempo para comparar `stanleyjobsox` com `stanleyjobso
Deste modo, ao utilizar `secrets.compare_digest()` no código de sua aplicação, ela estará a salvo contra toda essa gama de ataques de segurança. Deste modo, ao utilizar `secrets.compare_digest()` no código de sua aplicação, ela estará a salvo contra toda essa gama de ataques de segurança.
### Retorne o erro { #return-the-error }
### Retorne o erro
Após detectar que as credenciais estão incorretas, retorne um `HTTPException` com o status 401 (o mesmo retornado quando nenhuma credencial foi informada) e adicione o cabeçalho `WWW-Authenticate` para fazer com que o navegador mostre o prompt de login novamente: Após detectar que as credenciais estão incorretas, retorne um `HTTPException` com o status 401 (o mesmo retornado quando nenhuma credencial foi informada) e adicione o cabeçalho `WWW-Authenticate` para fazer com que o navegador mostre o prompt de login novamente:

View File

@ -1,6 +1,6 @@
# Segurança Avançada # Segurança Avançada { #advanced-security }
## Funcionalidades Adicionais ## Funcionalidades Adicionais { #additional-features }
Existem algumas funcionalidades adicionais para lidar com segurança além das cobertas em [Tutorial - Guia de Usuário: Segurança](../../tutorial/security/index.md){.internal-link target=_blank}. Existem algumas funcionalidades adicionais para lidar com segurança além das cobertas em [Tutorial - Guia de Usuário: Segurança](../../tutorial/security/index.md){.internal-link target=_blank}.
@ -12,7 +12,7 @@ E é possível que para o seu caso de uso, a solução está em uma delas.
/// ///
## Leia o Tutorial primeiro ## Leia o Tutorial primeiro { #read-the-tutorial-first }
As próximas seções pressupõem que você já leu o principal [Tutorial - Guia de Usuário: Segurança](../../tutorial/security/index.md){.internal-link target=_blank}. As próximas seções pressupõem que você já leu o principal [Tutorial - Guia de Usuário: Segurança](../../tutorial/security/index.md){.internal-link target=_blank}.

View File

@ -1,4 +1,4 @@
# Escopos OAuth2 # Escopos OAuth2 { #oauth2-scopes }
Você pode utilizar escopos do OAuth2 diretamente com o **FastAPI**, eles são integrados para funcionar perfeitamente. Você pode utilizar escopos do OAuth2 diretamente com o **FastAPI**, eles são integrados para funcionar perfeitamente.
@ -10,7 +10,7 @@ Toda vez que você "se autentica com" Facebook, Google, GitHub, Microsoft, X (Tw
Nesta seção, você verá como gerenciar a autenticação e autorização com os mesmos escopos do OAuth2 em sua aplicação **FastAPI**. Nesta seção, você verá como gerenciar a autenticação e autorização com os mesmos escopos do OAuth2 em sua aplicação **FastAPI**.
/// warning | Aviso /// warning | Atenção
Isso é uma seção mais ou menos avançada. Se você está apenas começando, você pode pular. Isso é uma seção mais ou menos avançada. Se você está apenas começando, você pode pular.
@ -18,7 +18,7 @@ Você não necessariamente precisa de escopos do OAuth2, e você pode lidar com
Mas o OAuth2 com escopos pode ser integrado de maneira fácil em sua API (com OpenAPI) e a sua documentação de API. Mas o OAuth2 com escopos pode ser integrado de maneira fácil em sua API (com OpenAPI) e a sua documentação de API.
No entando, você ainda aplica estes escopos, ou qualquer outro requisito de segurança/autorização, conforme necessário, em seu código. No entanto, você ainda aplica estes escopos, ou qualquer outro requisito de segurança/autorização, conforme necessário, em seu código.
Em muitos casos, OAuth2 com escopos pode ser um exagero. Em muitos casos, OAuth2 com escopos pode ser um exagero.
@ -26,7 +26,7 @@ Mas se você sabe que precisa, ou está curioso, continue lendo.
/// ///
## Escopos OAuth2 e OpenAPI ## Escopos OAuth2 e OpenAPI { #oauth2-scopes-and-openapi }
A especificação OAuth2 define "escopos" como uma lista de strings separadas por espaços. A especificação OAuth2 define "escopos" como uma lista de strings separadas por espaços.
@ -58,15 +58,15 @@ Para o OAuth2, eles são apenas strings.
/// ///
## Visão global ## Visão global { #global-view }
Primeiro, vamos olhar rapidamente as partes que mudam dos exemplos do **Tutorial - Guia de Usuário** para [OAuth2 com Senha (e hash), Bearer com tokens JWT](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. Agora utilizando escopos OAuth2: Primeiro, vamos olhar rapidamente as partes que mudam dos exemplos do **Tutorial - Guia de Usuário** para [OAuth2 com Senha (e hash), Bearer com tokens JWT](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. Agora utilizando escopos OAuth2:
{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:125,129:135,140,156] *} {* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *}
Agora vamos revisar essas mudanças passo a passo. Agora vamos revisar essas mudanças passo a passo.
## Esquema de segurança OAuth2 ## Esquema de segurança OAuth2 { #oauth2-security-scheme }
A primeira mudança é que agora nós estamos declarando o esquema de segurança OAuth2 com dois escopos disponíveis, `me` e `items`. A primeira mudança é que agora nós estamos declarando o esquema de segurança OAuth2 com dois escopos disponíveis, `me` e `items`.
@ -82,9 +82,9 @@ Este é o mesmo mecanismo utilizado quando você adiciona permissões enquanto s
<img src="/img/tutorial/security/image11.png"> <img src="/img/tutorial/security/image11.png">
## Token JWT com escopos ## Token JWT com escopos { #jwt-token-with-scopes }
Agora, modifique o *caminho de rota* para retornar os escopos solicitados. Agora, modifique a *operação de rota* do token para retornar os escopos solicitados.
Nós ainda estamos utilizando o mesmo `OAuth2PasswordRequestForm`. Ele inclui a propriedade `scopes` com uma `list` de `str`, com cada escopo que ele recebeu na requisição. Nós ainda estamos utilizando o mesmo `OAuth2PasswordRequestForm`. Ele inclui a propriedade `scopes` com uma `list` de `str`, com cada escopo que ele recebeu na requisição.
@ -98,15 +98,15 @@ Porém em sua aplicação, por segurança, você deve garantir que você apenas
/// ///
{* ../../docs_src/security/tutorial005_an_py310.py hl[156] *} {* ../../docs_src/security/tutorial005_an_py310.py hl[157] *}
## Declare escopos em *operações de rota* e dependências ## Declare escopos em *operações de rota* e dependências { #declare-scopes-in-path-operations-and-dependencies }
Agora nós declaramos que a *operação de rota* para `/users/me/items/` exige o escopo `items`. Agora nós declaramos que a *operação de rota* para `/users/me/items/` exige o escopo `items`.
Para isso, nós importamos e utilizamos `Security` de `fastapi`. Para isso, nós importamos e utilizamos `Security` de `fastapi`.
Você pode utilizar `Security` para declarar dependências (assim como `Depends`), porém o `Security` também recebe o parâmetros `scopes` com uma lista de escopos (strings). Você pode utilizar `Security` para declarar dependências (assim como `Depends`), porém o `Security` também recebe o parâmetro `scopes` com uma lista de escopos (strings).
Neste caso, nós passamos a função `get_current_active_user` como dependência para `Security` (da mesma forma que nós faríamos com `Depends`). Neste caso, nós passamos a função `get_current_active_user` como dependência para `Security` (da mesma forma que nós faríamos com `Depends`).
@ -124,9 +124,9 @@ Nós estamos fazendo isso aqui para demonstrar como o **FastAPI** lida com escop
/// ///
{* ../../docs_src/security/tutorial005_an_py310.py hl[5,140,171] *} {* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *}
/// info | Informações Técnicas /// info | Detalhes Técnicos
`Security` é na verdade uma subclasse de `Depends`, e ele possui apenas um parâmetro extra que veremos depois. `Security` é na verdade uma subclasse de `Depends`, e ele possui apenas um parâmetro extra que veremos depois.
@ -136,7 +136,7 @@ Mas quando você importa `Query`, `Path`, `Depends`, `Security` entre outros de
/// ///
## Utilize `SecurityScopes` ## Utilize `SecurityScopes` { #use-securityscopes }
Agora atualize a dependência `get_current_user`. Agora atualize a dependência `get_current_user`.
@ -152,7 +152,7 @@ A classe `SecurityScopes` é semelhante à classe `Request` (`Request` foi utili
{* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *} {* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *}
## Utilize os `scopes` ## Utilize os `scopes` { #use-the-scopes }
O parâmetro `security_scopes` será do tipo `SecurityScopes`. O parâmetro `security_scopes` será do tipo `SecurityScopes`.
@ -166,7 +166,7 @@ Nesta exceção, nós incluímos os escopos necessários (se houver algum) como
{* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *} {* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *}
## Verifique o `username` e o formato dos dados ## Verifique o `username` e o formato dos dados { #verify-the-username-and-data-shape }
Nós verificamos que nós obtemos um `username`, e extraímos os escopos. Nós verificamos que nós obtemos um `username`, e extraímos os escopos.
@ -180,17 +180,17 @@ No lugar de, por exemplo, um `dict`, ou alguma outra coisa, que poderia quebrar
Nós também verificamos que nós temos um usuário com o "*username*", e caso contrário, nós levantamos a mesma exceção que criamos anteriormente. Nós também verificamos que nós temos um usuário com o "*username*", e caso contrário, nós levantamos a mesma exceção que criamos anteriormente.
{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:128] *} {* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:129] *}
## Verifique os `scopes` ## Verifique os `scopes` { #verify-the-scopes }
Nós verificamos agora que todos os escopos necessários, por essa dependência e todos os dependentes (incluindo as *operações de rota*) estão incluídas nos escopos fornecidos pelo token recebido, caso contrário, levantamos uma `HTTPException`. Nós verificamos agora que todos os escopos necessários, por essa dependência e todos os dependentes (incluindo as *operações de rota*) estão incluídas nos escopos fornecidos pelo token recebido, caso contrário, levantamos uma `HTTPException`.
Para isso, nós utilizamos `security_scopes.scopes`, que contém uma `list` com todos esses escopos como uma `str`. Para isso, nós utilizamos `security_scopes.scopes`, que contém uma `list` com todos esses escopos como uma `str`.
{* ../../docs_src/security/tutorial005_an_py310.py hl[129:135] *} {* ../../docs_src/security/tutorial005_an_py310.py hl[130:136] *}
## Árvore de dependência e escopos ## Árvore de dependência e escopos { #dependency-tree-and-scopes }
Vamos rever novamente essa árvore de dependência e os escopos. Vamos rever novamente essa árvore de dependência e os escopos.
@ -223,7 +223,7 @@ Tudo depende dos `scopes` declarados em cada *operação de rota* e cada depend
/// ///
## Mais detalhes sobre `SecurityScopes` ## Mais detalhes sobre `SecurityScopes` { #more-details-about-securityscopes }
Você pode utilizar `SecurityScopes` em qualquer lugar, e em diversos lugares. Ele não precisa estar na dependência "raiz". Você pode utilizar `SecurityScopes` em qualquer lugar, e em diversos lugares. Ele não precisa estar na dependência "raiz".
@ -233,9 +233,9 @@ Porque o `SecurityScopes` terá todos os escopos declarados por dependentes, voc
Todos eles serão validados independentemente para cada *operação de rota*. Todos eles serão validados independentemente para cada *operação de rota*.
## Verifique ## Verifique { #check-it }
Se você abrir os documentos da API, você pode antenticar e especificar quais escopos você quer autorizar. Se você abrir os documentos da API, você pode autenticar e especificar quais escopos você quer autorizar.
<img src="/img/tutorial/security/image11.png"> <img src="/img/tutorial/security/image11.png">
@ -245,9 +245,9 @@ E se você selecionar o escopo `me`, mas não o escopo `items`, você poderá ac
Isso é o que aconteceria se uma aplicação terceira que tentou acessar uma dessas *operações de rota* com um token fornecido por um usuário, dependendo de quantas permissões o usuário forneceu para a aplicação. Isso é o que aconteceria se uma aplicação terceira que tentou acessar uma dessas *operações de rota* com um token fornecido por um usuário, dependendo de quantas permissões o usuário forneceu para a aplicação.
## Sobre integrações de terceiros ## Sobre integrações de terceiros { #about-third-party-integrations }
Neste exemplos nós estamos utilizando o fluxo de senha do OAuth2. Neste exemplo nós estamos utilizando o fluxo de senha do OAuth2.
Isso é apropriado quando nós estamos autenticando em nossa própria aplicação, provavelmente com o nosso próprio "*frontend*". Isso é apropriado quando nós estamos autenticando em nossa própria aplicação, provavelmente com o nosso próprio "*frontend*".
@ -269,6 +269,6 @@ Mas no final, eles estão implementando o mesmo padrão OAuth2.
O **FastAPI** inclui utilitários para todos esses fluxos de autenticação OAuth2 em `fastapi.security.oauth2`. O **FastAPI** inclui utilitários para todos esses fluxos de autenticação OAuth2 em `fastapi.security.oauth2`.
## `Security` em docoradores de `dependências` ## `Security` em decoradores de `dependencies` { #security-in-decorator-dependencies }
Da mesma forma que você pode definir uma `list` de `Depends` no parâmetro de `dependencias` do decorador (como explicado em [Dependências em decoradores de operações de rota](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}), você também pode utilizar `Security` com escopos lá. Da mesma forma que você pode definir uma `list` de `Depends` no parâmetro `dependencies` do decorador (como explicado em [Dependências em decoradores de operações de rota](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}), você também pode utilizar `Security` com escopos lá.

View File

@ -1,148 +1,30 @@
# Configurações e Variáveis de Ambiente # Configurações e Variáveis de Ambiente { #settings-and-environment-variables }
Em muitos casos a sua aplicação pode precisar de configurações externas, como chaves secretas, credenciais de banco de dados, credenciais para serviços de email, etc. Em muitos casos, sua aplicação pode precisar de configurações externas, por exemplo chaves secretas, credenciais de banco de dados, credenciais para serviços de e-mail, etc.
A maioria dessas configurações é variável (podem mudar), como URLs de bancos de dados. E muitas delas podem conter dados sensíveis, como tokens secretos. A maioria dessas configurações é variável (pode mudar), como URLs de banco de dados. E muitas podem ser sensíveis, como segredos.
Por isso é comum prover essas configurações como variáveis de ambiente que são utilizidas pela aplicação. Por esse motivo, é comum fornecê-las em variáveis de ambiente lidas pela aplicação.
## Variáveis de Ambiente
/// tip | Dica /// tip | Dica
Se você já sabe o que são variáveis de ambiente e como utilizá-las, sinta-se livre para avançar para o próximo tópico. Para entender variáveis de ambiente, você pode ler [Variáveis de Ambiente](../environment-variables.md){.internal-link target=_blank}.
/// ///
Uma <a href="https://pt.wikipedia.org/wiki/Variável_de_ambiente" class="external-link" target="_blank">variável de ambiente</a> (abreviada em inglês para "env var") é uma variável definida fora do código Python, no sistema operacional, e pode ser lida pelo seu código Python (ou por outros programas). ## Tipagem e validação { #types-and-validation }
Você pode criar e utilizar variáveis de ambiente no terminal, sem precisar utilizar Python: Essas variáveis de ambiente só conseguem lidar com strings de texto, pois são externas ao Python e precisam ser compatíveis com outros programas e com o resto do sistema (e até com diferentes sistemas operacionais, como Linux, Windows, macOS).
//// tab | Linux, macOS, Windows Bash Isso significa que qualquer valor lido em Python a partir de uma variável de ambiente será uma `str`, e qualquer conversão para um tipo diferente ou validação precisa ser feita em código.
<div class="termy"> ## Pydantic `Settings` { #pydantic-settings }
```console Felizmente, o Pydantic fornece uma ótima utilidade para lidar com essas configurações vindas de variáveis de ambiente com <a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/" class="external-link" target="_blank">Pydantic: Settings management</a>.
// Você pode criar uma env var MY_NAME usando
$ export MY_NAME="Wade Wilson"
// E utilizá-la em outros programas, como ### Instalar `pydantic-settings` { #install-pydantic-settings }
$ echo "Hello $MY_NAME"
Hello Wade Wilson Primeiro, certifique-se de criar seu [ambiente virtual](../virtual-environments.md){.internal-link target=_blank}, ativá-lo e então instalar o pacote `pydantic-settings`:
```
</div>
////
//// tab | Windows PowerShell
<div class="termy">
```console
// Criando env var MY_NAME
$ $Env:MY_NAME = "Wade Wilson"
// Usando em outros programas, como
$ echo "Hello $Env:MY_NAME"
Hello Wade Wilson
```
</div>
////
### Lendo variáveis de ambiente com Python
Você também pode criar variáveis de ambiente fora do Python, no terminal (ou com qualquer outro método), e realizar a leitura delas no Python.
Por exemplo, você pode definir um arquivo `main.py` com o seguinte código:
```Python hl_lines="3"
import os
name = os.getenv("MY_NAME", "World")
print(f"Hello {name} from Python")
```
/// tip | Dica
O segundo parâmetro em <a href="https://docs.python.org/3.8/library/os.html#os.getenv" class="external-link" target="_blank">`os.getenv()`</a> é o valor padrão para o retorno.
Se nenhum valor for informado, `None` é utilizado por padrão, aqui definimos `"World"` como o valor padrão a ser utilizado.
///
E depois você pode executar esse arquivo:
<div class="termy">
```console
// Aqui ainda não definimos a env var
$ python main.py
// Por isso obtemos o valor padrão
Hello World from Python
// Mas se definirmos uma variável de ambiente primeiro
$ export MY_NAME="Wade Wilson"
// E executarmos o programa novamente
$ python main.py
// Agora ele pode ler a variável de ambiente
Hello Wade Wilson from Python
```
</div>
Como variáveis de ambiente podem ser definidas fora do código da aplicação, mas acessadas pela aplicação, e não precisam ser armazenadas (versionadas com `git`) junto dos outros arquivos, é comum utilizá-las para guardar configurações.
Você também pode criar uma variável de ambiente específica para uma invocação de um programa, que é acessível somente para esse programa, e somente enquanto ele estiver executando.
Para fazer isso, crie a variável imediatamente antes de iniciar o programa, na mesma linha:
<div class="termy">
```console
// Criando uma env var MY_NAME na mesma linha da execução do programa
$ MY_NAME="Wade Wilson" python main.py
// Agora a aplicação consegue ler a variável de ambiente
Hello Wade Wilson from Python
// E a variável deixa de existir após isso
$ python main.py
Hello World from Python
```
</div>
/// tip | Dica
Você pode ler mais sobre isso em: <a href="https://12factor.net/pt_br/config" class="external-link" target="_blank">The Twelve-Factor App: Configurações</a>.
///
### Tipagem e Validação
Essas variáveis de ambiente suportam apenas strings, por serem externas ao Python e por que precisam ser compatíveis com outros programas e o resto do sistema (e até mesmo com outros sistemas operacionais, como Linux, Windows e macOS).
Isso significa que qualquer valor obtido de uma variável de ambiente em Python terá o tipo `str`, e qualquer conversão para um tipo diferente ou validação deve ser realizada no código.
## Pydantic `Settings`
Por sorte, o Pydantic possui uma funcionalidade para lidar com essas configurações vindas de variáveis de ambiente utilizando <a href="https://docs.pydantic.dev/latest/usage/pydantic_settings/" class="external-link" target="_blank">Pydantic: Settings management</a>.
### Instalando `pydantic-settings`
Primeiro, instale o pacote `pydantic-settings`:
<div class="termy"> <div class="termy">
@ -153,7 +35,7 @@ $ pip install pydantic-settings
</div> </div>
Ele também está incluído no fastapi quando você instala com a opção `all`: Ele também vem incluído quando você instala os extras `all` com:
<div class="termy"> <div class="termy">
@ -164,19 +46,19 @@ $ pip install "fastapi[all]"
</div> </div>
/// info /// info | Informação
Na v1 do Pydantic ele estava incluído no pacote principal. Agora ele está distribuido como um pacote independente para que você possa optar por instalar ou não caso você não precise dessa funcionalidade. No Pydantic v1 ele vinha incluído no pacote principal. Agora é distribuído como um pacote independente para que você possa optar por instalá-lo ou não, caso não precise dessa funcionalidade.
/// ///
### Criando o objeto `Settings` ### Criar o objeto `Settings` { #create-the-settings-object }
Importe a classe `BaseSettings` do Pydantic e crie uma nova subclasse, de forma parecida com um modelo do Pydantic. Importe `BaseSettings` do Pydantic e crie uma subclasse, muito parecido com um modelo do Pydantic.
Os atributos da classe são declarados com anotações de tipo, e possíveis valores padrão, da mesma maneira que os modelos do Pydantic. Da mesma forma que com modelos do Pydantic, você declara atributos de classe com anotações de tipo e, possivelmente, valores padrão.
Você pode utilizar todas as ferramentas e funcionalidades de validação que são utilizadas nos modelos do Pydantic, como tipos de dados diferentes e validações adicionei com `Field()`. Você pode usar as mesmas funcionalidades e ferramentas de validação que usa em modelos do Pydantic, como diferentes tipos de dados e validações adicionais com `Field()`.
//// tab | Pydantic v2 //// tab | Pydantic v2
@ -186,9 +68,9 @@ Você pode utilizar todas as ferramentas e funcionalidades de validação que s
//// tab | Pydantic v1 //// tab | Pydantic v1
/// info /// info | Informação
Na versão 1 do Pydantic você importaria `BaseSettings` diretamente do módulo `pydantic` em vez do módulo `pydantic_settings`. No Pydantic v1 você importaria `BaseSettings` diretamente de `pydantic` em vez de `pydantic_settings`.
/// ///
@ -198,23 +80,23 @@ Na versão 1 do Pydantic você importaria `BaseSettings` diretamente do módulo
/// tip | Dica /// tip | Dica
Se você quiser algo pronto para copiar e colar na sua aplicação, não use esse exemplo, mas sim o exemplo abaixo. Se você quer algo rápido para copiar e colar, não use este exemplo, use o último abaixo.
/// ///
Portanto, quando você cria uma instância da classe `Settings` (nesse caso, o objeto `settings`), o Pydantic lê as variáveis de ambiente sem diferenciar maiúsculas e minúsculas, por isso, uma variável maiúscula `APP_NAME` será usada para o atributo `app_name`. Então, quando você cria uma instância dessa classe `Settings` (neste caso, no objeto `settings`), o Pydantic vai ler as variáveis de ambiente sem diferenciar maiúsculas de minúsculas; assim, uma variável em maiúsculas `APP_NAME` ainda será lida para o atributo `app_name`.
Depois ele irá converter e validar os dados. Assim, quando você utilizar aquele objeto `settings`, os dados terão o tipo que você declarou (e.g. `items_per_user` será do tipo `int`). Em seguida, ele converterá e validará os dados. Assim, quando você usar esse objeto `settings`, terá dados dos tipos que declarou (por exemplo, `items_per_user` será um `int`).
### Usando o objeto `settings` ### Usar o `settings` { #use-the-settings }
Depois, Você pode utilizar o novo objeto `settings` na sua aplicação: Depois você pode usar o novo objeto `settings` na sua aplicação:
{* ../../docs_src/settings/tutorial001.py hl[18:20] *} {* ../../docs_src/settings/tutorial001.py hl[18:20] *}
### Executando o servidor ### Executar o servidor { #run-the-server }
No próximo passo, você pode inicializar o servidor passando as configurações em forma de variáveis de ambiente, por exemplo, você poderia definir `ADMIN_EMAIL` e `APP_NAME` da seguinte forma: Em seguida, você executaria o servidor passando as configurações como variáveis de ambiente, por exemplo, você poderia definir `ADMIN_EMAIL` e `APP_NAME` com:
<div class="termy"> <div class="termy">
@ -228,110 +110,110 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p
/// tip | Dica /// tip | Dica
Para definir múltiplas variáveis de ambiente para um único comando basta separá-las utilizando espaços, e incluir todas elas antes do comando. Para definir várias variáveis de ambiente para um único comando, basta separá-las com espaço e colocá-las todas antes do comando.
/// ///
Assim, o atributo `admin_email` seria definido como `"deadpool@example.com"`. Então a configuração `admin_email` seria definida como `"deadpool@example.com"`.
`app_name` seria `"ChimichangApp"`. O `app_name` seria `"ChimichangApp"`.
E `items_per_user` manteria o valor padrão de `50`. E `items_per_user` manteria seu valor padrão de `50`.
## Configurações em um módulo separado ## Configurações em outro módulo { #settings-in-another-module }
Você também pode incluir essas configurações em um arquivo de um módulo separado como visto em [Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=\_blank}. Você pode colocar essas configurações em outro arquivo de módulo como visto em [Aplicações Maiores - Múltiplos Arquivos](../tutorial/bigger-applications.md){.internal-link target=_blank}.
Por exemplo, você pode adicionar um arquivo `config.py` com: Por exemplo, você poderia ter um arquivo `config.py` com:
{* ../../docs_src/settings/app01/config.py *} {* ../../docs_src/settings/app01/config.py *}
E utilizar essa configuração em `main.py`: E então usá-lo em um arquivo `main.py`:
{* ../../docs_src/settings/app01/main.py hl[3,11:13] *} {* ../../docs_src/settings/app01/main.py hl[3,11:13] *}
/// tip | Dica /// tip | Dica
Você também precisa incluir um arquivo `__init__.py` como visto em [Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=\_blank}. Você também precisaria de um arquivo `__init__.py` como visto em [Aplicações Maiores - Múltiplos Arquivos](../tutorial/bigger-applications.md){.internal-link target=_blank}.
/// ///
## Configurações em uma dependência ## Configurações em uma dependência { #settings-in-a-dependency }
Em certas ocasiões, pode ser útil fornecer essas configurações a partir de uma dependência, em vez de definir um objeto global `settings` que é utilizado em toda a aplicação. Em algumas ocasiões, pode ser útil fornecer as configurações a partir de uma dependência, em vez de ter um objeto global `settings` usado em todos os lugares.
Isso é especialmente útil durante os testes, já que é bastante simples sobrescrever uma dependência com suas configurações personalizadas. Isso pode ser especialmente útil durante os testes, pois é muito fácil sobrescrever uma dependência com suas próprias configurações personalizadas.
### O arquivo de configuração ### O arquivo de configuração { #the-config-file }
Baseando-se no exemplo anterior, seu arquivo `config.py` seria parecido com isso: Vindo do exemplo anterior, seu arquivo `config.py` poderia ser assim:
{* ../../docs_src/settings/app02/config.py hl[10] *} {* ../../docs_src/settings/app02/config.py hl[10] *}
Perceba que dessa vez não criamos uma instância padrão `settings = Settings()`. Perceba que agora não criamos uma instância padrão `settings = Settings()`.
### O arquivo principal da aplicação ### O arquivo principal da aplicação { #the-main-app-file }
Agora criamos a dependência que retorna um novo objeto `config.Settings()`. Agora criamos uma dependência que retorna um novo `config.Settings()`.
{* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *} {* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *}
/// tip | Dica /// tip | Dica
Vamos discutir sobre `@lru_cache` logo mais. Vamos discutir o `@lru_cache` em breve.
Por enquanto, você pode considerar `get_settings()` como uma função normal. Por enquanto, você pode assumir que `get_settings()` é uma função normal.
/// ///
E então podemos declarar essas configurações como uma dependência na função de operação da rota e utilizar onde for necessário. E então podemos exigi-la na *função de operação de rota* como dependência e usá-la onde for necessário.
{* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *} {* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *}
### Configurações e testes ### Configurações e testes { #settings-and-testing }
Então seria muito fácil fornecer uma configuração diferente durante a execução dos testes sobrescrevendo a dependência de `get_settings`: Então seria muito fácil fornecer um objeto de configurações diferente durante os testes criando uma sobrescrita de dependência para `get_settings`:
{* ../../docs_src/settings/app02/test_main.py hl[9:10,13,21] *} {* ../../docs_src/settings/app02/test_main.py hl[9:10,13,21] *}
Na sobrescrita da dependência, definimos um novo valor para `admin_email` quando instanciamos um novo objeto `Settings`, e então retornamos esse novo objeto. Na sobrescrita da dependência definimos um novo valor para `admin_email` ao criar o novo objeto `Settings`, e então retornamos esse novo objeto.
Após isso, podemos testar se o valor está sendo utilizado. Depois podemos testar que ele é usado.
## Lendo um arquivo `.env` ## Lendo um arquivo `.env` { #reading-a-env-file }
Se você tiver muitas configurações que variem bastante, talvez em ambientes distintos, pode ser útil colocá-las em um arquivo e depois lê-las como se fossem variáveis de ambiente. Se você tiver muitas configurações que possivelmente mudam bastante, talvez em diferentes ambientes, pode ser útil colocá-las em um arquivo e então lê-las como se fossem variáveis de ambiente.
Essa prática é tão comum que possui um nome, essas variáveis de ambiente normalmente são colocadas em um arquivo `.env`, e esse arquivo é chamado de "dotenv". Essa prática é tão comum que tem um nome: essas variáveis de ambiente são comumente colocadas em um arquivo `.env`, e o arquivo é chamado de "dotenv".
/// tip | Dica /// tip | Dica
Um arquivo iniciando com um ponto final (`.`) é um arquivo oculto em sistemas baseados em Unix, como Linux e MacOS. Um arquivo começando com um ponto (`.`) é um arquivo oculto em sistemas tipo Unix, como Linux e macOS.
Mas um arquivo dotenv não precisa ter esse nome exato. Mas um arquivo dotenv não precisa ter exatamente esse nome de arquivo.
/// ///
Pydantic suporta a leitura desses tipos de arquivos utilizando uma biblioteca externa. Você pode ler mais em <a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support" class="external-link" target="_blank">Pydantic Settings: Dotenv (.env) support</a>. O Pydantic tem suporte para leitura desses tipos de arquivos usando uma biblioteca externa. Você pode ler mais em <a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support" class="external-link" target="_blank">Pydantic Settings: Dotenv (.env) support</a>.
/// tip | Dica /// tip | Dica
Para que isso funcione você precisa executar `pip install python-dotenv`. Para isso funcionar, você precisa executar `pip install python-dotenv`.
/// ///
### O arquivo `.env` ### O arquivo `.env` { #the-env-file }
Você pode definir um arquivo `.env` com o seguinte conteúdo: Você poderia ter um arquivo `.env` com:
```bash ```bash
ADMIN_EMAIL="deadpool@example.com" ADMIN_EMAIL="deadpool@example.com"
APP_NAME="ChimichangApp" APP_NAME="ChimichangApp"
``` ```
### Obtendo configurações do `.env` ### Ler configurações do `.env` { #read-settings-from-env }
E então adicionar o seguinte código em `config.py`: E então atualizar seu `config.py` com:
//// tab | Pydantic v2 //// tab | Pydantic v2
@ -339,7 +221,7 @@ E então adicionar o seguinte código em `config.py`:
/// tip | Dica /// tip | Dica
O atributo `model_config` é usado apenas para configuração do Pydantic. Você pode ler mais em <a href="https://docs.pydantic.dev/latest/usage/model_config/" class="external-link" target="_blank">Pydantic Model Config</a>. O atributo `model_config` é usado apenas para configuração do Pydantic. Você pode ler mais em <a href="https://docs.pydantic.dev/latest/concepts/config/" class="external-link" target="_blank">Pydantic: Concepts: Configuration</a>.
/// ///
@ -357,48 +239,48 @@ A classe `Config` é usada apenas para configuração do Pydantic. Você pode le
//// ////
/// info /// info | Informação
Na versão 1 do Pydantic a configuração é realizada por uma classe interna `Config`, na versão 2 do Pydantic isso é feito com o atributo `model_config`. Esse atributo recebe um `dict`, para utilizar o autocomplete e checagem de erros do seu editor de texto você pode importar e utilizar `SettingsConfigDict` para definir esse `dict`. Na versão 1 do Pydantic a configuração era feita em uma classe interna `Config`, na versão 2 do Pydantic é feita em um atributo `model_config`. Esse atributo recebe um `dict`, e para ter autocompletar e erros inline você pode importar e usar `SettingsConfigDict` para definir esse `dict`.
/// ///
Aqui definimos a configuração `env_file` dentro da classe `Settings` do Pydantic, e definimos o valor como o nome do arquivo dotenv que queremos utilizar. Aqui definimos a configuração `env_file` dentro da sua classe `Settings` do Pydantic e definimos o valor como o nome do arquivo dotenv que queremos usar.
### Declarando `Settings` apenas uma vez com `lru_cache` ### Criando o `Settings` apenas uma vez com `lru_cache` { #creating-the-settings-only-once-with-lru-cache }
Ler o conteúdo de um arquivo em disco normalmente é uma operação custosa (lenta), então você provavelmente quer fazer isso apenas um vez e reutilizar o mesmo objeto settings depois, em vez de ler os valores a cada requisição. Ler um arquivo do disco normalmente é uma operação custosa (lenta), então você provavelmente vai querer fazer isso apenas uma vez e depois reutilizar o mesmo objeto de configurações, em vez de lê-lo a cada requisição.
Mas cada vez que fazemos: Mas toda vez que fizermos:
```Python ```Python
Settings() Settings()
``` ```
um novo objeto `Settings` é instanciado, e durante a instanciação, o arquivo `.env` é lido novamente. um novo objeto `Settings` seria criado e, na criação, ele leria o arquivo `.env` novamente.
Se a função da dependência fosse apenas: Se a função de dependência fosse assim:
```Python ```Python
def get_settings(): def get_settings():
return Settings() return Settings()
``` ```
Iriamos criar um novo objeto a cada requisição, e estaríamos lendo o arquivo `.env` a cada requisição. ⚠️ criaríamos esse objeto para cada requisição e leríamos o arquivo `.env` para cada requisição. ⚠️
Mas como estamos utilizando o decorador `@lru_cache` acima, o objeto `Settings` é criado apenas uma vez, na primeira vez que a função é chamada. ✔️ Mas como estamos usando o decorador `@lru_cache` por cima, o objeto `Settings` será criado apenas uma vez, na primeira vez em que for chamado. ✔️
{* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *} {* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *}
Dessa forma, todas as chamadas da função `get_settings()` nas dependências das próximas requisições, em vez de executar o código interno de `get_settings()` e instanciar um novo objeto `Settings`, irão retornar o mesmo objeto que foi retornado na primeira chamada, de novo e de novo. Em qualquer chamada subsequente de `get_settings()` nas dependências das próximas requisições, em vez de executar o código interno de `get_settings()` e criar um novo objeto `Settings`, ele retornará o mesmo objeto que foi retornado na primeira chamada, repetidamente.
#### Detalhes Técnicos de `lru_cache` #### Detalhes Técnicos do `lru_cache` { #lru-cache-technical-details }
`@lru_cache` modifica a função decorada para retornar o mesmo valor que foi retornado na primeira vez, em vez de calculá-lo novamente, executando o código da função toda vez. `@lru_cache` modifica a função que decora para retornar o mesmo valor que foi retornado na primeira vez, em vez de calculá-lo novamente executando o código da função todas as vezes.
Assim, a função abaixo do decorador é executada uma única vez para cada combinação dos argumentos passados. E os valores retornados para cada combinação de argumentos são sempre reutilizados para cada nova chamada da função com a mesma combinação de argumentos. Assim, a função abaixo dele será executada uma vez para cada combinação de argumentos. E então os valores retornados para cada uma dessas combinações de argumentos serão usados repetidamente sempre que a função for chamada com exatamente a mesma combinação de argumentos.
Por exemplo, se você definir uma função: Por exemplo, se você tiver uma função:
```Python ```Python
@lru_cache @lru_cache
@ -406,59 +288,59 @@ def say_hi(name: str, salutation: str = "Ms."):
return f"Hello {salutation} {name}" return f"Hello {salutation} {name}"
``` ```
Seu programa poderia executar dessa forma: seu programa poderia executar assim:
```mermaid ```mermaid
sequenceDiagram sequenceDiagram
participant code as Código participant code as Code
participant function as say_hi() participant function as say_hi()
participant execute as Executar Função participant execute as Execute function
rect rgba(0, 255, 0, .1) rect rgba(0, 255, 0, .1)
code ->> function: say_hi(name="Camila") code ->> function: say_hi(name="Camila")
function ->> execute: executar código da função function ->> execute: execute function code
execute ->> code: retornar o resultado execute ->> code: return the result
end end
rect rgba(0, 255, 255, .1) rect rgba(0, 255, 255, .1)
code ->> function: say_hi(name="Camila") code ->> function: say_hi(name="Camila")
function ->> code: retornar resultado armazenado function ->> code: return stored result
end end
rect rgba(0, 255, 0, .1) rect rgba(0, 255, 0, .1)
code ->> function: say_hi(name="Rick") code ->> function: say_hi(name="Rick")
function ->> execute: executar código da função function ->> execute: execute function code
execute ->> code: retornar o resultado execute ->> code: return the result
end end
rect rgba(0, 255, 0, .1) rect rgba(0, 255, 0, .1)
code ->> function: say_hi(name="Rick", salutation="Mr.") code ->> function: say_hi(name="Rick", salutation="Mr.")
function ->> execute: executar código da função function ->> execute: execute function code
execute ->> code: retornar o resultado execute ->> code: return the result
end end
rect rgba(0, 255, 255, .1) rect rgba(0, 255, 255, .1)
code ->> function: say_hi(name="Rick") code ->> function: say_hi(name="Rick")
function ->> code: retornar resultado armazenado function ->> code: return stored result
end end
rect rgba(0, 255, 255, .1) rect rgba(0, 255, 255, .1)
code ->> function: say_hi(name="Camila") code ->> function: say_hi(name="Camila")
function ->> code: retornar resultado armazenado function ->> code: return stored result
end end
``` ```
No caso da nossa dependência `get_settings()`, a função não recebe nenhum argumento, então ela sempre retorna o mesmo valor. No caso da nossa dependência `get_settings()`, a função nem recebe argumentos, então ela sempre retorna o mesmo valor.
Dessa forma, ela se comporta praticamente como uma variável global, mas ao ser utilizada como uma função de uma dependência, pode facilmente ser sobrescrita durante os testes. Dessa forma, ela se comporta quase como se fosse apenas uma variável global. Mas como usa uma função de dependência, podemos sobrescrevê-la facilmente para testes.
`@lru_cache` é definido no módulo `functools` que faz parte da biblioteca padrão do Python, você pode ler mais sobre esse decorador no link <a href="https://docs.python.org/3/library/functools.html#functools.lru_cache" class="external-link" target="_blank">Python Docs sobre `@lru_cache`</a>. `@lru_cache` faz parte de `functools`, que faz parte da biblioteca padrão do Python; você pode ler mais sobre isso na <a href="https://docs.python.org/3/library/functools.html#functools.lru_cache" class="external-link" target="_blank">documentação do Python para `@lru_cache`</a>.
## Recapitulando ## Recapitulando { #recap }
Você pode usar o módulo Pydantic Settings para gerenciar as configurações de sua aplicação, utilizando todo o poder dos modelos Pydantic. Você pode usar Pydantic Settings para lidar com as configurações da sua aplicação, com todo o poder dos modelos Pydantic.
- Utilizar dependências simplifica os testes. * Usando uma dependência você pode simplificar os testes.
- Você pode utilizar arquivos .env junto das configurações do Pydantic. * Você pode usar arquivos `.env` com ele.
- Utilizar o decorador `@lru_cache` evita que o arquivo .env seja lido de novo e de novo para cada requisição, enquanto permite que você sobrescreva durante os testes. * Usar `@lru_cache` permite evitar ler o arquivo dotenv repetidamente a cada requisição, enquanto permite sobrescrevê-lo durante os testes.

View File

@ -1,41 +1,41 @@
# Sub Aplicações - Montagens # Sub Aplicações - Montagens { #sub-applications-mounts }
Se você precisar ter duas aplicações FastAPI independentes, cada uma com seu próprio OpenAPI e suas próprias interfaces de documentação, você pode ter um aplicativo principal e "montar" uma (ou mais) sub-aplicações. Se você precisar ter duas aplicações FastAPI independentes, cada uma com seu próprio OpenAPI e suas próprias interfaces de documentação, você pode ter um aplicativo principal e "montar" uma (ou mais) sub-aplicações.
## Montando uma aplicação **FastAPI** ## Montando uma aplicação **FastAPI** { #mounting-a-fastapi-application }
"Montar" significa adicionar uma aplicação completamente "independente" em um caminho específico, que então se encarrega de lidar com tudo sob esse caminho, com as operações de rota declaradas nessa sub-aplicação. "Montar" significa adicionar uma aplicação completamente "independente" em um path específico, que então se encarrega de lidar com tudo sob esse path, com as _operações de rota_ declaradas nessa sub-aplicação.
### Aplicação de nível superior ### Aplicação de nível superior { #top-level-application }
Primeiro, crie a aplicação principal, de nível superior, **FastAPI**, e suas *operações de rota*: Primeiro, crie a aplicação principal, de nível superior, **FastAPI**, e suas *operações de rota*:
{* ../../docs_src/sub_applications/tutorial001.py hl[3,6:8] *} {* ../../docs_src/sub_applications/tutorial001.py hl[3, 6:8] *}
### Sub-aplicação ### Sub-aplicação { #sub-application }
Em seguida, crie sua sub-aplicação e suas *operações de rota*. Em seguida, crie sua sub-aplicação e suas *operações de rota*.
Essa sub-aplicação é apenas outra aplicação FastAPI padrão, mas esta é a que será "montada": Essa sub-aplicação é apenas outra aplicação FastAPI padrão, mas esta é a que será "montada":
{* ../../docs_src/sub_applications/tutorial001.py hl[11,14:16] *} {* ../../docs_src/sub_applications/tutorial001.py hl[11, 14:16] *}
### Monte a sub-aplicação ### Monte a sub-aplicação { #mount-the-sub-application }
Na sua aplicação de nível superior, `app`, monte a sub-aplicação, `subapi`. Na sua aplicação de nível superior, `app`, monte a sub-aplicação, `subapi`.
Neste caso, ela será montada no caminho `/subapi`: Neste caso, ela será montada no path `/subapi`:
{* ../../docs_src/sub_applications/tutorial001.py hl[11,19] *} {* ../../docs_src/sub_applications/tutorial001.py hl[11, 19] *}
### Verifique a documentação automática da API ### Verifique a documentação automática da API { #check-the-automatic-api-docs }
Agora, execute `uvicorn` com a aplicação principal, se o seu arquivo for `main.py`, seria: Agora, execute o comando `fastapi` com o seu arquivo:
<div class="termy"> <div class="termy">
```console ```console
$ uvicorn main:app --reload $ fastapi dev main.py
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) <span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
``` ```
@ -50,17 +50,17 @@ Você verá a documentação automática da API para a aplicação principal, in
E então, abra a documentação para a sub-aplicação, em <a href="http://127.0.0.1:8000/subapi/docs" class="external-link" target="_blank">http://127.0.0.1:8000/subapi/docs</a>. E então, abra a documentação para a sub-aplicação, em <a href="http://127.0.0.1:8000/subapi/docs" class="external-link" target="_blank">http://127.0.0.1:8000/subapi/docs</a>.
Você verá a documentação automática da API para a sub-aplicação, incluindo apenas suas próprias _operações de rota_, todas sob o prefixo de sub-caminho correto `/subapi`: Você verá a documentação automática da API para a sub-aplicação, incluindo apenas suas próprias _operações de rota_, todas sob o prefixo de sub-path correto `/subapi`:
<img src="/img/tutorial/sub-applications/image02.png"> <img src="/img/tutorial/sub-applications/image02.png">
Se você tentar interagir com qualquer uma das duas interfaces de usuário, elas funcionarão corretamente, porque o navegador será capaz de se comunicar com cada aplicação ou sub-aplicação específica. Se você tentar interagir com qualquer uma das duas interfaces de usuário, elas funcionarão corretamente, porque o navegador será capaz de se comunicar com cada aplicação ou sub-aplicação específica.
### Detalhes Técnicos: `root_path` ### Detalhes Técnicos: `root_path` { #technical-details-root-path }
Quando você monta uma sub-aplicação como descrito acima, o FastAPI se encarrega de comunicar o caminho de montagem para a sub-aplicação usando um mecanismo da especificação ASGI chamado `root_path`. Quando você monta uma sub-aplicação como descrito acima, o FastAPI se encarrega de comunicar o path de montagem para a sub-aplicação usando um mecanismo da especificação ASGI chamado `root_path`.
Dessa forma, a sub-aplicação saberá usar esse prefixo de caminho para a interface de documentação. Dessa forma, a sub-aplicação saberá usar esse prefixo de path para a interface de documentação.
E a sub-aplicação também poderia ter suas próprias sub-aplicações montadas e tudo funcionaria corretamente, porque o FastAPI lida com todos esses `root_path`s automaticamente. E a sub-aplicação também poderia ter suas próprias sub-aplicações montadas e tudo funcionaria corretamente, porque o FastAPI lida com todos esses `root_path`s automaticamente.

View File

@ -1,4 +1,4 @@
# Templates # Templates { #templates }
Você pode usar qualquer template engine com o **FastAPI**. Você pode usar qualquer template engine com o **FastAPI**.
@ -6,28 +6,30 @@ Uma escolha comum é o Jinja2, o mesmo usado pelo Flask e outras ferramentas.
Existem utilitários para configurá-lo facilmente que você pode usar diretamente em sua aplicação **FastAPI** (fornecidos pelo Starlette). Existem utilitários para configurá-lo facilmente que você pode usar diretamente em sua aplicação **FastAPI** (fornecidos pelo Starlette).
## Instalação de dependências ## Instalar dependências { #install-dependencies }
Para instalar o `jinja2`, siga o código abaixo: Certifique-se de criar um [ambiente virtual](../virtual-environments.md){.internal-link target=_blank}, ativá-lo e instalar `jinja2`:
<div class="termy"> <div class="termy">
```console ```console
$ pip install jinja2 $ pip install jinja2
---> 100%
``` ```
</div> </div>
## Usando `Jinja2Templates` ## Usando `Jinja2Templates` { #using-jinja2templates }
* Importe `Jinja2Templates`. * Importe `Jinja2Templates`.
* Crie um `templates` que você possa reutilizar posteriormente. * Crie um objeto `templates` que você possa reutilizar posteriormente.
* Declare um parâmetro `Request` no *path operation* que retornará um template. * Declare um parâmetro `Request` no *path operation* que retornará um template.
* Use o `template` que você criou para renderizar e retornar uma `TemplateResponse`, passe o nome do template, o request object, e um "context" dict com pares chave-valor a serem usados dentro do template do Jinja2. * Use o `templates` que você criou para renderizar e retornar uma `TemplateResponse`, passe o nome do template, o objeto `request` e um dicionário "context" com pares chave-valor a serem usados dentro do template do Jinja2.
{* ../../docs_src/templates/tutorial001.py hl[4,11,15:18] *} {* ../../docs_src/templates/tutorial001.py hl[4,11,15:18] *}
/// note /// note | Nota
Antes do FastAPI 0.108.0, Starlette 0.29.0, `name` era o primeiro parâmetro. Antes do FastAPI 0.108.0, Starlette 0.29.0, `name` era o primeiro parâmetro.
@ -49,7 +51,7 @@ Você também poderia usar `from starlette.templating import Jinja2Templates`.
/// ///
## Escrevendo Templates ## Escrevendo templates { #writing-templates }
Então você pode escrever um template em `templates/item.html`, por exemplo: Então você pode escrever um template em `templates/item.html`, por exemplo:
@ -57,7 +59,7 @@ Então você pode escrever um template em `templates/item.html`, por exemplo:
{!../../docs_src/templates/templates/item.html!} {!../../docs_src/templates/templates/item.html!}
``` ```
### Interpolação de Valores no Template ### Valores de contexto do template { #template-context-values }
No código HTML que contém: No código HTML que contém:
@ -81,7 +83,7 @@ Por exemplo, dado um ID de valor `42`, aparecerá:
Item ID: 42 Item ID: 42
``` ```
### Argumentos do `url_for` ### Argumentos do `url_for` no template { #template-url-for-arguments }
Você também pode usar `url_for()` dentro do template, ele recebe como argumentos os mesmos argumentos que seriam usados pela sua *path operation function*. Você também pode usar `url_for()` dentro do template, ele recebe como argumentos os mesmos argumentos que seriam usados pela sua *path operation function*.
@ -103,9 +105,9 @@ Por exemplo, com um ID de `42`, isso renderizará:
<a href="/items/42"> <a href="/items/42">
``` ```
## Templates e Arquivos Estáticos ## Templates e arquivos estáticos { #templates-and-static-files }
Você também pode usar `url_for()` dentro do template e usá-lo, por examplo, com o `StaticFiles` que você montou com o `name="static"`. Você também pode usar `url_for()` dentro do template e usá-lo, por exemplo, com o `StaticFiles` que você montou com o `name="static"`.
```jinja hl_lines="4" ```jinja hl_lines="4"
{!../../docs_src/templates/templates/item.html!} {!../../docs_src/templates/templates/item.html!}
@ -117,8 +119,8 @@ Neste exemplo, ele seria vinculado a um arquivo CSS em `static/styles.css` com:
{!../../docs_src/templates/static/styles.css!} {!../../docs_src/templates/static/styles.css!}
``` ```
E como você está usando `StaticFiles`, este arquivo CSS será automaticamente servido pela sua aplicação FastAPI na URL `/static/styles.css`. E como você está usando `StaticFiles`, este arquivo CSS será automaticamente servido pela sua aplicação **FastAPI** na URL `/static/styles.css`.
## Mais detalhes ## Mais detalhes { #more-details }
Para obter mais detalhes, incluindo como testar templates, consulte a <a href="https://www.starlette.dev/templates/" class="external-link" target="_blank">documentação da Starlette sobre templates</a>. Para obter mais detalhes, incluindo como testar templates, consulte a <a href="https://www.starlette.dev/templates/" class="external-link" target="_blank">documentação da Starlette sobre templates</a>.

View File

@ -1,6 +1,6 @@
# Testando Dependências com Sobreposição (Overrides) # Testando Dependências com Sobreposições { #testing-dependencies-with-overrides }
## Sobrepondo dependências durante os testes ## Sobrepondo dependências durante os testes { #overriding-dependencies-during-testing }
Existem alguns cenários onde você deseje sobrepor uma dependência durante os testes. Existem alguns cenários onde você deseje sobrepor uma dependência durante os testes.
@ -8,7 +8,7 @@ Você não quer que a dependência original execute (e nenhuma das subdependênc
Em vez disso, você deseja fornecer uma dependência diferente que será usada somente durante os testes (possivelmente apenas para alguns testes específicos) e fornecerá um valor que pode ser usado onde o valor da dependência original foi usado. Em vez disso, você deseja fornecer uma dependência diferente que será usada somente durante os testes (possivelmente apenas para alguns testes específicos) e fornecerá um valor que pode ser usado onde o valor da dependência original foi usado.
### Casos de uso: serviço externo ### Casos de uso: serviço externo { #use-cases-external-service }
Um exemplo pode ser que você possua um provedor de autenticação externo que você precisa chamar. Um exemplo pode ser que você possua um provedor de autenticação externo que você precisa chamar.
@ -20,7 +20,7 @@ Você provavelmente quer testar o provedor externo uma vez, mas não necessariam
Neste caso, você pode sobrepor (*override*) a dependência que chama o provedor, e utilizar uma dependência customizada que retorna um *mock* do usuário, apenas para os seus testes. Neste caso, você pode sobrepor (*override*) a dependência que chama o provedor, e utilizar uma dependência customizada que retorna um *mock* do usuário, apenas para os seus testes.
### Utilize o atributo `app.dependency_overrides` ### Utilize o atributo `app.dependency_overrides` { #use-the-app-dependency-overrides-attribute }
Para estes casos, a sua aplicação **FastAPI** possui o atributo `app.dependency_overrides`. Ele é um simples `dict`. Para estes casos, a sua aplicação **FastAPI** possui o atributo `app.dependency_overrides`. Ele é um simples `dict`.
@ -34,7 +34,7 @@ E então o **FastAPI** chamará a sobreposição no lugar da dependência origin
Você pode definir uma sobreposição de dependência para uma dependência que é utilizada em qualquer lugar da sua aplicação **FastAPI**. Você pode definir uma sobreposição de dependência para uma dependência que é utilizada em qualquer lugar da sua aplicação **FastAPI**.
A dependência original pode estar sendo utilizada em uma *função de operação de rota*, um *docorador de operação de rota* (quando você não utiliza o valor retornado), uma chamada ao `.include_router()`, etc. A dependência original pode estar sendo utilizada em uma *função de operação de rota*, um *decorador de operação de rota* (quando você não utiliza o valor retornado), uma chamada ao `.include_router()`, etc.
O FastAPI ainda poderá sobrescrevê-lo. O FastAPI ainda poderá sobrescrevê-lo.
@ -48,6 +48,6 @@ app.dependency_overrides = {}
/// tip | Dica /// tip | Dica
Se você quer sobrepor uma dependência apenas para alguns testes, você pode definir a sobreposição no início do testes (dentro da função de teste) e reiniciá-la ao final (no final da função de teste). Se você quer sobrepor uma dependência apenas para alguns testes, você pode definir a sobreposição no início do teste (dentro da função de teste) e reiniciá-la ao final (no final da função de teste).
/// ///

View File

@ -1,5 +1,11 @@
# Testando Eventos: inicialização - encerramento # Testando eventos: lifespan e inicialização - encerramento { #testing-events-lifespan-and-startup-shutdown }
Quando você precisa que os seus manipuladores de eventos (`startup` e `shutdown`) sejam executados em seus testes, você pode utilizar o `TestClient` usando a instrução `with`: Quando você precisa que o `lifespan` seja executado em seus testes, você pode utilizar o `TestClient` com a instrução `with`:
{* ../../docs_src/app_testing/tutorial004.py hl[9:15,18,27:28,30:32,41:43] *}
Você pode ler mais detalhes sobre o ["Executando lifespan em testes no site oficial da documentação do Starlette."](https://www.starlette.dev/lifespan/#running-lifespan-in-tests)
Para os eventos `startup` e `shutdown` descontinuados, você pode usar o `TestClient` da seguinte forma:
{* ../../docs_src/app_testing/tutorial003.py hl[9:12,20:24] *} {* ../../docs_src/app_testing/tutorial003.py hl[9:12,20:24] *}

View File

@ -1,4 +1,4 @@
# Testando WebSockets # Testando WebSockets { #testing-websockets }
Você pode usar o mesmo `TestClient` para testar WebSockets. Você pode usar o mesmo `TestClient` para testar WebSockets.

View File

@ -1,10 +1,10 @@
# Utilizando o Request diretamente # Utilizando o Request diretamente { #using-the-request-directly }
Até agora você declarou as partes da requisição que você precisa utilizando os seus tipos. Até agora você declarou as partes da requisição que você precisa utilizando os seus tipos.
Obtendo dados de: Obtendo dados de:
* Os parâmetros das rotas. * O path como parâmetros.
* Cabeçalhos (*Headers*). * Cabeçalhos (*Headers*).
* Cookies. * Cookies.
* etc. * etc.
@ -13,7 +13,7 @@ E ao fazer isso, o **FastAPI** está validando as informações, convertendo-as
Porém há situações em que você possa precisar acessar o objeto `Request` diretamente. Porém há situações em que você possa precisar acessar o objeto `Request` diretamente.
## Detalhes sobre o objeto `Request` ## Detalhes sobre o objeto `Request` { #details-about-the-request-object }
Como o **FastAPI** é na verdade o **Starlette** por baixo, com camadas de diversas funcionalidades por cima, você pode utilizar o objeto <a href="https://www.starlette.dev/requests/" class="external-link" target="_blank">`Request`</a> do Starlette diretamente quando precisar. Como o **FastAPI** é na verdade o **Starlette** por baixo, com camadas de diversas funcionalidades por cima, você pode utilizar o objeto <a href="https://www.starlette.dev/requests/" class="external-link" target="_blank">`Request`</a> do Starlette diretamente quando precisar.
@ -23,7 +23,7 @@ Embora qualquer outro parâmetro declarado normalmente (o corpo da requisição
Mas há situações específicas onde é útil utilizar o objeto `Request`. Mas há situações específicas onde é útil utilizar o objeto `Request`.
## Utilize o objeto `Request` diretamente ## Utilize o objeto `Request` diretamente { #use-the-request-object-directly }
Vamos imaginar que você deseja obter o endereço de IP/host do cliente dentro da sua *função de operação de rota*. Vamos imaginar que você deseja obter o endereço de IP/host do cliente dentro da sua *função de operação de rota*.
@ -35,15 +35,15 @@ Ao declarar o parâmetro com o tipo sendo um `Request` em sua *função de opera
/// tip | Dica /// tip | Dica
Note que neste caso, nós estamos declarando o parâmetro da rota ao lado do parâmetro da requisição. Note que neste caso, nós estamos declarando o parâmetro de path ao lado do parâmetro da requisição.
Assim, o parâmetro da rota será extraído, validado, convertido para o tipo especificado e anotado com OpenAPI. Assim, o parâmetro de path será extraído, validado, convertido para o tipo especificado e anotado com OpenAPI.
Do mesmo jeito, você pode declarar qualquer outro parâmetro normalmente, e além disso, obter o `Request` também. Do mesmo jeito, você pode declarar qualquer outro parâmetro normalmente, e além disso, obter o `Request` também.
/// ///
## Documentação do `Request` ## Documentação do `Request` { #request-documentation }
Você pode ler mais sobre os detalhes do objeto <a href="https://www.starlette.dev/requests/" class="external-link" target="_blank">`Request` no site da documentação oficial do Starlette.</a>. Você pode ler mais sobre os detalhes do objeto <a href="https://www.starlette.dev/requests/" class="external-link" target="_blank">`Request` no site da documentação oficial do Starlette.</a>.

View File

@ -1,10 +1,10 @@
# WebSockets # WebSockets { #websockets }
Você pode usar <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API" class="external-link" target="_blank">WebSockets</a> com **FastAPI**. Você pode usar <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API" class="external-link" target="_blank">WebSockets</a> com **FastAPI**.
## Instalando `WebSockets` ## Instale `websockets` { #install-websockets }
Garanta que você criou um [ambiente virtual](../virtual-environments.md){.internal-link target=_blank}, o ativou e instalou o `websockets`: Garanta que você criou um [ambiente virtual](../virtual-environments.md){.internal-link target=_blank}, o ativou e instalou o `websockets` (uma biblioteca Python que facilita o uso do protocolo "WebSocket"):
<div class="termy"> <div class="termy">
@ -16,9 +16,9 @@ $ pip install websockets
</div> </div>
## Cliente WebSockets ## Cliente WebSockets { #websockets-client }
### Em produção ### Em produção { #in-production }
Em seu sistema de produção, você provavelmente tem um frontend criado com um framework moderno como React, Vue.js ou Angular. Em seu sistema de produção, você provavelmente tem um frontend criado com um framework moderno como React, Vue.js ou Angular.
@ -40,11 +40,11 @@ Mas é a maneira mais simples de focar no lado do servidor de WebSockets e ter u
{* ../../docs_src/websockets/tutorial001.py hl[2,6:38,41:43] *} {* ../../docs_src/websockets/tutorial001.py hl[2,6:38,41:43] *}
## Criando um `websocket` ## Crie um `websocket` { #create-a-websocket }
Em sua aplicação **FastAPI**, crie um `websocket`: Em sua aplicação **FastAPI**, crie um `websocket`:
{*../../docs_src/websockets/tutorial001.py hl[46:47]*} {* ../../docs_src/websockets/tutorial001.py hl[1,46:47] *}
/// note | Detalhes Técnicos /// note | Detalhes Técnicos
@ -54,15 +54,15 @@ A **FastAPI** fornece o mesmo `WebSocket` diretamente apenas como uma conveniên
/// ///
## Aguardar por mensagens e enviar mensagens ## Aguarde mensagens e envie mensagens { #await-for-messages-and-send-messages }
Em sua rota WebSocket você pode esperar (`await`) por mensagens e enviar mensagens. Em sua rota WebSocket você pode esperar (`await`) por mensagens e enviar mensagens.
{*../../docs_src/websockets/tutorial001.py hl[48:52]*} {* ../../docs_src/websockets/tutorial001.py hl[48:52] *}
Você pode receber e enviar dados binários, de texto e JSON. Você pode receber e enviar dados binários, de texto e JSON.
## Tente você mesmo ## Tente { #try-it }
Se seu arquivo for nomeado `main.py`, execute sua aplicação com: Se seu arquivo for nomeado `main.py`, execute sua aplicação com:
@ -96,7 +96,7 @@ Você pode enviar (e receber) muitas mensagens:
E todas elas usarão a mesma conexão WebSocket. E todas elas usarão a mesma conexão WebSocket.
## Usando `Depends` e outros ## Usando `Depends` e outros { #using-depends-and-others }
Nos endpoints WebSocket você pode importar do `fastapi` e usar: Nos endpoints WebSocket você pode importar do `fastapi` e usar:
@ -109,7 +109,7 @@ Nos endpoints WebSocket você pode importar do `fastapi` e usar:
Eles funcionam da mesma forma que para outros endpoints FastAPI/*operações de rota*: Eles funcionam da mesma forma que para outros endpoints FastAPI/*operações de rota*:
{*../../docs_src/websockets/tutorial002_an_py310.py hl[68:69,82]*} {* ../../docs_src/websockets/tutorial002_an_py310.py hl[68:69,82] *}
/// info | Informação /// info | Informação
@ -119,7 +119,7 @@ Você pode usar um código de fechamento dos <a href="https://tools.ietf.org/htm
/// ///
### Tente os WebSockets com dependências ### Tente os WebSockets com dependências { #try-the-websockets-with-dependencies }
Se seu arquivo for nomeado `main.py`, execute sua aplicação com: Se seu arquivo for nomeado `main.py`, execute sua aplicação com:
@ -133,11 +133,11 @@ $ fastapi dev main.py
</div> </div>
Abrar seu browser em: <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>. Abra seu navegador em: <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>.
Lá você pode definir: Lá você pode definir:
* O "Item ID", usado na rota. * O "Item ID", usado no path.
* O "Token" usado como um parâmetro de consulta. * O "Token" usado como um parâmetro de consulta.
/// tip | Dica /// tip | Dica
@ -150,15 +150,15 @@ Com isso você pode conectar o WebSocket e então enviar e receber mensagens:
<img src="/img/tutorial/websockets/image05.png"> <img src="/img/tutorial/websockets/image05.png">
## Lidando com desconexões e múltiplos clientes ## Lidando com desconexões e múltiplos clientes { #handling-disconnections-and-multiple-clients }
Quando uma conexão WebSocket é fechada, o `await websocket.receive_text()` levantará uma exceção `WebSocketDisconnect`, que você pode então capturar e lidar como neste exemplo. Quando uma conexão WebSocket é fechada, o `await websocket.receive_text()` levantará uma exceção `WebSocketDisconnect`, que você pode então capturar e lidar como neste exemplo.
{*../../docs_src/websockets/tutorial003_py39.py hl[79:81]*} {* ../../docs_src/websockets/tutorial003_py39.py hl[79:81] *}
Para testar: Para testar:
* Abrar o aplicativo com várias abas do navegador. * Abra o aplicativo com várias abas do navegador.
* Escreva mensagens a partir delas. * Escreva mensagens a partir delas.
* Então feche uma das abas. * Então feche uma das abas.
@ -172,13 +172,13 @@ Client #1596980209979 left the chat
O app acima é um exemplo mínimo e simples para demonstrar como lidar e transmitir mensagens para várias conexões WebSocket. O app acima é um exemplo mínimo e simples para demonstrar como lidar e transmitir mensagens para várias conexões WebSocket.
Mas tenha em mente que, como tudo é manipulado na memória, em uma única lista, ele só funcionará enquanto o processo estiver em execução e só funcionará com um único processo. Mas tenha em mente que, como tudo é manipulado na memória, em uma única list, ele só funcionará enquanto o processo estiver em execução e só funcionará com um único processo.
Se você precisa de algo fácil de integrar com o FastAPI, mas que seja mais robusto, suportado por Redis, PostgreSQL ou outros, verifique o <a href="https://github.com/encode/broadcaster" class="external-link" target="_blank">encode/broadcaster</a>. Se você precisa de algo fácil de integrar com o FastAPI, mas que seja mais robusto, suportado por Redis, PostgreSQL ou outros, verifique o <a href="https://github.com/encode/broadcaster" class="external-link" target="_blank">encode/broadcaster</a>.
/// ///
## Mais informações ## Mais informações { #more-info }
Para aprender mais sobre as opções, verifique a documentação do Starlette para: Para aprender mais sobre as opções, verifique a documentação do Starlette para:

View File

@ -1,22 +1,22 @@
# Adicionando WSGI - Flask, Django, entre outros # Adicionando WSGI - Flask, Django, entre outros { #including-wsgi-flask-django-others }
Como você viu em [Sub Applications - Mounts](sub-applications.md){.internal-link target=_blank} e [Behind a Proxy](behind-a-proxy.md){.internal-link target=_blank}, você pode **"montar"** aplicações WSGI. Como você viu em [Subaplicações - Montagens](sub-applications.md){.internal-link target=_blank} e [Atrás de um Proxy](behind-a-proxy.md){.internal-link target=_blank}, você pode montar aplicações WSGI.
Para isso, você pode utilizar o `WSGIMiddleware` para encapsular a sua aplicação WSGI, como por exemplo Flask, Django, etc. Para isso, você pode utilizar o `WSGIMiddleware` para encapsular a sua aplicação WSGI, como por exemplo Flask, Django, etc.
## Usando o `WSGIMiddleware` ## Usando `WSGIMiddleware` { #using-wsgimiddleware }
Você precisa importar o `WSGIMiddleware`. Você precisa importar o `WSGIMiddleware`.
Em seguinda, encapsular a aplicação WSGI (e.g. Flask) com o middleware. Em seguida, encapsule a aplicação WSGI (e.g. Flask) com o middleware.
E então **"montar"** em um caminho de rota. E então monte isso sob um path.
{* ../../docs_src/wsgi/tutorial001.py hl[2:3,23] *} {* ../../docs_src/wsgi/tutorial001.py hl[2:3,3] *}
## Conferindo ## Confira { #check-it }
Agora todas as requisições sob o caminho `/v1/` serão manipuladas pela aplicação utilizando Flask. Agora, todas as requisições sob o path `/v1/` serão manipuladas pela aplicação Flask.
E o resto será manipulado pelo **FastAPI**. E o resto será manipulado pelo **FastAPI**.

View File

@ -1,34 +1,34 @@
# Alternativas, Inspiração e Comparações # Alternativas, Inspiração e Comparações { #alternatives-inspiration-and-comparisons }
O que inspirou o **FastAPI**, como ele se compara às alternativas e o que FastAPI aprendeu delas. O que inspirou o **FastAPI**, como ele se compara às alternativas e o que ele aprendeu com elas.
## Introdução ## Introdução { #intro }
**FastAPI** não poderia existir se não fosse pelos trabalhos anteriores de outras pessoas. **FastAPI** não existiria se não fosse pelo trabalho anterior de outras pessoas.
Houveram tantas ferramentas criadas que ajudaram a inspirar sua criação. Houve muitas ferramentas criadas antes que ajudaram a inspirar sua criação.
Tenho evitado criar um novo framework por anos. Primeiramente tentei resolver todos os recursos cobertos pelo **FastAPI** utilizando muitos frameworks diferentes, plug-ins e ferramentas. Tenho evitado criar um novo framework por vários anos. Primeiro tentei resolver todas as funcionalidades cobertas pelo **FastAPI** utilizando muitos frameworks, plug-ins e ferramentas diferentes.
Mas em algum ponto, não houve outra opção senão criar algo que fornecesse todos esses recursos, pegando as melhores idéias de ferramentas anteriores, e combinando eles da melhor forma possível, utilizando recursos da linguagem que não estavam disponíveis antes (_Type Hints_ no Python 3.6+). Mas em algum momento, não havia outra opção senão criar algo que fornecesse todos esses recursos, pegando as melhores ideias de ferramentas anteriores e combinando-as da melhor maneira possível, usando funcionalidades da linguagem que nem sequer estavam disponíveis antes (anotações de tipo no Python 3.6+).
## Ferramentas anteriores ## Ferramentas anteriores { #previous-tools }
### <a href="https://www.djangoproject.com/" class="external-link" target="_blank">Django</a> ### <a href="https://www.djangoproject.com/" class="external-link" target="_blank">Django</a> { #django }
É o framework mais popular e largamente confiável. É utilizado para construir sistemas como o _Instagram_. É o framework Python mais popular e amplamente confiável. É utilizado para construir sistemas como o Instagram.
É bem acoplado com banco de dados relacional (como MySQL ou PostgreSQL), então, tendo um banco de dados NoSQL (como Couchbase, MongoDB, Cassandra etc) como a principal ferramenta de armazenamento não é muito fácil. É relativamente bem acoplado com bancos de dados relacionais (como MySQL ou PostgreSQL), então, ter um banco de dados NoSQL (como Couchbase, MongoDB, Cassandra, etc.) como mecanismo principal de armazenamento não é muito fácil.
Foi criado para gerar HTML no _backend_, não para criar APIs utilizando um _frontend_ moderno (como React, Vue.js e Angular) ou por outros sistemas (como dispositivos <abbr title="Internet das Coisas">IoT</abbr>) comunicando com ele. Foi criado para gerar o HTML no backend, não para criar APIs usadas por um frontend moderno (como React, Vue.js e Angular) ou por outros sistemas (como dispositivos <abbr title="Internet of Things Internet das Coisas">IoT</abbr>) comunicando com ele.
### <a href="https://www.django-rest-framework.org/" class="external-link" target="_blank">Django REST Framework</a> ### <a href="https://www.django-rest-framework.org/" class="external-link" target="_blank">Django REST Framework</a> { #django-rest-framework }
Django REST framework foi criado para ser uma caixa de ferramentas flexível para construção de APIs web utilizando Django por baixo, para melhorar suas capacidades de API. Django REST framework foi criado para ser uma caixa de ferramentas flexível para construção de APIs Web utilizando Django por baixo, para melhorar suas capacidades de API.
Ele é utilizado por muitas companhias incluindo Mozilla, Red Hat e Eventbrite. Ele é utilizado por muitas empresas incluindo Mozilla, Red Hat e Eventbrite.
Ele foi um dos primeiros exemplos de **documentação automática de API**, e essa foi especificamente uma das primeiras idéias que inspirou "a busca por" **FastAPI**. Foi um dos primeiros exemplos de **documentação automática de API**, e essa foi especificamente uma das primeiras ideias que inspirou "a busca por" **FastAPI**.
/// note | Nota /// note | Nota
@ -38,57 +38,57 @@ Django REST Framework foi criado por Tom Christie. O mesmo criador de Starlette
/// check | **FastAPI** inspirado para /// check | **FastAPI** inspirado para
Ter uma documentação automática da API em interface web. Ter uma interface web de documentação automática da API.
/// ///
### <a href="https://flask.palletsprojects.com" class="external-link" target="_blank">Flask</a> ### <a href="https://flask.palletsprojects.com" class="external-link" target="_blank">Flask</a> { #flask }
Flask é um "microframework", não inclui integração com banco de dados nem muitas das coisas que vêm por padrão no Django. Flask é um "microframework", não inclui integrações com banco de dados nem muitas das coisas que vêm por padrão no Django.
Sua simplicidade e flexibilidade permitem fazer coisas como utilizar bancos de dados NoSQL como principal sistema de armazenamento de dados. Essa simplicidade e flexibilidade permitem fazer coisas como utilizar bancos de dados NoSQL como o principal sistema de armazenamento de dados.
Por ser tão simples, é relativamente intuitivo de aprender, embora a documentação esteja de forma mais técnica em alguns pontos. Por ser muito simples, é relativamente intuitivo de aprender, embora a documentação se torne um pouco técnica em alguns pontos.
Ele é comumente utilizado por outras aplicações que não necessariamente precisam de banco de dados, gerenciamento de usuários, ou algum dos muitos recursos que já vem instalados no Django. Embora muitos desses recursos possam ser adicionados com plug-ins. Ele também é comumente utilizado por outras aplicações que não necessariamente precisam de banco de dados, gerenciamento de usuários, ou qualquer uma das muitas funcionalidades que já vêm prontas no Django. Embora muitas dessas funcionalidades possam ser adicionadas com plug-ins.
Esse desacoplamento de partes, e sendo um "microframework" que pode ser extendido para cobrir exatamente o que é necessário era um recurso chave que eu queria manter. Esse desacoplamento de partes, e ser um "microframework" que pode ser estendido para cobrir exatamente o que é necessário era uma funcionalidade chave que eu queria manter.
Dada a simplicidade do Flask, parecia uma ótima opção para construção de APIs. A próxima coisa a procurar era um "Django REST Framework" para Flask. Dada a simplicidade do Flask, ele parecia uma boa opção para construção de APIs. A próxima coisa a encontrar era um "Django REST Framework" para Flask.
/// check | **FastAPI** inspirado para /// check | **FastAPI** inspirado para
Ser um microframework. Fazer ele fácil para misturar e combinar com ferramentas e partes necessárias. Ser um microframework. Tornar fácil misturar e combinar as ferramentas e partes necessárias.
Ser simples e com sistema de roteamento fácil de usar. Ter um sistema de roteamento simples e fácil de usar.
/// ///
### <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests</a> ### <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests</a> { #requests }
**FastAPI** não é uma alternativa para **Requests**. O escopo deles é muito diferente. **FastAPI** na verdade não é uma alternativa ao **Requests**. O escopo deles é muito diferente.
Na verdade é comum utilizar Requests *dentro* de uma aplicação FastAPI. Na verdade, é comum utilizar Requests dentro de uma aplicação FastAPI.
Ainda assim, FastAPI pegou alguma inspiração do Requests. Ainda assim, o FastAPI tirou bastante inspiração do Requests.
**Requests** é uma biblioteca para interagir com APIs (como um cliente), enquanto **FastAPI** é uma biblioteca para *construir* APIs (como um servidor). **Requests** é uma biblioteca para interagir com APIs (como um cliente), enquanto **FastAPI** é uma biblioteca para construir APIs (como um servidor).
Eles estão, mais ou menos, em pontas opostas, um complementando o outro. Eles estão, mais ou menos, em pontas opostas, complementando-se.
Requests tem um projeto muito simples e intuitivo, fácil de usar, com padrões sensíveis. Mas ao mesmo tempo, é muito poderoso e customizável. Requests tem um design muito simples e intuitivo, é muito fácil de usar, com padrões sensatos. Mas ao mesmo tempo, é muito poderoso e personalizável.
É por isso que, como dito no site oficial: É por isso que, como dito no site oficial:
> Requests é um dos pacotes Python mais baixados de todos os tempos > Requests é um dos pacotes Python mais baixados de todos os tempos
O jeito de usar é muito simples. Por exemplo, para fazer uma requisição `GET`, você deveria escrever: O jeito de usar é muito simples. Por exemplo, para fazer uma requisição `GET`, você escreveria:
```Python ```Python
response = requests.get("http://example.com/some/url") response = requests.get("http://example.com/some/url")
``` ```
A contra-parte da aplicação FastAPI, *rota de operação*, poderia parecer como: A contra-parte na aplicação FastAPI, a operação de rota, poderia ficar assim:
```Python hl_lines="1" ```Python hl_lines="1"
@app.get("/some/url") @app.get("/some/url")
@ -102,50 +102,50 @@ Veja as similaridades em `requests.get(...)` e `@app.get(...)`.
* Ter uma API simples e intuitiva. * Ter uma API simples e intuitiva.
* Utilizar nomes de métodos HTTP (operações) diretamente, de um jeito direto e intuitivo. * Utilizar nomes de métodos HTTP (operações) diretamente, de um jeito direto e intuitivo.
* Ter padrões sensíveis, mas customizações poderosas. * Ter padrões sensatos, mas customizações poderosas.
/// ///
### <a href="https://swagger.io/" class="external-link" target="_blank">Swagger</a> / <a href="https://github.com/OAI/OpenAPI-Specification/" class="external-link" target="_blank">OpenAPI</a> ### <a href="https://swagger.io/" class="external-link" target="_blank">Swagger</a> / <a href="https://github.com/OAI/OpenAPI-Specification/" class="external-link" target="_blank">OpenAPI</a> { #swagger-openapi }
O principal recurso que eu queria do Django REST Framework era a documentação automática da API. A principal funcionalidade que eu queria do Django REST Framework era a documentação automática da API.
Então eu descobri que existia um padrão para documentar APIs, utilizando JSON (ou YAML, uma extensão do JSON) chamado Swagger. Então descobri que existia um padrão para documentar APIs, utilizando JSON (ou YAML, uma extensão do JSON) chamado Swagger.
E tinha uma interface web para APIs Swagger já criada. Então, sendo capaz de gerar documentação Swagger para uma API poderia permitir utilizar essa interface web automaticamente. E havia uma interface web para APIs Swagger já criada. Então, ser capaz de gerar documentação Swagger para uma API permitiria usar essa interface web automaticamente.
Em algum ponto, Swagger foi dado para a Fundação Linux, e foi renomeado OpenAPI. Em algum ponto, Swagger foi doado para a Fundação Linux, para ser renomeado OpenAPI.
Isso acontece porquê quando alguém fala sobre a versão 2.0 é comum dizer "Swagger", e para a versão 3+, "OpenAPI". É por isso que ao falar sobre a versão 2.0 é comum dizer "Swagger", e para a versão 3+ "OpenAPI".
/// check | **FastAPI** inspirado para /// check | **FastAPI** inspirado para
Adotar e usar um padrão aberto para especificações API, ao invés de algum esquema customizado. Adotar e usar um padrão aberto para especificações de API, em vez de um schema personalizado.
E integrar ferramentas de interface para usuários baseado nos padrões: E integrar ferramentas de interface para usuários baseadas nos padrões:
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a> * <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>
* <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a> * <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>
Esses dois foram escolhidos por serem bem populares e estáveis, mas fazendo uma pesquisa rápida, você pode encontrar dúzias de interfaces alternativas adicionais para OpenAPI (assim você poderá utilizar com **FastAPI**). Essas duas foram escolhidas por serem bem populares e estáveis, mas fazendo uma pesquisa rápida, você pode encontrar dúzias de interfaces alternativas adicionais para OpenAPI (que você pode utilizar com **FastAPI**).
/// ///
### Flask REST frameworks ### Flask REST frameworks { #flask-rest-frameworks }
Existem vários Flask REST frameworks, mas depois de investir tempo e trabalho investigando eles, eu descobri que muitos estão descontinuados ou abandonados, com alguns tendo questões que fizeram eles inadequados. Existem vários Flask REST frameworks, mas depois de investir tempo e trabalho investigando-os, descobri que muitos estão descontinuados ou abandonados, com diversas questões em aberto que os tornaram inadequados.
### <a href="https://marshmallow.readthedocs.io/en/3.0/" class="external-link" target="_blank">Marshmallow</a> ### <a href="https://marshmallow.readthedocs.io/en/stable/" class="external-link" target="_blank">Marshmallow</a> { #marshmallow }
Um dos principais recursos necessários em sistemas API é "<abbr title="também chamado _ marshalling, conversão">serialização</abbr>" de dados, que é pegar dados do código (Python) e converter eles em alguma coisa que possa ser enviado através da rede. Por exemplo, converter um objeto contendo dados de um banco de dados em um objeto JSON. Converter objetos `datetime` em strings etc. Uma das principais funcionalidades necessárias em sistemas de API é a "<abbr title="também chamado marshalling, conversão">serialização</abbr>" de dados, que é pegar dados do código (Python) e convertê-los em algo que possa ser enviado pela rede. Por exemplo, converter um objeto contendo dados de um banco de dados em um objeto JSON. Converter objetos `datetime` em strings, etc.
Outro grande recurso necessário nas APIs é validação de dados, certificando que os dados são válidos, dados certos parâmetros. Por exemplo, algum campo é `int`, e não alguma string aleatória. Isso é especialmente útil para dados que estão chegando. Outra grande funcionalidade necessária pelas APIs é a validação de dados, garantindo que os dados são válidos, dados certos parâmetros. Por exemplo, que algum campo seja `int`, e não alguma string aleatória. Isso é especialmente útil para dados de entrada.
Sem um sistema de validação de dados, você teria que realizar todas as verificações manualmente, no código. Sem um sistema de validação de dados, você teria que realizar todas as verificações manualmente, no código.
Esses recursos são o que Marshmallow foi construído para fornecer. Ele é uma ótima biblioteca, e eu já utilizei muito antes. Essas funcionalidades são o que o Marshmallow foi construído para fornecer. É uma ótima biblioteca, e eu a utilizei bastante antes.
Mas ele foi criado antes da existência do _type hints_ do Python. Então, para definir todo o <abbr title="definição de como os dados devem ser formados">_schema_</abbr> você precisa utilizar específicas ferramentas e classes fornecidas pelo Marshmallow. Mas ele foi criado antes de existirem as anotações de tipo do Python. Então, para definir cada <abbr title="a definição de como os dados devem ser formados">schema</abbr> você precisa utilizar utilitários e classes específicos fornecidos pelo Marshmallow.
/// check | **FastAPI** inspirado para /// check | **FastAPI** inspirado para
@ -153,17 +153,17 @@ Usar código para definir "schemas" que forneçam, automaticamente, tipos de dad
/// ///
### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a> ### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a> { #webargs }
Outro grande recurso necessário pelas APIs é a <abbr title="ler e converter para dados Python">análise</abbr> de dados vindos de requisições. Outra grande funcionalidade requerida pelas APIs é o <abbr title="ler e converter para dados Python">parsing</abbr> de dados vindos de requisições de entrada.
Webargs é uma ferramente feita para fornecer o que está no topo de vários frameworks, inclusive Flask. Webargs é uma ferramenta feita para fornecer isso no topo de vários frameworks, inclusive Flask.
Ele utiliza Marshmallow por baixo para validação de dados. E ele foi criado pelos mesmos desenvolvedores. Ele utiliza Marshmallow por baixo para a validação de dados. E foi criado pelos mesmos desenvolvedores.
Ele é uma grande ferramenta e eu também a utilizei muito, antes de ter o **FastAPI**. É uma grande ferramenta e eu também a utilizei bastante, antes de ter o **FastAPI**.
/// info /// info | Informação
Webargs foi criado pelos mesmos desenvolvedores do Marshmallow. Webargs foi criado pelos mesmos desenvolvedores do Marshmallow.
@ -171,29 +171,29 @@ Webargs foi criado pelos mesmos desenvolvedores do Marshmallow.
/// check | **FastAPI** inspirado para /// check | **FastAPI** inspirado para
Ter validação automática de dados vindos de requisições. Ter validação automática dos dados de requisições de entrada.
/// ///
### <a href="https://apispec.readthedocs.io/en/stable/" class="external-link" target="_blank">APISpec</a> ### <a href="https://apispec.readthedocs.io/en/stable/" class="external-link" target="_blank">APISpec</a> { #apispec }
Marshmallow e Webargs fornecem validação, análise e serialização como plug-ins. Marshmallow e Webargs fornecem validação, parsing e serialização como plug-ins.
Mas a documentação ainda está faltando. Então APISpec foi criado. Mas a documentação ainda estava faltando. Então APISpec foi criado.
APISpec tem plug-ins para muitos frameworks (e tem um plug-in para Starlette também). É um plug-in para muitos frameworks (e há um plug-in para Starlette também).
O jeito como ele funciona é que você escreve a definição do _schema_ usando formato YAML dentro da _docstring_ de cada função controlando uma rota. O jeito como ele funciona é que você escreve a definição do schema usando formato YAML dentro da docstring de cada função que lida com uma rota.
E ele gera _schemas_ OpenAPI. E ele gera schemas OpenAPI.
É assim como funciona no Flask, Starlette, Responder etc. É assim como funciona no Flask, Starlette, Responder, etc.
Mas então, nós temos novamente o problema de ter uma micro-sintaxe, dentro de uma string Python (um grande YAML). Mas então, temos novamente o problema de ter uma micro-sintaxe, dentro de uma string Python (um grande YAML).
O editor não poderá ajudar muito com isso. E se nós modificarmos os parâmetros dos _schemas_ do Marshmallow e esquecer de modificar também aquela _docstring_ YAML, o _schema_ gerado pode ficar obsoleto. O editor não pode ajudar muito com isso. E se modificarmos parâmetros ou schemas do Marshmallow e esquecermos de também modificar aquela docstring em YAML, o schema gerado ficaria obsoleto.
/// info /// info | Informação
APISpec foi criado pelos mesmos desenvolvedores do Marshmallow. APISpec foi criado pelos mesmos desenvolvedores do Marshmallow.
@ -201,31 +201,31 @@ APISpec foi criado pelos mesmos desenvolvedores do Marshmallow.
/// check | **FastAPI** inspirado para /// check | **FastAPI** inspirado para
Dar suporte a padrões abertos para APIs, OpenAPI. Dar suporte ao padrão aberto para APIs, OpenAPI.
/// ///
### <a href="https://flask-apispec.readthedocs.io/en/latest/" class="external-link" target="_blank">Flask-apispec</a> ### <a href="https://flask-apispec.readthedocs.io/en/latest/" class="external-link" target="_blank">Flask-apispec</a> { #flask-apispec }
É um plug-in Flask, que amarra junto Webargs, Marshmallow e APISpec. É um plug-in Flask, que amarra juntos Webargs, Marshmallow e APISpec.
Ele utiliza a informação do Webargs e Marshmallow para gerar automaticamente _schemas_ OpenAPI, usando APISpec. Ele utiliza a informação do Webargs e Marshmallow para gerar automaticamente schemas OpenAPI, usando APISpec.
É uma grande ferramenta, mas muito subestimada. Ela deveria ser um pouco mais popular do que muitos outros plug-ins Flask. É de ser esperado que sua documentação seja bem concisa e abstrata. É uma grande ferramenta, muito subestimada. Deveria ser bem mais popular do que muitos plug-ins Flask por aí. Pode ser devido à sua documentação ser concisa e abstrata demais.
Isso resolveu o problema de ter que escrever YAML (outra sintaxe) dentro das _docstrings_ Python. Isso resolveu ter que escrever YAML (outra sintaxe) dentro das docstrings do Python.
Essa combinação de Flask, Flask-apispec com Marshmallow e Webargs foi meu _backend stack_ favorito até construir o **FastAPI**. Essa combinação de Flask, Flask-apispec com Marshmallow e Webargs foi a minha stack de backend favorita até construir o **FastAPI**.
Usando essa combinação levou a criação de vários geradores Flask _full-stack_. Há muitas _stacks_ que eu (e vários times externos) estou utilizando até agora: Usá-la levou à criação de vários geradores Flask full-stack. Estas são as principais stacks que eu (e várias equipes externas) tenho utilizado até agora:
* <a href="https://github.com/tiangolo/full-stack" class="external-link" target="_blank">https://github.com/tiangolo/full-stack</a> * <a href="https://github.com/tiangolo/full-stack" class="external-link" target="_blank">https://github.com/tiangolo/full-stack</a>
* <a href="https://github.com/tiangolo/full-stack-flask-couchbase" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchbase</a> * <a href="https://github.com/tiangolo/full-stack-flask-couchbase" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchbase</a>
* <a href="https://github.com/tiangolo/full-stack-flask-couchdb" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchdb</a> * <a href="https://github.com/tiangolo/full-stack-flask-couchdb" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchdb</a>
E esses mesmos geradores _full-stack_ foram a base dos [Geradores de Projetos **FastAPI**](project-generation.md){.internal-link target=_blank}. E esses mesmos geradores full-stack foram a base dos [Geradores de Projetos **FastAPI**](project-generation.md){.internal-link target=_blank}.
/// info /// info | Informação
Flask-apispec foi criado pelos mesmos desenvolvedores do Marshmallow. Flask-apispec foi criado pelos mesmos desenvolvedores do Marshmallow.
@ -233,151 +233,149 @@ Flask-apispec foi criado pelos mesmos desenvolvedores do Marshmallow.
/// check | **FastAPI** inspirado para /// check | **FastAPI** inspirado para
Gerar _schema_ OpenAPI automaticamente, a partir do mesmo código que define serialização e validação. Gerar o schema OpenAPI automaticamente, a partir do mesmo código que define serialização e validação.
/// ///
### <a href="https://nestjs.com/" class="external-link" target="_blank">NestJS</a> (and <a href="https://angular.io/" class="external-link" target="_blank">Angular</a>) ### <a href="https://nestjs.com/" class="external-link" target="_blank">NestJS</a> (e <a href="https://angular.io/" class="external-link" target="_blank">Angular</a>) { #nestjs-and-angular }
NestJS, que não é nem Python, é um framework NodeJS JavaScript (TypeScript) inspirado pelo Angular. Isso nem é Python, NestJS é um framework NodeJS em JavaScript (TypeScript) inspirado pelo Angular.
Ele alcança de uma forma similar ao que pode ser feito com o Flask-apispec. Ele alcança algo um tanto similar ao que pode ser feito com Flask-apispec.
Ele tem um sistema de injeção de dependência integrado, inspirado pelo Angular 2. É necessário fazer o pré-registro dos "injetáveis" (como todos os sistemas de injeção de dependência que conheço), então, adicionando verbosidade e repetição de código. Ele tem um sistema de injeção de dependência integrado, inspirado pelo Angular 2. É necessário fazer o pré-registro dos "injetáveis" (como todos os sistemas de injeção de dependência que conheço), então, adiciona verbosidade e repetição de código.
Como os parâmetros são descritos com tipos TypeScript (similar aos _type hints_ do Python), o suporte ao editor é muito bom. Como os parâmetros são descritos com tipos do TypeScript (similares às anotações de tipo do Python), o suporte do editor é muito bom.
Mas como os dados TypeScript não são preservados após a compilação para o JavaScript, ele não pode depender dos tipos para definir a validação, serialização e documentação ao mesmo tempo. Devido a isso e a algumas decisões de projeto, para pegar a validação, serialização e geração automática do _schema_, é necessário adicionar decoradores em muitos lugares. Então, ele se torna muito verboso. Mas como os dados do TypeScript não são preservados após a compilação para JavaScript, ele não pode depender dos tipos para definir validação, serialização e documentação ao mesmo tempo. Devido a isso e a algumas decisões de projeto, para obter validação, serialização e geração automática de schema, é necessário adicionar decorators em muitos lugares. Então, ele se torna bastante verboso.
Ele também não controla modelos aninhados muito bem. Então, se o corpo JSON na requisição for um objeto JSON que contém campos internos que contém objetos JSON aninhados, ele não consegue ser validado e documentado apropriadamente. Ele não consegue lidar muito bem com modelos aninhados. Então, se o corpo JSON na requisição for um objeto JSON que contém campos internos que por sua vez são objetos JSON aninhados, ele não consegue ser documentado e validado apropriadamente.
/// check | **FastAPI** inspirado para /// check | **FastAPI** inspirado para
Usar tipos Python para ter um ótimo suporte do editor. Usar tipos do Python para ter um ótimo suporte do editor.
Ter um sistema de injeção de dependência poderoso. Achar um jeito de minimizar repetição de código. Ter um sistema de injeção de dependência poderoso. Encontrar um jeito de minimizar repetição de código.
/// ///
### <a href="https://sanic.readthedocs.io/en/latest/" class="external-link" target="_blank">Sanic</a> ### <a href="https://sanic.readthedocs.io/en/latest/" class="external-link" target="_blank">Sanic</a> { #sanic }
Ele foi um dos primeiros frameworks Python extremamente rápido baseado em `asyncio`. Ele foi feito para ser muito similar ao Flask. Ele foi um dos primeiros frameworks Python extremamente rápidos baseados em `asyncio`. Ele foi feito para ser muito similar ao Flask.
/// note | Detalhes técnicos /// note | Detalhes Técnicos
Ele utiliza <a href="https://github.com/MagicStack/uvloop" class="external-link" target="_blank">`uvloop`</a> ao invés do '_loop_' `asyncio` padrão do Python. É isso que deixa ele tão rápido. Ele utilizava <a href="https://github.com/MagicStack/uvloop" class="external-link" target="_blank">`uvloop`</a> em vez do loop `asyncio` padrão do Python. É isso que o deixava tão rápido.
Ele claramente inspirou Uvicorn e Starlette, que são atualmente mais rápidos que o Sanic em testes de performance abertos. Ele claramente inspirou Uvicorn e Starlette, que atualmente são mais rápidos que o Sanic em benchmarks abertos.
/// ///
/// check | **FastAPI** inspirado para /// check | **FastAPI** inspirado para
Achar um jeito de ter uma performance insana. Encontrar um jeito de ter uma performance insana.
É por isso que o **FastAPI** é baseado em Starlette, para que ele seja o framework mais rápido disponível (performance testada por terceiros). É por isso que o **FastAPI** é baseado em Starlette, pois ela é o framework mais rápido disponível (testado por benchmarks de terceiros).
/// ///
### <a href="https://falconframework.org/" class="external-link" target="_blank">Falcon</a> ### <a href="https://falconframework.org/" class="external-link" target="_blank">Falcon</a> { #falcon }
Falcon é outro framework Python de alta performance, e é projetado para ser minimalista, e funciona como fundação de outros frameworks como Hug. Falcon é outro framework Python de alta performance, projetado para ser minimalista, e servir como base para outros frameworks como Hug.
Ele usa o padrão anterior para frameworks web Python (WSGI) que é síncrono, então ele não pode controlar _WebSockets_ e outros casos de uso. No entanto, ele também tem uma boa performance. Ele é projetado para ter funções que recebem dois parâmetros, uma "request" e uma "response". Então você "lê" partes da requisição, e "escreve" partes para a resposta. Por causa desse design, não é possível declarar parâmetros de requisição e corpos com as anotações de tipo padrão do Python como parâmetros de função.
Ele é projetado para ter funções que recebem dois parâmetros, uma "requisição" e uma "resposta". Então você "lê" as partes da requisição, e "escreve" partes para a resposta. Devido ao seu design, não é possível declarar parâmetros de requisição e corpos com _type hints_ Python padrão como parâmetros de funções. Então, validação de dados, serialização e documentação têm que ser feitos no código, não automaticamente. Ou eles têm que ser implementados como um framework acima do Falcon, como o Hug. Essa mesma distinção acontece em outros frameworks inspirados pelo design do Falcon, de ter um objeto de request e um objeto de response como parâmetros.
Então, validação de dados, serialização e documentação tem que ser feitos no código, não automaticamente. Ou eles terão que ser implementados como um framework acima do Falcon, como o Hug. Essa mesma distinção acontece em outros frameworks que são inspirados pelo design do Falcon, tendo um objeto de requisição e um objeto de resposta como parâmetros.
/// check | **FastAPI** inspirado para /// check | **FastAPI** inspirado para
Achar jeitos de conseguir melhor performance. Encontrar maneiras de obter uma ótima performance.
Juntamente com Hug (como Hug é baseado no Falcon) inspirou **FastAPI** para declarar um parâmetro de `resposta` nas funções. Juntamente com Hug (como Hug é baseado no Falcon) inspirou **FastAPI** a declarar um parâmetro de `response` nas funções.
Embora no FastAPI seja opcional, é utilizado principalmente para configurar cabeçalhos, cookies e códigos de status alternativos. Embora no FastAPI seja opcional, é utilizado principalmente para configurar cabeçalhos, cookies e códigos de status alternativos.
/// ///
### <a href="https://moltenframework.com/" class="external-link" target="_blank">Molten</a> ### <a href="https://moltenframework.com/" class="external-link" target="_blank">Molten</a> { #molten }
Eu descobri Molten nos primeiros estágios da construção do **FastAPI**. E ele tem umas idéias bem similares: Eu descobri Molten nos primeiros estágios da construção do **FastAPI**. E ele tem ideias bastante similares:
* Baseado em _type hints_ Python. * Baseado nas anotações de tipo do Python.
* Validação e documentação desses tipos. * Validação e documentação a partir desses tipos.
* Sistema de injeção de dependência. * Sistema de Injeção de Dependência.
Ele não utiliza validação de dados, seriallização e documentação de bibliotecas de terceiros como o Pydantic, ele tem seu prórpio. Então, essas definições de tipo de dados não podem ser reutilizados tão facilmente. Ele não utiliza uma biblioteca de terceiros para validação de dados, serialização e documentação como o Pydantic, ele tem a sua própria. Então, essas definições de tipos de dados não seriam reutilizáveis tão facilmente.
Ele exige um pouco mais de verbosidade nas configurações. E como é baseado no WSGI (ao invés de ASGI), ele não é projetado para ter a vantagem da alta performance fornecida por ferramentas como Uvicorn, Starlette e Sanic. Ele exige configurações um pouco mais verbosas. E como é baseado em WSGI (em vez de ASGI), ele não é projetado para tirar vantagem da alta performance fornecida por ferramentas como Uvicorn, Starlette e Sanic.
O sistema de injeção de dependência exige pré-registro das dependências e as dependências são resolvidas baseadas nos tipos declarados. Então, não é possível declarar mais do que um "componente" que fornece um certo tipo. O sistema de injeção de dependência exige pré-registro das dependências e elas são resolvidas com base nos tipos declarados. Então, não é possível declarar mais de um "componente" que forneça um certo tipo.
Rotas são declaradas em um único lugar, usando funções declaradas em outros lugares (ao invés de usar decoradores que possam ser colocados diretamente acima da função que controla o _endpoint_). Isso é mais perto de como o Django faz isso do que como Flask (e Starlette) faz. Ele separa no código coisas que são relativamente amarradas. As rotas são declaradas em um único lugar, usando funções declaradas em outros lugares (em vez de usar decorators que possam ser colocados diretamente acima da função que lida com o endpoint). Isso é mais próximo de como o Django faz do que de como o Flask (e o Starlette) fazem. Separa no código coisas que são relativamente bem acopladas.
/// check | **FastAPI** inspirado para /// check | **FastAPI** inspirado para
Definir validações extras para tipos de dados usando valores "padrão" de atributos dos modelos. Isso melhora o suporte do editor, e não estava disponível no Pydantic antes. Definir validações extras para tipos de dados usando o valor "padrão" de atributos dos modelos. Isso melhora o suporte do editor, e não estava disponível no Pydantic antes.
Isso na verdade inspirou a atualização de partes do Pydantic, para dar suporte ao mesmo estilo de declaração da validação (toda essa funcionalidade já está disponível no Pydantic). Isso na verdade inspirou a atualização de partes do Pydantic, para dar suporte ao mesmo estilo de declaração da validação (toda essa funcionalidade já está disponível no Pydantic).
/// ///
### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">Hug</a> ### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">Hug</a> { #hug }
Hug foi um dos primeiros frameworks a implementar a declaração de tipos de parâmetros usando Python _type hints_. Isso foi uma ótima idéia que inspirou outras ferramentas a fazer o mesmo. Hug foi um dos primeiros frameworks a implementar a declaração de tipos de parâmetros de API usando anotações de tipo do Python. Isso foi uma ótima ideia que inspirou outras ferramentas a fazer o mesmo.
Ele usou tipos customizados em suas declarações ao invés dos tipos padrão Python, mas mesmo assim foi um grande passo. Ele usou tipos personalizados em suas declarações em vez dos tipos padrão do Python, mas mesmo assim foi um grande passo adiante.
Ele também foi um dos primeiros frameworks a gerar um _schema_ customizado declarando a API inteira em JSON. Ele também foi um dos primeiros frameworks a gerar um schema personalizado declarando a API inteira em JSON.
Ele não era baseado em um padrão como OpenAPI e JSON Schema. Então não poderia ter interação direta com outras ferramentas, como Swagger UI. Mas novamente, era uma idéia muito inovadora. Ele não era baseado em um padrão como OpenAPI e JSON Schema. Então não seria simples integrá-lo com outras ferramentas, como Swagger UI. Mas novamente, era uma ideia muito inovadora.
Hug tinha um incomum, interessante recurso: usando o mesmo framework, é possível criar tanto APIs como CLIs. Ele tem um recurso interessante e incomum: usando o mesmo framework, é possível criar APIs e também CLIs.
Como é baseado nos padrões anteriores de frameworks web síncronos (WSGI), ele não pode controlar _Websockets_ e outras coisas, embora ele ainda tenha uma alta performance também. Como é baseado no padrão anterior para frameworks web Python síncronos (WSGI), ele não consegue lidar com Websockets e outras coisas, embora ainda tenha alta performance também.
/// info /// info | Informação
Hug foi criado por Timothy Crosley, o mesmo criador do <a href="https://github.com/timothycrosley/isort" class="external-link" target="_blank">`isort`</a>, uma grande ferramenta para ordenação automática de _imports_ em arquivos Python. Hug foi criado por Timothy Crosley, o mesmo criador do <a href="https://github.com/timothycrosley/isort" class="external-link" target="_blank">`isort`</a>, uma ótima ferramenta para ordenar automaticamente imports em arquivos Python.
/// ///
/// check | Idéias inspiradas para o **FastAPI** /// check | Ideias que inspiraram o **FastAPI**
Hug inspirou partes do APIStar, e foi uma das ferramentas que eu achei mais promissora, ao lado do APIStar. Hug inspirou partes do APIStar, e foi uma das ferramentas que achei mais promissoras, ao lado do APIStar.
Hug ajudou a inspirar o **FastAPI** a usar _type hints_ do Python para declarar parâmetros, e para gerar um _schema_ definindo a API automaticamente. Hug ajudou a inspirar o **FastAPI** a usar anotações de tipo do Python para declarar parâmetros e para gerar um schema definindo a API automaticamente.
Hug inspirou **FastAPI** a declarar um parâmetro de `resposta` em funções para definir cabeçalhos e cookies. Hug inspirou **FastAPI** a declarar um parâmetro de `response` em funções para definir cabeçalhos e cookies.
/// ///
### <a href="https://github.com/encode/apistar" class="external-link" target="_blank">APIStar</a> (<= 0.5) ### <a href="https://github.com/encode/apistar" class="external-link" target="_blank">APIStar</a> (<= 0.5) { #apistar-0-5 }
Antes de decidir construir **FastAPI** eu encontrei o servidor **APIStar**. Tinha quase tudo que eu estava procurando e tinha um grande projeto. Pouco antes de decidir construir o **FastAPI** eu encontrei o servidor **APIStar**. Ele tinha quase tudo o que eu estava procurando e tinha um ótimo design.
Ele foi uma das primeiras implementações de um framework usando Python _type hints_ para declarar parâmetros e requisições que eu nunca vi (antes no NestJS e Molten). Eu encontrei ele mais ou menos na mesma época que o Hug. Mas o APIStar utilizava o padrão OpenAPI. Foi uma das primeiras implementações de um framework usando anotações de tipo do Python para declarar parâmetros e requisições que eu já vi (antes do NestJS e Molten). Eu o encontrei mais ou menos na mesma época que o Hug. Mas o APIStar utilizava o padrão OpenAPI.
Ele tinha validação de dados automática, serialização de dados e geração de _schema_ OpenAPI baseado nos mesmos _type hints_ em vários locais. Ele tinha validação de dados automática, serialização de dados e geração de schema OpenAPI baseadas nas mesmas anotações de tipo em vários locais.
Definições de _schema_ de corpo não utilizavam os mesmos Python _type hints_ como Pydantic, ele era um pouco mais similar ao Marshmallow, então, o suporte ao editor não seria tão bom, ainda assim, APIStar era a melhor opção disponível. As definições de schema de corpo não utilizavam as mesmas anotações de tipo do Python como o Pydantic, eram um pouco mais similares ao Marshmallow, então o suporte do editor não seria tão bom, ainda assim, APIStar era a melhor opção disponível.
Ele obteve as melhores performances em testes na época (somente batido por Starlette). Ele obteve os melhores benchmarks de performance na época (somente ultrapassado por Starlette).
A princípio, ele não tinha uma interface web com documentação automática da API, mas eu sabia que poderia adicionar o Swagger UI a ele. A princípio, ele não tinha uma interface web com documentação automática da API, mas eu sabia que poderia adicionar o Swagger UI a ele.
Ele tinha um sistema de injeção de dependência. Ele exigia pré-registro dos componentes, como outras ferramentas já discutidas acima. Mas ainda era um grande recurso. Ele tinha um sistema de injeção de dependência. Exigia pré-registro dos componentes, como outras ferramentas já discutidas acima. Mas ainda assim era um grande recurso.
Eu nunca fui capaz de usar ele num projeto inteiro, por não ter integração de segurança, então, eu não pude substituir todos os recursos que eu tinha com os geradores _full-stack_ baseados no Flask-apispec. Eu tive em minha gaveta de projetos a idéia de criar um _pull request_ adicionando essa funcionalidade. Eu nunca fui capaz de usá-lo em um projeto completo, pois ele não tinha integração de segurança, então, eu não pude substituir todos os recursos que eu tinha com os geradores full-stack baseados no Flask-apispec. Eu tinha no meu backlog de projetos criar um pull request adicionando essa funcionalidade.
Mas então, o foco do projeto mudou. Mas então, o foco do projeto mudou.
Ele não era mais um framework web API, como o criador precisava focar no Starlette. Ele não era mais um framework web de API, pois o criador precisava focar no Starlette.
Agora APIStar é um conjunto de ferramentas para validar especificações OpenAPI, não um framework web. Agora APIStar é um conjunto de ferramentas para validar especificações OpenAPI, não um framework web.
/// info /// info | Informação
APIStar foi criado por Tom Christie. O mesmo cara que criou: APIStar foi criado por Tom Christie. O mesmo cara que criou:
@ -391,98 +389,97 @@ APIStar foi criado por Tom Christie. O mesmo cara que criou:
Existir. Existir.
A idéia de declarar múltiplas coisas (validação de dados, serialização e documentação) com os mesmos tipos Python, que ao mesmo tempo fornecesse grande suporte ao editor, era algo que eu considerava uma brilhante idéia. A ideia de declarar múltiplas coisas (validação de dados, serialização e documentação) com os mesmos tipos do Python, que ao mesmo tempo fornecessem grande suporte ao editor, era algo que eu considerava uma ideia brilhante.
E após procurar por um logo tempo por um framework similar e testar muitas alternativas diferentes, APIStar foi a melhor opção disponível. E após procurar por muito tempo por um framework similar e testar muitas alternativas diferentes, APIStar foi a melhor opção disponível.
Então APIStar parou de existir como um servidor e Starlette foi criado, e foi uma nova melhor fundação para tal sistema. Essa foi a inspiração final para construir **FastAPI**. Então APIStar deixou de existir como servidor e o Starlette foi criado, sendo uma nova e melhor fundação para tal sistema. Essa foi a inspiração final para construir o **FastAPI**.
Eu considero **FastAPI** um "sucessor espiritual" para o APIStar, evoluindo e melhorando os recursos, sistema de tipagem e outras partes, baseado na aprendizagem de todas essas ferramentas acima. Eu considero o **FastAPI** um "sucessor espiritual" do APIStar, enquanto aprimora e amplia as funcionalidades, o sistema de tipagem e outras partes, baseado nos aprendizados de todas essas ferramentas anteriores.
/// ///
## Usados por **FastAPI** ## Usados por **FastAPI** { #used-by-fastapi }
### <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> ### <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> { #pydantic }
Pydantic é uma biblioteca para definir validação de dados, serialização e documentação (usando JSON Schema) baseado nos Python _type hints_. Pydantic é uma biblioteca para definir validação de dados, serialização e documentação (usando JSON Schema) com base nas anotações de tipo do Python.
Isso faz dele extremamente intuitivo. Isso o torna extremamente intuitivo.
Ele é comparável ao Marshmallow. Embora ele seja mais rápido que Marshmallow em testes de performance. E ele é baseado nos mesmos Python _type hints_, o suporte ao editor é ótimo. Ele é comparável ao Marshmallow. Embora seja mais rápido que o Marshmallow em benchmarks. E como é baseado nas mesmas anotações de tipo do Python, o suporte do editor é ótimo.
/// check | **FastAPI** usa isso para /// check | **FastAPI** usa isso para
Controlar toda a validação de dados, serialização de dados e modelo de documentação automática (baseado no JSON Schema). Controlar toda a validação de dados, serialização de dados e documentação automática de modelos (baseada no JSON Schema).
**FastAPI** então pega dados do JSON Schema e coloca eles no OpenAPI, à parte de todas as outras coisas que ele faz. **FastAPI** então pega esses dados do JSON Schema e os coloca no OpenAPI, além de todas as outras coisas que faz.
/// ///
### <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a> ### <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a> { #starlette }
Starlette é um framework/caixa de ferramentas <abbr title="O novo padrão para construção de Python web assíncrono">ASGI</abbr> peso leve, o que é ideal para construir serviços assíncronos de alta performance. Starlette é um framework/caixa de ferramentas <abbr title="O novo padrão para construir aplicações web Python assíncronas">ASGI</abbr> leve, o que é ideal para construir serviços asyncio de alta performance.
Ele é muito simples e intuitivo. É projetado para ser extensível facilmente, e ter componentes modulares. Ele é muito simples e intuitivo. É projetado para ser facilmente extensível, e ter componentes modulares.
Ele tem: Ele tem:
* Performance seriamente impressionante. * Performance seriamente impressionante.
* Suporte a WebSocket. * Suporte a WebSocket.
* Suporte a GraphQL. * Tarefas em segundo plano dentro do processo.
* Tarefas de processamento interno por trás dos panos.
* Eventos de inicialização e encerramento. * Eventos de inicialização e encerramento.
* Cliente de testes construído com HTTPX. * Cliente de testes construído com HTTPX.
* Respostas CORS, GZip, Arquivos Estáticos, Streaming. * CORS, GZip, Arquivos Estáticos, respostas Streaming.
* Suporte para Sessão e Cookie. * Suporte para Sessão e Cookie.
* 100% coberto por testes. * 100% coberto por testes.
* Código base 100% anotado com tipagem. * Código base 100% anotado com tipagem.
* Dependências complexas Zero. * Poucas dependências obrigatórias.
Starlette é atualmente o mais rápido framework Python testado. Somente ultrapassado pelo Uvicorn, que não é um framework, mas um servidor. Starlette é atualmente o framework Python mais rápido testado. Somente ultrapassado pelo Uvicorn, que não é um framework, mas um servidor.
Starlette fornece toda a funcionalidade básica de um microframework web. Starlette fornece toda a funcionalidade básica de um microframework web.
Mas ele não fornece validação de dados automática, serialização e documentação. Mas ele não fornece validação de dados automática, serialização ou documentação.
Essa é uma das principais coisas que **FastAPI** adiciona no topo, tudo baseado em Python _type hints_ (usando Pydantic). Isso, mais o sistema de injeção de dependência, utilidades de segurança, geração de _schema_ OpenAPI, etc. Essa é uma das principais coisas que o **FastAPI** adiciona por cima, tudo baseado nas anotações de tipo do Python (usando Pydantic). Isso, mais o sistema de injeção de dependência, utilidades de segurança, geração de schema OpenAPI, etc.
/// note | Detalhes Técnicos /// note | Detalhes Técnicos
ASGI é um novo "padrão" sendo desenvolvido pelos membros do time central do Django. Ele ainda não está como "Padrão Python" (PEP), embora eles estejam em processo de fazer isso. ASGI é um novo "padrão" sendo desenvolvido por membros do time central do Django. Ele ainda não é um "padrão Python" (uma PEP), embora eles estejam no processo de fazer isso.
No entanto, ele já está sendo utilizado como "padrão" por diversas ferramentas. Isso melhora enormemente a interoperabilidade, como você poderia trocar Uvicorn por qualquer outro servidor ASGI (como Daphne ou Hypercorn), ou você poderia adicionar ferramentas compatíveis com ASGI, como `python-socketio`. No entanto, ele já está sendo utilizado como "padrão" por diversas ferramentas. Isso melhora enormemente a interoperabilidade, pois você poderia trocar Uvicorn por qualquer outro servidor ASGI (como Daphne ou Hypercorn), ou você poderia adicionar ferramentas compatíveis com ASGI, como `python-socketio`.
/// ///
/// check | **FastAPI** usa isso para /// check | **FastAPI** usa isso para
Controlar todas as partes web centrais. Adiciona recursos no topo. Controlar todas as partes web centrais. Adiciona funcionalidades por cima.
A classe `FastAPI` em si herda `Starlette`. A classe `FastAPI` em si herda diretamente da classe `Starlette`.
Então, qualquer coisa que você faz com Starlette, você pode fazer diretamente com **FastAPI**, pois ele é basicamente um Starlette com esteróides. Então, qualquer coisa que você pode fazer com Starlette, você pode fazer diretamente com o **FastAPI**, pois ele é basicamente um Starlette com esteróides.
/// ///
### <a href="https://www.uvicorn.dev/" class="external-link" target="_blank">Uvicorn</a> ### <a href="https://www.uvicorn.dev/" class="external-link" target="_blank">Uvicorn</a> { #uvicorn }
Uvicorn é um servidor ASGI peso leve, construído com uvloop e httptools. Uvicorn é um servidor ASGI extremamente rápido, construído com uvloop e httptools.
Ele não é um framework web, mas sim um servidor. Por exemplo, ele não fornece ferramentas para roteamento por rotas. Isso é algo que um framework como Starlette (ou **FastAPI**) poderia fornecer por cima. Ele não é um framework web, mas sim um servidor. Por exemplo, ele não fornece ferramentas para roteamento por paths. Isso é algo que um framework como Starlette (ou **FastAPI**) forneceria por cima.
Ele é o servidor recomendado para Starlette e **FastAPI**. Ele é o servidor recomendado para Starlette e **FastAPI**.
/// check | **FastAPI** recomenda isso para /// check | **FastAPI** o recomenda como
O principal servidor web para rodar aplicações **FastAPI**. O principal servidor web para rodar aplicações **FastAPI**.
Você pode combinar ele com o Gunicorn, para ter um servidor multi-processos assíncrono. Você também pode usar a opção de linha de comando `--workers` para ter um servidor assíncrono multi-processos.
Verifique mais detalhes na seção [Deployment](deployment/index.md){.internal-link target=_blank}. Verifique mais detalhes na seção [Deployment](deployment/index.md){.internal-link target=_blank}.
/// ///
## Performance e velocidade ## Benchmarks e velocidade { #benchmarks-and-speed }
Para entender, comparar e ver a diferença entre Uvicorn, Starlette e FastAPI, verifique a seção sobre [Benchmarks](benchmarks.md){.internal-link target=_blank}. Para entender, comparar e ver a diferença entre Uvicorn, Starlette e FastAPI, verifique a seção sobre [Benchmarks](benchmarks.md){.internal-link target=_blank}.

View File

@ -1,10 +1,10 @@
# Concorrência e async / await # Concorrência e async / await { #concurrency-and-async-await }
Detalhes sobre a sintaxe `async def` para *funções de operação de rota* e alguns conceitos de código assíncrono, concorrência e paralelismo. Detalhes sobre a sintaxe `async def` para *funções de operação de rota* e alguns conceitos de código assíncrono, concorrência e paralelismo.
## Com pressa? ## Com pressa? { #in-a-hurry }
<abbr title="muito longo; não li"><strong>TL;DR:</strong></abbr> <abbr title="too long; didn't read muito longo; não li"><strong>TL;DR:</strong></abbr>
Se você estiver utilizando bibliotecas de terceiros que dizem para você chamar as funções com `await`, como: Se você estiver utilizando bibliotecas de terceiros que dizem para você chamar as funções com `await`, como:
@ -12,7 +12,7 @@ Se você estiver utilizando bibliotecas de terceiros que dizem para você chamar
results = await some_library() results = await some_library()
``` ```
Então, declare sua *função de operação de rota* com `async def` como: Então, declare suas *funções de operação de rota* com `async def` como:
```Python hl_lines="2" ```Python hl_lines="2"
@app.get('/') @app.get('/')
@ -21,7 +21,7 @@ async def read_results():
return results return results
``` ```
/// note /// note | Nota
Você só pode usar `await` dentro de funções criadas com `async def`. Você só pode usar `await` dentro de funções criadas com `async def`.
@ -29,7 +29,7 @@ Você só pode usar `await` dentro de funções criadas com `async def`.
--- ---
Se você está usando biblioteca de terceiros que se comunica com alguma coisa (um banco de dados, uma API, sistema de arquivos etc) e não tem suporte para utilizar `await` (esse é atualmente o caso para a maioria das bibliotecas de banco de dados), então declare suas *funções de operação de rota* normalmente, com apenas `def`, como: Se você está usando uma biblioteca de terceiros que se comunica com alguma coisa (um banco de dados, uma API, o sistema de arquivos etc.) e não tem suporte para utilizar `await` (esse é atualmente o caso para a maioria das bibliotecas de banco de dados), então declare suas *funções de operação de rota* normalmente, com apenas `def`, como:
```Python hl_lines="2" ```Python hl_lines="2"
@app.get('/') @app.get('/')
@ -40,7 +40,7 @@ def results():
--- ---
Se sua aplicação (de alguma forma) não tem que se comunicar com nada mais e esperar que o respondam, use `async def`. Se sua aplicação (de alguma forma) não tem que se comunicar com nada mais e esperar que o respondam, use `async def`, mesmo que você não precise usar `await` dentro dela.
--- ---
@ -54,17 +54,17 @@ De qualquer forma, em ambos os casos acima, FastAPI irá trabalhar assincronamen
Mas, seguindo os passos acima, ele será capaz de fazer algumas otimizações de performance. Mas, seguindo os passos acima, ele será capaz de fazer algumas otimizações de performance.
## Detalhes Técnicos ## Detalhes Técnicos { #technical-details }
Versões modernas de Python tem suporte para **"código assíncrono"** usando algo chamado **"corrotinas"**, com sintaxe **`async` e `await`**. Versões modernas de Python têm suporte para **"código assíncrono"** usando algo chamado **"corrotinas"**, com sintaxe **`async` e `await`**.
Vamos ver aquela frase por partes na seção abaixo: Vamos ver aquela frase por partes nas seções abaixo:
* **Código assíncrono** * **Código assíncrono**
* **`async` e `await`** * **`async` e `await`**
* **Corrotinas** * **Corrotinas**
## Código assíncrono ## Código assíncrono { #asynchronous-code }
Código assíncrono apenas significa que a linguagem 💬 tem um jeito de dizer para o computador / programa 🤖 que em certo ponto do código, ele 🤖 terá que esperar *algo* finalizar em outro lugar. Vamos dizer que esse *algo* seja chamado "arquivo lento" 📝. Código assíncrono apenas significa que a linguagem 💬 tem um jeito de dizer para o computador / programa 🤖 que em certo ponto do código, ele 🤖 terá que esperar *algo* finalizar em outro lugar. Vamos dizer que esse *algo* seja chamado "arquivo lento" 📝.
@ -74,10 +74,10 @@ Então o computador / programa 🤖 irá voltar sempre que tiver uma chance, sej
Depois, ele 🤖 pega a primeira tarefa para finalizar (vamos dizer, nosso "arquivo lento" 📝) e continua o que tem que fazer com ela. Depois, ele 🤖 pega a primeira tarefa para finalizar (vamos dizer, nosso "arquivo lento" 📝) e continua o que tem que fazer com ela.
Esse "esperar por algo" normalmente se refere a operações <abbr title="Entrada e Saída">I/O</abbr> que são relativamente "lentas" (comparadas à velocidade do processador e da memória RAM), como esperar por: Esse "esperar por algo" normalmente se refere a operações <abbr title="Input and Output Entrada e Saída">I/O</abbr> que são relativamente "lentas" (comparadas à velocidade do processador e da memória RAM), como esperar por:
* dados do cliente para serem enviados através da rede * dados do cliente para serem enviados através da rede
* dados enviados pelo seu programa serem recebidos pelo clente através da rede * dados enviados pelo seu programa serem recebidos pelo cliente através da rede
* conteúdo de um arquivo no disco ser lido pelo sistema e entregue ao seu programa * conteúdo de um arquivo no disco ser lido pelo sistema e entregue ao seu programa
* conteúdo que seu programa deu ao sistema para ser escrito no disco * conteúdo que seu programa deu ao sistema para ser escrito no disco
* uma operação em uma API remota * uma operação em uma API remota
@ -85,7 +85,7 @@ Esse "esperar por algo" normalmente se refere a operações <abbr title="Entrada
* uma solicitação no banco de dados retornar o resultado * uma solicitação no banco de dados retornar o resultado
* etc. * etc.
Quanto o tempo de execução é consumido majoritariamente pela espera de operações <abbr title="Entrada e Saída">I/O</abbr>, essas operações são chamadas operações "limitadas por I/O". Quanto o tempo de execução é consumido majoritariamente pela espera de operações <abbr title="Input and Output Entrada e Saída">I/O</abbr>, essas operações são chamadas operações "limitadas por I/O".
Isso é chamado de "assíncrono" porque o computador / programa não tem que ser "sincronizado" com a tarefa lenta, esperando pelo momento exato em que a tarefa finaliza, enquanto não faz nada, para ser capaz de pegar o resultado da tarefa e dar continuidade ao trabalho. Isso é chamado de "assíncrono" porque o computador / programa não tem que ser "sincronizado" com a tarefa lenta, esperando pelo momento exato em que a tarefa finaliza, enquanto não faz nada, para ser capaz de pegar o resultado da tarefa e dar continuidade ao trabalho.
@ -93,9 +93,9 @@ Ao invés disso, sendo um sistema "assíncrono", uma vez finalizada, a tarefa po
Para "síncrono" (contrário de "assíncrono") também é utilizado o termo "sequencial", porquê o computador / programa segue todos os passos, em sequência, antes de trocar para uma tarefa diferente, mesmo se alguns passos envolvam esperar. Para "síncrono" (contrário de "assíncrono") também é utilizado o termo "sequencial", porquê o computador / programa segue todos os passos, em sequência, antes de trocar para uma tarefa diferente, mesmo se alguns passos envolvam esperar.
### Concorrência e hambúrgueres ### Concorrência e hambúrgueres { #concurrency-and-burgers }
Essa idéia de código **assíncrono** descrita acima é às vezes chamado de **"concorrência"**. Isso é diferente de **"paralelismo"**. Essa ideia de código **assíncrono** descrita acima é às vezes chamada de **"concorrência"**. Isso é diferente de **"paralelismo"**.
**Concorrência** e **paralelismo** ambos são relacionados a "diferentes coisas acontecendo mais ou menos ao mesmo tempo". **Concorrência** e **paralelismo** ambos são relacionados a "diferentes coisas acontecendo mais ou menos ao mesmo tempo".
@ -103,31 +103,51 @@ Mas os detalhes entre *concorrência* e *paralelismo* são bem diferentes.
Para ver essa diferença, imagine a seguinte história sobre hambúrgueres: Para ver essa diferença, imagine a seguinte história sobre hambúrgueres:
### Hambúrgueres concorrentes ### Hambúrgueres concorrentes { #concurrent-burgers }
Você vai com seu _crush_ na lanchonete, e fica na fila enquanto o caixa pega os pedidos das pessoas na sua frente. 😍 Você vai com seu _crush_ na lanchonete, e fica na fila enquanto o caixa pega os pedidos das pessoas na sua frente. 😍
<img src="/img/async/concurrent-burgers/concurrent-burgers-01.png" class="illustration">
Então chega a sua vez, você pede dois saborosos hambúrgueres para você e seu _crush_. 🍔🍔 Então chega a sua vez, você pede dois saborosos hambúrgueres para você e seu _crush_. 🍔🍔
O caixa diz alguma coisa para o cozinheiro na cozinha para que eles saivam que têm que preparar seus hambúrgueres (mesmo que ele esteja atualmente preparando os lanches dos outros clientes). <img src="/img/async/concurrent-burgers/concurrent-burgers-02.png" class="illustration">
O caixa diz alguma coisa para o cozinheiro na cozinha para que eles saibam que têm que preparar seus hambúrgueres (mesmo que ele esteja atualmente preparando os lanches dos outros clientes).
<img src="/img/async/concurrent-burgers/concurrent-burgers-03.png" class="illustration">
Você paga. 💸 Você paga. 💸
O caixa te entrega seu número de chamada. O caixa te entrega seu número de chamada.
<img src="/img/async/concurrent-burgers/concurrent-burgers-04.png" class="illustration">
Enquanto você espera, você vai com seu _crush_ e pega uma mesa, senta e conversa com seu _crush_ por um bom tempo (já que seus hambúrgueres são muito saborosos, e leva um tempo para serem preparados). Enquanto você espera, você vai com seu _crush_ e pega uma mesa, senta e conversa com seu _crush_ por um bom tempo (já que seus hambúrgueres são muito saborosos, e leva um tempo para serem preparados).
Já que você está sentado na mesa com seu _crush_, esperando os hambúrgueres, você pode passar esse tempo admirando o quão lindo, maravilhoso e esperto é seu _crush_ ✨😍✨. Já que você está sentado na mesa com seu _crush_, esperando os hambúrgueres, você pode passar esse tempo admirando o quão lindo, maravilhoso e esperto é seu _crush_ ✨😍✨.
<img src="/img/async/concurrent-burgers/concurrent-burgers-05.png" class="illustration">
Enquanto espera e conversa com seu _crush_, de tempos em tempos, você verifica o número da chamada exibido no balcão para ver se já é sua vez. Enquanto espera e conversa com seu _crush_, de tempos em tempos, você verifica o número da chamada exibido no balcão para ver se já é sua vez.
Então em algum momento, é finalmente sua vez. Você vai ao balcão, pega seus hambúrgueres e volta para a mesa. Então em algum momento, é finalmente sua vez. Você vai ao balcão, pega seus hambúrgueres e volta para a mesa.
<img src="/img/async/concurrent-burgers/concurrent-burgers-06.png" class="illustration">
Você e seu _crush_ comem os hambúrgueres e aproveitam o tempo. ✨ Você e seu _crush_ comem os hambúrgueres e aproveitam o tempo. ✨
<img src="/img/async/concurrent-burgers/concurrent-burgers-07.png" class="illustration">
/// info | Informação
Belas ilustrações de <a href="https://www.instagram.com/ketrinadrawsalot" class="external-link" target="_blank">Ketrina Thompson</a>. 🎨
///
--- ---
Imagine que você seja o computador / programa nessa história. Imagine que você seja o computador / programa 🤖 nessa história.
Enquanto você está na fila, você está somente ocioso 😴, esperando por sua vez, sem fazer nada muito "produtivo". Mas a fila é rápida porque o caixa só está pegando os pedidos (não os preparando), então está tudo bem. Enquanto você está na fila, você está somente ocioso 😴, esperando por sua vez, sem fazer nada muito "produtivo". Mas a fila é rápida porque o caixa só está pegando os pedidos (não os preparando), então está tudo bem.
@ -139,13 +159,13 @@ Contudo, à medida que você se afasta do balcão e senta na mesa, com um númer
Então o caixa 💁 diz que "seus hambúrgueres estão prontos" colocando seu número no balcão, mas você não corre que nem um maluco imediatamente quando o número exibido é o seu. Você sabe que ninguém irá roubar seus hambúrgueres porque você tem o seu número da chamada, e os outros têm os deles. Então o caixa 💁 diz que "seus hambúrgueres estão prontos" colocando seu número no balcão, mas você não corre que nem um maluco imediatamente quando o número exibido é o seu. Você sabe que ninguém irá roubar seus hambúrgueres porque você tem o seu número da chamada, e os outros têm os deles.
Então você espera seu _crush_ terminar a história que estava contando (terminar o trabalho atual ⏯ / tarefa sendo processada 🤓), sorri gentilmente e diz que você está indo buscar os hambúrgueres. Então você espera seu _crush_ terminar a história que estava contando (terminar o trabalho atual ⏯ / tarefa sendo processada 🤓), sorri gentilmente e diz que você está indo buscar os hambúrgueres.
Então você vai ao balcão 🔀, para a tarefa inicial que agora está finalizada⏯, pega os hambúrgueres, agradece, e leva-os para a mesa. Isso finaliza esse passo / tarefa da interação com o balcão ⏹. Isso, por sua vez, cria uma nova tarefa, a de "comer hambúrgueres" 🔀 ⏯, mas a tarefa anterior de "pegar os hambúrgueres" já está finalizada ⏹. Então você vai ao balcão 🔀, para a tarefa inicial que agora está finalizada ⏯, pega os hambúrgueres, agradece, e leva-os para a mesa. Isso finaliza esse passo / tarefa da interação com o balcão ⏹. Isso, por sua vez, cria uma nova tarefa, a de "comer hambúrgueres" 🔀 ⏯, mas a tarefa anterior de "pegar os hambúrgueres" já está finalizada ⏹.
### Hambúrgueres paralelos ### Hambúrgueres paralelos { #parallel-burgers }
Agora vamos imaginar que esses não são "Hambúrgueres Concorrentes", e sim "Hambúrgueres Paralelos" Agora vamos imaginar que esses não são "Hambúrgueres Concorrentes", e sim "Hambúrgueres Paralelos".
Você vai com seu _crush_ na lanchonete paralela. Você vai com seu _crush_ na lanchonete paralela.
@ -153,29 +173,47 @@ Você fica na fila enquanto vários (vamos dizer 8) caixas que também são cozi
Todo mundo na sua frente está esperando seus hambúrgueres ficarem prontos antes de deixar o caixa porque cada um dos 8 caixas vai e prepara o hambúrguer logo após receber o pedido, antes de pegar o próximo pedido. Todo mundo na sua frente está esperando seus hambúrgueres ficarem prontos antes de deixar o caixa porque cada um dos 8 caixas vai e prepara o hambúrguer logo após receber o pedido, antes de pegar o próximo pedido.
<img src="/img/async/parallel-burgers/parallel-burgers-01.png" class="illustration">
Então é finalmente sua vez, você pede 2 hambúrgueres muito saborosos para você e seu _crush_. Então é finalmente sua vez, você pede 2 hambúrgueres muito saborosos para você e seu _crush_.
Você paga 💸. Você paga 💸.
<img src="/img/async/parallel-burgers/parallel-burgers-02.png" class="illustration">
O caixa vai para a cozinha. O caixa vai para a cozinha.
Você espera, na frente do balcão 🕙, para que ninguém pegue seus hambúrgueres antes de você, já que não tem números de chamadas. Você espera, na frente do balcão 🕙, para que ninguém pegue seus hambúrgueres antes de você, já que não tem números de chamadas.
<img src="/img/async/parallel-burgers/parallel-burgers-03.png" class="illustration">
Como você e seu _crush_ estão ocupados não permitindo que ninguém passe na frente e pegue seus hambúrgueres assim que estiverem prontos, você não pode dar atenção ao seu _crush_. 😞 Como você e seu _crush_ estão ocupados não permitindo que ninguém passe na frente e pegue seus hambúrgueres assim que estiverem prontos, você não pode dar atenção ao seu _crush_. 😞
Isso é trabalho "síncrono", você está "sincronizado" com o caixa / cozinheiro👨🍳. Você tem que esperar 🕙 e estar lá no exato momento que o caixa / cozinheiro 👨‍🍳 terminar os hambúrgueres e os der a você, ou então, outro alguém pode pegá-los. Isso é trabalho "síncrono", você está "sincronizado" com o caixa / cozinheiro 👨‍🍳. Você tem que esperar 🕙 e estar lá no exato momento que o caixa / cozinheiro 👨‍🍳 terminar os hambúrgueres e os der a você, ou então, outro alguém pode pegá-los.
<img src="/img/async/parallel-burgers/parallel-burgers-04.png" class="illustration">
Então seu caixa / cozinheiro 👨‍🍳 finalmente volta com seus hambúrgueres, depois de um longo tempo esperando 🕙 por eles em frente ao balcão. Então seu caixa / cozinheiro 👨‍🍳 finalmente volta com seus hambúrgueres, depois de um longo tempo esperando 🕙 por eles em frente ao balcão.
<img src="/img/async/parallel-burgers/parallel-burgers-05.png" class="illustration">
Você pega seus hambúrgueres e vai para a mesa com seu _crush_. Você pega seus hambúrgueres e vai para a mesa com seu _crush_.
Vocês comem os hambúrgueres, e o trabalho está terminado. ⏹ Vocês comem os hambúrgueres, e o trabalho está terminado. ⏹
<img src="/img/async/parallel-burgers/parallel-burgers-06.png" class="illustration">
Não houve muita conversa ou flerte já que a maior parte do tempo foi gasto esperando 🕙 na frente do balcão. 😞 Não houve muita conversa ou flerte já que a maior parte do tempo foi gasto esperando 🕙 na frente do balcão. 😞
/// info | Informação
Belas ilustrações de <a href="https://www.instagram.com/ketrinadrawsalot" class="external-link" target="_blank">Ketrina Thompson</a>. 🎨
///
--- ---
Nesse cenário dos hambúrgueres paralelos, você é um computador / programa com dois processadores (você e seu _crush_), ambos esperando 🕙 e dedicando sua atenção ⏯ "esperando no balcão" 🕙 por um bom tempo. Nesse cenário dos hambúrgueres paralelos, você é um computador / programa 🤖 com dois processadores (você e seu _crush_), ambos esperando 🕙 e dedicando sua atenção ⏯ "esperando no balcão" 🕙 por um bom tempo.
A lanchonete paralela tem 8 processadores (caixas / cozinheiros), enquanto a lanchonete dos hambúrgueres concorrentes tinha apenas 2 (um caixa e um cozinheiro). A lanchonete paralela tem 8 processadores (caixas / cozinheiros), enquanto a lanchonete dos hambúrgueres concorrentes tinha apenas 2 (um caixa e um cozinheiro).
@ -183,7 +221,7 @@ Ainda assim, a experiência final não foi a melhor. 😞
--- ---
Essa seria o equivalente paralelo à histório dos hambúrgueres. 🍔 Essa seria o equivalente paralelo à história dos hambúrgueres. 🍔
Para um exemplo "mais real", imagine um banco. Para um exemplo "mais real", imagine um banco.
@ -195,7 +233,7 @@ E você tinha que esperar 🕙 na fila por um longo tempo ou poderia perder a ve
Você provavelmente não gostaria de levar seu _crush_ 😍 com você para um rolezinho no banco 🏦. Você provavelmente não gostaria de levar seu _crush_ 😍 com você para um rolezinho no banco 🏦.
### Conclusão dos hambúrgueres ### Conclusão dos hambúrgueres { #burger-conclusion }
Nesse cenário dos "hambúrgueres com seu _crush_", como tem muita espera, faz mais sentido ter um sistema concorrente ⏸🔀⏯. Nesse cenário dos "hambúrgueres com seu _crush_", como tem muita espera, faz mais sentido ter um sistema concorrente ⏸🔀⏯.
@ -215,7 +253,7 @@ E esse é o mesmo nível de performance que você tem com o **FastAPI**.
E como você pode ter paralelismo e assincronicidade ao mesmo tempo, você tem uma maior performance do que a maioria dos frameworks NodeJS testados e lado a lado com Go, que é uma linguagem compilada, mais próxima ao C <a href="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1" class="external-link" target="_blank">(tudo graças ao Starlette)</a>. E como você pode ter paralelismo e assincronicidade ao mesmo tempo, você tem uma maior performance do que a maioria dos frameworks NodeJS testados e lado a lado com Go, que é uma linguagem compilada, mais próxima ao C <a href="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1" class="external-link" target="_blank">(tudo graças ao Starlette)</a>.
### Concorrência é melhor que paralelismo? ### Concorrência é melhor que paralelismo? { #is-concurrency-better-than-parallelism }
Não! Essa não é a moral da história. Não! Essa não é a moral da história.
@ -239,7 +277,7 @@ Mas nesse caso, se você trouxesse os 8 ex-caixas / cozinheiros / agora-faxineir
Nesse cenário, cada um dos faxineiros (incluindo você) poderia ser um processador, fazendo a sua parte do trabalho. Nesse cenário, cada um dos faxineiros (incluindo você) poderia ser um processador, fazendo a sua parte do trabalho.
E a maior parte do tempo de execução é tomada por trabalho real (ao invés de ficar esperando), e o trabalho em um computador é feito pela <abbr title="Unidade de Processamento Central">CPU</abbr>. Eles chamam esses problemas de "limitados por CPU". E a maior parte do tempo de execução é tomada por trabalho real (ao invés de ficar esperando), e o trabalho em um computador é feito pela <abbr title="Central Processing Unit Unidade Central de Processamento">CPU</abbr>. Eles chamam esses problemas de "limitados por CPU".
--- ---
@ -249,22 +287,20 @@ Por exemplo:
* **Processamento de áudio** ou **imagem** * **Processamento de áudio** ou **imagem**
* **Visão Computacional**: uma imagem é composta por milhões de pixels, cada pixel tem 3 valores / cores, processar isso normalmente exige alguma computação em todos esses pixels ao mesmo tempo * **Visão Computacional**: uma imagem é composta por milhões de pixels, cada pixel tem 3 valores / cores, processar isso normalmente exige alguma computação em todos esses pixels ao mesmo tempo
* **Aprendizado de Máquina**: Normalmente exige muita multiplicação de matrizes e vetores. Pense numa grande planilha com números e em multiplicar todos eles juntos e ao mesmo tempo.
* **Deep Learning**: Esse é um subcampo do Aprendizado de Máquina, então, o mesmo se aplica. A diferença é que não há apenas uma grande planilha com números para multiplicar, mas um grande conjunto delas, e em muitos casos, você utiliza um processador especial para construir e/ou usar esses modelos.
* **Machine Learning**: Normalmente exige muita multiplicação de matrizes e vetores. Pense numa grande planilha com números e em multiplicar todos eles juntos e ao mesmo tempo. ### Concorrência + Paralelismo: Web + Aprendizado de Máquina { #concurrency-parallelism-web-machine-learning }
* **Deep Learning**: Esse é um subcampo do Machine Learning, então, o mesmo se aplica. A diferença é que não há apenas uma grande planilha com números para multiplicar, mas um grande conjunto delas, e em muitos casos, você utiliza um processador especial para construir e/ou usar esses modelos.
### Concorrência + Paralelismo: Web + Machine learning
Com **FastAPI** você pode levar a vantagem da concorrência que é muito comum para desenvolvimento web (o mesmo atrativo de NodeJS). Com **FastAPI** você pode levar a vantagem da concorrência que é muito comum para desenvolvimento web (o mesmo atrativo de NodeJS).
Mas você também pode explorar os benefícios do paralelismo e multiprocessamento (tendo múltiplos processadores rodando em paralelo) para trabalhos **limitados por CPU** como aqueles em sistemas de Machine Learning. Mas você também pode explorar os benefícios do paralelismo e multiprocessamento (tendo múltiplos processadores rodando em paralelo) para trabalhos **limitados por CPU** como aqueles em sistemas de Aprendizado de Máquina.
Isso, somado ao simples fato que Python é a principal linguagem para **Data Science**, Machine Learning e especialmente Deep Learning, faz do FastAPI uma ótima escolha para APIs web e aplicações com Data Science / Machine Learning (entre muitas outras). Isso, somado ao simples fato que Python é a principal linguagem para **Data Science**, Aprendizado de Máquina e especialmente Deep Learning, faz do FastAPI uma ótima escolha para APIs web e aplicações com Data Science / Aprendizado de Máquina (entre muitas outras).
Para ver como alcançar esse paralelismo em produção veja a seção sobre [Deployment](deployment/index.md){.internal-link target=_blank}. Para ver como alcançar esse paralelismo em produção veja a seção sobre [Implantação](deployment/index.md){.internal-link target=_blank}.
## `async` e `await` ## `async` e `await` { #async-and-await }
Versões modernas do Python têm um modo muito intuitivo para definir código assíncrono. Isso faz parecer do mesmo jeito do código normal "sequencial" e fazer a "espera" para você nos momentos certos. Versões modernas do Python têm um modo muito intuitivo para definir código assíncrono. Isso faz parecer do mesmo jeito do código normal "sequencial" e fazer a "espera" para você nos momentos certos.
@ -274,7 +310,7 @@ Quando tem uma operação que exigirá espera antes de dar os resultados e tem s
burgers = await get_burgers(2) burgers = await get_burgers(2)
``` ```
A chave aqui é o `await`. Ele diz ao Python que ele tem que esperar por `get_burgers(2)` finalizar suas coisas 🕙 antes de armazenar os resultados em `burgers`. Com isso, o Python saberá que ele pode ir e fazer outras coisas 🔀 ⏯ nesse meio tempo (como receber outra requisição). A chave aqui é o `await`. Ele diz ao Python que ele tem que esperar por `get_burgers(2)` finalizar suas coisas 🕙 antes de armazenar os resultados em `burgers`. Com isso, o Python saberá que ele pode ir e fazer outras coisas 🔀 ⏯ nesse meio tempo (como receber outra requisição).
Para o `await` funcionar, tem que estar dentro de uma função que suporte essa assincronicidade. Para fazer isso, apenas declare a função com `async def`: Para o `await` funcionar, tem que estar dentro de uma função que suporte essa assincronicidade. Para fazer isso, apenas declare a função com `async def`:
@ -306,18 +342,18 @@ burgers = get_burgers(2)
Então, se você está usando uma biblioteca que diz que você pode chamá-la com `await`, você precisa criar as *funções de operação de rota* com `async def`, como em: Então, se você está usando uma biblioteca que diz que você pode chamá-la com `await`, você precisa criar as *funções de operação de rota* com `async def`, como em:
```Python hl_lines="2 3" ```Python hl_lines="2-3"
@app.get('/burgers') @app.get('/burgers')
async def read_burgers(): async def read_burgers():
burgers = await get_burgers(2) burgers = await get_burgers(2)
return burgers return burgers
``` ```
### Mais detalhes técnicos ### Mais detalhes técnicos { #more-technical-details }
Você deve ter observado que `await` pode ser usado somente dentro de funções definidas com `async def`. Você deve ter observado que `await` pode ser usado somente dentro de funções definidas com `async def`.
Mas ao mesmo tempo, funções definidas com `async def` têm que ser "aguardadas". Então, funções com `async def` pdem ser chamadas somente dentro de funções definidas com `async def` também. Mas ao mesmo tempo, funções definidas com `async def` têm que ser "aguardadas". Então, funções com `async def` podem ser chamadas somente dentro de funções definidas com `async def` também.
Então, sobre o ovo e a galinha, como você chama a primeira função async? Então, sobre o ovo e a galinha, como você chama a primeira função async?
@ -325,7 +361,7 @@ Se você estivar trabalhando com **FastAPI** não terá que se preocupar com iss
Mas se você quiser usar `async` / `await` sem FastAPI, você também pode fazê-lo. Mas se você quiser usar `async` / `await` sem FastAPI, você também pode fazê-lo.
### Escreva seu próprio código assíncrono ### Escreva seu próprio código assíncrono { #write-your-own-async-code }
Starlette (e **FastAPI**) são baseados no <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a>, o que o torna compatível com ambos o <a href="https://docs.python.org/3/library/asyncio-task.html" class="external-link" target="_blank">asyncio</a> da biblioteca padrão do Python, e o <a href="https://trio.readthedocs.io/en/stable/" class="external-link" target="_blank">Trio</a>. Starlette (e **FastAPI**) são baseados no <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a>, o que o torna compatível com ambos o <a href="https://docs.python.org/3/library/asyncio-task.html" class="external-link" target="_blank">asyncio</a> da biblioteca padrão do Python, e o <a href="https://trio.readthedocs.io/en/stable/" class="external-link" target="_blank">Trio</a>.
@ -333,10 +369,9 @@ Em particular, você pode usar diretamente o <a href="https://anyio.readthedocs.
E até se você não estiver utilizando FastAPI, você também pode escrever suas próprias aplicações assíncronas com o <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a> por ser altamente compatível e ganhar seus benefícios (e.g. *concorrência estruturada*). E até se você não estiver utilizando FastAPI, você também pode escrever suas próprias aplicações assíncronas com o <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a> por ser altamente compatível e ganhar seus benefícios (e.g. *concorrência estruturada*).
Eu criei outra biblioteca em cima do AnyIO, como uma fina camada acima, para melhorar um pouco as anotações de tipo e obter melhor **autocompletar**, **erros de linha**, etc. Ela também possui uma introdução amigável e um tutorial para ajudar você a **entender** e escrever **seu próprio código async**: <a href="https://asyncer.tiangolo.com/" class="external-link" target="_blank">Asyncer</a>. Seria particularmente útil se você precisar **combinar código async com código regular** (bloqueador/síncrono). Eu criei outra biblioteca em cima do AnyIO, como uma fina camada acima, para melhorar um pouco as anotações de tipo e obter melhor **preenchimento automático**, **erros inline**, etc. Ela também possui uma introdução amigável e um tutorial para ajudar você a **entender** e escrever **seu próprio código async**: <a href="https://asyncer.tiangolo.com/" class="external-link" target="_blank">Asyncer</a>. Seria particularmente útil se você precisar **combinar código async com código regular** (bloqueador/síncrono).
### Outras formas de código assíncrono { #other-forms-of-asynchronous-code }
### Outras formas de código assíncrono
Esse estilo de usar `async` e `await` é relativamente novo na linguagem. Esse estilo de usar `async` e `await` é relativamente novo na linguagem.
@ -346,17 +381,17 @@ Essa mesma sintaxe (ou quase a mesma) foi também incluída recentemente em vers
Mas antes disso, controlar código assíncrono era bem mais complexo e difícil. Mas antes disso, controlar código assíncrono era bem mais complexo e difícil.
Nas versões anteriores do Python, você poderia utilizar threads ou <a href="http://www.gevent.org/" class="external-link" target="_blank">Gevent</a>. Mas o código é bem mais complexo de entender, debugar, e pensar sobre. Nas versões anteriores do Python, você poderia utilizar threads ou <a href="https://www.gevent.org/" class="external-link" target="_blank">Gevent</a>. Mas o código é bem mais complexo de entender, debugar, e pensar sobre.
Nas versões anteriores do NodeJS / Navegador JavaScript, você utilizaria "callbacks". O que leva ao "inferno do callback". Nas versões anteriores do NodeJS / Navegador JavaScript, você utilizaria "callbacks". O que leva ao "inferno do callback".
## Corrotinas ## Corrotinas { #coroutines }
**Corrotina** é apenas um jeito bonitinho para a coisa que é retornada de uma função `async def`. O Python sabe que é algo como uma função, que pode começar e que vai terminar em algum ponto, mas que pode ser pausada ⏸ internamente também, sempre que tiver um `await` dentro dela. **Corrotina** é apenas um jeito bonitinho para a coisa que é retornada de uma função `async def`. O Python sabe que é algo como uma função, que pode começar e que vai terminar em algum ponto, mas que pode ser pausada ⏸ internamente também, sempre que tiver um `await` dentro dela.
Mas toda essa funcionalidade de código assíncrono com `async` e `await` é muitas vezes resumida como usando "corrotinas". É comparável ao principal recurso chave do Go, a "Gorrotina". Mas toda essa funcionalidade de código assíncrono com `async` e `await` é muitas vezes resumida como usando "corrotinas". É comparável ao principal recurso chave do Go, a "Gorrotina".
## Conclusão ## Conclusão { #conclusion }
Vamos ver a mesma frase de cima: Vamos ver a mesma frase de cima:
@ -366,9 +401,9 @@ Isso pode fazer mais sentido agora. ✨
Tudo isso é o que empodera o FastAPI (através do Starlette) e que o faz ter uma performance tão impressionante. Tudo isso é o que empodera o FastAPI (através do Starlette) e que o faz ter uma performance tão impressionante.
## Detalhes muito técnicos ## Detalhes muito técnicos { #very-technical-details }
/// warning /// warning | Atenção
Você pode provavelmente pular isso. Você pode provavelmente pular isso.
@ -378,23 +413,23 @@ Se você tem certo conhecimento técnico (corrotinas, threads, blocking etc) e e
/// ///
### Funções de operação de rota ### Funções de operação de rota { #path-operation-functions }
Quando você declara uma *função de operação de rota* com `def` normal ao invés de `async def`, ela é rodada em uma threadpool externa que é então aguardada, ao invés de ser chamada diretamente (já que ela bloquearia o servidor). Quando você declara uma *função de operação de rota* com `def` normal ao invés de `async def`, ela é rodada em uma threadpool externa que é então aguardada, ao invés de ser chamada diretamente (já que ela bloquearia o servidor).
Se você está chegando de outro framework assíncrono que não funciona como descrito acima e você está acostumado a definir *funções de operação de rota* triviais somente de computação com simples `def` para ter um mínimo ganho de performance (cerca de 100 nanosegundos), por favor observe que no **FastAPI** o efeito pode ser bem o oposto. Nesses casos, é melhor usar `async def` a menos que suas *funções de operação de rota* utilizem código que performe bloqueamento <abbr title="Input/Output: disco lendo ou escrevendo, comunicações de rede.">IO</abbr>. Se você está chegando de outro framework assíncrono que não funciona como descrito acima e você está acostumado a definir *funções de operação de rota* triviais somente de computação com simples `def` para ter um mínimo ganho de performance (cerca de 100 nanosegundos), por favor observe que no **FastAPI** o efeito pode ser bem o oposto. Nesses casos, é melhor usar `async def` a menos que suas *funções de operação de rota* utilizem código que performe bloqueamento <abbr title="Input/Output Entrada e Saída: leitura ou escrita no disco, comunicações de rede.">I/O</abbr>.
Ainda, em ambas as situações, as chances são que o **FastAPI** [ainda será mais rápido](index.md#performance){.internal-link target=_blank} do que (ou ao menos comparável a) seu framework anterior. Ainda, em ambas as situações, as chances são que o **FastAPI** [ainda será mais rápido](index.md#performance){.internal-link target=_blank} do que (ou ao menos comparável a) seu framework anterior.
### Dependências ### Dependências { #dependencies }
O mesmo se aplica para as [dependências](tutorial/dependencies/index.md){.internal-link target=_blank}. Se uma dependência tem as funções com padrão `def` ao invés de `async def`, ela é rodada no threadpool externo. O mesmo se aplica para as [dependências](tutorial/dependencies/index.md){.internal-link target=_blank}. Se uma dependência tem as funções com padrão `def` ao invés de `async def`, ela é rodada no threadpool externo.
### Sub-dependências ### Sub-dependências { #sub-dependencies }
Você pode ter múltiplas dependências e [sub-dependências](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} requisitando uma à outra (como parâmetros de definições de funções), algumas delas podem ser criadas com `async def` e algumas com `def` normal. Isso ainda funcionaria, e aquelas criadas com `def` normal seriam chamadas em uma thread externa (do threadpool) ao invés de serem "aguardadas". Você pode ter múltiplas dependências e [sub-dependências](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} requisitando uma à outra (como parâmetros de definições de funções), algumas delas podem ser criadas com `async def` e algumas com `def` normal. Isso ainda funcionaria, e aquelas criadas com `def` normal seriam chamadas em uma thread externa (do threadpool) ao invés de serem "aguardadas".
### Outras funções de utilidade ### Outras funções de utilidade { #other-utility-functions }
Qualquer outra função de utilidade que você chame diretamente pode ser criada com `def` normal ou `async def` e o FastAPI não irá afetar o modo como você a chama. Qualquer outra função de utilidade que você chame diretamente pode ser criada com `def` normal ou `async def` e o FastAPI não irá afetar o modo como você a chama.

View File

@ -1,10 +1,10 @@
# Comparações # Benchmarks { #benchmarks }
As comparações independentes da TechEmpower mostram as aplicações **FastAPI** rodando com Uvicorn como <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">um dos _frameworks_ Python mais rápidos disponíveis</a>, somente atrás dos próprios Starlette e Uvicorn (utilizados internamente pelo FastAPI). (*) Benchmarks independentes da TechEmpower mostram as aplicações **FastAPI** rodando com Uvicorn como <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">um dos frameworks Python mais rápidos disponíveis</a>, somente atrás dos próprios Starlette e Uvicorn (utilizados internamente pelo FastAPI).
Mas quando se checa _benchmarks_ e comparações você deveria ter o seguinte em mente. Mas quando se checa _benchmarks_ e comparações você deveria ter o seguinte em mente.
## Comparações e velocidade ## Benchmarks e velocidade { #benchmarks-and-speed }
Ao verificar os _benchmarks_, é comum observar algumas ferramentas de diferentes tipos comparadas como equivalentes. Ao verificar os _benchmarks_, é comum observar algumas ferramentas de diferentes tipos comparadas como equivalentes.

View File

@ -1,13 +1,16 @@
# Implantar FastAPI em provedores de nuvem # Implantar FastAPI em provedores de nuvem { #deploy-fastapi-on-cloud-providers }
Você pode usar praticamente **qualquer provedor de nuvem** para implantar seu aplicativo FastAPI. Você pode usar praticamente **qualquer provedor de nuvem** para implantar seu aplicativo FastAPI.
Na maioria dos casos, os principais provedores de nuvem têm guias para implantar o FastAPI com eles. Na maioria dos casos, os principais provedores de nuvem têm tutoriais para implantar o FastAPI com eles.
## Provedores de Nuvem - Patrocinadores ## Provedores de Nuvem - Patrocinadores { #cloud-providers-sponsors }
Alguns provedores de nuvem ✨ [**patrocinam o FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, o que garante o **desenvolvimento** contínuo e saudável do FastAPI e seu **ecossistema**. Alguns provedores de nuvem ✨ [**patrocinam o FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, o que garante o **desenvolvimento** contínuo e saudável do FastAPI e seu **ecossistema**.
E isso mostra seu verdadeiro comprometimento com o FastAPI e sua **comunidade** (você), pois eles não querem apenas fornecer a você um **bom serviço**, mas também querem ter certeza de que você tenha uma **estrutura boa e saudável**, o FastAPI. 🙇 E isso mostra seu verdadeiro comprometimento com o FastAPI e sua **comunidade** (você), pois eles não querem apenas fornecer a você um **bom serviço**, mas também querem ter certeza de que você tenha um **framework bom e saudável**, o FastAPI. 🙇
Talvez você queira experimentar os serviços deles e seguir os guias. Talvez você queira experimentar os serviços deles e seguir os tutoriais:
* <a href="https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi" class="external-link" target="_blank">Render</a>
* <a href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi" class="external-link" target="_blank">Railway</a>

View File

@ -1,4 +1,4 @@
# Conceitos de Implantações # Conceitos de Implantações { #deployments-concepts }
Ao implantar um aplicativo **FastAPI**, ou na verdade, qualquer tipo de API da web, há vários conceitos com os quais você provavelmente se importa e, usando-os, você pode encontrar a maneira **mais apropriada** de **implantar seu aplicativo**. Ao implantar um aplicativo **FastAPI**, ou na verdade, qualquer tipo de API da web, há vários conceitos com os quais você provavelmente se importa e, usando-os, você pode encontrar a maneira **mais apropriada** de **implantar seu aplicativo**.
@ -23,7 +23,7 @@ Nos próximos capítulos, darei a você mais **receitas concretas** para implant
Mas por enquanto, vamos verificar essas importantes **ideias conceituais**. Esses conceitos também se aplicam a qualquer outro tipo de API da web. 💡 Mas por enquanto, vamos verificar essas importantes **ideias conceituais**. Esses conceitos também se aplicam a qualquer outro tipo de API da web. 💡
## Segurança - HTTPS ## Segurança - HTTPS { #security-https }
No [capítulo anterior sobre HTTPS](https.md){.internal-link target=_blank} aprendemos como o HTTPS fornece criptografia para sua API. No [capítulo anterior sobre HTTPS](https.md){.internal-link target=_blank} aprendemos como o HTTPS fornece criptografia para sua API.
@ -31,7 +31,7 @@ Também vimos que o HTTPS normalmente é fornecido por um componente **externo**
E tem que haver algo responsável por **renovar os certificados HTTPS**, pode ser o mesmo componente ou pode ser algo diferente. E tem que haver algo responsável por **renovar os certificados HTTPS**, pode ser o mesmo componente ou pode ser algo diferente.
### Ferramentas de exemplo para HTTPS ### Ferramentas de exemplo para HTTPS { #example-tools-for-https }
Algumas das ferramentas que você pode usar como um proxy de terminação TLS são: Algumas das ferramentas que você pode usar como um proxy de terminação TLS são:
@ -55,11 +55,11 @@ Mostrarei alguns exemplos concretos nos próximos capítulos.
Os próximos conceitos a serem considerados são todos sobre o programa que executa sua API real (por exemplo, Uvicorn). Os próximos conceitos a serem considerados são todos sobre o programa que executa sua API real (por exemplo, Uvicorn).
## Programa e Processo ## Programa e Processo { #program-and-process }
Falaremos muito sobre o "**processo**" em execução, então é útil ter clareza sobre o que ele significa e qual é a diferença com a palavra "**programa**". Falaremos muito sobre o "**processo**" em execução, então é útil ter clareza sobre o que ele significa e qual é a diferença com a palavra "**programa**".
### O que é um Programa ### O que é um Programa { #what-is-a-program }
A palavra **programa** é comumente usada para descrever muitas coisas: A palavra **programa** é comumente usada para descrever muitas coisas:
@ -67,7 +67,7 @@ A palavra **programa** é comumente usada para descrever muitas coisas:
* O **arquivo** que pode ser **executado** pelo sistema operacional, por exemplo: `python`, `python.exe` ou `uvicorn`. * O **arquivo** que pode ser **executado** pelo sistema operacional, por exemplo: `python`, `python.exe` ou `uvicorn`.
* Um programa específico enquanto está **em execução** no sistema operacional, usando a CPU e armazenando coisas na memória. Isso também é chamado de **processo**. * Um programa específico enquanto está **em execução** no sistema operacional, usando a CPU e armazenando coisas na memória. Isso também é chamado de **processo**.
### O que é um Processo ### O que é um Processo { #what-is-a-process }
A palavra **processo** normalmente é usada de forma mais específica, referindo-se apenas ao que está sendo executado no sistema operacional (como no último ponto acima): A palavra **processo** normalmente é usada de forma mais específica, referindo-se apenas ao que está sendo executado no sistema operacional (como no último ponto acima):
@ -88,11 +88,11 @@ E, por exemplo, você provavelmente verá que há vários processos executando o
Agora que sabemos a diferença entre os termos **processo** e **programa**, vamos continuar falando sobre implantações. Agora que sabemos a diferença entre os termos **processo** e **programa**, vamos continuar falando sobre implantações.
## Executando na inicialização ## Executando na inicialização { #running-on-startup }
Na maioria dos casos, quando você cria uma API web, você quer que ela esteja **sempre em execução**, ininterrupta, para que seus clientes possam sempre acessá-la. Isso é claro, a menos que você tenha um motivo específico para querer que ela seja executada somente em certas situações, mas na maioria das vezes você quer que ela esteja constantemente em execução e **disponível**. Na maioria dos casos, quando você cria uma API web, você quer que ela esteja **sempre em execução**, ininterrupta, para que seus clientes possam sempre acessá-la. Isso é claro, a menos que você tenha um motivo específico para querer que ela seja executada somente em certas situações, mas na maioria das vezes você quer que ela esteja constantemente em execução e **disponível**.
### Em um servidor remoto ### Em um servidor remoto { #in-a-remote-server }
Ao configurar um servidor remoto (um servidor em nuvem, uma máquina virtual, etc.), a coisa mais simples que você pode fazer é usar `fastapi run` (que usa Uvicorn) ou algo semelhante, manualmente, da mesma forma que você faz ao desenvolver localmente. Ao configurar um servidor remoto (um servidor em nuvem, uma máquina virtual, etc.), a coisa mais simples que você pode fazer é usar `fastapi run` (que usa Uvicorn) ou algo semelhante, manualmente, da mesma forma que você faz ao desenvolver localmente.
@ -102,15 +102,15 @@ Mas se sua conexão com o servidor for perdida, o **processo em execução** pro
E se o servidor for reiniciado (por exemplo, após atualizações ou migrações do provedor de nuvem), você provavelmente **não notará**. E por causa disso, você nem saberá que precisa reiniciar o processo manualmente. Então, sua API simplesmente permanecerá inativa. 😱 E se o servidor for reiniciado (por exemplo, após atualizações ou migrações do provedor de nuvem), você provavelmente **não notará**. E por causa disso, você nem saberá que precisa reiniciar o processo manualmente. Então, sua API simplesmente permanecerá inativa. 😱
### Executar automaticamente na inicialização ### Executar automaticamente na inicialização { #run-automatically-on-startup }
Em geral, você provavelmente desejará que o programa do servidor (por exemplo, Uvicorn) seja iniciado automaticamente na inicialização do servidor e, sem precisar de nenhuma **intervenção humana**, tenha um processo sempre em execução com sua API (por exemplo, Uvicorn executando seu aplicativo FastAPI). Em geral, você provavelmente desejará que o programa do servidor (por exemplo, Uvicorn) seja iniciado automaticamente na inicialização do servidor e, sem precisar de nenhuma **intervenção humana**, tenha um processo sempre em execução com sua API (por exemplo, Uvicorn executando seu aplicativo FastAPI).
### Programa separado ### Programa separado { #separate-program }
Para conseguir isso, você normalmente terá um **programa separado** que garantiria que seu aplicativo fosse executado na inicialização. E em muitos casos, ele também garantiria que outros componentes ou aplicativos também fossem executados, por exemplo, um banco de dados. Para conseguir isso, você normalmente terá um **programa separado** que garantiria que seu aplicativo fosse executado na inicialização. E em muitos casos, ele também garantiria que outros componentes ou aplicativos também fossem executados, por exemplo, um banco de dados.
### Ferramentas de exemplo para executar na inicialização ### Ferramentas de exemplo para executar na inicialização { #example-tools-to-run-at-startup }
Alguns exemplos de ferramentas que podem fazer esse trabalho são: Alguns exemplos de ferramentas que podem fazer esse trabalho são:
@ -125,29 +125,29 @@ Alguns exemplos de ferramentas que podem fazer esse trabalho são:
Darei exemplos mais concretos nos próximos capítulos. Darei exemplos mais concretos nos próximos capítulos.
## Reinicializações ## Reinicializações { #restarts }
Semelhante a garantir que seu aplicativo seja executado na inicialização, você provavelmente também deseja garantir que ele seja **reiniciado** após falhas. Semelhante a garantir que seu aplicativo seja executado na inicialização, você provavelmente também deseja garantir que ele seja **reiniciado** após falhas.
### Nós cometemos erros ### Nós cometemos erros { #we-make-mistakes }
Nós, como humanos, cometemos **erros** o tempo todo. O software quase *sempre* tem **bugs** escondidos em lugares diferentes. 🐛 Nós, como humanos, cometemos **erros** o tempo todo. O software quase *sempre* tem **bugs** escondidos em lugares diferentes. 🐛
E nós, como desenvolvedores, continuamos aprimorando o código à medida que encontramos esses bugs e implementamos novos recursos (possivelmente adicionando novos bugs também 😅). E nós, como desenvolvedores, continuamos aprimorando o código à medida que encontramos esses bugs e implementamos novos recursos (possivelmente adicionando novos bugs também 😅).
### Pequenos erros são tratados automaticamente ### Pequenos erros são tratados automaticamente { #small-errors-automatically-handled }
Ao criar APIs da web com FastAPI, se houver um erro em nosso código, o FastAPI normalmente o conterá na única solicitação que acionou o erro. 🛡 Ao criar APIs da web com FastAPI, se houver um erro em nosso código, o FastAPI normalmente o conterá na única solicitação que acionou o erro. 🛡
O cliente receberá um **Erro Interno do Servidor 500** para essa solicitação, mas o aplicativo continuará funcionando para as próximas solicitações em vez de travar completamente. O cliente receberá um **Erro Interno do Servidor 500** para essa solicitação, mas o aplicativo continuará funcionando para as próximas solicitações em vez de travar completamente.
### Erros maiores - Travamentos ### Erros maiores - Travamentos { #bigger-errors-crashes }
No entanto, pode haver casos em que escrevemos algum código que **trava todo o aplicativo**, fazendo com que o Uvicorn e o Python travem. 💥 No entanto, pode haver casos em que escrevemos algum código que **trava todo o aplicativo**, fazendo com que o Uvicorn e o Python travem. 💥
E ainda assim, você provavelmente não gostaria que o aplicativo permanecesse inativo porque houve um erro em um lugar, você provavelmente quer que ele **continue em execução** pelo menos para as *operações de caminho* que não estão quebradas. E ainda assim, você provavelmente não gostaria que o aplicativo permanecesse inativo porque houve um erro em um lugar, você provavelmente quer que ele **continue em execução** pelo menos para as *operações de caminho* que não estão quebradas.
### Reiniciar após falha ### Reiniciar após falha { #restart-after-crash }
Mas nos casos com erros realmente graves que travam o **processo** em execução, você vai querer um componente externo que seja responsável por **reiniciar** o processo, pelo menos algumas vezes... Mas nos casos com erros realmente graves que travam o **processo** em execução, você vai querer um componente externo que seja responsável por **reiniciar** o processo, pelo menos algumas vezes...
@ -161,7 +161,7 @@ Então, vamos nos concentrar nos casos principais, onde ele pode travar completa
Você provavelmente gostaria de ter a coisa responsável por reiniciar seu aplicativo como um **componente externo**, porque a essa altura, o mesmo aplicativo com Uvicorn e Python já havia travado, então não há nada no mesmo código do mesmo aplicativo que possa fazer algo a respeito. Você provavelmente gostaria de ter a coisa responsável por reiniciar seu aplicativo como um **componente externo**, porque a essa altura, o mesmo aplicativo com Uvicorn e Python já havia travado, então não há nada no mesmo código do mesmo aplicativo que possa fazer algo a respeito.
### Ferramentas de exemplo para reiniciar automaticamente ### Ferramentas de exemplo para reiniciar automaticamente { #example-tools-to-restart-automatically }
Na maioria dos casos, a mesma ferramenta usada para **executar o programa na inicialização** também é usada para lidar com **reinicializações** automáticas. Na maioria dos casos, a mesma ferramenta usada para **executar o programa na inicialização** também é usada para lidar com **reinicializações** automáticas.
@ -176,19 +176,19 @@ Por exemplo, isso poderia ser resolvido por:
* Gerenciado internamente por um provedor de nuvem como parte de seus serviços * Gerenciado internamente por um provedor de nuvem como parte de seus serviços
* Outros... * Outros...
## Replicação - Processos e Memória ## Replicação - Processos e Memória { #replication-processes-and-memory }
Com um aplicativo FastAPI, usando um programa de servidor como o comando `fastapi` que executa o Uvicorn, executá-lo uma vez em **um processo** pode atender a vários clientes simultaneamente. Com um aplicativo FastAPI, usando um programa de servidor como o comando `fastapi` que executa o Uvicorn, executá-lo uma vez em **um processo** pode atender a vários clientes simultaneamente.
Mas em muitos casos, você desejará executar vários processos de trabalho ao mesmo tempo. Mas em muitos casos, você desejará executar vários processos de trabalho ao mesmo tempo.
### Processos Múltiplos - Trabalhadores ### Processos Múltiplos - Trabalhadores { #multiple-processes-workers }
Se você tiver mais clientes do que um único processo pode manipular (por exemplo, se a máquina virtual não for muito grande) e tiver **vários núcleos** na CPU do servidor, você poderá ter **vários processos** em execução com o mesmo aplicativo ao mesmo tempo e distribuir todas as solicitações entre eles. Se você tiver mais clientes do que um único processo pode manipular (por exemplo, se a máquina virtual não for muito grande) e tiver **vários núcleos** na CPU do servidor, você poderá ter **vários processos** em execução com o mesmo aplicativo ao mesmo tempo e distribuir todas as solicitações entre eles.
Quando você executa **vários processos** do mesmo programa de API, eles são comumente chamados de **trabalhadores**. Quando você executa **vários processos** do mesmo programa de API, eles são comumente chamados de **trabalhadores**.
### Processos do Trabalhador e Portas ### Processos do Trabalhador e Portas { #worker-processes-and-ports }
Lembra da documentação [Sobre HTTPS](https.md){.internal-link target=_blank} que diz que apenas um processo pode escutar em uma combinação de porta e endereço IP em um servidor? Lembra da documentação [Sobre HTTPS](https.md){.internal-link target=_blank} que diz que apenas um processo pode escutar em uma combinação de porta e endereço IP em um servidor?
@ -196,19 +196,19 @@ Isso ainda é verdade.
Então, para poder ter **vários processos** ao mesmo tempo, tem que haver um **único processo escutando em uma porta** que então transmite a comunicação para cada processo de trabalho de alguma forma. Então, para poder ter **vários processos** ao mesmo tempo, tem que haver um **único processo escutando em uma porta** que então transmite a comunicação para cada processo de trabalho de alguma forma.
### Memória por Processo ### Memória por Processo { #memory-per-process }
Agora, quando o programa carrega coisas na memória, por exemplo, um modelo de aprendizado de máquina em uma variável, ou o conteúdo de um arquivo grande em uma variável, tudo isso **consome um pouco da memória (RAM)** do servidor. Agora, quando o programa carrega coisas na memória, por exemplo, um modelo de aprendizado de máquina em uma variável, ou o conteúdo de um arquivo grande em uma variável, tudo isso **consome um pouco da memória (RAM)** do servidor.
E vários processos normalmente **não compartilham nenhuma memória**. Isso significa que cada processo em execução tem suas próprias coisas, variáveis e memória. E se você estiver consumindo uma grande quantidade de memória em seu código, **cada processo** consumirá uma quantidade equivalente de memória. E vários processos normalmente **não compartilham nenhuma memória**. Isso significa que cada processo em execução tem suas próprias coisas, variáveis e memória. E se você estiver consumindo uma grande quantidade de memória em seu código, **cada processo** consumirá uma quantidade equivalente de memória.
### Memória do servidor ### Memória do servidor { #server-memory }
Por exemplo, se seu código carrega um modelo de Machine Learning com **1 GB de tamanho**, quando você executa um processo com sua API, ele consumirá pelo menos 1 GB de RAM. E se você iniciar **4 processos** (4 trabalhadores), cada um consumirá 1 GB de RAM. Então, no total, sua API consumirá **4 GB de RAM**. Por exemplo, se seu código carrega um modelo de Machine Learning com **1 GB de tamanho**, quando você executa um processo com sua API, ele consumirá pelo menos 1 GB de RAM. E se você iniciar **4 processos** (4 trabalhadores), cada um consumirá 1 GB de RAM. Então, no total, sua API consumirá **4 GB de RAM**.
E se o seu servidor remoto ou máquina virtual tiver apenas 3 GB de RAM, tentar carregar mais de 4 GB de RAM causará problemas. 🚨 E se o seu servidor remoto ou máquina virtual tiver apenas 3 GB de RAM, tentar carregar mais de 4 GB de RAM causará problemas. 🚨
### Processos Múltiplos - Um Exemplo ### Processos Múltiplos - Um Exemplo { #multiple-processes-an-example }
Neste exemplo, há um **Processo Gerenciador** que inicia e controla dois **Processos de Trabalhadores**. Neste exemplo, há um **Processo Gerenciador** que inicia e controla dois **Processos de Trabalhadores**.
@ -224,7 +224,7 @@ Um detalhe interessante é que a porcentagem da **CPU usada** por cada processo
Se você tiver uma API que faz uma quantidade comparável de cálculos todas as vezes e tiver muitos clientes, então a **utilização da CPU** provavelmente *também será estável* (em vez de ficar constantemente subindo e descendo rapidamente). Se você tiver uma API que faz uma quantidade comparável de cálculos todas as vezes e tiver muitos clientes, então a **utilização da CPU** provavelmente *também será estável* (em vez de ficar constantemente subindo e descendo rapidamente).
### Exemplos de ferramentas e estratégias de replicação ### Exemplos de ferramentas e estratégias de replicação { #examples-of-replication-tools-and-strategies }
Pode haver várias abordagens para conseguir isso, e falarei mais sobre estratégias específicas nos próximos capítulos, por exemplo, ao falar sobre Docker e contêineres. Pode haver várias abordagens para conseguir isso, e falarei mais sobre estratégias específicas nos próximos capítulos, por exemplo, ao falar sobre Docker e contêineres.
@ -247,7 +247,7 @@ Falarei mais sobre imagens de contêiner, Docker, Kubernetes, etc. em um capítu
/// ///
## Etapas anteriores antes de começar ## Etapas anteriores antes de começar { #previous-steps-before-starting }
Há muitos casos em que você deseja executar algumas etapas **antes de iniciar** sua aplicação. Há muitos casos em que você deseja executar algumas etapas **antes de iniciar** sua aplicação.
@ -269,7 +269,7 @@ Nesse caso, você não precisaria se preocupar com nada disso. 🤷
/// ///
### Exemplos de estratégias de etapas anteriores ### Exemplos de estratégias de etapas anteriores { #examples-of-previous-steps-strategies }
Isso **dependerá muito** da maneira como você **implanta seu sistema** e provavelmente estará conectado à maneira como você inicia programas, lida com reinicializações, etc. Isso **dependerá muito** da maneira como você **implanta seu sistema** e provavelmente estará conectado à maneira como você inicia programas, lida com reinicializações, etc.
@ -285,7 +285,7 @@ Darei exemplos mais concretos de como fazer isso com contêineres em um capítul
/// ///
## Utilização de recursos ## Utilização de recursos { #resource-utilization }
Seu(s) servidor(es) é(são) um **recurso** que você pode consumir ou **utilizar**, com seus programas, o tempo de computação nas CPUs e a memória RAM disponível. Seu(s) servidor(es) é(são) um **recurso** que você pode consumir ou **utilizar**, com seus programas, o tempo de computação nas CPUs e a memória RAM disponível.
@ -305,7 +305,7 @@ Você poderia colocar um **número arbitrário** para atingir, por exemplo, algo
Você pode usar ferramentas simples como `htop` para ver a CPU e a RAM usadas no seu servidor ou a quantidade usada por cada processo. Ou você pode usar ferramentas de monitoramento mais complexas, que podem ser distribuídas entre servidores, etc. Você pode usar ferramentas simples como `htop` para ver a CPU e a RAM usadas no seu servidor ou a quantidade usada por cada processo. Ou você pode usar ferramentas de monitoramento mais complexas, que podem ser distribuídas entre servidores, etc.
## Recapitular ## Recapitular { #recap }
Você leu aqui alguns dos principais conceitos que provavelmente precisa ter em mente ao decidir como implantar seu aplicativo: Você leu aqui alguns dos principais conceitos que provavelmente precisa ter em mente ao decidir como implantar seu aplicativo:

View File

@ -1,4 +1,4 @@
# FastAPI em contêineres - Docker # FastAPI em contêineres - Docker { #fastapi-in-containers-docker }
Ao fazer o deploy de aplicações FastAPI uma abordagem comum é construir uma **imagem de contêiner Linux**. Isso normalmente é feito usando o <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a>. Você pode a partir disso fazer o deploy dessa imagem de algumas maneiras. Ao fazer o deploy de aplicações FastAPI uma abordagem comum é construir uma **imagem de contêiner Linux**. Isso normalmente é feito usando o <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a>. Você pode a partir disso fazer o deploy dessa imagem de algumas maneiras.
@ -6,7 +6,7 @@ Usando contêineres Linux você tem diversas vantagens incluindo **segurança**,
/// tip | Dica /// tip | Dica
Está com pressa e já sabe dessas coisas? Pode ir direto para [`Dockerfile` abaixo 👇](#construindo-uma-imagem-docker-para-fastapi). Está com pressa e já sabe dessas coisas? Pode ir direto para o [`Dockerfile` abaixo 👇](#build-a-docker-image-for-fastapi).
/// ///
@ -24,25 +24,25 @@ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
COPY ./app /code/app COPY ./app /code/app
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] CMD ["fastapi", "run", "app/main.py", "--port", "80"]
# If running behind a proxy like Nginx or Traefik add --proxy-headers # Se estiver executando atrás de um proxy como Nginx ou Traefik, adicione --proxy-headers
# CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80", "--proxy-headers"] # CMD ["fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"]
``` ```
</details> </details>
## O que é um Contêiner ## O que é um Contêiner { #what-is-a-container }
Contêineres (especificamente contêineres Linux) são um jeito muito **leve** de empacotar aplicações contendo todas as dependências e arquivos necessários enquanto os mantém isolados de outros contêineres (outras aplicações ou componentes) no mesmo sistema. Contêineres (principalmente contêineres Linux) são um jeito muito **leve** de empacotar aplicações contendo todas as dependências e arquivos necessários enquanto os mantém isolados de outros contêineres (outras aplicações ou componentes) no mesmo sistema.
Contêineres Linux rodam usando o mesmo kernel Linux do hospedeiro (máquina, máquina virtual, servidor na nuvem, etc). Isso simplesmente significa que eles são muito leves (comparados com máquinas virtuais emulando um sistema operacional completo). Contêineres Linux rodam usando o mesmo kernel Linux do hospedeiro (máquina, máquina virtual, servidor na nuvem, etc). Isso simplesmente significa que eles são muito leves (comparados com máquinas virtuais emulando um sistema operacional completo).
Dessa forma, contêineres consomem **poucos recursos**, uma quantidade comparável com rodar os processos diretamente (uma máquina virtual consumiria muito mais). Dessa forma, contêineres consomem **poucos recursos**, uma quantidade comparável com rodar os processos diretamente (uma máquina virtual consumiria muito mais).
Contêineres também possuem seus próprios processos (comumente um único processo), sistema de arquivos e rede **isolados** simplificando deploy, segurança, desenvolvimento, etc. Contêineres também possuem seus próprios processos em execução (comumente **um único processo**), sistema de arquivos e rede **isolados**, simplificando deploy, segurança, desenvolvimento, etc.
## O que é uma Imagem de Contêiner ## O que é uma Imagem de Contêiner { #what-is-a-container-image }
Um **contêiner** roda a partir de uma **imagem de contêiner**. Um **contêiner** roda a partir de uma **imagem de contêiner**.
@ -56,7 +56,7 @@ Uma imagem de contêiner é comparável ao arquivo de **programa** e seus conte
E o **contêiner** em si (em contraste à **imagem de contêiner**) é a própria instância da imagem rodando, comparável a um **processo**. Na verdade, um contêiner está rodando somente quando há um **processo rodando** (e normalmente é somente um processo). O contêiner finaliza quando não há um processo rodando nele. E o **contêiner** em si (em contraste à **imagem de contêiner**) é a própria instância da imagem rodando, comparável a um **processo**. Na verdade, um contêiner está rodando somente quando há um **processo rodando** (e normalmente é somente um processo). O contêiner finaliza quando não há um processo rodando nele.
## Imagens de contêiner ## Imagens de contêiner { #container-images }
Docker tem sido uma das principais ferramentas para criar e gerenciar **imagens de contêiner** e **contêineres**. Docker tem sido uma das principais ferramentas para criar e gerenciar **imagens de contêiner** e **contêineres**.
@ -71,15 +71,15 @@ E existe muitas outras imagens para diferentes coisas, como bancos de dados, por
* <a href="https://hub.docker.com/_/mongo" class="external-link" target="_blank">MongoDB</a> * <a href="https://hub.docker.com/_/mongo" class="external-link" target="_blank">MongoDB</a>
* <a href="https://hub.docker.com/_/redis" class="external-link" target="_blank">Redis</a>, etc. * <a href="https://hub.docker.com/_/redis" class="external-link" target="_blank">Redis</a>, etc.
Usando imagens de contêiner pré-prontas é muito fácil **combinar** e usar diferentes ferramentas. Por exemplo, para testar um novo banco de dados. Em muitos casos, você pode usar as **imagens oficiais** precisando somente de variáveis de ambiente para configurá-las. Usando imagens de contêiner pré-prontas é muito fácil **combinar** e usar diferentes ferramentas. Por exemplo, para testar um novo banco de dados. Em muitos casos, você pode usar as **imagens oficiais**, precisando somente de variáveis de ambiente para configurá-las.
Dessa forma, em muitos casos você pode aprender sobre contêineres e Docker e re-usar essa experiência com diversos componentes e ferramentas. Dessa forma, em muitos casos você pode aprender sobre contêineres e Docker e reusar essa experiência com diversos componentes e ferramentas.
Então, você rodaria **vários contêineres** com coisas diferentes, como um banco de dados, uma aplicação Python, um servidor web com uma aplicação frontend React, e conectá-los juntos via sua rede interna. Então, você rodaria **vários contêineres** com coisas diferentes, como um banco de dados, uma aplicação Python, um servidor web com uma aplicação frontend React, e conectá-los juntos via sua rede interna.
Todos os sistemas de gerenciamento de contêineres (como Docker ou Kubernetes) possuem essas funcionalidades de rede integradas a eles. Todos os sistemas de gerenciamento de contêineres (como Docker ou Kubernetes) possuem essas funcionalidades de rede integradas a eles.
## Contêineres e Processos ## Contêineres e Processos { #containers-and-processes }
Uma **imagem de contêiner** normalmente inclui em seus metadados o programa padrão ou comando que deve ser executado quando o **contêiner** é iniciado e os parâmetros a serem passados para esse programa. Muito similar ao que seria se estivesse na linha de comando. Uma **imagem de contêiner** normalmente inclui em seus metadados o programa padrão ou comando que deve ser executado quando o **contêiner** é iniciado e os parâmetros a serem passados para esse programa. Muito similar ao que seria se estivesse na linha de comando.
@ -91,11 +91,11 @@ Um contêiner normalmente tem um **único processo**, mas também é possível i
Mas não é possível ter um contêiner rodando sem **pelo menos um processo rodando**. Se o processo principal parar, o contêiner também para. Mas não é possível ter um contêiner rodando sem **pelo menos um processo rodando**. Se o processo principal parar, o contêiner também para.
## Construindo uma Imagem Docker para FastAPI ## Construir uma Imagem Docker para FastAPI { #build-a-docker-image-for-fastapi }
Okay, vamos construir algo agora! 🚀 Okay, vamos construir algo agora! 🚀
Eu vou mostrar como construir uma **imagem Docker** para FastAPI **do zero**, baseado na **imagem oficial do Python**. Eu vou mostrar como construir uma **imagem Docker** para FastAPI **do zero**, baseada na imagem **oficial do Python**.
Isso é o que você quer fazer na **maioria dos casos**, por exemplo: Isso é o que você quer fazer na **maioria dos casos**, por exemplo:
@ -103,22 +103,21 @@ Isso é o que você quer fazer na **maioria dos casos**, por exemplo:
* Quando rodando em uma **Raspberry Pi** * Quando rodando em uma **Raspberry Pi**
* Usando um serviço em nuvem que irá rodar uma imagem de contêiner para você, etc. * Usando um serviço em nuvem que irá rodar uma imagem de contêiner para você, etc.
### O Pacote Requirements ### Requisitos de Pacotes { #package-requirements }
Você normalmente teria os **requisitos do pacote** para sua aplicação em algum arquivo. Você normalmente teria os **requisitos de pacotes** da sua aplicação em algum arquivo.
Isso pode depender principalmente da ferramenta que você usa para **instalar** esses requisitos. Isso pode depender principalmente da ferramenta que você usa para **instalar** esses requisitos.
O caminho mais comum de fazer isso é ter um arquivo `requirements.txt` com os nomes dos pacotes e suas versões, um por linha. A forma mais comum de fazer isso é ter um arquivo `requirements.txt` com os nomes dos pacotes e suas versões, um por linha.
Você, naturalmente, usaria as mesmas ideias que você leu em [Sobre Versões do FastAPI](versions.md){.internal-link target=_blank} para definir os intervalos de versões. Você, naturalmente, usaria as mesmas ideias que você leu em [Sobre versões do FastAPI](versions.md){.internal-link target=_blank} para definir os intervalos de versões.
Por exemplo, seu `requirements.txt` poderia parecer com: Por exemplo, seu `requirements.txt` poderia parecer com:
``` ```
fastapi>=0.68.0,<0.69.0 fastapi[standard]>=0.113.0,<0.114.0
pydantic>=1.8.0,<2.0.0 pydantic>=2.7.0,<3.0.0
uvicorn>=0.15.0,<0.16.0
``` ```
E você normalmente instalaria essas dependências de pacote com `pip`, por exemplo: E você normalmente instalaria essas dependências de pacote com `pip`, por exemplo:
@ -128,27 +127,25 @@ E você normalmente instalaria essas dependências de pacote com `pip`, por exem
```console ```console
$ pip install -r requirements.txt $ pip install -r requirements.txt
---> 100% ---> 100%
Successfully installed fastapi pydantic uvicorn Successfully installed fastapi pydantic
``` ```
</div> </div>
/// info /// info | Informação
Há outros formatos e ferramentas para definir e instalar dependências de pacote. Há outros formatos e ferramentas para definir e instalar dependências de pacotes.
Eu vou mostrar um exemplo depois usando Poetry em uma seção abaixo. 👇
/// ///
### Criando o Código do **FastAPI** ### Crie o código do **FastAPI** { #create-the-fastapi-code }
* Crie um diretório `app` e entre nele. * Crie um diretório `app` e entre nele.
* Crie um arquivo vazio `__init__.py`. * Crie um arquivo vazio `__init__.py`.
* Crie um arquivo `main.py` com: * Crie um arquivo `main.py` com:
```Python ```Python
from typing import Optional from typing import Union
from fastapi import FastAPI from fastapi import FastAPI
@ -165,28 +162,28 @@ def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q} return {"item_id": item_id, "q": q}
``` ```
### Dockerfile ### Dockerfile { #dockerfile }
Agora, no mesmo diretório do projeto, crie um arquivo `Dockerfile` com: Agora, no mesmo diretório do projeto, crie um arquivo `Dockerfile` com:
```{ .dockerfile .annotate } ```{ .dockerfile .annotate }
# (1) # (1)!
FROM python:3.9 FROM python:3.9
# (2) # (2)!
WORKDIR /code WORKDIR /code
# (3) # (3)!
COPY ./requirements.txt /code/requirements.txt COPY ./requirements.txt /code/requirements.txt
# (4) # (4)!
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
# (5) # (5)!
COPY ./app /code/app COPY ./app /code/app
# (6) # (6)!
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] CMD ["fastapi", "run", "app/main.py", "--port", "80"]
``` ```
1. Inicie a partir da imagem base oficial do Python. 1. Inicie a partir da imagem base oficial do Python.
@ -205,7 +202,7 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
A opção `--no-cache-dir` diz ao `pip` para não salvar os pacotes baixados localmente, pois isso só aconteceria se `pip` fosse executado novamente para instalar os mesmos pacotes, mas esse não é o caso quando trabalhamos com contêineres. A opção `--no-cache-dir` diz ao `pip` para não salvar os pacotes baixados localmente, pois isso só aconteceria se `pip` fosse executado novamente para instalar os mesmos pacotes, mas esse não é o caso quando trabalhamos com contêineres.
/// note /// note | Nota
`--no-cache-dir` é apenas relacionado ao `pip`, não tem nada a ver com Docker ou contêineres. `--no-cache-dir` é apenas relacionado ao `pip`, não tem nada a ver com Docker ou contêineres.
@ -223,21 +220,51 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
Então, é importante colocar isso **perto do final** do `Dockerfile`, para otimizar o tempo de construção da imagem do contêiner. Então, é importante colocar isso **perto do final** do `Dockerfile`, para otimizar o tempo de construção da imagem do contêiner.
6. Defina o **comando** para rodar o servidor `uvicorn`. 6. Defina o **comando** para usar `fastapi run`, que utiliza o Uvicorn por baixo dos panos.
`CMD` recebe uma lista de strings, cada uma dessas strings é o que você digitaria na linha de comando separado por espaços. `CMD` recebe uma lista de strings, cada uma dessas strings é o que você digitaria na linha de comando separado por espaços.
Esse comando será executado a partir do **diretório de trabalho atual**, o mesmo diretório `/code` que você definiu acima com `WORKDIR /code`. Esse comando será executado a partir do **diretório de trabalho atual**, o mesmo diretório `/code` que você definiu acima com `WORKDIR /code`.
Porque o programa será iniciado em `/code` e dentro dele está o diretório `./app` com seu código, o **Uvicorn** será capaz de ver e **importar** `app` de `app.main`. /// tip | Dica
/// tip
Revise o que cada linha faz clicando em cada bolha com o número no código. 👆 Revise o que cada linha faz clicando em cada bolha com o número no código. 👆
/// ///
Agora você deve ter uma estrutura de diretório como: /// warning | Atenção
Certifique-se de **sempre** usar a **forma exec** da instrução `CMD`, como explicado abaixo.
///
#### Use `CMD` - Forma Exec { #use-cmd-exec-form }
A instrução <a href="https://docs.docker.com/reference/dockerfile/#cmd" class="external-link" target="_blank">`CMD`</a> no Docker pode ser escrita de duas formas:
✅ Forma **Exec**:
```Dockerfile
# ✅ Faça assim
CMD ["fastapi", "run", "app/main.py", "--port", "80"]
```
⛔️ Forma **Shell**:
```Dockerfile
# ⛔️ Não faça assim
CMD fastapi run app/main.py --port 80
```
Garanta que você sempre use a forma **exec** para assegurar que o FastAPI consiga encerrar graciosamente e que os [eventos de lifespan](../advanced/events.md){.internal-link target=_blank} sejam disparados.
Você pode ler mais na <a href="https://docs.docker.com/reference/dockerfile/#shell-and-exec-form" class="external-link" target="_blank">documentação do Docker sobre as formas shell e exec</a>.
Isso pode ser bem perceptível ao usar `docker compose`. Veja esta seção de FAQ do Docker Compose para mais detalhes técnicos: <a href="https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop" class="external-link" target="_blank">Por que meus serviços demoram 10 segundos para recriar ou parar?</a>.
#### Estrutura de diretórios { #directory-structure }
Agora você deve haver uma estrutura de diretório como:
``` ```
. .
@ -248,15 +275,15 @@ Agora você deve ter uma estrutura de diretório como:
└── requirements.txt └── requirements.txt
``` ```
#### Por Trás de um Proxy de Terminação TLS #### Por trás de um Proxy de Terminação TLS { #behind-a-tls-termination-proxy }
Se você está executando seu contêiner atrás de um Proxy de Terminação TLS (load balancer) como Nginx ou Traefik, adicione a opção `--proxy-headers`, isso fará com que o Uvicorn confie nos cabeçalhos enviados por esse proxy, informando que o aplicativo está sendo executado atrás do HTTPS, etc. Se você está executando seu contêiner atrás de um Proxy de Terminação TLS (load balancer) como Nginx ou Traefik, adicione a opção `--proxy-headers`, isso fará com que o Uvicorn (pela CLI do FastAPI) confie nos cabeçalhos enviados por esse proxy, informando que o aplicativo está sendo executado atrás do HTTPS, etc.
```Dockerfile ```Dockerfile
CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"] CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"]
``` ```
#### Cache Docker #### Cache Docker { #docker-cache }
Existe um truque importante nesse `Dockerfile`, primeiro copiamos o **arquivo com as dependências sozinho**, não o resto do código. Deixe-me te contar o porquê disso. Existe um truque importante nesse `Dockerfile`, primeiro copiamos o **arquivo com as dependências sozinho**, não o resto do código. Deixe-me te contar o porquê disso.
@ -288,7 +315,7 @@ A partir daí, perto do final do `Dockerfile`, copiamos todo o código. Como iss
COPY ./app /code/app COPY ./app /code/app
``` ```
### Construindo a Imagem Docker ### Construa a Imagem Docker { #build-the-docker-image }
Agora que todos os arquivos estão no lugar, vamos construir a imagem do contêiner. Agora que todos os arquivos estão no lugar, vamos construir a imagem do contêiner.
@ -305,7 +332,7 @@ $ docker build -t myimage .
</div> </div>
/// tip /// tip | Dica
Note o `.` no final, é equivalente a `./`, ele diz ao Docker o diretório a ser usado para construir a imagem do contêiner. Note o `.` no final, é equivalente a `./`, ele diz ao Docker o diretório a ser usado para construir a imagem do contêiner.
@ -313,19 +340,19 @@ Nesse caso, é o mesmo diretório atual (`.`).
/// ///
### Inicie o contêiner Docker ### Inicie o Contêiner Docker { #start-the-docker-container }
* Execute um contêiner baseado na sua imagem: * Execute um contêiner baseado na sua imagem:
<div class="termy"> <div class="termy">
```console ```console
$ docker run -d --name mycontêiner -p 80:80 myimage $ docker run -d --name mycontainer -p 80:80 myimage
``` ```
</div> </div>
## Verifique ## Verifique { #check-it }
Você deve ser capaz de verificar isso no URL do seu contêiner Docker, por exemplo: <a href="http://192.168.99.100/items/5?q=somequery" class="external-link" target="_blank">http://192.168.99.100/items/5?q=somequery</a> ou <a href="http://127.0.0.1/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1/items/5?q=somequery</a> (ou equivalente, usando seu host Docker). Você deve ser capaz de verificar isso no URL do seu contêiner Docker, por exemplo: <a href="http://192.168.99.100/items/5?q=somequery" class="external-link" target="_blank">http://192.168.99.100/items/5?q=somequery</a> ou <a href="http://127.0.0.1/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1/items/5?q=somequery</a> (ou equivalente, usando seu host Docker).
@ -335,7 +362,7 @@ Você verá algo como:
{"item_id": 5, "q": "somequery"} {"item_id": 5, "q": "somequery"}
``` ```
## Documentação interativa da API ## Documentação interativa da API { #interactive-api-docs }
Agora você pode ir para <a href="http://192.168.99.100/docs" class="external-link" target="_blank">http://192.168.99.100/docs</a> ou <a href="http://127.0.0.1/docs" class="external-link" target="_blank">http://127.0.0.1/docs</a> (ou equivalente, usando seu host Docker). Agora você pode ir para <a href="http://192.168.99.100/docs" class="external-link" target="_blank">http://192.168.99.100/docs</a> ou <a href="http://127.0.0.1/docs" class="external-link" target="_blank">http://127.0.0.1/docs</a> (ou equivalente, usando seu host Docker).
@ -343,7 +370,7 @@ Você verá a documentação interativa automática da API (fornecida pelo <a hr
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
## Documentação alternativa da API ## Documentação alternativa da API { #alternative-api-docs }
E você também pode ir para <a href="http://192.168.99.100/redoc" class="external-link" target="_blank">http://192.168.99.100/redoc</a> ou <a href="http://127.0.0.1/redoc" class="external-link" target="_blank">http://127.0.0.1/redoc</a> (ou equivalente, usando seu host Docker). E você também pode ir para <a href="http://192.168.99.100/redoc" class="external-link" target="_blank">http://192.168.99.100/redoc</a> ou <a href="http://127.0.0.1/redoc" class="external-link" target="_blank">http://127.0.0.1/redoc</a> (ou equivalente, usando seu host Docker).
@ -351,7 +378,7 @@ Você verá a documentação alternativa automática (fornecida pela <a href="ht
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## Construindo uma Imagem Docker com um Arquivo Único FastAPI ## Construa uma Imagem Docker com um FastAPI de Arquivo Único { #build-a-docker-image-with-a-single-file-fastapi }
Se seu FastAPI for um único arquivo, por exemplo, `main.py` sem um diretório `./app`, sua estrutura de arquivos poderia ser assim: Se seu FastAPI for um único arquivo, por exemplo, `main.py` sem um diretório `./app`, sua estrutura de arquivos poderia ser assim:
@ -373,20 +400,20 @@ COPY ./requirements.txt /code/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
# (1) # (1)!
COPY ./main.py /code/ COPY ./main.py /code/
# (2) # (2)!
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"] CMD ["fastapi", "run", "main.py", "--port", "80"]
``` ```
1. Copie o arquivo `main.py` para o diretório `/code` diretamente (sem nenhum diretório `./app`). 1. Copie o arquivo `main.py` para o diretório `/code` diretamente (sem nenhum diretório `./app`).
2. Execute o Uvicorn e diga a ele para importar o objeto `app` de `main` (em vez de importar de `app.main`). 2. Use `fastapi run` para servir sua aplicação no arquivo único `main.py`.
Então ajuste o comando Uvicorn para usar o novo módulo `main` em vez de `app.main` para importar o objeto FastAPI `app`. Quando você passa o arquivo para `fastapi run` ele detecta automaticamente que é um arquivo único e não parte de um pacote e sabe como importá-lo e servir sua aplicação FastAPI. 😎
## Conceitos de Implantação ## Conceitos de Implantação { #deployment-concepts }
Vamos falar novamente sobre alguns dos mesmos [Conceitos de Implantação](concepts.md){.internal-link target=_blank} em termos de contêineres. Vamos falar novamente sobre alguns dos mesmos [Conceitos de Implantação](concepts.md){.internal-link target=_blank} em termos de contêineres.
@ -403,21 +430,21 @@ Vamos revisar esses **conceitos de implantação** em termos de contêineres:
* Memória * Memória
* Passos anteriores antes de começar * Passos anteriores antes de começar
## HTTPS ## HTTPS { #https }
Se nos concentrarmos apenas na **imagem do contêiner** para um aplicativo FastAPI (e posteriormente no **contêiner** em execução), o HTTPS normalmente seria tratado **externamente** por outra ferramenta. Se nos concentrarmos apenas na **imagem do contêiner** para um aplicativo FastAPI (e posteriormente no **contêiner** em execução), o HTTPS normalmente seria tratado **externamente** por outra ferramenta.
Isso poderia ser outro contêiner, por exemplo, com <a href="https://traefik.io/" class="external-link" target="_blank">Traefik</a>, lidando com **HTTPS** e aquisição **automática** de **certificados**. Isso poderia ser outro contêiner, por exemplo, com <a href="https://traefik.io/" class="external-link" target="_blank">Traefik</a>, lidando com **HTTPS** e aquisição **automática** de **certificados**.
/// tip /// tip | Dica
Traefik tem integrações com Docker, Kubernetes e outros, portanto, é muito fácil configurar e configurar o HTTPS para seus contêineres com ele. Traefik tem integrações com Docker, Kubernetes e outros, portanto, é muito fácil configurar o HTTPS para seus contêineres com ele.
/// ///
Alternativamente, o HTTPS poderia ser tratado por um provedor de nuvem como um de seus serviços (enquanto ainda executasse o aplicativo em um contêiner). Alternativamente, o HTTPS poderia ser tratado por um provedor de nuvem como um de seus serviços (enquanto ainda executasse o aplicativo em um contêiner).
## Executando na inicialização e reinicializações ## Executando na inicialização e reinicializações { #running-on-startup-and-restarts }
Normalmente, outra ferramenta é responsável por **iniciar e executar** seu contêiner. Normalmente, outra ferramenta é responsável por **iniciar e executar** seu contêiner.
@ -427,21 +454,21 @@ Na maioria (ou em todos) os casos, há uma opção simples para habilitar a exec
Sem usar contêineres, fazer aplicativos executarem na inicialização e com reinicializações pode ser trabalhoso e difícil. Mas quando **trabalhando com contêineres** em muitos casos essa funcionalidade é incluída por padrão. ✨ Sem usar contêineres, fazer aplicativos executarem na inicialização e com reinicializações pode ser trabalhoso e difícil. Mas quando **trabalhando com contêineres** em muitos casos essa funcionalidade é incluída por padrão. ✨
## Replicação - Número de Processos ## Replicação - Número de Processos { #replication-number-of-processes }
Se você tiver um <abbr title="Um grupo de máquinas que são configuradas para estarem conectadas e trabalharem juntas de alguma forma">cluster</abbr> de máquinas com **Kubernetes**, Docker Swarm Mode, Nomad ou outro sistema complexo semelhante para gerenciar contêineres distribuídos em várias máquinas, então provavelmente desejará **lidar com a replicação** no **nível do cluster** em vez de usar um **gerenciador de processos** (como o Gunicorn com workers) em cada contêiner. Se você tiver um <abbr title="Um grupo de máquinas que são configuradas para estarem conectadas e trabalharem juntas de alguma forma.">cluster</abbr> de máquinas com **Kubernetes**, Docker Swarm Mode, Nomad ou outro sistema complexo semelhante para gerenciar contêineres distribuídos em várias máquinas, então provavelmente desejará **lidar com a replicação** no **nível do cluster** em vez de usar um **gerenciador de processos** (como Uvicorn com workers) em cada contêiner.
Um desses sistemas de gerenciamento de contêineres distribuídos como o Kubernetes normalmente tem alguma maneira integrada de lidar com a **replicação de contêineres** enquanto ainda oferece **balanceamento de carga** para as solicitações recebidas. Tudo no **nível do cluster**. Um desses sistemas de gerenciamento de contêineres distribuídos como o Kubernetes normalmente tem alguma maneira integrada de lidar com a **replicação de contêineres** enquanto ainda oferece **balanceamento de carga** para as solicitações recebidas. Tudo no **nível do cluster**.
Nesses casos, você provavelmente desejará criar uma **imagem do contêiner do zero** como [explicado acima](#dockerfile), instalando suas dependências e executando **um único processo Uvicorn** em vez de executar algo como Gunicorn com trabalhadores Uvicorn. Nesses casos, você provavelmente desejará criar uma **imagem Docker do zero** como [explicado acima](#dockerfile), instalando suas dependências e executando **um único processo Uvicorn** em vez de usar múltiplos workers do Uvicorn.
### Balanceamento de Carga ### Balanceador de Carga { #load-balancer }
Quando usando contêineres, normalmente você terá algum componente **escutando na porta principal**. Poderia ser outro contêiner que também é um **Proxy de Terminação TLS** para lidar com **HTTPS** ou alguma ferramenta semelhante. Quando usando contêineres, normalmente você terá algum componente **escutando na porta principal**. Poderia ser outro contêiner que também é um **Proxy de Terminação TLS** para lidar com **HTTPS** ou alguma ferramenta semelhante.
Como esse componente assumiria a **carga** de solicitações e distribuiria isso entre os trabalhadores de uma maneira (esperançosamente) **balanceada**, ele também é comumente chamado de **Balanceador de Carga**. Como esse componente assumiria a **carga** de solicitações e distribuiria isso entre os workers de uma maneira (esperançosamente) **balanceada**, ele também é comumente chamado de **Balanceador de Carga**.
/// tip /// tip | Dica
O mesmo componente **Proxy de Terminação TLS** usado para HTTPS provavelmente também seria um **Balanceador de Carga**. O mesmo componente **Proxy de Terminação TLS** usado para HTTPS provavelmente também seria um **Balanceador de Carga**.
@ -449,9 +476,9 @@ O mesmo componente **Proxy de Terminação TLS** usado para HTTPS provavelmente
E quando trabalhar com contêineres, o mesmo sistema que você usa para iniciar e gerenciá-los já terá ferramentas internas para transmitir a **comunicação de rede** (por exemplo, solicitações HTTP) do **balanceador de carga** (que também pode ser um **Proxy de Terminação TLS**) para o(s) contêiner(es) com seu aplicativo. E quando trabalhar com contêineres, o mesmo sistema que você usa para iniciar e gerenciá-los já terá ferramentas internas para transmitir a **comunicação de rede** (por exemplo, solicitações HTTP) do **balanceador de carga** (que também pode ser um **Proxy de Terminação TLS**) para o(s) contêiner(es) com seu aplicativo.
### Um Balanceador de Carga - Múltiplos Contêineres de Workers ### Um Balanceador de Carga - Múltiplos Contêineres de Workers { #one-load-balancer-multiple-worker-containers }
Quando trabalhando com **Kubernetes** ou sistemas similares de gerenciamento de contêiner distribuído, usando seus mecanismos de rede internos permitiria que o único **balanceador de carga** que estivesse escutando na **porta principal** transmitisse comunicação (solicitações) para possivelmente **múltiplos contêineres** executando seu aplicativo. Quando trabalhando com **Kubernetes** ou sistemas similares de gerenciamento de contêiner distribuído, usar seus mecanismos de rede internos permite que o único **balanceador de carga** que está escutando na **porta principal** transmita a comunicação (solicitações) para possivelmente **múltiplos contêineres** executando seu aplicativo.
Cada um desses contêineres executando seu aplicativo normalmente teria **apenas um processo** (ex.: um processo Uvicorn executando seu aplicativo FastAPI). Todos seriam **contêineres idênticos**, executando a mesma coisa, mas cada um com seu próprio processo, memória, etc. Dessa forma, você aproveitaria a **paralelização** em **núcleos diferentes** da CPU, ou até mesmo em **máquinas diferentes**. Cada um desses contêineres executando seu aplicativo normalmente teria **apenas um processo** (ex.: um processo Uvicorn executando seu aplicativo FastAPI). Todos seriam **contêineres idênticos**, executando a mesma coisa, mas cada um com seu próprio processo, memória, etc. Dessa forma, você aproveitaria a **paralelização** em **núcleos diferentes** da CPU, ou até mesmo em **máquinas diferentes**.
@ -459,54 +486,61 @@ E o sistema de contêiner com o **balanceador de carga** iria **distribuir as so
E normalmente esse **balanceador de carga** seria capaz de lidar com solicitações que vão para *outros* aplicativos em seu cluster (por exemplo, para um domínio diferente, ou sob um prefixo de URL diferente), e transmitiria essa comunicação para os contêineres certos para *esse outro* aplicativo em execução em seu cluster. E normalmente esse **balanceador de carga** seria capaz de lidar com solicitações que vão para *outros* aplicativos em seu cluster (por exemplo, para um domínio diferente, ou sob um prefixo de URL diferente), e transmitiria essa comunicação para os contêineres certos para *esse outro* aplicativo em execução em seu cluster.
### Um Processo por Contêiner ### Um Processo por Contêiner { #one-process-per-container }
Nesse tipo de cenário, provavelmente você desejará ter **um único processo (Uvicorn) por contêiner**, pois já estaria lidando com a replicação no nível do cluster. Nesse tipo de cenário, provavelmente você desejará ter **um único processo (Uvicorn) por contêiner**, pois já estaria lidando com a replicação no nível do cluster.
Então, nesse caso, você **não** desejará ter um gerenciador de processos como o Gunicorn com trabalhadores Uvicorn, ou o Uvicorn usando seus próprios trabalhadores Uvicorn. Você desejará ter apenas um **único processo Uvicorn** por contêiner (mas provavelmente vários contêineres). Então, nesse caso, você **não** desejará ter múltiplos workers no contêiner, por exemplo com a opção de linha de comando `--workers`. Você desejará ter apenas um **único processo Uvicorn** por contêiner (mas provavelmente vários contêineres).
Tendo outro gerenciador de processos dentro do contêiner (como seria com o Gunicorn ou o Uvicorn gerenciando trabalhadores Uvicorn) só adicionaria **complexidade desnecessária** que você provavelmente já está cuidando com seu sistema de cluster. Ter outro gerenciador de processos dentro do contêiner (como seria com múltiplos workers) só adicionaria **complexidade desnecessária** que você provavelmente já está cuidando com seu sistema de cluster.
### Contêineres com Múltiplos Processos e Casos Especiais ### Contêineres com Múltiplos Processos e Casos Especiais { #containers-with-multiple-processes-and-special-cases }
Claro, existem **casos especiais** em que você pode querer ter um **contêiner** com um **gerenciador de processos Gunicorn** iniciando vários **processos trabalhadores Uvicorn** dentro. Claro, existem **casos especiais** em que você pode querer ter **um contêiner** com vários **processos workers do Uvicorn** dentro.
Nesses casos, você pode usar a **imagem oficial do Docker** que inclui o **Gunicorn** como um gerenciador de processos executando vários **processos trabalhadores Uvicorn**, e algumas configurações padrão para ajustar o número de trabalhadores com base nos atuais núcleos da CPU automaticamente. Eu vou te contar mais sobre isso abaixo em [Imagem Oficial do Docker com Gunicorn - Uvicorn](#imagem-oficial-do-docker-com-gunicorn-uvicorn). Nesses casos, você pode usar a opção de linha de comando `--workers` para definir o número de workers que deseja executar:
```{ .dockerfile .annotate }
FROM python:3.9
WORKDIR /code
COPY ./requirements.txt /code/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
COPY ./app /code/app
# (1)!
CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"]
```
1. Aqui usamos a opção de linha de comando `--workers` para definir o número de workers como 4.
Aqui estão alguns exemplos de quando isso pode fazer sentido: Aqui estão alguns exemplos de quando isso pode fazer sentido:
#### Um Aplicativo Simples #### Um Aplicativo Simples { #a-simple-app }
Você pode querer um gerenciador de processos no contêiner se seu aplicativo for **simples o suficiente** para que você não precise (pelo menos não agora) ajustar muito o número de processos, e você pode simplesmente usar um padrão automatizado (com a imagem oficial do Docker), e você está executando em um **único servidor**, não em um cluster. Você pode querer um gerenciador de processos no contêiner se seu aplicativo for **simples o suficiente** para rodar em um **único servidor**, não em um cluster.
#### Docker Compose #### Docker Compose { #docker-compose }
Você pode estar implantando em um **único servidor** (não em um cluster) com o **Docker Compose**, então você não teria uma maneira fácil de gerenciar a replicação de contêineres (com o Docker Compose) enquanto preserva a rede compartilhada e o **balanceamento de carga**. Você pode estar implantando em um **único servidor** (não em um cluster) com o **Docker Compose**, então você não teria uma maneira fácil de gerenciar a replicação de contêineres (com o Docker Compose) enquanto preserva a rede compartilhada e o **balanceamento de carga**.
Então você pode querer ter **um único contêiner** com um **gerenciador de processos** iniciando **vários processos trabalhadores** dentro. Então você pode querer ter **um único contêiner** com um **gerenciador de processos** iniciando **vários processos workers** dentro.
#### Prometheus and Outros Motivos
Você também pode ter **outros motivos** que tornariam mais fácil ter um **único contêiner** com **múltiplos processos** em vez de ter **múltiplos contêineres** com **um único processo** em cada um deles.
Por exemplo (dependendo de sua configuração), você poderia ter alguma ferramenta como um exportador do Prometheus no mesmo contêiner que deve ter acesso a **cada uma das solicitações** que chegam.
Nesse caso, se você tivesse **múltiplos contêineres**, por padrão, quando o Prometheus fosse **ler as métricas**, ele receberia as métricas de **um único contêiner cada vez** (para o contêiner que tratou essa solicitação específica), em vez de receber as **métricas acumuladas** de todos os contêineres replicados.
Então, nesse caso, poderia ser mais simples ter **um único contêiner** com **múltiplos processos**, e uma ferramenta local (por exemplo, um exportador do Prometheus) no mesmo contêiner coletando métricas do Prometheus para todos os processos internos e expor essas métricas no único contêiner.
--- ---
O ponto principal é que **nenhum** desses são **regras escritas em pedra** que você deve seguir cegamente. Você pode usar essas idéias para **avaliar seu próprio caso de uso** e decidir qual é a melhor abordagem para seu sistema, verificando como gerenciar os conceitos de: O ponto principal é que **nenhum** desses são **regras escritas em pedra** que você deve seguir cegamente. Você pode usar essas ideias para **avaliar seu próprio caso de uso** e decidir qual é a melhor abordagem para seu sistema, verificando como gerenciar os conceitos de:
* Segurança - HTTPS * Segurança - HTTPS
* Executando na inicialização * Executando na inicialização
* Reinicializações * Reinicializações
* Replicação (o número de processos em execução) * Replicação (o número de processos em execução)
* Memória * Memória
* Passos anteriores antes de inicializar * Passos anteriores antes de iniciar
## Memória ## Memória { #memory }
Se você executar **um único processo por contêiner**, terá uma quantidade mais ou menos bem definida, estável e limitada de memória consumida por cada um desses contêineres (mais de um se eles forem replicados). Se você executar **um único processo por contêiner**, terá uma quantidade mais ou menos bem definida, estável e limitada de memória consumida por cada um desses contêineres (mais de um se eles forem replicados).
@ -514,17 +548,17 @@ E então você pode definir esses mesmos limites e requisitos de memória em sua
Se sua aplicação for **simples**, isso provavelmente **não será um problema**, e você pode não precisar especificar limites de memória rígidos. Mas se você estiver **usando muita memória** (por exemplo, com **modelos de aprendizado de máquina**), deve verificar quanta memória está consumindo e ajustar o **número de contêineres** que executa em **cada máquina** (e talvez adicionar mais máquinas ao seu cluster). Se sua aplicação for **simples**, isso provavelmente **não será um problema**, e você pode não precisar especificar limites de memória rígidos. Mas se você estiver **usando muita memória** (por exemplo, com **modelos de aprendizado de máquina**), deve verificar quanta memória está consumindo e ajustar o **número de contêineres** que executa em **cada máquina** (e talvez adicionar mais máquinas ao seu cluster).
Se você executar **múltiplos processos por contêiner** (por exemplo, com a imagem oficial do Docker), deve garantir que o número de processos iniciados não **consuma mais memória** do que o disponível. Se você executar **múltiplos processos por contêiner**, deve garantir que o número de processos iniciados não **consuma mais memória** do que o disponível.
## Passos anteriores antes de inicializar e contêineres ## Passos anteriores antes de iniciar e contêineres { #previous-steps-before-starting-and-containers }
Se você estiver usando contêineres (por exemplo, Docker, Kubernetes), existem duas abordagens principais que você pode usar. Se você estiver usando contêineres (por exemplo, Docker, Kubernetes), existem duas abordagens principais que você pode usar.
### Contêineres Múltiplos ### Contêineres Múltiplos { #multiple-containers }
Se você tiver **múltiplos contêineres**, provavelmente cada um executando um **único processo** (por exemplo, em um cluster do **Kubernetes**), então provavelmente você gostaria de ter um **contêiner separado** fazendo o trabalho dos **passos anteriores** em um único contêiner, executando um único processo, **antes** de executar os contêineres trabalhadores replicados. Se você tiver **múltiplos contêineres**, provavelmente cada um executando um **único processo** (por exemplo, em um cluster do **Kubernetes**), então provavelmente você gostaria de ter um **contêiner separado** fazendo o trabalho dos **passos anteriores** em um único contêiner, executando um único processo, **antes** de executar os contêineres workers replicados.
/// info /// info | Informação
Se você estiver usando o Kubernetes, provavelmente será um <a href="https://kubernetes.io/docs/concepts/workloads/pods/init-containers/" class="external-link" target="_blank">Init Container</a>. Se você estiver usando o Kubernetes, provavelmente será um <a href="https://kubernetes.io/docs/concepts/workloads/pods/init-containers/" class="external-link" target="_blank">Init Container</a>.
@ -532,85 +566,29 @@ Se você estiver usando o Kubernetes, provavelmente será um <a href="https://ku
Se no seu caso de uso não houver problema em executar esses passos anteriores **em paralelo várias vezes** (por exemplo, se você não estiver executando migrações de banco de dados, mas apenas verificando se o banco de dados está pronto), então você também pode colocá-los em cada contêiner logo antes de iniciar o processo principal. Se no seu caso de uso não houver problema em executar esses passos anteriores **em paralelo várias vezes** (por exemplo, se você não estiver executando migrações de banco de dados, mas apenas verificando se o banco de dados está pronto), então você também pode colocá-los em cada contêiner logo antes de iniciar o processo principal.
### Contêiner Único ### Contêiner Único { #single-container }
Se você tiver uma configuração simples, com um **único contêiner** que então inicia vários **processos trabalhadores** (ou também apenas um processo), então poderia executar esses passos anteriores no mesmo contêiner, logo antes de iniciar o processo com o aplicativo. A imagem oficial do Docker suporta isso internamente. Se você tiver uma configuração simples, com um **único contêiner** que então inicia vários **processos workers** (ou também apenas um processo), então poderia executar esses passos anteriores no mesmo contêiner, logo antes de iniciar o processo com o aplicativo.
## Imagem Oficial do Docker com Gunicorn - Uvicorn ### Imagem Docker base { #base-docker-image }
Há uma imagem oficial do Docker que inclui o Gunicorn executando com trabalhadores Uvicorn, conforme detalhado em um capítulo anterior: [Server Workers - Gunicorn com Uvicorn](server-workers.md){.internal-link target=_blank}. Antes havia uma imagem oficial do FastAPI para Docker: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>. Mas agora ela está descontinuada. ⛔️
Essa imagem seria útil principalmente nas situações descritas acima em: [Contêineres com Múltiplos Processos e Casos Especiais](#conteineres-com-multiplos-processos-e-casos-especiais). Você provavelmente **não** deve usar essa imagem base do Docker (ou qualquer outra semelhante).
* <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>. Se você está usando **Kubernetes** (ou outros) e já está definindo a **replicação** no nível do cluster, com vários **contêineres**. Nesses casos, é melhor **construir uma imagem do zero** como descrito acima: [Construir uma Imagem Docker para FastAPI](#build-a-docker-image-for-fastapi).
/// warning E se você precisar ter múltiplos workers, você pode simplesmente usar a opção de linha de comando `--workers`.
Existe uma grande chance de que você **não** precise dessa imagem base ou de qualquer outra semelhante, e seria melhor construir a imagem do zero, como [descrito acima em: Construa uma Imagem Docker para o FastAPI](#construindo-uma-imagem-docker-para-fastapi). /// note | Detalhes Técnicos
A imagem Docker foi criada quando o Uvicorn não suportava gerenciar e reiniciar workers mortos, então era necessário usar o Gunicorn com o Uvicorn, o que adicionava bastante complexidade, apenas para que o Gunicorn gerenciasse e reiniciasse os processos workers do Uvicorn.
Mas agora que o Uvicorn (e o comando `fastapi`) suportam o uso de `--workers`, não há razão para usar uma imagem base do Docker em vez de construir a sua própria (é praticamente a mesma quantidade de código 😅).
/// ///
Essa imagem tem um mecanismo de **auto-ajuste** incluído para definir o **número de processos trabalhadores** com base nos núcleos de CPU disponíveis. ## Deploy da Imagem do Contêiner { #deploy-the-container-image }
Isso tem **padrões sensíveis**, mas você ainda pode alterar e atualizar todas as configurações com **variáveis de ambiente** ou arquivos de configuração.
Há também suporte para executar <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker#pre_start_path" class="external-link" target="_blank">**passos anteriores antes de iniciar**</a> com um script.
/// tip
Para ver todas as configurações e opções, vá para a página da imagem Docker: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>.
///
### Número de Processos na Imagem Oficial do Docker
O **número de processos** nesta imagem é **calculado automaticamente** a partir dos **núcleos de CPU** disponíveis.
Isso significa que ele tentará **aproveitar** o máximo de **desempenho** da CPU possível.
Você também pode ajustá-lo com as configurações usando **variáveis de ambiente**, etc.
Mas isso também significa que, como o número de processos depende da CPU do contêiner em execução, a **quantidade de memória consumida** também dependerá disso.
Então, se seu aplicativo consumir muito memória (por exemplo, com modelos de aprendizado de máquina), e seu servidor tiver muitos núcleos de CPU **mas pouca memória**, então seu contêiner pode acabar tentando usar mais memória do que está disponível e degradar o desempenho muito (ou até mesmo travar). 🚨
### Criando um `Dockerfile`
Aqui está como você criaria um `Dockerfile` baseado nessa imagem:
```Dockerfile
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9
COPY ./requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
COPY ./app /app
```
### Aplicações Maiores
Se você seguiu a seção sobre a criação de [Aplicações Maiores com Múltiplos Arquivos](../tutorial/bigger-applications.md){.internal-link target=_blank}, seu `Dockerfile` pode parecer com isso:
```Dockerfile
```Dockerfile hl_lines="7"
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9
COPY ./requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
COPY ./app /app/app
```
### Quando Usar
Você provavelmente **não** deve usar essa imagem base oficial (ou qualquer outra semelhante) se estiver usando **Kubernetes** (ou outros) e já estiver definindo **replicação** no nível do cluster, com vários **contêineres**. Nesses casos, é melhor **construir uma imagem do zero** conforme descrito acima: [Construindo uma Imagem Docker para FastAPI](#construindo-uma-imagem-docker-para-fastapi).
Essa imagem seria útil principalmente nos casos especiais descritos acima em [Contêineres com Múltiplos Processos e Casos Especiais](#conteineres-com-multiplos-processos-e-casos-especiais). Por exemplo, se sua aplicação for **simples o suficiente** para que a configuração padrão de número de processos com base na CPU funcione bem, você não quer se preocupar com a configuração manual da replicação no nível do cluster e não está executando mais de um contêiner com seu aplicativo. Ou se você estiver implantando com **Docker Compose**, executando em um único servidor, etc.
## Deploy da Imagem do Contêiner
Depois de ter uma imagem de contêiner (Docker), existem várias maneiras de implantá-la. Depois de ter uma imagem de contêiner (Docker), existem várias maneiras de implantá-la.
@ -622,100 +600,11 @@ Por exemplo:
* Com outra ferramenta como o Nomad * Com outra ferramenta como o Nomad
* Com um serviço de nuvem que pega sua imagem de contêiner e a implanta * Com um serviço de nuvem que pega sua imagem de contêiner e a implanta
## Imagem Docker com Poetry ## Imagem Docker com `uv` { #docker-image-with-uv }
Se você usa <a href="https://python-poetry.org/" class="external-link" target="_blank">Poetry</a> para gerenciar as dependências do seu projeto, pode usar a construção multi-estágio do Docker: Se você está usando o <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">uv</a> para instalar e gerenciar seu projeto, você pode seguir o <a href="https://docs.astral.sh/uv/guides/integration/docker/" class="external-link" target="_blank">guia de Docker do uv</a>.
```{ .dockerfile .annotate } ## Recapitulando { #recap }
# (1)
FROM python:3.9 as requirements-stage
# (2)
WORKDIR /tmp
# (3)
RUN pip install poetry
# (4)
COPY ./pyproject.toml ./poetry.lock* /tmp/
# (5)
RUN poetry export -f requirements.txt --output requirements.txt --without-hashes
# (6)
FROM python:3.9
# (7)
WORKDIR /code
# (8)
COPY --from=requirements-stage /tmp/requirements.txt /code/requirements.txt
# (9)
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
# (10)
COPY ./app /code/app
# (11)
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
```
1. Esse é o primeiro estágio, ele é chamado `requirements-stage`.
2. Defina `/tmp` como o diretório de trabalho atual.
Aqui é onde geraremos o arquivo `requirements.txt`
3. Instale o Poetry nesse estágio do Docker.
4. Copie os arquivos `pyproject.toml` e `poetry.lock` para o diretório `/tmp`.
Porque está usando `./poetry.lock*` (terminando com um `*`), não irá falhar se esse arquivo ainda não estiver disponível.
5. Gere o arquivo `requirements.txt`.
6. Este é o estágio final, tudo aqui será preservado na imagem final do contêiner.
7. Defina o diretório de trabalho atual como `/code`.
8. Copie o arquivo `requirements.txt` para o diretório `/code`.
Essse arquivo só existe no estágio anterior do Docker, é por isso que usamos `--from-requirements-stage` para copiá-lo.
9. Instale as dependências de pacote do arquivo `requirements.txt` gerado.
10. Copie o diretório `app` para o diretório `/code`.
11. Execute o comando `uvicorn`, informando-o para usar o objeto `app` importado de `app.main`.
/// tip
Clique nos números das bolhas para ver o que cada linha faz.
///
Um **estágio do Docker** é uma parte de um `Dockerfile` que funciona como uma **imagem temporária do contêiner** que só é usada para gerar alguns arquivos para serem usados posteriormente.
O primeiro estágio será usado apenas para **instalar Poetry** e para **gerar o `requirements.txt`** com as dependências do seu projeto a partir do arquivo `pyproject.toml` do Poetry.
Esse arquivo `requirements.txt` será usado com `pip` mais tarde no **próximo estágio**.
Na imagem final do contêiner, **somente o estágio final** é preservado. Os estágios anteriores serão descartados.
Quando usar Poetry, faz sentido usar **construções multi-estágio do Docker** porque você realmente não precisa ter o Poetry e suas dependências instaladas na imagem final do contêiner, você **apenas precisa** ter o arquivo `requirements.txt` gerado para instalar as dependências do seu projeto.
Então, no próximo (e último) estágio, você construiria a imagem mais ou menos da mesma maneira descrita anteriormente.
### Por trás de um proxy de terminação TLS - Poetry
Novamente, se você estiver executando seu contêiner atrás de um proxy de terminação TLS (balanceador de carga) como Nginx ou Traefik, adicione a opção `--proxy-headers` ao comando:
```Dockerfile
CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"]
```
## Recapitulando
Usando sistemas de contêiner (por exemplo, com **Docker** e **Kubernetes**), torna-se bastante simples lidar com todos os **conceitos de implantação**: Usando sistemas de contêiner (por exemplo, com **Docker** e **Kubernetes**), torna-se bastante simples lidar com todos os **conceitos de implantação**:
@ -724,10 +613,8 @@ Usando sistemas de contêiner (por exemplo, com **Docker** e **Kubernetes**), to
* Reinícios * Reinícios
* Replicação (o número de processos rodando) * Replicação (o número de processos rodando)
* Memória * Memória
* Passos anteriores antes de inicializar * Passos anteriores antes de iniciar
Na maioria dos casos, você provavelmente não desejará usar nenhuma imagem base e, em vez disso, **construir uma imagem de contêiner do zero** baseada na imagem oficial do Docker Python. Na maioria dos casos, você provavelmente não desejará usar nenhuma imagem base e, em vez disso, **construir uma imagem de contêiner do zero** baseada na imagem oficial do Docker Python.
Tendo cuidado com a **ordem** das instruções no `Dockerfile` e o **cache do Docker**, você pode **minimizar os tempos de construção**, para maximizar sua produtividade (e evitar a tédio). 😎 Tendo cuidado com a **ordem** das instruções no `Dockerfile` e o **cache do Docker**, você pode **minimizar os tempos de construção**, para maximizar sua produtividade (e evitar o tédio). 😎
Em alguns casos especiais, você pode querer usar a imagem oficial do Docker para o FastAPI. 🤓

View File

@ -1,4 +1,4 @@
# Sobre HTTPS # Sobre HTTPS { #about-https }
É fácil assumir que HTTPS é algo que é apenas "habilitado" ou não. É fácil assumir que HTTPS é algo que é apenas "habilitado" ou não.
@ -10,31 +10,31 @@ Se você está com pressa ou não se importa, continue com as seções seguintes
/// ///
Para aprender o básico de HTTPS de uma perspectiva do usuário, verifique <a href="https://howhttps.works/pt-br/" class="external-link" target="_blank">https://howhttps.works/pt-br/</a>. Para aprender o básico de HTTPS do ponto de vista do consumidor, verifique <a href="https://howhttps.works/" class="external-link" target="_blank">https://howhttps.works/</a>.
Agora, a partir de uma perspectiva do desenvolvedor, aqui estão algumas coisas para ter em mente ao pensar em HTTPS: Agora, a partir de uma perspectiva do desenvolvedor, aqui estão algumas coisas para ter em mente ao pensar em HTTPS:
* Para HTTPS, **o servidor** precisa ter certificados gerados por **um terceiro**. * Para HTTPS, o servidor precisa ter "certificados" gerados por um terceiro.
* Esses certificados são na verdade **adquiridos** de um terceiro, eles não são simplesmente "gerados". * Esses certificados são na verdade adquiridos de um terceiro, eles não são simplesmente "gerados".
* Certificados têm um **tempo de vida**. * Certificados têm um tempo de vida.
* Eles **expiram**. * Eles expiram.
* E então eles precisam ser **renovados**, **adquirindo-os novamente** de um terceiro. * E então eles precisam ser renovados, adquirindo-os novamente de um terceiro.
* A criptografia da conexão acontece no **nível TCP**. * A criptografia da conexão acontece no nível TCP.
* Essa é uma camada **abaixo do HTTP**. * Essa é uma camada abaixo do HTTP.
* Portanto, o manuseio do **certificado e da criptografia** é feito **antes do HTTP**. * Portanto, o manuseio do certificado e da criptografia é feito antes do HTTP.
* **O TCP não sabe sobre "domínios"**. Apenas sobre endereços IP. * O TCP não sabe sobre "domínios". Apenas sobre endereços IP.
* As informações sobre o **domínio solicitado** vão nos **dados HTTP**. * As informações sobre o domínio específico solicitado vão nos dados HTTP.
* Os **certificados HTTPS** “certificam” um **determinado domínio**, mas o protocolo e a encriptação acontecem ao nível do TCP, **antes de sabermos** de que domínio se trata. * Os certificados HTTPS “certificam” um determinado domínio, mas o protocolo e a encriptação acontecem ao nível do TCP, antes de sabermos de que domínio se trata.
* **Por padrão**, isso significa que você só pode ter **um certificado HTTPS por endereço IP**. * Por padrão, isso significa que você só pode ter um certificado HTTPS por endereço IP.
* Não importa o tamanho do seu servidor ou quão pequeno cada aplicativo que você tem nele possa ser. * Não importa o tamanho do seu servidor ou quão pequeno cada aplicativo que você tem nele possa ser.
* No entanto, existe uma **solução** para isso. * No entanto, existe uma solução para isso.
* Há uma **extensão** para o protocolo **TLS** (aquele que lida com a criptografia no nível TCP, antes do HTTP) chamado **<a href="https://en.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr title="Server Name Indication">SNI</abbr></a>**. * Há uma extensão para o protocolo TLS (aquele que lida com a criptografia no nível TCP, antes do HTTP) chamada <a href="https://en.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr title="Server Name Indication">SNI</abbr></a>.
* Esta extensão SNI permite que um único servidor (com um **único endereço IP**) tenha **vários certificados HTTPS** e atenda a **vários domínios / aplicativos HTTPS**. * Esta extensão SNI permite que um único servidor (com um único endereço IP) tenha vários certificados HTTPS e atenda a vários domínios / aplicativos HTTPS.
* Para que isso funcione, um **único** componente (programa) em execução no servidor, ouvindo no **endereço IP público**, deve ter **todos os certificados HTTPS** no servidor. * Para que isso funcione, um único componente (programa) em execução no servidor, ouvindo no endereço IP público, deve ter todos os certificados HTTPS no servidor.
* **Depois** de obter uma conexão segura, o protocolo de comunicação **ainda é HTTP**. * Depois de obter uma conexão segura, o protocolo de comunicação ainda é HTTP.
* Os conteúdos são **criptografados**, embora sejam enviados com o **protocolo HTTP**. * Os conteúdos são criptografados, embora sejam enviados com o protocolo HTTP.
É uma prática comum ter um **programa/servidor HTTP** em execução no servidor (máquina, host, etc.) e **gerenciar todas as partes HTTPS**: **recebendo as requisições encriptadas**, enviando as **solicitações HTTP descriptografadas** para o aplicativo HTTP real em execução no mesmo servidor (a aplicação **FastAPI**, neste caso), pegue a **resposta HTTP** do aplicativo, **criptografe-a** usando o **certificado HTTPS** apropriado e envie-a de volta ao cliente usando **HTTPS**. Este servidor é frequentemente chamado de **<a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" class="external-link" target="_blank">Proxy de Terminação TLS</a>**. É uma prática comum ter um programa/servidor HTTP em execução no servidor (máquina, host, etc.) e gerenciar todas as partes HTTPS: recebendo as requisições HTTPS encriptadas, enviando as solicitações HTTP descriptografadas para o aplicativo HTTP real em execução no mesmo servidor (a aplicação FastAPI, neste caso), pegar a resposta HTTP do aplicativo, criptografá-la usando o certificado HTTPS apropriado e enviá-la de volta ao cliente usando HTTPS. Este servidor é frequentemente chamado de <a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" class="external-link" target="_blank">Proxy de Terminação TLS</a>.
Algumas das opções que você pode usar como Proxy de Terminação TLS são: Algumas das opções que você pode usar como Proxy de Terminação TLS são:
@ -43,31 +43,31 @@ Algumas das opções que você pode usar como Proxy de Terminação TLS são:
* Nginx * Nginx
* HAProxy * HAProxy
## Let's Encrypt ## Let's Encrypt { #lets-encrypt }
Antes de Let's Encrypt, esses **certificados HTTPS** eram vendidos por terceiros confiáveis. Antes de Let's Encrypt, esses certificados HTTPS eram vendidos por terceiros confiáveis.
O processo de aquisição de um desses certificados costumava ser complicado, exigia bastante papelada e os certificados eram bastante caros. O processo de aquisição de um desses certificados costumava ser complicado, exigia bastante papelada e os certificados eram bastante caros.
Mas então o **<a href="https://letsencrypt.org/" class="external-link" target="_blank">Let's Encrypt</a>** foi criado. Mas então o <a href="https://letsencrypt.org/" class="external-link" target="_blank">Let's Encrypt</a> foi criado.
Ele é um projeto da Linux Foundation que fornece **certificados HTTPS gratuitamente** . De forma automatizada. Esses certificados usam toda a segurança criptográfica padrão e têm vida curta (cerca de 3 meses), então a **segurança é, na verdade, melhor** por causa de sua vida útil reduzida. Ele é um projeto da Linux Foundation que fornece certificados HTTPS gratuitamente. De forma automatizada. Esses certificados usam toda a segurança criptográfica padrão e têm vida curta (cerca de 3 meses), então a segurança é, na verdade, melhor por causa do seu lifespan reduzido.
Os domínios são verificados com segurança e os certificados são gerados automaticamente. Isso também permite automatizar a renovação desses certificados. Os domínios são verificados com segurança e os certificados são gerados automaticamente. Isso também permite automatizar a renovação desses certificados.
A ideia é automatizar a aquisição e renovação desses certificados, para que você tenha **HTTPS seguro, de graça e para sempre**. A ideia é automatizar a aquisição e renovação desses certificados, para que você tenha HTTPS seguro, de graça e para sempre.
## HTTPS para Desenvolvedores ## HTTPS para Desenvolvedores { #https-for-developers }
Aqui está um exemplo de como uma API HTTPS poderia ser estruturada, passo a passo, com foco principal nas ideias relevantes para desenvolvedores. Aqui está um exemplo de como uma API HTTPS poderia ser estruturada, passo a passo, com foco principal nas ideias relevantes para desenvolvedores.
### Nome do domínio ### Nome do domínio { #domain-name }
A etapa inicial provavelmente seria **adquirir** algum **nome de domínio**. Então, você iria configurá-lo em um servidor DNS (possivelmente no mesmo provedor em nuvem). A etapa inicial provavelmente seria adquirir algum nome de domínio. Então, você iria configurá-lo em um servidor DNS (possivelmente no mesmo provedor em nuvem).
Você provavelmente usaria um servidor em nuvem (máquina virtual) ou algo parecido, e ele teria <abbr title="Que não muda">fixed</abbr> **Endereço IP público**. Você provavelmente usaria um servidor em nuvem (máquina virtual) ou algo parecido, e ele teria um <abbr title="Que não muda">fixo</abbr> Endereço IP público.
No(s) servidor(es) DNS, você configuraria um registro (`registro A`) para apontar **seu domínio** para o **endereço IP público do seu servidor**. No(s) servidor(es) DNS, você configuraria um registro (um `A record`) para apontar seu domínio para o endereço IP público do seu servidor.
Você provavelmente fará isso apenas uma vez, na primeira vez em que tudo estiver sendo configurado. Você provavelmente fará isso apenas uma vez, na primeira vez em que tudo estiver sendo configurado.
@ -77,123 +77,155 @@ Essa parte do Nome do Domínio se dá muito antes do HTTPS, mas como tudo depend
/// ///
### DNS ### DNS { #dns }
Agora vamos focar em todas as partes que realmente fazem parte do HTTPS. Agora vamos focar em todas as partes que realmente fazem parte do HTTPS.
Primeiro, o navegador iria verificar com os **servidores DNS** qual o **IP do domínio**, nesse caso, `someapp.example.com`. Primeiro, o navegador iria verificar com os servidores DNS qual o IP do domínio, nesse caso, `someapp.example.com`.
Os servidores DNS iriam informar o navegador para utilizar algum **endereço IP** específico. Esse seria o endereço IP público em uso no seu servidor, que você configurou nos servidores DNS. Os servidores DNS iriam informar o navegador para utilizar algum endereço IP específico. Esse seria o endereço IP público em uso no seu servidor, que você configurou nos servidores DNS.
<img src="/img/deployment/https/https01.drawio.svg"> <img src="/img/deployment/https/https01.drawio.svg">
### Início do Handshake TLS ### Início do Handshake TLS { #tls-handshake-start }
O navegador então irá comunicar-se com esse endereço IP na **porta 443** (a porta HTTPS). O navegador então irá comunicar-se com esse endereço IP na porta 443 (a porta HTTPS).
A primeira parte dessa comunicação é apenas para estabelecer a conexão entre o cliente e o servidor e para decidir as chaves criptográficas a serem utilizadas, etc. A primeira parte dessa comunicação é apenas para estabelecer a conexão entre o cliente e o servidor e para decidir as chaves criptográficas a serem utilizadas, etc.
<img src="/img/deployment/https/https02.drawio.svg"> <img src="/img/deployment/https/https02.drawio.svg">
Esse interação entre o cliente e o servidor para estabelecer uma conexão TLS é chamada de **Handshake TLS**. Esse interação entre o cliente e o servidor para estabelecer uma conexão TLS é chamada de Handshake TLS.
### TLS com a Extensão SNI ### TLS com a Extensão SNI { #tls-with-sni-extension }
**Apenas um processo** no servidor pode se conectar a uma **porta** em um **endereço IP**. Poderiam existir outros processos conectados em outras portas desse mesmo endereço IP, mas apenas um para cada combinação de endereço IP e porta. Apenas um processo no servidor pode se conectar a uma porta em um endereço IP. Poderiam existir outros processos conectados em outras portas desse mesmo endereço IP, mas apenas um para cada combinação de endereço IP e porta.
TLS (HTTPS) usa a porta `443` por padrão. Então essa é a porta que precisamos. TLS (HTTPS) usa a porta `443` por padrão. Então essa é a porta que precisamos.
Como apenas um único processo pode se comunicar com essa porta, o processo que faria isso seria o **Proxy de Terminação TLS**. Como apenas um único processo pode se comunicar com essa porta, o processo que faria isso seria o Proxy de Terminação TLS.
O Proxy de Terminação TLS teria acesso a um ou mais **certificados TLS** (certificados HTTPS). O Proxy de Terminação TLS teria acesso a um ou mais certificados TLS (certificados HTTPS).
Utilizando a **extensão SNI** discutida acima, o Proxy de Terminação TLS iria checar qual dos certificados TLS (HTTPS) disponíveis deve ser usado para essa conexão, utilizando o que corresponda ao domínio esperado pelo cliente. Utilizando a extensão SNI discutida acima, o Proxy de Terminação TLS iria checar qual dos certificados TLS (HTTPS) disponíveis deve ser usado para essa conexão, utilizando o que corresponda ao domínio esperado pelo cliente.
Nesse caso, ele usaria o certificado para `someapp.example.com`. Nesse caso, ele usaria o certificado para `someapp.example.com`.
<img src="/img/deployment/https/https03.drawio.svg"> <img src="/img/deployment/https/https03.drawio.svg">
O cliente já **confia** na entidade que gerou o certificado TLS (nesse caso, o Let's Encrypt, mas veremos sobre isso mais tarde), então ele pode **verificar** que o certificado é válido. O cliente já confia na entidade que gerou o certificado TLS (nesse caso, o Let's Encrypt, mas veremos sobre isso mais tarde), então ele pode verificar que o certificado é válido.
Então, utilizando o certificado, o cliente e o Proxy de Terminação TLS **decidem como encriptar** o resto da **comunicação TCP**. Isso completa a parte do **Handshake TLS**. Então, utilizando o certificado, o cliente e o Proxy de Terminação TLS decidem como encriptar o resto da comunicação TCP. Isso completa a parte do Handshake TLS.
Após isso, o cliente e o servidor possuem uma **conexão TCP encriptada**, que é provida pelo TLS. E então eles podem usar essa conexão para começar a **comunicação HTTP** propriamente dita. Após isso, o cliente e o servidor possuem uma conexão TCP encriptada, que é provida pelo TLS. E então eles podem usar essa conexão para começar a comunicação HTTP propriamente dita.
E isso resume o que é **HTTPS**, apenas **HTTP** simples dentro de uma **conexão TLS segura** em vez de uma conexão TCP pura (não encriptada). E isso resume o que é HTTPS, apenas HTTP simples dentro de uma conexão TLS segura em vez de uma conexão TCP pura (não encriptada).
/// tip | Dica /// tip | Dica
Percebe que a encriptação da comunicação acontece no **nível do TCP**, não no nível do HTTP. Percebe que a encriptação da comunicação acontece no nível do TCP, não no nível do HTTP.
/// ///
### Solicitação HTTPS ### Solicitação HTTPS { #https-request }
Agora que o cliente e servidor (especialmente o navegador e o Proxy de Terminação TLS) possuem uma **conexão TCP encriptada**, eles podem iniciar a **comunicação HTTP**. Agora que o cliente e servidor (especialmente o navegador e o Proxy de Terminação TLS) possuem uma conexão TCP encriptada, eles podem iniciar a comunicação HTTP.
Então, o cliente envia uma **solicitação HTTPS**. Que é apenas uma solicitação HTTP sobre uma conexão TLS encriptada. Então, o cliente envia uma solicitação HTTPS. Que é apenas uma solicitação HTTP sobre uma conexão TLS encriptada.
<img src="/img/deployment/https/https04.drawio.svg"> <img src="/img/deployment/https/https04.drawio.svg">
### Desencriptando a Solicitação ### Desencriptando a Solicitação { #decrypt-the-request }
O Proxy de Terminação TLS então usaria a encriptação combinada para **desencriptar a solicitação**, e transmitiria a **solicitação básica (desencriptada)** para o processo executando a aplicação (por exemplo, um processo com Uvicorn executando a aplicação FastAPI). O Proxy de Terminação TLS então usaria a encriptação combinada para desencriptar a solicitação, e transmitiria a solicitação básica (desencriptada) para o processo executando a aplicação (por exemplo, um processo com Uvicorn executando a aplicação FastAPI).
<img src="/img/deployment/https/https05.drawio.svg"> <img src="/img/deployment/https/https05.drawio.svg">
### Resposta HTTP ### Resposta HTTP { #http-response }
A aplicação processaria a solicitação e retornaria uma **resposta HTTP básica (não encriptada)** para o Proxy de Terminação TLS. A aplicação processaria a solicitação e retornaria uma resposta HTTP básica (não encriptada) para o Proxy de Terminação TLS.
<img src="/img/deployment/https/https06.drawio.svg"> <img src="/img/deployment/https/https06.drawio.svg">
### Resposta HTTPS ### Resposta HTTPS { #https-response }
O Proxy de Terminação TLS iria **encriptar a resposta** utilizando a criptografia combinada anteriormente (que foi definida com o certificado para `someapp.example.com`), e devolveria para o navegador. O Proxy de Terminação TLS iria encriptar a resposta utilizando a criptografia combinada anteriormente (que foi definida com o certificado para `someapp.example.com`), e devolveria para o navegador.
No próximo passo, o navegador verifica que a resposta é válida e encriptada com a chave criptográfica correta, etc. E depois **desencripta a resposta** e a processa. No próximo passo, o navegador verifica que a resposta é válida e encriptada com a chave criptográfica correta, etc. E depois desencripta a resposta e a processa.
<img src="/img/deployment/https/https07.drawio.svg"> <img src="/img/deployment/https/https07.drawio.svg">
O cliente (navegador) saberá que a resposta vem do servidor correto por que ela usa a criptografia que foi combinada entre eles usando o **certificado HTTPS** anterior. O cliente (navegador) saberá que a resposta vem do servidor correto por que ela usa a criptografia que foi combinada entre eles usando o certificado HTTPS anterior.
### Múltiplas Aplicações ### Múltiplas Aplicações { #multiple-applications }
Podem existir **múltiplas aplicações** em execução no mesmo servidor (ou servidores), por exemplo: outras APIs ou um banco de dados. Podem existir múltiplas aplicações em execução no mesmo servidor (ou servidores), por exemplo: outras APIs ou um banco de dados.
Apenas um processo pode estar vinculado a um IP e porta (o Proxy de Terminação TLS, por exemplo), mas outras aplicações/processos também podem estar em execução no(s) servidor(es), desde que não tentem usar a mesma **combinação de IP público e porta**. Apenas um processo pode estar vinculado a um IP e porta (o Proxy de Terminação TLS, por exemplo), mas outras aplicações/processos também podem estar em execução no(s) servidor(es), desde que não tentem usar a mesma combinação de IP público e porta.
<img src="/img/deployment/https/https08.drawio.svg"> <img src="/img/deployment/https/https08.drawio.svg">
Dessa forma, o Proxy de Terminação TLS pode gerenciar o HTTPS e os certificados de **múltiplos domínios**, para múltiplas aplicações, e então transmitir as requisições para a aplicação correta em cada caso. Dessa forma, o Proxy de Terminação TLS pode gerenciar o HTTPS e os certificados de múltiplos domínios, para múltiplas aplicações, e então transmitir as requisições para a aplicação correta em cada caso.
### Renovação de Certificados ### Renovação de Certificados { #certificate-renewal }
Em algum momento futuro, cada certificado irá **expirar** (aproximadamente 3 meses após a aquisição). Em algum momento futuro, cada certificado irá expirar (aproximadamente 3 meses após a aquisição).
E então, haverá outro programa (em alguns casos pode ser o próprio Proxy de Terminação TLS) que irá interagir com o Let's Encrypt e renovar o(s) certificado(s). E então, haverá outro programa (em alguns casos pode ser o próprio Proxy de Terminação TLS) que irá interagir com o Let's Encrypt e renovar o(s) certificado(s).
<img src="/img/deployment/https/https.drawio.svg"> <img src="/img/deployment/https/https.drawio.svg">
Os **certificados TLS** são **associados com um nome de domínio**, e não a um endereço IP. Os certificados TLS são associados com um nome de domínio, e não a um endereço IP.
Então para renovar os certificados, o programa de renovação precisa **provar** para a autoridade (Let's Encrypt) que ele realmente **possui e controla esse domínio**> Então para renovar os certificados, o programa de renovação precisa provar para a autoridade (Let's Encrypt) que ele realmente "possui" e controla esse domínio.
Para fazer isso, e acomodar as necessidades de diferentes aplicações, existem diferentes opções para esse programa. Algumas escolhas populares são: Para fazer isso, e acomodar as necessidades de diferentes aplicações, existem diferentes opções para esse programa. Algumas escolhas populares são:
* **Modificar alguns registros DNS** * Modificar alguns registros DNS
* Para isso, o programa de renovação precisa ter suporte as APIs do provedor DNS, então, dependendo do provedor DNS que você utilize, isso pode ou não ser uma opção viável. * Para isso, o programa de renovação precisa ter suporte às APIs do provedor DNS, então, dependendo do provedor DNS que você utilize, isso pode ou não ser uma opção viável.
* **Executar como um servidor** (ao menos durante o processo de aquisição do certificado) no endereço IP público associado com o domínio. * Executar como um servidor (ao menos durante o processo de aquisição do certificado) no endereço IP público associado com o domínio.
* Como dito anteriormente, apenas um processo pode estar ligado a uma porta e IP específicos. * Como dito anteriormente, apenas um processo pode estar ligado a uma porta e IP específicos.
* Essa é uma dos motivos que fazem utilizar o mesmo Proxy de Terminação TLS para gerenciar a renovação de certificados ser tão útil. * Essa é uma dos motivos que fazem utilizar o mesmo Proxy de Terminação TLS para gerenciar a renovação de certificados ser tão útil.
* Caso contrário, você pode ter que parar a execução do Proxy de Terminação TLS momentaneamente, inicializar o programa de renovação para renovar os certificados, e então reiniciar o Proxy de Terminação TLS. Isso não é o ideal, já que sua(s) aplicação(ões) não vão estar disponíveis enquanto o Proxy de Terminação TLS estiver desligado. * Caso contrário, você pode ter que parar a execução do Proxy de Terminação TLS momentaneamente, inicializar o programa de renovação para renovar os certificados, e então reiniciar o Proxy de Terminação TLS. Isso não é o ideal, já que sua(s) aplicação(ões) não vão estar disponíveis enquanto o Proxy de Terminação TLS estiver desligado.
Todo esse processo de renovação, enquanto o aplicativo ainda funciona, é uma das principais razões para preferir um **sistema separado para gerenciar HTTPS** com um Proxy de Terminação TLS em vez de usar os certificados TLS no servidor da aplicação diretamente (e.g. com o Uvicorn). Todo esse processo de renovação, enquanto o aplicativo ainda funciona, é uma das principais razões para preferir um sistema separado para gerenciar HTTPS com um Proxy de Terminação TLS em vez de usar os certificados TLS no servidor da aplicação diretamente (e.g. com o Uvicorn).
## Recapitulando ## Cabeçalhos encaminhados por Proxy { #proxy-forwarded-headers }
Possuir **HTTPS** habilitado na sua aplicação é bastante importante, e até **crítico** na maioria dos casos. A maior parte do esforço que você tem que colocar sobre o HTTPS como desenvolvedor está em **entender esses conceitos** e como eles funcionam. Ao usar um proxy para lidar com HTTPS, seu servidor de aplicação (por exemplo, Uvicorn via FastAPI CLI) não sabe nada sobre o processo de HTTPS; ele se comunica com HTTP simples com o Proxy de Terminação TLS.
Mas uma vez que você saiba o básico de **HTTPS para desenvolvedores**, você pode combinar e configurar diferentes ferramentas facilmente para gerenciar tudo de uma forma simples. Esse proxy normalmente define alguns cabeçalhos HTTP dinamicamente antes de transmitir a requisição para o servidor de aplicação, para informar ao servidor de aplicação que a requisição está sendo encaminhada pelo proxy.
Em alguns dos próximos capítulos, eu mostrarei para você vários exemplos concretos de como configurar o **HTTPS** para aplicações **FastAPI**. 🔒 /// note | Detalhes Técnicos
Os cabeçalhos do proxy são:
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For" class="external-link" target="_blank">X-Forwarded-For</a>
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto" class="external-link" target="_blank">X-Forwarded-Proto</a>
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host" class="external-link" target="_blank">X-Forwarded-Host</a>
///
No entanto, como o servidor de aplicação não sabe que está atrás de um proxy confiável, por padrão ele não confiaria nesses cabeçalhos.
Mas você pode configurar o servidor de aplicação para confiar nos cabeçalhos encaminhados enviados pelo proxy. Se você estiver usando o FastAPI CLI, pode usar a opção de CLI `--forwarded-allow-ips` para dizer de quais IPs ele deve confiar nesses cabeçalhos encaminhados.
Por exemplo, se o servidor de aplicação só estiver recebendo comunicação do proxy confiável, você pode defini-lo como `--forwarded-allow-ips="*"` para fazê-lo confiar em todos os IPs de entrada, já que ele só receberá requisições de seja lá qual for o IP usado pelo proxy.
Dessa forma, a aplicação seria capaz de saber qual é sua própria URL pública, se está usando HTTPS, o domínio, etc.
Isso seria útil, por exemplo, para lidar corretamente com redirecionamentos.
/// tip | Dica
Você pode saber mais sobre isso na documentação em [Atrás de um Proxy - Habilitar cabeçalhos encaminhados pelo proxy](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank}
///
## Recapitulando { #recap }
Possuir HTTPS habilitado na sua aplicação é bastante importante, e até crítico na maioria dos casos. A maior parte do esforço que você tem que colocar sobre o HTTPS como desenvolvedor está em entender esses conceitos e como eles funcionam.
Mas uma vez que você saiba o básico de HTTPS para desenvolvedores, você pode combinar e configurar diferentes ferramentas facilmente para gerenciar tudo de uma forma simples.
Em alguns dos próximos capítulos, eu mostrarei para você vários exemplos concretos de como configurar o HTTPS para aplicações FastAPI. 🔒

View File

@ -1,7 +1,21 @@
# Implantação # Implantação { #deployment }
A implantação de uma aplicação **FastAPI** é relativamente simples. Implantar uma aplicação **FastAPI** é relativamente fácil.
Existem várias maneiras para fazer isso, dependendo do seu caso específico e das ferramentas que você utiliza. ## O que significa Implantação { #what-does-deployment-mean }
Você verá mais detalhes para se ter em mente e algumas das técnicas para a implantação nas próximas seções. Implantar uma aplicação significa executar as etapas necessárias para torná-la disponível para os usuários.
Para uma **web API**, isso normalmente envolve colocá-la em uma **máquina remota**, com um **programa de servidor** que ofereça bom desempenho, estabilidade, etc., de modo que seus **usuários** possam **acessar** a aplicação com eficiência e sem interrupções ou problemas.
Isso contrasta com as fases de **desenvolvimento**, em que você está constantemente alterando o código, quebrando e consertando, parando e reiniciando o servidor de desenvolvimento, etc.
## Estratégias de Implantação { #deployment-strategies }
Há várias maneiras de fazer isso, dependendo do seu caso de uso específico e das ferramentas que você utiliza.
Você pode **implantar um servidor** por conta própria usando uma combinação de ferramentas, pode usar um **serviço em nuvem** que faça parte do trabalho por você, entre outras opções.
Vou mostrar alguns dos principais conceitos que você provavelmente deve ter em mente ao implantar uma aplicação **FastAPI** (embora a maior parte se aplique a qualquer outro tipo de aplicação web).
Você verá mais detalhes para ter em mente e algumas das técnicas para fazer isso nas próximas seções. ✨

View File

@ -1,6 +1,6 @@
# Execute um Servidor Manualmente # Execute um Servidor Manualmente { #run-a-server-manually }
## Utilize o comando `fastapi run` ## Utilize o comando `fastapi run` { #use-the-fastapi-run-command }
Em resumo, utilize o comando `fastapi run` para inicializar sua aplicação FastAPI: Em resumo, utilize o comando `fastapi run` para inicializar sua aplicação FastAPI:
@ -42,23 +42,23 @@ Isto deve funcionar para a maioria dos casos. 😎
Você pode utilizar esse comando, por exemplo, para iniciar sua aplicação **FastAPI** em um contêiner, em um servidor, etc. Você pode utilizar esse comando, por exemplo, para iniciar sua aplicação **FastAPI** em um contêiner, em um servidor, etc.
## Servidores ASGI ## Servidores ASGI { #asgi-servers }
Vamos nos aprofundar um pouco mais em detalhes. Vamos nos aprofundar um pouco mais em detalhes.
FastAPI utiliza um padrão para construir frameworks e servidores web em Python chamado <abbr title="Asynchronous Server Gateway Interface">ASGI</abbr>. FastAPI é um framework web ASGI. FastAPI utiliza um padrão para construir frameworks e servidores web em Python chamado <abbr title="Asynchronous Server Gateway Interface Interface de Gateway de Servidor Assíncrono">ASGI</abbr>. FastAPI é um framework web ASGI.
A principal coisa que você precisa para executar uma aplicação **FastAPI** (ou qualquer outra aplicação ASGI) em uma máquina de servidor remoto é um programa de servidor ASGI como o **Uvicorn**, que é o que vem por padrão no comando `fastapi`. A principal coisa que você precisa para executar uma aplicação **FastAPI** (ou qualquer outra aplicação ASGI) em uma máquina de servidor remoto é um programa de servidor ASGI como o **Uvicorn**, que é o que vem por padrão no comando `fastapi`.
Existem diversas alternativas, incluindo: Existem diversas alternativas, incluindo:
* <a href="https://www.uvicorn.dev/" class="external-link" target="_blank">Uvicorn</a>: um servidor ASGI de alta performance. * <a href="https://www.uvicorn.dev/" class="external-link" target="_blank">Uvicorn</a>: um servidor ASGI de alta performance.
* <a href="https://hypercorn.readthedocs.io/" class="external-link" target="_blank">Hypercorn</a>: um servidor ASGI compátivel com HTTP/2, Trio e outros recursos. * <a href="https://hypercorn.readthedocs.io/" class="external-link" target="_blank">Hypercorn</a>: um servidor ASGI compatível com HTTP/2, Trio e outros recursos.
* <a href="https://github.com/django/daphne" class="external-link" target="_blank">Daphne</a>: servidor ASGI construído para Django Channels. * <a href="https://github.com/django/daphne" class="external-link" target="_blank">Daphne</a>: servidor ASGI construído para Django Channels.
* <a href="https://github.com/emmett-framework/granian" class="external-link" target="_blank">Granian</a>: um servidor HTTP Rust para aplicações Python. * <a href="https://github.com/emmett-framework/granian" class="external-link" target="_blank">Granian</a>: um servidor HTTP Rust para aplicações Python.
* <a href="https://unit.nginx.org/howto/fastapi/" class="external-link" target="_blank">NGINX Unit</a>: NGINX Unit é um runtime de aplicação web leve e versátil. * <a href="https://unit.nginx.org/howto/fastapi/" class="external-link" target="_blank">NGINX Unit</a>: NGINX Unit é um runtime de aplicação web leve e versátil.
## Máquina Servidora e Programa Servidor ## Máquina Servidora e Programa Servidor { #server-machine-and-server-program }
Existe um pequeno detalhe sobre estes nomes para se manter em mente. 💡 Existe um pequeno detalhe sobre estes nomes para se manter em mente. 💡
@ -68,7 +68,7 @@ Apenas tenha em mente que quando você ler "servidor" em geral, isso pode se ref
Quando se refere à máquina remota, é comum chamá-la de **servidor**, mas também de **máquina**, **VM** (máquina virtual), **nó**. Todos esses termos se referem a algum tipo de máquina remota, normalmente executando Linux, onde você executa programas. Quando se refere à máquina remota, é comum chamá-la de **servidor**, mas também de **máquina**, **VM** (máquina virtual), **nó**. Todos esses termos se referem a algum tipo de máquina remota, normalmente executando Linux, onde você executa programas.
## Instale o Programa Servidor ## Instale o Programa Servidor { #install-the-server-program }
Quando você instala o FastAPI, ele vem com um servidor de produção, o Uvicorn, e você pode iniciá-lo com o comando `fastapi run`. Quando você instala o FastAPI, ele vem com um servidor de produção, o Uvicorn, e você pode iniciá-lo com o comando `fastapi run`.
@ -100,7 +100,7 @@ Quando você instala o FastAPI com algo como `pip install "fastapi[standard]"`,
/// ///
## Execute o Programa Servidor ## Execute o Programa Servidor { #run-the-server-program }
Se você instalou um servidor ASGI manualmente, normalmente precisará passar uma string de importação em um formato especial para que ele importe sua aplicação FastAPI: Se você instalou um servidor ASGI manualmente, normalmente precisará passar uma string de importação em um formato especial para que ele importe sua aplicação FastAPI:
@ -131,7 +131,7 @@ from main import app
Cada programa de servidor ASGI alternativo teria um comando semelhante, você pode ler mais na documentação respectiva. Cada programa de servidor ASGI alternativo teria um comando semelhante, você pode ler mais na documentação respectiva.
/// warning | Aviso /// warning | Atenção
Uvicorn e outros servidores suportam a opção `--reload` que é útil durante o desenvolvimento. Uvicorn e outros servidores suportam a opção `--reload` que é útil durante o desenvolvimento.
@ -141,7 +141,7 @@ Ela ajuda muito durante o **desenvolvimento**, mas você **não deve** usá-la e
/// ///
## Conceitos de Implantação ## Conceitos de Implantação { #deployment-concepts }
Esses exemplos executam o programa do servidor (por exemplo, Uvicorn), iniciando **um único processo**, ouvindo em todos os IPs (`0.0.0.0`) em uma porta predefinida (por exemplo, `80`). Esses exemplos executam o programa do servidor (por exemplo, Uvicorn), iniciando **um único processo**, ouvindo em todos os IPs (`0.0.0.0`) em uma porta predefinida (por exemplo, `80`).

View File

@ -1,4 +1,4 @@
# Trabalhadores do Servidor - Uvicorn com Trabalhadores # Trabalhadores do Servidor - Uvicorn com Trabalhadores { #server-workers-uvicorn-with-workers }
Vamos rever os conceitos de implantação anteriores: Vamos rever os conceitos de implantação anteriores:
@ -25,7 +25,7 @@ Em particular, ao executar no **Kubernetes** você provavelmente **não** vai qu
/// ///
## Vários trabalhadores ## Vários trabalhadores { #multiple-workers }
Você pode iniciar vários trabalhadores com a opção de linha de comando `--workers`: Você pode iniciar vários trabalhadores com a opção de linha de comando `--workers`:
@ -111,7 +111,7 @@ A única opção nova aqui é `--workers` informando ao Uvicorn para iniciar 4 p
Você também pode ver que ele mostra o **PID** de cada processo, `27365` para o processo pai (este é o **gerenciador de processos**) e um para cada processo de trabalho: `27368`, `27369`, `27370` e `27367`. Você também pode ver que ele mostra o **PID** de cada processo, `27365` para o processo pai (este é o **gerenciador de processos**) e um para cada processo de trabalho: `27368`, `27369`, `27370` e `27367`.
## Conceitos de Implantação ## Conceitos de Implantação { #deployment-concepts }
Aqui você viu como usar vários **trabalhadores** para **paralelizar** a execução do aplicativo, aproveitar **vários núcleos** na CPU e conseguir atender **mais solicitações**. Aqui você viu como usar vários **trabalhadores** para **paralelizar** a execução do aplicativo, aproveitar **vários núcleos** na CPU e conseguir atender **mais solicitações**.
@ -124,13 +124,13 @@ Da lista de conceitos de implantação acima, o uso de trabalhadores ajudaria pr
* **Memória** * **Memória**
* **Etapas anteriores antes de iniciar** * **Etapas anteriores antes de iniciar**
## Contêineres e Docker ## Contêineres e Docker { #containers-and-docker }
No próximo capítulo sobre [FastAPI em contêineres - Docker](docker.md){.internal-link target=_blank}, explicarei algumas estratégias que você pode usar para lidar com os outros **conceitos de implantação**. No próximo capítulo sobre [FastAPI em contêineres - Docker](docker.md){.internal-link target=_blank}, explicarei algumas estratégias que você pode usar para lidar com os outros **conceitos de implantação**.
Vou mostrar como **construir sua própria imagem do zero** para executar um único processo Uvicorn. É um processo simples e provavelmente é o que você gostaria de fazer ao usar um sistema de gerenciamento de contêineres distribuídos como o **Kubernetes**. Vou mostrar como **construir sua própria imagem do zero** para executar um único processo Uvicorn. É um processo simples e provavelmente é o que você gostaria de fazer ao usar um sistema de gerenciamento de contêineres distribuídos como o **Kubernetes**.
## Recapitular ## Recapitular { #recap }
Você pode usar vários processos de trabalho com a opção CLI `--workers` com os comandos `fastapi` ou `uvicorn` para aproveitar as vantagens de **CPUs multi-core** e executar **vários processos em paralelo**. Você pode usar vários processos de trabalho com a opção CLI `--workers` com os comandos `fastapi` ou `uvicorn` para aproveitar as vantagens de **CPUs multi-core** e executar **vários processos em paralelo**.

View File

@ -1,46 +1,46 @@
# Sobre as versões do FastAPI # Sobre as versões do FastAPI { #about-fastapi-versions }
**FastAPI** já está sendo usado em produção em diversas aplicações e sistemas, a cobertura de testes é mantida em 100%, mas seu desenvolvimento está avançando rapidamente. **FastAPI** já está sendo usado em produção em muitas aplicações e sistemas. E a cobertura de testes é mantida em 100%. Mas seu desenvolvimento ainda está avançando rapidamente.
Novos recursos são adicionados com frequência, bugs são corrigidos regularmente e o código está sempre melhorando. Novas funcionalidades são adicionadas com frequência, bugs são corrigidos regularmente e o código continua melhorando continuamente.
Esse é o motivo das versões atuais estarem em `0.x.x`, significando que em cada versão pode haver mudanças significativas, tudo isso seguindo as <a href="https://semver.org/lang/pt-BR/" class="external-link" target="_blank">convenções de controle de versão semântica.</a> É por isso que as versões atuais ainda são `0.x.x`, isso reflete que cada versão pode potencialmente ter mudanças significativas. Isso segue as convenções de <a href="https://semver.org/" class="external-link" target="_blank">Versionamento Semântico</a>.
Já é possível criar aplicativos de produção com **FastAPI** (e provavelmente você já faz isso há algum tempo), apenas precisando ter certeza de usar uma versão que funcione corretamente com o resto do seu código. Você pode criar aplicações de produção com **FastAPI** agora mesmo (e provavelmente já vem fazendo isso há algum tempo), apenas certifique-se de usar uma versão que funcione corretamente com o resto do seu código.
## Fixe a sua versão de `fastapi` ## Fixe a sua versão de `fastapi` { #pin-your-fastapi-version }
A primeira coisa que você deve fazer é "fixar" a versão do **FastAPI** que você está utilizando na mais atual, na qual você sabe que funciona corretamente para o seu aplicativo. A primeira coisa que você deve fazer é "fixar" a versão do **FastAPI** que você está utilizando na versão mais recente específica que você sabe que funciona corretamente para a sua aplicação.
Por exemplo, supondo que você está usando a versão `0.45.0` em sua aplicação. Por exemplo, suponha que você esteja usando a versão `0.112.0` em sua aplicação.
Caso você utilize o arquivo `requirements.txt`, você poderia especificar a versão com: Se você usa um arquivo `requirements.txt`, você poderia especificar a versão com:
```txt ```txt
fastapi==0.45.0 fastapi[standard]==0.112.0
``` ```
Isso significa que você conseguiria utilizar a versão exata `0.45.0`. isso significaria que você usaria exatamente a versão `0.112.0`.
Ou, você poderia fixá-la com: Ou você também poderia fixá-la com:
```txt ```txt
fastapi>=0.45.0,<0.46.0 fastapi[standard]>=0.112.0,<0.113.0
``` ```
isso significa que você iria usar as versões `0.45.0` ou acima, mas inferiores à `0.46.0`, por exemplo, a versão `0.45.2` ainda seria aceita. isso significaria que você usaria as versões `0.112.0` ou superiores, mas menores que `0.113.0`, por exemplo, a versão `0.112.2` ainda seria aceita.
Se você usar qualquer outra ferramenta para gerenciar suas instalações, como Poetry, Pipenv ou outras, todas elas têm uma maneira que você pode usar para definir as versões específicas dos seus pacotes. Se você usa qualquer outra ferramenta para gerenciar suas instalações, como `uv`, Poetry, Pipenv ou outras, todas elas têm uma forma de definir versões específicas para seus pacotes.
## Versões disponíveis ## Versões disponíveis { #available-versions }
Você pode ver as versões disponíveis (por exemplo, para verificar qual é a versão atual) em [Release Notes](../release-notes.md){.internal-link target=\_blank}. Você pode ver as versões disponíveis (por exemplo, para verificar qual é a mais recente) nas [Release Notes](../release-notes.md){.internal-link target=_blank}.
## Sobre versões ## Sobre versões { #about-versions }
Seguindo as convenções de controle de versão semântica, qualquer versão abaixo de `1.0.0` pode adicionar mudanças significativas. Seguindo as convenções de Versionamento Semântico, qualquer versão abaixo de `1.0.0` pode potencialmente adicionar mudanças significativas.
FastAPI também segue a convenção de que qualquer alteração de versão "PATCH" é para correção de bugs e alterações não significativas. FastAPI também segue a convenção de que qualquer alteração de versão "PATCH" é para correções de bugs e mudanças que não quebram compatibilidade.
/// tip | Dica /// tip | Dica
@ -54,40 +54,40 @@ Logo, você deveria conseguir fixar a versão, como:
fastapi>=0.45.0,<0.46.0 fastapi>=0.45.0,<0.46.0
``` ```
Mudanças significativas e novos recursos são adicionados em versões "MINOR". Mudanças significativas e novas funcionalidades são adicionadas em versões "MINOR".
/// tip | Dica /// tip | Dica
O "MINOR" é o número que está no meio, por exemplo, em `0.2.3`, a versão MINOR é `2`. O "MINOR" é o número do meio, por exemplo, em `0.2.3`, a versão MINOR é `2`.
/// ///
## Atualizando as versões do FastAPI ## Atualizando as versões do FastAPI { #upgrading-the-fastapi-versions }
Você deve adicionar testes para a sua aplicação. Você deve adicionar testes para a sua aplicação.
Com **FastAPI** isso é muito fácil (graças a Starlette), verifique a documentação: [Testing](../tutorial/testing.md){.internal-link target=\_blank} Com **FastAPI** isso é muito fácil (graças ao Starlette), veja a documentação: [Testing](../tutorial/testing.md){.internal-link target=_blank}
Após a criação dos testes, você pode atualizar a sua versão do **FastAPI** para uma mais recente, execute os testes para se certificar de que todo o seu código está funcionando corretamente. Depois que você tiver testes, você pode atualizar a sua versão do **FastAPI** para uma mais recente e se certificar de que todo o seu código está funcionando corretamente executando seus testes.
Se tudo estiver funcionando, ou após você realizar as alterações necessárias e todos os testes estiverem passando, então você pode fixar sua versão de `FastAPI` para essa mais nova. Se tudo estiver funcionando, ou após você realizar as alterações necessárias e todos os testes estiverem passando, então você pode fixar sua versão de `fastapi` para essa versão mais recente.
## Sobre Starlette ## Sobre Starlette { #about-starlette }
Não é recomendado fixar a versão de `starlette`. Não é recomendado fixar a versão de `starlette`.
Versões diferentes de **FastAPI** utilizarão uma versão específica e mais recente de Starlette. Versões diferentes de **FastAPI** utilizarão uma versão específica e mais recente de Starlette.
Então, você pode deixar **FastAPI** escolher a versão compatível e correta de Starlette. Então, você pode deixar **FastAPI** usar a versão correta do Starlette.
## Sobre Pydantic ## Sobre Pydantic { #about-pydantic }
Pydantic incluí os testes para **FastAPI** em seus próprios testes, então as novas versões de Pydantic (acima da `1.0.0`) sempre serão compatíveis com FastAPI. Pydantic inclui os testes para **FastAPI** em seus próprios testes, então novas versões do Pydantic (acima de `1.0.0`) são sempre compatíveis com FastAPI.
Você pode fixar qualquer versão de Pydantic que desejar, desde que seja acima da `1.0.0` e abaixo da `2.0.0`. Você pode fixar o Pydantic em qualquer versão acima de `1.0.0` que funcione para você.
Por exemplo: Por exemplo:
```txt ```txt
pydantic>=1.2.0,<2.0.0 pydantic>=2.7.0,<3.0.0
``` ```

View File

@ -1,4 +1,4 @@
# Variáveis de Ambiente # Variáveis de Ambiente { #environment-variables }
/// tip | Dica /// tip | Dica
@ -10,7 +10,7 @@ Uma variável de ambiente (também conhecida como "**env var**") é uma variáve
Variáveis de ambiente podem ser úteis para lidar com **configurações** do aplicativo, como parte da **instalação** do Python, etc. Variáveis de ambiente podem ser úteis para lidar com **configurações** do aplicativo, como parte da **instalação** do Python, etc.
## Criar e Usar Variáveis de Ambiente ## Criar e Usar Variáveis de Ambiente { #create-and-use-env-vars }
Você pode **criar** e usar variáveis de ambiente no **shell (terminal)**, sem precisar do Python: Você pode **criar** e usar variáveis de ambiente no **shell (terminal)**, sem precisar do Python:
@ -50,7 +50,7 @@ Hello Wade Wilson
//// ////
## Ler Variáveis de Ambiente no Python ## Ler Variáveis de Ambiente no Python { #read-env-vars-in-python }
Você também pode criar variáveis de ambiente **fora** do Python, no terminal (ou com qualquer outro método) e depois **lê-las no Python**. Você também pode criar variáveis de ambiente **fora** do Python, no terminal (ou com qualquer outro método) e depois **lê-las no Python**.
@ -157,7 +157,7 @@ Você pode ler mais sobre isso em <a href="https://12factor.net/config" class="e
/// ///
## Tipos e Validação ## Tipos e Validação { #types-and-validation }
Essas variáveis de ambiente só podem lidar com **strings de texto**, pois são externas ao Python e precisam ser compatíveis com outros programas e com o resto do sistema (e até mesmo com diferentes sistemas operacionais, como Linux, Windows, macOS). Essas variáveis de ambiente só podem lidar com **strings de texto**, pois são externas ao Python e precisam ser compatíveis com outros programas e com o resto do sistema (e até mesmo com diferentes sistemas operacionais, como Linux, Windows, macOS).
@ -165,7 +165,7 @@ Isso significa que **qualquer valor** lido em Python de uma variável de ambient
Você aprenderá mais sobre como usar variáveis de ambiente para lidar com **configurações do aplicativo** no [Guia do Usuário Avançado - Configurações e Variáveis de Ambiente](./advanced/settings.md){.internal-link target=_blank}. Você aprenderá mais sobre como usar variáveis de ambiente para lidar com **configurações do aplicativo** no [Guia do Usuário Avançado - Configurações e Variáveis de Ambiente](./advanced/settings.md){.internal-link target=_blank}.
## Variável de Ambiente `PATH` ## Variável de Ambiente `PATH` { #path-environment-variable }
Existe uma variável de ambiente **especial** chamada **`PATH`** que é usada pelos sistemas operacionais (Linux, macOS, Windows) para encontrar programas para executar. Existe uma variável de ambiente **especial** chamada **`PATH`** que é usada pelos sistemas operacionais (Linux, macOS, Windows) para encontrar programas para executar.
@ -209,7 +209,7 @@ Por exemplo, quando você digita `python` no terminal, o sistema operacional pro
Se ele o encontrar, então ele o **usará**. Caso contrário, ele continua procurando nos **outros diretórios**. Se ele o encontrar, então ele o **usará**. Caso contrário, ele continua procurando nos **outros diretórios**.
### Instalando o Python e Atualizando o `PATH` ### Instalando o Python e Atualizando o `PATH` { #installing-python-and-updating-the-path }
Durante a instalação do Python, você pode ser questionado sobre a atualização da variável de ambiente `PATH`. Durante a instalação do Python, você pode ser questionado sobre a atualização da variável de ambiente `PATH`.
@ -287,7 +287,7 @@ $ C:\opt\custompython\bin\python
Essas informações serão úteis ao aprender sobre [Ambientes Virtuais](virtual-environments.md){.internal-link target=_blank}. Essas informações serão úteis ao aprender sobre [Ambientes Virtuais](virtual-environments.md){.internal-link target=_blank}.
## Conclusão ## Conclusão { #conclusion }
Com isso, você deve ter uma compreensão básica do que são **variáveis de ambiente** e como usá-las em Python. Com isso, você deve ter uma compreensão básica do que são **variáveis de ambiente** e como usá-las em Python.

View File

@ -1,87 +1,75 @@
# FastAPI CLI # FastAPI CLI { #fastapi-cli }
**FastAPI CLI** é uma interface por linha de comando do `fastapi` que você pode usar para rodar sua app FastAPI, gerenciar seu projeto FastAPI e mais. **FastAPI CLI** é um programa de linha de comando que você pode usar para servir sua aplicação FastAPI, gerenciar seu projeto FastAPI e muito mais.
Quando você instala o FastAPI (ex.: com `pip install fastapi`), isso inclui um pacote chamado `fastapi-cli`. Esse pacote disponibiliza o comando `fastapi` no terminal. Quando você instala o FastAPI (por exemplo, com `pip install "fastapi[standard]"`), isso inclui um pacote chamado `fastapi-cli`; esse pacote disponibiliza o comando `fastapi` no terminal.
Para rodar seu app FastAPI em desenvolvimento, você pode usar o comando `fastapi dev`: Para executar sua aplicação FastAPI durante o desenvolvimento, você pode usar o comando `fastapi dev`:
<div class="termy"> <div class="termy">
```console ```console
$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:single">main.py</u> $ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid">main.py</u>
<font color="#3465A4">INFO </font> Using path <font color="#3465A4">main.py</font>
<font color="#3465A4">INFO </font> Resolved absolute path <font color="#75507B">/home/user/code/awesomeapp/</font><font color="#AD7FA8">main.py</font>
<font color="#3465A4">INFO </font> Searching for package file structure from directories with <font color="#3465A4">__init__.py</font> files
<font color="#3465A4">INFO </font> Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font>
╭─ <font color="#8AE234"><b>Python module file</b></font> ─╮ <span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting development server 🚀
│ │
│ 🐍 main.py │
│ │
╰──────────────────────╯
<font color="#3465A4">INFO </font> Importing module <font color="#4E9A06">main</font> Searching for package file structure from directories with
<font color="#3465A4">INFO </font> Found importable FastAPI app <font color="#3465A4">__init__.py</font> files
Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font>
╭─ <font color="#8AE234"><b>Importable FastAPI app</b></font> ─╮ <span style="background-color:#007166"><font color="#D3D7CF"> module </font></span> 🐍 main.py
│ │
<span style="background-color:#272822"><font color="#FF4689">from</font></span><span style="background-color:#272822"><font color="#F8F8F2"> main </font></span><span style="background-color:#272822"><font color="#FF4689">import</font></span><span style="background-color:#272822"><font color="#F8F8F2"> app</font></span><span style="background-color:#272822"> </span>
│ │
╰──────────────────────────╯
<font color="#3465A4">INFO </font> Using import string <font color="#8AE234"><b>main:app</b></font> <span style="background-color:#007166"><font color="#D3D7CF"> code </font></span> Importing the FastAPI app object from the module with the
following code:
<span style="background-color:#C4A000"><font color="#2E3436">╭────────── FastAPI CLI - Development mode ───────────╮</font></span> <u style="text-decoration-style:solid">from </u><u style="text-decoration-style:solid"><b>main</b></u><u style="text-decoration-style:solid"> import </u><u style="text-decoration-style:solid"><b>app</b></u>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ Serving at: http://127.0.0.1:8000 │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ API docs: http://127.0.0.1:8000/docs │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ Running in development mode, for production use: │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436"></font></span><span style="background-color:#C4A000"><font color="#555753"><b>fastapi run</b></font></span><span style="background-color:#C4A000"><font color="#2E3436"></font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">╰─────────────────────────────────────────────────────╯</font></span>
<font color="#4E9A06">INFO</font>: Will watch for changes in these directories: [&apos;/home/user/code/awesomeapp&apos;] <span style="background-color:#007166"><font color="#D3D7CF"> app </font></span> Using import string: <font color="#3465A4">main:app</font>
<font color="#4E9A06">INFO</font>: Uvicorn running on <b>http://127.0.0.1:8000</b> (Press CTRL+C to quit)
<font color="#4E9A06">INFO</font>: Started reloader process [<font color="#34E2E2"><b>2265862</b></font>] using <font color="#34E2E2"><b>WatchFiles</b></font> <span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Server started at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font>
<font color="#4E9A06">INFO</font>: Started server process [<font color="#06989A">2265873</font>] <span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Documentation at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000/docs</u></font>
<font color="#4E9A06">INFO</font>: Waiting for application startup.
<font color="#4E9A06">INFO</font>: Application startup complete. <span style="background-color:#007166"><font color="#D3D7CF"> tip </font></span> Running in development mode, for production use:
<b>fastapi run</b>
Logs:
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Will watch for changes in these directories:
<b>[</b><font color="#4E9A06">&apos;/home/user/code/awesomeapp&apos;</font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Uvicorn running on <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font> <b>(</b>Press CTRL+C to
quit<b>)</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started reloader process <b>[</b><font color="#34E2E2"><b>383138</b></font><b>]</b> using WatchFiles
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>383153</b></font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
``` ```
</div> </div>
Aquele commando por linha de programa chamado `fastapi` é o **FastAPI CLI**. O programa de linha de comando chamado `fastapi` é o **FastAPI CLI**.
O FastAPI CLI recebe o caminho do seu programa Python, detecta automaticamente a variável com o FastAPI (comumente nomeada `app`) e como importá-la, e então a serve. O FastAPI CLI recebe o caminho para o seu programa Python (por exemplo, `main.py`), detecta automaticamente a instância de `FastAPI` (comumente nomeada `app`), determina a forma correta de importação e então a serve.
Para produção você usaria `fastapi run` no lugar. 🚀 Para produção, você usaria `fastapi run`. 🚀
Internamente, **FastAPI CLI** usa <a href="https://www.uvicorn.dev" class="external-link" target="_blank">Uvicorn</a>, um servidor ASGI de alta performance e pronto para produção. 😎 Internamente, o **FastAPI CLI** usa o <a href="https://www.uvicorn.dev" class="external-link" target="_blank">Uvicorn</a>, um servidor ASGI de alta performance e pronto para produção. 😎
## `fastapi dev` ## `fastapi dev` { #fastapi-dev }
Quando você roda `fastapi dev`, isso vai executar em modo de desenvolvimento. Executar `fastapi dev` inicia o modo de desenvolvimento.
Por padrão, teremos o **recarregamento automático** ativo, então o programa irá recarregar o servidor automaticamente toda vez que você fizer mudanças no seu código. Isso usa muitos recursos e pode ser menos estável. Você deve apenas usá-lo em modo de desenvolvimento. Por padrão, o recarregamento automático está ativado, recarregando o servidor automaticamente quando você faz mudanças no seu código. Isso consome muitos recursos e pode ser menos estável do que quando está desativado. Você deve usá-lo apenas no desenvolvimento. Ele também escuta no endereço IP `127.0.0.1`, que é o IP para a sua máquina se comunicar apenas consigo mesma (`localhost`).
O servidor de desenvolvimento escutará no endereço de IP `127.0.0.1` por padrão, este é o IP que sua máquina usa para se comunicar com ela mesma (`localhost`). ## `fastapi run` { #fastapi-run }
## `fastapi run` Executar `fastapi run` inicia o FastAPI em modo de produção por padrão.
Quando você rodar `fastapi run`, isso executará em modo de produção por padrão. Por padrão, o recarregamento automático está desativado. Ele também escuta no endereço IP `0.0.0.0`, o que significa todos os endereços IP disponíveis; dessa forma, ficará acessível publicamente para qualquer pessoa que consiga se comunicar com a máquina. É assim que você normalmente o executaria em produção, por exemplo, em um contêiner.
Este modo terá **recarregamento automático desativado** por padrão. Na maioria dos casos, você teria (e deveria ter) um "proxy de terminação" tratando o HTTPS por cima; isso dependerá de como você faz o deploy da sua aplicação, seu provedor pode fazer isso por você ou talvez seja necessário que você configure isso por conta própria.
Isso irá escutar no endereço de IP `0.0.0.0`, o que significa todos os endereços IP disponíveis, dessa forma o programa estará acessível publicamente para qualquer um que consiga se comunicar com a máquina. Isso é como você normalmente roda em produção em um contêiner, por exemplo. /// tip | Dica
Em muitos casos você pode ter (e deveria ter) um "proxy de saída" tratando HTTPS no topo, isso dependerá de como você fará o deploy da sua aplicação, seu provedor pode fazer isso pra você ou talvez seja necessário fazer você mesmo. Você pode aprender mais sobre isso na [documentação de deployment](deployment/index.md){.internal-link target=_blank}.
/// tip
Você pode aprender mais sobre em [documentação de deployment](deployment/index.md){.internal-link target=_blank}.
/// ///

View File

@ -1,19 +1,19 @@
# Recursos # Recursos { #features }
## Recursos do FastAPI ## Recursos do FastAPI { #fastapi-features }
**FastAPI** te oferece o seguinte: **FastAPI** te oferece o seguinte:
### Baseado em padrões abertos ### Baseado em padrões abertos { #based-on-open-standards }
* <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a> para criação de APIs, incluindo declarações de <abbr title="também conhecido como métodos HTTP, como POST, GET, PUT, DELETE">operações</abbr> de <abbr title="também conhecido como: endpoints, routes">caminho</abbr>, parâmetros, requisições de corpo, segurança etc. * <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a> para criação de APIs, incluindo declarações de <abbr title="também conhecido como: endpoints, routes">caminho</abbr> <abbr title="também conhecido como métodos HTTP, como POST, GET, PUT, DELETE">operações</abbr>, parâmetros, requisições de corpo, segurança etc.
* Modelo de documentação automática com <a href="https://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> (já que o OpenAPI em si é baseado no JSON Schema). * Modelo de documentação automática com <a href="https://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> (já que o OpenAPI em si é baseado no JSON Schema).
* Projetado em cima desses padrões após um estudo meticuloso, em vez de uma reflexão breve. * Projetado em cima desses padrões após um estudo meticuloso, em vez de uma reflexão breve.
* Isso também permite o uso de **geração de código do cliente** automaticamente em muitas linguagens. * Isso também permite o uso de **geração de código do cliente** automaticamente em muitas linguagens.
### Documentação automática ### Documentação automática { #automatic-docs }
Documentação interativa da API e navegação _web_ da interface de usuário. Como o _framework_ é baseado no OpenAPI, há várias opções, 2 incluídas por padrão. Documentação interativa da API e navegação web da interface de usuário. Como o framework é baseado no OpenAPI, há várias opções, 2 incluídas por padrão.
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank"><strong>Swagger UI</strong></a>, com navegação interativa, chame e teste sua API diretamente do navegador. * <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank"><strong>Swagger UI</strong></a>, com navegação interativa, chame e teste sua API diretamente do navegador.
@ -23,9 +23,9 @@ Documentação interativa da API e navegação _web_ da interface de usuário. C
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Apenas Python moderno ### Apenas Python moderno { #just-modern-python }
Tudo é baseado no padrão das declarações de **tipos do Python 3.8** (graças ao Pydantic). Nenhuma sintaxe nova para aprender. Apenas o padrão moderno do Python. Tudo é baseado no padrão das declarações de **tipos do Python** (graças ao Pydantic). Nenhuma sintaxe nova para aprender. Apenas o padrão moderno do Python.
Se você precisa refrescar a memória rapidamente sobre como usar tipos do Python (mesmo que você não use o FastAPI), confira esse rápido tutorial: [Tipos do Python](python-types.md){.internal-link target=_blank}. Se você precisa refrescar a memória rapidamente sobre como usar tipos do Python (mesmo que você não use o FastAPI), confira esse rápido tutorial: [Tipos do Python](python-types.md){.internal-link target=_blank}.
@ -63,7 +63,7 @@ second_user_data = {
my_second_user: User = User(**second_user_data) my_second_user: User = User(**second_user_data)
``` ```
/// info /// info | Informação
`**second_user_data` quer dizer: `**second_user_data` quer dizer:
@ -71,13 +71,13 @@ Passe as chaves e valores do dicionário `second_user_data` diretamente como arg
/// ///
### Suporte de editores ### Suporte de editores { #editor-support }
Todo o _framework_ foi projetado para ser fácil e intuitivo de usar, todas as decisões foram testadas em vários editores antes do início do desenvolvimento, para garantir a melhor experiência de desenvolvimento. Todo o framework foi projetado para ser fácil e intuitivo de usar, todas as decisões foram testadas em vários editores antes do início do desenvolvimento, para garantir a melhor experiência de desenvolvimento.
Na última pesquisa do desenvolvedor Python ficou claro <a href="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features" class="external-link" target="_blank">que o recurso mais utilizado é o "auto completar"</a>. Na pesquisa de desenvolvedores Python, ficou claro <a href="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features" class="external-link" target="_blank">que um dos recursos mais utilizados é o "preenchimento automático"</a>.
Todo o _framework_ **FastAPI** é feito para satisfazer isso. Auto completação funciona em todos os lugares. Todo o framework **FastAPI** é feito para satisfazer isso. O preenchimento automático funciona em todos os lugares.
Você raramente precisará voltar à documentação. Você raramente precisará voltar à documentação.
@ -91,17 +91,17 @@ Aqui está como o editor poderá te ajudar:
![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) ![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png)
Você terá completação do seu código que você poderia considerar impossível antes. Como por exemplo, a chave `price` dentro do corpo JSON (que poderia ter sido aninhado) que vem de uma requisição. Você terá preenchimento automático no seu código que você poderia considerar impossível antes. Como por exemplo, a chave `price` dentro do corpo JSON (que poderia ter sido aninhado) que vem de uma requisição.
Sem a necessidade de digitar nomes de chaves erroneamente, ir e voltar entre documentações, ou rolar pela página para descobrir se você utilizou `username` or `user_name`. Sem a necessidade de digitar nomes de chaves erroneamente, ir e voltar entre documentações, ou rolar pela página para descobrir se você utilizou `username` ou `user_name`.
### Breve ### Breve { #short }
**padrões** sensíveis para tudo, com configurações adicionais em todos os lugares. Todos os parâmetros podem ser regulados para fazer o que você precisa e para definir a API que você necessita. **padrões** sensíveis para tudo, com configurações adicionais em todos os lugares. Todos os parâmetros podem ser regulados para fazer o que você precisa e para definir a API que você necessita.
Por padrão, tudo **"simplesmente funciona"**. Por padrão, tudo **"simplesmente funciona"**.
### Validação ### Validação { #validation }
* Validação para a maioria dos (ou todos?) **tipos de dados** do Python, incluindo: * Validação para a maioria dos (ou todos?) **tipos de dados** do Python, incluindo:
* objetos JSON (`dict`). * objetos JSON (`dict`).
@ -117,7 +117,7 @@ Por padrão, tudo **"simplesmente funciona"**.
Toda a validação é controlada pelo robusto e bem estabelecido **Pydantic**. Toda a validação é controlada pelo robusto e bem estabelecido **Pydantic**.
### Segurança e autenticação ### Segurança e autenticação { #security-and-authentication }
Segurança e autenticação integradas. Sem nenhum compromisso com bancos de dados ou modelos de dados. Segurança e autenticação integradas. Sem nenhum compromisso com bancos de dados ou modelos de dados.
@ -130,34 +130,34 @@ Todos os esquemas de seguranças definidos no OpenAPI, incluindo:
* parâmetros da Query. * parâmetros da Query.
* Cookies etc. * Cookies etc.
Além disso, todos os recursos de seguranças do Starlette (incluindo **cookies de sessão**). Além disso, todos os recursos de segurança do Starlette (incluindo **cookies de sessão**).
Tudo construído como ferramentas e componentes reutilizáveis que são fáceis de integrar com seus sistemas, armazenamento de dados, banco de dados relacionais e não-relacionais etc. Tudo construído como ferramentas e componentes reutilizáveis que são fáceis de integrar com seus sistemas, armazenamento de dados, banco de dados relacionais e não-relacionais etc.
### Injeção de dependência ### Injeção de dependência { #dependency-injection }
FastAPI inclui um sistema de <abbr title='também conhecido como "components", "resources", "services", "providers"'><strong>injeção de dependência</strong></abbr> extremamente fácil de usar, mas extremamente poderoso. FastAPI inclui um sistema de <abbr title='também conhecido como "components", "resources", "services", "providers"'><strong>injeção de dependência</strong></abbr> extremamente fácil de usar, mas extremamente poderoso.
* Mesmo dependências podem ter dependências, criando uma hierarquia ou **"grafo" de dependências**. * Mesmo dependências podem ter dependências, criando uma hierarquia ou **"grafo" de dependências**.
* Tudo **automaticamente controlado** pelo _framework_. * Tudo **automaticamente controlado** pelo framework.
* Todas as dependências podem pedir dados das requisições e **ampliar** as restrições e documentação automática da **operação de caminho**. * Todas as dependências podem pedir dados das requisições e **ampliar** as restrições e documentação automática da **operação de caminho**.
* **Validação automática** mesmo para parâmetros da *operação de caminho* definidos em dependências. * **Validação automática** mesmo para parâmetros da *operação de caminho* definidos em dependências.
* Suporte para sistemas de autenticação complexos, **conexões com banco de dados** etc. * Suporte para sistemas de autenticação complexos, **conexões com banco de dados** etc.
* **Sem comprometer** os bancos de dados, _frontends_ etc. Mas fácil integração com todos eles. * **Sem comprometer** os bancos de dados, frontends etc. Mas fácil integração com todos eles.
### "Plug-ins" ilimitados ### "Plug-ins" ilimitados { #unlimited-plug-ins }
Ou, de outra forma, sem a necessidade deles, importe e use o código que precisar. Ou, de outra forma, sem a necessidade deles, importe e use o código que precisar.
Qualquer integração é projetada para ser tão simples de usar (com dependências) que você pode criar um "plug-in" para suas aplicações com 2 linhas de código usando a mesma estrutura e sintaxe para as suas *operações de caminho*. Qualquer integração é projetada para ser tão simples de usar (com dependências) que você pode criar um "plug-in" para suas aplicações com 2 linhas de código usando a mesma estrutura e sintaxe para as suas *operações de caminho*.
### Testado ### Testado { #tested }
* 100% <abbr title="A quantidade de código que é testada automaticamente">de cobertura de testes</abbr>. * 100% <abbr title="A quantidade de código que é testada automaticamente">de cobertura de testes</abbr>.
* 100% do código utiliza <abbr title="Type annotations do Python, com isso seu editor e ferramentas externas podem te dar um suporte melhor">type annotations</abbr>. * 100% do código com <abbr title="Anotações de tipo do Python, com isso seu editor e ferramentas externas podem te dar um suporte melhor">anotações de tipo</abbr>.
* Usado para aplicações em produção. * Usado para aplicações em produção.
## Recursos do Starlette ## Recursos do Starlette { #starlette-features }
**FastAPI** é totalmente compatível com (e baseado no) <a href="https://www.starlette.dev/" class="external-link" target="_blank"><strong>Starlette</strong></a>. Então, qualquer código adicional Starlette que você tiver, também funcionará. **FastAPI** é totalmente compatível com (e baseado no) <a href="https://www.starlette.dev/" class="external-link" target="_blank"><strong>Starlette</strong></a>. Então, qualquer código adicional Starlette que você tiver, também funcionará.
@ -165,18 +165,17 @@ Qualquer integração é projetada para ser tão simples de usar (com dependênc
Com **FastAPI**, você terá todos os recursos do **Starlette** (já que FastAPI é apenas um Starlette com esteróides): Com **FastAPI**, você terá todos os recursos do **Starlette** (já que FastAPI é apenas um Starlette com esteróides):
* Desempenho realmente impressionante. É <a href="https://github.com/encode/starlette#performance" class="external-link" target="_blank">um dos _frameworks_ Python disponíveis mais rápidos, a par com o **NodeJS** e **Go**</a>. * Desempenho realmente impressionante. É <a href="https://github.com/encode/starlette#performance" class="external-link" target="_blank">um dos frameworks Python disponíveis mais rápidos, a par com o **NodeJS** e **Go**</a>.
* Suporte a **WebSocket**. * Suporte a **WebSocket**.
* Suporte a **GraphQL**. * Tarefas em processo background.
* Tarefas em processo _background_.
* Eventos na inicialização e encerramento. * Eventos na inicialização e encerramento.
* Cliente de testes construído sobre HTTPX. * Cliente de testes construído sobre HTTPX.
* Respostas em **CORS**, GZip, Static Files, Streaming. * Respostas em **CORS**, GZip, Static Files, Streaming.
* Suporte a **Session e Cookie**. * Suporte a **Session e Cookie**.
* 100% de cobertura de testes. * 100% de cobertura de testes.
* 100% do código utilizando _type annotations_. * 100% do código utilizando anotações de tipo.
## Recursos do Pydantic ## Recursos do Pydantic { #pydantic-features }
**FastAPI** é totalmente compatível com (e baseado no) <a href="https://docs.pydantic.dev/" class="external-link" target="_blank"><strong>Pydantic</strong></a>. Então, qualquer código Pydantic adicional que você tiver, também funcionará. **FastAPI** é totalmente compatível com (e baseado no) <a href="https://docs.pydantic.dev/" class="external-link" target="_blank"><strong>Pydantic</strong></a>. Então, qualquer código Pydantic adicional que você tiver, também funcionará.
@ -192,7 +191,7 @@ Com **FastAPI** você terá todos os recursos do **Pydantic** (já que FastAPI u
* Sem novas definições de esquema de micro-linguagem para aprender. * Sem novas definições de esquema de micro-linguagem para aprender.
* Se você conhece os tipos do Python, você sabe como usar o Pydantic. * Se você conhece os tipos do Python, você sabe como usar o Pydantic.
* Vai bem com o/a seu/sua **<abbr title="Ambiente de Desenvolvimento Integrado, similar a um editor de código">IDE</abbr>/<abbr title="Um programa que confere erros de código">linter</abbr>/cérebro**: * Vai bem com o/a seu/sua **<abbr title="Ambiente de Desenvolvimento Integrado, similar a um editor de código">IDE</abbr>/<abbr title="Um programa que confere erros de código">linter</abbr>/cérebro**:
* Como as estruturas de dados do Pydantic são apenas instâncias de classes que você define, a auto completação, _linting_, _mypy_ e a sua intuição devem funcionar corretamente com seus dados validados. * Como as estruturas de dados do Pydantic são apenas instâncias de classes que você define, o preenchimento automático, linting, mypy e a sua intuição devem funcionar corretamente com seus dados validados.
* Valida **estruturas complexas**: * Valida **estruturas complexas**:
* Use modelos hierárquicos do Pydantic, `List` e `Dict` do `typing` do Python, etc. * Use modelos hierárquicos do Pydantic, `List` e `Dict` do `typing` do Python, etc.
* Validadores permitem que esquemas de dados complexos sejam limpos e facilmente definidos, conferidos e documentados como JSON Schema. * Validadores permitem que esquemas de dados complexos sejam limpos e facilmente definidos, conferidos e documentados como JSON Schema.

View File

@ -1,149 +1,256 @@
# Ajuda FastAPI - Obter Ajuda # Ajude o FastAPI - Obtenha ajuda { #help-fastapi-get-help }
Você gosta do **FastAPI**? Você gosta do **FastAPI**?
Você gostaria de ajudar o FastAPI, outros usários, e o autor? Você gostaria de ajudar o FastAPI, outras pessoas usuárias e o autor?
Ou você gostaria de obter ajuda relacionada ao **FastAPI**?? Ou você gostaria de obter ajuda com o **FastAPI**?
Existem métodos muito simples de ajudar (A maioria das ajudas podem ser feitas com um ou dois cliques). Há maneiras muito simples de ajudar (várias envolvem apenas um ou dois cliques).
E também existem vários modos de se conseguir ajuda. E também há várias formas de obter ajuda.
## Inscreva-se na newsletter ## Assine a newsletter { #subscribe-to-the-newsletter }
Você pode se inscrever (pouco frequente) [**FastAPI e amigos** newsletter](newsletter.md){.internal-link target=_blank} para receber atualizações: Você pode assinar a (infrequente) [newsletter do **FastAPI and friends**](newsletter.md){.internal-link target=_blank} para ficar por dentro de:
* Notícias sobre FastAPI e amigos 🚀 * Notícias sobre FastAPI e amigos 🚀
* Tutoriais 📝 * Tutoriais 📝
* Recursos ✨ * Funcionalidades ✨
* Mudanças de última hora 🚨 * Mudanças incompatíveis 🚨
* Truques e dicas ✅ * Dicas e truques ✅
## Siga o FastAPI no X (Twitter) ## Siga o FastAPI no X (Twitter) { #follow-fastapi-on-x-twitter }
<a href="https://x.com/fastapi" class="external-link" target="_blank">Siga @fastapi no **X (Twitter)**</a> para receber as últimas notícias sobre o **FastAPI**. 🐦 <a href="https://x.com/fastapi" class="external-link" target="_blank">Siga @fastapi no **X (Twitter)**</a> para receber as últimas notícias sobre o **FastAPI**. 🐦
## Favorite o **FastAPI** no GitHub ## Dê uma estrela ao **FastAPI** no GitHub { #star-fastapi-in-github }
Você pode "favoritar" o FastAPI no GitHub (clicando na estrela no canto superior direito): <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>. ⭐️ Você pode “marcar com estrela” o FastAPI no GitHub (clicando no botão de estrela no canto superior direito): <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>. ⭐️
Favoritando, outros usuários poderão encontrar mais facilmente e verão que já foi útil para muita gente. Ao adicionar uma estrela, outras pessoas conseguirão encontrá-lo com mais facilidade e verão que já foi útil para muita gente.
## Acompanhe novos updates no repositorio do GitHub ## Acompanhe o repositório no GitHub para lançamentos { #watch-the-github-repository-for-releases }
Você pode "acompanhar" (watch) o FastAPI no GitHub (clicando no botão com um "olho" no canto superior direito): <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>. 👀 Você pode “acompanhar” (watch) o FastAPI no GitHub (clicando no botão “watch” no canto superior direito): <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>. 👀
Podendo selecionar apenas "Novos Updates". Lá você pode selecionar “Apenas lançamentos” (Releases only).
Fazendo isto, serão enviadas notificações (em seu email) sempre que tiver novos updates (uma nova versão) com correções de bugs e novos recursos no **FastAPI** Fazendo isso, você receberá notificações (no seu email) sempre que houver um novo lançamento (uma nova versão) do **FastAPI** com correções de bugs e novas funcionalidades.
## Conect-se com o autor ## Conecte-se com o autor { #connect-with-the-author }
Você pode se conectar <a href="https://tiangolo.com" class="external-link" target="_blank">comigo (Sebastián Ramírez / `tiangolo`)</a>, o autor. Você pode se conectar <a href="https://tiangolo.com" class="external-link" target="_blank">comigo (Sebastián Ramírez / `tiangolo`)</a>, o autor.
Você pode: Você pode:
* <a href="https://github.com/tiangolo" class="external-link" target="_blank">Me siga no **GitHub**</a>. * <a href="https://github.com/tiangolo" class="external-link" target="_blank">Me seguir no **GitHub**</a>.
* Ver também outros projetos Open Source criados por mim que podem te ajudar. * Ver outros projetos Open Source que criei e que podem ajudar você.
* Me seguir para saber quando um novo projeto Open Source for criado. * Me seguir para saber quando eu criar um novo projeto Open Source.
* <a href="https://x.com/tiangolo" class="external-link" target="_blank">Me siga no **X (Twitter)**</a>. * <a href="https://x.com/tiangolo" class="external-link" target="_blank">Me seguir no **X (Twitter)**</a> ou no <a href="https://fosstodon.org/@tiangolo" class="external-link" target="_blank">Mastodon</a>.
* Me dizer o motivo pelo o qual você está usando o FastAPI(Adoro ouvir esse tipo de comentário). * Me contar como você usa o FastAPI (adoro saber disso).
* Saber quando eu soltar novos anúncios ou novas ferramentas. * Ficar sabendo quando eu fizer anúncios ou lançar novas ferramentas.
* Também é possivel <a href="https://x.com/fastapi" class="external-link" target="_blank">seguir o @fastapi no X (Twitter)</a> (uma conta aparte). * Você também pode <a href="https://x.com/fastapi" class="external-link" target="_blank">seguir @fastapi no X (Twitter)</a> (uma conta separada).
* <a href="https://www.linkedin.com/in/tiangolo/" class="external-link" target="_blank">Conect-se comigo no **Linkedin**</a>. * <a href="https://www.linkedin.com/in/tiangolo/" class="external-link" target="_blank">Me seguir no **LinkedIn**</a>.
* Saber quando eu fizer novos anúncios ou novas ferramentas (apesar de que uso o X (Twitter) com mais frequência 🤷‍♂). * Ver quando eu fizer anúncios ou lançar novas ferramentas (embora eu use mais o X (Twitter) 🤷‍♂).
* Ler meus artigos (ou me seguir) no <a href="https://dev.to/tiangolo" class="external-link" target="_blank">**Dev.to**</a> ou no <a href="https://medium.com/@tiangolo" class="external-link" target="_blank">**Medium**</a>. * Ler o que escrevo (ou me seguir) no <a href="https://dev.to/tiangolo" class="external-link" target="_blank">**Dev.to**</a> ou no <a href="https://medium.com/@tiangolo" class="external-link" target="_blank">**Medium**</a>.
* Ficar por dentro de novas ideias, artigos, e ferramentas criadas por mim. * Ler outras ideias, artigos e conhecer ferramentas que criei.
* Me siga para saber quando eu publicar algo novo. * Me seguir para ver quando eu publicar algo novo.
## Tweete sobre **FastAPI** ## Tweet sobre o **FastAPI** { #tweet-about-fastapi }
<a href="https://x.com/compose/tweet?text=I'm loving @fastapi because... https://github.com/fastapi/fastapi" class="external-link" target="_blank">Tweete sobre o **FastAPI**</a> e compartilhe comigo e com os outros o porque de gostar do FastAPI. 🎉 <a href="https://x.com/compose/tweet?text=I'm loving @fastapi because... https://github.com/fastapi/fastapi" class="external-link" target="_blank">Tweet sobre o **FastAPI**</a> e conte para mim e para outras pessoas por que você gosta dele. 🎉
Adoro ouvir sobre como o **FastAPI** é usado, o que você gosta nele, em qual projeto/empresa está sendo usado, etc. Eu adoro saber como o **FastAPI** está sendo usado, o que você tem curtido nele, em qual projeto/empresa você o utiliza, etc.
## Vote no FastAPI ## Vote no FastAPI { #vote-for-fastapi }
* <a href="https://www.slant.co/options/34241/~fastapi-review" class="external-link" target="_blank">Vote no **FastAPI** no Slant</a>. * <a href="https://www.slant.co/options/34241/~fastapi-review" class="external-link" target="_blank">Vote no **FastAPI** no Slant</a>.
* <a href="https://alternativeto.net/software/fastapi/" class="external-link" target="_blank">Vote no **FastAPI** no AlternativeTo</a>. * <a href="https://alternativeto.net/software/fastapi/about/" class="external-link" target="_blank">Vote no **FastAPI** no AlternativeTo</a>.
* <a href="https://stackshare.io/pypi-fastapi" class="external-link" target="_blank">Diga que você usa o **FastAPI** no StackShare</a>.
## Responda perguntas no GitHub ## Ajude outras pessoas com perguntas no GitHub { #help-others-with-questions-in-github }
Você pode acompanhar as <a href="https://github.com/fastapi/fastapi/issues" class="external-link" target="_blank">perguntas existentes</a> e tentar ajudar outros, . 🤓 Você pode tentar ajudar outras pessoas com suas perguntas em:
Ajudando a responder as questões de varias pessoas, você pode se tornar um [Expert em FastAPI](fastapi-people.md#especialistas){.internal-link target=_blank} oficial. 🎉 * <a href="https://github.com/fastapi/fastapi/discussions/categories/questions?discussions_q=category%3AQuestions+is%3Aunanswered" class="external-link" target="_blank">GitHub Discussions</a>
* <a href="https://github.com/fastapi/fastapi/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Aquestion+-label%3Aanswered+" class="external-link" target="_blank">GitHub Issues</a>
## Acompanhe o repositório do GitHub Em muitos casos você já pode saber a resposta para aquelas perguntas. 🤓
Você pode "acompanhar" (watch) o FastAPI no GitHub (clicando no "olho" no canto superior direito): <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>. 👀 Se você estiver ajudando muitas pessoas com suas perguntas, você se tornará um(a) [Especialista em FastAPI](fastapi-people.md#fastapi-experts){.internal-link target=_blank} oficial. 🎉
Se você selecionar "Acompanhando" (Watching) em vez de "Apenas Lançamentos" (Releases only) você receberá notificações quando alguém tiver uma nova pergunta. Apenas lembre-se, o ponto mais importante é: tente ser gentil. As pessoas chegam com frustrações e, em muitos casos, não perguntam da melhor forma, mas tente ao máximo ser gentil. 🤗
Assim podendo tentar ajudar a resolver essas questões. A ideia é que a comunidade do **FastAPI** seja gentil e acolhedora. Ao mesmo tempo, não aceite bullying ou comportamentos desrespeitosos com outras pessoas. Temos que cuidar uns dos outros.
## Faça perguntas
É possível <a href="https://github.com/fastapi/fastapi/issues/new/choose" class="external-link" target="_blank">criar uma nova pergunta</a> no repositório do GitHub, por exemplo:
* Faça uma **pergunta** ou pergunte sobre um **problema**.
* Sugira novos **recursos**.
**Nota**: Se você fizer uma pergunta, então eu gostaria de pedir que você também ajude os outros com suas respectivas perguntas. 😉
## Crie um Pull Request
É possível [contribuir](contributing.md){.internal-link target=_blank} no código fonte fazendo Pull Requests, por exemplo:
* Para corrigir um erro de digitação que você encontrou na documentação.
* Para compartilhar um artigo, video, ou podcast criados por você sobre o FastAPI <a href="https://github.com/fastapi/fastapi/edit/master/docs/en/data/external_links.yml" class="external-link" target="_blank">editando este arquivo</a>.
* Não se esqueça de adicionar o link no começo da seção correspondente.
* Para ajudar [traduzir a documentação](contributing.md#traducoes){.internal-link target=_blank} para sua lingua.
* Também é possivel revisar as traduções já existentes.
* Para propor novas seções na documentação.
* Para corrigir um bug/questão.
* Para adicionar um novo recurso.
## Entre no chat
Entre no 👥 <a href="https://discord.gg/VQjSZaeJmf" class="external-link" target="_blank">server de conversa do Discord</a> 👥 e conheça novas pessoas da comunidade
do FastAPI.
/// tip | Dica
Para perguntas, pergunte nas <a href="https://github.com/fastapi/fastapi/issues/new/choose" class="external-link" target="_blank">questões do GitHub</a>, lá tem um chance maior de você ser ajudado sobre o FastAPI [FastAPI Experts](fastapi-people.md#especialistas){.internal-link target=_blank}.
Use o chat apenas para outro tipo de assunto.
///
### Não faça perguntas no chat
Tenha em mente que os chats permitem uma "conversa mais livre", dessa forma é muito fácil fazer perguntas que são muito genéricas e dificeís de responder, assim você pode acabar não sendo respondido.
Nas questões do GitHub o template irá te guiar para que você faça a sua pergunta de um jeito mais correto, fazendo com que você receba respostas mais completas, e até mesmo que você mesmo resolva o problema antes de perguntar. E no GitHub eu garanto que sempre irei responder todas as perguntas, mesmo que leve um tempo. Eu pessoalmente não consigo fazer isso via chat. 😅
Conversas no chat não são tão fáceis de serem encontrados quanto no GitHub, então questões e respostas podem se perder dentro da conversa. E apenas as que estão nas questões do GitHub contam para você se tornar um [Expert em FastAPI](fastapi-people.md#especialistas){.internal-link target=_blank}, então você receberá mais atenção nas questões do GitHub.
Por outro lado, existem milhares de usuários no chat, então tem uma grande chance de você encontrar alguém para trocar uma idéia por lá em qualquer horário. 😄
## Patrocine o autor
Você também pode ajudar o autor financeiramente (eu) através do <a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">GitHub sponsors</a>.
Lá você pode me pagar um cafézinho ☕️ como agradecimento. 😄
E você também pode se tornar um patrocinador Prata ou Ouro do FastAPI. 🏅🎉
## Patrocine as ferramente que potencializam o FastAPI
Como você viu na documentação, o FastAPI se apoia em nos gigantes, Starlette e Pydantic.
Patrocine também:
* <a href="https://github.com/sponsors/samuelcolvin" class="external-link" target="_blank">Samuel Colvin (Pydantic)</a>
* <a href="https://github.com/sponsors/encode" class="external-link" target="_blank">Encode (Starlette, Uvicorn)</a>
--- ---
Muito Obrigado! 🚀 Veja como ajudar outras pessoas com perguntas (em discussions ou issues):
### Entenda a pergunta { #understand-the-question }
* Verifique se você consegue entender qual é o **objetivo** e o caso de uso de quem está perguntando.
* Depois verifique se a pergunta (a grande maioria são perguntas) está **clara**.
* Em muitos casos a pergunta feita é sobre uma solução imaginada pela pessoa usuária, mas pode haver uma solução **melhor**. Se você entender melhor o problema e o caso de uso, pode sugerir uma **solução alternativa** melhor.
* Se você não entender a pergunta, peça mais **detalhes**.
### Reproduza o problema { #reproduce-the-problem }
Na maioria dos casos e na maioria das perguntas há algo relacionado ao **código original** da pessoa.
Em muitos casos ela só copia um fragmento do código, mas isso não é suficiente para **reproduzir o problema**.
* Você pode pedir que forneçam um <a href="https://stackoverflow.com/help/minimal-reproducible-example" class="external-link" target="_blank">exemplo mínimo, reproduzível</a>, que você possa **copiar e colar** e executar localmente para ver o mesmo erro ou comportamento que elas estão vendo, ou para entender melhor o caso de uso.
* Se você estiver muito generoso(a), pode tentar **criar um exemplo** assim você mesmo(a), apenas com base na descrição do problema. Só tenha em mente que isso pode levar bastante tempo e pode ser melhor pedir primeiro que esclareçam o problema.
### Sugira soluções { #suggest-solutions }
* Depois de conseguir entender a pergunta, você pode dar uma possível **resposta**.
* Em muitos casos, é melhor entender o **problema subjacente ou caso de uso**, pois pode haver uma forma melhor de resolver do que aquilo que estão tentando fazer.
### Peça para encerrar { #ask-to-close }
Se a pessoa responder, há uma grande chance de você ter resolvido o problema, parabéns, **você é um(a) herói(na)**! 🦸
* Agora, se isso resolveu o problema, você pode pedir para:
* No GitHub Discussions: marcar o comentário como a **resposta**.
* No GitHub Issues: **encerrar** a issue.
## Acompanhe o repositório do GitHub { #watch-the-github-repository }
Você pode “acompanhar” (watch) o FastAPI no GitHub (clicando no botão “watch” no canto superior direito): <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>. 👀
Se você selecionar “Acompanhando” (Watching) em vez de “Apenas lançamentos” (Releases only), receberá notificações quando alguém criar uma nova issue ou pergunta. Você também pode especificar que quer ser notificado(a) apenas sobre novas issues, ou discussions, ou PRs, etc.
Assim você pode tentar ajudar a resolver essas questões.
## Faça perguntas { #ask-questions }
Você pode <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">criar uma nova pergunta</a> no repositório do GitHub, por exemplo para:
* Fazer uma **pergunta** ou perguntar sobre um **problema**.
* Sugerir uma nova **funcionalidade**.
**Nota**: se você fizer isso, então vou pedir que você também ajude outras pessoas. 😉
## Revise Pull Requests { #review-pull-requests }
Você pode me ajudar revisando pull requests de outras pessoas.
Novamente, por favor tente ao máximo ser gentil. 🤗
---
Veja o que ter em mente e como revisar um pull request:
### Entenda o problema { #understand-the-problem }
* Primeiro, garanta que você **entendeu o problema** que o pull request tenta resolver. Pode haver uma discussão mais longa em uma Discussion ou issue do GitHub.
* Também há uma boa chance de o pull request não ser realmente necessário porque o problema pode ser resolvido de uma **forma diferente**. Aí você pode sugerir ou perguntar sobre isso.
### Não se preocupe com estilo { #dont-worry-about-style }
* Não se preocupe muito com coisas como estilos de mensagens de commit, eu vou fazer squash e merge personalizando o commit manualmente.
* Também não se preocupe com regras de estilo, já há ferramentas automatizadas verificando isso.
E se houver qualquer outra necessidade de estilo ou consistência, vou pedir diretamente, ou vou adicionar commits por cima com as mudanças necessárias.
### Verifique o código { #check-the-code }
* Verifique e leia o código, veja se faz sentido, **execute localmente** e veja se realmente resolve o problema.
* Depois **comente** dizendo que você fez isso, é assim que saberei que você realmente verificou.
/// info | Informação
Infelizmente, eu não posso simplesmente confiar em PRs que têm várias aprovações.
Já aconteceu várias vezes de haver PRs com 3, 5 ou mais aprovações, provavelmente porque a descrição é atraente, mas quando eu verifico os PRs, eles estão quebrados, têm um bug, ou não resolvem o problema que afirmam resolver. 😅
Por isso, é realmente importante que você leia e execute o código, e me avise nos comentários que você fez isso. 🤓
///
* Se o PR puder ser simplificado de alguma forma, você pode pedir isso, mas não há necessidade de ser exigente demais, pode haver muitos pontos de vista subjetivos (e eu terei o meu também 🙈), então é melhor focar nas coisas fundamentais.
### Testes { #tests }
* Me ajude a verificar se o PR tem **testes**.
* Verifique se os testes **falham** antes do PR. 🚨
* Depois verifique se os testes **passam** após o PR. ✅
* Muitos PRs não têm testes, você pode **lembrar** a pessoa de adicionar testes, ou até **sugerir** alguns testes você mesmo(a). Essa é uma das coisas que consomem mais tempo e você pode ajudar muito com isso.
* Depois também comente o que você testou, assim vou saber que você verificou. 🤓
## Crie um Pull Request { #create-a-pull-request }
Você pode [contribuir](contributing.md){.internal-link target=_blank} com o código-fonte fazendo Pull Requests, por exemplo:
* Para corrigir um erro de digitação que você encontrou na documentação.
* Para compartilhar um artigo, vídeo ou podcast que você criou ou encontrou sobre o FastAPI, <a href="https://github.com/fastapi/fastapi/edit/master/docs/en/data/external_links.yml" class="external-link" target="_blank">editando este arquivo</a>.
* Garanta que você adicione seu link no início da seção correspondente.
* Para ajudar a [traduzir a documentação](contributing.md#translations){.internal-link target=_blank} para seu idioma.
* Você também pode ajudar a revisar as traduções criadas por outras pessoas.
* Para propor novas seções de documentação.
* Para corrigir uma issue/bug existente.
* Garanta que você adicione testes.
* Para adicionar uma nova funcionalidade.
* Garanta que você adicione testes.
* Garanta que você adicione documentação se for relevante.
## Ajude a manter o FastAPI { #help-maintain-fastapi }
Ajude-me a manter o **FastAPI**! 🤓
Há muito trabalho a fazer e, para a maior parte dele, **VOCÊ** pode ajudar.
As principais tarefas que você pode fazer agora são:
* [Ajudar outras pessoas com perguntas no GitHub](#help-others-with-questions-in-github){.internal-link target=_blank} (veja a seção acima).
* [Revisar Pull Requests](#review-pull-requests){.internal-link target=_blank} (veja a seção acima).
Essas duas tarefas são as que **mais consomem tempo**. Esse é o principal trabalho de manter o FastAPI.
Se você puder me ajudar com isso, **você está me ajudando a manter o FastAPI** e garantindo que ele continue **avançando mais rápido e melhor**. 🚀
## Entre no chat { #join-the-chat }
Entre no 👥 <a href="https://discord.gg/VQjSZaeJmf" class="external-link" target="_blank">servidor de chat do Discord</a> 👥 e converse com outras pessoas da comunidade FastAPI.
/// tip | Dica
Para perguntas, faça-as no <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">GitHub Discussions</a>, há uma chance muito maior de você receber ajuda pelos [Especialistas em FastAPI](fastapi-people.md#fastapi-experts){.internal-link target=_blank}.
Use o chat apenas para outras conversas gerais.
///
### Não use o chat para perguntas { #dont-use-the-chat-for-questions }
Tenha em mente que, como os chats permitem uma “conversa mais livre”, é fácil fazer perguntas muito gerais e mais difíceis de responder, então você pode acabar não recebendo respostas.
No GitHub, o template vai orientar você a escrever a pergunta certa para que você consiga obter uma boa resposta com mais facilidade, ou até resolver o problema sozinho(a) antes de perguntar. E no GitHub eu consigo garantir que sempre vou responder tudo, mesmo que leve algum tempo. Eu pessoalmente não consigo fazer isso com os sistemas de chat. 😅
As conversas nos sistemas de chat também não são tão fáceis de pesquisar quanto no GitHub, então perguntas e respostas podem se perder na conversa. E somente as que estão no GitHub contam para você se tornar um(a) [Especialista em FastAPI](fastapi-people.md#fastapi-experts){.internal-link target=_blank}, então é bem provável que você receba mais atenção no GitHub.
Por outro lado, há milhares de usuários nos sistemas de chat, então há uma grande chance de você encontrar alguém para conversar por lá quase o tempo todo. 😄
## Patrocine o autor { #sponsor-the-author }
Se o seu **produto/empresa** depende de ou está relacionado ao **FastAPI** e você quer alcançar suas pessoas usuárias, você pode patrocinar o autor (eu) através do <a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">GitHub sponsors</a>. Dependendo do nível, você pode obter benefícios extras, como um selo na documentação. 🎁
---
Obrigado! 🚀

View File

@ -1,4 +1,4 @@
# História, Design e Futuro # História, Design e Futuro { #history-design-and-future }
Há algum tempo, <a href="https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920" class="external-link" target="_blank">um usuário **FastAPI** perguntou</a>: Há algum tempo, <a href="https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920" class="external-link" target="_blank">um usuário **FastAPI** perguntou</a>:
@ -6,7 +6,7 @@ Há algum tempo, <a href="https://github.com/fastapi/fastapi/issues/3#issuecomme
Aqui está um pouco dessa história. Aqui está um pouco dessa história.
## Alternativas ## Alternativas { #alternatives }
Eu tenho criado APIs com requisitos complexos por vários anos (Aprendizado de Máquina, sistemas distribuídos, tarefas assíncronas, banco de dados NoSQL etc.), liderando vários times de desenvolvedores. Eu tenho criado APIs com requisitos complexos por vários anos (Aprendizado de Máquina, sistemas distribuídos, tarefas assíncronas, banco de dados NoSQL etc.), liderando vários times de desenvolvedores.
@ -28,7 +28,7 @@ Mas em algum ponto, não havia outra opção senão criar algo que oferecia toda
</blockquote> </blockquote>
## Investigação ## Investigação { #investigation }
Ao usar todas as alternativas anteriores, eu tive a chance de aprender com todas elas, aproveitar ideias e combiná-las da melhor maneira que encontrei para mim e para os times de desenvolvedores com os quais trabalhava. Ao usar todas as alternativas anteriores, eu tive a chance de aprender com todas elas, aproveitar ideias e combiná-las da melhor maneira que encontrei para mim e para os times de desenvolvedores com os quais trabalhava.
@ -38,7 +38,7 @@ Também, a melhor abordagem era usar padrões já existentes.
Então, antes mesmo de começar a codificar o **FastAPI**, eu investi vários meses estudando as especificações do OpenAPI, JSON Schema, OAuth2 etc. Entendendo suas relações, sobreposições e diferenças. Então, antes mesmo de começar a codificar o **FastAPI**, eu investi vários meses estudando as especificações do OpenAPI, JSON Schema, OAuth2 etc. Entendendo suas relações, sobreposições e diferenças.
## Design ## Design { #design }
Eu então dediquei algum tempo projetando a "API" de desenvolvimento que eu queria como usuário (como um desenvolvedor usando o FastAPI). Eu então dediquei algum tempo projetando a "API" de desenvolvimento que eu queria como usuário (como um desenvolvedor usando o FastAPI).
@ -48,23 +48,23 @@ Pela última <a href="https://www.jetbrains.com/research/python-developers-surve
Isso significa que o **FastAPI** foi testado especificamente com os editores usados por 80% dos desenvolvedores Python. Como a maioria dos outros editores tendem a funcionar de forma similar, todos os seus benefícios devem funcionar para virtualmente todos os editores. Isso significa que o **FastAPI** foi testado especificamente com os editores usados por 80% dos desenvolvedores Python. Como a maioria dos outros editores tendem a funcionar de forma similar, todos os seus benefícios devem funcionar para virtualmente todos os editores.
Dessa forma eu pude encontrar a melhor maneira de reduzir duplicação de código o máximo possível, ter completação de texto em todos os lugares, conferência de tipos e erros etc. Dessa forma eu pude encontrar a melhor maneira de reduzir duplicação de código o máximo possível, ter preenchimento automático em todos os lugares, conferência de tipos e erros etc.
Tudo de uma forma que oferecesse a melhor experiência de desenvolvimento para todos os desenvolvedores. Tudo de uma forma que oferecesse a melhor experiência de desenvolvimento para todos os desenvolvedores.
## Requisitos ## Requisitos { #requirements }
Após testar várias alternativas, eu decidi que usaria o <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">**Pydantic**</a> por suas vantagens. Após testar várias alternativas, eu decidi que usaria o <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">**Pydantic**</a> por suas vantagens.
Então eu contribuí com ele, para deixá-lo completamente de acordo com o JSON Schema, para dar suporte a diferentes maneiras de definir declarações de restrições, e melhorar o suporte a editores (conferências de tipos, auto completações) baseado nos testes em vários editores. Então eu contribuí com ele, para deixá-lo completamente de acordo com o JSON Schema, para dar suporte a diferentes maneiras de definir declarações de restrições, e melhorar o suporte a editores (conferências de tipos, preenchimento automático) baseado nos testes em vários editores.
Durante o desenvolvimento, eu também contribuí com o <a href="https://www.starlette.dev/" class="external-link" target="_blank">**Starlette**</a>, outro requisito chave. Durante o desenvolvimento, eu também contribuí com o <a href="https://www.starlette.dev/" class="external-link" target="_blank">**Starlette**</a>, outro requisito chave.
## Desenvolvimento ## Desenvolvimento { #development }
Quando comecei a criar o **FastAPI** de fato, a maior parte das peças já estavam encaixadas, o design estava definido, os requisitos e ferramentas já estavam prontos, e o conhecimento sobre os padrões e especificações estavam claros e frescos. Quando comecei a criar o **FastAPI** de fato, a maior parte das peças já estavam encaixadas, o design estava definido, os requisitos e ferramentas já estavam prontos, e o conhecimento sobre os padrões e especificações estavam claros e frescos.
## Futuro ## Futuro { #future }
Nesse ponto, já está claro que o **FastAPI** com suas ideias está sendo útil para muitas pessoas. Nesse ponto, já está claro que o **FastAPI** com suas ideias está sendo útil para muitas pessoas.

View File

@ -1,12 +1,12 @@
# OpenAPI condicional # OpenAPI condicional { #conditional-openapi }
Se necessário, você pode usar configurações e variáveis de ambiente para configurar o OpenAPI condicionalmente, dependendo do ambiente, e até mesmo desativá-lo completamente. Se necessário, você pode usar configurações e variáveis de ambiente para configurar o OpenAPI condicionalmente dependendo do ambiente e até mesmo desativá-lo completamente.
## Sobre segurança, APIs e documentos ## Sobre segurança, APIs e documentação { #about-security-apis-and-docs }
Ocultar suas interfaces de usuário de documentação na produção *não deveria* ser a maneira de proteger sua API. Ocultar suas interfaces de usuário de documentação na produção não *deveria* ser a maneira de proteger sua API.
Isso não adiciona nenhuma segurança extra à sua API; as *operações de rotas* ainda estarão disponíveis onde estão. Isso não adiciona nenhuma segurança extra à sua API; as *operações de rota* ainda estarão disponíveis onde estão.
Se houver uma falha de segurança no seu código, ela ainda existirá. Se houver uma falha de segurança no seu código, ela ainda existirá.
@ -17,15 +17,15 @@ Se você quiser proteger sua API, há várias coisas melhores que você pode faz
* Certifique-se de ter modelos Pydantic bem definidos para seus corpos de solicitação e respostas. * Certifique-se de ter modelos Pydantic bem definidos para seus corpos de solicitação e respostas.
* Configure quaisquer permissões e funções necessárias usando dependências. * Configure quaisquer permissões e funções necessárias usando dependências.
* Nunca armazene senhas em texto simples, apenas hashes de senha. * Nunca armazene senhas em texto simples, apenas hashes de senha.
* Implemente e use ferramentas criptográficas bem conhecidas, como tokens JWT e Passlib, etc. * Implemente e use ferramentas criptográficas bem conhecidas, como pwdlib e tokens JWT, etc.
* Adicione controles de permissão mais granulares com escopos OAuth2 quando necessário. * Adicione controles de permissão mais granulares com escopos OAuth2 quando necessário.
* ...etc. * ...etc.
No entanto, você pode ter um caso de uso muito específico em que realmente precisa desabilitar a documentação da API para algum ambiente (por exemplo, para produção) ou dependendo de configurações de variáveis de ambiente. No entanto, você pode ter um caso de uso muito específico em que realmente precisa desabilitar a documentação da API para algum ambiente (por exemplo, para produção) ou dependendo de configurações de variáveis de ambiente.
## OpenAPI condicional com configurações e variáveis de ambiente ## OpenAPI condicional com configurações e variáveis de ambiente { #conditional-openapi-from-settings-and-env-vars }
Você pode usar facilmente as mesmas configurações do Pydantic para configurar sua OpenAPI gerada e as interfaces de usuário de documentos. Você pode usar facilmente as mesmas configurações do Pydantic para configurar sua OpenAPI gerada e as interfaces de usuário da documentação.
Por exemplo: Por exemplo:
@ -33,9 +33,9 @@ Por exemplo:
Aqui declaramos a configuração `openapi_url` com o mesmo padrão de `"/openapi.json"`. Aqui declaramos a configuração `openapi_url` com o mesmo padrão de `"/openapi.json"`.
E então o usamos ao criar o aplicativo `FastAPI`. E então a usamos ao criar a aplicação `FastAPI`.
Então você pode desabilitar o OpenAPI (incluindo os documentos da interface do usuário) definindo a variável de ambiente `OPENAPI_URL` como uma string vazia, como: Então você pode desabilitar o OpenAPI (incluindo a documentação da interface do usuário) definindo a variável de ambiente `OPENAPI_URL` como uma string vazia, como:
<div class="termy"> <div class="termy">
@ -47,7 +47,7 @@ $ OPENAPI_URL= uvicorn main:app
</div> </div>
Então, se você acessar as URLs em `/openapi.json`, `/docs` ou `/redoc`, você receberá apenas um erro `404 Não Encontrado` como: Então, se você acessar as URLs em `/openapi.json`, `/docs` ou `/redoc`, você receberá apenas um erro `404 Not Found` como:
```JSON ```JSON
{ {

View File

@ -1,14 +1,14 @@
# Configurar Swagger UI # Configure a UI do Swagger { #configure-swagger-ui }
Você pode configurar alguns <a href="https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/" class="external-link" target="_blank">parâmetros extras da UI do Swagger</a>. Você pode configurar alguns <a href="https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/" class="external-link" target="_blank">parâmetros extras da UI do Swagger</a>.
Para configurá-los, passe o argumento `swagger_ui_parameters` ao criar o objeto de aplicativo `FastAPI()` ou para a função `get_swagger_ui_html()`. Para configurá-los, passe o argumento `swagger_ui_parameters` ao criar o objeto da aplicação `FastAPI()` ou para a função `get_swagger_ui_html()`.
`swagger_ui_parameters` recebe um dicionário com as configurações passadas diretamente para o Swagger UI. `swagger_ui_parameters` recebe um dicionário com as configurações passadas diretamente para o Swagger UI.
O FastAPI converte as configurações para **JSON** para torná-las compatíveis com JavaScript, pois é disso que o Swagger UI precisa. O FastAPI converte as configurações para **JSON** para torná-las compatíveis com JavaScript, pois é disso que o Swagger UI precisa.
## Desabilitar realce de sintaxe ## Desabilitar destaque de sintaxe { #disable-syntax-highlighting }
Por exemplo, você pode desabilitar o destaque de sintaxe na UI do Swagger. Por exemplo, você pode desabilitar o destaque de sintaxe na UI do Swagger.
@ -24,7 +24,7 @@ Mas você pode desabilitá-lo definindo `syntaxHighlight` como `False`:
<img src="/img/tutorial/extending-openapi/image03.png"> <img src="/img/tutorial/extending-openapi/image03.png">
## Alterar o tema ## Alterar o tema { #change-the-theme }
Da mesma forma que você pode definir o tema de destaque de sintaxe com a chave `"syntaxHighlight.theme"` (observe que há um ponto no meio): Da mesma forma que você pode definir o tema de destaque de sintaxe com a chave `"syntaxHighlight.theme"` (observe que há um ponto no meio):
@ -34,13 +34,13 @@ Essa configuração alteraria o tema de cores de destaque de sintaxe:
<img src="/img/tutorial/extending-openapi/image04.png"> <img src="/img/tutorial/extending-openapi/image04.png">
## Alterar parâmetros de UI padrão do Swagger ## Alterar parâmetros de UI padrão do Swagger { #change-default-swagger-ui-parameters }
O FastAPI inclui alguns parâmetros de configuração padrão apropriados para a maioria dos casos de uso. O FastAPI inclui alguns parâmetros de configuração padrão apropriados para a maioria dos casos de uso.
Inclui estas configurações padrão: Inclui estas configurações padrão:
{* ../../fastapi/openapi/docs.py ln[7:23] *} {* ../../fastapi/openapi/docs.py ln[8:23] hl[17:23] *}
Você pode substituir qualquer um deles definindo um valor diferente no argumento `swagger_ui_parameters`. Você pode substituir qualquer um deles definindo um valor diferente no argumento `swagger_ui_parameters`.
@ -48,15 +48,15 @@ Por exemplo, para desabilitar `deepLinking` você pode passar essas configuraç
{* ../../docs_src/configure_swagger_ui/tutorial003.py hl[3] *} {* ../../docs_src/configure_swagger_ui/tutorial003.py hl[3] *}
## Outros parâmetros da UI do Swagger ## Outros parâmetros da UI do Swagger { #other-swagger-ui-parameters }
Para ver todas as outras configurações possíveis que você pode usar, leia a <a href="https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/" class="external-link" target="_blank">documentação oficial dos parâmetros da UI do Swagger</a>. Para ver todas as outras configurações possíveis que você pode usar, leia a <a href="https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/" class="external-link" target="_blank">documentação oficial dos parâmetros da UI do Swagger</a>.
## Configurações somente JavaScript ## Configurações somente JavaScript { #javascript-only-settings }
A interface do usuário do Swagger também permite que outras configurações sejam objetos **somente JavaScript** (por exemplo, funções JavaScript). A UI do Swagger também permite que outras configurações sejam objetos **somente JavaScript** (por exemplo, funções JavaScript).
O FastAPI também inclui estas configurações de `predefinições` somente para JavaScript: O FastAPI também inclui estas configurações `presets` somente para JavaScript:
```JavaScript ```JavaScript
presets: [ presets: [
@ -67,4 +67,4 @@ presets: [
Esses são objetos **JavaScript**, não strings, então você não pode passá-los diretamente do código Python. Esses são objetos **JavaScript**, não strings, então você não pode passá-los diretamente do código Python.
Se você precisar usar configurações somente JavaScript como essas, você pode usar um dos métodos acima. Sobrescreva todas as *operações de rotas* do Swagger UI e escreva manualmente qualquer JavaScript que você precisar. Se você precisar usar configurações somente JavaScript como essas, você pode usar um dos métodos acima. Substitua toda a *operação de rota* do Swagger UI e escreva manualmente qualquer JavaScript que você precisar.

View File

@ -1,26 +1,26 @@
# Recursos Estáticos Personalizados para a UI de Documentação (Hospedagem Própria) # Recursos Estáticos Personalizados para a UI de Documentação (Hospedagem Própria) { #custom-docs-ui-static-assets-self-hosting }
A documentação da API usa **Swagger UI** e **ReDoc**, e cada um deles precisa de alguns arquivos JavaScript e CSS. A documentação da API usa **Swagger UI** e **ReDoc**, e cada um deles precisa de alguns arquivos JavaScript e CSS.
Por padrão, esses arquivos são fornecidos por um <abbr title="Content Delivery Network: Um serviço, normalmente composto por vários servidores, que fornece arquivos estáticos, como JavaScript e CSS. É comumente usado para providenciar esses arquivos do servidor mais próximo do cliente, melhorando o desempenho.">CDN</abbr>. Por padrão, esses arquivos são fornecidos por um <abbr title="Content Delivery Network Rede de Entrega de Conteúdo: Um serviço, normalmente composto por vários servidores, que fornece arquivos estáticos, como JavaScript e CSS. É comumente usado para providenciar esses arquivos do servidor mais próximo do cliente, melhorando o desempenho.">CDN</abbr>.
Mas é possível personalizá-los, você pode definir um CDN específico ou providenciar os arquivos você mesmo. Mas é possível personalizá-los, você pode definir um CDN específico ou providenciar os arquivos você mesmo.
## CDN Personalizado para JavaScript e CSS ## CDN Personalizado para JavaScript e CSS { #custom-cdn-for-javascript-and-css }
Vamos supor que você deseja usar um <abbr title="Content Delivery Network">CDN</abbr> diferente, por exemplo, você deseja usar `https://unpkg.com/`. Vamos supor que você deseja usar um <abbr title="Content Delivery Network Rede de Entrega de Conteúdo">CDN</abbr> diferente, por exemplo, você deseja usar `https://unpkg.com/`.
Isso pode ser útil se, por exemplo, você mora em um país que restringe algumas URLs. Isso pode ser útil se, por exemplo, você mora em um país que restringe algumas URLs.
### Desativar a documentação automática ### Desativar a documentação automática { #disable-the-automatic-docs }
O primeiro passo é desativar a documentação automática, pois por padrão, ela usa o CDN padrão. O primeiro passo é desativar a documentação automática, pois por padrão, ela usa o CDN padrão.
Para desativá-los, defina suas URLs como `None` ao criar seu aplicativo `FastAPI`: Para desativá-los, defina suas URLs como `None` ao criar sua aplicação FastAPI:
{* ../../docs_src/custom_docs_ui/tutorial001.py hl[8] *} {* ../../docs_src/custom_docs_ui/tutorial001.py hl[8] *}
### Incluir a documentação personalizada ### Incluir a documentação personalizada { #include-the-custom-docs }
Agora você pode criar as *operações de rota* para a documentação personalizada. Agora você pode criar as *operações de rota* para a documentação personalizada.
@ -46,23 +46,23 @@ Swagger UI lidará com isso nos bastidores para você, mas ele precisa desse aux
/// ///
### Criar uma *operação de rota* para testar ### Criar uma *operação de rota* para testar { #create-a-path-operation-to-test-it }
Agora, para poder testar se tudo funciona, crie uma *operação de rota*: Agora, para poder testar se tudo funciona, crie uma *operação de rota*:
{* ../../docs_src/custom_docs_ui/tutorial001.py hl[36:38] *} {* ../../docs_src/custom_docs_ui/tutorial001.py hl[36:38] *}
### Teste ### Teste { #test-it }
Agora, você deve ser capaz de ir para a documentação em <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>, e recarregar a página, ela carregará esses recursos do novo CDN. Agora, você deve ser capaz de ir para a documentação em <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>, e recarregar a página, ela carregará esses recursos do novo CDN.
## Hospedagem Própria de JavaScript e CSS para a documentação ## Hospedagem Própria de JavaScript e CSS para a documentação { #self-hosting-javascript-and-css-for-docs }
Hospedar o JavaScript e o CSS pode ser útil se, por exemplo, você precisa que seu aplicativo continue funcionando mesmo offline, sem acesso aberto à Internet, ou em uma rede local. Hospedar o JavaScript e o CSS pode ser útil se, por exemplo, você precisa que seu aplicativo continue funcionando mesmo offline, sem acesso aberto à Internet, ou em uma rede local.
Aqui você verá como providenciar esses arquivos você mesmo, no mesmo aplicativo FastAPI, e configurar a documentação para usá-los. Aqui você verá como providenciar esses arquivos você mesmo, na mesma aplicação FastAPI, e configurar a documentação para usá-los.
### Estrutura de Arquivos do Projeto ### Estrutura de Arquivos do Projeto { #project-file-structure }
Vamos supor que a estrutura de arquivos do seu projeto se pareça com isso: Vamos supor que a estrutura de arquivos do seu projeto se pareça com isso:
@ -85,7 +85,7 @@ Sua nova estrutura de arquivos poderia se parecer com isso:
└── static/ └── static/
``` ```
### Baixe os arquivos ### Baixe os arquivos { #download-the-files }
Baixe os arquivos estáticos necessários para a documentação e coloque-os no diretório `static/`. Baixe os arquivos estáticos necessários para a documentação e coloque-os no diretório `static/`.
@ -96,7 +96,7 @@ Você provavelmente pode clicar com o botão direito em cada link e selecionar u
* <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js" class="external-link" target="_blank">`swagger-ui-bundle.js`</a> * <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js" class="external-link" target="_blank">`swagger-ui-bundle.js`</a>
* <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css" class="external-link" target="_blank">`swagger-ui.css`</a> * <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css" class="external-link" target="_blank">`swagger-ui.css`</a>
E o **ReDoc** usa os arquivos: E o **ReDoc** usa o arquivo:
* <a href="https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js" class="external-link" target="_blank">`redoc.standalone.js`</a> * <a href="https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js" class="external-link" target="_blank">`redoc.standalone.js`</a>
@ -113,14 +113,14 @@ Depois disso, sua estrutura de arquivos deve se parecer com:
└── swagger-ui.css └── swagger-ui.css
``` ```
### Prover os arquivos estáticos ### Prover os arquivos estáticos { #serve-the-static-files }
* Importe `StaticFiles`. * Importe `StaticFiles`.
* "Monte" a instância `StaticFiles()` em um caminho específico. * "Monte" a instância `StaticFiles()` em um caminho específico.
{* ../../docs_src/custom_docs_ui/tutorial002.py hl[7,11] *} {* ../../docs_src/custom_docs_ui/tutorial002.py hl[7,11] *}
### Teste os arquivos estáticos ### Teste os arquivos estáticos { #test-the-static-files }
Inicialize seu aplicativo e vá para <a href="http://127.0.0.1:8000/static/redoc.standalone.js" class="external-link" target="_blank">http://127.0.0.1:8000/static/redoc.standalone.js</a>. Inicialize seu aplicativo e vá para <a href="http://127.0.0.1:8000/static/redoc.standalone.js" class="external-link" target="_blank">http://127.0.0.1:8000/static/redoc.standalone.js</a>.
@ -138,15 +138,15 @@ Isso confirma que você está conseguindo fornecer arquivos estáticos do seu ap
Agora, podemos configurar o aplicativo para usar esses arquivos estáticos para a documentação. Agora, podemos configurar o aplicativo para usar esses arquivos estáticos para a documentação.
### Desativar a documentação automática para arquivos estáticos ### Desativar a documentação automática para arquivos estáticos { #disable-the-automatic-docs-for-static-files }
Da mesma forma que ao usar um CDN personalizado, o primeiro passo é desativar a documentação automática, pois ela usa o CDN padrão. Da mesma forma que ao usar um CDN personalizado, o primeiro passo é desativar a documentação automática, pois ela usa o CDN padrão.
Para desativá-los, defina suas URLs como `None` ao criar seu aplicativo `FastAPI`: Para desativá-los, defina suas URLs como `None` ao criar sua aplicação FastAPI:
{* ../../docs_src/custom_docs_ui/tutorial002.py hl[9] *} {* ../../docs_src/custom_docs_ui/tutorial002.py hl[9] *}
### Incluir a documentação personalizada para arquivos estáticos ### Incluir a documentação personalizada para arquivos estáticos { #include-the-custom-docs-for-static-files }
E da mesma forma que com um CDN personalizado, agora você pode criar as *operações de rota* para a documentação personalizada. E da mesma forma que com um CDN personalizado, agora você pode criar as *operações de rota* para a documentação personalizada.
@ -155,7 +155,7 @@ Novamente, você pode reutilizar as funções internas do FastAPI para criar as
* `openapi_url`: a URL onde a página HTML para a documentação pode obter o esquema OpenAPI para a sua API. Você pode usar aqui o atributo `app.openapi_url`. * `openapi_url`: a URL onde a página HTML para a documentação pode obter o esquema OpenAPI para a sua API. Você pode usar aqui o atributo `app.openapi_url`.
* `title`: o título da sua API. * `title`: o título da sua API.
* `oauth2_redirect_url`: Você pode usar `app.swagger_ui_oauth2_redirect_url` aqui para usar o padrão. * `oauth2_redirect_url`: Você pode usar `app.swagger_ui_oauth2_redirect_url` aqui para usar o padrão.
* `swagger_js_url`: a URL onde a página HTML para a sua documentação do Swagger UI pode obter o arquivo **JavaScript**. Este é o URL do CDN personalizado. **Este é o URL que seu aplicativo está fornecendo**. * `swagger_js_url`: a URL onde a página HTML para a sua documentação do Swagger UI pode obter o arquivo **JavaScript**. **Este é o URL que seu aplicativo está fornecendo**.
* `swagger_css_url`: a URL onde a página HTML para a sua documentação do Swagger UI pode obter o arquivo **CSS**. **Esse é o que seu aplicativo está fornecendo**. * `swagger_css_url`: a URL onde a página HTML para a sua documentação do Swagger UI pode obter o arquivo **CSS**. **Esse é o que seu aplicativo está fornecendo**.
E de forma semelhante para o ReDoc... E de forma semelhante para o ReDoc...
@ -172,13 +172,13 @@ Swagger UI lidará com isso nos bastidores para você, mas ele precisa desse aux
/// ///
### Criar uma *operação de rota* para testar arquivos estáticos ### Criar uma *operação de rota* para testar arquivos estáticos { #create-a-path-operation-to-test-static-files }
Agora, para poder testar se tudo funciona, crie uma *operação de rota*: Agora, para poder testar se tudo funciona, crie uma *operação de rota*:
{* ../../docs_src/custom_docs_ui/tutorial002.py hl[39:41] *} {* ../../docs_src/custom_docs_ui/tutorial002.py hl[39:41] *}
### Teste a UI de Arquivos Estáticos ### Teste a UI de Arquivos Estáticos { #test-static-files-ui }
Agora, você deve ser capaz de desconectar o WiFi, ir para a documentação em <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>, e recarregar a página. Agora, você deve ser capaz de desconectar o WiFi, ir para a documentação em <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>, e recarregar a página.

View File

@ -1,12 +1,12 @@
# Requisições Personalizadas e Classes da APIRoute # Request e classe APIRoute personalizadas { #custom-request-and-apiroute-class }
Em algum casos, você pode querer sobreescrever a lógica usada pelas classes `Request`e `APIRoute`. Em alguns casos, você pode querer sobrescrever a lógica usada pelas classes `Request` e `APIRoute`.
Em particular, isso pode ser uma boa alternativa para uma lógica em um middleware Em particular, isso pode ser uma boa alternativa para uma lógica em um middleware.
Por exemplo, se você quiser ler ou manipular o corpo da requisição antes que ele seja processado pela sua aplicação. Por exemplo, se você quiser ler ou manipular o corpo da requisição antes que ele seja processado pela sua aplicação.
/// danger | Perigo /// danger | Cuidado
Isso é um recurso "avançado". Isso é um recurso "avançado".
@ -14,7 +14,7 @@ Se você for um iniciante em **FastAPI** você deve considerar pular essa seçã
/// ///
## Casos de Uso ## Casos de Uso { #use-cases }
Alguns casos de uso incluem: Alguns casos de uso incluem:
@ -22,13 +22,13 @@ Alguns casos de uso incluem:
* Descomprimir corpos de requisição comprimidos com gzip. * Descomprimir corpos de requisição comprimidos com gzip.
* Registrar automaticamente todos os corpos de requisição. * Registrar automaticamente todos os corpos de requisição.
## Manipulando codificações de corpo de requisição personalizadas ## Manipulando codificações de corpo de requisição personalizadas { #handling-custom-request-body-encodings }
Vamos ver como usar uma subclasse personalizada de `Request` para descomprimir requisições gzip. Vamos ver como usar uma subclasse personalizada de `Request` para descomprimir requisições gzip.
E uma subclasse de `APIRoute` para usar essa classe de requisição personalizada. E uma subclasse de `APIRoute` para usar essa classe de requisição personalizada.
### Criar uma classe `GzipRequest` personalizada ### Criar uma classe `GzipRequest` personalizada { #create-a-custom-gziprequest-class }
/// tip | Dica /// tip | Dica
@ -44,7 +44,7 @@ Dessa forma, a mesma classe de rota pode lidar com requisições comprimidas ou
{* ../../docs_src/custom_request_and_route/tutorial001.py hl[8:15] *} {* ../../docs_src/custom_request_and_route/tutorial001.py hl[8:15] *}
### Criar uma classe `GzipRoute` personalizada ### Criar uma classe `GzipRoute` personalizada { #create-a-custom-gziproute-class }
Em seguida, criamos uma subclasse personalizada de `fastapi.routing.APIRoute` que fará uso do `GzipRequest`. Em seguida, criamos uma subclasse personalizada de `fastapi.routing.APIRoute` que fará uso do `GzipRequest`.
@ -58,7 +58,7 @@ Aqui nós usamos para criar um `GzipRequest` a partir da requisição original.
/// note | Detalhes Técnicos /// note | Detalhes Técnicos
Um `Request` também tem um `request.receive`, que é uma função para "receber" o corpo da requisição. Um `Request` tem um atributo `request.scope`, que é apenas um `dict` do Python contendo os metadados relacionados à requisição.
Um `Request` também tem um `request.receive`, que é uma função para "receber" o corpo da requisição. Um `Request` também tem um `request.receive`, que é uma função para "receber" o corpo da requisição.
@ -78,7 +78,7 @@ Depois disso, toda a lógica de processamento é a mesma.
Mas por causa das nossas mudanças em `GzipRequest.body`, o corpo da requisição será automaticamente descomprimido quando for carregado pelo **FastAPI** quando necessário. Mas por causa das nossas mudanças em `GzipRequest.body`, o corpo da requisição será automaticamente descomprimido quando for carregado pelo **FastAPI** quando necessário.
## Acessando o corpo da requisição em um manipulador de exceção ## Acessando o corpo da requisição em um manipulador de exceção { #accessing-the-request-body-in-an-exception-handler }
/// tip | Dica /// tip | Dica
@ -98,9 +98,9 @@ Se uma exceção ocorrer, a instância `Request` ainda estará em escopo, então
{* ../../docs_src/custom_request_and_route/tutorial002.py hl[16:18] *} {* ../../docs_src/custom_request_and_route/tutorial002.py hl[16:18] *}
## Classe `APIRoute` personalizada em um router ## Classe `APIRoute` personalizada em um router { #custom-apiroute-class-in-a-router }
você também pode definir o parametro `route_class` de uma `APIRouter`; Você também pode definir o parâmetro `route_class` de uma `APIRouter`:
{* ../../docs_src/custom_request_and_route/tutorial003.py hl[26] *} {* ../../docs_src/custom_request_and_route/tutorial003.py hl[26] *}

Some files were not shown because too many files have changed in this diff Show More