Skip to content

Commit ce27aa1

Browse files
authored
Merge pull request #2018 from brefphp/warning-header-size
Log a warning when hitting the HTTP headers max size
2 parents b2d344d + 9ee9056 commit ce27aa1

File tree

2 files changed

+38
-4
lines changed

2 files changed

+38
-4
lines changed

src/Event/Http/HttpHandler.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ public function handle($event, Context $context): array
2525
$response = $this->handleRequest($httpEvent, $context);
2626

2727
if ($httpEvent->isFormatV2()) {
28-
return $response->toApiGatewayFormatV2();
28+
return $response->toApiGatewayFormatV2($context->getAwsRequestId());
2929
}
3030

31-
return $response->toApiGatewayFormat($httpEvent->hasMultiHeader());
31+
return $response->toApiGatewayFormat($httpEvent->hasMultiHeader(), $context->getAwsRequestId());
3232
}
3333
}

src/Event/Http/HttpResponse.php

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public function __construct(string $body, array $headers = [], int $statusCode =
2121
$this->statusCode = $statusCode;
2222
}
2323

24-
public function toApiGatewayFormat(bool $multiHeaders = false): array
24+
public function toApiGatewayFormat(bool $multiHeaders = false, ?string $awsRequestId = null): array
2525
{
2626
$base64Encoding = (bool) getenv('BREF_BINARY_RESPONSES');
2727

@@ -38,6 +38,8 @@ public function toApiGatewayFormat(bool $multiHeaders = false): array
3838
}
3939
}
4040

41+
$this->checkHeadersSize($headers, $awsRequestId);
42+
4143
// The headers must be a JSON object. If the PHP array is empty it is
4244
// serialized to `[]` (we want `{}`) so we force it to an empty object.
4345
$headers = empty($headers) ? new \stdClass : $headers;
@@ -58,7 +60,7 @@ public function toApiGatewayFormat(bool $multiHeaders = false): array
5860
/**
5961
* See https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.response
6062
*/
61-
public function toApiGatewayFormatV2(): array
63+
public function toApiGatewayFormatV2(?string $awsRequestId = null): array
6264
{
6365
$base64Encoding = (bool) getenv('BREF_BINARY_RESPONSES');
6466

@@ -76,6 +78,11 @@ public function toApiGatewayFormatV2(): array
7678
}
7779
}
7880

81+
$this->checkHeadersSize(array_merge(
82+
$headers,
83+
['Set-Cookie' => $cookies], // include cookies in the size check
84+
), $awsRequestId);
85+
7986
// The headers must be a JSON object. If the PHP array is empty it is
8087
// serialized to `[]` (we want `{}`) so we force it to an empty object.
8188
$headers = empty($headers) ? new \stdClass : $headers;
@@ -98,4 +105,31 @@ private function capitalizeHeaderName(string $name): string
98105
$name = ucwords($name);
99106
return str_replace(' ', '-', $name);
100107
}
108+
109+
/**
110+
* API Gateway v1 and v2 have a headers total max size of 10 KB.
111+
* ALB has a max size of 32 KB.
112+
* It's hard to calculate the exact size of headers here, so we just
113+
* estimate it roughly: if above 9.5 KB we log a warning.
114+
*
115+
* @param array<string|string[]> $headers
116+
*/
117+
private function checkHeadersSize(array $headers, ?string $awsRequestId): void
118+
{
119+
$estimatedHeadersSize = 0;
120+
foreach ($headers as $name => $values) {
121+
$estimatedHeadersSize += strlen($name);
122+
if (is_array($values)) {
123+
foreach ($values as $value) {
124+
$estimatedHeadersSize += strlen($value);
125+
}
126+
} else {
127+
$estimatedHeadersSize += strlen($values);
128+
}
129+
}
130+
131+
if ($estimatedHeadersSize > 9_500) {
132+
echo "$awsRequestId\tWARNING\tThe total size of HTTP response headers is estimated to be above 10 KB, which is the API Gateway limit. If the limit is reached, the HTTP response will be a 500 error.\n";
133+
}
134+
}
101135
}

0 commit comments

Comments
 (0)