Skip to content

Commit 3d1a5c5

Browse files
authored
Adding Swoole (#11)
* Adding Swoole * Normalize composer * Hack namespace * Add extension
0 parents  commit 3d1a5c5

File tree

9 files changed

+237
-0
lines changed

9 files changed

+237
-0
lines changed

.github/FUNDING.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# These are supported funding model platforms
2+
3+
github: [nyholm]

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/vendor/
2+
composer.lock

README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Swoole Runtime
2+
3+
A runtime for [Swoole](https://www.swoole.co.uk/)
4+
5+
## Installation
6+
7+
```
8+
composer require runtime/swoole
9+
```
10+
11+
## Usage
12+
13+
Define the environment variable `APP_RUNTIME` for your application.
14+
15+
```
16+
APP_RUNTIME=Runtime\Swoole\Runtime
17+
```
18+
19+
### Pure PHP
20+
21+
```php
22+
// public/index.php
23+
24+
use Swoole\Http\Request;
25+
use Swoole\Http\Response;
26+
27+
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
28+
29+
return function () {
30+
return function (Request $request, Response $response) {
31+
$response->header("Content-Type", "text/plain");
32+
$response->end("Hello World\n");
33+
};
34+
};
35+
```
36+
37+
### Symfony
38+
39+
```php
40+
// public/index.php
41+
42+
use App\Kernel;
43+
44+
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
45+
46+
return function (array $context) {
47+
return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
48+
};
49+
```

composer.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"name": "runtime/swoole",
3+
"type": "library",
4+
"description": "Swoole runtime",
5+
"license": "MIT",
6+
"authors": [
7+
{
8+
"name": "Tobias Nyholm",
9+
"email": "[email protected]"
10+
}
11+
],
12+
"require": {
13+
"symfony/runtime": "5.x-dev"
14+
},
15+
"require-dev": {
16+
"swoole/ide-helper": "^4.6",
17+
"symfony/http-foundation": "^4.4 || ^5.2",
18+
"symfony/http-kernel": "^4.4 || ^5.2",
19+
"symfony/phpunit-bridge": "^5.2"
20+
},
21+
"autoload": {
22+
"psr-4": {
23+
"Runtime\\Swoole\\": "src/"
24+
}
25+
},
26+
"autoload-dev": {
27+
"psr-4": {
28+
"Runtime\\Swoole\\Tests\\": "tests/"
29+
}
30+
},
31+
"minimum-stability": "dev",
32+
"prefer-stable": true
33+
}

phpunit.xml.dist

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
4+
backupGlobals="false"
5+
colors="true"
6+
bootstrap="vendor/autoload.php"
7+
failOnRisky="true"
8+
failOnWarning="true"
9+
>
10+
<php>
11+
<ini name="error_reporting" value="-1"/>
12+
</php>
13+
<testsuites>
14+
<testsuite name="Test Suite">
15+
<directory>./tests</directory>
16+
<directory suffix=".phpt">./tests/phpt</directory>
17+
</testsuite>
18+
</testsuites>
19+
</phpunit>

src/Runner.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
namespace Runtime\Swoole;
4+
5+
use Swoole\Http\Server;
6+
use Symfony\Component\Runtime\RunnerInterface;
7+
8+
/**
9+
* A simple runner that will run a callable.
10+
*
11+
* @author Tobias Nyholm <[email protected]>
12+
*/
13+
class Runner implements RunnerInterface
14+
{
15+
private $application;
16+
private $port;
17+
private $host;
18+
19+
public function __construct(callable $application, $host, $port)
20+
{
21+
$this->application = $application;
22+
$this->host = $host;
23+
$this->port = $port;
24+
}
25+
26+
public function run(): int
27+
{
28+
$server = new Server($this->host, $this->port);
29+
30+
$server->on('request', $this->application);
31+
32+
$server->start();
33+
34+
return 0;
35+
}
36+
}

src/Runtime.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
namespace Runtime\Swoole;
4+
5+
use Symfony\Component\HttpKernel\HttpKernelInterface;
6+
use Symfony\Component\Runtime\RunnerInterface;
7+
use Symfony\Component\Runtime\SymfonyRuntime;
8+
9+
/**
10+
* A runtime for Swoole.
11+
*
12+
* @author Tobias Nyholm <[email protected]>
13+
*/
14+
class Runtime extends SymfonyRuntime
15+
{
16+
public function __construct(array $options)
17+
{
18+
$options['swoole_host'] = $options['swoole_host'] ?? $_SERVER['SWOOLE_HOST'] ?? $_ENV['SWOOLE_HOST'] ?? '127.0.0.1';
19+
$options['swoole_port'] = $options['swoole_port'] ?? $_SERVER['SWOOLE_PORT'] ?? $_ENV['SWOOLE_PORT'] ?? 8000;
20+
21+
parent::__construct($options);
22+
}
23+
24+
public function getRunner(?object $application): RunnerInterface
25+
{
26+
if (is_callable($application)) {
27+
return new Runner($application, $this->options['swoole_host'], $this->options['swoole_port']);
28+
}
29+
30+
if ($application instanceof HttpKernelInterface) {
31+
return new SymfonyRunner($application, $this->options['swoole_host'], $this->options['swoole_port']);
32+
}
33+
34+
return parent::getRunner($application);
35+
}
36+
}

src/SymfonyRunner.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
namespace Runtime\Swoole;
4+
5+
use Swoole\Http\Request;
6+
use Swoole\Http\Response;
7+
use Swoole\Http\Server;
8+
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
9+
use Symfony\Component\HttpKernel\HttpKernelInterface;
10+
use Symfony\Component\Runtime\RunnerInterface;
11+
12+
/**
13+
* A runner for Symfony.
14+
*
15+
* @author Tobias Nyholm <[email protected]>
16+
*/
17+
class SymfonyRunner implements RunnerInterface
18+
{
19+
private $application;
20+
private $port;
21+
private $host;
22+
23+
public function __construct(HttpKernelInterface $application, $host, $port)
24+
{
25+
$this->application = $application;
26+
$this->host = $host;
27+
$this->port = $port;
28+
}
29+
30+
public function run(): int
31+
{
32+
$server = new Server($this->host, $this->port);
33+
34+
$app = $this->application;
35+
36+
$server->on('request', function (Request $request, Response $response) use ($app) {
37+
// convert to HttpFoundation request
38+
$sfRequest = new SymfonyRequest(
39+
$request->get ?? [],
40+
$request->post ?? [],
41+
[],
42+
$request->cookie ?? [],
43+
$request->files ?? [],
44+
$request->server ?? [],
45+
$request->rawContent()
46+
);
47+
48+
$sfResponse = $app->handle($sfRequest);
49+
foreach ($sfResponse->headers->all() as $name => $value) {
50+
$response->header($name, $value);
51+
}
52+
$response->end($sfResponse->getContent());
53+
});
54+
55+
$server->start();
56+
57+
return 0;
58+
}
59+
}

tests/.gitignore

Whitespace-only changes.

0 commit comments

Comments
 (0)