TIL: JavaScript Turbo Stream Requests

I am working on search for Album Whale and I was very confused when my JavaScript fetch requests were not resulting in turbo_stream rendering getting displayed on my page. I checked my logs to see if the render was happening. I looked for missing <%= tags. Debugged and logger.info'd all over.

Then I finally noticed the following in my Rails logs:

Processing by AlbumsController#search as */*

Oh, I expected that to say something about TURBO_STREAM, like:

Processing by AlbumsController#search as TURBO_STREAM

This sent me on a dive into headers (I didn't have an Accept header on my fetch request), response handling, and the fetch API.

Here's what I came up with for our first rough cut of a working, live search field (this is Stimulus code):

async searchForAlbum() {
let queryString = this.queryStringTarget.value
if (queryString.length > 2) {
fetch(this.urlValue, {
method: 'POST',
body: JSON.stringify({
"queryString": queryString
}),
credentials: 'same-origin',
headers: this.getHeaders()
})
.then((response) => {
if (!response.ok) {
alert("something went wrong!");
window.location.reload(true);
}
return response.text()
})
# Here we need to pass the response to Turbo for processing
.then((html) => Turbo.renderStreamMessage(html))
}
}

getHeaders() {
let headers = new Headers()
headers.append('Content-Type', 'application/json')
# Here we want a Turbo response
headers.append('Accept', 'text/vnd.turbo-stream.html')
headers.append('X-CSRF-Token', document.querySelector('meta[name="csrf-token"]').content)
return headers
}

I suspect there's a more succinct way to do this, but I'm setting it down for now.