Skip to content

Commit 2aac9c5

Browse files
committed
Fixes netbox-community#4986: Add error responses to swagger spec
1 parent 6638fd8 commit 2aac9c5

File tree

2 files changed

+80
-1
lines changed

2 files changed

+80
-1
lines changed

netbox/utilities/custom_inspectors.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from drf_yasg import openapi
22
from drf_yasg.inspectors import FieldInspector, NotHandled, PaginatorInspector, SwaggerAutoSchema
33
from drf_yasg.utils import get_serializer_ref_name
4+
from utilities.errorresponseautoschema import ErrorResponseAutoSchema
45
from rest_framework.fields import ChoiceField
56
from rest_framework.relations import ManyRelatedField
67

@@ -9,7 +10,7 @@
910
from netbox.api.serializers import WritableNestedSerializer
1011

1112

12-
class NetBoxSwaggerAutoSchema(SwaggerAutoSchema):
13+
class NetBoxSwaggerAutoSchema(ErrorResponseAutoSchema):
1314
writable_serializers = {}
1415

1516
def get_operation_id(self, operation_keys=None):
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
from drf_yasg import openapi
2+
from drf_yasg.inspectors.view import SwaggerAutoSchema
3+
from drf_yasg.utils import force_real_str, is_list_view
4+
from rest_framework import exceptions
5+
from rest_framework.settings import api_settings
6+
from rest_framework import status
7+
8+
9+
# Copied from https://github.com/axnsan12/drf-yasg/issues/224#issuecomment-449646157 by axnsan12
10+
11+
class ErrorResponseAutoSchema(SwaggerAutoSchema):
12+
def get_generic_error_schema(self):
13+
return openapi.Schema(
14+
'Generic API Error',
15+
type=openapi.TYPE_OBJECT,
16+
properties={
17+
'detail': openapi.Schema(type=openapi.TYPE_STRING, description='Error details'),
18+
},
19+
required=['detail']
20+
)
21+
22+
def get_validation_error_schema(self):
23+
return openapi.Schema(
24+
'Validation Error',
25+
type=openapi.TYPE_OBJECT,
26+
# properties={
27+
# 'errors': openapi.Schema(
28+
# type=openapi.TYPE_OBJECT,
29+
# description='error messages for each field that triggered a validation error',
30+
# additional_properties=openapi.Schema(
31+
# description='A list of error messages for the field',
32+
# type=openapi.TYPE_ARRAY, items=openapi.Schema(
33+
# type=openapi.TYPE_STRING)
34+
# )),
35+
# api_settings.NON_FIELD_ERRORS_KEY: openapi.Schema(
36+
# description='List of validation errors not related to any field',
37+
# type=openapi.TYPE_ARRAY, items=openapi.Schema(
38+
# type=openapi.TYPE_STRING)
39+
# ),
40+
# }
41+
)
42+
43+
def get_response_serializers(self):
44+
responses = super().get_response_serializers()
45+
definitions = self.components.with_scope(
46+
openapi.SCHEMA_DEFINITIONS) # type: openapi.ReferenceResolver
47+
48+
definitions.setdefault('GenericError', self.get_generic_error_schema)
49+
definitions.setdefault(
50+
'ValidationError', self.get_validation_error_schema)
51+
definitions.setdefault('APIException', self.get_generic_error_schema)
52+
53+
if self.get_request_serializer() or self.get_query_serializer():
54+
responses.setdefault(exceptions.ValidationError.status_code, openapi.Response(
55+
description=force_real_str(
56+
exceptions.ValidationError.default_detail),
57+
schema=openapi.SchemaRef(definitions, 'ValidationError')
58+
))
59+
60+
security = self.get_security()
61+
if security is None or len(security) > 0:
62+
# Note: 401 error codes are coerced into 403 see rest_framework/views.py:433:handle_exception
63+
# This is b/c the API uses token auth which doesn't have WWW-Authenticate header
64+
responses.setdefault(status.HTTP_403_FORBIDDEN, openapi.Response(
65+
description="Authentication credentials were invalid, absent or insufficient.",
66+
schema=openapi.SchemaRef(definitions, 'GenericError')
67+
))
68+
if not is_list_view(self.path, self.method, self.view):
69+
responses.setdefault(exceptions.PermissionDenied.status_code, openapi.Response(
70+
description="Permission denied.",
71+
schema=openapi.SchemaRef(definitions, 'APIException')
72+
))
73+
responses.setdefault(exceptions.NotFound.status_code, openapi.Response(
74+
description="Object does not exist or caller has insufficient permissions to access it.",
75+
schema=openapi.SchemaRef(definitions, 'APIException')
76+
))
77+
78+
return responses

0 commit comments

Comments
 (0)