htmx icon indicating copy to clipboard operation
htmx copied to clipboard

Response from HX-Location should respect HX-Push-Url header

Open devashishdxt opened this issue 1 year ago • 6 comments

I have a scenario where I set the HX-Location header to redirect the client to other page (assume /x). In some cases, the response (of /x) could contain HX-Push-Url header (assume /y) which is not being respected, i.e., the page url is still same as the url in HX-Location header (/x).

Is there a way to push the url in HX-Push-Url (/y) header of response in browser history after the redirect using HX-Location header?

devashishdxt avatar Jan 09 '25 02:01 devashishdxt

From what I see in the sources:

https://github.com/bigskysoftware/htmx/blob/e0905ff94a3623f6383278bf2ea740c65b616105/src/htmx.js#L4692-L4694 https://github.com/bigskysoftware/htmx/blob/e0905ff94a3623f6383278bf2ea740c65b616105/src/htmx.js#L4703-L4705

I don't see any reason HX-Push-Url would not be applied from the second endpoint's response, however it looks like htmx ignores whether the redirected endpoint submitted any instruction about pushing a URL or not, and uses pushUrlIntoHistory after the request is made to push the redirected URL anyway

So, I would expect your history to actually contain the URL sent back by your second endpoint's HX-Push-Url header as you would expect, but likely one step backwards in the history (which would be an issue of course).

Could you confirm if this is actually what is happening? Do you see the desired URL when going back in the history by 1 step? If so, we can likely add a fix for that

Telroshan avatar Jan 09 '25 08:01 Telroshan

also see #3045 for more detail on the cause

MichaelWest22 avatar Jan 09 '25 09:01 MichaelWest22

The issue is the ajaxHelper function is waits to complete fully as a promise which will push the hx-push-url to history and 'then' it will push the hx-location URL every time. We could add

      ajaxHelper('get', redirectPath, redirectSwapSpec).then(function() {
        if (!redirectSwapSpec?.noPushUrl) pushUrlIntoHistory(redirectPath)
      })

to add a new optional key to hx-location data spec that if set true would block the post request push if required.

Maybe a better way would be this

      const oldPath = currentPathForHistory
      ajaxHelper('get', redirectPath, redirectSwapSpec).then(function() {
        if (oldPath === currentPathForHistory) pushUrlIntoHistory(redirectPath)
      })

MichaelWest22 avatar Jan 09 '25 09:01 MichaelWest22

Could you confirm if this is actually what is happening? Do you see the desired URL when going back in the history by 1 step? If so, we can likely add a fix for that

Yes. I can see the desired URL if I go one step back.

devashishdxt avatar Jan 09 '25 09:01 devashishdxt

could another solution be to add a pushUrl optional boolean to HtmxAjaxHelperContext and HtmxAjaxEtc and HtmxResponseInfoand then allow ajaxHelper to pass this through with the request config and then set this true for all hx-location requests. Then get the ajax request to push history at the end if this is true by using this boolean in the determineHistoryUpdates function. This new option would also resolve #3114 as there would then be a proper ajax api to push url.

MichaelWest22 avatar Jan 09 '25 10:01 MichaelWest22

added a possible PR that has a proper fix for this bug

MichaelWest22 avatar Aug 05 '25 05:08 MichaelWest22