Skip to content

Commit f185ea0

Browse files
committed
Add proto to request converter; add the roadrunner-php/roadrunner-api-dto package
1 parent c6aef2a commit f185ea0

File tree

2 files changed

+77
-5
lines changed

2 files changed

+77
-5
lines changed

composer.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,14 @@
4242
"psr/http-factory": "^1.0.1",
4343
"psr/http-message": "^1.0.1 || ^2.0",
4444
"spiral/roadrunner": "^2023.3",
45-
"spiral/roadrunner-worker": "^3.1.0"
45+
"spiral/roadrunner-worker": "^3.3.0"
4646
},
4747
"require-dev": {
4848
"buggregator/trap": "^1.0",
4949
"jetbrains/phpstorm-attributes": "^1.0",
5050
"nyholm/psr7": "^1.3",
5151
"phpunit/phpunit": "^10.0",
52+
"roadrunner-php/roadrunner-api-dto": "^1.4",
5253
"symfony/process": "^6.2",
5354
"symfony/var-dumper": "^6.3",
5455
"vimeo/psalm": "^5.9"
@@ -73,7 +74,8 @@
7374
"analyze": "psalm"
7475
},
7576
"suggest": {
76-
"spiral/roadrunner-cli": "Provides RoadRunner installation and management CLI tools"
77+
"spiral/roadrunner-cli": "Provides RoadRunner installation and management CLI tools",
78+
"ext-protobuf": "Provides Protocol Buffers support"
7779
},
7880
"config": {
7981
"sort-packages": true

src/HttpWorker.php

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
namespace Spiral\RoadRunner\Http;
66

77
use Generator;
8+
use RoadRunner\HTTP\DTO\V1BETA1\FileUpload;
9+
use RoadRunner\HTTP\DTO\V1BETA1\HeaderValue;
10+
use RoadRunner\HTTP\DTO\V1BETA1\Request as RequestProto;
11+
use Spiral\RoadRunner\Encoding;
812
use Spiral\RoadRunner\Http\Exception\StreamStoppedException;
913
use Spiral\RoadRunner\Message\Command\StreamStop;
1014
use Spiral\RoadRunner\Payload;
@@ -56,10 +60,17 @@ public function waitRequest(): ?Request
5660
return null;
5761
}
5862

63+
if ($payload->encoding === Encoding::Protobuf) {
64+
$message = new RequestProto();
65+
$message->mergeFromString($payload->body);
66+
67+
return $this->requestFromProto($message);
68+
}
69+
5970
/** @var RequestContext $context */
6071
$context = \json_decode($payload->header, true, 512, \JSON_THROW_ON_ERROR);
6172

62-
return $this->createRequest($payload->body, $context);
73+
return $this->arrayToRequest($payload->body, $context);
6374
}
6475

6576
/**
@@ -134,7 +145,7 @@ private function respondStream(int $status, Generator $body, array $headers = []
134145
/**
135146
* @param RequestContext $context
136147
*/
137-
private function createRequest(string $body, array $context): Request
148+
private function arrayToRequest(string $body, array $context): Request
138149
{
139150
\parse_str($context['rawQuery'], $query);
140151
return new Request(
@@ -154,6 +165,47 @@ private function createRequest(string $body, array $context): Request
154165
);
155166
}
156167

168+
private function requestFromProto(RequestProto $message): Request
169+
{
170+
$headers = $this->headerValueToArray($message->getHeader());
171+
$uploadedFiles = [];
172+
173+
/**
174+
* @var non-empty-string $name
175+
* @var FileUpload $uploads
176+
*/
177+
foreach ($message->getUploads() as $name => $uploads) {
178+
$uploadedFiles[$name] = [
179+
'name' => $uploads->getName(),
180+
'mime' => $uploads->getMime(),
181+
'size' => $uploads->getSize(),
182+
'error' => $uploads->getError(),
183+
'tmpName' => $uploads->getTempFilename(),
184+
];
185+
}
186+
187+
\parse_str($message->getRawQuery(), $query);
188+
return new Request(
189+
remoteAddr: $message->getRemoteAddr(),
190+
protocol: $message->getProtocol(),
191+
method: $message->getMethod(),
192+
uri: $message->getUri(),
193+
headers: $this->filterHeaders($headers),
194+
cookies: \array_map(
195+
static fn(array $values) => \implode(',', $values),
196+
$this->headerValueToArray($message->getCookies()),
197+
),
198+
uploads: $uploadedFiles,
199+
attributes: [
200+
Request::PARSED_BODY_ATTRIBUTE_NAME => $message->getParsed(),
201+
] + \iterator_to_array($message->getAttributes()),
202+
query: $query,
203+
// todo rawBody?
204+
body: $message->getBody(),
205+
parsed: $message->getParsed(),
206+
);
207+
}
208+
157209
/**
158210
* Remove all non-string and empty-string keys
159211
*
@@ -164,7 +216,7 @@ private function filterHeaders(array $headers): array
164216
{
165217
foreach ($headers as $key => $_) {
166218
if (!\is_string($key) || $key === '') {
167-
// ignore invalid header names or values (otherwise, the worker will be crashed)
219+
// ignore invalid header names or values (otherwise, the worker might be crashed)
168220
// @see: <https://git.io/JzjgJ>
169221
unset($headers[$key]);
170222
}
@@ -173,4 +225,22 @@ private function filterHeaders(array $headers): array
173225
/** @var HeadersList $headers */
174226
return $headers;
175227
}
228+
229+
/**
230+
* @param \Traversable<non-empty-string, HeaderValue> $message
231+
* @return HeadersList
232+
*/
233+
private function headerValueToArray(\Traversable $message): array
234+
{
235+
$result = [];
236+
/**
237+
* @var non-empty-string $key
238+
* @var HeaderValue $value
239+
*/
240+
foreach ($message as $key => $value) {
241+
$result[$key] = \iterator_to_array($value->getValue());
242+
}
243+
244+
return $result;
245+
}
176246
}

0 commit comments

Comments
 (0)