Skip to content

Commit bae4bea

Browse files
author
Radovan Kepák
authored
RequestFactory was refactored (#8)
1 parent 1170bc5 commit bae4bea

9 files changed

+692
-101
lines changed

config/roadrunner.neon

+4
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,7 @@ extensions:
33

44
roadrunner:
55
showExceptions: true
6+
middlewares:
7+
- TracyMiddleware
8+
- SessionMiddleware
9+
- PsrApplication

phpstan.neon

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
parameters:
2-
level: 7
3-
2+
checkGenericClassInNonGenericObjectType: false
3+
level: 5
44
paths:
55
- src

src/DI/Extension.php

+43
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
namespace Mallgroup\RoadRunner\DI;
66

7+
use Mallgroup\RoadRunner\PsrChain;
78
use Nette;
9+
use Nette\Http\Session;
10+
use Tracy;
811
use Nette\Schema\Expect;
912
use Nette\Schema\Schema;
1013
use Nyholm\Psr7\Factory\Psr17Factory;
@@ -76,5 +79,45 @@ public function loadConfiguration()
7679
->setFactory(PsrApplication::class)
7780
->addSetup('$catchExceptions', [$config->catchExceptions])
7881
->addSetup('$errorPresenter', [$config->errorPresenter]);
82+
83+
# Session should be ours, to support RR
84+
/** @var Nette\DI\Definitions\ServiceDefinition $sessionDefinition */
85+
$sessionDefinition = $builder->getDefinitionByType(Session::class);
86+
$sessionDefinition->setFactory(\Mallgroup\RoadRunner\Http\Session::class)
87+
->setType(\Mallgroup\RoadRunner\Http\Session::class);
7988
}
89+
90+
public function beforeCompile()
91+
{
92+
$builder = $this->getContainerBuilder();
93+
94+
# Setup blueScreen if possible
95+
if ($builder->getByType(Tracy\BlueScreen::class)) {
96+
/** @var Nette\DI\Definitions\ServiceDefinition $serviceDefinition */
97+
$serviceDefinition = $builder->getDefinition($this->prefix('application'));
98+
$serviceDefinition->addSetup([self::class, 'initializeBlueScreenPanel']);
99+
}
100+
}
101+
102+
/** @internal */
103+
public static function initializeBlueScreenPanel(
104+
Tracy\BlueScreen $blueScreen,
105+
Nette\Http\IRequest $httpRequest,
106+
Nette\Http\IResponse $httpResponse,
107+
PsrApplication $application,
108+
): void {
109+
$blueScreen->addPanel(function (?\Throwable $e) use ($application, $blueScreen, $httpResponse, $httpRequest): ?array {
110+
/** @psalm-suppress InternalMethod */
111+
$dumper = $blueScreen->getDumper();
112+
return $e ? null : [
113+
'tab' => 'Psr Application',
114+
'panel' => '<h3>Requests</h3>' . $dumper($application->getRequests())
115+
. '<h3>Presenter</h3>' . $dumper($application->getPresenter())
116+
. '<h3>Http/Request</h3>' . $dumper($httpRequest)
117+
. '<h3>Http/Response</h3>' . $dumper($httpResponse),
118+
];
119+
});
120+
}
121+
122+
/** Nette\Http\Helpers::initCookie(self::$defaultHttpRequest, new Nette\Http\Response); */
80123
}

src/Http/Request.php

+1-2
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,11 @@ class Request implements IRequest
1414
public function __construct(
1515
private RequestFactory $requestFactory
1616
) {
17-
$this->request = $this->requestFactory->fromRequest();
1817
}
1918

2019
public function updateFromPsr(ServerRequestInterface $request): void
2120
{
22-
$this->request = $this->requestFactory->fromPsr($request);
21+
$this->request = $this->requestFactory->getRequest($request);
2322
}
2423

2524
public function getUrl(): Http\UrlScript

src/Http/RequestFactory.php

+54-58
Original file line numberDiff line numberDiff line change
@@ -11,61 +11,42 @@
1111
use Nette\Http\UrlScript;
1212
use Psr\Http\Message\ServerRequestInterface;
1313
use Psr\Http\Message\UploadedFileInterface;
14-
use Psr\Http\Message\UriInterface;
1514

