From fd338d0e9ba4be28bbe3eaba64b19fad1889c4e1 Mon Sep 17 00:00:00 2001 From: Bartosz Date: Wed, 10 Jun 2026 13:39:23 +0200 Subject: [PATCH] 3.1.0: slim down default request context (#195) --- CHANGELOG.md | 12 ++++ README.md | 4 +- RELEASING.md | 15 ++-- package-lock.json | 4 +- package.json | 2 +- src/client-id/client-id.module.ts | 1 - .../services/client-id-extract.service.ts | 12 ---- src/client-id/services/index.ts | 1 - .../services/context-get-default.service.ts | 10 +-- .../services/context-prepare.service.ts | 1 - .../services/headers-get-cookie.service.ts | 20 ------ src/headers/services/index.ts | 1 - .../client-id-extract.service.test.ts | 53 -------------- .../context-get-default.service.test.ts | 7 +- .../headers-get-cookie.service.test.ts | 70 ------------------- .../services/payload-prepare-service.test.ts | 1 - 16 files changed, 27 insertions(+), 187 deletions(-) delete mode 100644 src/client-id/client-id.module.ts delete mode 100644 src/client-id/services/client-id-extract.service.ts delete mode 100644 src/client-id/services/index.ts delete mode 100644 src/headers/services/headers-get-cookie.service.ts delete mode 100644 test/client-id/services/client-id-extract.service.test.ts delete mode 100644 test/headers/services/headers-get-cookie.service.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index cca129e..0448fb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## 3.1.0 + +**Housekeeping:** + +- Slim down the default request context to `headers`, `ip`, and `library`. The + client id is carried by `headers` (the `x-castle-client-id` header / `__cid` + cookie) and resolved by Castle server-side, so the SDK no longer derives it + separately. +- Remove the internal client-id extraction service and the now-unused cookie + helper (`HeadersGetCookieService`) along with the `cookies` plumbing in + `ContextGetDefaultService` / `ContextPrepareService`. + ## 3.0.0 **BREAKING CHANGES:** diff --git a/README.md b/README.md index 3976ff4..1d1738f 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ const castle = new Castle({ apiSecret: process.env.CASTLE_API_SECRET }); const context = ContextPrepareService.call( req, - { cookies: req.cookies }, + undefined, castle.configuration ); @@ -74,7 +74,7 @@ With CommonJS: const { Castle, ContextPrepareService } = require('@castleio/sdk'); ``` -`ContextPrepareService.call(request, options, configuration)` extracts the IP, headers, and client id that Castle needs from a Node `request` object. See [Advanced configuration](#advanced-configuration) for how header allow/deny lists and proxy chains are resolved. +`ContextPrepareService.call(request, options, configuration)` extracts the IP and headers that Castle needs from a Node `request` object. See [Advanced configuration](#advanced-configuration) for how header allow/deny lists and proxy chains are resolved. ## Configuration diff --git a/RELEASING.md b/RELEASING.md index 2d84c21..d258810 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,13 +1,14 @@ # Releasing -1. Create branch `release/X.Y.Z` from `master`. +1. Create branch `release/X.Y.Z` from `develop`. 2. Update `version` in `package.json` to the new version 3. Run `npm install` (to refresh `package-lock.json`) 4. Update the `CHANGELOG.md` for the impending release 5. `git commit -am "release X.Y.Z"` (where X.Y.Z is the new version) -6. Push to Github, make PR to the `master` branch, and when approved, merge. -7. Make a release on Github from the `master` branch, specify tag as `vX.Y.Z` to create a tag. -8. `git checkout master && git pull` -9. Clean unversioned files: `git clean -fdx dist` -10. `npm run build && npm pack` to verify the package -11. `npm publish` +6. Push to Github, make PR to the `develop` branch, and when approved, merge. +7. Pull latest `develop`, merge it into `master`, and push `master` to `origin`. +8. Make a release on Github from the `master` branch, specify tag as `vX.Y.Z` to create a tag. +9. `git checkout master && git pull` +10. Clean unversioned files: `git clean -fdx dist` +11. `npm run build && npm pack` to verify the package +12. `npm publish` diff --git a/package-lock.json b/package-lock.json index 2c4d2f5..e0bf4f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@castleio/sdk", - "version": "3.0.0", + "version": "3.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@castleio/sdk", - "version": "3.0.0", + "version": "3.1.0", "license": "MIT", "dependencies": { "pino": "^9.7.0", diff --git a/package.json b/package.json index 1aa1ccf..167701a 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "$schema": "http://json.schemastore.org/package", "name": "@castleio/sdk", "description": "Castle SDK for Node", - "version": "3.0.0", + "version": "3.1.0", "main": "./dist/index.js", "module": "./dist/index.mjs", "types": "./dist/index.d.ts", diff --git a/src/client-id/client-id.module.ts b/src/client-id/client-id.module.ts deleted file mode 100644 index e371345..0000000 --- a/src/client-id/client-id.module.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './services'; diff --git a/src/client-id/services/client-id-extract.service.ts b/src/client-id/services/client-id-extract.service.ts deleted file mode 100644 index b44eb51..0000000 --- a/src/client-id/services/client-id-extract.service.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { IncomingHttpHeaders } from 'http2'; -import { HeadersGetCookieService } from '../../headers/headers.module'; - -export const ClientIdExtractService = { - call: (headers: IncomingHttpHeaders = {}, cookies?: string | string[]) => { - return ( - headers['x-castle-client-id'] || - HeadersGetCookieService.call(cookies, '__cid') || - '' - ); - }, -}; diff --git a/src/client-id/services/index.ts b/src/client-id/services/index.ts deleted file mode 100644 index 049b4ed..0000000 --- a/src/client-id/services/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './client-id-extract.service'; diff --git a/src/context/services/context-get-default.service.ts b/src/context/services/context-get-default.service.ts index 8e557fd..f77fc8c 100644 --- a/src/context/services/context-get-default.service.ts +++ b/src/context/services/context-get-default.service.ts @@ -1,6 +1,5 @@ import { isEmpty, pickByTruthy } from '../../utils/object'; import { Configuration } from '../../configuration'; -import { ClientIdExtractService } from '../../client-id/client-id.module'; import { HeadersExtractService } from '../../headers/headers.module'; import { IPsExtractService } from '../../ips/ips.module'; import { version } from '../../../package.json'; @@ -8,19 +7,13 @@ import type { IncomingHttpHeaders } from 'http2'; const requestContextData = ( request: { headers: IncomingHttpHeaders }, - cookies: string | undefined, configuration: Configuration ): { [key: string]: any } => { if (isEmpty(request)) { return {}; } - const cookiesForClientId = - cookies || (request.headers as { [key: string]: any })?.cookies; return { - client_id: - ClientIdExtractService.call(request.headers, cookiesForClientId) || false, - active: true, headers: HeadersExtractService.call(request.headers, configuration), ip: IPsExtractService.call(request.headers, configuration), }; @@ -29,11 +22,10 @@ const requestContextData = ( export const ContextGetDefaultService = { call: ( request: { headers: IncomingHttpHeaders }, - cookies: string | undefined, configuration: Configuration ): { [key: string]: any } => { return { - ...pickByTruthy(requestContextData(request, cookies, configuration)), + ...pickByTruthy(requestContextData(request, configuration)), library: { name: 'castle-node', version, diff --git a/src/context/services/context-prepare.service.ts b/src/context/services/context-prepare.service.ts index fe67d76..c53bd08 100644 --- a/src/context/services/context-prepare.service.ts +++ b/src/context/services/context-prepare.service.ts @@ -11,7 +11,6 @@ export const ContextPrepareService = { ) => { const defaultContext = ContextGetDefaultService.call( request, - options?.cookies, configuration ); return deepMerge(defaultContext, options?.context); diff --git a/src/headers/services/headers-get-cookie.service.ts b/src/headers/services/headers-get-cookie.service.ts deleted file mode 100644 index d3695df..0000000 --- a/src/headers/services/headers-get-cookie.service.ts +++ /dev/null @@ -1,20 +0,0 @@ -export const HeadersGetCookieService = { - call: ( - cookies: string | string[] | undefined, - name: string - ): string | undefined => { - if (!cookies) { - return; - } - - const pattern = new RegExp(`(?:^|\\s+)\\s?${name}=(.*?)(?:;|$)`); - const results = cookies.toString().match(pattern); - - if (results && results.length === 2) { - // return the last match - return results[1]; - } - - return; - }, -}; diff --git a/src/headers/services/index.ts b/src/headers/services/index.ts index 9508f73..48cb18f 100644 --- a/src/headers/services/index.ts +++ b/src/headers/services/index.ts @@ -1,2 +1 @@ export * from './headers-extract.service'; -export * from './headers-get-cookie.service'; diff --git a/test/client-id/services/client-id-extract.service.test.ts b/test/client-id/services/client-id-extract.service.test.ts deleted file mode 100644 index b3e4e70..0000000 --- a/test/client-id/services/client-id-extract.service.test.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { ClientIdExtractService } from '../../../src/client-id/client-id.module'; - -describe('ClientIdExtractService', () => { - describe('call', () => { - const expectedFromCookie = 'abcd'; - const expectedFromHeader = 'abcde'; - - describe('with client_id', () => { - it('extracts client_id from cookie', () => { - const headers = { - cookie: '__cid=abcd;other=efgh', - 'x-forwarded-for': '1.2.3.4', - }; - const received = ClientIdExtractService.call(headers, headers.cookie); - expect(received).toEqual(expectedFromCookie); - }); - }); - - describe('with x-castle-client-id header', () => { - it('extracts client_id from cookie', () => { - const headers = { - cookie: '', - 'x-forwarded-for': '1.2.3.4', - 'x-castle-client-id': expectedFromHeader, - }; - const received = ClientIdExtractService.call(headers, headers.cookie); - expect(received).toEqual(expectedFromHeader); - }); - }); - - describe('with cookies and headers undefined', () => { - it('returns empty string', () => { - const headers = { - cookie: '', - }; - const received = ClientIdExtractService.call(headers, headers.cookie); - expect(received).toEqual(''); - }); - }); - - describe('with headers and cookie defined', () => { - it('extracts client_id from headers', () => { - const headers = { - cookie: '__cid=abcd;other=efgh', - 'x-forwarded-for': '1.2.3.4', - 'x-castle-client-id': expectedFromHeader, - }; - const received = ClientIdExtractService.call(headers, headers.cookie); - expect(received).toEqual(expectedFromHeader); - }); - }); - }); -}); diff --git a/test/context/services/context-get-default.service.test.ts b/test/context/services/context-get-default.service.test.ts index eb0e8e7..7c524ab 100644 --- a/test/context/services/context-get-default.service.test.ts +++ b/test/context/services/context-get-default.service.test.ts @@ -14,7 +14,6 @@ describe('ContextGetDefaultService', () => { name: 'castle-node', version, }, - client_id: 'client_id', ip: '1.2.3.4', }; @@ -35,11 +34,7 @@ describe('ContextGetDefaultService', () => { } as ExpressRequest; it('generates default context', () => { - const received = ContextGetDefaultService.call( - mockRequest, - undefined, - config - ); + const received = ContextGetDefaultService.call(mockRequest, config); expect(received).toMatchObject(expected); }); }); diff --git a/test/headers/services/headers-get-cookie.service.test.ts b/test/headers/services/headers-get-cookie.service.test.ts deleted file mode 100644 index a66cd90..0000000 --- a/test/headers/services/headers-get-cookie.service.test.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { HeadersGetCookieService } from '../../../src/headers/headers.module'; - -describe('HeadersGetCookieService', () => { - describe('call', () => { - it('doesnt get cookie from empty header', () => { - const headers = { - cookie: '', - }; - - expect( - HeadersGetCookieService.call(headers.cookie, '_key') - ).toBeUndefined(); - }); - - it('gets cookie with encoded value', () => { - const headers = { - cookie: - '__uid=21917; cfids187=; cf=\u002C\u003B; a_key=f195d29f3ee38e07bd95ae9c', - }; - - expect(HeadersGetCookieService.call(headers.cookie, 'cf')).toEqual(','); - }); - - it('gets cookie from the end', () => { - const headers = { - cookie: '__uid=21917; cfids187=; _key=f195d29f3ee38e07bd95ae9c', - }; - expect(HeadersGetCookieService.call(headers.cookie, '_key')).toEqual( - 'f195d29f3ee38e07bd95ae9c' - ); - }); - - it('gets cookie from the middle', () => { - const headers = { - cookie: - '__uid=21917; cfids187=; cf=abc; a_key=f195d29f3ee38e07bd95ae9c', - }; - expect(HeadersGetCookieService.call(headers.cookie, 'cf')).toEqual('abc'); - }); - - it('gets cookie from the start', () => { - const headers = { - cookie: - '__uid=21917; cfids187=; cf=abc; a_key=f195d29f3ee38e07bd95ae9c', - }; - expect(HeadersGetCookieService.call(headers.cookie, '__uid')).toEqual( - '21917' - ); - }); - - it('does not get cookie with similar prefix', () => { - const headers = { - cookie: '__uid=21917; cfids187=; a_key=f195d29f3ee38e07bd95ae9c', - }; - expect( - HeadersGetCookieService.call(headers.cookie, '_key') - ).toBeUndefined(); - }); - - it('doesnt get cookie from the middle when empty', () => { - const headers = { - cookie: - '__uid=21917; cfids187=; cf=abc; a_key=f195d29f3ee38e07bd95ae9c', - }; - expect(HeadersGetCookieService.call(headers.cookie, 'cfids187')).toEqual( - '' - ); - }); - }); -}); diff --git a/test/payload/services/payload-prepare-service.test.ts b/test/payload/services/payload-prepare-service.test.ts index 3fcb545..1f2a01a 100644 --- a/test/payload/services/payload-prepare-service.test.ts +++ b/test/payload/services/payload-prepare-service.test.ts @@ -11,7 +11,6 @@ describe('PayloadPrepareService', () => { version, }, client_id: '123', - active: true, }, user_id: '123', };