mirror of https://github.com/tiangolo/fastapi.git
🌐 Update translations for de (add-missing) (#15153)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
parent
4889a9659c
commit
96beaeb167
|
|
@ -0,0 +1,63 @@
|
|||
# JSON mit Bytes als base64 { #json-with-bytes-as-base64 }
|
||||
|
||||
Wenn Ihre App JSON-Daten empfangen und senden muss, Sie darin aber Binärdaten einschließen müssen, können Sie diese als base64 kodieren.
|
||||
|
||||
## Base64 vs Dateien { #base64-vs-files }
|
||||
|
||||
Prüfen Sie zunächst, ob Sie [Request Files](../tutorial/request-files.md) zum Hochladen von Binärdaten und [Benutzerdefinierte Response – FileResponse](./custom-response.md#fileresponse--fileresponse-) zum Senden von Binärdaten verwenden können, anstatt sie in JSON zu kodieren.
|
||||
|
||||
JSON kann nur UTF-8-kodierte Strings enthalten, es kann daher keine rohen Bytes enthalten.
|
||||
|
||||
Base64 kann Binärdaten in Strings kodieren, dafür werden jedoch mehr Zeichen benötigt als in den ursprünglichen Binärdaten; es ist daher in der Regel weniger effizient als der Umgang mit normalen Dateien.
|
||||
|
||||
Verwenden Sie base64 nur, wenn Sie Binärdaten unbedingt in JSON einbetten müssen und dafür keine Dateien verwenden können.
|
||||
|
||||
## Pydantic `bytes` { #pydantic-bytes }
|
||||
|
||||
Sie können ein Pydantic-Modell mit `bytes`-Feldern deklarieren und dann in der Modellkonfiguration `val_json_bytes` verwenden, um anzugeben, dass zur *Validierung* von eingehenden JSON-Daten base64 genutzt werden soll; im Rahmen dieser Validierung wird der base64-String in Bytes dekodiert.
|
||||
|
||||
{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *}
|
||||
|
||||
Wenn Sie die `/docs` aufrufen, zeigt die Dokumentation, dass das Feld `data` base64-kodierte Bytes erwartet:
|
||||
|
||||
<div class="screenshot">
|
||||
<img src="/img/tutorial/json-base64-bytes/image01.png">
|
||||
</div>
|
||||
|
||||
Sie könnten einen Request wie folgt senden:
|
||||
|
||||
```json
|
||||
{
|
||||
"description": "Some data",
|
||||
"data": "aGVsbG8="
|
||||
}
|
||||
```
|
||||
|
||||
/// tip | Tipp
|
||||
|
||||
`aGVsbG8=` ist die base64-Kodierung von `hello`.
|
||||
|
||||
///
|
||||
|
||||
Anschließend dekodiert Pydantic den base64-String und stellt Ihnen die ursprünglichen Bytes im Feld `data` des Modells bereit.
|
||||
|
||||
Sie erhalten eine Response wie:
|
||||
|
||||
```json
|
||||
{
|
||||
"description": "Some data",
|
||||
"content": "hello"
|
||||
}
|
||||
```
|
||||
|
||||
## Pydantic `bytes` für Ausgabedaten { #pydantic-bytes-for-output-data }
|
||||
|
||||
Sie können in der Modellkonfiguration für Ausgabedaten auch `bytes`-Felder mit `ser_json_bytes` verwenden; Pydantic wird die Bytes bei der Erzeugung der JSON-Response als base64 *serialisieren*.
|
||||
|
||||
{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *}
|
||||
|
||||
## Pydantic `bytes` für Eingabe- und Ausgabedaten { #pydantic-bytes-for-input-and-output-data }
|
||||
|
||||
Und selbstverständlich können Sie dasselbe Modell so konfigurieren, dass base64 sowohl für Eingaben (*validieren*) mit `val_json_bytes` als auch für Ausgaben (*serialisieren*) mit `ser_json_bytes` verwendet wird, wenn JSON-Daten empfangen und gesendet werden.
|
||||
|
||||
{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
# Daten streamen { #stream-data }
|
||||
|
||||
Wenn Sie Daten streamen möchten, die als JSON strukturiert werden können, sollten Sie [JSON Lines streamen](../tutorial/stream-json-lines.md).
|
||||
|
||||
Wenn Sie jedoch **reine Binärdaten** oder Strings streamen möchten, so können Sie es machen.
|
||||
|
||||
/// info | Info
|
||||
|
||||
Hinzugefügt in FastAPI 0.134.0.
|
||||
|
||||
///
|
||||
|
||||
## Anwendungsfälle { #use-cases }
|
||||
|
||||
Sie könnten dies verwenden, wenn Sie reine Strings streamen möchten, z. B. direkt aus der Ausgabe eines **AI-LLM**-Dienstes.
|
||||
|
||||
Sie könnten es auch nutzen, um **große Binärdateien** zu streamen, wobei Sie jeden Datenchunk beim Lesen streamen, ohne alles auf einmal in den Speicher laden zu müssen.
|
||||
|
||||
Sie könnten auf diese Weise auch **Video** oder **Audio** streamen, es könnte sogar beim Verarbeiten erzeugt und gesendet werden.
|
||||
|
||||
## Eine `StreamingResponse` mit `yield` { #a-streamingresponse-with-yield }
|
||||
|
||||
Wenn Sie in Ihrer Pfadoperation-Funktion ein `response_class=StreamingResponse` deklarieren, können Sie `yield` verwenden, um nacheinander jeden Datenchunk zu senden.
|
||||
|
||||
{* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *}
|
||||
|
||||
FastAPI übergibt jeden Datenchunk unverändert an die `StreamingResponse`, es wird nicht versucht, ihn in JSON oder etwas Ähnliches zu konvertieren.
|
||||
|
||||
### Nicht-async-Pfadoperation-Funktionen { #non-async-path-operation-functions }
|
||||
|
||||
Sie können auch reguläre `def`-Funktionen (ohne `async`) verwenden und `yield` auf die gleiche Weise einsetzen.
|
||||
|
||||
{* ../../docs_src/stream_data/tutorial001_py310.py ln[26:29] hl[27] *}
|
||||
|
||||
### Keine Annotation { #no-annotation }
|
||||
|
||||
Sie müssen den Rückgabetyp für das Streamen von Binärdaten nicht wirklich annotieren.
|
||||
|
||||
Da FastAPI die Daten nicht mit Pydantic in JSON umzuwandeln oder sie anderweitig zu serialisieren versucht, ist die Typannotation hier nur für Ihren Editor und Tools relevant, sie wird von FastAPI nicht verwendet.
|
||||
|
||||
{* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *}
|
||||
|
||||
Das bedeutet auch, dass Sie mit `StreamingResponse` die **Freiheit** und **Verantwortung** haben, die Datenbytes genau so zu erzeugen und zu encodieren, wie sie gesendet werden sollen, unabhängig von den Typannotationen. 🤓
|
||||
|
||||
### Bytes streamen { #stream-bytes }
|
||||
|
||||
Einer der Hauptanwendungsfälle wäre, `bytes` statt Strings zu streamen, das können Sie selbstverständlich tun.
|
||||
|
||||
{* ../../docs_src/stream_data/tutorial001_py310.py ln[44:47] hl[47] *}
|
||||
|
||||
## Eine benutzerdefinierte `PNGStreamingResponse` { #a-custom-pngstreamingresponse }
|
||||
|
||||
In den obigen Beispielen wurden die Datenbytes gestreamt, aber die Response hatte keinen `Content-Type`-Header, sodass der Client nicht wusste, welchen Datentyp er erhielt.
|
||||
|
||||
Sie können eine benutzerdefinierte Unterklasse von `StreamingResponse` erstellen, die den `Content-Type`-Header auf den Typ der gestreamten Daten setzt.
|
||||
|
||||
Zum Beispiel können Sie eine `PNGStreamingResponse` erstellen, die den `Content-Type`-Header mit dem Attribut `media_type` auf `image/png` setzt:
|
||||
|
||||
{* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *}
|
||||
|
||||
Dann können Sie diese neue Klasse mit `response_class=PNGStreamingResponse` in Ihrer Pfadoperation-Funktion verwenden:
|
||||
|
||||
{* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *}
|
||||
|
||||
### Eine Datei simulieren { #simulate-a-file }
|
||||
|
||||
In diesem Beispiel simulieren wir eine Datei mit `io.BytesIO`, einem dateiähnlichen Objekt, das nur im Speicher lebt, uns aber dieselbe Schnittstelle nutzen lässt.
|
||||
|
||||
Wir können z. B. darüber iterieren, um seinen Inhalt zu konsumieren, so wie bei einer Datei.
|
||||
|
||||
{* ../../docs_src/stream_data/tutorial002_py310.py ln[1:27] hl[3,12:13,25] *}
|
||||
|
||||
/// note | Technische Details
|
||||
|
||||
Die anderen beiden Variablen, `image_base64` und `binary_image`, sind ein in Base64 encodiertes Bild, dann in Bytes konvertiert, um es anschließend an `io.BytesIO` zu übergeben.
|
||||
|
||||
Nur damit es in derselben Datei leben kann, für dieses Beispiel, und Sie es unverändert kopieren und ausführen können. 🥚
|
||||
|
||||
///
|
||||
|
||||
Mit einem `with`-Block stellen wir sicher, dass das dateiähnliche Objekt geschlossen wird, nachdem die Generatorfunktion (die Funktion mit `yield`) fertig ist. Also nachdem die Response gesendet wurde.
|
||||
|
||||
In diesem speziellen Beispiel wäre das nicht so wichtig, weil es sich um eine unechte In-Memory-Datei (mit `io.BytesIO`) handelt, aber bei einer echten Datei wäre es wichtig sicherzustellen, dass die Datei nach der Arbeit damit geschlossen wird.
|
||||
|
||||
### Dateien und Async { #files-and-async }
|
||||
|
||||
In den meisten Fällen sind dateiähnliche Objekte standardmäßig nicht mit async und await kompatibel.
|
||||
|
||||
Beispielsweise haben sie kein `await file.read()` oder `async for chunk in file`.
|
||||
|
||||
Und in vielen Fällen wäre das Lesen eine blockierende Operation (die die Event-Loop blockieren könnte), weil von der Festplatte oder aus dem Netzwerk gelesen wird.
|
||||
|
||||
/// info | Info
|
||||
|
||||
Das obige Beispiel ist tatsächlich eine Ausnahme, weil sich das `io.BytesIO`-Objekt bereits im Speicher befindet, daher blockiert sein Lesen nichts.
|
||||
|
||||
Aber in vielen Fällen würde das Lesen einer Datei oder eines dateiähnlichen Objekts blockieren.
|
||||
|
||||
///
|
||||
|
||||
Um die Event-Loop nicht zu blockieren, können Sie die Pfadoperation-Funktion einfach mit normalem `def` statt `async def` deklarieren, dadurch führt FastAPI sie in einem Threadpool-Worker aus, um die Haupt-Event-Loop nicht zu blockieren.
|
||||
|
||||
{* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *}
|
||||
|
||||
/// tip | Tipp
|
||||
|
||||
Wenn Sie blockierenden Code aus einer async-Funktion heraus aufrufen müssen, oder eine async-Funktion aus einer blockierenden Funktion, könnten Sie [Asyncer](https://asyncer.tiangolo.com), eine Schwesterbibliothek zu FastAPI, verwenden.
|
||||
|
||||
///
|
||||
|
||||
### `yield from` { #yield-from }
|
||||
|
||||
Wenn Sie über etwas iterieren, z. B. ein dateiähnliches Objekt, und dann für jedes Element `yield` verwenden, könnten Sie auch `yield from` verwenden, um jedes Element direkt weiterzugeben und die `for`-Schleife zu sparen.
|
||||
|
||||
Das ist nichts Spezifisches an FastAPI, das ist einfach Python, aber ein netter Trick. 😎
|
||||
|
||||
{* ../../docs_src/stream_data/tutorial002_py310.py ln[37:40] hl[40] *}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
# Strikte Content-Type-Prüfung { #strict-content-type-checking }
|
||||
|
||||
Standardmäßig verwendet **FastAPI** eine strikte Prüfung des `Content-Type`-Headers für JSON-Requestbodys. Das bedeutet, dass JSON-Requests einen gültigen `Content-Type`-Header (z. B. `application/json`) enthalten MÜSSEN, damit der Body als JSON geparst wird.
|
||||
|
||||
## CSRF-Risiko { #csrf-risk }
|
||||
|
||||
Dieses Standardverhalten schützt vor einer Klasse von **Cross-Site Request Forgery (CSRF)**-Angriffen in einem sehr spezifischen Szenario.
|
||||
|
||||
Diese Angriffe nutzen aus, dass Browser Skripte Requests senden lassen, ohne einen CORS-Preflight-Check durchzuführen, wenn sie:
|
||||
|
||||
* keinen `Content-Type`-Header haben (z. B. mit `fetch()` und einem `Blob`-Body)
|
||||
* und keine Authentifizierungsdaten senden.
|
||||
|
||||
Diese Art von Angriff ist vor allem relevant, wenn:
|
||||
|
||||
* die Anwendung lokal läuft (z. B. auf `localhost`) oder in einem internen Netzwerk
|
||||
* und die Anwendung keine Authentifizierung hat, sondern erwartet, dass jeder Request aus demselben Netzwerk vertrauenswürdig ist.
|
||||
|
||||
## Beispielangriff { #example-attack }
|
||||
|
||||
Stellen Sie sich vor, Sie bauen eine Möglichkeit, lokal einen KI-Agenten auszuführen.
|
||||
|
||||
Er stellt eine API bereit unter
|
||||
|
||||
```
|
||||
http://localhost:8000/v1/agents/multivac
|
||||
```
|
||||
|
||||
Es gibt auch ein Frontend unter
|
||||
|
||||
```
|
||||
http://localhost:8000
|
||||
```
|
||||
|
||||
/// tip | Tipp
|
||||
|
||||
Beachten Sie, dass beide denselben Host haben.
|
||||
|
||||
///
|
||||
|
||||
Dann können Sie über das Frontend den KI-Agenten Dinge in Ihrem Namen erledigen lassen.
|
||||
|
||||
Da er **lokal** läuft und nicht im offenen Internet, entscheiden Sie sich, **keine Authentifizierung** einzurichten und vertrauen stattdessen einfach auf den Zugriff im lokalen Netzwerk.
|
||||
|
||||
Dann könnte einer Ihrer Benutzer es installieren und lokal ausführen.
|
||||
|
||||
Anschließend könnte er eine bösartige Website öffnen, z. B. so etwas wie
|
||||
|
||||
```
|
||||
https://evilhackers.example.com
|
||||
```
|
||||
|
||||
Und diese bösartige Website sendet Requests mit `fetch()` und einem `Blob`-Body an die lokale API unter
|
||||
|
||||
```
|
||||
http://localhost:8000/v1/agents/multivac
|
||||
```
|
||||
|
||||
Obwohl der Host der bösartigen Website und der lokalen App unterschiedlich ist, löst der Browser keinen CORS-Preflight-Request aus, weil:
|
||||
|
||||
* sie ohne Authentifizierung läuft, es müssen keine Credentials gesendet werden.
|
||||
* der Browser annimmt, dass kein JSON gesendet wird (wegen des fehlenden `Content-Type`-Headers).
|
||||
|
||||
Dann könnte die bösartige Website den lokalen KI-Agenten dazu bringen, wütende Nachrichten an den Ex-Chef des Benutzers zu schicken ... oder Schlimmeres. 😅
|
||||
|
||||
## Offenes Internet { #open-internet }
|
||||
|
||||
Wenn Ihre App im offenen Internet läuft, würden Sie nicht „dem Netzwerk vertrauen“ und jedem erlauben, privilegierte Requests ohne Authentifizierung zu senden.
|
||||
|
||||
Angreifer könnten einfach ein Skript ausführen, um Requests an Ihre API zu senden, es ist keine Browserinteraktion nötig. Daher sichern Sie wahrscheinlich schon alle privilegierten Endpunkte.
|
||||
|
||||
In diesem Fall gilt **dieser Angriff / dieses Risiko nicht für Sie**.
|
||||
|
||||
Dieses Risiko und dieser Angriff sind vor allem relevant, wenn die App im **lokalen Netzwerk** läuft und das die **einzige angenommene Schutzmaßnahme** ist.
|
||||
|
||||
## Requests ohne Content-Type erlauben { #allowing-requests-without-content-type }
|
||||
|
||||
Wenn Sie Clients unterstützen müssen, die keinen `Content-Type`-Header senden, können Sie die strikte Prüfung deaktivieren, indem Sie `strict_content_type=False` setzen:
|
||||
|
||||
{* ../../docs_src/strict_content_type/tutorial001_py310.py hl[4] *}
|
||||
|
||||
Mit dieser Einstellung werden Requests ohne `Content-Type`-Header im Body als JSON geparst. Das entspricht dem Verhalten älterer FastAPI-Versionen.
|
||||
|
||||
/// info | Info
|
||||
|
||||
Dieses Verhalten und diese Konfiguration wurden in FastAPI 0.132.0 hinzugefügt.
|
||||
|
||||
///
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# Editor-Unterstützung { #editor-support }
|
||||
|
||||
Die offizielle [FastAPI-Erweiterung](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) verbessert Ihren FastAPI-Entwicklungsworkflow mit Pfadoperation-Erkennung und -Navigation sowie FastAPI-Cloud-Deployment und Live-Logstreaming.
|
||||
|
||||
Weitere Details zur Erweiterung finden Sie im README im [GitHub-Repository](https://github.com/fastapi/fastapi-vscode).
|
||||
|
||||
## Einrichtung und Installation { #setup-and-installation }
|
||||
|
||||
Die **FastAPI-Erweiterung** ist sowohl für [VS Code](https://code.visualstudio.com/) als auch für [Cursor](https://www.cursor.com/) verfügbar. Sie kann direkt über das Erweiterungen-Panel in jedem Editor installiert werden, indem Sie nach „FastAPI“ suchen und die von **FastAPI Labs** veröffentlichte Erweiterung auswählen. Die Erweiterung funktioniert auch in browserbasierten Editoren wie [vscode.dev](https://vscode.dev) und [github.dev](https://github.dev).
|
||||
|
||||
### Anwendungserkennung { #application-discovery }
|
||||
|
||||
Standardmäßig erkennt die Erweiterung FastAPI-Anwendungen in Ihrem Workspace automatisch, indem sie nach Dateien sucht, die `FastAPI()` instanziieren. Falls die automatische Erkennung mit Ihrer Projektstruktur nicht funktioniert, können Sie einen Entry-Point über `[tool.fastapi]` in `pyproject.toml` oder die VS-Code-Einstellung `fastapi.entryPoint` in Modulnotation angeben (z. B. `myapp.main:app`).
|
||||
|
||||
## Funktionen { #features }
|
||||
|
||||
- Pfadoperation-Explorer – Eine Baumansicht in der Seitenleiste aller <dfn title="Routen, Endpunkte">*Pfadoperationen*</dfn> in Ihrer Anwendung. Klicken Sie, um zu einer beliebigen Route- oder Router-Definition zu springen.
|
||||
- Routensuche – Suchen Sie nach Pfad, Methode oder Namen mit <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>E</kbd> (unter macOS: <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>E</kbd>).
|
||||
- CodeLens-Navigation – Anklickbare Links oberhalb von Testclient-Aufrufen (z. B. `client.get('/items')`), die zur passenden Pfadoperation springen und so eine schnelle Navigation zwischen Tests und Implementierung ermöglichen.
|
||||
- Zu FastAPI Cloud deployen – Deployment Ihrer App mit einem Klick auf [FastAPI Cloud](https://fastapicloud.com/).
|
||||
- Anwendungslogs streamen – Echtzeit-Logstreaming Ihrer auf FastAPI Cloud deployten Anwendung mit Loglevel-Filterung und Textsuche.
|
||||
|
||||
Wenn Sie sich mit den Funktionen der Erweiterung vertraut machen möchten, können Sie den Erweiterungs‑Walkthrough aufrufen, indem Sie die Befehlspalette öffnen (<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> oder unter macOS: <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd>) und „Welcome: Open walkthrough …“ auswählen und anschließend den Walkthrough „Get started with FastAPI“ wählen.
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
# Server-Sent Events (SSE) { #server-sent-events-sse }
|
||||
|
||||
Sie können Daten mithilfe von **Server-Sent Events** (SSE) an den Client streamen.
|
||||
|
||||
Das ist ähnlich wie [JSON Lines streamen](stream-json-lines.md), verwendet aber das Format `text/event-stream`, das von Browsern nativ mit der [die `EventSource`-API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) unterstützt wird.
|
||||
|
||||
/// info | Info
|
||||
|
||||
Hinzugefügt in FastAPI 0.135.0.
|
||||
|
||||
///
|
||||
|
||||
## Was sind Server-Sent Events? { #what-are-server-sent-events }
|
||||
|
||||
SSE ist ein Standard zum Streamen von Daten vom Server zum Client über HTTP.
|
||||
|
||||
Jedes Event ist ein kleiner Textblock mit „Feldern“ wie `data`, `event`, `id` und `retry`, getrennt durch Leerzeilen.
|
||||
|
||||
Das sieht so aus:
|
||||
|
||||
```
|
||||
data: {"name": "Portal Gun", "price": 999.99}
|
||||
|
||||
data: {"name": "Plumbus", "price": 32.99}
|
||||
|
||||
```
|
||||
|
||||
SSE wird häufig für KI-Chat-Streaming, Live-Benachrichtigungen, Logs und Observability sowie andere Fälle verwendet, in denen der Server Updates an den Client pusht.
|
||||
|
||||
/// tip | Tipp
|
||||
|
||||
Wenn Sie Binärdaten streamen wollen, z. B. Video oder Audio, sehen Sie im fortgeschrittenen Handbuch nach: [Daten streamen](../advanced/stream-data.md).
|
||||
|
||||
///
|
||||
|
||||
## SSE mit FastAPI streamen { #stream-sse-with-fastapi }
|
||||
|
||||
Um SSE mit FastAPI zu streamen, verwenden Sie `yield` in Ihrer *Pfadoperation-Funktion* und setzen Sie `response_class=EventSourceResponse`.
|
||||
|
||||
Importieren Sie `EventSourceResponse` aus `fastapi.sse`:
|
||||
|
||||
{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[4,22] *}
|
||||
|
||||
Jedes mit `yield` zurückgegebene Element wird als JSON kodiert und im Feld `data:` eines SSE-Events gesendet.
|
||||
|
||||
Wenn Sie den Rückgabetyp als `AsyncIterable[Item]` deklarieren, verwendet FastAPI ihn, um die Daten mit Pydantic zu **validieren**, zu **dokumentieren** und zu **serialisieren**.
|
||||
|
||||
{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[10:12,23] *}
|
||||
|
||||
/// tip | Tipp
|
||||
|
||||
Da Pydantic es auf der **Rust**-Seite serialisiert, erhalten Sie eine deutlich höhere **Leistung**, als wenn Sie keinen Rückgabetyp deklarieren.
|
||||
|
||||
///
|
||||
|
||||
### Nicht-async-*Pfadoperation-Funktionen* { #non-async-path-operation-functions }
|
||||
|
||||
Sie können auch normale `def`-Funktionen (ohne `async`) verwenden und `yield` genauso einsetzen.
|
||||
|
||||
FastAPI stellt sicher, dass sie korrekt ausgeführt wird, sodass sie die Event Loop nicht blockiert.
|
||||
|
||||
Da die Funktion in diesem Fall nicht async ist, wäre der passende Rückgabetyp `Iterable[Item]`:
|
||||
|
||||
{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[28:31] hl[29] *}
|
||||
|
||||
### Kein Rückgabetyp { #no-return-type }
|
||||
|
||||
Sie können den Rückgabetyp auch weglassen. FastAPI verwendet dann den [`jsonable_encoder`](./encoder.md), um die Daten zu konvertieren und zu senden.
|
||||
|
||||
{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[34:37] hl[35] *}
|
||||
|
||||
## `ServerSentEvent` { #serversentevent }
|
||||
|
||||
Wenn Sie SSE-Felder wie `event`, `id`, `retry` oder `comment` setzen müssen, können Sie statt reiner Daten `ServerSentEvent`-Objekte yielden.
|
||||
|
||||
Importieren Sie `ServerSentEvent` aus `fastapi.sse`:
|
||||
|
||||
{* ../../docs_src/server_sent_events/tutorial002_py310.py hl[4,26] *}
|
||||
|
||||
Das Feld `data` wird immer als JSON kodiert. Sie können jeden Wert übergeben, der als JSON serialisierbar ist, einschließlich Pydantic-Modellen.
|
||||
|
||||
## Rohdaten { #raw-data }
|
||||
|
||||
Wenn Sie Daten **ohne** JSON-Kodierung senden müssen, verwenden Sie `raw_data` statt `data`.
|
||||
|
||||
Das ist nützlich zum Senden vorformatierter Texte, Logzeilen oder spezieller <dfn title="Ein Wert, der verwendet wird, um eine besondere Bedingung oder einen besonderen Zustand anzuzeigen">„Sentinel“</dfn>-Werte wie `[DONE]`.
|
||||
|
||||
{* ../../docs_src/server_sent_events/tutorial003_py310.py hl[17] *}
|
||||
|
||||
/// note | Hinweis
|
||||
|
||||
`data` und `raw_data` schließen sich gegenseitig aus. Sie können pro `ServerSentEvent` nur eines von beiden setzen.
|
||||
|
||||
///
|
||||
|
||||
## Mit `Last-Event-ID` fortsetzen { #resuming-with-last-event-id }
|
||||
|
||||
Wenn ein Browser nach einem Verbindungsabbruch erneut verbindet, sendet er die zuletzt empfangene `id` im Header `Last-Event-ID`.
|
||||
|
||||
Sie können ihn als Header-Parameter einlesen und verwenden, um den Stream dort fortzusetzen, wo der Client aufgehört hat:
|
||||
|
||||
{* ../../docs_src/server_sent_events/tutorial004_py310.py hl[25,27,31] *}
|
||||
|
||||
## SSE mit POST { #sse-with-post }
|
||||
|
||||
SSE funktioniert mit **jedem HTTP-Method**, nicht nur mit `GET`.
|
||||
|
||||
Das ist nützlich für Protokolle wie [MCP](https://modelcontextprotocol.io), die SSE über `POST` streamen:
|
||||
|
||||
{* ../../docs_src/server_sent_events/tutorial005_py310.py hl[14] *}
|
||||
|
||||
## Technische Details { #technical-details }
|
||||
|
||||
FastAPI implementiert einige bewährte SSE-Praktiken direkt out of the box.
|
||||
|
||||
- Alle 15 Sekunden, wenn keine Nachricht gesendet wurde, einen **„keep alive“-`ping`-Kommentar** senden, um zu verhindern, dass einige Proxys die Verbindung schließen, wie in der [HTML-Spezifikation: Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html#authoring-notes) vorgeschlagen.
|
||||
- Den Header `Cache-Control: no-cache` setzen, um **Caching** des Streams zu verhindern.
|
||||
- Einen speziellen Header `X-Accel-Buffering: no` setzen, um **Buffering** in einigen Proxys wie Nginx zu verhindern.
|
||||
|
||||
Sie müssen dafür nichts tun, das funktioniert out of the box. 🤓
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
# JSON Lines streamen { #stream-json-lines }
|
||||
|
||||
Sie könnten eine Folge von Daten haben, die Sie in einem „Stream“ senden möchten, das können Sie mit **JSON Lines** tun.
|
||||
|
||||
/// info | Info
|
||||
|
||||
Hinzugefügt in FastAPI 0.134.0.
|
||||
|
||||
///
|
||||
|
||||
## Was ist ein Stream? { #what-is-a-stream }
|
||||
|
||||
„Streaming“ von Daten bedeutet, dass Ihre App damit beginnt, Datenelemente an den Client zu senden, ohne darauf zu warten, dass die gesamte Folge von Elementen fertig ist.
|
||||
|
||||
Sie sendet also das erste Element, der Client empfängt es und beginnt mit der Verarbeitung, und Sie erzeugen währenddessen möglicherweise bereits das nächste Element.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant App
|
||||
participant Client
|
||||
|
||||
App->>App: Produce Item 1
|
||||
App->>Client: Send Item 1
|
||||
App->>App: Produce Item 2
|
||||
Client->>Client: Process Item 1
|
||||
App->>Client: Send Item 2
|
||||
App->>App: Produce Item 3
|
||||
Client->>Client: Process Item 2
|
||||
App->>Client: Send Item 3
|
||||
Client->>Client: Process Item 3
|
||||
Note over App: Keeps producing...
|
||||
Note over Client: Keeps consuming...
|
||||
```
|
||||
|
||||
Es könnte sogar ein unendlicher Stream sein, bei dem Sie kontinuierlich Daten senden.
|
||||
|
||||
## JSON Lines { #json-lines }
|
||||
|
||||
In diesen Fällen ist es üblich, „JSON Lines“ zu senden, das ist ein Format, bei dem Sie pro Zeile genau ein JSON-Objekt senden.
|
||||
|
||||
Eine Response hätte einen Content-Type von `application/jsonl` (anstelle von `application/json`) und der Body sähe etwa so aus:
|
||||
|
||||
```json
|
||||
{"name": "Plumbus", "description": "A multi-purpose household device."}
|
||||
{"name": "Portal Gun", "description": "A portal opening device."}
|
||||
{"name": "Meeseeks Box", "description": "A box that summons a Meeseeks."}
|
||||
```
|
||||
|
||||
Es ist einem JSON-Array (entspricht einer Python-Liste) sehr ähnlich, aber anstatt in `[]` eingeschlossen zu sein und `,` zwischen den Elementen zu haben, gibt es hier **ein JSON-Objekt pro Zeile**, sie sind durch ein Zeilenumbruchzeichen getrennt.
|
||||
|
||||
/// info | Info
|
||||
|
||||
Der wichtige Punkt ist, dass Ihre App in der Lage ist, jede Zeile der Reihe nach zu erzeugen, während der Client die vorherigen Zeilen konsumiert.
|
||||
|
||||
///
|
||||
|
||||
/// note | Technische Details
|
||||
|
||||
Da jedes JSON-Objekt durch einen Zeilenumbruch getrennt wird, können sie keine wörtlichen Zeilenumbrüche in ihrem Inhalt enthalten, aber sie können escapte Zeilenumbrüche (`\n`) enthalten, das ist Teil des JSON-Standards.
|
||||
|
||||
Normalerweise müssen Sie sich darum aber nicht kümmern, das geschieht automatisch, lesen Sie weiter. 🤓
|
||||
|
||||
///
|
||||
|
||||
## Anwendungsfälle { #use-cases }
|
||||
|
||||
Sie könnten dies verwenden, um Daten von einem **AI LLM**-Service, aus **Logs** oder **Telemetrie**, oder aus anderen Typen von Daten zu streamen, die sich in **JSON**-Items strukturieren lassen.
|
||||
|
||||
/// tip | Tipp
|
||||
|
||||
Wenn Sie Binärdaten streamen möchten, zum Beispiel Video oder Audio, sehen Sie sich den erweiterten Leitfaden an: [Daten streamen](../advanced/stream-data.md).
|
||||
|
||||
///
|
||||
|
||||
## JSON Lines mit FastAPI streamen { #stream-json-lines-with-fastapi }
|
||||
|
||||
Um JSON Lines mit FastAPI zu streamen, können Sie anstelle von `return` in Ihrer *Pfadoperation-Funktion* `yield` verwenden, um jedes Element der Reihe nach zu erzeugen.
|
||||
|
||||
{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[1:24] hl[24] *}
|
||||
|
||||
Wenn jedes JSON-Item, das Sie zurücksenden möchten, vom Typ `Item` ist (ein Pydantic-Modell) und es sich um eine async-Funktion handelt, können Sie den Rückgabetyp als `AsyncIterable[Item]` deklarieren:
|
||||
|
||||
{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[1:24] hl[9:11,22] *}
|
||||
|
||||
Wenn Sie den Rückgabetyp deklarieren, wird FastAPI ihn verwenden, um die Daten zu **validieren**, sie in OpenAPI zu **dokumentieren**, sie zu **filtern** und sie mit Pydantic zu **serialisieren**.
|
||||
|
||||
/// tip | Tipp
|
||||
|
||||
Da Pydantic es auf der **Rust**-Seite serialisiert, erhalten Sie eine deutlich höhere **Leistung** als wenn Sie keinen Rückgabetyp deklarieren.
|
||||
|
||||
///
|
||||
|
||||
### Nicht-async *Pfadoperation-Funktionen* { #non-async-path-operation-functions }
|
||||
|
||||
Sie können auch normale `def`-Funktionen (ohne `async`) verwenden und `yield` auf die gleiche Weise einsetzen.
|
||||
|
||||
FastAPI stellt sicher, dass sie korrekt ausgeführt werden, sodass der Event Loop nicht blockiert wird.
|
||||
|
||||
Da die Funktion in diesem Fall nicht async ist, wäre der richtige Rückgabetyp `Iterable[Item]`:
|
||||
|
||||
{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[27:30] hl[28] *}
|
||||
|
||||
### Kein Rückgabetyp { #no-return-type }
|
||||
|
||||
Sie können den Rückgabetyp auch weglassen. FastAPI verwendet dann den [`jsonable_encoder`](./encoder.md), um die Daten in etwas zu konvertieren, das zu JSON serialisiert werden kann, und sendet sie anschließend als JSON Lines.
|
||||
|
||||
{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[33:36] hl[34] *}
|
||||
|
||||
## Server-Sent Events (SSE) { #server-sent-events-sse }
|
||||
|
||||
FastAPI hat außerdem erstklassige Unterstützung für Server-Sent Events (SSE), die dem sehr ähnlich sind, aber ein paar zusätzliche Details mitbringen. Sie können im nächsten Kapitel mehr darüber lernen: [Server-Sent Events (SSE)](server-sent-events.md). 🤓
|
||||
Loading…
Reference in New Issue