From 42696f469e620bc9c9c9f095495a24f2c3b0923d Mon Sep 17 00:00:00 2001 From: Gijs Date: Thu, 22 Jun 2023 14:41:42 +0200 Subject: [PATCH] Force HTTP header to string --- src/Event/Http/Psr7Bridge.php | 2 +- src/FpmRuntime/FpmHandler.php | 2 +- tests/Event/Http/CommonHttpTest.php | 25 ++++++ .../ag-v1-header-numeric-multivalue.json | 86 +++++++++++++++++++ .../Http/Fixture/ag-v1-header-numeric.json | 53 ++++++++++++ .../ag-v2-header-numeric-multivalue.json | 41 +++++++++ .../Http/Fixture/ag-v2-header-numeric.json | 41 +++++++++ tests/FpmRuntime/FpmHandlerTest.php | 35 ++++++++ 8 files changed, 283 insertions(+), 2 deletions(-) create mode 100644 tests/Event/Http/Fixture/ag-v1-header-numeric-multivalue.json create mode 100644 tests/Event/Http/Fixture/ag-v1-header-numeric.json create mode 100644 tests/Event/Http/Fixture/ag-v2-header-numeric-multivalue.json create mode 100644 tests/Event/Http/Fixture/ag-v2-header-numeric.json diff --git a/src/Event/Http/Psr7Bridge.php b/src/Event/Http/Psr7Bridge.php index f6503951e..2db1406d0 100644 --- a/src/Event/Http/Psr7Bridge.php +++ b/src/Event/Http/Psr7Bridge.php @@ -49,7 +49,7 @@ public static function convertRequest(HttpRequestEvent $event, Context $context) ]); foreach ($headers as $name => $values) { - $server['HTTP_' . strtoupper(str_replace('-', '_', $name))] = $values[0]; + $server['HTTP_' . strtoupper(str_replace('-', '_', (string) $name))] = $values[0]; } /** diff --git a/src/FpmRuntime/FpmHandler.php b/src/FpmRuntime/FpmHandler.php index a63c3a467..2205966f8 100644 --- a/src/FpmRuntime/FpmHandler.php +++ b/src/FpmRuntime/FpmHandler.php @@ -248,7 +248,7 @@ private function eventToFastCgiRequest(HttpRequestEvent $event, Context $context } foreach ($event->getHeaders() as $header => $values) { foreach ($values as $value) { - $key = 'HTTP_' . strtoupper(str_replace('-', '_', $header)); + $key = 'HTTP_' . strtoupper(str_replace('-', '_', (string) $header)); $request->setCustomVar($key, $value); } } diff --git a/tests/Event/Http/CommonHttpTest.php b/tests/Event/Http/CommonHttpTest.php index 7e6210d69..3e931a97b 100644 --- a/tests/Event/Http/CommonHttpTest.php +++ b/tests/Event/Http/CommonHttpTest.php @@ -163,6 +163,31 @@ public function test request with custom multi header(int $version) } } + /** + * @dataProvider provide API Gateway versions + */ + public function test request with numeric header(int $version) + { + $this->fromFixture(__DIR__ . "/Fixture/ag-v$version-header-numeric.json"); + $this->assertHeader('12345', ['Hello world']); + } + + /** + * @dataProvider provide API Gateway versions + */ + public function test request with numeric multi header(int $version) + { + $this->fromFixture(__DIR__ . "/Fixture/ag-v$version-header-numeric-multivalue.json"); + if ($version === 2) { + // In v2, multi-value headers are joined by a comma + // See https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html + $this->assertHeader('12345', ['Hello world,Hello john']); + } else { + $this->assertHeader('12345', ['Hello world', 'Hello john']); + $this->assertHasMultiHeader(true); + } + } + /** * @dataProvider provide API Gateway versions */ diff --git a/tests/Event/Http/Fixture/ag-v1-header-numeric-multivalue.json b/tests/Event/Http/Fixture/ag-v1-header-numeric-multivalue.json new file mode 100644 index 000000000..ccd7d9281 --- /dev/null +++ b/tests/Event/Http/Fixture/ag-v1-header-numeric-multivalue.json @@ -0,0 +1,86 @@ +{ + "version": "1.0", + "resource": "/path", + "path": "/path", + "httpMethod": "GET", + "headers": { + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate", + "Cache-Control": "no-cache", + "Host": "example.org", + "User-Agent": "PostmanRuntime/7.20.1", + "X-Amzn-Trace-Id": "Root=1-ffffffff-ffffffffffffffffffffffff", + "X-Forwarded-For": "1.1.1.1", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https", + "12345": "Hello world" + }, + "multiValueHeaders": { + "Accept": [ + "*/*" + ], + "Accept-Encoding": [ + "gzip, deflate" + ], + "Cache-Control": [ + "no-cache" + ], + "Host": [ + "example.org" + ], + "User-Agent": [ + "PostmanRuntime/7.20.1" + ], + "X-Amzn-Trace-Id": [ + "Root=1-ffffffff-ffffffffffffffffffffffff" + ], + "X-Forwarded-For": [ + "1.1.1.1" + ], + "X-Forwarded-Port": [ + "443" + ], + "X-Forwarded-Proto": [ + "https" + ], + "12345": [ + "Hello world", + "Hello john" + ] + }, + "queryStringParameters": null, + "pathParameters": null, + "stageVariables": null, + "requestContext": { + "resourceId": "xxxxxx", + "resourcePath": "/path", + "httpMethod": "PUT", + "extendedRequestId": "XXXXXX-xxxxxxxx=", + "requestTime": "24/Nov/2019:18:55:08 +0000", + "path": "/path", + "accountId": "123400000000", + "protocol": "HTTP/1.1", + "stage": "dev", + "domainPrefix": "dev", + "requestTimeEpoch": 1574621708700, + "requestId": "ffffffff-ffff-4fff-ffff-ffffffffffff", + "identity": { + "cognitoIdentityPoolId": null, + "accountId": null, + "cognitoIdentityId": null, + "caller": null, + "sourceIp": "1.1.1.1", + "principalOrgId": null, + "accessKey": null, + "cognitoAuthenticationType": null, + "cognitoAuthenticationProvider": null, + "userArn": null, + "userAgent": "PostmanRuntime/7.20.1", + "user": null + }, + "domainName": "example.org", + "apiId": "xxxxxxxxxx" + }, + "body": "", + "isBase64Encoded": false +} diff --git a/tests/Event/Http/Fixture/ag-v1-header-numeric.json b/tests/Event/Http/Fixture/ag-v1-header-numeric.json new file mode 100644 index 000000000..0f806d250 --- /dev/null +++ b/tests/Event/Http/Fixture/ag-v1-header-numeric.json @@ -0,0 +1,53 @@ +{ + "version": "1.0", + "resource": "/path", + "path": "/path", + "httpMethod": "GET", + "headers": { + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate", + "Cache-Control": "no-cache", + "Host": "example.org", + "User-Agent": "PostmanRuntime/7.20.1", + "X-Amzn-Trace-Id": "Root=1-ffffffff-ffffffffffffffffffffffff", + "X-Forwarded-For": "1.1.1.1", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https", + "12345": "Hello world" + }, + "queryStringParameters": null, + "pathParameters": null, + "stageVariables": null, + "requestContext": { + "resourceId": "xxxxxx", + "resourcePath": "/path", + "httpMethod": "PUT", + "extendedRequestId": "XXXXXX-xxxxxxxx=", + "requestTime": "24/Nov/2019:18:55:08 +0000", + "path": "/path", + "accountId": "123400000000", + "protocol": "HTTP/1.1", + "stage": "dev", + "domainPrefix": "dev", + "requestTimeEpoch": 1574621708700, + "requestId": "ffffffff-ffff-4fff-ffff-ffffffffffff", + "identity": { + "cognitoIdentityPoolId": null, + "accountId": null, + "cognitoIdentityId": null, + "caller": null, + "sourceIp": "1.1.1.1", + "principalOrgId": null, + "accessKey": null, + "cognitoAuthenticationType": null, + "cognitoAuthenticationProvider": null, + "userArn": null, + "userAgent": "PostmanRuntime/7.20.1", + "user": null + }, + "domainName": "example.org", + "apiId": "xxxxxxxxxx" + }, + "body": "", + "isBase64Encoded": false +} diff --git a/tests/Event/Http/Fixture/ag-v2-header-numeric-multivalue.json b/tests/Event/Http/Fixture/ag-v2-header-numeric-multivalue.json new file mode 100644 index 000000000..3d7950543 --- /dev/null +++ b/tests/Event/Http/Fixture/ag-v2-header-numeric-multivalue.json @@ -0,0 +1,41 @@ +{ + "version": "2.0", + "routeKey": "ANY /path", + "rawPath": "/path", + "rawQueryString": "", + "headers": { + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate", + "Cache-Control": "no-cache", + "Host": "example.org", + "User-Agent": "PostmanRuntime/7.20.1", + "X-Amzn-Trace-Id": "Root=1-ffffffff-ffffffffffffffffffffffff", + "X-Forwarded-For": "1.1.1.1", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https", + "12345": "Hello world,Hello john" + }, + "queryStringParameters": null, + "stageVariables": null, + "requestContext": { + "accountId": "123400000000", + "apiId": "xxxxxxxxxx", + "domainName": "example.org", + "domainPrefix": "0000000000", + "http": { + "method": "GET", + "path": "/path", + "protocol": "HTTP/1.1", + "sourceIp": "1.1.1.1", + "userAgent": "PostmanRuntime/7.20.1" + }, + "requestId": "JTHoQgr2oAMEPMg=", + "routeId": "47matwk", + "routeKey": "ANY /path", + "stage": "$default", + "time": "24/Nov/2019:18:55:08 +0000", + "timeEpoch": 1574621708700 + }, + "body": "", + "isBase64Encoded": false +} diff --git a/tests/Event/Http/Fixture/ag-v2-header-numeric.json b/tests/Event/Http/Fixture/ag-v2-header-numeric.json new file mode 100644 index 000000000..2ca8a1a6e --- /dev/null +++ b/tests/Event/Http/Fixture/ag-v2-header-numeric.json @@ -0,0 +1,41 @@ +{ + "version": "2.0", + "routeKey": "ANY /path", + "rawPath": "/path", + "rawQueryString": "", + "headers": { + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate", + "Cache-Control": "no-cache", + "Host": "example.org", + "User-Agent": "PostmanRuntime/7.20.1", + "X-Amzn-Trace-Id": "Root=1-ffffffff-ffffffffffffffffffffffff", + "X-Forwarded-For": "1.1.1.1", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https", + "12345": "Hello world" + }, + "queryStringParameters": null, + "stageVariables": null, + "requestContext": { + "accountId": "123400000000", + "apiId": "xxxxxxxxxx", + "domainName": "example.org", + "domainPrefix": "0000000000", + "http": { + "method": "GET", + "path": "/path", + "protocol": "HTTP/1.1", + "sourceIp": "1.1.1.1", + "userAgent": "PostmanRuntime/7.20.1" + }, + "requestId": "JTHoQgr2oAMEPMg=", + "routeId": "47matwk", + "routeKey": "ANY /path", + "stage": "$default", + "time": "24/Nov/2019:18:55:08 +0000", + "timeEpoch": 1574621708700 + }, + "body": "", + "isBase64Encoded": false +} diff --git a/tests/FpmRuntime/FpmHandlerTest.php b/tests/FpmRuntime/FpmHandlerTest.php index 10a246a9d..388803894 100644 --- a/tests/FpmRuntime/FpmHandlerTest.php +++ b/tests/FpmRuntime/FpmHandlerTest.php @@ -286,6 +286,41 @@ public function test request with custom header(int $version) ]); } + /** + * @dataProvider provide API Gateway versions + */ + public function test request with numeric header(int $version) + { + $event = [ + 'version' => '1.0', + 'httpMethod' => 'GET', + 'path' => '/', + 'headers' => [ + '12345' => 'Hello world', + ], + ]; + $this->assertGlobalVariables($event, [ + '$_GET' => [], + '$_POST' => [], + '$_FILES' => [], + '$_COOKIE' => [], + '$_REQUEST' => [], + '$_SERVER' => [ + 'REQUEST_URI' => '/', + 'PHP_SELF' => '/', + 'PATH_INFO' => '/', + 'REQUEST_METHOD' => 'GET', + 'QUERY_STRING' => '', + 'HTTP_12345' => 'Hello world', + 'CONTENT_LENGTH' => '0', + 'CONTENT_TYPE' => 'application/x-www-form-urlencoded', + 'LAMBDA_INVOCATION_CONTEXT' => json_encode($this->fakeContext), + 'LAMBDA_REQUEST_CONTEXT' => '[]', + ], + 'HTTP_RAW_BODY' => '', + ]); + } + /** * @dataProvider provide API Gateway versions */