Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Content-type negotiation for images #94

Open
csmith opened this issue Mar 18, 2022 · 7 comments
Open

Content-type negotiation for images #94

csmith opened this issue Mar 18, 2022 · 7 comments
Labels
enhancement New feature or request help wanted Extra attention is needed v2 v2 release

Comments

@csmith
Copy link
Contributor

csmith commented Mar 18, 2022

Is your feature request related to a problem? Please describe.
Sometimes I have multiple formats of the same resource, and want to serve whatever the browser prefers.

The main example I'm thinking of here is image formats - giving browsers that support them webp or avif images, while falling back to jpeg or png for older browsers. (This "pick the right format" logic can be done client-side for some use cases but not all of them)

Describe the solution you'd like
I think as a first pass something like Apache's MultiViews directive would work: if a client requests a resource x, and x does not exist on the file system, but x.* does, then return the match with the most favoured mime-type.

Most-favoured would be defined firstly by the client's Accept header, but if all of them are equal (e.g. Accept: */*) then a built-in priority order for the common mime-types might be needed to break the tie.

To me this would fit in with how e.g. cache-control headers work at the minute - it's good enough for 95% of cases and just does the right thing out of the box.

Describe alternatives you've considered
Every alternative relies on a lot of configuration, and doesn't work out-of-the-box. nginx can do this sort of thing by mapping against the accept header, and then using tryfiles, but it's very clunky. You can get similar results with various rewrite modules, but again they're fairly heavy-handed.

Additional context
This could be expanded in the future to support languages as well (e.g. you have index.html.en, index.html.fr instead of index.html and it negotiates based on the Accept-Language header).

@joseluisq
Copy link
Collaborator

Not bad idea.
In fact I'm thinking about the content type negotiation based on Accept header as an incremental feature. Which could get started with the image types, always looking at the Accept header (order matters) to negotiate.
So I ask, what other use cases do you know apart from image types?

This could be expanded in the future to support languages as well (e.g. you have index.html.en, index.html.fr instead of index.html and it negotiates based on the Accept-Language header).

Yeah, good idea. Content negotiation based on Accept-Language header is also a similar feature.

@joseluisq joseluisq added enhancement New feature or request help wanted Extra attention is needed v2 v2 release labels Mar 19, 2022
@csmith
Copy link
Contributor Author

csmith commented Mar 21, 2022

I'm struggling to think of anything other than images.

There's lots of theoretical things like "a client could request plain text instead of HTML" but in reality that just doesn't happen. The only other time I've seen it used is for API responses, which doesn't really make sense for SWS.

@joseluisq
Copy link
Collaborator

I think is just fine to restrict this feature to images only in the Accept header context.

Because things like this are overwhelming.

image

In the other-hand, for Accept-Language header we could have no such implications like the Accept one.

@joseluisq
Copy link
Collaborator

BTW It would be great if you can adjust the feature title in concordance.

@csmith csmith changed the title Content-type negotiation Content-type negotiation for images Mar 21, 2022
@joseluisq
Copy link
Collaborator

I was thinking around this feature request but I'm wondering how the alternative image should be delivered.
My question is, once the image is found on filesystem how should be it returned? Via a http redirection to the proper image? I didn't found something for example in the Apache's MultiViews directive.

@csmith
Copy link
Contributor Author

csmith commented Dec 16, 2022

My question is, once the image is found on filesystem how should be it returned? Via a http redirection to the proper image?

I think just returning it directly is fine, given the client has said it will accept it. I's fairly common to see a URL that ends in .jpeg or .png that actually serves a .webm for modern browsers (or, say, a .gif URL that serves an mp4 file). For example this Jetbrains logo serves a webp response if that's in the client's accept header, and a png otherwise: https://www.jetbrains.com/icon-512.png

(Sorry for the delay responding, missed the notification!)

@joseluisq
Copy link
Collaborator

No worries.

Ok, then returning the image type directly looks fine if the client accepts it. It got it.

$ curl -I -H "accept: image/avif,image/webp,image/apng" https://www.jetbrains.com/icon-512.png
HTTP/2 200 
content-type: image/webp
content-length: 2070
date: Wed, 21 Dec 2022 08:51:19 GMT
server: nginx
last-modified: Thu, 21 Jul 2022 12:33:16 GMT
etag: "62d9478c-816"
expires: Wed, 21 Dec 2022 08:51:19 GMT
cache-control: max-age=0
x-frame-options: DENY
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
strict-transport-security: max-age=31536000;
pragma: no-cache
accept-ranges: bytes
$ curl -I https://www.jetbrains.com/icon-512.png
HTTP/2 200 
content-type: image/png
content-length: 8864
date: Wed, 21 Dec 2022 08:51:28 GMT
server: nginx
last-modified: Fri, 17 Jun 2022 15:20:46 GMT
etag: "62ac9bce-22a0"
expires: Wed, 21 Dec 2022 08:51:28 GMT
cache-control: max-age=0
x-frame-options: DENY
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
strict-transport-security: max-age=31536000;
pragma: no-cache
accept-ranges: bytes

It looks trivial to implement, probability under a new flag/option. Let's see how it will go.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed v2 v2 release
Projects
None yet
Development

No branches or pull requests

2 participants