Skip to content

Commit 8a7856a

Browse files
authored
Convert bref HTTP event to Symfony request via psr-7 bridge (#16)
* Convert http event to Symfony request via psr-7 bridge * Code style * Add back missing vars
1 parent c12daec commit 8a7856a

File tree

1 file changed

+10
-180
lines changed

1 file changed

+10
-180
lines changed

src/Http/SymfonyRequestBridge.php

Lines changed: 10 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -2,203 +2,33 @@
22

33
namespace CacheWerk\BrefLaravelBridge\Http;
44

5-
use RuntimeException;
6-
75
use Bref\Context\Context;
86
use Bref\Event\Http\HttpRequestEvent;
9-
10-
use Riverline\MultiPartParser\StreamedPart;
7+
use Bref\Event\Http\Psr7Bridge;
8+
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;
119
use Symfony\Component\HttpFoundation\Request;
12-
use Symfony\Component\HttpFoundation\File\UploadedFile;
1310

1411
class SymfonyRequestBridge
1512
{
1613
/**
17-
* Convert Bref HTTP request to Symfony request.
14+
* Convert Bref HTTP event to Symfony request.
1815
*
1916
* @param \Bref\Event\Http\HttpRequestEvent $event
2017
* @param \Bref\Context\Context $context
2118
* @return \Symfony\Component\HttpFoundation\Request
2219
*/
2320
public static function convertRequest(HttpRequestEvent $event, Context $context): Request
2421
{
25-
$headers = $event->getHeaders();
26-
27-
[$user, $password] = self::parseBasicAuthorization($headers);
22+
$psr7Request = Psr7Bridge::convertRequest($event, $context);
23+
$httpFoundationFactory = new HttpFoundationFactory();
24+
$symfonyRequest = $httpFoundationFactory->createRequest($psr7Request);
2825

29-
$server = array_filter([
30-
'AUTH_TYPE' => $headers['auth-type'] ?? null,
31-
'CONTENT_LENGTH' => $headers['content-length'][0] ?? null,
32-
'CONTENT_TYPE' => $event->getContentType(),
33-
'DOCUMENT_ROOT' => getcwd(),
34-
'GATEWAY_INTERFACE' => 'FastCGI/1.0',
35-
'QUERY_STRING' => $event->getQueryString(),
36-
'REQUEST_METHOD' => $event->getMethod(),
37-
'SCRIPT_FILENAME' => $_SERVER['_HANDLER'] ?? $_SERVER['SCRIPT_FILENAME'],
38-
'SERVER_ADDR' => '127.0.0.1',
39-
'SERVER_NAME' => $event->getServerName(),
40-
'SERVER_PORT' => $event->getServerPort(),
41-
'SERVER_PROTOCOL' => $event->getProtocol(),
42-
'PATH_INFO' => $event->getPath(),
43-
'REMOTE_PORT' => $event->getRemotePort(),
44-
'REQUEST_TIME' => time(),
45-
'REQUEST_TIME_FLOAT' => microtime(true),
46-
'REQUEST_URI' => $event->getUri(),
47-
'REMOTE_ADDR' => '127.0.0.1',
26+
$symfonyRequest->server->add([
27+
'HTTP_X_REQUEST_ID' => $context->getAwsRequestId(),
4828
'LAMBDA_INVOCATION_CONTEXT' => json_encode($context),
4929
'LAMBDA_REQUEST_CONTEXT' => json_encode($event->getRequestContext()),
50-
'HTTP_X_SOURCE_IP' => $event->getSourceIp(),
51-
'HTTP_X_REQUEST_ID' => $context->getAwsRequestId(),
52-
'PHP_AUTH_USER' => $user,
53-
'PHP_AUTH_PW' => $password,
54-
], fn ($value) => ! is_null($value));
55-
56-
foreach ($headers as $name => $values) {
57-
$server['HTTP_' . strtoupper(str_replace('-', '_', $name))] = $values[0];
58-
}
59-
60-
[$files, $parsedBody, $bodyString] = self::parseBodyAndUploadedFiles($event);
61-
62-
return new Request(
63-
$event->getQueryParameters(),
64-
$parsedBody ?? [],
65-
[],
66-
$event->getCookies(),
67-
$files,
68-
$server,
69-
$bodyString
70-
);
71-
}
72-
73-
/**
74-
* Parse request body and uploaded files.
75-
*
76-
* @param \Bref\Event\Http\HttpRequestEvent $event
77-
* @return array
78-
*/
79-
protected static function parseBodyAndUploadedFiles(HttpRequestEvent $event): array
80-
{
81-
$bodyString = $event->getBody();
82-
$files = [];
83-
$parsedBody = null;
84-
$contentType = $event->getContentType();
85-
86-
if (null !== $contentType && 'POST' === $event->getMethod()) {
87-
if ('application/x-www-form-urlencoded' === $contentType) {
88-
parse_str($bodyString, $parsedBody);
89-
} else {
90-
$stream = fopen('php://temp', 'rw');
91-
fwrite($stream, "Content-type: {$contentType}\r\n\r\n{$bodyString}");
92-
rewind($stream);
93-
94-
$document = new StreamedPart($stream);
95-
96-
if ($document->isMultiPart()) {
97-
$bodyString = '';
98-
$parsedBody = [];
99-
foreach ($document->getParts() as $part) {
100-
if ($part->isFile()) {
101-
$tmpPath = tempnam(sys_get_temp_dir(), 'bref_upload_');
102-
if (false === $tmpPath) {
103-
throw new RuntimeException('Unable to create a temporary directory');
104-
}
105-
file_put_contents($tmpPath, $part->getBody());
106-
if (0 !== filesize($tmpPath) && '' !== $part->getFileName()) {
107-
$file = new UploadedFile(
108-
$tmpPath,
109-
$part->getFileName(),
110-
$part->getMimeType(),
111-
UPLOAD_ERR_OK,
112-
true
113-
);
114-
} else {
115-
$file = null;
116-
}
117-
118-
self::parseKeyAndInsertValueInArray($files, $part->getName(), $file);
119-
} else {
120-
self::parseKeyAndInsertValueInArray($parsedBody, $part->getName(), $part->getBody());
121-
}
122-
}
123-
}
124-
}
125-
}
126-
127-
return [$files, $parsedBody, $bodyString];
128-
}
129-
130-
/**
131-
* Parse a string key like "files[id_cards][jpg][]" and do $array['files']['id_cards']['jpg'][] = $value.
132-
*
133-
* @param array $value
134-
* @param string $key
135-
* @param mixed $value
136-
* @return void
137-
*/
138-
protected static function parseKeyAndInsertValueInArray(array &$array, string $key, $value): void
139-
{
140-
if (false === strpos($key, '[')) {
141-
$array[$key] = $value;
142-
143-
return;
144-
}
145-
146-
$parts = explode('[', $key); // files[id_cards][jpg][] => [ 'files', 'id_cards]', 'jpg]', ']' ]
147-
$pointer = &$array;
148-
149-
foreach ($parts as $k => $part) {
150-
if (0 === $k) {
151-
$pointer = &$pointer[$part];
152-
153-
continue;
154-
}
155-
156-
// Skip two special cases:
157-
// [[ in the key produces empty string
158-
// [test : starts with [ but does not end with ]
159-
if ('' === $part || ']' !== substr($part, -1)) {
160-
// Malformed key, we use it "as is"
161-
$array[$key] = $value;
162-
163-
return;
164-
}
165-
166-
$part = substr($part, 0, -1); // The last char is a ] => remove it to have the real key
167-
168-
if ('' === $part) { // [] case
169-
$pointer = &$pointer[];
170-
} else {
171-
$pointer = &$pointer[$part];
172-
}
173-
}
174-
175-
$pointer = $value;
176-
}
177-
178-
/**
179-
* Parse the username and password from the `Authorization` header.
180-
* Only "Basic" is supported.
181-
*
182-
* @param array $headers
183-
* @return string[]|null[]
184-
*/
185-
protected static function parseBasicAuthorization(array $headers)
186-
{
187-
$authorization = trim($headers['authorization'][0] ?? '');
188-
189-
if (! str_starts_with($authorization, 'Basic ')) {
190-
return [null, null];
191-
}
192-
193-
$auth = base64_decode(trim(explode(' ', $authorization)[1]));
194-
195-
if (! $auth || ! strpos($auth, ':')) {
196-
return [null, null];
197-
}
30+
]);
19831

199-
return [
200-
strstr($auth, ':', true),
201-
substr(strstr($auth, ':'), 1),
202-
];
32+
return $symfonyRequest;
20333
}
20434
}

0 commit comments

Comments
 (0)