reactphp / http

Event-driven, streaming HTTP client and server implementation for ReactPHP.
https://reactphp.org/http/
MIT License
747 stars 143 forks source link

When a request is cancelled, the promise seems to not be cancelled. #534

Open wpjscc opened 4 months ago

wpjscc commented 4 months ago

When a request is cancelled, the promise seems to not be cancelled.

<?php

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

use function React\Async\async;
use function React\Async\delay;
use function React\Promise\resolve;
use Psr\Http\Message\ServerRequestInterface;
use React\Http\Message\Response;

$http = new React\Http\HttpServer(
    function (ServerRequestInterface $request, callable $next) {
        $withHeaders = [
            'Access-Control-Allow-Origin' => '*',
            'Access-Control-Allow-Methods' => '*',
            'Access-Control-Allow-Headers' => '*',
            'Access-Control-Expose-Headers' => '*',
        ];

        if ($request->getMethod() == 'OPTIONS') {
            return new Response(200, $withHeaders, 'OK');
        }
        return resolve($next($request))->then(
            function ($response) use ($withHeaders) {
                foreach ($withHeaders as $key => $value) {
                    if (!$response->hasHeader($key)) {
                        $response = $response->withHeader($key, $value);
                    }
                }
                return $response;
            }
        );
    },
    function (Psr\Http\Message\ServerRequestInterface $request) {
        return async(function () {
            echo "hello world 1\n";
            delay(3);
            echo "hello world 2\n";
            return React\Http\Message\Response::plaintext(
                "Hello World!\n"
            )->withHeader('Access-Control-Allow-Origin', '*')
                ->withHeader('Access-Control-Allow-Methods', '*')
                ->withHeader('Access-Control-Allow-Headers', '*')
                ->withHeader('Access-Control-Expose-Headers', '*');
        })();
    }
);
$socket = new React\Socket\SocketServer(getenv('LISTEN') ?: '0.0.0.0:8070');
$http->listen($socket);

echo "Server running at http://127.0.0.1:8070" . PHP_EOL;

front Cancel request after 1 seconds.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
       const controller = new AbortController();
        const signal = controller.signal;

        setTimeout(() => {
            controller.abort();
        }, 1000);

        fetch('http://192.168.1.9:8070', { 
            signal, 
            method: 'post',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                'hello':'world'
            })
        })
        .then(response => response.json())
        .then(data => console.log(data))
        .catch(error => {
            if (error.name === 'AbortError') {
            console.log('请求已取消');
            } else {
            console.error('请求失败:', error);
            }
        });
    </script>
</body>

</html>

After the cancellation of the 1 second, the backend also displayed "hello world 2".

when modify the https://github.com/reactphp/http/blob/3.x/src/Middleware/RequestBodyBufferMiddleware.php ,it work for me

link