Drive is including `Accept: text/vnd.turbo-stream.html` on visits that are not inside of a Frame
See original GitHub issueWe are working on transitioning a JS-heavy filtered list to Turbo Frames + Streams, and something we’ve run into seems like it might be a bug in Turbo.
We have a DealsController#index
action that is one of the primary parts of our application, with a link in our main navigation to it like this:
<a href="/deals">Deals</a>
We’ve got Turbo Drive set up for the application, so with no introduction of Frames/Streams, this works perfectly, it updates the <body>
through Drive as expected. Then we started introducing <turbo-frame>
s to support things like infinite scrolling of “deals”, with our index.html.erb
looking something like this:
<%= turbo_frame_tag 'deals', target: '_top' do %>
<%= render @deals %>
<% end %>
<%= turbo_frame_tag 'deals-next-page', src: url_for(page: @page + 1), loading: 'lazy' %>
And an index.turbo_stream.erb
that looks something like this:
<%= turbo_stream.append 'deals' do %>
<%= render partial: @deals, formats: %i[html] %>
<% end %>
<%= turbo_stream.replace 'deals-next-page' do %>
<%= turbo_frame_tag 'deals-next-page', src: url_for(page: @page + 1), loading: 'lazy' %>
<% end %>
However, when we introduce index.turbo_stream.erb
, our navigation link (which is outside of any <turbo-frame>
and should behave just as a simple Drive request) no longer works as expected. Instead of getting the full HTML response from the server and replacing the <body>
, it receives index.turbo_stream.erb
, which makes for all sorts of weird issues when clicking that navigation link from other pages (i.e. from our home page, where there is no <turbo-frame id: 'deals'>
element on the page).
After looking into this a bit more, I’m pretty sure it’s because Turbo Drive is including the Accept: text/vnd.turbo-stream.html
header with all of its requests, which is causing my controller to respond with that format if it’s available.
When clicking a link (or submitting a form) inside of a <turbo-frame>
(without a target='_top'
), that makes perfect sense to me, but I’m surprised it does this when clicking a link anywhere else on the page. In that case, I’d expect Turbo Drive to do its thing, and simply fetch the standard HTML response from the server, without the text/vnd.turbo-stream.html
content type included in the Accept
header.
Am I misunderstanding something basic about Turbo, or is this something that should be fixed?
Issue Analytics
- State:
- Created 3 years ago
- Comments:7 (5 by maintainers)
Top GitHub Comments
@agrobbin after the change introduced in #52 , does your infinite scroll approach not break?
The initial page load would render
index.html.erb
with something like:just fine.
But the Fetch initiated by
<%= turbo_frame_tag 'deals-next-page', src: url_for(page: @page + 1), loading: 'lazy' %>
no longer has theAccept: text/vnd.turbo-stream.html
header, and so loadsindex.html.erb
instead of the desiredindex.turbo_frame.erb
. Dose it not?@agrobbin I ended up with a similar refactoring.
The paged index route implemented with Turbo Streams and overloaded views is elegant; 🙏 #146