ActionController::Live
# Action Controller Live
Mix this module into your controller, and all actions in that controller will be able to stream data to the client as it’s written.
class MyController < ActionController::Base include ActionController::Live def stream response.headers['Content-Type'] = 'text/event-stream' 100.times { response.stream.write "hello world\n" sleep 1 } ensure response.stream.close end end
There are a few caveats with this module. You *cannot* write headers after the response has been committed (Response#committed? will return truthy). Calling `write` or `close` on the response stream will cause the response object to be committed. Make sure all headers are set before calling write or close on your stream.
You *must* call close on your stream when you’re finished, otherwise the socket may be left open forever.
The final caveat is that your actions are executed in a separate thread than the main thread. Make sure your actions are thread safe, and this shouldn’t be a problem (don’t share state across threads, etc).
Note that Rails includes `Rack::ETag` by default, which will buffer your response. As a result, streaming responses may not work properly with Rack 2.2.x, and you may need to implement workarounds in your application. You can either set the `ETag` or `Last-Modified` response headers or remove `Rack::ETag` from the middleware stack to address this issue.
Here’s an example of how you can set the `Last-Modified` header if your Rack version is 2.2.x:
def stream response.headers["Content-Type"] = "text/event-stream" response.headers["Last-Modified"] = Time.now.httpdate # Add this line if your Rack version is 2.2.x ... end
Files
- actionpack/lib/action_controller/metal/live.rb
- actionpack/lib/action_controller/test_case.rb