@middy/http-cors 7.0.3 → 7.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/index.d.ts +3 -2
- package/index.js +71 -3
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<h1>Middy
|
|
2
|
+
<h1>Middy `http-cors` middleware</h1>
|
|
3
3
|
<img alt="Middy logo" src="https://raw.githubusercontent.com/middyjs/middy/main/docs/img/middy-logo.svg"/>
|
|
4
4
|
<p><strong>CORS middleware for the middy framework, the stylish Node.js middleware engine for AWS Lambda</strong></p>
|
|
5
5
|
<p>
|
package/index.d.ts
CHANGED
|
@@ -12,9 +12,10 @@ export interface Options {
|
|
|
12
12
|
origins?: string[];
|
|
13
13
|
exposeHeaders?: string;
|
|
14
14
|
maxAge?: number | string;
|
|
15
|
-
requestHeaders?: string;
|
|
16
|
-
requestMethods?: string;
|
|
15
|
+
requestHeaders?: string[];
|
|
16
|
+
requestMethods?: string[];
|
|
17
17
|
cacheControl?: string;
|
|
18
|
+
vary?: string;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
declare function httpCors(options?: Options): middy.MiddlewareObj;
|
package/index.js
CHANGED
|
@@ -2,6 +2,35 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
import { normalizeHttpResponse } from "@middy/util";
|
|
4
4
|
|
|
5
|
+
const hostnameToPunycode = (hostname) => {
|
|
6
|
+
const placeholder = "-_ANY_-";
|
|
7
|
+
const tempHostname = hostname.replace(/\*/g, placeholder);
|
|
8
|
+
try {
|
|
9
|
+
const url = new URL(`https://${tempHostname}`);
|
|
10
|
+
return url.host.replaceAll(placeholder.toLowerCase(), "*");
|
|
11
|
+
} catch {
|
|
12
|
+
return hostname;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const originToPunycode = (origin) => {
|
|
17
|
+
if (!origin || origin === "*") return origin;
|
|
18
|
+
const match = origin.match(/^(https?:\/\/)(.+)$/);
|
|
19
|
+
if (!match) return origin;
|
|
20
|
+
const [, protocol, host] = match;
|
|
21
|
+
return protocol + hostnameToPunycode(host);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// CORS-safelisted request headers
|
|
25
|
+
// https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_request_header
|
|
26
|
+
const corsSafelistedRequestHeaders = [
|
|
27
|
+
"accept",
|
|
28
|
+
"accept-language",
|
|
29
|
+
"content-language",
|
|
30
|
+
"content-type",
|
|
31
|
+
"range",
|
|
32
|
+
];
|
|
33
|
+
|
|
5
34
|
const defaults = {
|
|
6
35
|
disableBeforePreflightResponse: true,
|
|
7
36
|
getOrigin: undefined, // default inserted below
|
|
@@ -12,6 +41,8 @@ const defaults = {
|
|
|
12
41
|
origins: [],
|
|
13
42
|
exposeHeaders: undefined,
|
|
14
43
|
maxAge: undefined,
|
|
44
|
+
requestHeaders: undefined,
|
|
45
|
+
requestMethods: undefined,
|
|
15
46
|
cacheControl: undefined,
|
|
16
47
|
vary: undefined,
|
|
17
48
|
};
|
|
@@ -46,15 +77,19 @@ const httpCorsMiddleware = (opts = {}) => {
|
|
|
46
77
|
...opts,
|
|
47
78
|
};
|
|
48
79
|
|
|
80
|
+
options.requestHeaders = options.requestHeaders?.map((v) => v.toLowerCase());
|
|
81
|
+
options.requestMethods = options.requestMethods?.map((v) => v.toUpperCase());
|
|
82
|
+
|
|
49
83
|
let originAny = false;
|
|
50
84
|
let originMany = options.origins.length > 1;
|
|
51
85
|
const originStatic = {};
|
|
52
86
|
const originDynamic = [];
|
|
53
87
|
|
|
54
|
-
for (
|
|
88
|
+
for (let origin of [options.origin, ...options.origins]) {
|
|
55
89
|
if (!origin) {
|
|
56
90
|
continue;
|
|
57
91
|
}
|
|
92
|
+
origin = originToPunycode(origin);
|
|
58
93
|
// All
|
|
59
94
|
if (origin === "*") {
|
|
60
95
|
originAny = true;
|
|
@@ -67,7 +102,6 @@ const httpCorsMiddleware = (opts = {}) => {
|
|
|
67
102
|
}
|
|
68
103
|
originMany = true;
|
|
69
104
|
// Dynamic
|
|
70
|
-
// TODO: IDN -> puncycode not handled, add in if requested
|
|
71
105
|
const regExpStr = origin
|
|
72
106
|
.replace(/[.+?^${}()|[\]\\]/g, "\\$&")
|
|
73
107
|
.replaceAll("*", "[^.]*");
|
|
@@ -149,6 +183,40 @@ const httpCorsMiddleware = (opts = {}) => {
|
|
|
149
183
|
);
|
|
150
184
|
if (method === "OPTIONS") {
|
|
151
185
|
normalizeHttpResponse(request);
|
|
186
|
+
const eventHeaders = request.event.headers ?? {};
|
|
187
|
+
const requestMethod =
|
|
188
|
+
eventHeaders["Access-Control-Request-Method"] ??
|
|
189
|
+
eventHeaders["access-control-request-method"];
|
|
190
|
+
|
|
191
|
+
if (options.requestMethods?.length && requestMethod) {
|
|
192
|
+
if (!options.requestMethods.includes(requestMethod)) {
|
|
193
|
+
request.response.statusCode = 204;
|
|
194
|
+
request.response.headers = {};
|
|
195
|
+
return request.response;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const requestHeadersValue =
|
|
200
|
+
eventHeaders["Access-Control-Request-Headers"] ??
|
|
201
|
+
eventHeaders["access-control-request-headers"];
|
|
202
|
+
|
|
203
|
+
if (options.requestHeaders?.length && requestHeadersValue) {
|
|
204
|
+
const requestedHeaders = requestHeadersValue
|
|
205
|
+
.split(",")
|
|
206
|
+
.map((h) => h.trim().toLowerCase());
|
|
207
|
+
const nonSafelistedHeaders = requestedHeaders.filter(
|
|
208
|
+
(h) => !corsSafelistedRequestHeaders.includes(h),
|
|
209
|
+
);
|
|
210
|
+
const hasDisallowedHeader = nonSafelistedHeaders.some(
|
|
211
|
+
(h) => !options.requestHeaders.includes(h),
|
|
212
|
+
);
|
|
213
|
+
if (hasDisallowedHeader) {
|
|
214
|
+
request.response.statusCode = 204;
|
|
215
|
+
request.response.headers = {};
|
|
216
|
+
return request.response;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
152
220
|
const headers = {};
|
|
153
221
|
modifyHeaders(headers, options, request);
|
|
154
222
|
request.response.headers = headers;
|
|
@@ -178,7 +246,7 @@ const getVersionHttpMethod = {
|
|
|
178
246
|
"2.0": (event) => event.requestContext.http.method,
|
|
179
247
|
};
|
|
180
248
|
|
|
181
|
-
// header in
|
|
249
|
+
// header in official name, lowercase variant handled
|
|
182
250
|
const addHeaderPart = (headers, header, value) => {
|
|
183
251
|
if (!value) return;
|
|
184
252
|
const headerLower = header.toLowerCase();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@middy/http-cors",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.1.1",
|
|
4
4
|
"description": "CORS (Cross-Origin Resource Sharing) middleware for the middy framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -65,9 +65,10 @@
|
|
|
65
65
|
},
|
|
66
66
|
"gitHead": "7a6c0fbb8ab71d6a2171e678697de9f237568431",
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@middy/util": "7.
|
|
68
|
+
"@middy/util": "7.1.1"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"@middy/core": "7.
|
|
71
|
+
"@middy/core": "7.1.1",
|
|
72
|
+
"@types/aws-lambda": "^8.0.0"
|
|
72
73
|
}
|
|
73
74
|
}
|