Skip to content

Commit 70a51b3

Browse files
rkbeatsstiangolo
andauthored
✨ Auto-generate OpenAPI servers from root_path (#1596)
* root_path included in servers object instead of path prefix * ♻️ Refactor implementation of auto-including root_path in OpenAPI servers * 📝 Update docs and examples for Behind a Proxy, including servers * 📝 Update Extending OpenAPI as openapi_prefix is no longer needed * ✅ Add extra tests for root_path in servers and root_path_in_servers=False * 🍱 Update security docs images with relative token URL * 📝 Update security docs with relative token URL * 📝 Update example sources with relative token URLs * ✅ Update tests with relative tokens Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
1 parent 340a582 commit 70a51b3

35 files changed

+239
-55
lines changed

docs/en/docs/advanced/behind-a-proxy.md

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,19 @@ proxy --> server
4242
!!! tip
4343
The IP `0.0.0.0` is commonly used to mean that the program listens on all the IPs available in that machine/server.
4444

45-
The docs UI would also need that the JSON payload with the OpenAPI schema has the path defined as `/api/v1/app` (behind the proxy) instead of `/app`. For example, something like:
45+
The docs UI would also need the OpenAPI schema to declare that this API `server` is located at `/api/v1` (behind the proxy). For example:
4646

47-
```JSON hl_lines="5"
47+
```JSON hl_lines="4 5 6 7 8"
4848
{
4949
"openapi": "3.0.2",
5050
// More stuff here
51+
"servers": [
52+
{
53+
"url": "/api/v1"
54+
}
55+
],
5156
"paths": {
52-
"/api/v1/app": {
5357
// More stuff here
54-
}
5558
}
5659
}
5760
```
@@ -264,15 +267,77 @@ You can check it at <a href="http://127.0.0.1:8000/docs" class="external-link" t
264267

265268
<img src="/img/tutorial/behind-a-proxy/image01.png">
266269

267-
But if we access the docs UI at the "official" URL using the proxy, at `/api/v1/docs`, it works correctly! 🎉
270+
But if we access the docs UI at the "official" URL using the proxy with port `9999`, at `/api/v1/docs`, it works correctly! 🎉
271+
272+
You can check it at <a href="http://127.0.0.1:9999/api/v1/docs" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/docs</a>:
273+
274+
<img src="/img/tutorial/behind-a-proxy/image02.png">
268275

269276
Right as we wanted it. ✔️
270277

271-
This is because FastAPI uses this `root_path` internally to tell the docs UI to use the URL for OpenAPI with the path prefix provided by `root_path`.
278+
This is because FastAPI uses this `root_path` to create the default `server` in OpenAPI with the URL provided by `root_path`.
272279

273-
You can check it at <a href="http://127.0.0.1:9999/api/v1/docs" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/docs</a>:
280+
## Additional servers
274281

275-
<img src="/img/tutorial/behind-a-proxy/image02.png">
282+
!!! warning
283+
This is a more advanced use case. Feel free to skip it.
284+
285+
By default, **FastAPI** will create a `server` in the OpenAPI schema with the URL for the `root_path`.
286+
287+
But you can also provide other alternative `servers`, for example if you want *the same* docs UI to interact with a staging and production environments.
288+
289+
If you pass a custom list of `servers` and there's a `root_path` (because your API lives behind a proxy), **FastAPI** will insert a "server" with this `root_path` at the beginning of the list.
290+
291+
For example:
292+
293+
```Python hl_lines="4 5 6 7"
294+
{!../../../docs_src/behind_a_proxy/tutorial003.py!}
295+
```
296+
297+
Will generate an OpenAPI schema like:
298+
299+
```JSON hl_lines="5 6 7"
300+
{
301+
"openapi": "3.0.2",
302+
// More stuff here
303+
"servers": [
304+
{
305+
"url": "/api/v1"
306+
},
307+
{
308+
"url": "https://stag.example.com",
309+
"description": "Staging environment"
310+
},
311+
{
312+
"url": "https://prod.example.com",
313+
"description": "Production environment"
314+
}
315+
],
316+
"paths": {
317+
// More stuff here
318+
}
319+
}
320+
```
321+
322+
!!! tip
323+
Notice the auto-generated server with a `url` value of `/api/v1`, taken from the `root_path`.
324+
325+
In the docs UI at <a href="http://127.0.0.1:9999/api/v1/docs" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/docs</a> it would look like:
326+
327+
<img src="/img/tutorial/behind-a-proxy/image03.png">
328+
329+
!!! tip
330+
The docs UI will interact with the server that you select.
331+
332+
### Disable automatic server from `root_path`
333+
334+
If you don't want **FastAPI** to include an automatic server using the `root_path`, you can use the parameter `root_path_in_servers=False`:
335+
336+
```Python hl_lines="9"
337+
{!../../../docs_src/behind_a_proxy/tutorial004.py!}
338+
```
339+
340+
and then it won't include it in the OpenAPI schema.
276341

277342
## Mounting a sub-application
278343

docs/en/docs/advanced/extending-openapi.md

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ And that function `get_openapi()` receives as parameters:
3232
* `openapi_version`: The version of the OpenAPI specification used. By default, the latest: `3.0.2`.
3333
* `description`: The description of your API.
3434
* `routes`: A list of routes, these are each of the registered *path operations*. They are taken from `app.routes`.
35-
* `openapi_prefix`: The URL prefix to be used in your OpenAPI.
3635

3736
## Overriding the defaults
3837

@@ -52,22 +51,15 @@ First, write all your **FastAPI** application as normally:
5251

5352
Then, use the same utility function to generate the OpenAPI schema, inside a `custom_openapi()` function:
5453

55-
```Python hl_lines="2 15 16 17 18 19 20 21"
54+
```Python hl_lines="2 15 16 17 18 19 20"
5655
{!../../../docs_src/extending_openapi/tutorial001.py!}
5756
```
5857

59-
!!! tip
60-
The `openapi_prefix` will contain any prefix needed for the generated OpenAPI *path operations*.
61-
62-
FastAPI will automatically use the `root_path` to pass it in the `openapi_prefix`.
63-
64-
But the important thing is that your function should receive that parameter `openapi_prefix` and pass it along.
65-
6658
### Modify the OpenAPI schema
6759

6860
Now you can add the ReDoc extension, adding a custom `x-logo` to the `info` "object" in the OpenAPI schema:
6961

70-
```Python hl_lines="22 23 24"
62+
```Python hl_lines="21 22 23"
7163
{!../../../docs_src/extending_openapi/tutorial001.py!}
7264
```
7365

@@ -79,15 +71,15 @@ That way, your application won't have to generate the schema every time a user o
7971

8072
It will be generated only once, and then the same cached schema will be used for the next requests.
8173

82-
```Python hl_lines="13 14 25 26"
74+
```Python hl_lines="13 14 24 25"
8375
{!../../../docs_src/extending_openapi/tutorial001.py!}
8476
```
8577

8678
### Override the method
8779

8880
Now you can replace the `.openapi()` method with your new function.
8981

90-
```Python hl_lines="29"
82+
```Python hl_lines="28"
9183
{!../../../docs_src/extending_openapi/tutorial001.py!}
9284
```
9385

-30.4 KB
Loading
32.1 KB
Loading
72.5 KB
Loading
9.02 KB
Loading
595 Bytes
Loading
1.47 KB
Loading
310 Bytes
Loading
-3.13 KB
Loading

0 commit comments

Comments
 (0)