summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Diactoros/ServerRequestFactory.php26
-rw-r--r--src/Diactoros/StreamFactory.php45
-rw-r--r--src/Diactoros/UploadedFileFactory.php35
-rw-r--r--src/Exception/RoadRunnerException.php2
-rw-r--r--src/HttpClient.php74
-rw-r--r--src/PSR7Client.php77
-rw-r--r--src/Worker.php4
7 files changed, 222 insertions, 41 deletions
diff --git a/src/Diactoros/ServerRequestFactory.php b/src/Diactoros/ServerRequestFactory.php
new file mode 100644
index 00000000..4d427121
--- /dev/null
+++ b/src/Diactoros/ServerRequestFactory.php
@@ -0,0 +1,26 @@
+<?php
+declare(strict_types=1);
+
+/**
+ * High-performance PHP process supervisor and load balancer written in Go
+ *
+ * @author Wolfy-J
+ */
+
+namespace Spiral\RoadRunner\Diactoros;
+
+use Psr\Http\Message\ServerRequestFactoryInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Zend\Diactoros\ServerRequest;
+
+final class ServerRequestFactory implements ServerRequestFactoryInterface
+{
+ /**
+ * @inheritdoc
+ */
+ public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface
+ {
+ $uploadedFiles = [];
+ return new ServerRequest($serverParams, $uploadedFiles, $uri, $method);
+ }
+} \ No newline at end of file
diff --git a/src/Diactoros/StreamFactory.php b/src/Diactoros/StreamFactory.php
new file mode 100644
index 00000000..6004ef11
--- /dev/null
+++ b/src/Diactoros/StreamFactory.php
@@ -0,0 +1,45 @@
+<?php
+declare(strict_types=1);
+
+/**
+ * High-performance PHP process supervisor and load balancer written in Go
+ *
+ * @author Wolfy-J
+ */
+
+namespace Spiral\RoadRunner\Diactoros;
+
+use Psr\Http\Message\StreamFactoryInterface;
+use Psr\Http\Message\StreamInterface;
+use Zend\Diactoros\Stream;
+
+final class StreamFactory implements StreamFactoryInterface
+{
+ /**
+ * @inheritdoc
+ */
+ public function createStream(string $content = ''): StreamInterface
+ {
+ $resource = fopen('php://temp', 'r+');
+ fwrite($resource, $content);
+ rewind($resource);
+ return $this->createStreamFromResource($resource);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function createStreamFromFile(string $file, string $mode = 'r'): StreamInterface
+ {
+ $resource = fopen($file, $mode);
+ return $this->createStreamFromResource($resource);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function createStreamFromResource($resource): StreamInterface
+ {
+ return new Stream($resource);
+ }
+} \ No newline at end of file
diff --git a/src/Diactoros/UploadedFileFactory.php b/src/Diactoros/UploadedFileFactory.php
new file mode 100644
index 00000000..1543a826
--- /dev/null
+++ b/src/Diactoros/UploadedFileFactory.php
@@ -0,0 +1,35 @@
+<?php
+declare(strict_types=1);
+
+/**
+ * High-performance PHP process supervisor and load balancer written in Go
+ *
+ * @author Wolfy-J
+ */
+
+namespace Spiral\RoadRunner\Diactoros;
+
+use Psr\Http\Message\StreamInterface;
+use Psr\Http\Message\UploadedFileFactoryInterface;
+use Psr\Http\Message\UploadedFileInterface;
+use Zend\Diactoros\UploadedFile;
+
+final class UploadedFileFactory implements UploadedFileFactoryInterface
+{
+ /**
+ * @inheritdoc
+ */
+ public function createUploadedFile(
+ StreamInterface $stream,
+ int $size = null,
+ int $error = \UPLOAD_ERR_OK,
+ string $clientFilename = null,
+ string $clientMediaType = null
+ ): UploadedFileInterface {
+ if ($size === null) {
+ $size = $stream->getSize();
+ }
+
+ return new UploadedFile($stream, $size, $error, $clientFilename, $clientMediaType);
+ }
+} \ No newline at end of file
diff --git a/src/Exception/RoadRunnerException.php b/src/Exception/RoadRunnerException.php
index ee99bb2b..7c5c5929 100644
--- a/src/Exception/RoadRunnerException.php
+++ b/src/Exception/RoadRunnerException.php
@@ -1,4 +1,6 @@
<?php
+declare(strict_types=1);
+
/**
* High-performance PHP process supervisor and load balancer written in Go
*
diff --git a/src/HttpClient.php b/src/HttpClient.php
new file mode 100644
index 00000000..e469dd30
--- /dev/null
+++ b/src/HttpClient.php
@@ -0,0 +1,74 @@
+<?php
+declare(strict_types=1);
+
+/**
+ * High-performance PHP process supervisor and load balancer written in Go
+ *
+ * @author Alex Bond
+ */
+
+namespace Spiral\RoadRunner;
+
+class HttpClient
+{
+ /** @var Worker */
+ private $worker;
+
+ /**
+ * @param Worker $worker
+ */
+ public function __construct(Worker $worker)
+ {
+ $this->worker = $worker;
+ }
+
+ /**
+ * @return Worker
+ */
+ public function getWorker(): Worker
+ {
+ return $this->worker;
+ }
+
+ /**
+ * @return array|null Request information as ['ctx'=>[], 'body'=>string] or null if termination request or invalid context.
+ */
+ public function acceptRequest()
+ {
+ $body = $this->getWorker()->receive($ctx);
+ if (empty($body) && empty($ctx)) {
+ // termination request
+ return null;
+ }
+
+ $ctx = json_decode($ctx, true);
+ if (is_null($ctx)) {
+ // invalid context
+ return null;
+ }
+
+ return ['ctx' => $ctx, 'body' => $body];
+ }
+
+ /**
+ * Send response to the application server.
+ *
+ * @param int $status Http status code
+ * @param string $body Body of response
+ * @param string[][] $headers An associative array of the message's headers. Each
+ * key MUST be a header name, and each value MUST be an array of strings
+ * for that header.
+ */
+ public function respond(int $status, string $body, array $headers = [])
+ {
+ if (empty($headers)) {
+ // this is required to represent empty header set as map and not as array
+ $headers = new \stdClass();
+ }
+
+ $this->getWorker()->send(
+ $body,
+ json_encode(['status' => $status, 'headers' => $headers])
+ );
+ }
+}
diff --git a/src/PSR7Client.php b/src/PSR7Client.php
index 0b148884..8229b7d5 100644
--- a/src/PSR7Client.php
+++ b/src/PSR7Client.php
@@ -1,4 +1,6 @@
<?php
+declare(strict_types=1);
+
/**
* High-performance PHP process supervisor and load balancer written in Go
*
@@ -7,7 +9,6 @@
namespace Spiral\RoadRunner;
-use Http\Factory\Diactoros;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestFactoryInterface;
use Psr\Http\Message\ServerRequestInterface;
@@ -19,8 +20,8 @@ use Psr\Http\Message\UploadedFileFactoryInterface;
*/
class PSR7Client
{
- /** @var Worker */
- private $worker;
+ /** @var HttpClient */
+ private $httpClient;
/** @var ServerRequestFactoryInterface */
private $requestFactory;
@@ -31,6 +32,8 @@ class PSR7Client
/*** @var UploadedFileFactoryInterface */
private $uploadsFactory;
+ private $originalServer = [];
+
/** @var array Valid values for HTTP protocol version */
private static $allowedVersions = ['1.0', '1.1', '2',];
@@ -46,10 +49,11 @@ class PSR7Client
StreamFactoryInterface $streamFactory = null,
UploadedFileFactoryInterface $uploadsFactory = null
) {
- $this->worker = $worker;
+ $this->httpClient = new HttpClient($worker);
$this->requestFactory = $requestFactory ?? new Diactoros\ServerRequestFactory();
$this->streamFactory = $streamFactory ?? new Diactoros\StreamFactory();
$this->uploadsFactory = $uploadsFactory ?? new Diactoros\UploadedFileFactory();
+ $this->originalServer = $_SERVER;
}
/**
@@ -57,7 +61,7 @@ class PSR7Client
*/
public function getWorker(): Worker
{
- return $this->worker;
+ return $this->httpClient->getWorker();
}
/**
@@ -65,46 +69,40 @@ class PSR7Client
*/
public function acceptRequest()
{
- $body = $this->worker->receive($ctx);
- if (empty($body) && empty($ctx)) {
- // termination request
- return null;
- }
-
- if (empty($ctx = json_decode($ctx, true))) {
- // invalid context
+ $rawRequest = $this->httpClient->acceptRequest();
+ if ($rawRequest === null) {
return null;
}
- $_SERVER = $this->configureServer($ctx);
+ $_SERVER = $this->configureServer($rawRequest['ctx']);
$request = $this->requestFactory->createServerRequest(
- $ctx['method'],
- $ctx['uri'],
+ $rawRequest['ctx']['method'],
+ $rawRequest['ctx']['uri'],
$_SERVER
);
- parse_str($ctx['rawQuery'], $query);
+ parse_str($rawRequest['ctx']['rawQuery'], $query);
$request = $request
- ->withProtocolVersion(static::fetchProtocolVersion($ctx['protocol']))
- ->withCookieParams($ctx['cookies'])
+ ->withProtocolVersion(static::fetchProtocolVersion($rawRequest['ctx']['protocol']))
+ ->withCookieParams($rawRequest['ctx']['cookies'])
->withQueryParams($query)
- ->withUploadedFiles($this->wrapUploads($ctx['uploads']));
+ ->withUploadedFiles($this->wrapUploads($rawRequest['ctx']['uploads']));
- foreach ($ctx['attributes'] as $name => $value) {
+ foreach ($rawRequest['ctx']['attributes'] as $name => $value) {
$request = $request->withAttribute($name, $value);
}
- foreach ($ctx['headers'] as $name => $value) {
+ foreach ($rawRequest['ctx']['headers'] as $name => $value) {
$request = $request->withHeader($name, $value);
}
- if ($ctx['parsed']) {
- $request = $request->withParsedBody(json_decode($body, true));
+ if ($rawRequest['ctx']['parsed']) {
+ $request = $request->withParsedBody(json_decode($rawRequest['body'], true));
} else {
- if ($body !== null) {
- $request = $request->withBody($this->streamFactory->createStream($body));
+ if ($rawRequest['body'] !== null) {
+ $request = $request->withBody($this->streamFactory->createStream($rawRequest['body']));
}
}
@@ -118,16 +116,11 @@ class PSR7Client
*/
public function respond(ResponseInterface $response)
{
- $headers = $response->getHeaders();
- if (empty($headers)) {
- // this is required to represent empty header set as map and not as array
- $headers = new \stdClass();
- }
-
- $this->worker->send($response->getBody(), json_encode([
- 'status' => $response->getStatusCode(),
- 'headers' => $headers
- ]));
+ $this->httpClient->respond(
+ $response->getStatusCode(),
+ $response->getBody()->__toString(),
+ $response->getHeaders()
+ );
}
/**
@@ -139,15 +132,19 @@ class PSR7Client
*/
protected function configureServer(array $ctx): array
{
- $server = $_SERVER;
+ $server = $this->originalServer;
$server['REQUEST_TIME'] = time();
$server['REQUEST_TIME_FLOAT'] = microtime(true);
$server['REMOTE_ADDR'] = $ctx['attributes']['ipAddress'] ?? $ctx['remoteAddr'] ?? '127.0.0.1';
- $server['REMOTE_ADDR'] = $ctx['attributes']['ipAddress'] ?? $ctx['remoteAddr'] ?? '127.0.0.1';
$server['HTTP_USER_AGENT'] = '';
- if (isset($ctx['headers']['User-Agent'][0])) {
- $server['HTTP_USER_AGENT'] = $ctx['headers']['User-Agent'][0];
+ foreach ($ctx['headers'] as $key => $value) {
+ $key = strtoupper(str_replace('-', '_', $key));
+ if (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH'])) {
+ $server[$key] = implode(', ', $value);
+ } else {
+ $server['HTTP_' . $key] = implode(', ', $value);
+ }
}
return $server;
diff --git a/src/Worker.php b/src/Worker.php
index 7f92a714..da80e461 100644
--- a/src/Worker.php
+++ b/src/Worker.php
@@ -1,4 +1,6 @@
<?php
+declare(strict_types=1);
+
/**
* High-performance PHP process supervisor and load balancer written in Go
*
@@ -132,7 +134,7 @@ class Worker
*
* @throws RoadRunnerException
*/
- private function handleControl(string $body = null, &$header = null, int $flags): bool
+ private function handleControl(string $body = null, &$header = null, int $flags = 0): bool
{
$header = $body;
if (is_null($body) || $flags & Relay::PAYLOAD_RAW) {