├── .gitignore ├── src ├── Exception │ ├── SwooleExpressiveException.php │ ├── MissingRoutesException.php │ └── MissingPipeLineException.php ├── Bridge │ ├── Psr7RequestBuilderFactory.php │ ├── SwooleResponseEmitterFactory.php │ ├── MiddlewareSetupRunnerInterface.php │ ├── MiddlewareSetupRunnerFactory.php │ ├── SwooleResponseEmitter.php │ ├── MiddlewareSetupRunner.php │ └── Psr7RequestBuilder.php ├── Command │ ├── SwooleRunnerCommandFactory.php │ └── SwooleRunnerCommand.php └── ConfigProvider.php ├── tests ├── Mock │ ├── MockRoutes.php │ ├── MockPipeline.php │ └── RequestMockTrait.php ├── Bridge │ ├── Psr7RequestBuilderFactoryTest.php │ ├── SwooleResponseEmitterFactoryTest.php │ ├── MiddlewareSetupRunnerFactoryTest.php │ ├── SwooleResponseEmitterTest.php │ ├── MiddlewareSetupRunnerTest.php │ └── Psr7RequestBuilderTest.php └── Command │ └── SwooleRunnerCommandFactoryTest.php ├── phpunit.xml ├── .travis.yml ├── phpmd.xml ├── composer.json ├── bin └── swoole-expressive └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | .idea 3 | composer.lock 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /src/Exception/SwooleExpressiveException.php: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | ./test 9 | 10 | 11 | 12 | 13 | 14 | ./src 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 7.2 5 | 6 | cache: 7 | directories: 8 | - $HOME/.composer/cache 9 | 10 | before_script: 11 | - pecl install swoole-2.1.1 12 | - composer self-update 13 | - composer install --prefer-dist -n 14 | 15 | script: 16 | - ./vendor/bin/phpunit tests/ --coverage-clover clover.xml 17 | - ./vendor/bin/phpcs --extensions=php --standard=PSR2 --ignore=*/_files/* src/ tests/ 18 | - ./vendor/bin/phpmd ./src text ./phpmd.xml --suffixes php 19 | 20 | after_success: 21 | - bash <(curl -s https://codecov.io/bash) 22 | - wget https://scrutinizer-ci.com/ocular.phar 23 | - php ocular.phar code-coverage:upload --format=php-clover clover.xml 24 | -------------------------------------------------------------------------------- /tests/Bridge/Psr7RequestBuilderFactoryTest.php: -------------------------------------------------------------------------------- 1 | createMock(ContainerInterface::class); 16 | $factory = new Psr7RequestBuilderFactory(); 17 | $instance = $factory($container); 18 | $this->assertInstanceOf(Psr7RequestBuilder::class, $instance); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Bridge/MiddlewareSetupRunnerFactory.php: -------------------------------------------------------------------------------- 1 | get(Application::class); 16 | 17 | /** @var \Zend\Expressive\MiddlewareFactory $factory */ 18 | $factory = $container->get(MiddlewareFactory::class); 19 | 20 | return new MiddlewareSetupRunner($app, $factory, $container); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/Bridge/SwooleResponseEmitterFactoryTest.php: -------------------------------------------------------------------------------- 1 | createMock(ContainerInterface::class); 16 | $factory = new SwooleResponseEmitterFactory(); 17 | $instance = $factory($container); 18 | $this->assertInstanceOf(SwooleResponseEmitter::class, $instance); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /phpmd.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | Custom Rule Set 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/Command/SwooleRunnerCommandFactory.php: -------------------------------------------------------------------------------- 1 | get(\Zend\Expressive\Application::class); 17 | 18 | /** @var MiddlewareSetupRunnerInterface $factory */ 19 | $setupRunner = $container->get(MiddlewareSetupRunnerInterface::class); 20 | 21 | /** @var Psr7RequestBuilder $requestBuilder */ 22 | $requestBuilder = $container->get(Psr7RequestBuilder::class); 23 | 24 | /** @var SwooleResponseEmitter $responseEmitter */ 25 | $responseEmitter = $container->get(SwooleResponseEmitter::class); 26 | 27 | return new SwooleRunnerCommand($app, $setupRunner, $requestBuilder, $responseEmitter); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wshafer/swoole-expressive", 3 | "license": "BSD-2-Clause", 4 | "authors": [ 5 | { 6 | "name": "Westin Shafer", 7 | "email": "shafer_w2002@yahoo.com" 8 | } 9 | ], 10 | "description": "Swoole + Zend Expressive Runner", 11 | "type": "library", 12 | "prefer-stable": true, 13 | "require": { 14 | "php": "^7.2", 15 | "ext-swoole": ">=2.1.0", 16 | "zendframework/zend-expressive": "^3.0.1", 17 | "symfony/console": "^2.8 || ^3.0 || ^4.0", 18 | "psr/log": "^1.0" 19 | }, 20 | "require-dev": { 21 | "phpmd/phpmd" : "@stable", 22 | "zendframework/zend-diactoros": "^1.7.1", 23 | "phpunit/phpunit": "^6.5.4", 24 | "squizlabs/php_codesniffer": "^2.9.1" 25 | }, 26 | "autoload": { 27 | "psr-4": { 28 | "WShafer\\SwooleExpressive\\": "src/" 29 | } 30 | }, 31 | "autoload-dev": { 32 | "psr-4": { 33 | "WShafer\\SwooleExpressive\\Test\\": "tests/" 34 | } 35 | }, 36 | "extra": { 37 | "zf": { 38 | "config-provider": "WShafer\\SwooleExpressive\\ConfigProvider" 39 | } 40 | }, 41 | "bin": [ 42 | "bin/swoole-expressive" 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /bin/swoole-expressive: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | get(\WShafer\SwooleExpressive\Command\SwooleRunnerCommand::class); 36 | $application->add($command); 37 | $application->setDefaultCommand($command->getName()); 38 | 39 | $application->run(); 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **WARNING: This package is abandoned and no longer maintained.** 2 | 3 | **Please see the [zendframework/zend-expressive-swoole](https://github.com/zendframework/zend-expressive-swoole) 4 | package instead.** 5 | 6 | 7 | # Swoole + Zend Expressive 8 | [![Build Status](https://travis-ci.org/wshafer/swoole-expressive.svg?branch=master)](https://travis-ci.org/wshafer/swoole-expressive) 9 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/wshafer/swoole-expressive/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/wshafer/swoole-expressive/?branch=master) 10 | [![codecov](https://codecov.io/gh/wshafer/swoole-expressive/branch/master/graph/badge.svg)](https://codecov.io/gh/wshafer/swoole-expressive) 11 | 12 | This package provides a Zend Expressive 3 runner for Swoole. 13 | 14 | ## Install 15 | 16 | Install Swoole 17 | ```bash 18 | $ pecl install swoole-2.1.1 19 | ``` 20 | 21 | Install Zend Expressive 22 | ```bash 23 | $ composer create-project zendframework/zend-expressive-skeleton 24 | ``` 25 | 26 | Add the Swoole + Expressive composer package 27 | 28 | ```bash 29 | $ composer require wshafer/swoole-expressive:dev-master 30 | ``` 31 | 32 | 33 | 34 | ## Usage 35 | 36 | ```bash 37 | $ vendor/bin/swoole-expressive --host=0.0.0.0 --port=8080 38 | ``` 39 | 40 | Open your browser to http://127.0.0.1:8080 to validate you're 41 | up and running. 42 | -------------------------------------------------------------------------------- /src/ConfigProvider.php: -------------------------------------------------------------------------------- 1 | $this->getDependencies(), 21 | ]; 22 | } 23 | 24 | public function getDependencies() : array 25 | { 26 | return [ 27 | 'aliases' => [], 28 | 'factories' => [ 29 | SwooleRunnerCommand::class => SwooleRunnerCommandFactory::class, 30 | SwooleResponseEmitter::class => SwooleResponseEmitterFactory::class, 31 | Psr7RequestBuilder::class => Psr7RequestBuilderFactory::class, 32 | MiddlewareSetupRunnerInterface::class => MiddlewareSetupRunnerFactory::class, 33 | ], 34 | ]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/Bridge/MiddlewareSetupRunnerFactoryTest.php: -------------------------------------------------------------------------------- 1 | createMock(ContainerInterface::class); 18 | 19 | $mockApp = $this->getMockBuilder(Application::class) 20 | ->disableOriginalConstructor() 21 | ->getMock(); 22 | 23 | $mockMiddleware = $this->getMockBuilder(MiddlewareFactory::class) 24 | ->disableOriginalConstructor() 25 | ->getMock(); 26 | 27 | $map = [ 28 | [Application::class, $mockApp], 29 | [MiddlewareFactory::class, $mockMiddleware], 30 | ]; 31 | 32 | $mockContainer->expects($this->exactly(2)) 33 | ->method('get') 34 | ->will($this->returnValueMap($map)); 35 | 36 | $factory = new MiddlewareSetupRunnerFactory(); 37 | $instance = $factory($mockContainer); 38 | $this->assertInstanceOf(MiddlewareSetupRunner::class, $instance); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Bridge/SwooleResponseEmitter.php: -------------------------------------------------------------------------------- 1 | status($psr7Response->getStatusCode()); 19 | $this->populateHeaders($psr7Response, $swooleResponse); 20 | $this->sendResponse($psr7Response, $swooleResponse); 21 | } 22 | 23 | protected function populateHeaders( 24 | ResponseInterface $psr7Response, 25 | SwooleResponse $swooleResponse 26 | ) { 27 | $headers = $psr7Response->getHeaders(); 28 | 29 | foreach ($headers as $name => $values) { 30 | $name = $this->filterHeader($name); 31 | 32 | if ($name === 'Set-Cookie') { 33 | $swooleResponse->header($name, end($values)); 34 | continue; 35 | } 36 | 37 | $swooleResponse->header($name, implode(', ', $values)); 38 | } 39 | } 40 | 41 | protected function sendResponse( 42 | ResponseInterface $psr7Response, 43 | SwooleResponse $swooleResponse 44 | ) { 45 | $content = $psr7Response->getBody(); 46 | $content->rewind(); 47 | $swooleResponse->end($content->getContents()); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/Command/SwooleRunnerCommandFactoryTest.php: -------------------------------------------------------------------------------- 1 | createMock(ContainerInterface::class); 20 | 21 | $mockApp = $this->getMockBuilder(Application::class) 22 | ->disableOriginalConstructor() 23 | ->getMock(); 24 | 25 | $mockMiddlewareSetup = $this->getMockBuilder(MiddlewareSetupRunnerInterface::class) 26 | ->disableOriginalConstructor() 27 | ->getMock(); 28 | 29 | $mockRequestBuilder = $this->getMockBuilder(Psr7RequestBuilder::class) 30 | ->disableOriginalConstructor() 31 | ->getMock(); 32 | 33 | $mockResponseEmitter = $this->getMockBuilder(SwooleResponseEmitter::class) 34 | ->disableOriginalConstructor() 35 | ->getMock(); 36 | 37 | $map = [ 38 | [Application::class, $mockApp], 39 | [MiddlewareSetupRunnerInterface::class, $mockMiddlewareSetup], 40 | [Psr7RequestBuilder::class, $mockRequestBuilder], 41 | [SwooleResponseEmitter::class, $mockResponseEmitter], 42 | ]; 43 | 44 | $mockContainer->expects($this->exactly(4)) 45 | ->method('get') 46 | ->will($this->returnValueMap($map)); 47 | 48 | $factory = new SwooleRunnerCommandFactory(); 49 | $instance = $factory($mockContainer); 50 | $this->assertInstanceOf(SwooleRunnerCommand::class, $instance); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /tests/Bridge/SwooleResponseEmitterTest.php: -------------------------------------------------------------------------------- 1 | mockPsr7Response = $this->createMock(ResponseInterface::class); 27 | $this->mockSwooleResponse = $this->createMock(SwooleResponse::class); 28 | $this->emitter = new SwooleResponseEmitter(); 29 | $this->assertInstanceOf(SwooleResponseEmitter::class, $this->emitter); 30 | } 31 | 32 | public function testConstructor() 33 | { 34 | } 35 | 36 | public function testToSwoole() 37 | { 38 | $this->mockPsr7Response->expects($this->once()) 39 | ->method('getStatusCode') 40 | ->willReturn(404); 41 | 42 | $this->mockSwooleResponse->expects($this->once()) 43 | ->method('status') 44 | ->with(404) 45 | ->willReturn(null); 46 | 47 | $headers = [ 48 | 'Content-Type' => ['text/javascript', 'text/css'], 49 | 'Set-Cookie' => ['cookie-one', 'cookie-end'] 50 | ]; 51 | 52 | $this->mockPsr7Response->expects($this->once()) 53 | ->method('getHeaders') 54 | ->willReturn($headers); 55 | 56 | $this->mockSwooleResponse->expects($this->exactly(2)) 57 | ->method('header') 58 | ->withConsecutive( 59 | [$this->equalTo('Content-Type'), $this->equalTo('text/javascript, text/css'), $this->isNull()], 60 | [$this->equalTo('Set-Cookie'), $this->equalTo('cookie-end'), $this->isNull()] 61 | ); 62 | 63 | $mockStream = $this->createMock(StreamInterface::class); 64 | 65 | $this->mockPsr7Response->expects($this->once()) 66 | ->method('getBody') 67 | ->willReturn($mockStream); 68 | 69 | $mockStream->expects($this->once()) 70 | ->method('rewind') 71 | ->willReturn(null); 72 | 73 | $content = 'This is some body'; 74 | 75 | $mockStream->expects($this->once()) 76 | ->method('getContents') 77 | ->willReturn($content); 78 | 79 | $this->mockSwooleResponse->expects($this->once()) 80 | ->method('end') 81 | ->with($this->equalTo($content)); 82 | 83 | $this->emitter->toSwoole($this->mockPsr7Response, $this->mockSwooleResponse); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /tests/Bridge/MiddlewareSetupRunnerTest.php: -------------------------------------------------------------------------------- 1 | mockContainer = $this->createMock(ContainerInterface::class); 33 | 34 | $this->mockApplication = $this->getMockBuilder(Application::class) 35 | ->disableOriginalConstructor() 36 | ->getMock(); 37 | 38 | $this->mockMiddleware = $this->getMockBuilder(MiddlewareFactory::class) 39 | ->disableOriginalConstructor() 40 | ->getMock(); 41 | 42 | 43 | $this->runner = new MiddlewareSetupRunner( 44 | $this->mockApplication, 45 | $this->mockMiddleware, 46 | $this->mockContainer 47 | ); 48 | 49 | $this->assertInstanceOf(MiddlewareSetupRunner::class, $this->runner); 50 | } 51 | 52 | public function testConstructor() 53 | { 54 | } 55 | 56 | public function testSetAndGetPipeline() 57 | { 58 | $this->runner->setPipelineFilePath($this->mockPipeline); 59 | $result = $this->runner->getPipeline(); 60 | $this->assertEquals($this->mockPipeline, $result); 61 | } 62 | 63 | /** 64 | * @expectedException \WShafer\SwooleExpressive\Exception\MissingPipeLineException 65 | */ 66 | public function testSetPipelineFileNotFound() 67 | { 68 | $this->runner->setPipelineFilePath('not-here'); 69 | } 70 | 71 | public function testSetAndGetRoutes() 72 | { 73 | $this->runner->setRoutesFilePath($this->mockRoutes); 74 | $result = $this->runner->getRoutes(); 75 | $this->assertEquals($this->mockRoutes, $result); 76 | } 77 | 78 | /** 79 | * @expectedException \WShafer\SwooleExpressive\Exception\MissingRoutesException 80 | */ 81 | public function testSetRoutesFileNotFound() 82 | { 83 | $this->runner->setRoutesFilePath('not-here'); 84 | } 85 | 86 | public function testExecute() 87 | { 88 | $this->runner->setPipelineFilePath($this->mockPipeline); 89 | $this->runner->setRoutesFilePath($this->mockRoutes); 90 | $result = $this->runner->execute(); 91 | $this->assertTrue($result); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/Bridge/MiddlewareSetupRunner.php: -------------------------------------------------------------------------------- 1 | application = $application; 33 | $this->factory = $factory; 34 | $this->container = $container; 35 | } 36 | 37 | /** 38 | * @return bool 39 | * @throws MissingPipeLineException 40 | * @throws MissingRoutesException 41 | */ 42 | public function execute() : bool 43 | { 44 | $pipeLine = $this->getPipeline(); 45 | 46 | if (!$pipeLine) { 47 | throw new MissingPipeLineException('Cannot locate pipeline'); 48 | } 49 | 50 | $routes = $this->getRoutes(); 51 | 52 | if (!$routes) { 53 | throw new MissingRoutesException('Cannot locate routes'); 54 | } 55 | 56 | // Execute programmatic/declarative middleware pipeline and routing 57 | // configuration statements 58 | 59 | $pipeLineRunner = require $pipeLine; 60 | $pipeLineRunner($this->application, $this->factory, $this->container); 61 | 62 | $routeRunner = require $routes; 63 | $routeRunner($this->application, $this->factory, $this->container); 64 | 65 | return true; 66 | } 67 | 68 | public function getPipeline() 69 | { 70 | if (file_exists($this->pipelineFile)) { 71 | return $this->pipelineFile; 72 | } 73 | 74 | return null; 75 | } 76 | 77 | public function getRoutes() 78 | { 79 | if (file_exists($this->routeFile)) { 80 | return $this->routeFile; 81 | } 82 | 83 | return null; 84 | } 85 | 86 | /** 87 | * @param $path 88 | * @throws MissingPipeLineException 89 | */ 90 | public function setPipelineFilePath($path) 91 | { 92 | if (!file_exists($path)) { 93 | throw new MissingPipeLineException($path.' does not exist or is not readable'); 94 | } 95 | 96 | $this->pipelineFile = $path; 97 | } 98 | 99 | /** 100 | * @param $path 101 | * @throws MissingRoutesException 102 | */ 103 | public function setRoutesFilePath($path) 104 | { 105 | if (!file_exists($path)) { 106 | throw new MissingRoutesException($path.' does not exist or is not readable'); 107 | } 108 | 109 | $this->routeFile = $path; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /tests/Bridge/Psr7RequestBuilderTest.php: -------------------------------------------------------------------------------- 1 | requestBuilder = new Psr7RequestBuilder(); 28 | $this->mockRequest = $this->createMock(SwooleRequest::class); 29 | } 30 | 31 | protected function buildUpMockRequest($data) 32 | { 33 | $this->mockRequest->fd = $data['fd']; 34 | $this->mockRequest->header = $data['header']; 35 | $this->mockRequest->server = $data['server']; 36 | $this->mockRequest->request = $data['request']; 37 | $this->mockRequest->cookie = $data['cookie']; 38 | $this->mockRequest->get = $data['get']; 39 | $this->mockRequest->files = $data['files']; 40 | $this->mockRequest->post = $data['post']; 41 | $this->mockRequest->tmpfiles = $data['tmpfiles']; 42 | } 43 | 44 | public function testToPsr7WithDefaults() 45 | { 46 | $psr7Request = $this->requestBuilder->build($this->mockRequest); 47 | $this->assertInstanceOf(ServerRequest::class, $psr7Request); 48 | } 49 | 50 | protected function headerTest($headers, ServerRequest $psr7Request) 51 | { 52 | foreach ($headers as $name => $value) { 53 | $this->assertEquals( 54 | $value, 55 | $psr7Request->getHeader($name)[0] 56 | ); 57 | } 58 | } 59 | 60 | public function testToPsr7WithValues() 61 | { 62 | $request = $this->getRequestMock(); 63 | $this->buildUpMockRequest($request); 64 | $this->mockRequest->expects($this->once()) 65 | ->method('rawcontent') 66 | ->willReturn(''); 67 | 68 | $psr7Request = $this->requestBuilder->build($this->mockRequest); 69 | $this->assertInstanceOf(ServerRequest::class, $psr7Request); 70 | 71 | $this->assertEquals( 72 | $request['files'] ?? [], 73 | $psr7Request->getUploadedFiles() 74 | ); 75 | 76 | $this->headerTest($request['header'], $psr7Request); 77 | } 78 | 79 | public function testToPsr7WithPostData() 80 | { 81 | $request = $this->getFormPostMock(); 82 | $this->buildUpMockRequest($request); 83 | $this->mockRequest->expects($this->once()) 84 | ->method('rawcontent') 85 | ->willReturn(''); 86 | 87 | $psr7Request = $this->requestBuilder->build($this->mockRequest); 88 | $this->assertInstanceOf(ServerRequest::class, $psr7Request); 89 | 90 | $this->assertEquals( 91 | $request['files'] ?? [], 92 | $psr7Request->getUploadedFiles() 93 | ); 94 | 95 | $this->headerTest($request['header'], $psr7Request); 96 | 97 | $this->assertEquals( 98 | $request['post'], 99 | $psr7Request->getParsedBody() 100 | ); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/Command/SwooleRunnerCommand.php: -------------------------------------------------------------------------------- 1 | app = $application; 46 | $this->setupRunner = $setupRunner; 47 | $this->requestBuilder = $requestBuilder; 48 | $this->responseEmitter = $responseEmitter; 49 | parent::__construct($name); 50 | } 51 | 52 | protected function configure() 53 | { 54 | $this->setName('swoole:expressive:runner') 55 | ->setDescription('Run Expressive inside Swoole web server') 56 | ->setHelp('This command will start a Swoole web server for Zend Expressive'); 57 | 58 | $this->addOption( 59 | 'host', 60 | 'i', 61 | InputOption::VALUE_OPTIONAL, 62 | 'Swoole host to listen to.', 63 | '0.0.0.0' 64 | ); 65 | 66 | $this->addOption( 67 | 'port', 68 | 'p', 69 | InputOption::VALUE_OPTIONAL, 70 | 'Swoole port number to listen on.', 71 | 8080 72 | ); 73 | } 74 | 75 | protected function execute(InputInterface $input, OutputInterface $output) 76 | { 77 | try { 78 | $this->setupRunner->execute(); 79 | } catch (SwooleExpressiveException $e) { 80 | $output->writeln($e->getMessage()); 81 | throw $e; 82 | } 83 | 84 | $host = (string) $input->getOption('host'); 85 | $port = (int) $input->getOption('port'); 86 | 87 | $http = new \swoole_http_server($host, $port); 88 | $app = $this->app; 89 | $requestBuilder = $this->requestBuilder; 90 | $responseEmitter = $this->responseEmitter; 91 | 92 | $http->on( 93 | 'request', 94 | function (Request $request, Response $response) use ($app, $requestBuilder, $responseEmitter) { 95 | $psrResponse = $app->handle($requestBuilder->build($request)); 96 | $responseEmitter->toSwoole($psrResponse, $response); 97 | } 98 | ); 99 | 100 | $http->start(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/Bridge/Psr7RequestBuilder.php: -------------------------------------------------------------------------------- 1 | rawcontent(); 15 | 16 | $body = new Stream('php://memory', 'r+b'); 17 | $body->write($rawContent); 18 | 19 | return new ServerRequest( 20 | $this->buildServerParams($swooleRequest), 21 | $swooleRequest->files ?? [], 22 | $swooleRequest->server['request_uri'] ?? null, 23 | $swooleRequest->server['request_method'] ?? null, 24 | $body, 25 | $swooleRequest->header ?? [], 26 | $swooleRequest->cookie ?? [], 27 | $swooleRequest->get ?? [], 28 | $swooleRequest->post ?? null, 29 | $swooleRequest->server['server_protocol'] ?? '1.1' 30 | ); 31 | } 32 | 33 | public function buildServerParams(SwooleRequest $swooleRequest) 34 | { 35 | $server = $swooleRequest->server ?? []; 36 | $header = $swooleRequest->header ?? []; 37 | 38 | $return['USER'] = get_current_user(); 39 | 40 | if (function_exists('posix_getpwuid')) { 41 | $return['USER'] = posix_getpwuid(posix_geteuid())['name']; 42 | } 43 | 44 | $return['HTTP_CACHE_CONTROL'] = $header['cache-control'] ?? ''; 45 | $return['HTTP_UPGRADE_INSECURE_REQUESTS'] = $header['upgrade-insecure-requests-control'] ?? ''; 46 | $return['HTTP_CONNECTION'] = $header['connection'] ?? ''; 47 | $return['HTTP_DNT'] = $header['dnt'] ?? ''; 48 | $return['HTTP_ACCEPT_ENCODING'] = $header['accept-encoding'] ?? ''; 49 | $return['HTTP_ACCEPT_LANGUAGE'] = $header['accept-accept-language'] ?? ''; 50 | $return['HTTP_ACCEPT'] = $header['accept'] ?? ''; 51 | $return['HTTP_USER_AGENT'] = $header['user-agent'] ?? ''; 52 | $return['HTTP_HOST'] = $header['user-host'] ?? ''; 53 | $return['SERVER_NAME'] = '_'; 54 | $return['SERVER_PORT'] = $server['server_port'] ?? null; 55 | $return['SERVER_ADDR'] = $server['server_addr'] ?? ''; 56 | $return['REMOTE_PORT'] = $server['remote_port'] ?? null; 57 | $return['REMOTE_ADDR'] = $server['remote_addr'] ?? ''; 58 | $return['SERVER_SOFTWARE'] = $server['server_software'] ?? ''; 59 | $return['GATEWAY_INTERFACE'] = $server['server_software'] ?? ''; 60 | $return['REQUEST_SCHEME'] = 'http'; 61 | $return['SERVER_PROTOCOL'] = $server['server_protocol'] ?? null; 62 | $return['DOCUMENT_ROOT'] = realpath(__DIR__.'/../../bin'); 63 | $return['DOCUMENT_URI'] = '/'; 64 | $return['REQUEST_URI'] = $server['request_uri'] ?? ''; 65 | $return['SCRIPT_NAME'] = '/swoole-expressive'; 66 | $return['CONTENT_LENGTH'] = $header['content-length'] ?? null; 67 | $return['CONTENT_TYPE'] = $header['content-type'] ?? null; 68 | $return['REQUEST_METHOD'] = $server['request_method'] ?? 'GET'; 69 | $return['QUERY_STRING'] = $server['query_string'] ?? ''; 70 | $return['SCRIPT_FILENAME'] = rtrim($return['DOCUMENT_ROOT'], '/').'/'.ltrim($return['SCRIPT_NAME']); 71 | $return['PATH_INFO'] = $server['path_info'] ?? ''; 72 | $return['FCGI_ROLE'] = 'RESPONDER'; 73 | $return['PHP_SELF'] = $return['PATH_INFO']; 74 | $return['REQUEST_TIME_FLOAT'] = $server['request_time_float'] ?? ''; 75 | $return['REQUEST_TIME'] = $server['request_time'] ?? ''; 76 | 77 | return $return; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /tests/Mock/RequestMockTrait.php: -------------------------------------------------------------------------------- 1 | 1, 12 | 'header' => [ 13 | 'host' => 'localhost:8080', 14 | 'user-agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:58.0) Gecko/20100101 Firefox/58.0', 15 | 'accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 16 | 'accept-language' => 'en-US,en;q=0.5', 17 | 'accept-encoding' => 'gzip, deflate', 18 | 'dnt' => '1', 19 | 'connection' => 'keep-alive', 20 | 'upgrade-insecure-requests' => '1', 21 | ], 22 | 'server' => [ 23 | 'request_method' => 'GET', 24 | 'request_uri' => '/', 25 | 'path_info' => '/', 26 | 'request_time' => 1518236599, 27 | 'request_time_float' => 1518236599.4486, 28 | 'server_port' => 8080, 29 | 'remote_port' => 55885, 30 | 'remote_addr' => '10.0.2.2', 31 | 'master_time' => 1518236599, 32 | 'server_protocol' => 'HTTP/1.1', 33 | 'server_software' => 'swoole-http-server', 34 | ], 35 | 'request' => null, 36 | 'cookie' => null, 37 | 'get' => null, 38 | 'files' => null, 39 | 'post' => null, 40 | 'tmpfiles' => null, 41 | ]; 42 | } 43 | 44 | public function getFormPostMock() 45 | { 46 | return [ 47 | 'fd' => 3, 48 | 'header' => [ 49 | 'cache-control' => 'no-cache', 50 | 'postman-token' => 'afe7fabc-adaf-4770-82ec-96e11e2ac407', 51 | 'user-agent' => 'PostmanRuntime/7.1.1', 52 | 'accept' => '*/*', 53 | 'host' => 'localhost:8080', 54 | 'accept-encoding' => 'gzip, deflate', 55 | 'content-type' => 'multipart/form-data; boundary=--------------------------166769271679051152714386', 56 | 'content-length' => '272', 57 | 'connection' => 'keep-alive', 58 | ], 59 | 'server' => [ 60 | 'request_method' => 'POST', 61 | 'request_uri' => '/', 62 | 'path_info' => '/', 63 | 'request_time' => 1518468402, 64 | 'request_time_float' => 1518468402.560589, 65 | 'server_port' => 8080, 66 | 'remote_port' => 49849, 67 | 'remote_addr' => '10.0.2.2', 68 | 'master_time' => 1518468402, 69 | 'server_protocol' => 'HTTP/1.1', 70 | 'server_software' => 'swoole-http-server', 71 | ], 72 | 'request' => null, 73 | 'cookie' => null, 74 | 'get' => null, 75 | 'files' => null, 76 | 'post' => [ 77 | 'test' => 'test', 78 | 'test2' => 'test2', 79 | ], 80 | 'tmpfiles' => null, 81 | ]; 82 | } 83 | 84 | public function getMockFilePost() 85 | { 86 | return [ 87 | 'fd' => 3, 88 | 'header' => [ 89 | 'content-type' => 'multipart/form-data; boundary=--------------------------300832713124378419925087', 90 | 'cache-control' => 'no-cache', 91 | 'postman-token' => '4670cf73-429b-478c-b985-baa9e4b72c07', 92 | 'user-agent' => 'PostmanRuntime/7.1.1', 93 | 'accept' => '*/*', 94 | 'host' => 'localhost:8080', 95 | 'accept-encoding' => 'gzip, deflate', 96 | 'content-length' => '95245', 97 | 'connection' => 'keep-alive', 98 | ], 99 | 'server' => [ 100 | 'request_method' => 'POST', 101 | 'request_uri' => '/', 102 | 'path_info' => '/', 103 | 'request_time' => 1518471625, 104 | 'request_time_float' => 1518471625.887792, 105 | 'server_port' => 8080, 106 | 'remote_port' => 49849, 107 | 'remote_addr' => '10.0.2.2', 108 | 'master_time' => 1518471625, 109 | 'server_protocol' => 'HTTP/1.1', 110 | 'server_software' => 'swoole-http-server', 111 | ], 112 | 'request' => null, 113 | 'cookie' => null, 114 | 'get' => null, 115 | 'files' => [ 116 | 'testfile' => [ 117 | 'name' => 'Screen Shot 2018-02-07 at 5.34.57 PM.png', 118 | 'type' => 'image/png', 119 | 'tmp_name' => '/tmp/swoole.upfile.LTq4xs', 120 | 'error' => 0, 121 | 'size' => 94895, 122 | ], 123 | ], 124 | 'post' => [ 125 | 'test2' => 'test2', 126 | ], 127 | 'tmpfiles' => [ 128 | 0 => '/tmp/swoole.upfile.LTq4xs', 129 | ], 130 | ]; 131 | } 132 | 133 | public function getMockRequestWithGetParams() 134 | { 135 | return [ 136 | 'fd' => 3, 137 | 'header' => [ 138 | 'cache-control' => 'no-cache', 139 | 'postman-token' => '8a650de7-f73d-4dd4-8c07-bfc3f10d9f33', 140 | 'user-agent' => 'PostmanRuntime/7.1.1', 141 | 'accept' => '*/*', 142 | 'host' => 'localhost:8080', 143 | 'accept-encoding' => 'gzip, deflate', 144 | 'connection' => 'keep-alive', 145 | ], 146 | 'server' => [ 147 | 'query_string' => 'test=1&test2=2&testarray[0]=param1&testarray[1]=param2', 148 | 'request_method' => 'GET', 149 | 'request_uri' => '/test-get-params', 150 | 'path_info' => '/test-get-params', 151 | 'request_time' => 1518471848, 152 | 'request_time_float' => 1518471849.429033, 153 | 'server_port' => 8080, 154 | 'remote_port' => 49849, 155 | 'remote_addr' => '10.0.2.2', 156 | 'master_time' => 1518471848, 157 | 'server_protocol' => 'HTTP/1.1', 158 | 'server_software' => 'swoole-http-server', 159 | ], 160 | 'request' => null, 161 | 'cookie' => null, 162 | 'get' => [ 163 | 'test' => '1', 164 | 'test2' => '2', 165 | 'testarray' => [ 166 | 0 => 'param1', 167 | 1 => 'param2', 168 | ], 169 | ], 170 | 'files' => null, 171 | 'post' => null, 172 | 'tmpfiles' => null, 173 | ]; 174 | } 175 | 176 | public function getMockRequestWithCookies() 177 | { 178 | [ 179 | 'fd' => 3, 180 | 'header' => [ 181 | 'cache-control' => 'no-cache', 182 | 'postman-token' => '8081f1ee-4445-4fd3-ab0e-1731eed0f239', 183 | 'user-agent' => 'PostmanRuntime/7.1.1', 184 | 'accept' => '*/*', 185 | 'host' => 'localhost:8080', 186 | 'accept-encoding' => 'gzip, deflate', 187 | 'connection' => 'keep-alive', 188 | ], 189 | 'server' => [ 190 | 'request_method' => 'GET', 191 | 'request_uri' => '/', 192 | 'path_info' => '/', 193 | 'request_time' => 1518471991, 194 | 'request_time_float' => 1518471992.58964, 195 | 'server_port' => 8080, 196 | 'remote_port' => 49849, 197 | 'remote_addr' => '10.0.2.2', 198 | 'master_time' => 1518471991, 199 | 'server_protocol' => 'HTTP/1.1', 200 | 'server_software' => 'swoole-http-server', 201 | ], 202 | 'request' => null, 203 | 'cookie' => [ 204 | 'Cookie_1' => 'value', 205 | ], 206 | 'get' => null, 207 | 'files' => null, 208 | 'post' => null, 209 | 'tmpfiles' => null, 210 | ]; 211 | } 212 | } 213 | --------------------------------------------------------------------------------