Skip to content

Commit 6a3c69a

Browse files
fix(edge): remove read-only and blacklisted headers from cloudfront response (#393)
* fix(edge): remove read-only and blacklisted headers from cloudfront response * chore: replace console.log to debug * refactor: code review requests * revert: package.json * Create small-knives-hug.md --------- Co-authored-by: conico974 <[email protected]>
1 parent 78308f4 commit 6a3c69a

File tree

3 files changed

+114
-1
lines changed

3 files changed

+114
-1
lines changed

.changeset/small-knives-hug.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"open-next": patch
3+
---
4+
5+
fix(edge): remove read-only and blacklisted headers from cloudfront response

packages/open-next/src/adapters/event-mapper.ts

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,12 +211,62 @@ function convertToApiGatewayProxyResultV2(
211211
return response;
212212
}
213213

214+
const CloudFrontBlacklistedHeaders = [
215+
// Disallowed headers, see: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/edge-function-restrictions-all.html#function-restrictions-disallowed-headers
216+
"connection",
217+
"expect",
218+
"keep-alive",
219+
"proxy-authenticate",
220+
"proxy-authorization",
221+
"proxy-connection",
222+
"trailer",
223+
"upgrade",
224+
"x-accel-buffering",
225+
"x-accel-charset",
226+
"x-accel-limit-rate",
227+
"x-accel-redirect",
228+
/x-amz-cf-(.*)/,
229+
"x-amzn-auth",
230+
"x-amzn-cf-billing",
231+
"x-amzn-cf-id",
232+
"x-amzn-cf-xff",
233+
"x-amzn-errortype",
234+
"x-amzn-fle-profile",
235+
"x-amzn-header-count",
236+
"x-amzn-header-order",
237+
"x-amzn-lambda-integration-tag",
238+
"x-amzn-requestid",
239+
/x-edge-(.*)/,
240+
"x-cache",
241+
"x-forwarded-proto",
242+
"x-real-ip",
243+
244+
// Read-only headers, see: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/edge-function-restrictions-all.html#function-restrictions-read-only-headers
245+
"accept-encoding",
246+
"content-length",
247+
"if-modified-since",
248+
"if-none-match",
249+
"if-range",
250+
"if-unmodified-since",
251+
"transfer-encoding",
252+
"via",
253+
];
254+
214255
function convertToCloudFrontRequestResult(
215256
result: InternalResult,
216257
): CloudFrontRequestResult {
258+
debug("result headers", result.headers);
259+
217260
const headers: CloudFrontHeaders = {};
218261
Object.entries(result.headers)
219-
.filter(([key]) => key.toLowerCase() !== "content-length")
262+
.filter(
263+
([key]) =>
264+
!CloudFrontBlacklistedHeaders.some((header) =>
265+
typeof header === "string"
266+
? header === key.toLowerCase()
267+
: header.test(key.toLowerCase()),
268+
),
269+
)
220270
.forEach(([key, value]) => {
221271
if (key === "set-cookie") {
222272
const cookies = parseCookies(value);

packages/tests-unit/tests/event-mapper.test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,5 +110,63 @@ describe("convertTo", () => {
110110
],
111111
});
112112
});
113+
114+
describe("blacklisted headers", () => {
115+
it("should remove all blacklisted or read-only headers from the response", () => {
116+
const response = convertTo({
117+
body: "",
118+
headers: {
119+
Connection: "keep-alive",
120+
expect: "100-continue",
121+
"keep-Alive": "timeout=5, max=100",
122+
"Proxy-Authenticate": "Basic",
123+
"proxy-authorization": "Basic",
124+
"proxy-connection": "keep-alive",
125+
trailer: "Max-Forwards",
126+
Upgrade: "HTTP/2.0",
127+
"X-accel-buffering": "no",
128+
"X-accel-charset": "UTF-8",
129+
"x-accel-limit-rate": "1000",
130+
"X-accel-redirect": "http://example.com",
131+
"X-amz-cf-id": "example",
132+
"x-amzn-auth": "example",
133+
"x-Amzn-cf-billing": "example",
134+
"x-Amzn-cf-id": "example",
135+
"x-Amzn-Cf-xff": "example",
136+
"x-amzn-Errortype": "example",
137+
"x-amzn-fle-Profile": "example",
138+
"x-amzn-header-Count": "example",
139+
"x-amzn-Header-order": "example",
140+
"X-Amzn-Lambda-Integration-tag": "example",
141+
"x-amzn-Requestid": "example",
142+
"x-edge-Location": "example",
143+
"X-Cache": "Hit from cloudfront",
144+
"X-Forwarded-proto": "https",
145+
"x-Real-ip": "example",
146+
"Accept-encoding": "gzip",
147+
"content-length": "100",
148+
"if-modified-Since": "example",
149+
"if-none-match": "example",
150+
"if-range": "example",
151+
"if-unmodified-since": "example",
152+
"transfer-encoding": "example",
153+
via: "1.1 abc123.cloudfront.net (CloudFront)",
154+
"x-powered-by": "Next.js",
155+
},
156+
isBase64Encoded: false,
157+
statusCode: 200,
158+
type: "cf",
159+
}) as CloudFrontRequestResult;
160+
161+
expect(response?.headers).toStrictEqual({
162+
"x-powered-by": [
163+
{
164+
key: "x-powered-by",
165+
value: "Next.js",
166+
},
167+
],
168+
});
169+
});
170+
});
113171
});
114172
});

0 commit comments

Comments
 (0)