-
Notifications
You must be signed in to change notification settings - Fork 18
Description
Problem
On PUT, `squad_number` is included in the request body but silently discarded
— the service always overwrites it with the path parameter value
(`player.squad_number = squad_number` in `services/player_service.py`).
Clients receive no feedback when the body value conflicts with the URL, which
is misleading: a request that appears well-formed is quietly modified
server-side with no indication that the body value was ignored.
Proposed Solution (minimal fix)
Add a mismatch guard at the top of `put_async` in `routes/player_route.py`,
before the existence lookup:
```python
if player_model.squad_number != squad_number:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST)
```
The path parameter is the authoritative source of identity on PUT. If the body
carries a different value the request is ambiguous — rejecting it with 400 is
the correct and explicit behaviour.
Alternatives Considered
Option A — Split into PlayerCreateModel / PlayerUpdateModel
Splitting the request model adds a third Pydantic model to the codebase.
The model itself does not need to know about the difference between POST and
PUT — that distinction belongs at the route layer, where HTTP concerns are
handled. A route-level check is simpler and keeps the model layer focused on
data shape, not operation semantics.
Option B — PlayerUpdateModel with Optional squad_number
Making `squad_number` optional on an update model is cleaner from a pure REST
perspective (the URL already conveys identity), but it silently accepts a
mismatched value from the client rather than rejecting it — which is the
original problem. This option trades one form of silent behaviour for another.
Option C — Pydantic model_validator with context
Pydantic v2 supports `model_validate(data, context=...)` for per-operation
validation rules. However, FastAPI validates `Body(...)` automatically and
does not expose a way to inject context into that pipeline without bypassing
framework conventions. The added complexity yields no benefit over a simple
route-level check.
Acceptance Criteria
- PUT returns 400 if `squad_number` in the body does not match the path parameter
- `PlayerRequestModel` remains unchanged (single model for POST and PUT)
- New test `test_request_put_player_squadnumber_mismatch_response_status_bad_request` covers the mismatch case
- All pre-commit checks pass (flake8, black, pytest, coverage ≥ 80%)