16-
/**
17-
* TODO: Polish this a bit more, this is just ugly code to make this works
18-
*/
1915
class RequestFactory
2016
{
2117
/** @var string[] */
2218
private array $proxies = [];
23-
private static ServerRequestInterface $request;
2419

2520
/** @param string[] $proxies */
2621
public function setProxy(array $proxies): void
2722
{
2823
$this->proxies = $proxies;
2924
}
3025

31-
public static function setRequest(ServerRequestInterface $request): void
26+
public function getRequest(ServerRequestInterface $request): Request
3227
{
33-
self::$request = $request;
34-
}
35-
36-
public static function fromRequest(ServerRequestInterface $request = null): Request
37-
{
38-
return (new RequestFactory())->fromPsr($request ?: self::$request);
39-
}
40-
41-
public function fromPsr(ServerRequestInterface $request): Request
42-
{
43-
$uri = $request->getUri();
44-
$url = $this->createUrlFromRequest($request);
45-
$url->setQuery($uri->getQuery());
46-
47-
$this->setAuthorization($url, $uri);
28+
$url = $this->createUrl($request);
4829

49-
[$remoteAddr, $remoteHost] = $this->resolveClientAttributes($request, $url);
30+
[$remoteAddr, $remoteHost] = $this->resolveClientAttributes($url, $request);
5031

5132
return new Request(
52-
new UrlScript($url, $this->getScriptPath($url)),
53-
(array)$request->getParsedBody(),
54-
$this->mapUploadedFiles($request->getUploadedFiles()),
33+
new UrlScript($url, $this->getScriptPath($url, $request)),
34+
$this->getPost($request),
35+
$this->getUploadedFiles($request),
5536
$request->getCookieParams(),
56-
$this->mapHeaders($request->getHeaders()),
37+
$this->getHeaders($request),
5738
$request->getMethod(),
5839
$remoteAddr,
5940
$remoteHost,
60-
fn(): string => (string)$request->getBody()
41+
fn(): string => (string) $request->getBody()
6142
);
6243
}
6344

64-
private function getScriptPath(Url $url): string
45+
private function getScriptPath(Url $url, ServerRequestInterface $request): string
6546
{
6647
$path = $url->getPath();
6748
$lpath = strtolower($path);
68-
$script = strtolower($_SERVER['SCRIPT_NAME'] ?? '');
49+
$script = strtolower($request->getServerParams()['SCRIPT_NAME'] ?? '');
6950
if ($lpath !== $script) {
7051
$max = min(strlen($lpath), strlen($script));
7152
for ($i = 0; $i < $max && $lpath[$i] === $script[$i]; $i++) ;
@@ -79,15 +60,18 @@ private function getScriptPath(Url $url): string
7960
/**
8061
* @return string[]
8162
*/
82-
private function resolveClientAttributes(ServerRequestInterface $request, Url $url): array
63+
private function resolveClientAttributes(Url $url, ServerRequestInterface $request): array
8364
{
8465
$serverParams = $request->getServerParams();
66+
8567
$remoteAddr = $serverParams['REMOTE_ADDR'] ?? ($request->getHeader('REMOTE_ADDR')[0] ?? null);
8668
$remoteHost = $serverParams['REMOTE_HOST'] ?? ($request->getHeader('REMOTE_HOST')[0] ?? null);
8769

88-
$usingTrustedProxy = $remoteAddr && !empty(array_filter($this->proxies, function (string $proxy) use ($remoteAddr): bool {
89-
return Helpers::ipMatch($remoteAddr, $proxy);
90-
}));
70+
$usingTrustedProxy = $remoteAddr
71+
&& !empty(array_filter(
72+
$this->proxies,
73+
fn (string $proxy): bool => Helpers::ipMatch($remoteAddr, $proxy)
74+
));
9175

9276
if ($usingTrustedProxy) {
9377
[$remoteAddr, $remoteHost] = empty($request->getHeader('HTTP_FORWARDED'))
@@ -159,7 +143,9 @@ private function useNonstandardProxy(
159143
): array {
160144

161145
if (isset($request->getHeader('HTTP_X_FORWARDED_PROTO')[0])) {
162-
$url->setScheme(strcasecmp($request->getHeader('HTTP_X_FORWARDED_PROTO')[0], 'https') === 0 ? 'https' : 'http');
146+
$url->setScheme(
147+
strcasecmp($request->getHeader('HTTP_X_FORWARDED_PROTO')[0], 'https') === 0 ? 'https' : 'http'
148+
);
163149
$url->setPort($url->getScheme() === 'https' ? 443 : 80);
164150
}
165151

@@ -172,7 +158,8 @@ private function useNonstandardProxy(
172158
$request->getHeader('HTTP_X_FORWARDED_FOR'),
173159
function (string $ip): bool {
174160
return !array_filter($this->proxies, function (string $proxy) use ($ip): bool {
175-
return filter_var(trim($ip), FILTER_VALIDATE_IP) !== false && Helpers::ipMatch(trim($ip), $proxy);
161+
return filter_var(trim($ip), FILTER_VALIDATE_IP) !== false
162+
&& Helpers::ipMatch(trim($ip), $proxy);
176163
});
177164
}
178165
);
@@ -193,25 +180,9 @@ function (string $ip): bool {
193180
return [$remoteAddr, $remoteHost];
194181
}
195182

196-
private function createUrlFromRequest(ServerRequestInterface $request): Url
183+
private function setAuthorization(Url $url, string $user): void
197184
{
198-
$url = new Url;
199-
$uri = $request->getUri();
200-
201-
$url->setScheme($uri->getScheme());
202-
$url->setHost($uri->getHost());
203-
$url->setPort($uri->getPort());
204-
$url->setPath($uri->getPath());
205-
$url->setQuery($uri->getQuery());
206-
207-
return $url;
208-
}
209-
210-
private function setAuthorization(Url $url, UriInterface $uri): void
211-
{
212-
$user = $uri->getUserInfo();
213185
$pass = '';
214-
215186
if (str_contains($user, ':')) {
216187
[$user, $pass] = explode(':', $user, 2);
217188
}
@@ -221,25 +192,50 @@ private function setAuthorization(Url $url, UriInterface $uri): void
221192
}
222193

223194
/**
224-
* @param array<string, string[]> $headers
225195
* @return array<string, string>
226196
*/
227-
private function mapHeaders(array $headers): array
197+
private function getHeaders(ServerRequestInterface $request): array
228198
{
229-
return array_map(static fn(array $header) => implode("\n", $header), $headers);
199+
return array_map(
200+
static fn(array $header) => implode("\n", $header),
201+
$request->getHeaders()
202+
);
230203
}
231204

232205
/**
233-
* @param UploadedFileInterface[] $uploadedFiles
234206
* @return FileUpload[]
235207
*/
236-
private function mapUploadedFiles(array $uploadedFiles): array
208+
private function getUploadedFiles(ServerRequestInterface $request): array
237209
{
238210
return array_map(static fn(UploadedFileInterface $file) => new FileUpload([
239211
'name' => $file->getClientFilename(),
240212
'size' => $file->getSize(),
241213
'error' => $file->getError(),
242214
'tmpName' => $file->getStream()->getMetadata('uri'),
243-
]), $uploadedFiles);
215+
]), $request->getUploadedFiles());
216+
}
217+
218+
/**
219+
* @return array<string, mixed>
220+
*/
221+
private function getPost(ServerRequestInterface $request): array
222+
{
223+
return (array) $request->getParsedBody();
224+
}
225+
226+
private function createUrl(ServerRequestInterface $request): Url
227+
{
228+
$url = new Url;
229+
$uri = $request->getUri();
230+
231+
$url->setScheme($uri->getScheme());
232+
$url->setHost($uri->getHost());
233+
$url->setPort($uri->getPort());
234+
$url->setPath($uri->getPath());
235+
$url->setQuery($uri->getQuery());
236+
237+
$this->setAuthorization($url, $uri->getUserInfo());
238+
239+
return $url;
244240
}
245241
}

src/Http/Response.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class Response implements IResponse
1919
public string $cookieDomain = '';
2020
public string $cookiePath = '/';
2121
public bool $cookieSecure = false;
22+
public ?bool $cookieHttpOnly = null;
2223

2324
public function __construct()
2425
{
@@ -134,7 +135,6 @@ public function setCookie(
134135
?bool $httpOnly = null,
135136
?string $sameSite = null,
136137
): static {
137-
138138
$headerValue = sprintf(
139139
'%s=%s; path=%s; SameSite=%s',
140140
$name,

0 commit comments

Comments
 (0)