Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
[HttpFoundation] added support for streamed responses #2935
To stream a Response, use the StreamedResponse class instead of the
As you can see, a StreamedResponse instance takes a PHP callback instead of
From a controller, do something like this:
If you are using the base controller, you can use the stream() method instead:
You can stream an existing file by using the PHP built-in readfile() function:
Read http://php.net/flush for more information about output buffering in PHP.
Note that you should do your best to move all expensive operations to
If you are using Twig as a template engine, everything should work as
However, note that streaming is not supported for PHP templates. Support
Exceptions thrown during rendering will be rendered as usual except that
As the getContent() method always returns false for streamed Responses, some
Also note that streamed responses cannot benefit from HTTP caching for obvious
Just an idea: what about exposing flush() to twig? Possibly in a way that it will not call it if the template is not streaming. That way you could always add a flush() after your tag to make sure that goes out as fast as possible, but it wouldn't mess with non-streamed responses. Although it appears flush() doesn't affect output buffers, so I guess it doesn't need anything special.
When you say "ESI is not supported.", that means only the AppCache right? I don't see why this would affect Varnish, but then again as far as I know Varnish will buffer if ESI is used so the benefit of streaming there is non-existent.
Essentially it allows faster fetching of web assets (JS, CSS, etc) located in the <head></head>, allowing those assets to be fetched as soon as possible before the remainder of the content body is computed and sent to the browser. The end goal is to improve page load speed.
There are other uses cases too like making large body content available quickly to the service consuming it. Think if you were monitoring a live feed of JSON data of newest Twitter comments.
How does this relate the limitations mentioned in:
Am I right to understand that due to how twig works we are not really streaming the content pieces when we call render(), but instead the entire template with its layout is rendered and only then will we flush? or does it mean that the render call will work its way to the top level layout template and form then on it can send the content until it hits another block, which it then first renders before it continues to send the data?
@lsmith77 this is why the
@lsmith77: We don't have the Rails problem thanks to Twig as the order of execution is the right one by default (the layout is executed first); it means that we can have the flush feature without any change to how the core works. As @stof mentioned, we are using
@fzaninotto: What do you mean?
With Twig, your layout is defined with blocks ("holes"). These blocks are overridden by child templates, but evaluated as they are encountered in the layout. So, everything works as expected.
As noted in the commit message, this does not work with PHP templates for the problems mentioned in the Rails post (as the order of execution is not the right one -- the child template is first evaluated and then the layout).
added a commit
this pull request
Dec 31, 2011
I ran into some problems with the way this is implemented. The issues are related to transfer-encoding.
First, it is not possible to force identity (the default) encoding, because StreamedResponse overrides it in any case. It should only set the encoding if none is set yet. Note: Even if it is explicitly set to identity and not overriden to chunked, apache will change it to "identity, chunked" because no content-length is set.
Now this brings us to the second issue. When you send a transfer-encoding=chunked header, apache will expect the content to already be chunked. Of course this is not the case, and thus it does not work. Unless other webservers require it to be present, I would suggest simply not setting the transfer-encoding header. Since no content-length is set, the server should switch to chunked automatically.