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

AJAX calls should use text/html, */* as value for Accept header #1229

Open
odrotbohm opened this issue Jan 30, 2023 · 19 comments
Open

AJAX calls should use text/html, */* as value for Accept header #1229

odrotbohm opened this issue Jan 30, 2023 · 19 comments
Labels
enhancement New feature or request under discussion Issues that are being considered but require further alignment

Comments

@odrotbohm
Copy link

By default, HTMX doesn't seem to add any Accept header to the calls it issues to the server. This causes the servers to receive an Accept: */* and doesn't give them a hint in case which media type to produce in case they can serve multiple ones for the same resource.

As HTMX is so focussed on HTML as response media type, it would be nice if it expressed that in the HTTP headers it sends, advertising, that it is primarily interested in HTML.

@drmaniac
Copy link

drmaniac commented Feb 9, 2023

I also support this, but consequently it should be possible to overwrite the accept header if other types are needed.

@netaisllc
Copy link

AFAIK, this would be the vector to use today: https://htmx.org/events/#htmx:configRequest. but I tend to agree with @odrotbohm

@drmaniac
Copy link

drmaniac commented Feb 24, 2023

@netaisllc didn't know that such a configuration is already there (nice), nevertheless if you have to support multiple different header it would be nice to have a short way within the html tag to be able to configure it direct by the request. Like hx-get="endpoint/to/get" hx-header="Accept: text/html;Custom:value;Something:else". Or a solution only for the Accept header like hx-get="endpoint/to/get hx-accept="application/svg+xml"

@yawaramin
Copy link
Contributor

yawaramin commented May 18, 2023

This would also help with HTTP caching of partials. If htmx would set the request header e.g. Accept: text/html;hx=1, then backend servers could serve full or partial HTML depending on the value:

  • Accept: text/html (browser default for requests): serve full page
  • Accept: text/html;hx=1 (set by htmx): serve partial

And backends could also set the Vary header if they wanted to cache responses: Vary: Accept.

HTTP content negotiation FTW!

@jollytoad
Copy link
Contributor

htmx already passes the HX-Request (with a value of true), this can be used to determine whether to serve a full or partial page... https://htmx.org/reference/#request_headers

@yawaramin
Copy link
Contributor

@jollytoad that doesn't work when you want to cache the response from an endpoint that could return full or partial response depending on the value of the header. Because you would need to set the Vary: HX-Request response header on the full or partial response. But since non-htmx requests don't have the HX-Request header, the Vary header mechanism won't work properly. To use Vary, you need a header which is always sent with the request, whether it's from htmx or not. And that is the Accept header.

I have already implemented this manually and it works perfectly.

@alexpetros alexpetros added the under discussion Issues that are being considered but require further alignment label Aug 20, 2023
@alexpetros
Copy link
Collaborator

alexpetros commented Aug 20, 2023

Relevant resources for anyone reading up on this for the first time (like me)

But since non-htmx requests don't have the HX-Request header, the Vary header mechanism won't work properly. To use Vary, you need a header which is always sent with the request, whether it's from htmx or not. And that is the Accept header.

This seems important to me. The only thing I don't really like is hx=1, which feels like a mini-language. Apparently there's precedent for that syntax. I kind of prefer just adding another format though, which is less opaque.

Why not something like:

Accept: text/htmx,text/html

or even

Accept: text/html-partial,text/html

if you wanted to try and come up with a generic name for elements that come from AJAX swapping, which I think could be a really good idea.

@yawaramin
Copy link
Contributor

I am good with any distinct content type, but if we want it to be RFC-compliant, maybe we can stick to text/html;...something...

@alexpetros
Copy link
Collaborator

alexpetros commented Aug 20, 2023

If I'm reading the RFC right, I think different formats are separated by commas, with the semicolon for option modifiers.

@alexpetros
Copy link
Collaborator

alexpetros commented Aug 21, 2023

