@63klabs/cache-data 1.3.10 → 1.3.11
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/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,12 @@ To report an issue, or to see proposed and upcoming enhancements, check out [63K
|
|
|
8
8
|
|
|
9
9
|
Report all vulnerabilities under the [Security menu](https://github.com/63Klabs/cache-data/security/advisories) in the Cache-Data GitHub repository.
|
|
10
10
|
|
|
11
|
+
## v1.3.11 (2026-04-09)
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **ClientRequest / RequestInfo: X-Forwarded-For and User-Agent header priority** - When API Gateway is behind CloudFront (or any reverse proxy), `getClientIp()` and `getClientUserAgent()` now return the original client values from the `x-forwarded-for` and `user-agent` headers instead of CloudFront's identity values. Falls back to `identity.sourceIp` and `identity.userAgent` when headers are absent. [Spec: 1-3-11-client-request-update-forwarded-for](.kiro/specs/1-3-11-client-request-update-forwarded-for/)
|
|
16
|
+
|
|
11
17
|
## v1.3.10 (2026-03-15)
|
|
12
18
|
|
|
13
19
|
### Fixes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@63klabs/cache-data",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.11",
|
|
4
4
|
"description": "A package for AWS Lambda Node.js applications to access and cache data from remote API endpoints (or other sources) utilizing AWS S3 and DynamoDb for the cache storage. Also provides a simple request handling, routing, and response logging framework for running a web service with minimal dependencies.",
|
|
5
5
|
"author": "Chad Kluck (https://chadkluck.me)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"@eslint/js": "^10.0.1",
|
|
29
29
|
"eslint": "^10.0.1",
|
|
30
30
|
"fast-check": "^4.5.3",
|
|
31
|
-
"jest": "^30.2.0"
|
|
31
|
+
"jest": "^30.2.0"
|
|
32
|
+
},
|
|
32
33
|
"overrides": {
|
|
33
34
|
"fast-xml-parser": ">=5.3.4",
|
|
34
35
|
"glob": ">=13.0.6",
|
|
@@ -1400,8 +1400,16 @@ class ClientRequest extends RequestInfo {
|
|
|
1400
1400
|
/**
|
|
1401
1401
|
* Get the _processed_ request properties. These are the properties that
|
|
1402
1402
|
* the ClientRequest object took from the event sent to Lambda, validated,
|
|
1403
|
-
* supplemented, and makes available to controllers.
|
|
1404
|
-
*
|
|
1403
|
+
* supplemented, and makes available to controllers.
|
|
1404
|
+
*
|
|
1405
|
+
* Note When accessed behind CloudFront:
|
|
1406
|
+
* To ensure the user agent is passed along to API Gateway, use the AWS
|
|
1407
|
+
* managed Origin Request Policy named AllViewerExceptHostHeader. This
|
|
1408
|
+
* forwards the User-Agent along with most other viewer headers while
|
|
1409
|
+
* maintaining the correct Host header required for API Gateway to route
|
|
1410
|
+
* the request properly.
|
|
1411
|
+
*
|
|
1412
|
+
* @returns {{ method: string, path: string, pathArray: string[], resource: string, resourceArray: string[], pathParameters: {}, queryStringParameters: {}, headerParameters: {}, cookieParameters: {}, bodyParameters: {}, bodyPayload: string, client: {ip: string, userAgent: string, origin: string, referrer: string, isAuthenticated: boolean, isGuest: boolean, authorizations: string[], roles: string[]}, deadline: number, calcMsToDeadline: function}
|
|
1405
1413
|
*/
|
|
1406
1414
|
getProps() {
|
|
1407
1415
|
return this.#props;
|
|
@@ -130,6 +130,12 @@ class RequestInfo {
|
|
|
130
130
|
|
|
131
131
|
/**
|
|
132
132
|
* User Agent of client request
|
|
133
|
+
* Note When accessed behind CloudFront:
|
|
134
|
+
* To ensure the user agent is passed along to API Gateway, use the AWS
|
|
135
|
+
* managed Origin Request Policy named AllViewerExceptHostHeader. This
|
|
136
|
+
* forwards the User-Agent along with most other viewer headers while
|
|
137
|
+
* maintaining the correct Host header required for API Gateway to route
|
|
138
|
+
* the request properly.
|
|
133
139
|
* @returns {string} The user agent string supplied by the client request
|
|
134
140
|
*/
|
|
135
141
|
getClientUserAgent() {
|
|
@@ -259,9 +265,25 @@ class RequestInfo {
|
|
|
259
265
|
|
|
260
266
|
|
|
261
267
|
/**
|
|
262
|
-
* Obtain lambda event request details for logging
|
|
263
|
-
*
|
|
264
|
-
*
|
|
268
|
+
* Obtain lambda event request details for logging.
|
|
269
|
+
* Parses the API Gateway event to extract client information including IP,
|
|
270
|
+
* user agent, origin, referrer, headers, and query parameters.
|
|
271
|
+
*
|
|
272
|
+
* For `client.ip`, the `x-forwarded-for` header is preferred over
|
|
273
|
+
* `identity.sourceIp`. When `x-forwarded-for` is present and non-empty,
|
|
274
|
+
* the first IP from the comma-separated list is used (trimmed). This
|
|
275
|
+
* ensures the original client IP is returned when behind a proxy such
|
|
276
|
+
* as CloudFront. Falls back to `identity.sourceIp` when the header is
|
|
277
|
+
* absent or empty.
|
|
278
|
+
*
|
|
279
|
+
* For `client.userAgent`, the `user-agent` header is preferred over
|
|
280
|
+
* `identity.userAgent`. When the header is present and non-empty, its
|
|
281
|
+
* value is used directly. This ensures the original client user agent
|
|
282
|
+
* is returned instead of a proxy identifier (e.g. "Amazon CloudFront").
|
|
283
|
+
* Falls back to `identity.userAgent` when the header is absent or empty.
|
|
284
|
+
*
|
|
285
|
+
* @param {object} event - API Gateway Lambda event object
|
|
286
|
+
* @returns {{ip: string|null, userAgent: string|null, origin: string|null, referrer: string|null, ifModifiedSince: string|null, ifNoneMatch: string|null, accept: string|null, headers: object, parameters: object, body: string|null}} Client request information
|
|
265
287
|
*/
|
|
266
288
|
_clientRequestInfo (event) {
|
|
267
289
|
|
|
@@ -292,11 +314,24 @@ class RequestInfo {
|
|
|
292
314
|
client.ip = identity.sourceIp;
|
|
293
315
|
}
|
|
294
316
|
|
|
317
|
+
// if x-forwarded-for header is present, prefer it over identity.sourceIp (first IP in the list is the original client)
|
|
318
|
+
if ( "x-forwarded-for" in headers && headers["x-forwarded-for"] !== null && headers["x-forwarded-for"] !== "" ) {
|
|
319
|
+
let firstIp = headers["x-forwarded-for"].split(",")[0].trim();
|
|
320
|
+
if ( firstIp !== "" ) {
|
|
321
|
+
client.ip = firstIp;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
295
325
|
// if there is a user-agent header, set it
|
|
296
326
|
if ( "userAgent" in identity && identity.userAgent !== null ) {
|
|
297
327
|
client.userAgent = identity.userAgent;
|
|
298
328
|
}
|
|
299
329
|
|
|
330
|
+
// if user-agent header is present, prefer it over identity.userAgent (original client user agent)
|
|
331
|
+
if ( "user-agent" in headers && headers["user-agent"] !== null && headers["user-agent"] !== "" ) {
|
|
332
|
+
client.userAgent = headers["user-agent"];
|
|
333
|
+
}
|
|
334
|
+
|
|
300
335
|
// if there is an origin header, set it
|
|
301
336
|
if ( headers?.origin) {
|
|
302
337
|
client.origin = headers.origin;
|