]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
:sparkles: Multi-value query parameters and duplicate headers (#95)
authorSebastián Ramírez <tiangolo@gmail.com>
Fri, 22 Mar 2019 17:47:54 +0000 (21:47 +0400)
committerGitHub <noreply@github.com>
Fri, 22 Mar 2019 17:47:54 +0000 (21:47 +0400)
* :memo: Document multi-value query parameters

* :sparkles: Document and test multiple query values

* :sparkles: Document receiving duplicate headers

docs/img/tutorial/query-params-str-validations/image02.png [new file with mode: 0644]
docs/src/header_params/tutorial003.py [new file with mode: 0644]
docs/src/query_params_str_validations/tutorial011.py [new file with mode: 0644]
docs/tutorial/header-params.md
docs/tutorial/query-params-str-validations.md
tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py [new file with mode: 0644]

diff --git a/docs/img/tutorial/query-params-str-validations/image02.png b/docs/img/tutorial/query-params-str-validations/image02.png
new file mode 100644 (file)
index 0000000..3851b88
Binary files /dev/null and b/docs/img/tutorial/query-params-str-validations/image02.png differ
diff --git a/docs/src/header_params/tutorial003.py b/docs/src/header_params/tutorial003.py
new file mode 100644 (file)
index 0000000..85d0fb3
--- /dev/null
@@ -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}
diff --git a/docs/src/query_params_str_validations/tutorial011.py b/docs/src/query_params_str_validations/tutorial011.py
new file mode 100644 (file)
index 0000000..f1c0e5b
--- /dev/null
@@ -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
index 82684669f468dc98c274f387c2ca7ec50d2974aa..f2da422254f308cccf51419e2df4e817851a318e 100644 (file)
@@ -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`.
index 9189a6a50a161695da9bfa54f8c3349b019a76aa..a82018437b446e74e493f6d6de15a01628829b4f 100644 (file)
@@ -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.
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py
new file mode 100644 (file)
index 0000000..ff38574
--- /dev/null
@@ -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"]}