Actually, the more I think about this, the more I like the option modifiers, but I think it should be generic, not hx, because it's a good opportunity to promote the generic idea that you might be requesting a full or partial reload. So like text/html;reload=partial or text/html;reload=full. Or maybe document=partial. Something like that.

@alexpetros alexpetros added the enhancement New feature or request label Aug 21, 2023
@yawaramin
Copy link
Contributor

yawaramin commented Aug 22, 2023

Maybe text/html;frag=1

@jollytoad
Copy link
Contributor

Should it also include the target if available too, as this may well affect the response considerably? (ie. currently passed in the HX-Target header value), eg: text/html;target=<id>

@yawaramin
Copy link
Contributor

You can customize the header to return anything (even now). We are just discussing what the default should be, I don't see any good reason to include that level of granularity by default. The detail of whether it's a full page or a partial is an obvious one because of caching.

@JordanShurmer
Copy link

Why would the same url return a different response when requested by HTMX vs not-htmx? And if it did (which it shouldn't?), why would it only have 1 possible response for the htmx response.

If someone wants HTMX to get a partial view of a page, shouldn't they be requesting a different url? The url would include some indication to the server of what part of the resource it's requesting.

For example:

  • /some/path.html for the full resource.
  • /some/path.article.html for just the article body, no header nav, no footer, etc
  • /some/path.edit.html to get the editable view of the page
  • etc.

@alexpetros
Copy link
Collaborator

Why would the same url return a different response when requested by HTMX vs not-htmx? And if it did (which it shouldn't?), why would it only have 1 possible response for the htmx response.

The two reasons I've seen are progressive enhancement and composability. I don't think progressive enhancement is a reasonable goal for a modern website (yet, I think htmx could promote some browser standards that would change that) but in theory if JS is off, you get the whole page, if it's on you get a partial refresh.

As for composability, a lot of htmx frameworks support a pattern where you get the full page on first load, and then get a fragment of that page if the HX-Request header is present. I personally do not use this pattern for the reasons you wrote, but it's a valid one, and I think that a general way of describing "give me just this resource or give me the entire page along with this resource" is a thing that makes a lot of sense to have a standard way of communicating.

@JordanShurmer
Copy link

JordanShurmer commented Aug 28, 2023

then get a fragment of that page if the HX-Request header is present.

Interesting.. that's surprising to me, and almost feels like something that should be discouraged by this library? Maybe I'm over thinking this though.

That would require specific caching rules, or at least Vary: HX-Request in all responses to a resource which has that htmx fragment view available. More importantly, it implies that there's only 1 representation of the resource that HTMX cares about, which seems unlikely to be true.

🤔 what am I missing?

@JordanShurmer
Copy link

since non-htmx requests don't have the HX-Request header, the Vary header mechanism won't work properly.

@yawaramin the Vary header would still work appropriately here. Every response to the resource should contain Vary: HX-Request whether that header was present in the request or not. The server has to know that the requested resource would be affected by the header, and include the Vary header if so.

The absence of the header in the request indicates one variation of the response, and then any actual value of HX-Request indicates another variation. The spec supports this when they say "or lack thereof"

@sergeliatko
Copy link

Hi guys, would it be possible something like? text/html; partial=1; targets=[id1,idk]

@rhdunn
Copy link

rhdunn commented Jul 6, 2024

The use-case I have is where you have a GET endpoint such as GET /foo/[id] that uses an accept header to determine the content to return -- HTML, JSON, XML, etc.

Because HTMX is passing */* as the accept header I don't know what content to return, so respond with a 406 Not Acceptable instead of the HTML content. As such, I need to add a check to see if the request is a HTMX response, making the accept logic more complex.

So in my case it is not about returning a partial vs full HTML page, but returning HTML vs an error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request under discussion Issues that are being considered but require further alignment
Projects
None yet
Development

No branches or pull requests

9 participants