Skip to content

Commit c7d231d

Browse files
committed
Improve http worker types
1 parent 446ece8 commit c7d231d

File tree

1 file changed

+76
-43
lines changed

1 file changed

+76
-43
lines changed

src/HttpWorker.php

Lines changed: 76 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,45 @@
11
<?php
22

33
/**
4-
* High-performance PHP process supervisor and load balancer written in Go. Http core.
4+
* This file is part of RoadRunner package.
55
*
6-
* @author Alex Bond
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
78
*/
89

910
declare(strict_types=1);
1011

1112
namespace Spiral\RoadRunner\Http;
1213

14+
use Spiral\RoadRunner\Payload;
1315
use Spiral\RoadRunner\WorkerInterface;
1416

17+
/**
18+
* @psalm-import-type HeadersList from Request
19+
* @psalm-import-type AttributesList from Request
20+
* @psalm-import-type UploadedFilesList from Request
21+
* @psalm-import-type CookiesList from Request
22+
*
23+
* @psalm-type RequestContext = array {
24+
* remoteAddr?: string,
25+
* protocol?: string,
26+
* method?: string,
27+
* uri?: string,
28+
* attributes?: AttributesList,
29+
* headers?: HeadersList,
30+
* cookies?: CookiesList,
31+
* uploads?: UploadedFilesList|null,
32+
* rawQuery?: string,
33+
* parsed?: string|null
34+
* }
35+
*
36+
* @see Request
37+
*/
1538
class HttpWorker implements HttpWorkerInterface
1639
{
17-
/** @var WorkerInterface */
40+
/**
41+
* @var WorkerInterface
42+
*/
1843
private WorkerInterface $worker;
1944

2045
/**
@@ -34,73 +59,81 @@ public function getWorker(): WorkerInterface
3459
}
3560

3661
/**
37-
* Wait for incoming http request.
38-
*
39-
* @return Request|null
62+
* {@inheritDoc}
63+
* @throws \JsonException
4064
*/
4165
public function waitRequest(): ?Request
4266
{
43-
$payload = $this->getWorker()->waitPayload();
44-
if (empty($payload->body) && empty($payload->header)) {
45-
// termination request
67+
$payload = $this->worker->waitPayload();
68+
69+
// Termination request
70+
if ($payload === null || (!$payload->body && !$payload->header)) {
4671
return null;
4772
}
4873

49-
$request = new Request();
50-
$request->body = $payload->body;
74+
/** @var RequestContext $context */
75+
$context = \json_decode($payload->header, true, 512, \JSON_THROW_ON_ERROR);
5176

52-
$context = json_decode($payload->header, true);
53-
if ($context === null) {
54-
// invalid context
55-
return null;
56-
}
77+
return $this->createRequest($payload->body, $context);
78+
}
5779

58-
$this->hydrateRequest($request, $context);
80+
/**
81+
* {@inheritDoc}
82+
* @throws \JsonException
83+
*/
84+
public function respond(int $status, string $body, array $headers = []): void
85+
{
86+
$headers = (string)\json_encode([
87+
'status' => $status,
88+
'headers' => $headers ?: (object)[],
89+
], \JSON_THROW_ON_ERROR);
5990

60-
return $request;
91+
$this->worker->respond(new Payload($body, $headers));
6192
}
6293

6394
/**
64-
* Send response to the application server.
95+
* @param string $body
96+
* @param RequestContext $context
97+
* @return Request
6598
*
66-
* @param int $status Http status code
67-
* @param string $body Body of response
68-
* @param string[][] $headers An associative array of the message's headers. Each
69-
* key MUST be a header name, and each value MUST be an array of strings
70-
* for that header.
99+
* @psalm-suppress InaccessibleProperty
71100
*/
72-
public function respond(int $status, string $body, array $headers = []): void
101+
private function createRequest(string $body, array $context): Request
73102
{
74-
if ($headers === []) {
75-
// this is required to represent empty header set as map and not as array
76-
$headers = new \stdClass();
77-
}
103+
$request = new Request();
104+
$request->body = $body;
78105

79-
$this->getWorker()->send(
80-
$body,
81-
(string) json_encode(['status' => $status, 'headers' => $headers])
82-
);
106+
$this->hydrateRequest($request, $context);
107+
108+
return $request;
83109
}
84110

85111
/**
86112
* @param Request $request
87-
* @param array $context
113+
* @param RequestContext $context
114+
*
115+
* @psalm-suppress InaccessibleProperty
116+
* @psalm-suppress PossiblyUndefinedArrayOffset
117+
* @psalm-suppress MixedPropertyTypeCoercion
88118
*/
89119
private function hydrateRequest(Request $request, array $context): void
90120
{
121+
assert(\is_string($context['remoteAddr'] ?? null), 'Missing remote address context argument');
122+
assert(\is_string($context['protocol'] ?? null), 'Missing protocol context argument');
123+
assert(\is_string($context['method'] ?? null), 'Missing method context argument');
124+
assert(\is_string($context['uri'] ?? null), 'Missing uri context argument');
125+
assert(\is_string($context['rawQuery'] ?? null), 'Missing rawQuery context argument');
126+
91127
$request->remoteAddr = $context['remoteAddr'];
92128
$request->protocol = $context['protocol'];
93129
$request->method = $context['method'];
94130
$request->uri = $context['uri'];
95-
$request->attributes = $context['attributes'] ?? [];
96-
$request->headers = $context['headers'];
97-
$request->cookies = $context['cookies'] ?? [];
98-
$request->uploads = $context['uploads'] ?? [];
99-
100-
$request->query = [];
101-
parse_str($context['rawQuery'], $request->query);
131+
\parse_str($context['rawQuery'], $request->query);
102132

103-
// indicates that body was parsed
104-
$request->parsed = $context['parsed'];
133+
$request->attributes = (array)($context['attributes'] ?? []);
134+
$request->headers = (array)($context['headers'] ?? []);
135+
$request->cookies = (array)($context['cookies'] ?? []);
136+
$request->uploads = (array)($context['uploads'] ?? []);
137+
$request->parsed = (bool)$context['parsed'];
105138
}
106139
}

0 commit comments

Comments
 (0)