mirror of https://github.com/tiangolo/fastapi.git
Add variants for `openapi-callbacks/tutorial001`
This commit is contained in:
parent
998a92af97
commit
c23c072572
|
|
@ -31,7 +31,7 @@ It will have a *path operation* that will receive an `Invoice` body, and a query
|
|||
|
||||
This part is pretty normal, most of the code is probably already familiar to you:
|
||||
|
||||
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[9:13,36:53] *}
|
||||
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[7:11,34:51] *}
|
||||
|
||||
/// tip
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ Temporarily adopting this point of view (of the *external developer*) can help y
|
|||
|
||||
First create a new `APIRouter` that will contain one or more callbacks.
|
||||
|
||||
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[3,25] *}
|
||||
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *}
|
||||
|
||||
### Create the callback *path operation* { #create-the-callback-path-operation }
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ It should look just like a normal FastAPI *path operation*:
|
|||
* It should probably have a declaration of the body it should receive, e.g. `body: InvoiceEvent`.
|
||||
* And it could also have a declaration of the response it should return, e.g. `response_model=InvoiceEventReceived`.
|
||||
|
||||
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[16:18,21:22,28:32] *}
|
||||
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *}
|
||||
|
||||
There are 2 main differences from a normal *path operation*:
|
||||
|
||||
|
|
@ -169,7 +169,7 @@ At this point you have the *callback path operation(s)* needed (the one(s) that
|
|||
|
||||
Now use the parameter `callbacks` in *your API's path operation decorator* to pass the attribute `.routes` (that's actually just a `list` of routes/*path operations*) from that callback router:
|
||||
|
||||
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[35] *}
|
||||
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *}
|
||||
|
||||
/// tip
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
from fastapi import APIRouter, FastAPI
|
||||
from pydantic import BaseModel, HttpUrl
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
class Invoice(BaseModel):
|
||||
id: str
|
||||
title: str | None = None
|
||||
customer: str
|
||||
total: float
|
||||
|
||||
|
||||
class InvoiceEvent(BaseModel):
|
||||
description: str
|
||||
paid: bool
|
||||
|
||||
|
||||
class InvoiceEventReceived(BaseModel):
|
||||
ok: bool
|
||||
|
||||
|
||||
invoices_callback_router = APIRouter()
|
||||
|
||||
|
||||
@invoices_callback_router.post(
|
||||
"{$callback_url}/invoices/{$request.body.id}", response_model=InvoiceEventReceived
|
||||
)
|
||||
def invoice_notification(body: InvoiceEvent):
|
||||
pass
|
||||
|
||||
|
||||
@app.post("/invoices/", callbacks=invoices_callback_router.routes)
|
||||
def create_invoice(invoice: Invoice, callback_url: HttpUrl | None = None):
|
||||
"""
|
||||
Create an invoice.
|
||||
|
||||
This will (let's imagine) let the API user (some external developer) create an
|
||||
invoice.
|
||||
|
||||
And this path operation will:
|
||||
|
||||
* Send the invoice to the client.
|
||||
* Collect the money from the client.
|
||||
* Send a notification back to the API user (the external developer), as a callback.
|
||||
* At this point is that the API will somehow send a POST request to the
|
||||
external API with the notification of the invoice event
|
||||
(e.g. "payment successful").
|
||||
"""
|
||||
# Send the invoice, collect the money, send the notification (the callback)
|
||||
return {"msg": "Invoice received"}
|
||||
|
|
@ -1,12 +1,33 @@
|
|||
import importlib
|
||||
from types import ModuleType
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from docs_src.openapi_callbacks.tutorial001 import app, invoice_notification
|
||||
|
||||
client = TestClient(app)
|
||||
from tests.utils import needs_py310
|
||||
|
||||
|
||||
def test_get():
|
||||
@pytest.fixture(
|
||||
name="mod",
|
||||
params=[
|
||||
pytest.param("tutorial001"),
|
||||
pytest.param("tutorial001_py310", marks=needs_py310),
|
||||
],
|
||||
)
|
||||
def get_mod(request: pytest.FixtureRequest):
|
||||
mod = importlib.import_module(f"docs_src.openapi_callbacks.{request.param}")
|
||||
return mod
|
||||
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def get_client(mod: ModuleType):
|
||||
client = TestClient(mod.app)
|
||||
client.headers.clear()
|
||||
return client
|
||||
|
||||
|
||||
def test_get(client: TestClient):
|
||||
response = client.post(
|
||||
"/invoices/", json={"id": "fooinvoice", "customer": "John", "total": 5.3}
|
||||
)
|
||||
|
|
@ -14,12 +35,12 @@ def test_get():
|
|||
assert response.json() == {"msg": "Invoice received"}
|
||||
|
||||
|
||||
def test_dummy_callback():
|
||||
def test_dummy_callback(mod: ModuleType):
|
||||
# Just for coverage
|
||||
invoice_notification({})
|
||||
mod.invoice_notification({})
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
def test_openapi_schema(client: TestClient):
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
|
|
|
|||
Loading…
Reference in New Issue