Closed jayvdb closed 4 years ago
i suppose the view could be a bit more forgiving regarding accepts
. it should work though if you do not provide any accept or the vendor ones. i'll have a look.
on a different note, the stacktrace looks more like a non-serializable object snuk into the schema and the yaml encoder choked on it: raise RepresenterError("cannot represent an object", data)
improved accept handling: 266904c
i left out the error handling for now. i still believe your error is unrelated to the accept header. happened to me before, where there was a datetime object or something that could not be serialized. error looked similar.
Yes of course the stacktrace is an unserializable object. But it isnt data from the schema - it is an error because there is no handler for any of the Accept
requested. That is explained fairly clearly here and in my PR https://github.com/tfranzel/drf-spectacular/pull/42 .
data
is {'detail', ErrorDetail(string='Could not satisfy the request Accept header.', code='not_acceptable')}
I dont understand why this error is being given to the "first" renderer given that DRF already knows the renderer doesnt respond with an acceptable media type. It is possible that this type of data
shouldnt be given to any renderer - maybe it can be blocked sooner.
Maybe the problem is that there is no registered error handler in DRF for yaml.
I can dig into it a bit more, and happy to build test cases, but if you know a better different solution then go for it. I dont want to be wasting my time working on something that you want to fix yourself.
still a bit puzzled how that can happen. i'll try to write a minimal test to get to the bottom of this.
so i had a look and it is an unfortunate situation. ideally the error would be in json and the schema in yaml each with correct media types.
which leaves us out of options to do it proper. all we can do is handle the error in yaml which i did with 5f4fa7d. this is acceptable i believe because this should be a very rare thing and the response is informative in any case.
in theory one could influence the response content type, but then it would not have the correct content type which is even worse.
I dont get this. Responding with content with the wrong content type is extremely bad. If the accept header was "openapi yaml", responding any other type of yaml is wrong. That is why there is a dedicated status code for this.
Another approach is to also respond with a Location:
which could give more information.
btw, https://tools.ietf.org/html/rfc7807 may be of interest for this and other error problems. (and pypi drf-problems is also of interest but I havent tried it yet) I'm not sure of a yaml equivalent, but a vendor-ish yaml content type could be created for it.
I dont get this. Responding with content with the wrong content type is extremely bad.
that is why i said it is even worse.
is there a problem here? code supports vendor types, application/json
and application/yaml
response = APIClient().get('/api/v1/schema/', HTTP_ACCEPT='application/unknown, application/json')
responds with json as expected. "openapi yaml" is not an official MIME type. afaik DRF would normally bail there anyway.
Accept: application/vnd.oai.openapi
should respond with only valid "openapi yaml". Official or not.
Accept: application/vnd.oai.openapi
should respond with only valid "openapi json" - im not sure the error body in the response complies with this.
i see what you mean and i agree. i see no (good) way to influence the the accept error handling. all this handling happens in the framework. the renderer is basically just a glorified json.dumps(data)
.
i also tried hooking into content negotiations with no luck. available_renderers
is ignored and again default is chosen.
class ContentNegotiation(DefaultContentNegotiation):
""" fall back to JSON if negotiations fail """
def select_renderer(self, request, renderers, format_suffix=None):
try:
super().select_renderer(request, renderers, format_suffix)
except NotAcceptable as e:
raise NotAcceptable(available_renderers=[JSONRenderer])
do you have a better solution except making application/yaml
the first renderer? strictly speaking that would have its own problems as it does not officially exist. some say text/yaml
, some say application/vnd.yaml
and so forth.
feel free to provide a non-hacky, non-intrusive solution. sry, but i will not invest more time in this non-critical issue.
I am trying to get https://github.com/dhcode/openapi-ui working, but it uses
Accept: application/json, application/yaml
, which causes the following backtrace as a result, and it also displays only "untagged" but will be a separate issue.