mirror of https://github.com/tiangolo/fastapi.git
📝 Add docs for HTTP QUERY method
- Add docs source example in `docs_src/http_query/tutorial001.py` - Add documentation page `docs/en/docs/tutorial/http-query.md` - Add test for docs in `tests/test_tutorial/test_http_query/test_tutorial001.py` - Update `mkdocs.yml` navigation
This commit is contained in:
parent
fae884e319
commit
1d327c7f55
|
|
@ -0,0 +1,30 @@
|
|||
# HTTP QUERY
|
||||
|
||||
Typically, when you want to read data you use `GET`. If you need to send complex data (like a large JSON object) to filter that data, you traditionally had to use `POST` because `GET` requests does not support request bodies.
|
||||
|
||||
However, using `POST` for read-only operations isn't semantically correct, as `POST` implies that you are creating or modifying data.
|
||||
|
||||
There is a newer HTTP method called **QUERY**. It is designed exactly for this: performing safe, idempotent read operations that require a request body.
|
||||
|
||||
## Using `QUERY`
|
||||
|
||||
In **FastAPI**, you can use the `QUERY` method using the `@app.query()` decorator.
|
||||
|
||||
It works similarly to `@app.post()`, allowing you to receive Pydantic models in the body, but it signals that the operation is a read-only query.
|
||||
|
||||
|
||||
{* ../../docs_src/http_query/tutorial001.py hl[7] *}
|
||||
|
||||
### Testing it
|
||||
|
||||
You can test it using an HTTP client that supports the `QUERY` method.
|
||||
|
||||
Because it allows a body, you can send complex filters without hitting URL length limits common with `GET` query parameters.
|
||||
|
||||
### Technical Details
|
||||
|
||||
The `QUERY` method is defined in the [IETF HTTP QUERY Method Draft](https://www.ietf.org/archive/id/draft-ietf-httpbis-safe-method-w-body-02.html). It is considered:
|
||||
|
||||
* **Safe**: It does not alter the state of the server (read-only).
|
||||
* **Idempotent**: Making the same request multiple times yields the same result.
|
||||
|
||||
|
|
@ -136,6 +136,7 @@ nav:
|
|||
- tutorial/request-forms-and-files.md
|
||||
- tutorial/handling-errors.md
|
||||
- tutorial/path-operation-configuration.md
|
||||
- tutorial/http-query.md
|
||||
- tutorial/encoder.md
|
||||
- tutorial/body-updates.md
|
||||
- Dependencies:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
class ItemSearch(BaseModel):
|
||||
keyword: str
|
||||
min_price: Optional[float] = None
|
||||
max_price: Optional[float] = None
|
||||
|
||||
|
||||
@app.query("/items/")
|
||||
async def search_items(search_params: ItemSearch):
|
||||
return {"message": "Searching items", "search_params": search_params}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
from fastapi.testclient import TestClient
|
||||
|
||||
from docs_src.http_query.tutorial001 import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
def test_query_items():
|
||||
response = client.request(
|
||||
"QUERY",
|
||||
"/items/",
|
||||
json={"keyword": "book", "max_price": 50},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"message": "Searching items",
|
||||
"search_params": {
|
||||
"keyword": "book",
|
||||
"min_price": None,
|
||||
"max_price": 50.0,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
schema = response.json()
|
||||
assert "query" in schema["paths"]["/items/"]
|
||||
operation = schema["paths"]["/items/"]["query"]
|
||||
assert "requestBody" in operation
|
||||
assert "ItemSearch" in operation["requestBody"]["content"]["application/json"]["schema"]["$ref"]
|
||||
Loading…
Reference in New Issue