leotaku / tower-livereload

Tower middleware to automatically reload your web browser during development
Apache License 2.0
62 stars 7 forks source link

Script is injected into htmx responses #2

Closed wrapperup closed 1 year ago

wrapperup commented 1 year ago

Since htmx responds with html fragments (with the text/html content type), the reload script is also injected with every htmx response. Is there a sensible way to prevent this? htmx does add an hx-request header on every request it makes.

For reference: https://htmx.org/reference/#headers

leotaku commented 1 year ago

Unfortunately, this is currently not easily possible without some internal changes. However, I think making injection configurable would be a good addition to the library, so I'd be willing to add it.

Just for my own reference, as I'm not that familiar with htmx, when you say "htmx responds with html fragments" do you mean that your backend responds to htmx requests with html fragments? If so, one simple fix might be to put the service that is responsible for returning the html fragments under a different route which you do not wrap in a LiveReloadLayer.

One simple way to do this would be the following (untested):

let app = Router::new()
    .nest("/", your_html_routes)
    .layer(LiveReloadLayer::new())
    .nest("/htmx", your_htmx_routes);

Because middleware is only applied for routes that are added before it, this would ensure that any responses for stuff under the "htmx" path would not have this middleware applied. Of course I understand that this would be somewhat limiting and might not be compatible with your current setup, so I'll still look into making injection configurable based on requests.

wrapperup commented 1 year ago

Just for my own reference, as I'm not that familiar with htmx, when you say "htmx responds with html fragments" do you mean that your backend responds to htmx requests with html fragments? If so, one simple fix might be to put the service that is responsible for returning the html fragments under a different route which you do not wrap in a LiveReloadLayer.

Yep, that's correct. I am actually doing it the way you suggest, but that did require me to split out a few of these into their own routes (since I would check for the hx-request header in some of these routes instead of making new ones). Regardless, it can be worked around, so not the end of the world.

Of course I understand that this would be somewhat limiting and might not be compatible with your current setup, so I'll still look into making injection configurable based on requests.

Awesome! Either way, thanks for the useful library.

Moanrisy commented 11 months ago

I put the liveReload middleware at the end of the routes, it working fine. But after I click my button 7 times to do POST request with htmx, the button stopped working.

Because middleware is only applied for routes that are added before it, this would ensure that any responses for stuff under the "htmx" path would not have this middleware applied.

After I put the liveReload middleware on the first then thr routes, that solve my problem too.

wrapperup commented 11 months ago

After I put the liveReload middleware on the first then thr routes, that solve my problem too.

This crate has a better way to do it now, see https://github.com/leotaku/tower-livereload/pull/3 for a nice htmx example.

You can have it ignore htmx requests, which means you aren't required to order the middleware in any specific way, and you can merge htmx and non-htmx routes together if you wanted.