📝 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:
Rauan 2025-11-26 10:15:28 +05:00
parent fae884e319
commit 1d327c7f55
4 changed files with 80 additions and 0 deletions

View File

@ -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.

View File

@ -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:

View File

@ -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}

View File

@ -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"]