diff --git a/src/ServerRequestFactory.php b/src/ServerRequestFactory.php index 57cdc167..ec81fc9c 100644 --- a/src/ServerRequestFactory.php +++ b/src/ServerRequestFactory.php @@ -9,7 +9,9 @@ use InvalidArgumentException; use Psr\Http\Message\UploadedFileInterface; +use RuntimeException; use stdClass; +use swoole_http_request; use UnexpectedValueException; use function array_change_key_case; @@ -99,6 +101,82 @@ public static function fromGlobals( ); } + /** + * Create a request from a Swoole request + * + * @param swoole_http_request $request + * @return ServerRequest + * @throws RuntimeException if Swoole is not installed + */ + + public static function fromSwoole(swoole_http_request $request) + { + if (! extension_loaded('swoole')) { + throw new Exception\RuntimeException('Swoole extension is not installed!'); + } + $get = isset($request->get) ? $request->get : []; + $post = isset($request->post) ? $request->post : []; + $cookie = isset($request->cookie) ? $request->cookie : []; + $files = isset($request->files) ? $request->files : []; + + $server = [ + 'REQUEST_METHOD' => $request->server['request_method'], + 'REQUEST_URI' => $request->server['request_uri'], + 'PATH_INFO' => $request->server['path_info'], + 'REQUEST_TIME' => $request->server['request_time'], + 'GATEWAY_INTERFACE' => 'swoole/' . SWOOLE_VERSION, + // Server + 'SERVER_PROTOCOL' => isset($request->header['server_protocol']) ? + $request->header['server_protocol'] : $request->server['server_protocol'], + 'REQUEST_SCHEMA' => isset($request->header['request_scheme']) ? + $request->header['request_scheme'] : + explode('/', $request->server['server_protocol'])[0], + 'SERVER_NAME' => isset($request->header['server_name']) ? + $request->header['server_name'] : $request->header['host'], + 'SERVER_ADDR' => $request->header['host'], + 'SERVER_PORT' => isset($request->header['server_port']) ? + $request->header['server_port'] : $request->server['server_port'], + 'REMOTE_ADDR' => isset($request->server['remote_addr']) ? + $request->server['remote_addr'] : $request->header['host'], + 'REMOTE_PORT' => isset($request->header['remote_port']) ? + $request->header['remote_port'] : $request->server['remote_port'], + 'QUERY_STRING' => isset($request->server['query_string']) ? + $request->server['query_string'] : '', + // Headers + 'HTTP_HOST' => $request->header['host'], + 'HTTP_USER_AGENT' => isset($request->header['user-agent']) ? + $request->header['user-agent'] : '', + 'HTTP_ACCEPT' => isset($request->header['accept']) ? + $request->header['accept'] : '*/*', + 'HTTP_ACCEPT_LANGUAGE' => isset($request->header['accept-language']) ? + $request->header['accept-language'] : '', + 'HTTP_ACCEPT_ENCODING' => isset($request->header['accept-encoding']) ? + $request->header['accept-encoding'] : '', + 'HTTP_CONNECTION' => isset($request->header['connection']) ? + $request->header['connection'] : '', + 'HTTP_CACHE_CONTROL' => isset($request->header['cache-control']) ? + $request->header['cache-control'] : '', + ]; + + $headers = []; + foreach ($request->header as $name => $value) { + $headers[str_replace('-', '_', $name)] = $value; + } + + return new ServerRequest( + $server, + static::normalizeFiles($files), + static::marshalUriFromServer($server, $headers), + $server['REQUEST_METHOD'], + $request->rawContent(), + $headers, + $cookie, + $get, + $post, + static::marshalProtocolVersion($server) + ); + } + /** * Access a value in an array, returning a default value if not found * diff --git a/test/ServerRequestFactoryTest.php b/test/ServerRequestFactoryTest.php index 63f202e1..36b9f06b 100644 --- a/test/ServerRequestFactoryTest.php +++ b/test/ServerRequestFactoryTest.php @@ -10,6 +10,7 @@ use PHPUnit\Framework\TestCase; use ReflectionMethod; use ReflectionProperty; +use swoole_http_request; use UnexpectedValueException; use Zend\Diactoros\ServerRequest; use Zend\Diactoros\ServerRequestFactory; @@ -580,4 +581,34 @@ public function marshalProtocolVersionProvider() 'HTTP/2' => ['HTTP/2', '2'], ]; } + + public function testFromSwoole() + { + if (! extension_loaded('swoole')) { + $this->markTestSkipped('The Swoole extesion is not available'); + } + + $swooleRequest = $this->createMock(swoole_http_request::class); + $swooleRequest->header['host'] = 'localhost:9501'; + $swooleRequest->server['request_method'] = 'GET'; + $swooleRequest->server['request_uri'] = '/'; + $swooleRequest->server['path_info'] = '/'; + $swooleRequest->server['request_time'] = time(); + $swooleRequest->server['server_protocol'] = 'HTTP/1.1'; + $swooleRequest->server['server_port'] = 9501; + $swooleRequest->server['remote_port'] = 45314; + $swooleRequest->method('rawContent')->willReturn('php://input'); + + $request = ServerRequestFactory::fromSwoole($swooleRequest); + $this->assertInstanceOf(ServerRequest::class, $request); + $this->assertEquals('GET', $request->getMethod()); + $this->assertEquals('/', $request->getRequestTarget()); + $this->assertEquals('/', $request->getUri()->getPath()); + $this->assertEquals('1.1', $request->getProtocolVersion()); + $this->assertEquals('', $request->getBody()); + $this->assertEquals([], $request->getCookieParams()); + $this->assertEquals([], $request->getQueryParams()); + $this->assertEquals([], $request->getUploadedFiles()); + $this->assertEquals(['host' => ['localhost:9501']], $request->getHeaders()); + } }