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

Body Stream Closes when running Browser Request #510

Closed
mrsimonbennett opened this issue Nov 29, 2023 · 3 comments
Closed

Body Stream Closes when running Browser Request #510

mrsimonbennett opened this issue Nov 29, 2023 · 3 comments
Labels

Comments

@mrsimonbennett
Copy link
Contributor

So I am trying to write some middleware that will authenticate the request, todo the middleware needs to make a call to another HTTP server to find out, (the final version will use cache)

I have boiled down to the smallest working example of things breaking. Observe the body changing to unreadable.

If I use a StreamingRequestMiddleware everything will work fine, however as soon as I do a browser request the request body closes and becomes unreadable.

Maybe I am missing something and this is how it's meant to work, if so a workaround or solution direction would be most welcomed.

I don't really want to do a blocking http call, (I have tested this and this works other than it blocking the whole server)

<?php
require __DIR__ . '/../vendor/autoload.php';

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use React\Http\HttpServer;
use React\Http\Middleware\StreamingRequestMiddleware;


$http = new HttpServer(

    new StreamingRequestMiddleware(),
    function (ServerRequestInterface $request, callable $next) {
        dump($request->getBody()->isReadable()); //true


        return $next($request);
    },
    function (ServerRequestInterface $request, callable $next) {
        dump($request->getBody()->isReadable()); //true

        $browser = new React\Http\Browser();

        return $browser->get('https://www.google.com')->then(
            function (ResponseInterface $response) use ($next, $request) {
                dump($request->getBody()->isReadable()); //false

                return $next($request);
            }
        );
    },
    function (ServerRequestInterface $request) {

        dump($request->getBody()->isReadable()); //false

        return new React\Http\Message\Response(
            200,
            ['Content-Type' => 'text/plain'],
            'Hello World!'
        );

    }
);
$socket = new React\Socket\SocketServer('127.0.0.1:8080');
$http->listen($socket);
echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL;
@mrsimonbennett
Copy link
Contributor Author

mrsimonbennett commented Nov 29, 2023

Hold the phone

I am experimenting with adding a middleware to pause the body stream before doing anything else

$http = new HttpServer(

    new StreamingRequestMiddleware(),
    function (ServerRequestInterface $request, callable $next) {
        $request->getBody()->pause();
        return $next($request);
    },...

@WyriHaximus
Copy link
Member

Since you went with a streaming request body we expect you to take care of it. Pausing or buffering at the start can be a way. However it is meant for use cases where you parse the body as it streams in. But it is only recommended to use a streaming body if you have a need for it. If you don't, drop it and let the server buffer the body for you.

So in your case what probably happened is:

  • Request comes in
  • Body is still streaming in when your closure gets called
  • Browser sends request out
  • Fully body came in while that request is out
  • Body stream closes
  • Browser request completes
  • You confused of what just happened

@SimonFrings SimonFrings added question and removed bug labels Dec 15, 2023
@SimonFrings
Copy link
Member

Hey @mrsimonbennett, I think the stream in your example above gets closed by the client while your sending out your HTTP request (client finishes and closes stream). In ReactPHP everything is event-driven, so we can actually listen on specific events and see what's going on behind the scenes. This means, after a connection has been established, we can start listening on incoming data events from the client (as described in https://github.com/reactphp/stream#stream-usage). We can also do the same for end and close events to see if the client is responsible for closing here.

I am experimenting with adding a middleware to pause the body stream before doing anything else

You're onto something. What you need to do here is to control the stream by pausing before sending out your HTTP requets and resuming it afterwards.

I hope this helps 👍

I believe this should answer your question, so I will close this ticket for now. We can reopen this if you encounter the same issues again after trying out the solutions mentioned in here. If you do need to reopen the ticket, please provide some information about the steps you've taken so far, what worked and what didn't.

If our conversation answered your questions or helped you progressing, consider supporting the ReactPHP ecosystem by becoming a sponsor ❤️

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

No branches or pull requests

3 participants