From 73260971b5a1499c92e70aa11a96c406497a1f14 Mon Sep 17 00:00:00 2001 From: Ben Dayan Date: Wed, 11 Dec 2019 18:58:01 +0200 Subject: [PATCH] :sparkles: Add support for OpenAPI Callbacks (#722) --- .../tutorial/openapi-callbacks/image01.png | Bin 0 -> 99295 bytes docs/src/openapi_callbacks/tutorial001.py | 53 +++++ docs/tutorial/openapi-callbacks.md | 186 ++++++++++++++++++ fastapi/applications.py | 16 ++ fastapi/openapi/utils.py | 8 + fastapi/routing.py | 44 ++++- fastapi/utils.py | 7 +- mkdocs.yml | 1 + tests/test_application.py | 40 ++-- tests/test_extra_routes.py | 2 +- tests/test_starlette_exception.py | 2 +- .../test_tutorial009.py | 2 +- .../test_extra_models/test_tutorial005.py | 4 +- .../test_handling_errors/test_tutorial002.py | 2 +- .../test_openapi_callbacks/__init__.py | 0 .../test_tutorial001.py | 174 ++++++++++++++++ 16 files changed, 503 insertions(+), 38 deletions(-) create mode 100644 docs/img/tutorial/openapi-callbacks/image01.png create mode 100644 docs/src/openapi_callbacks/tutorial001.py create mode 100644 docs/tutorial/openapi-callbacks.md create mode 100644 tests/test_tutorial/test_openapi_callbacks/__init__.py create mode 100644 tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py diff --git a/docs/img/tutorial/openapi-callbacks/image01.png b/docs/img/tutorial/openapi-callbacks/image01.png new file mode 100644 index 0000000000000000000000000000000000000000..45e6366ab939da5963ef710555da435d91ff47ab GIT binary patch literal 99295 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�ovz&xaOs;8O7u=KFd`=#Fr|r~1 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%0As#TR5<#U zI{!?5E2vkeR4BCmT=A>I5Lx1HpLzc5<>9$jKB~T#v!0*1%Corxl+g2iGcbF3?#&jB z(ln19H;2WeShw!}uuVPhJUtUzcPvJJm_$yaN(k$$I_Au6Vi>r6@A?AXDr5(>hxf!Pq-8?fUU zDqi09Ebi{CHm)y*YMzdwgZi_N0^Ck*&V3jxtO3omM+`AFZXY-ve787QY15R5x)>mH zI4#_O`Vu{kNlH3`MEE(UjMS>OH~t9Ty_hjN$CSd2Ch67S3G707L=8Z|`xlJl9Vpt` zWW7m`xJo2hu6$Pf<5wErw)4x%zNQw3-L?{K1!+{dw{Hde>b7N|?XofHyJKE7D;lQi zC|Z3Xov-D+0NAdIxO{Cduz8<+gVK~nCOw~!GYn7NKe4h!P&RA6F_S{$>&`qtR=FZ2 z)fcf4of(8cWu4LanfVR_J4xT*uwY49(KzxOxc|qVONJHsR7s~p>uj=Pm6~6h*)Bvs zJ3_ghxN0_)N2Eu?e$enf&slyqX2}vrj5k6=o_CMFZezt+fEMhaaD(9l0X&x>mIrlk zoSh~)=${>5)}KSK%6dHwuMp#NpK_e2hvzL)aVj++6OUbX$@(xo**5j91L{5U(`<)* zTjN_sESS$N8>j^@*wY=R^b|DHu%SdDWt46(zQ^3r?y@zE2FNQ@<8Ty^E;~eoEitMp zBoJyIx6ih^6oN}SlZgV{qf7Sj-73u5Ru&mJ3Hz+KZ}%f@iLSNt2n)EEW=t`r6nf=a z_=f)RiTb8TlwFgV)Gya!{1FSeTV@<2&iwu&*225TmN~v6V(G@t3?xX;uoLGp`xhwt zR-z4Df#(sgM_*3LJAwG*AbR~j;3Neew$v%swUA-*rA9?+rJje);8g#$MkbK?xoh$;El#ofiht4{fx(K=nqVDrM; zy{<>9X(6W^qw+&-_ix#LZu~*?(*dkqs#V5_qE!FR*5mV}M9*?J+!q`@=F>{~I(0To zvD6O>ZhS~jH+Nje(B`zGL;4KUTc(}k$Lzd)=@L5$cY+z+8nFkNh@tT<^>QHNsFpbO z_+4wa&^_5GT1YY+JszVtT3A5TJx0uncc4Lh22uD?Ad?vcG*TIFFEXCBYHjGwR;yG8 zX9s%yggq4$k14xa%;bOAUk`y3j=~zid3hP_gS}E2xPOcYBoKmQ)GsHPZKU;wCk3Kb#spHJjt}6`%HWaa65f zsB8ZD%et&EcvBzLV`-zla#rmmOh{C)0}~;f;%__$!>xK4igqyH6O$madget}0FCK3jPLz$ZlIAIB2=)DF=|b& z(xa!KvCt1mGTkWnVn0wAS(>vEmEr9)JyC$h|JIqHCC>T{!if`I*BIIggPro`% zO#Yz80Pb+`)-vpFX?XQazufN|P2I(K2)7F@7Z;|GeZ-*Y^pTF3HfFT!%J z5#Z`v%_92Hi03{PWH?{@r)diF*O$St%H0)UOyXQ6w}{k}n0jQ-Rfte+?NK~NZ>U@2 zRA*e`M45fqw)8E#6TIp$yzYl9l0=;pC(wk`xOtKe^@_}S_L7C4tk(umHhFcjl(CR= z#%q2@<^=^YE%oaPwX|Ki7||DTv-q5%HYWW)&fHOYy} z4s0-==#Mm1#7;;~O+U2ag|I(Mj!u8zl>aLt{eN%rmz4IOCtU{1o{aOL|#QgbnUMs@*OWqflGE4yi?=~Oa*E#G*HnpL~ zfF$dc{{+_$_9_b5Le|HOftywu8gt@(#%0S%f`d(ZobHjAyr7Gu3Un$iQigmXU23cy zX=`cX_{#t8c`w3B%-U#x>1;*s{WEce`;XmX(m3LYsWar36Dl69M=}-3`QKBN;w5U5$OeKnj1;dV+ouEf4N?#iY|UOI?}ILW^z~-E@FOv%E-O=eS&>Cy zw;_`n|1`Hs^_#J}<3)c)0`%I-f<;`TbFSPW)vFHEsfW0)*WLtWB2}L@PhVOyAVa~4 zI?w2i3b65@awVL+9~y}%u&W;SHCeR^T+>mW$Nsi(gmeFUn6k@OoE(=WX!43?c3R*9AyOh~|(CZqe>vPq^72zHr zl>Mg8+!P`*wKv7^Wlx{=g}!p6o%b9zd*8YiyW!#TY5Jm#%3)3Pa(CZ2#)K~4<~I2FhLp@jfh$+sS<^B4AZzLt6x6nX64Oab#_6<^TP zZfl9mi9wo@miR(<=RAC;{3_}Z>&%AFQv6T*Xz?{a*9JdmzKNW^=KqEzmCe!99HGEz zNn~Cz>=oy8xW^I}Ig33!05J+=u^v2Z)XKki>!$Ra>hLbjtUg-P%sDjx*3Psrk$!-PD&#yebCQ2ah7uS>bs-d zv@c4Ye!Tg5uMgbii~1%IzrEu(T#yJNuxkzk=VpAWkfo*%&4F--Zn7*niaen&`CyI$ z+LTGKH5>$O1+r(N*&~UB%Q7+=+^Bn3S#^@&OtEhaG!5=3L+3g~96UE>9Xi@kFtK$g zrWSy-w&4xGve-7;#Hgj5>6R*(W4TN9rovE)Qij|^O&e%u==H1Tn&Y)Z$pF=+)I(d) zoeEAzsg>}+A{?^&p1r=KsBU^zJG_?DjlLQ%!36QozC5MYP3kuhrzfcD zAGH?G42cfi88)w>=}(i^P@w{AYFKf%s9aYVIqD7wvCzw-xt z->O-%=T*MD6_i+X(>5p15^txH_c;bD$~j$29?>TyzwD+rUG?SZ{u^lw`birpmUW2m zn2@Rx5(aTv*X+~d4-kU!svwG~)MroGbSrluHHB*&u>0W%mb!qLTtZ-%vGV@^fv<+b(9t`r% z3=BGNnA(NP4}M!h0!$FRxo~qP-<|WTWn|db5ak{{$(C2$7_50#TVv+0QTEBUssbC@ z`2?LvIa?^{H|=0>vQ~_Otyk_#vBYuvxmkM}A~u@fDQ%M|xI8x|rb03?mug(e&k?zU zn2fTfIp|N0NOQ$N73VuX^AWQCLX1XYm6I=2YC0p|xlAPRuzF{UJKK#>Q&;6o?Sxu} zN0-fG{P5Ox-FPHMR&-<*dC{G~ZmD+qZWRf?AL#>I&?C#U+eZPC4Sp63s_}6VU3hp# z$VE=xCN3O1l>ns{14$h)>d``cN1j6jKN=mrGTMQDkhR9#6jAPde5wh;!%LL<_-XQ` z-rU}0uneg!t8veg1Hf}ZZEKxqVh_(mFjK*xF~%L#nsqOX3#ZGdF_gxxVEGT;=ip!<{Yb9QT*n(rgkNlsz<-%3iW$Ia zd?sCG>A9UEYTcEE@4+5qHZtTD!r&93C5p6ap|JBGcu`O5|70?O*V*jgpd9)Lc|<-s z*>8Hb+8<}D2VHD<=V#I)^p?B#!FQ8M^ZKlP_g~R+;#cLzJOgQ0Vkm6=8;yr#4IZb@ zzgrPK2)MBAWk)c$ciXU*F+8I0zWQ08k(8DHhfW?+*&(q1ec?u1Mh8G1*y4j~)P#Ou zG-k7rHKh-zD(PFm@NWTLPGMvg~lm|@`-MFazG z!M+SLpvT-L5M3Jf_>LcyhoD6%0kGwCp^1_pLP@$48ag$csyyJ7Pfi0eSuzJ&^tzTh z&116Y%B~k9&P0+uXHYA%$qUr0o}}Ybc8+A~6VcZxBHJQ2(zq3kIM6!ZtusAGyOUSy zK>I5S!1YB=WEtKQ)8D#p6~}Zv*T9u6njUFxNkh*30WNqjCS30{8JjU(p?2&&Av)QI zoY87#WKCL#-DPE8{g6fH^b%LW$;th_wN z>fXCRq)0HfTw`X68?o%Wt4}%**?AN&`~EdaV{;=Wv3FG<9c}t=8;^dyNW-6wkYz6+ zT=wzw*yEutCM$+_Ux<5&W(7{wRxr*MZ>%{U-teX79dU7RVfrj3J1Q;;zGx7@@TX=p zXE$EX{B__!rm9iMU2CC?(YLB7@Af` z2O&iar4NN&jd~M z4>035zLrvY&mJ%A?Hj^w@MnAH_J7$q90B|FH1OtvGh*29 zv$@0t%6oZ>QJvepbvB`-xl$7J*zc_rN@}!a!;zzq;V^99`RqiF!1JobbRh^Ki#Y7a ze_GPV@he_H;IL-~0D#%9h5LIyZrdtk8e6RL(X8VyJ2cYb0?RXqR0TrRKqw#cB9BcJ z#q%o*HojH7;v%p$hg2w32Y91niG={z7ut5dMtBrlk){pv^VJEpPePWtV9Arg5rc&6FzIpv#9&y4oLuLGXyC@5i)D#;s9? zl{fnsIX59@?5Z7<*mG3SxK!TEcllNq8pz?DNa`97r#j^1Eq=dn@g9ErKhh z&0q7*$|sQ<{%R;(!C-^ta9@2rNHT_sMfU}zm0#BeqA-7rY`I7X@Qs#;^N-8XI_^

Jxa*xhe^}g2}DxrTcC5Fr!`?p2Lr5>TEG$z3aJfy-I+*73s(cuXkneP6k%~&Y|ErdY<4Bu;pi8E zdRy1TaKeJ0JVfc}Gdr8Y+eNhS)bqUKRRDEH3xlYKCk!j+Z4>jSOAnN*P~Q9T1!DJV zbK1SG4iL3(iM*UO5Y1@VadH+3GtLPgljRXQeMblsCy~=oq|aiu;569{$1V?hg1b`P?OU!iM}C^BtBW4< zRDxl-BCKY^S}1yJ)shd+_|2k3!-go^;3y(5Uu1&?hB-Rr#7Lkr_nZyzG$)5tJ9ECb{DD%{7R?b zdF#1;2)|gRL*~x>c@bN5-N?-$vajo)bM*fKk=hz~sg&f7s5d>;r9dTL~B{0hGkAkeK KOp%na-+usYg-0&{ literal 0 Hc-jL100001 diff --git a/docs/src/openapi_callbacks/tutorial001.py b/docs/src/openapi_callbacks/tutorial001.py new file mode 100644 index 0000000000..b2838b0a26 --- /dev/null +++ b/docs/src/openapi_callbacks/tutorial001.py @@ -0,0 +1,53 @@ +from fastapi import APIRouter, FastAPI +from pydantic import BaseModel, HttpUrl +from starlette.responses import JSONResponse + +app = FastAPI() + + +class Invoice(BaseModel): + id: str + title: str = None + customer: str + total: float + + +class InvoiceEvent(BaseModel): + description: str + paid: bool + + +class InvoiceEventReceived(BaseModel): + ok: bool + + +invoices_callback_router = APIRouter(default_response_class=JSONResponse) + + +@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): + """ + 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"} diff --git a/docs/tutorial/openapi-callbacks.md b/docs/tutorial/openapi-callbacks.md new file mode 100644 index 0000000000..e48ee7f951 --- /dev/null +++ b/docs/tutorial/openapi-callbacks.md @@ -0,0 +1,186 @@ +You could create an API with a *path operation* that could trigger a request to an *external API* created by someone else (probably the same developer that would be *using* your API). + +The process that happens when your API app calls the *external API* is named a "callback". Because the software that the external developer wrote sends a request to your API and then your API *calls back*, sending a request to an *external API* (that was probably created by the same developer). + +In this case, you could want to document how that external API *should* look like. What *path operation* it should have, what body it should expect, what response it should return, etc. + +## An app with callbacks + +Let's see all this with an example. + +Imagine you develop an app that allows creating invoices. + +These invoices will have an `id`, `title` (optional), `customer`, and `total`. + +The user of your API (an external developer) will create an invoice in your API with a POST request. + +Then your API will (let's imagine): + +* Send the invoice to some customer of the external developer. +* Collect the money. +* Send a notification back to the API user (the external developer). + * This will be done by sending a POST request (from *your API*) to some *external API* provided by that external developer (this is the "callback"). + +## The normal **FastAPI** app + +Let's first see how the normal API app would look like before adding the callback. + +It will have a *path operation* that will receive an `Invoice` body, and a query parameter `callback_url` that will contain the URL for the callback. + +This part is pretty normal, most of the code is probably already familiar to you: + +```Python hl_lines="8 9 10 11 12 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54" +{!./src/openapi_callbacks/tutorial001.py!} +``` + +!!! tip + The `callback_url` query parameter uses a Pydantic URL type. + +The only new thing is the `callbacks=messages_callback_router.routes` as an argument to the *path operation decorator*. We'll see what that is next. + +## Documenting the callback + +The actual callback code will depend heavily on your own API app. + +And it will probably vary a lot from one app to the next. + +It could be just one or two lines of code, like: + +```Python +callback_url = "https://example.com/api/v1/invoices/events/" +requests.post(callback_url, json={"description": "Invoice paid", "paid": True}) +``` + +But possibly the most important part of the callback is making sure that your API user (the external developer) implements the *external API* correctly, according to the data that *your API* is going to send in the request body of the callback, etc. + +So, what we will do next is add the code to document how that *external API* should look like to receive the callback from *your API*. + +That documentation will show up in the Swagger UI at `/docs` in your API, and it will let external developers know how to build the *external API*. + +This example doesn't implement the callback itself (that could be just a line of code), only the documentation part. + +!!! tip + The actual callback is just an HTTP request. + + When implementing the callback yourself, you could use something like HTTPX or Requests. + +## Write the callback documentation code + +This code won't be executed in your app, we only need it to *document* how that *external API* should look like. + +But, you already know how to easily create automatic documentation for an API with **FastAPI**. + +So we are going to use that same knowledge to document how the *external API* should look like... by creating the *path operation(s)* that the external API should implement (the ones your API will call). + +!!! tip + When writing the code to document a callback, it might be useful to imagine that you are that *external developer*. And that you are currently implementing the *external API*, not *your API*. + + Temporarily adopting this point of view (of the *external developer*) can help you feel like it's more obvious where to put the parameters, the Pydantic model for the body, for the response, etc. for that *external API*. + +### Create a callback `APIRouter` + +First create a new `APIRouter` that will contain one or more callbacks. + +This router will never be added to an actual `FastAPI` app (i.e. it will never be passed to `app.include_router(...)`). + +Because of that, you need to declare what will be the `default_response_class`, and set it to `JSONResponse`. + +!!! Note "Technical Details" + The `response_class` is normally set by the `FastAPI` app during the call to `app.include_router(some_router)`. + + But as we are never calling `app.include_router(some_router)`, we need to set the `default_response_class` during creation of the `APIRouter`. + +```Python hl_lines="3 24" +{!./src/openapi_callbacks/tutorial001.py!} +``` + +### Create the callback *path operation* + +To create the callback *path operation* use the same `APIRouter` you created above. + +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`. + +```Python hl_lines="15 16 17 20 21 27 28 29 30 31 32" +{!./src/openapi_callbacks/tutorial001.py!} +``` + +There are 2 main differences from a normal *path operation*: + +* It doesn't need to have any actual code, because your app will never call this code. It's only used to document the *external API*. So, the function could just have `pass`. +* The *path* can contain an OpenAPI 3 expression (see more below) where it can use variables with parameters and parts of the original request sent to *your API*. + +### The callback path expression + +The callback *path* can have an OpenAPI 3 expression that can contain parts of the original request sent to *your API*. + +In this case, it's the `str`: + +```Python +"{$callback_url}/invoices/{$request.body.id}" +``` + +So, if your API user (the external developer) sends a request to *your API* to: + +``` +https://yourapi.com/invoices/?callback_url=https://www.external.org/events +``` + +with a JSON body of: + +```JSON +{ + "id": "2expen51ve", + "customer": "Mr. Richie Rich", + "total": "9999" +} +``` + +Then *your API* will process the invoice, and at some point later, send a callback request to the `callback_url` (the *external API*): + +``` +https://www.external.org/events/invoices/2expen51ve +``` + +with a JSON body containing something like: + +```JSON +{ + "description": "Payment celebration", + "paid": true +} +``` + +and it would expect a response from that *external API* with a JSON body like: + +```JSON +{ + "ok": true +} +``` + +!!! tip + Notice how the callback URL used contains the URL received as a query parameter in `callback_url` (`https://www.external.org/events`) and also the invoice `id` from inside of the JSON body (`2expen51ve`). + +### Add the callback router + +At this point you have the *callback path operation(s)* needed (the one(s) that the *external developer* should implement in the *external API*) in the callback router you created above. + +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: + +```Python hl_lines="35" +{!./src/openapi_callbacks/tutorial001.py!} +``` + +!!! tip + Notice that you are not passing the router itself (`invoices_callback_router`) to `callback=`, but the attribute `.routes`, as in `invoices_callback_router.routes`. + +### Check the docs + +Now you can start your app with Uvicorn and go to http://127.0.0.1:8000/docs. + +You will see your docs including a "Callback" section for your *path operation* that shows how the *external API* should look like: + + diff --git a/fastapi/applications.py b/fastapi/applications.py index ab1b77e6dc..5a533866b4 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -303,6 +303,7 @@ class FastAPI(Starlette): include_in_schema: bool = True, response_class: Type[Response] = None, name: str = None, + callbacks: List[routing.APIRoute] = None, ) -> Callable: if response_model_skip_defaults is not None: warning_response_model_skip_defaults_deprecated() # pragma: nocover @@ -327,6 +328,7 @@ class FastAPI(Starlette): include_in_schema=include_in_schema, response_class=response_class or self.default_response_class, name=name, + callbacks=callbacks, ) def put( @@ -351,6 +353,7 @@ class FastAPI(Starlette): include_in_schema: bool = True, response_class: Type[Response] = None, name: str = None, + callbacks: List[routing.APIRoute] = None, ) -> Callable: if response_model_skip_defaults is not None: warning_response_model_skip_defaults_deprecated() # pragma: nocover @@ -375,6 +378,7 @@ class FastAPI(Starlette): include_in_schema=include_in_schema, response_class=response_class or self.default_response_class, name=name, + callbacks=callbacks, ) def post( @@ -399,6 +403,7 @@ class FastAPI(Starlette): include_in_schema: bool = True, response_class: Type[Response] = None, name: str = None, + callbacks: List[routing.APIRoute] = None, ) -> Callable: if response_model_skip_defaults is not None: warning_response_model_skip_defaults_deprecated() # pragma: nocover @@ -423,6 +428,7 @@ class FastAPI(Starlette): include_in_schema=include_in_schema, response_class=response_class or self.default_response_class, name=name, + callbacks=callbacks, ) def delete( @@ -447,6 +453,7 @@ class FastAPI(Starlette): include_in_schema: bool = True, response_class: Type[Response] = None, name: str = None, + callbacks: List[routing.APIRoute] = None, ) -> Callable: if response_model_skip_defaults is not None: warning_response_model_skip_defaults_deprecated() # pragma: nocover @@ -471,6 +478,7 @@ class FastAPI(Starlette): include_in_schema=include_in_schema, response_class=response_class or self.default_response_class, name=name, + callbacks=callbacks, ) def options( @@ -495,6 +503,7 @@ class FastAPI(Starlette): include_in_schema: bool = True, response_class: Type[Response] = None, name: str = None, + callbacks: List[routing.APIRoute] = None, ) -> Callable: if response_model_skip_defaults is not None: warning_response_model_skip_defaults_deprecated() # pragma: nocover @@ -519,6 +528,7 @@ class FastAPI(Starlette): include_in_schema=include_in_schema, response_class=response_class or self.default_response_class, name=name, + callbacks=callbacks, ) def head( @@ -543,6 +553,7 @@ class FastAPI(Starlette): include_in_schema: bool = True, response_class: Type[Response] = None, name: str = None, + callbacks: List[routing.APIRoute] = None, ) -> Callable: if response_model_skip_defaults is not None: warning_response_model_skip_defaults_deprecated() # pragma: nocover @@ -567,6 +578,7 @@ class FastAPI(Starlette): include_in_schema=include_in_schema, response_class=response_class or self.default_response_class, name=name, + callbacks=callbacks, ) def patch( @@ -591,6 +603,7 @@ class FastAPI(Starlette): include_in_schema: bool = True, response_class: Type[Response] = None, name: str = None, + callbacks: List[routing.APIRoute] = None, ) -> Callable: if response_model_skip_defaults is not None: warning_response_model_skip_defaults_deprecated() # pragma: nocover @@ -615,6 +628,7 @@ class FastAPI(Starlette): include_in_schema=include_in_schema, response_class=response_class or self.default_response_class, name=name, + callbacks=callbacks, ) def trace( @@ -639,6 +653,7 @@ class FastAPI(Starlette): include_in_schema: bool = True, response_class: Type[Response] = None, name: str = None, + callbacks: List[routing.APIRoute] = None, ) -> Callable: if response_model_skip_defaults is not None: warning_response_model_skip_defaults_deprecated() # pragma: nocover @@ -663,4 +678,5 @@ class FastAPI(Starlette): include_in_schema=include_in_schema, response_class=response_class or self.default_response_class, name=name, + callbacks=callbacks, ) diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index d2dd620813..d53ee6b97b 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -187,6 +187,14 @@ def get_openapi_path( ) if request_body_oai: operation["requestBody"] = request_body_oai + if route.callbacks: + callbacks = {} + for callback in route.callbacks: + cb_path, cb_security_schemes, cb_definitions, = get_openapi_path( + route=callback, model_name_map=model_name_map + ) + callbacks[callback.name] = {callback.path: cb_path} + operation["callbacks"] = callbacks if route.responses: for (additional_status_code, response) in route.responses.items(): assert isinstance( diff --git a/fastapi/routing.py b/fastapi/routing.py index 8f4c67ca5d..ee75374b4e 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -218,6 +218,7 @@ class APIRoute(routing.Route): include_in_schema: bool = True, response_class: Optional[Type[Response]] = None, dependency_overrides_provider: Any = None, + callbacks: Optional[List["APIRoute"]] = None, ) -> None: self.path = path self.endpoint = endpoint @@ -338,6 +339,7 @@ class APIRoute(routing.Route): ) self.body_field = get_body_field(dependant=self.dependant, name=self.unique_id) self.dependency_overrides_provider = dependency_overrides_provider + self.callbacks = callbacks self.app = request_response(self.get_route_handler()) def get_route_handler(self) -> Callable: @@ -363,12 +365,14 @@ class APIRouter(routing.Router): default: ASGIApp = None, dependency_overrides_provider: Any = None, route_class: Type[APIRoute] = APIRoute, + default_response_class: Type[Response] = None, ) -> None: super().__init__( routes=routes, redirect_slashes=redirect_slashes, default=default ) self.dependency_overrides_provider = dependency_overrides_provider self.route_class = route_class + self.default_response_class = default_response_class def add_api_route( self, @@ -395,6 +399,7 @@ class APIRouter(routing.Router): response_class: Type[Response] = None, name: str = None, route_class_override: Optional[Type[APIRoute]] = None, + callbacks: List[APIRoute] = None, ) -> None: if response_model_skip_defaults is not None: warning_response_model_skip_defaults_deprecated() # pragma: nocover @@ -420,9 +425,10 @@ class APIRouter(routing.Router): response_model_exclude_unset or response_model_skip_defaults ), include_in_schema=include_in_schema, - response_class=response_class, + response_class=response_class or self.default_response_class, name=name, dependency_overrides_provider=self.dependency_overrides_provider, + callbacks=callbacks, ) self.routes.append(route) @@ -449,6 +455,7 @@ class APIRouter(routing.Router): include_in_schema: bool = True, response_class: Type[Response] = None, name: str = None, + callbacks: List[APIRoute] = None, ) -> Callable: if response_model_skip_defaults is not None: warning_response_model_skip_defaults_deprecated() # pragma: nocover @@ -475,8 +482,9 @@ class APIRouter(routing.Router): response_model_exclude_unset or response_model_skip_defaults ), include_in_schema=include_in_schema, - response_class=response_class, + response_class=response_class or self.default_response_class, name=name, + callbacks=callbacks, ) return func @@ -586,6 +594,7 @@ class APIRouter(routing.Router): include_in_schema: bool = True, response_class: Type[Response] = None, name: str = None, + callbacks: List[APIRoute] = None, ) -> Callable: if response_model_skip_defaults is not None: warning_response_model_skip_defaults_deprecated() # pragma: nocover @@ -609,8 +618,9 @@ class APIRouter(routing.Router): response_model_exclude_unset or response_model_skip_defaults ), include_in_schema=include_in_schema, - response_class=response_class, + response_class=response_class or self.default_response_class, name=name, + callbacks=callbacks, ) def put( @@ -635,6 +645,7 @@ class APIRouter(routing.Router): include_in_schema: bool = True, response_class: Type[Response] = None, name: str = None, + callbacks: List[APIRoute] = None, ) -> Callable: if response_model_skip_defaults is not None: warning_response_model_skip_defaults_deprecated() # pragma: nocover @@ -658,8 +669,9 @@ class APIRouter(routing.Router): response_model_exclude_unset or response_model_skip_defaults ), include_in_schema=include_in_schema, - response_class=response_class, + response_class=response_class or self.default_response_class, name=name, + callbacks=callbacks, ) def post( @@ -684,6 +696,7 @@ class APIRouter(routing.Router): include_in_schema: bool = True, response_class: Type[Response] = None, name: str = None, + callbacks: List[APIRoute] = None, ) -> Callable: if response_model_skip_defaults is not None: warning_response_model_skip_defaults_deprecated() # pragma: nocover @@ -707,8 +720,9 @@ class APIRouter(routing.Router): response_model_exclude_unset or response_model_skip_defaults ), include_in_schema=include_in_schema, - response_class=response_class, + response_class=response_class or self.default_response_class, name=name, + callbacks=callbacks, ) def delete( @@ -733,6 +747,7 @@ class APIRouter(routing.Router): include_in_schema: bool = True, response_class: Type[Response] = None, name: str = None, + callbacks: List[APIRoute] = None, ) -> Callable: if response_model_skip_defaults is not None: warning_response_model_skip_defaults_deprecated() # pragma: nocover @@ -756,8 +771,9 @@ class APIRouter(routing.Router): response_model_exclude_unset or response_model_skip_defaults ), include_in_schema=include_in_schema, - response_class=response_class, + response_class=response_class or self.default_response_class, name=name, + callbacks=callbacks, ) def options( @@ -782,6 +798,7 @@ class APIRouter(routing.Router): include_in_schema: bool = True, response_class: Type[Response] = None, name: str = None, + callbacks: List[APIRoute] = None, ) -> Callable: if response_model_skip_defaults is not None: warning_response_model_skip_defaults_deprecated() # pragma: nocover @@ -805,8 +822,9 @@ class APIRouter(routing.Router): response_model_exclude_unset or response_model_skip_defaults ), include_in_schema=include_in_schema, - response_class=response_class, + response_class=response_class or self.default_response_class, name=name, + callbacks=callbacks, ) def head( @@ -831,6 +849,7 @@ class APIRouter(routing.Router): include_in_schema: bool = True, response_class: Type[Response] = None, name: str = None, + callbacks: List[APIRoute] = None, ) -> Callable: if response_model_skip_defaults is not None: warning_response_model_skip_defaults_deprecated() # pragma: nocover @@ -854,8 +873,9 @@ class APIRouter(routing.Router): response_model_exclude_unset or response_model_skip_defaults ), include_in_schema=include_in_schema, - response_class=response_class, + response_class=response_class or self.default_response_class, name=name, + callbacks=callbacks, ) def patch( @@ -880,6 +900,7 @@ class APIRouter(routing.Router): include_in_schema: bool = True, response_class: Type[Response] = None, name: str = None, + callbacks: List[APIRoute] = None, ) -> Callable: if response_model_skip_defaults is not None: warning_response_model_skip_defaults_deprecated() # pragma: nocover @@ -903,8 +924,9 @@ class APIRouter(routing.Router): response_model_exclude_unset or response_model_skip_defaults ), include_in_schema=include_in_schema, - response_class=response_class, + response_class=response_class or self.default_response_class, name=name, + callbacks=callbacks, ) def trace( @@ -929,6 +951,7 @@ class APIRouter(routing.Router): include_in_schema: bool = True, response_class: Type[Response] = None, name: str = None, + callbacks: List[APIRoute] = None, ) -> Callable: if response_model_skip_defaults is not None: warning_response_model_skip_defaults_deprecated() # pragma: nocover @@ -952,6 +975,7 @@ class APIRouter(routing.Router): response_model_exclude_unset or response_model_skip_defaults ), include_in_schema=include_in_schema, - response_class=response_class, + response_class=response_class or self.default_response_class, name=name, + callbacks=callbacks, ) diff --git a/fastapi/utils.py b/fastapi/utils.py index 5e624f0ea2..a068cc5823 100644 --- a/fastapi/utils.py +++ b/fastapi/utils.py @@ -46,6 +46,7 @@ def warning_response_model_skip_defaults_deprecated() -> None: def get_flat_models_from_routes(routes: Sequence[BaseRoute]) -> Set[Type[BaseModel]]: body_fields_from_routes: List[ModelField] = [] responses_from_routes: List[ModelField] = [] + callback_flat_models: Set[Type[BaseModel]] = set() for route in routes: if getattr(route, "include_in_schema", None) and isinstance( route, routing.APIRoute @@ -59,7 +60,9 @@ def get_flat_models_from_routes(routes: Sequence[BaseRoute]) -> Set[Type[BaseMod responses_from_routes.append(route.response_field) if route.response_fields: responses_from_routes.extend(route.response_fields.values()) - flat_models = get_flat_models_from_fields( + if route.callbacks: + callback_flat_models |= get_flat_models_from_routes(route.callbacks) + flat_models = callback_flat_models | get_flat_models_from_fields( body_fields_from_routes + responses_from_routes, known_models=set() ) return flat_models @@ -153,6 +156,6 @@ def create_cloned_field(field: ModelField) -> ModelField: def generate_operation_id_for_path(*, name: str, path: str, method: str) -> str: operation_id = name + path - operation_id = operation_id.replace("{", "_").replace("}", "_").replace("/", "_") + operation_id = re.sub("[^0-9a-zA-Z_]", "_", operation_id) operation_id = operation_id + "_" + method.lower() return operation_id diff --git a/mkdocs.yml b/mkdocs.yml index d458366a76..541afc8e8a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -88,6 +88,7 @@ nav: - Testing Dependencies with Overrides: 'tutorial/testing-dependencies.md' - Debugging: 'tutorial/debugging.md' - Extending OpenAPI: 'tutorial/extending-openapi.md' + - OpenAPI Callbacks: 'tutorial/openapi-callbacks.md' - Concurrency and async / await: 'async.md' - Deployment: 'deployment.md' - Project Generation - Template: 'project-generation.md' diff --git a/tests/test_application.py b/tests/test_application.py index bdbff1cf6f..11f463336a 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -244,7 +244,7 @@ openapi_schema = { }, }, "summary": "Get Path Param Required Id", - "operationId": "get_path_param_required_id_path_param-required__item_id__get", + "operationId": "get_path_param_required_id_path_param_required__item_id__get", "parameters": [ { "required": True, @@ -274,7 +274,7 @@ openapi_schema = { }, }, "summary": "Get Path Param Min Length", - "operationId": "get_path_param_min_length_path_param-minlength__item_id__get", + "operationId": "get_path_param_min_length_path_param_minlength__item_id__get", "parameters": [ { "required": True, @@ -308,7 +308,7 @@ openapi_schema = { }, }, "summary": "Get Path Param Max Length", - "operationId": "get_path_param_max_length_path_param-maxlength__item_id__get", + "operationId": "get_path_param_max_length_path_param_maxlength__item_id__get", "parameters": [ { "required": True, @@ -342,7 +342,7 @@ openapi_schema = { }, }, "summary": "Get Path Param Min Max Length", - "operationId": "get_path_param_min_max_length_path_param-min_maxlength__item_id__get", + "operationId": "get_path_param_min_max_length_path_param_min_maxlength__item_id__get", "parameters": [ { "required": True, @@ -377,7 +377,7 @@ openapi_schema = { }, }, "summary": "Get Path Param Gt", - "operationId": "get_path_param_gt_path_param-gt__item_id__get", + "operationId": "get_path_param_gt_path_param_gt__item_id__get", "parameters": [ { "required": True, @@ -411,7 +411,7 @@ openapi_schema = { }, }, "summary": "Get Path Param Gt0", - "operationId": "get_path_param_gt0_path_param-gt0__item_id__get", + "operationId": "get_path_param_gt0_path_param_gt0__item_id__get", "parameters": [ { "required": True, @@ -445,7 +445,7 @@ openapi_schema = { }, }, "summary": "Get Path Param Ge", - "operationId": "get_path_param_ge_path_param-ge__item_id__get", + "operationId": "get_path_param_ge_path_param_ge__item_id__get", "parameters": [ { "required": True, @@ -479,7 +479,7 @@ openapi_schema = { }, }, "summary": "Get Path Param Lt", - "operationId": "get_path_param_lt_path_param-lt__item_id__get", + "operationId": "get_path_param_lt_path_param_lt__item_id__get", "parameters": [ { "required": True, @@ -513,7 +513,7 @@ openapi_schema = { }, }, "summary": "Get Path Param Lt0", - "operationId": "get_path_param_lt0_path_param-lt0__item_id__get", + "operationId": "get_path_param_lt0_path_param_lt0__item_id__get", "parameters": [ { "required": True, @@ -547,7 +547,7 @@ openapi_schema = { }, }, "summary": "Get Path Param Le", - "operationId": "get_path_param_le_path_param-le__item_id__get", + "operationId": "get_path_param_le_path_param_le__item_id__get", "parameters": [ { "required": True, @@ -581,7 +581,7 @@ openapi_schema = { }, }, "summary": "Get Path Param Lt Gt", - "operationId": "get_path_param_lt_gt_path_param-lt-gt__item_id__get", + "operationId": "get_path_param_lt_gt_path_param_lt_gt__item_id__get", "parameters": [ { "required": True, @@ -616,7 +616,7 @@ openapi_schema = { }, }, "summary": "Get Path Param Le Ge", - "operationId": "get_path_param_le_ge_path_param-le-ge__item_id__get", + "operationId": "get_path_param_le_ge_path_param_le_ge__item_id__get", "parameters": [ { "required": True, @@ -651,7 +651,7 @@ openapi_schema = { }, }, "summary": "Get Path Param Lt Int", - "operationId": "get_path_param_lt_int_path_param-lt-int__item_id__get", + "operationId": "get_path_param_lt_int_path_param_lt_int__item_id__get", "parameters": [ { "required": True, @@ -685,7 +685,7 @@ openapi_schema = { }, }, "summary": "Get Path Param Gt Int", - "operationId": "get_path_param_gt_int_path_param-gt-int__item_id__get", + "operationId": "get_path_param_gt_int_path_param_gt_int__item_id__get", "parameters": [ { "required": True, @@ -719,7 +719,7 @@ openapi_schema = { }, }, "summary": "Get Path Param Le Int", - "operationId": "get_path_param_le_int_path_param-le-int__item_id__get", + "operationId": "get_path_param_le_int_path_param_le_int__item_id__get", "parameters": [ { "required": True, @@ -753,7 +753,7 @@ openapi_schema = { }, }, "summary": "Get Path Param Ge Int", - "operationId": "get_path_param_ge_int_path_param-ge-int__item_id__get", + "operationId": "get_path_param_ge_int_path_param_ge_int__item_id__get", "parameters": [ { "required": True, @@ -787,7 +787,7 @@ openapi_schema = { }, }, "summary": "Get Path Param Lt Gt Int", - "operationId": "get_path_param_lt_gt_int_path_param-lt-gt-int__item_id__get", + "operationId": "get_path_param_lt_gt_int_path_param_lt_gt_int__item_id__get", "parameters": [ { "required": True, @@ -822,7 +822,7 @@ openapi_schema = { }, }, "summary": "Get Path Param Le Ge Int", - "operationId": "get_path_param_le_ge_int_path_param-le-ge-int__item_id__get", + "operationId": "get_path_param_le_ge_int_path_param_le_ge_int__item_id__get", "parameters": [ { "required": True, @@ -1037,7 +1037,7 @@ openapi_schema = { }, }, "summary": "Get Query Param Required", - "operationId": "get_query_param_required_query_param-required_get", + "operationId": "get_query_param_required_query_param_required_get", "parameters": [ { "required": True, @@ -1067,7 +1067,7 @@ openapi_schema = { }, }, "summary": "Get Query Param Required Type", - "operationId": "get_query_param_required_type_query_param-required_int_get", + "operationId": "get_query_param_required_type_query_param_required_int_get", "parameters": [ { "required": True, diff --git a/tests/test_extra_routes.py b/tests/test_extra_routes.py index f5bd7b3f20..bfe79d77f9 100644 --- a/tests/test_extra_routes.py +++ b/tests/test_extra_routes.py @@ -259,7 +259,7 @@ openapi_schema = { }, }, "summary": "Get Not Decorated", - "operationId": "get_not_decorated_items-not-decorated__item_id__get", + "operationId": "get_not_decorated_items_not_decorated__item_id__get", "parameters": [ { "required": True, diff --git a/tests/test_starlette_exception.py b/tests/test_starlette_exception.py index 706957b991..bafa318357 100644 --- a/tests/test_starlette_exception.py +++ b/tests/test_starlette_exception.py @@ -80,7 +80,7 @@ openapi_schema = { }, }, "summary": "Create Item", - "operationId": "create_item_starlette-items__item_id__get", + "operationId": "create_item_starlette_items__item_id__get", "parameters": [ { "required": True, diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial009.py b/tests/test_tutorial/test_body_nested_models/test_tutorial009.py index e88e7a94ad..d51b072529 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial009.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial009.py @@ -27,7 +27,7 @@ openapi_schema = { }, }, "summary": "Create Index Weights", - "operationId": "create_index_weights_index-weights__post", + "operationId": "create_index_weights_index_weights__post", "requestBody": { "content": { "application/json": { diff --git a/tests/test_tutorial/test_extra_models/test_tutorial005.py b/tests/test_tutorial/test_extra_models/test_tutorial005.py index 7f815e08a7..935debf922 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial005.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial005.py @@ -16,7 +16,7 @@ openapi_schema = { "content": { "application/json": { "schema": { - "title": "Response Read Keyword Weights Keyword-Weights Get", + "title": "Response Read Keyword Weights Keyword Weights Get", "type": "object", "additionalProperties": {"type": "number"}, } @@ -25,7 +25,7 @@ openapi_schema = { } }, "summary": "Read Keyword Weights", - "operationId": "read_keyword_weights_keyword-weights__get", + "operationId": "read_keyword_weights_keyword_weights__get", } } }, diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial002.py b/tests/test_tutorial/test_handling_errors/test_tutorial002.py index 3381f9d720..e0aa05a159 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial002.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial002.py @@ -27,7 +27,7 @@ openapi_schema = { }, }, "summary": "Read Item Header", - "operationId": "read_item_header_items-header__item_id__get", + "operationId": "read_item_header_items_header__item_id__get", "parameters": [ { "required": True, diff --git a/tests/test_tutorial/test_openapi_callbacks/__init__.py b/tests/test_tutorial/test_openapi_callbacks/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py b/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py new file mode 100644 index 0000000000..febbe7479d --- /dev/null +++ b/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py @@ -0,0 +1,174 @@ +from starlette.testclient import TestClient + +from openapi_callbacks.tutorial001 import app, invoice_notification + +client = TestClient(app) + +openapi_schema = { + "openapi": "3.0.2", + "info": {"title": "Fast API", "version": "0.1.0"}, + "paths": { + "/invoices/": { + "post": { + "summary": "Create Invoice", + "description": 'Create an invoice.\n\nThis will (let\'s imagine) let the API user (some external developer) create an\ninvoice.\n\nAnd this path operation will:\n\n* Send the invoice to the client.\n* Collect the money from the client.\n* Send a notification back to the API user (the external developer), as a callback.\n * At this point is that the API will somehow send a POST request to the\n external API with the notification of the invoice event\n (e.g. "payment successful").', + "operationId": "create_invoice_invoices__post", + "parameters": [ + { + "required": False, + "schema": { + "title": "Callback Url", + "maxLength": 2083, + "minLength": 1, + "type": "string", + "format": "uri", + }, + "name": "callback_url", + "in": "query", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Invoice"} + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "callbacks": { + "invoice_notification": { + "{$callback_url}/invoices/{$request.body.id}": { + "post": { + "summary": "Invoice Notification", + "operationId": "invoice_notification__callback_url__invoices___request_body_id__post", + "requestBody": { + "required": True, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InvoiceEvent" + } + } + }, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InvoiceEventReceived" + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + } + }, + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "Invoice": { + "title": "Invoice", + "required": ["id", "customer", "total"], + "type": "object", + "properties": { + "id": {"title": "Id", "type": "string"}, + "title": {"title": "Title", "type": "string"}, + "customer": {"title": "Customer", "type": "string"}, + "total": {"title": "Total", "type": "number"}, + }, + }, + "InvoiceEvent": { + "title": "InvoiceEvent", + "required": ["description", "paid"], + "type": "object", + "properties": { + "description": {"title": "Description", "type": "string"}, + "paid": {"title": "Paid", "type": "boolean"}, + }, + }, + "InvoiceEventReceived": { + "title": "InvoiceEventReceived", + "required": ["ok"], + "type": "object", + "properties": {"ok": {"title": "Ok", "type": "boolean"}}, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": {"type": "string"}, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, +} + + +def test_openapi(): + with client: + response = client.get("/openapi.json") + + assert response.json() == openapi_schema + + +def test_get(): + response = client.post( + "/invoices/", json={"id": "fooinvoice", "customer": "John", "total": 5.3} + ) + assert response.status_code == 200 + assert response.json() == {"msg": "Invoice received"} + + +def test_dummy_callback(): + # Just for coverage + invoice_notification({}) -- 2.47.3