Just to add some context about this in case it helps to get some feedback:
NewRelic has an interesting feature for Ruby applications called
auto-instrumentation, which will inject the required code in the HTML
header in a Rack middleware.
For this to work, it has to read the response body and then modify it
accordingly. But it's not safe (or desirable) to do so for streamed
responses. Not only it would remove the benefits from streaming but it
may also cause bugs in applications that would otherwise work without
that middleware (if auto-instrumentation is enabled, which is usually
the case). For instance, Rails will freeze the headers hash for
streaming responses after the first commit/flush, since the headers have
already been sent. Another middleware could be tempted to add some
header (cookie, whatever) and will then get an exception when trying to
do so.
This is not a theoretical issue. For my application, the NewRelic
middleware caused the flush to happen before the other Rack middleware
would set the cookies.
So it would be extremely interesting if Rack (or Rails at least) could
provide some reliable supported way for middlewares to know whether a
response is streamed or not. Should we use the same convention as the
Rack::ETag middleware and check for Cache-Control: no-cache? Or is there
another recommended method for doing so?
Thanks in advance,
Rodrigo.
On 15-07-2014 12:20, Rodrigo Rosenfeld Rosas wrote:
On 14-07-2014 18:14, Jason Clark wrote:
I'm curious if there's a good way to detect from a Rack middleware
whether a response is streaming or not.
From what I can see, my options are:
1 - In the Controller note we've included `ActionController::Live`
somewhere the middleware can access it
2 - Look at the response object coming back to Rack to see if its
class is `ActionController::Live::Response`
3 - Look at the `stream` (if available) on the response object
returned to Rack to check if it's a `ActionController::Live::Buffer`
All of these ideas seem pretty brittle and liable to break across new
versions of Rails and/or new streaming mechanisms that might come
along. Is there something I'm missing?
Hi Jason,
Actually (2) is not possible using the public API if I remember
correctly because the response is wrapped inside a Rack::BodyProxy (or
something like that). That's why I used (3) when I needed to detect if
streaming was enabled.
Another option would be to use the same convention as Rack::ETag
middleware and do not attempt to read the response if the
Cache-Control header is set to no-cache. ActionController::Live will
set this header on the first response.stream.write call (although
there's still a bug that will happen and affect the ETag middleware as
well if the action calls response.commit! before response.stream.write).
This might be a better and less intrusive work-around until Rack
support some new API to let the middlewares know whether it's a
streamed response or not.
HTH,
Rodrigo.
--
You received this message because you are subscribed to the Google Groups "Ruby on
Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/rubyonrails-core.
For more options, visit https://groups.google.com/d/optout.