Skip to content

Commit f33e013

Browse files
committed
fix: Ensure generic swagger problem definitions inherit documentation uri template and strict settings.
1 parent ef6348d commit f33e013

File tree

2 files changed

+65
-10
lines changed

2 files changed

+65
-10
lines changed

src/fastapi_problem/handler.py

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,15 @@ class Example(t.NamedTuple):
3333
title: str
3434
type_: str
3535
status: int
36+
detail: str
3637

3738

3839
def _swagger_problem_response(description: str, examples: list[Example]) -> dict:
3940
examples_ = {
4041
ex.title: {
4142
"value": {
4243
"title": ex.title,
43-
"detail": "Additional error context.",
44+
"detail": ex.detail,
4445
"type": ex.type_,
4546
"status": ex.status,
4647
},
@@ -79,6 +80,7 @@ def _generate_swagger_response(
7980
title=d["title"],
8081
type_=d["type"],
8182
status=d["status"],
83+
detail=d["detail"],
8284
),
8385
)
8486
return _swagger_problem_response(
@@ -87,7 +89,11 @@ def _generate_swagger_response(
8789
)
8890

8991

90-
def generate_swagger_response(*exceptions: type[Problem], documentation_uri_template: str = "", strict: bool = False) -> dict:
92+
def generate_swagger_response(
93+
*exceptions: type[Problem],
94+
documentation_uri_template: str = "",
95+
strict: bool = False,
96+
) -> dict:
9197
warn(
9298
"Direct calls to generate_swagger_response are being deprecated, use `eh.generate_swagger_response(...)` instead.",
9399
FutureWarning,
@@ -109,7 +115,13 @@ def generate_swagger_response(self, *exceptions: type[Problem]) -> dict:
109115
)
110116

111117

112-
def customise_openapi(func: t.Callable[..., dict], *, generic_defaults: bool = True) -> t.Callable[..., dict]:
118+
def customise_openapi(
119+
func: t.Callable[..., dict],
120+
*,
121+
documentation_uri_template: str = "",
122+
strict: bool = False,
123+
generic_defaults: bool = True,
124+
) -> t.Callable[..., dict]:
113125
"""Customize OpenAPI schema."""
114126

115127
def wrapper() -> dict:
@@ -198,23 +210,39 @@ def wrapper() -> dict:
198210
"content"
199211
].pop("application/json")
200212
if generic_defaults:
213+
user_error = Problem(
214+
"User facing error message.",
215+
type_="client-error-type",
216+
status=400,
217+
detail="Additional error context.",
218+
)
219+
d = user_error.marshal(uri=documentation_uri_template, strict=strict)
201220
details["responses"]["4XX"] = _swagger_problem_response(
202221
description="Client Error",
203222
examples=[
204223
Example(
205-
title="User facing error message.",
206-
type_="client-error-type",
207-
status=400,
224+
title=d["title"],
225+
type_=d["type"],
226+
status=d["status"],
227+
detail=d["detail"],
208228
),
209229
],
210230
)
231+
server_error = Problem(
232+
"User facing error message.",
233+
type_="server-error-type",
234+
status=500,
235+
detail="Additional error context.",
236+
)
237+
d = server_error.marshal(uri=documentation_uri_template, strict=strict)
211238
details["responses"]["5XX"] = _swagger_problem_response(
212239
description="Server Error",
213240
examples=[
214241
Example(
215-
title="User facing error message.",
216-
type_="server-error-type",
217-
status=500,
242+
title=d["title"],
243+
type_=d["type"],
244+
status=d["status"],
245+
detail=d["detail"],
218246
),
219247
],
220248
)
@@ -324,7 +352,12 @@ def add_exception_handler( # noqa: PLR0913
324352
app.add_exception_handler(RequestValidationError, eh)
325353

326354
# Override default 422 with Problem schema
327-
app.openapi = customise_openapi(app.openapi, generic_defaults=generic_swagger_defaults)
355+
app.openapi = customise_openapi(
356+
app.openapi,
357+
generic_defaults=generic_swagger_defaults,
358+
documentation_uri_template=eh.documentation_uri_template,
359+
strict=eh.strict,
360+
)
328361

329362
return eh
330363

tests/test_handler.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@ def test_swagger_problem_response():
452452
title="User facing error message.",
453453
type_="client-error-type",
454454
status=400,
455+
detail="Additional error context.",
455456
),
456457
],
457458
) == {
@@ -480,11 +481,13 @@ def test_swagger_problem_response_multiple_examples():
480481
title="User facing error message.",
481482
type_="client-error-type",
482483
status=400,
484+
detail="Additional error context.",
483485
),
484486
handler.Example(
485487
title="Another user facing error message.",
486488
type_="another-client-error-type",
487489
status=400,
490+
detail="Additional error context.",
488491
),
489492
],
490493
) == {
@@ -517,6 +520,25 @@ def test_swagger_problem_response_multiple_examples():
517520
}
518521

519522

523+
def test_generate_swagger_response_status_problem_deprecated():
524+
assert handler.generate_swagger_response(error.BadRequestProblem) == {
525+
"content": {
526+
"application/problem+json": {
527+
"schema": {
528+
"$ref": "#/components/schemas/Problem",
529+
},
530+
"example": {
531+
"title": "Base http exception.",
532+
"detail": "Additional error context.",
533+
"type": "bad-request-problem",
534+
"status": 400,
535+
},
536+
},
537+
},
538+
"description": "Bad Request",
539+
}
540+
541+
520542
def test_generate_swagger_response_status_problem():
521543
eh = handler.new_exception_handler()
522544
assert eh.generate_swagger_response(error.BadRequestProblem) == {

0 commit comments

Comments
 (0)