mirror of https://github.com/tiangolo/fastapi.git
✨ Multi-value query parameters and duplicate headers (#95)
* 📝 Document multi-value query parameters * ✨ Document and test multiple query values * ✨ Document receiving duplicate headers
This commit is contained in:
parent
4f852878d6
commit
c64f8346ae
Binary file not shown.
|
After Width: | Height: | Size: 71 KiB |
|
|
@ -0,0 +1,10 @@
|
|||
from typing import List
|
||||
|
||||
from fastapi import FastAPI, Header
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/items/")
|
||||
async def read_items(x_token: List[str] = Header(None)):
|
||||
return {"X-Token values": x_token}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
from typing import List
|
||||
|
||||
from fastapi import FastAPI, Query
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/items/")
|
||||
async def read_items(q: List[str] = Query(None)):
|
||||
query_items = {"q": q}
|
||||
return query_items
|
||||
|
|
@ -47,6 +47,39 @@ If for some reason you need to disable automatic conversion of underscores to hy
|
|||
!!! warning
|
||||
Before setting `convert_underscores` to `False`, bear in mind that some HTTP proxies and servers disallow the usage of headers with underscores.
|
||||
|
||||
|
||||
## Duplicate headers
|
||||
|
||||
It is possible to receive duplicate headers. That means, the same header with multiple values.
|
||||
|
||||
You can define those cases using a list in the type declaration.
|
||||
|
||||
You will receive all the values from the duplicate header as a Python `list`.
|
||||
|
||||
For example, to declare a header of `X-Token` that can appear more than once, you can write:
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!./src/header_params/tutorial003.py!}
|
||||
```
|
||||
|
||||
If you communicate with that *path operation* sending two HTTP headers like:
|
||||
|
||||
```
|
||||
X-Token: foo
|
||||
X-Token: bar
|
||||
```
|
||||
|
||||
The response would be like:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"X-Token values": [
|
||||
"bar",
|
||||
"foo"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Recap
|
||||
|
||||
Declare headers with `Header`, using the same common pattern as `Query`, `Path` and `Cookie`.
|
||||
|
|
|
|||
|
|
@ -124,6 +124,43 @@ So, when you need to declare a value as required while using `Query`, you can us
|
|||
|
||||
This will let **FastAPI** know that this parameter is required.
|
||||
|
||||
## Query parameter list / multiple values
|
||||
|
||||
When you define a query parameter explicitly with `Query` you can also declare it to receive a list of values, or said in other way, to receive multiple values.
|
||||
|
||||
For example, to declare a query parameter `q` that can appear multiple times in the URL, you can write:
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!./src/query_params_str_validations/tutorial011.py!}
|
||||
```
|
||||
|
||||
Then, with a URL like:
|
||||
|
||||
```
|
||||
http://localhost:8000/items/?q=foo&q=bar
|
||||
```
|
||||
|
||||
you would receive the multiple `q` *query parameters'* values (`foo` and `bar`) in a Python `list` inside your *path operation function*, in the *function parameter* `q`.
|
||||
|
||||
So, the response to that URL would be:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"q": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
To declare a query parameter with a type of `list`, like in the example above, you need to explicitly use `Query`, otherwise it would be interpreted as a request body.
|
||||
|
||||
|
||||
The interactive API docs will update accordingly, to allow multiple values:
|
||||
|
||||
<img src="/img/tutorial/query-params-str-validations/image02.png">
|
||||
|
||||
## Declare more metadata
|
||||
|
||||
You can add more information about the parameter.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
from starlette.testclient import TestClient
|
||||
|
||||
from query_params_str_validations.tutorial011 import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
openapi_schema = {
|
||||
"openapi": "3.0.2",
|
||||
"info": {"title": "Fast API", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Read Items Get",
|
||||
"operationId": "read_items_items__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"title": "Q",
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"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"},
|
||||
},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == openapi_schema
|
||||
|
||||
|
||||
def test_multi_query_values():
|
||||
url = "/items/?q=foo&q=bar"
|
||||
response = client.get(url)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"q": ["foo", "bar"]}
|
||||
Loading…
Reference in New Issue