mirror of https://github.com/tiangolo/fastapi.git
🐛 Fix parsing extra non-body parameter list (#14356)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
This commit is contained in:
parent
2330e2de75
commit
de5bec637c
|
|
@ -791,9 +791,16 @@ def request_params_to_args(
|
||||||
processed_keys.add(alias or field.alias)
|
processed_keys.add(alias or field.alias)
|
||||||
processed_keys.add(field.name)
|
processed_keys.add(field.name)
|
||||||
|
|
||||||
for key, value in received_params.items():
|
for key in received_params.keys():
|
||||||
if key not in processed_keys:
|
if key not in processed_keys:
|
||||||
|
if hasattr(received_params, "getlist"):
|
||||||
|
value = received_params.getlist(key)
|
||||||
|
if isinstance(value, list) and (len(value) == 1):
|
||||||
|
params_to_process[key] = value[0]
|
||||||
|
else:
|
||||||
params_to_process[key] = value
|
params_to_process[key] = value
|
||||||
|
else:
|
||||||
|
params_to_process[key] = received_params.get(key)
|
||||||
|
|
||||||
if single_not_embedded_field:
|
if single_not_embedded_field:
|
||||||
field_info = first_field.field_info
|
field_info = first_field.field_info
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
from fastapi import Cookie, FastAPI, Header, Query
|
||||||
|
from fastapi._compat import PYDANTIC_V2
|
||||||
|
from fastapi.testclient import TestClient
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
class Model(BaseModel):
|
||||||
|
param: str
|
||||||
|
|
||||||
|
if PYDANTIC_V2:
|
||||||
|
model_config = {"extra": "allow"}
|
||||||
|
else:
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
extra = "allow"
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/query")
|
||||||
|
async def query_model_with_extra(data: Model = Query()):
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/header")
|
||||||
|
async def header_model_with_extra(data: Model = Header()):
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/cookie")
|
||||||
|
async def cookies_model_with_extra(data: Model = Cookie()):
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def test_query_pass_extra_list():
|
||||||
|
client = TestClient(app)
|
||||||
|
resp = client.get(
|
||||||
|
"/query",
|
||||||
|
params={
|
||||||
|
"param": "123",
|
||||||
|
"param2": ["456", "789"], # Pass a list of values as extra parameter
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert resp.status_code == 200
|
||||||
|
assert resp.json() == {
|
||||||
|
"param": "123",
|
||||||
|
"param2": ["456", "789"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_query_pass_extra_single():
|
||||||
|
client = TestClient(app)
|
||||||
|
resp = client.get(
|
||||||
|
"/query",
|
||||||
|
params={
|
||||||
|
"param": "123",
|
||||||
|
"param2": "456",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert resp.status_code == 200
|
||||||
|
assert resp.json() == {
|
||||||
|
"param": "123",
|
||||||
|
"param2": "456",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_header_pass_extra_list():
|
||||||
|
client = TestClient(app)
|
||||||
|
|
||||||
|
resp = client.get(
|
||||||
|
"/header",
|
||||||
|
headers=[
|
||||||
|
("param", "123"),
|
||||||
|
("param2", "456"), # Pass a list of values as extra parameter
|
||||||
|
("param2", "789"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
assert resp.status_code == 200
|
||||||
|
resp_json = resp.json()
|
||||||
|
assert "param2" in resp_json
|
||||||
|
assert resp_json["param2"] == ["456", "789"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_header_pass_extra_single():
|
||||||
|
client = TestClient(app)
|
||||||
|
|
||||||
|
resp = client.get(
|
||||||
|
"/header",
|
||||||
|
headers=[
|
||||||
|
("param", "123"),
|
||||||
|
("param2", "456"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
assert resp.status_code == 200
|
||||||
|
resp_json = resp.json()
|
||||||
|
assert "param2" in resp_json
|
||||||
|
assert resp_json["param2"] == "456"
|
||||||
|
|
||||||
|
|
||||||
|
def test_cookie_pass_extra_list():
|
||||||
|
client = TestClient(app)
|
||||||
|
client.cookies = [
|
||||||
|
("param", "123"),
|
||||||
|
("param2", "456"), # Pass a list of values as extra parameter
|
||||||
|
("param2", "789"),
|
||||||
|
]
|
||||||
|
resp = client.get("/cookie")
|
||||||
|
assert resp.status_code == 200
|
||||||
|
resp_json = resp.json()
|
||||||
|
assert "param2" in resp_json
|
||||||
|
assert resp_json["param2"] == "789" # Cookies only keep the last value
|
||||||
|
|
@ -77,7 +77,7 @@ def test_header_param_model_no_underscore(client: TestClient):
|
||||||
"user-agent": "testclient",
|
"user-agent": "testclient",
|
||||||
"save-data": "true",
|
"save-data": "true",
|
||||||
"if-modified-since": "yesterday",
|
"if-modified-since": "yesterday",
|
||||||
"x-tag": "two",
|
"x-tag": ["one", "two"],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue