reactphp / filesystem

Evented filesystem access.
MIT License
135 stars 40 forks source link

500 internal server error #92

Closed valzargaming closed 3 years ago

valzargaming commented 3 years ago

I tried a basic test by attempting to use the React/Filesystem to load a file and return it as a stream, but it still returns a 500 internal server error. Right now I am not sure if this is dependency-related. I am currently running this under PHP 8.0.1 alongside discord-php/DiscordPHP. image image

$filesystem = \React\Filesystem\Filesystem::create($discord->getLoop()); //Awaiting full PHP 8 support
$rtmp = new Server($discord->getLoop(), function (ServerRequestInterface $request) use ($filesystem) {
    $file = $filesystem->file(__DIR__ . '/media/SpaceEngineers.mp4');
    return $file->exists()
        ->then(
            function () use ($file) {
                return $file->open('r', true)
                    ->then(function ($stream) {
                        echo '[TEST]' . __FILE__ . ':' . __LINE__ . PHP_EOL;
                        file_put_contents('stream.txt', $stream); //0 bytes
                        file_put_contents('stream.mp4', $stream); // 0 bytes
                        return new Response(200, ['Content-Type' => 'video/mp4'], $stream);
                    });
            },
            function () {
                return new Response(404, ['Content-Type' => 'text/plain'], "This video doesn't exist on server.");
            });
});
$rsocket = new \React\Socket\Server(sprintf('%s:%s', '0.0.0.0', '55554'), $discord->getLoop());
$rtmp->listen($rsocket);
WyriHaximus commented 3 years ago

Try adding $rtmp->on('error', function (Throwable $t) { echo $t; }); to display the cause of the 500 error.

valzargaming commented 3 years ago

The stack trace log was quite hefty, but didn't shed much light on what the root cause of the issue is. https://pastebin.com/Bh6kzvDX

WyriHaximus commented 3 years ago

Ah doh! So the stream you pass into the response, it's a PHP stream, it's a ReadableStreamInterface. And that's the root cause of the 500 error.

valzargaming commented 3 years ago

That makes a bit of sense now. Is there another preferable way to accomplish this? The source will eventually want to be a live .m3u8 (or equivalent) that will be written to at the same time, so I wanted to set up a way to view the active stream as you would with any streaming service, such as Twitch.

I also wanted to use this as an opportunity to push the source to another source, such as an NGINX Gryphon server, and then use it for multicasting. I saw something about using pipes to accomplish this but I'm not sure if that will work on a Windows setup.

clue commented 3 years ago

The following lines from your error output suggest you're using the Guzzle\Psr7\Response class which does not accept an instance of React\Stream\ReadableStreamInterface:

InvalidArgumentException: Invalid resource type: object in C:\Discord Bots\discord - Palace DiscordPHP\vendor\guzzlehttp\psr7\src\Utils.php:334
Stack trace:
#0 C:\Discord Bots\discord - Palace DiscordPHP\vendor\guzzlehttp\psr7\src\Response.php(104): GuzzleHttp\Psr7\Utils::streamFor()
#1 C:\Discord Bots\discord - Palace DiscordPHP\run.php(77): GuzzleHttp\Psr7\Response->__construct()
#2 C:\Discord Bots\discord - Palace DiscordPHP\vendor\react\promise\src\FulfilledPromise.php(28): {closure}()
…

The fix is easy. According to our HTTP documentation, you should use the React\Http\Message\Response class instead, which also allows a React\Stream\ReadableStreamInterface. In your case, this means only replacing the use statement, as the method signature is identical otherwise:

- use Guzzle\Psr7\Response;
+ use React\Http\Message\Response;

See also https://github.com/reactphp/http#streaming-outgoing-response

I believe this has been answered, so I'm closing this for now. Please come back with more details if this problem persists and we can always reopen this :+1: