-
Docs https://falcon.readthedocs.io/en/stable/api/media.html#content-type-negotiation state:
I found a case where falcon does link Accept header to response Content-Type.
The requirement for this to happen is a configured media handler for the requested content type. If falcon can't find a handler for it or if the handler doesn't support requested method, the content type of the response is set to the requested type. By default the response is empty, so it shouldn't matter that much, but at least this caught me by a surprise. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 1 reply
-
Hi @suola! Falcon has actually been doing some kind of limited content type negotiation in the default error serializer since almost forever, but that was limited to JSON/XML/no content. In 3.0, we added support for custom JSON media handlers in the default error serializer, and since 4.0 we are respecting all media handlers there. In 4.1, we are planning to add full content negotiation for media as well, as an optional feature. |
Beta Was this translation helpful? Give feedback.
-
@suola FWIW, I have added your note to #2029, so that we don't forget to improve the documentation, and explain that the default error serializer does actually perform [almost] full media type negotiation. |
Beta Was this translation helpful? Give feedback.
-
Just adding a more detailed explanation to other readers of this discussion. Let's assume our application registers a media handler for CSV ( import csv
import io
import falcon
import falcon.media
class CSVWriter(falcon.media.BaseHandler):
def serialize(self, media, content_type):
with io.StringIO() as out:
writer = csv.writer(out)
if isinstance(media, dict):
writer.writerow(list(media.keys()))
writer.writerow(list(media.values()))
else:
for row in media:
writer.writerow(media)
return out.getvalue().encode()
app = falcon.App()
app.resp_options.media_handlers['text/csv'] = CSVWriter() By default, when sending a generic GET /foo/bar HTTP/1.1
Accept: */*
Host: localhost:8000
HTTP/1.1 404 Not Found
Content-Length: 26
Content-Type: application/json
Vary: Accept
{
"title": "404 Not Found"
} However, if the client prefers GET /foo/bar HTTP/1.1
Accept: text/csv
Host: localhost:8000
HTTP/1.1 404 Not Found
Content-Length: 22
Content-Type: text/csv
Vary: Accept
title
404 Not Found Finally, if no media type can be negotiated that is acceptable to both the client and server, Falcon renders an empty response (but still conveying the correct HTTP error code): GET /foo/bar HTTP/1.1
Accept: falcon/peregrine
Host: localhost:8000
HTTP/1.1 404 Not Found
Content-Length: 0
Content-Type: application/json
Vary: Accept Note that here it would probably be more appropriate to omit the |
Beta Was this translation helpful? Give feedback.
Hi @suola!
Yes, it's a good point, probably we haven't communicated the change well enough.
Falcon has actually been doing some kind of limited content type negotiation in the default error serializer since almost forever, but that was limited to JSON/XML/no content. In 3.0, we added support for custom JSON media handlers in the default error serializer, and since 4.0 we are respecting all media handlers there.
In 4.1, we are planning to add full content negotiation for media as well, as an optional feature.
Just to reiterate, currently this behaviour that you have described should only happen in the default error serializer. If this is not desirable, you can set a custom one.