# OpenAPI-Callbacks { #openapi-callbacks } Sie könnten eine API mit einer *Pfadoperation* erstellen, die einen Request an eine *externe API* auslösen könnte, welche von jemand anderem erstellt wurde (wahrscheinlich derselbe Entwickler, der Ihre API *verwenden* würde). Der Vorgang, der stattfindet, wenn Ihre API-Anwendung die *externe API* aufruft, wird als „Callback“ bezeichnet. Denn die Software, die der externe Entwickler geschrieben hat, sendet einen Request an Ihre API und dann *ruft Ihre API zurück* (*calls back*) und sendet einen Request an eine *externe API* (die wahrscheinlich vom selben Entwickler erstellt wurde). In diesem Fall möchten Sie möglicherweise dokumentieren, wie diese externe API aussehen *sollte*. Welche *Pfadoperation* sie haben sollte, welchen Body sie erwarten sollte, welche Response sie zurückgeben sollte, usw. ## Eine Anwendung mit Callbacks { #an-app-with-callbacks } Sehen wir uns das alles anhand eines Beispiels an. Stellen Sie sich vor, Sie entwickeln eine Anwendung, mit der Sie Rechnungen erstellen können. Diese Rechnungen haben eine `id`, einen optionalen `title`, einen `customer` (Kunde) und ein `total` (Gesamtsumme). Der Benutzer Ihrer API (ein externer Entwickler) erstellt mit einem POST-Request eine Rechnung in Ihrer API. Dann wird Ihre API (stellen wir uns vor): * die Rechnung an einen Kunden des externen Entwicklers senden. * das Geld einsammeln. * eine Benachrichtigung an den API-Benutzer (den externen Entwickler) zurücksenden. * Dies erfolgt durch Senden eines POST-Requests (von *Ihrer API*) an eine *externe API*, die von diesem externen Entwickler bereitgestellt wird (das ist der „Callback“). ## Die normale **FastAPI**-Anwendung { #the-normal-fastapi-app } Sehen wir uns zunächst an, wie die normale API-Anwendung aussehen würde, bevor wir den Callback hinzufügen. Sie verfügt über eine *Pfadoperation*, die einen `Invoice`-Body empfängt, und einen Query-Parameter `callback_url`, der die URL für den Callback enthält. Dieser Teil ist ziemlich normal, der größte Teil des Codes ist Ihnen wahrscheinlich bereits bekannt: {* ../../docs_src/openapi_callbacks/tutorial001.py hl[9:13,36:53] *} /// tip | Tipp Der Query-Parameter `callback_url` verwendet einen Pydantic-Url-Typ. /// Das einzig Neue ist `callbacks=invoices_callback_router.routes` als Argument für den *Pfadoperation-Dekorator*. Wir werden als Nächstes sehen, was das ist. ## Dokumentation des Callbacks { #documenting-the-callback } Der tatsächliche Callback-Code hängt stark von Ihrer eigenen API-Anwendung ab. Und er wird wahrscheinlich von Anwendung zu Anwendung sehr unterschiedlich sein. Es könnten nur eine oder zwei Codezeilen sein, wie zum Beispiel: ```Python callback_url = "https://example.com/api/v1/invoices/events/" httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) ``` Der möglicherweise wichtigste Teil des Callbacks besteht jedoch darin, sicherzustellen, dass Ihr API-Benutzer (der externe Entwickler) die *externe API* gemäß den Daten, die *Ihre API* im Requestbody des Callbacks senden wird, korrekt implementiert, usw. Als Nächstes fügen wir den Code hinzu, um zu dokumentieren, wie diese *externe API* aussehen sollte, um den Callback von *Ihrer API* zu empfangen. Diese Dokumentation wird in der Swagger-Oberfläche unter `/docs` in Ihrer API angezeigt und zeigt externen Entwicklern, wie diese die *externe API* erstellen sollten. In diesem Beispiel wird nicht der Callback selbst implementiert (das könnte nur eine Codezeile sein), sondern nur der Dokumentationsteil. /// tip | Tipp Der eigentliche Callback ist nur ein HTTP-Request. Wenn Sie den Callback selbst implementieren, können Sie beispielsweise HTTPX oder Requests verwenden. /// ## Schreiben des Codes, der den Callback dokumentiert { #write-the-callback-documentation-code } Dieser Code wird nicht in Ihrer Anwendung ausgeführt, wir benötigen ihn nur, um zu *dokumentieren*, wie diese *externe API* aussehen soll. Sie wissen jedoch bereits, wie Sie mit **FastAPI** ganz einfach eine automatische Dokumentation für eine API erstellen. Daher werden wir dasselbe Wissen nutzen, um zu dokumentieren, wie die *externe API* aussehen sollte ... indem wir die *Pfadoperation(en)* erstellen, welche die externe API implementieren soll (die, welche Ihre API aufruft). /// tip | Tipp Wenn Sie den Code zum Dokumentieren eines Callbacks schreiben, kann es hilfreich sein, sich vorzustellen, dass Sie dieser *externe Entwickler* sind. Und dass Sie derzeit die *externe API* implementieren, nicht *Ihre API*. Wenn Sie diese Sichtweise (des *externen Entwicklers*) vorübergehend übernehmen, wird es offensichtlicher, wo die Parameter, das Pydantic-Modell für den Body, die Response, usw. für diese *externe API* hingehören. /// ### Einen Callback-`APIRouter` erstellen { #create-a-callback-apirouter } Erstellen Sie zunächst einen neuen `APIRouter`, der einen oder mehrere Callbacks enthält. {* ../../docs_src/openapi_callbacks/tutorial001.py hl[3,25] *} ### Die Callback-*Pfadoperation* erstellen { #create-the-callback-path-operation } Um die Callback-*Pfadoperation* zu erstellen, verwenden Sie denselben `APIRouter`, den Sie oben erstellt haben. Sie sollte wie eine normale FastAPI-*Pfadoperation* aussehen: * Sie sollte wahrscheinlich eine Deklaration des Bodys enthalten, die sie erhalten soll, z. B. `body: InvoiceEvent`. * Und sie könnte auch eine Deklaration der Response enthalten, die zurückgegeben werden soll, z. B. `response_model=InvoiceEventReceived`. {* ../../docs_src/openapi_callbacks/tutorial001.py hl[16:18,21:22,28:32] *} Es gibt zwei Hauptunterschiede zu einer normalen *Pfadoperation*: * Es muss kein tatsächlicher Code vorhanden sein, da Ihre Anwendung diesen Code niemals aufruft. Sie wird nur zur Dokumentation der *externen API* verwendet. Die Funktion könnte also einfach `pass` enthalten. * Der *Pfad* kann einen OpenAPI-3-Ausdruck enthalten (mehr dazu weiter unten), wo er Variablen mit Parametern und Teilen des ursprünglichen Requests verwenden kann, der an *Ihre API* gesendet wurde. ### Der Callback-Pfadausdruck { #the-callback-path-expression } Der Callback-*Pfad* kann einen OpenAPI-3-Ausdruck enthalten, welcher Teile des ursprünglichen Requests enthalten kann, der an *Ihre API* gesendet wurde. In diesem Fall ist es der `str`: ```Python "{$callback_url}/invoices/{$request.body.id}" ``` Wenn Ihr API-Benutzer (der externe Entwickler) also einen Request an *Ihre API* sendet, via: ``` https://yourapi.com/invoices/?callback_url=https://www.external.org/events ``` mit einem JSON-Körper: ```JSON { "id": "2expen51ve", "customer": "Mr. Richie Rich", "total": "9999" } ``` dann verarbeitet *Ihre API* die Rechnung und sendet irgendwann später einen Callback-Request an die `callback_url` (die *externe API*): ``` https://www.external.org/events/invoices/2expen51ve ``` mit einem JSON-Body, der etwa Folgendes enthält: ```JSON { "description": "Payment celebration", "paid": true } ``` und sie würde eine Response von dieser *externen API* mit einem JSON-Body wie dem folgenden erwarten: ```JSON { "ok": true } ``` /// tip | Tipp Beachten Sie, dass die verwendete Callback-URL die URL enthält, die als Query-Parameter in `callback_url` (`https://www.external.org/events`) empfangen wurde, und auch die Rechnungs-`id` aus dem JSON-Body (`2expen51ve`). /// ### Den Callback-Router hinzufügen { #add-the-callback-router } An diesem Punkt haben Sie die benötigte(n) *Callback-Pfadoperation(en)* (diejenige(n), die der *externe Entwickler* in der *externen API* implementieren sollte) im Callback-Router, den Sie oben erstellt haben. Verwenden Sie nun den Parameter `callbacks` im *Pfadoperation-Dekorator Ihrer API*, um das Attribut `.routes` (das ist eigentlich nur eine `list`e von Routen/*Pfadoperationen*) dieses Callback-Routers zu übergeben: {* ../../docs_src/openapi_callbacks/tutorial001.py hl[35] *} /// tip | Tipp Beachten Sie, dass Sie nicht den Router selbst (`invoices_callback_router`) an `callback=` übergeben, sondern das Attribut `.routes`, wie in `invoices_callback_router.routes`. /// ### Es in der Dokumentation testen { #check-the-docs } Jetzt können Sie Ihre Anwendung starten und auf http://127.0.0.1:8000/docs gehen. Sie sehen Ihre Dokumentation, einschließlich eines Abschnitts „Callbacks“ für Ihre *Pfadoperation*, der zeigt, wie die *externe API* aussehen sollte: