@nifrajs/aws-lambda 4.0.2 → 5.1.0
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 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +37 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +40 -18
package/README.md
CHANGED
|
@@ -29,6 +29,7 @@ How it holds the line:
|
|
|
29
29
|
|
|
30
30
|
- **Post-decode body limits.** The body is decoded (base64 or UTF-8) and its real `byteLength` checked against `maxBodyBytes` (default 1,000,000 - match your app's setting if you changed it) *before* a `Request` is constructed. The event's own length claims are never trusted; over the limit answers a flat `413`.
|
|
31
31
|
- **One header merge site.** Request headers come from the v2 `headers` map plus the separate `cookies` array in exactly one function; the array is canonical, so a `cookie` key smuggled into `headers` never reaches the app. Response `Set-Cookie` values travel in the result's `cookies` array, one entry each - never comma-joined.
|
|
32
|
+
- **Body-less HEAD.** A `HEAD` answer keeps the GET route's status and headers but carries no body, on both handlers. A streaming body is cancelled rather than read, so its producer stops.
|
|
32
33
|
- **Base64 honesty.** Response `isBase64Encoded` is decided by a strict UTF-8 decode of the actual bytes, never by content-type guessing. Binary round-trips exactly; text ships as text.
|
|
33
34
|
- **Client IP.** `event.requestContext.http.sourceIp` feeds core's client-IP seam; `X-Forwarded-For` trust stays where it belongs, in the app's `clientIp` server option.
|
|
34
35
|
- **Flat errors.** Uncaught failures collapse to the same `{"ok":false,"error":"internal_error"}` 500 as every other nifra runtime - the event is never echoed.
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,4FAA4F;AAC5F,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAA;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,CAAA;CACzD;AAED,wFAAwF;AACxF,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CACjF;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAA;IAC/D,+FAA+F;IAC/F,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;IAClC,QAAQ,CAAC,cAAc,CAAC,EAAE;QACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;QAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE;YACd,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;YACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;SAC3B,CAAA;KACF,CAAA;CACF;AAED,gGAAgG;AAChG,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAChC;AAED,iGAAiG;AACjG,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;IAC3B,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,SAAS,CAAA;CAC5C;AAED,+EAA+E;AAC/E,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,+FAA+F;IAC/F,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,eAAe,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAC/B;AAED,iGAAiG;AACjG,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAA;IAC1C,GAAG,IAAI,OAAO,CAAA;IACd,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAA;CACpD;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -74,10 +74,15 @@ const flatError = (status, code) => new Response(`{"ok":false,"error":"${code}"}
|
|
|
74
74
|
* Build the `Request`, or a flat error `Response` when the event must be rejected before the app
|
|
75
75
|
* runs. The body is decoded and measured first - a 413 here means no `Request` ever existed.
|
|
76
76
|
*/
|
|
77
|
+
/** A host name or IP literal with an optional port: nothing that could end the authority early. */
|
|
78
|
+
const AUTHORITY = /^(?:[A-Za-z0-9.-]+|\[[0-9A-Fa-f:.]+\])(?::\d{1,5})?$/;
|
|
77
79
|
const toRequest = (event, maxBodyBytes) => {
|
|
78
80
|
const method = event.requestContext?.http?.method ?? "GET";
|
|
79
81
|
const headers = requestHeaders(event);
|
|
80
|
-
|
|
82
|
+
// The Host header is the client's when the event names no domain. A `/`, `?`, `#` or `@` in it
|
|
83
|
+
// would move the URL's host or path away from the event's own `rawPath`.
|
|
84
|
+
const host = headers.get("host");
|
|
85
|
+
const authority = event.requestContext?.domainName ?? (host !== null && AUTHORITY.test(host) ? host : "localhost");
|
|
81
86
|
const path = event.rawPath !== undefined && event.rawPath !== "" ? event.rawPath : "/";
|
|
82
87
|
const query = event.rawQueryString !== undefined && event.rawQueryString !== ""
|
|
83
88
|
? `?${event.rawQueryString}`
|
|
@@ -107,18 +112,27 @@ const resultHeaders = (response) => {
|
|
|
107
112
|
}
|
|
108
113
|
return { headers, cookies: response.headers.getSetCookie() };
|
|
109
114
|
};
|
|
110
|
-
|
|
115
|
+
// Nothing reads a HEAD answer's body. Cancelled, its source learns the exchange is over, as on
|
|
116
|
+
// the other adapters; left alone, a streaming route's producer runs on with no reader.
|
|
117
|
+
const discardBody = (response) => {
|
|
118
|
+
response.body?.cancel().catch(() => { });
|
|
119
|
+
};
|
|
120
|
+
const toResult = async (response, head) => {
|
|
111
121
|
const { headers, cookies } = resultHeaders(response);
|
|
112
|
-
|
|
113
|
-
let
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
body = UTF8_STRICT.decode(bytes);
|
|
117
|
-
isBase64Encoded = false;
|
|
122
|
+
let body = "";
|
|
123
|
+
let isBase64Encoded = false;
|
|
124
|
+
if (head) {
|
|
125
|
+
discardBody(response);
|
|
118
126
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
127
|
+
else {
|
|
128
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
129
|
+
try {
|
|
130
|
+
body = UTF8_STRICT.decode(bytes);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
body = toBase64(bytes);
|
|
134
|
+
isBase64Encoded = true;
|
|
135
|
+
}
|
|
122
136
|
}
|
|
123
137
|
const result = { statusCode: response.status, headers, body, isBase64Encoded };
|
|
124
138
|
if (cookies.length > 0)
|
|
@@ -129,10 +143,12 @@ const INTERNAL_ERROR = () => flatError(500, "internal_error");
|
|
|
129
143
|
/** Run the app for one event. Never throws: failures collapse to the flat 500. */
|
|
130
144
|
const invoke = async (app, event, context, maxBodyBytes) => {
|
|
131
145
|
const pending = [];
|
|
146
|
+
let head = false;
|
|
132
147
|
try {
|
|
133
148
|
const built = toRequest(event, maxBodyBytes);
|
|
134
149
|
if (built instanceof Response)
|
|
135
|
-
return { response: built, pending };
|
|
150
|
+
return { response: built, pending, head };
|
|
151
|
+
head = built.method === "HEAD";
|
|
136
152
|
const response = await app.fetch(built, {
|
|
137
153
|
env: { event, context },
|
|
138
154
|
clientIp: event.requestContext?.http?.sourceIp,
|
|
@@ -140,10 +156,10 @@ const invoke = async (app, event, context, maxBodyBytes) => {
|
|
|
140
156
|
pending.push(promise);
|
|
141
157
|
},
|
|
142
158
|
});
|
|
143
|
-
return { response, pending };
|
|
159
|
+
return { response, pending, head };
|
|
144
160
|
}
|
|
145
161
|
catch {
|
|
146
|
-
return { response: INTERNAL_ERROR(), pending };
|
|
162
|
+
return { response: INTERNAL_ERROR(), pending, head };
|
|
147
163
|
}
|
|
148
164
|
};
|
|
149
165
|
// Background work must settle before the handler returns - Lambda freezes the container the
|
|
@@ -164,9 +180,9 @@ export function handle(app, options = {}) {
|
|
|
164
180
|
const maxBodyBytes = options.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES;
|
|
165
181
|
assertBodyLimit(maxBodyBytes);
|
|
166
182
|
return async (event, context) => {
|
|
167
|
-
const { response, pending } = await invoke(app, event, context, maxBodyBytes);
|
|
183
|
+
const { response, pending, head } = await invoke(app, event, context, maxBodyBytes);
|
|
168
184
|
try {
|
|
169
|
-
const result = await toResult(response);
|
|
185
|
+
const result = await toResult(response, head);
|
|
170
186
|
await settle(pending);
|
|
171
187
|
return result;
|
|
172
188
|
}
|
|
@@ -195,14 +211,17 @@ export function streamHandle(app, options = {}) {
|
|
|
195
211
|
const maxBodyBytes = options.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES;
|
|
196
212
|
assertBodyLimit(maxBodyBytes);
|
|
197
213
|
return awslambda.streamifyResponse(async (event, responseStream, context) => {
|
|
198
|
-
const { response, pending } = await invoke(app, event, context, maxBodyBytes);
|
|
214
|
+
const { response, pending, head } = await invoke(app, event, context, maxBodyBytes);
|
|
199
215
|
const { headers, cookies } = resultHeaders(response);
|
|
200
216
|
const metadata = { statusCode: response.status, headers };
|
|
201
217
|
if (cookies.length > 0)
|
|
202
218
|
metadata.cookies = cookies;
|
|
203
219
|
const out = awslambda.HttpResponseStream.from(responseStream, metadata);
|
|
204
220
|
try {
|
|
205
|
-
if (
|
|
221
|
+
if (head) {
|
|
222
|
+
discardBody(response);
|
|
223
|
+
}
|
|
224
|
+
else if (response.body !== null) {
|
|
206
225
|
for await (const chunk of response.body) {
|
|
207
226
|
if (out.write(chunk) === false && typeof out.once === "function") {
|
|
208
227
|
await new Promise((resolve) => {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nifrajs/aws-lambda",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"description": "AWS Lambda adapter for nifra - API Gateway HTTP API (payload v2) and Function URLs, buffered or streaming, with post-decode body limits and single-site header merging. Dependency-free.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bun",
|
package/src/index.ts
CHANGED
|
@@ -174,10 +174,17 @@ const flatError = (status: number, code: string): Response =>
|
|
|
174
174
|
* Build the `Request`, or a flat error `Response` when the event must be rejected before the app
|
|
175
175
|
* runs. The body is decoded and measured first - a 413 here means no `Request` ever existed.
|
|
176
176
|
*/
|
|
177
|
+
/** A host name or IP literal with an optional port: nothing that could end the authority early. */
|
|
178
|
+
const AUTHORITY = /^(?:[A-Za-z0-9.-]+|\[[0-9A-Fa-f:.]+\])(?::\d{1,5})?$/
|
|
179
|
+
|
|
177
180
|
const toRequest = (event: LambdaEvent, maxBodyBytes: number): Request | Response => {
|
|
178
181
|
const method = event.requestContext?.http?.method ?? "GET"
|
|
179
182
|
const headers = requestHeaders(event)
|
|
180
|
-
|
|
183
|
+
// The Host header is the client's when the event names no domain. A `/`, `?`, `#` or `@` in it
|
|
184
|
+
// would move the URL's host or path away from the event's own `rawPath`.
|
|
185
|
+
const host = headers.get("host")
|
|
186
|
+
const authority =
|
|
187
|
+
event.requestContext?.domainName ?? (host !== null && AUTHORITY.test(host) ? host : "localhost")
|
|
181
188
|
const path = event.rawPath !== undefined && event.rawPath !== "" ? event.rawPath : "/"
|
|
182
189
|
const query =
|
|
183
190
|
event.rawQueryString !== undefined && event.rawQueryString !== ""
|
|
@@ -212,17 +219,26 @@ const resultHeaders = (
|
|
|
212
219
|
return { headers, cookies: response.headers.getSetCookie() }
|
|
213
220
|
}
|
|
214
221
|
|
|
215
|
-
|
|
222
|
+
// Nothing reads a HEAD answer's body. Cancelled, its source learns the exchange is over, as on
|
|
223
|
+
// the other adapters; left alone, a streaming route's producer runs on with no reader.
|
|
224
|
+
const discardBody = (response: Response): void => {
|
|
225
|
+
response.body?.cancel().catch(() => {})
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const toResult = async (response: Response, head: boolean): Promise<LambdaResult> => {
|
|
216
229
|
const { headers, cookies } = resultHeaders(response)
|
|
217
|
-
|
|
218
|
-
let
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
230
|
+
let body = ""
|
|
231
|
+
let isBase64Encoded = false
|
|
232
|
+
if (head) {
|
|
233
|
+
discardBody(response)
|
|
234
|
+
} else {
|
|
235
|
+
const bytes = new Uint8Array(await response.arrayBuffer())
|
|
236
|
+
try {
|
|
237
|
+
body = UTF8_STRICT.decode(bytes)
|
|
238
|
+
} catch {
|
|
239
|
+
body = toBase64(bytes)
|
|
240
|
+
isBase64Encoded = true
|
|
241
|
+
}
|
|
226
242
|
}
|
|
227
243
|
const result: LambdaResult = { statusCode: response.status, headers, body, isBase64Encoded }
|
|
228
244
|
if (cookies.length > 0) result.cookies = cookies
|
|
@@ -234,6 +250,8 @@ const INTERNAL_ERROR = (): Response => flatError(500, "internal_error")
|
|
|
234
250
|
interface Invocation {
|
|
235
251
|
response: Response
|
|
236
252
|
pending: readonly Promise<unknown>[]
|
|
253
|
+
/** The request was a HEAD, so the answer goes out without its body. */
|
|
254
|
+
head: boolean
|
|
237
255
|
}
|
|
238
256
|
|
|
239
257
|
/** Run the app for one event. Never throws: failures collapse to the flat 500. */
|
|
@@ -244,9 +262,11 @@ const invoke = async (
|
|
|
244
262
|
maxBodyBytes: number,
|
|
245
263
|
): Promise<Invocation> => {
|
|
246
264
|
const pending: Promise<unknown>[] = []
|
|
265
|
+
let head = false
|
|
247
266
|
try {
|
|
248
267
|
const built = toRequest(event, maxBodyBytes)
|
|
249
|
-
if (built instanceof Response) return { response: built, pending }
|
|
268
|
+
if (built instanceof Response) return { response: built, pending, head }
|
|
269
|
+
head = built.method === "HEAD"
|
|
250
270
|
const response = await app.fetch(built, {
|
|
251
271
|
env: { event, context },
|
|
252
272
|
clientIp: event.requestContext?.http?.sourceIp,
|
|
@@ -254,9 +274,9 @@ const invoke = async (
|
|
|
254
274
|
pending.push(promise)
|
|
255
275
|
},
|
|
256
276
|
})
|
|
257
|
-
return { response, pending }
|
|
277
|
+
return { response, pending, head }
|
|
258
278
|
} catch {
|
|
259
|
-
return { response: INTERNAL_ERROR(), pending }
|
|
279
|
+
return { response: INTERNAL_ERROR(), pending, head }
|
|
260
280
|
}
|
|
261
281
|
}
|
|
262
282
|
|
|
@@ -283,9 +303,9 @@ export function handle(
|
|
|
283
303
|
const maxBodyBytes = options.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES
|
|
284
304
|
assertBodyLimit(maxBodyBytes)
|
|
285
305
|
return async (event, context) => {
|
|
286
|
-
const { response, pending } = await invoke(app, event, context, maxBodyBytes)
|
|
306
|
+
const { response, pending, head } = await invoke(app, event, context, maxBodyBytes)
|
|
287
307
|
try {
|
|
288
|
-
const result = await toResult(response)
|
|
308
|
+
const result = await toResult(response, head)
|
|
289
309
|
await settle(pending)
|
|
290
310
|
return result
|
|
291
311
|
} catch {
|
|
@@ -319,13 +339,15 @@ export function streamHandle(
|
|
|
319
339
|
const maxBodyBytes = options.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES
|
|
320
340
|
assertBodyLimit(maxBodyBytes)
|
|
321
341
|
return awslambda.streamifyResponse(async (event, responseStream, context) => {
|
|
322
|
-
const { response, pending } = await invoke(app, event, context, maxBodyBytes)
|
|
342
|
+
const { response, pending, head } = await invoke(app, event, context, maxBodyBytes)
|
|
323
343
|
const { headers, cookies } = resultHeaders(response)
|
|
324
344
|
const metadata: StreamMetadata = { statusCode: response.status, headers }
|
|
325
345
|
if (cookies.length > 0) metadata.cookies = cookies
|
|
326
346
|
const out = awslambda.HttpResponseStream.from(responseStream, metadata)
|
|
327
347
|
try {
|
|
328
|
-
if (
|
|
348
|
+
if (head) {
|
|
349
|
+
discardBody(response)
|
|
350
|
+
} else if (response.body !== null) {
|
|
329
351
|
for await (const chunk of response.body) {
|
|
330
352
|
if (out.write(chunk) === false && typeof out.once === "function") {
|
|
331
353
|
await new Promise<void>((resolve) => {
|