Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Proposal] Support no output buffering at all #2481

Closed
1ma opened this issue Aug 6, 2018 · 3 comments
Closed

[Proposal] Support no output buffering at all #2481

1ma opened this issue Aug 6, 2018 · 3 comments

Comments

@1ma
Copy link

1ma commented Aug 6, 2018

Use case

Adding the ability to completely disable output buffering would empower the developer to push content to the user agent while still processing an HTTP request (i.e. while still inside the callback or Action class). This would allow, for instance, to give real-time feedback at every iteration of a long-running loop.

The following is a minimal demonstration in pure PHP that can be served with the builtin webserver to see the effect firsthand:

// index.php

header('Content-Type: text/plain');

foreach (range('A', 'F') as $char) {
  sleep(1);
  echo "$char\n";

  ob_flush();
  flush();
}

demo

Current status

Slim 3 has an outputBuffering setting whose legal values are false, 'append' and 'prepend' (default 'append'). However, false seems to simply instruct the framework to neither prepend nor append stray echo's to the PSR7 response.

As far as I understand, Slim does not currently support this behaviour.

Proposed API

I believe that the cleanest way to add this feature would be through a new specialized implementation of the StreamInterface that would handle all the details under the hood in its write method. The former sample could be then rewritten like this:

namespace Demo;

use Slim\Http;

final class NonBufferedAction
{
    public function __invoke(Http\Request $request, Http\Response $response): Http\Response
    {
        $response = $response
            ->withBody(new NonBufferedBody())
            ->withHeader('Content-Type', 'text/plain');

        foreach (range('A', 'F') as $char) {
            sleep(1);
            $response->getBody()->write("$char\n");
        }

        return $response;
    }
}

What are yer thoughts?

@llvdl
Copy link
Contributor

llvdl commented Aug 19, 2018

I think that would break the ability for middleware to replace or alter the response.

I think a generator as a body would be a good fit here. If Slim could be altered to allow a generator as well as a Psr\Http\Message\StreamInterface instance, then the following code could be used:

class NonBufferedAction
{
  public function __invoke(Request $request, Response $response): Response
  {
    return $response
      ->withBody(function (): Generator  { // won't work now, as Slim expects a StreamInterface instance
        foreach (['alpha', 'beta', 'gamma', 'delta'] as $data) {
          sleep(1);
          yield $data;
        }
      });
  }
}

@akrabat
Copy link
Member

akrabat commented Sep 16, 2018

I like the idea of a specialised StreamInterface.

Implementing this will also address Server Sent Events support (#1959).

@1ma
Copy link
Author

1ma commented Sep 21, 2018

I submitted a PR with a possible implementation, but I'd like to have a bit of input from the mantainers and/or other community members before doing the rest of the gruntwork (mostly documentation).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants