Skip to content

http: send HX-Request-Type from HTMX 1.x and 2.x - #87

Merged
rameel merged 1 commit into
mainfrom
request-type-header
Oct 11, 2026
Merged

rameel merged 1 commit into
mainfrom
request-type-header

Conversation

@rameel

@rameel rameel commented Oct 11, 2026

Copy link
Copy Markdown
Owner

HTMX 4.x tells the server whether it expects a fragment or a full page. HTMX 1.x and 2.x do not, and the other headers cannot answer it, so IsHtmxPartialRequest() and [HtmxRequest(RequestType = ...)] worked only with HTMX 4.x.

  • The companion script adds HX-Request-Type for HTMX 1.x and 2.x, computed the way HTMX 4.x does:
    full when the target is the body or a selector applies, partial otherwise. It is set in
    htmx:beforeRequest, the first event that sees the select of htmx.ajax and HX-Location requests.
    Requests with noHeaders in hx-request and requests that already set the header are left as is.
  • RequestType and IsHtmxFullRequest() report a history restoration request without the header as Full.
    HTMX 1.x and 2.x send it without the header; HTMX 4.x sends full.

Verification

Unit tests cover the server side. The script was checked in Chromium against HTMX 1.9.12, 2.0.11 and 4.0.0, both htmx-toolkit.js and htmx-toolkit.min.js, with these cases:

  • hx-target: an inner element and body
  • hx-select: on the element, inherited, unset, and with hx-disinherit
  • boosted links with and without hx-target
  • htmx.ajax with and without select and target
  • HX-Location with and without select
  • noHeaders: on the element, inherited, overridden, and the unbraced form
  • an explicit HX-Request-Type set with hx-headers
  • history restoration after a cache miss

HTMX 1.x and 2.x send the expected value in every case. HTMX 4.x keeps its own header, and no request carries two values.

Known limit: an hx-request value that starts with js: is not evaluated, so it cannot turn the header off.

HTMX 4.x tells the server whether it expects a fragment or a full page.
HTMX 1.x and 2.x do not, and the other headers cannot answer it:
HX-Target holds only an ID, and hx-select never reaches the server.
An endpoint that returned a partial for every HTMX request therefore
broke boosted navigation and hx-select, which expect the full page.

- Add HX-Request-Type in the companion script for HTMX 1.x and 2.x,
  computed the way HTMX 4.x does: "full" when the target is the body
  or a selector applies, "partial" otherwise. The header is set in
  htmx:beforeRequest, the first event that sees the select of
  htmx.ajax and HX-Location requests. Requests with noHeaders in
  hx-request and requests that already set the header are left as is.
- Report history restoration requests without the header as Full in
  RequestType and IsHtmxFullRequest. HTMX 1.x and 2.x send them
  without it; HTMX 4.x sends "full".
- Use IsHtmxPartialRequest in the README and articles to serve a page
  and its fragment from one URL.
@rameel
rameel merged commit 7420bd4 into main Oct 11, 2026
1 check passed
@rameel
rameel deleted the request-type-header branch October 11, 2026 18:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant