@c15t/backend 1.2.0-canary.13 → 1.2.0-canary.2
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/.turbo/turbo-build.log +20 -22
- package/.turbo/turbo-fmt.log +4 -4
- package/.turbo/turbo-test.log +531 -0
- package/coverage/coverage-final.json +84 -0
- package/coverage/coverage-summary.json +85 -0
- package/coverage/html/backend/index.html +116 -0
- package/coverage/html/backend/rslib.config.ts.html +415 -0
- package/coverage/html/backend/src/contracts/consent/index.html +161 -0
- package/coverage/html/backend/src/contracts/consent/index.ts.html +112 -0
- package/coverage/html/backend/src/contracts/consent/post.contract.ts.html +559 -0
- package/coverage/html/backend/src/contracts/consent/show-banner.contract.ts.html +220 -0
- package/coverage/html/backend/src/contracts/consent/verify.contract.ts.html +463 -0
- package/coverage/html/backend/src/contracts/index.html +116 -0
- package/coverage/html/backend/src/contracts/index.ts.html +139 -0
- package/coverage/html/backend/src/contracts/meta/index.html +131 -0
- package/coverage/html/backend/src/contracts/meta/index.ts.html +100 -0
- package/coverage/html/backend/src/contracts/meta/status.contract.ts.html +196 -0
- package/coverage/html/backend/src/contracts/shared/index.html +116 -0
- package/coverage/html/backend/src/contracts/shared/jurisdiction.schema.ts.html +175 -0
- package/coverage/html/backend/src/core.ts.html +1624 -0
- package/coverage/html/backend/src/handlers/consent/index.html +161 -0
- package/coverage/html/backend/src/handlers/consent/index.ts.html +112 -0
- package/coverage/html/backend/src/handlers/consent/post.handler.ts.html +889 -0
- package/coverage/html/backend/src/handlers/consent/show-banner.handler.ts.html +535 -0
- package/coverage/html/backend/src/handlers/consent/verify.handler.ts.html +1000 -0
- package/coverage/html/backend/src/handlers/meta/index.html +131 -0
- package/coverage/html/backend/src/handlers/meta/index.ts.html +100 -0
- package/coverage/html/backend/src/handlers/meta/status.handler.ts.html +226 -0
- package/coverage/html/backend/src/index.html +161 -0
- package/coverage/html/backend/src/init.ts.html +1018 -0
- package/coverage/html/backend/src/pkgs/api-router/hooks/index.html +116 -0
- package/coverage/html/backend/src/pkgs/api-router/hooks/processor.ts.html +544 -0
- package/coverage/html/backend/src/pkgs/api-router/index.html +116 -0
- package/coverage/html/backend/src/pkgs/api-router/telemetry.ts.html +334 -0
- package/coverage/html/backend/src/pkgs/api-router/utils/cors.ts.html +304 -0
- package/coverage/html/backend/src/pkgs/api-router/utils/index.html +131 -0
- package/coverage/html/backend/src/pkgs/api-router/utils/ip.ts.html +361 -0
- package/coverage/html/backend/src/pkgs/data-model/fields/field-factory.ts.html +709 -0
- package/coverage/html/backend/src/pkgs/data-model/fields/id-generator.ts.html +256 -0
- package/coverage/html/backend/src/pkgs/data-model/fields/index.html +161 -0
- package/coverage/html/backend/src/pkgs/data-model/fields/superjson-utils.ts.html +136 -0
- package/coverage/html/backend/src/pkgs/data-model/fields/zod-fields.ts.html +496 -0
- package/coverage/html/backend/src/pkgs/data-model/hooks/create-hooks.ts.html +349 -0
- package/coverage/html/backend/src/pkgs/data-model/hooks/index.html +176 -0
- package/coverage/html/backend/src/pkgs/data-model/hooks/update-hooks.ts.html +358 -0
- package/coverage/html/backend/src/pkgs/data-model/hooks/update-many-hooks.ts.html +613 -0
- package/coverage/html/backend/src/pkgs/data-model/hooks/utils.ts.html +538 -0
- package/coverage/html/backend/src/pkgs/data-model/hooks/with-hooks-factory.ts.html +289 -0
- package/coverage/html/backend/src/pkgs/db-adapters/adapter-factory.ts.html +289 -0
- package/coverage/html/backend/src/pkgs/db-adapters/adapters/drizzle-adapter/drizzle-adapter.ts.html +2203 -0
- package/coverage/html/backend/src/pkgs/db-adapters/adapters/drizzle-adapter/index.html +116 -0
- package/coverage/html/backend/src/pkgs/db-adapters/adapters/index.html +116 -0
- package/coverage/html/backend/src/pkgs/db-adapters/adapters/kysely-adapter/dialect.ts.html +670 -0
- package/coverage/html/backend/src/pkgs/db-adapters/adapters/kysely-adapter/index.html +131 -0
- package/coverage/html/backend/src/pkgs/db-adapters/adapters/kysely-adapter/kysely-adapter.ts.html +3634 -0
- package/coverage/html/backend/src/pkgs/db-adapters/adapters/kysely-adapter/tests/index.html +116 -0
- package/coverage/html/backend/src/pkgs/db-adapters/adapters/kysely-adapter/tests/test-utils.ts.html +1417 -0
- package/coverage/html/backend/src/pkgs/db-adapters/adapters/memory-adapter/index.html +116 -0
- package/coverage/html/backend/src/pkgs/db-adapters/adapters/memory-adapter/memory-adapter.ts.html +2071 -0
- package/coverage/html/backend/src/pkgs/db-adapters/adapters/prisma-adapter/index.html +116 -0
- package/coverage/html/backend/src/pkgs/db-adapters/adapters/prisma-adapter/prisma-adapter.ts.html +1834 -0
- package/coverage/html/backend/src/pkgs/db-adapters/adapters/test.ts.html +316 -0
- package/coverage/html/backend/src/pkgs/db-adapters/index.html +131 -0
- package/coverage/html/backend/src/pkgs/db-adapters/utils.ts.html +238 -0
- package/coverage/html/backend/src/pkgs/migrations/get-migration.ts.html +343 -0
- package/coverage/html/backend/src/pkgs/migrations/get-schema/get-schema.ts.html +217 -0
- package/coverage/html/backend/src/pkgs/migrations/get-schema/index.html +146 -0
- package/coverage/html/backend/src/pkgs/migrations/get-schema/process-fields.ts.html +280 -0
- package/coverage/html/backend/src/pkgs/migrations/get-schema/process-tables.ts.html +289 -0
- package/coverage/html/backend/src/pkgs/migrations/index.html +176 -0
- package/coverage/html/backend/src/pkgs/migrations/migration-builders.ts.html +595 -0
- package/coverage/html/backend/src/pkgs/migrations/migration-execution.ts.html +301 -0
- package/coverage/html/backend/src/pkgs/migrations/schema-comparison.ts.html +694 -0
- package/coverage/html/backend/src/pkgs/migrations/type-mapping.ts.html +817 -0
- package/coverage/html/backend/src/pkgs/results/core/error-class.ts.html +976 -0
- package/coverage/html/backend/src/pkgs/results/core/error-codes.ts.html +703 -0
- package/coverage/html/backend/src/pkgs/results/core/index.html +146 -0
- package/coverage/html/backend/src/pkgs/results/core/tracing.ts.html +280 -0
- package/coverage/html/backend/src/pkgs/results/create-telemetry-options.ts.html +271 -0
- package/coverage/html/backend/src/pkgs/results/index.html +131 -0
- package/coverage/html/backend/src/pkgs/results/orpc-error-handler.ts.html +496 -0
- package/coverage/html/backend/src/pkgs/results/results/index.html +131 -0
- package/coverage/html/backend/src/pkgs/results/results/recovery-utils.ts.html +628 -0
- package/coverage/html/backend/src/pkgs/results/results/result-helpers.ts.html +1234 -0
- package/coverage/html/backend/src/pkgs/utils/env.ts.html +337 -0
- package/coverage/html/backend/src/pkgs/utils/index.html +146 -0
- package/coverage/html/backend/src/pkgs/utils/logger.ts.html +199 -0
- package/coverage/html/backend/src/pkgs/utils/url.ts.html +400 -0
- package/coverage/html/backend/src/router.ts.html +109 -0
- package/coverage/html/backend/src/schema/audit-log/index.html +146 -0
- package/coverage/html/backend/src/schema/audit-log/registry.ts.html +436 -0
- package/coverage/html/backend/src/schema/audit-log/schema.ts.html +223 -0
- package/coverage/html/backend/src/schema/audit-log/table.ts.html +640 -0
- package/coverage/html/backend/src/schema/consent/index.html +146 -0
- package/coverage/html/backend/src/schema/consent/registry.ts.html +616 -0
- package/coverage/html/backend/src/schema/consent/schema.ts.html +238 -0
- package/coverage/html/backend/src/schema/consent/table.ts.html +748 -0
- package/coverage/html/backend/src/schema/consent-policy/index.html +146 -0
- package/coverage/html/backend/src/schema/consent-policy/registry.ts.html +1063 -0
- package/coverage/html/backend/src/schema/consent-policy/schema.ts.html +265 -0
- package/coverage/html/backend/src/schema/consent-policy/table.ts.html +535 -0
- package/coverage/html/backend/src/schema/consent-purpose/index.html +146 -0
- package/coverage/html/backend/src/schema/consent-purpose/registry.ts.html +589 -0
- package/coverage/html/backend/src/schema/consent-purpose/schema.ts.html +259 -0
- package/coverage/html/backend/src/schema/consent-purpose/table.ts.html +547 -0
- package/coverage/html/backend/src/schema/consent-record/index.html +131 -0
- package/coverage/html/backend/src/schema/consent-record/schema.ts.html +211 -0
- package/coverage/html/backend/src/schema/consent-record/table.ts.html +457 -0
- package/coverage/html/backend/src/schema/create-registry.ts.html +148 -0
- package/coverage/html/backend/src/schema/definition.ts.html +685 -0
- package/coverage/html/backend/src/schema/domain/index.html +146 -0
- package/coverage/html/backend/src/schema/domain/registry.ts.html +973 -0
- package/coverage/html/backend/src/schema/domain/schema.ts.html +214 -0
- package/coverage/html/backend/src/schema/domain/table.ts.html +496 -0
- package/coverage/html/backend/src/schema/index.html +146 -0
- package/coverage/html/backend/src/schema/schemas.ts.html +166 -0
- package/coverage/html/backend/src/schema/subject/index.html +146 -0
- package/coverage/html/backend/src/schema/subject/registry.ts.html +973 -0
- package/coverage/html/backend/src/schema/subject/schema.ts.html +208 -0
- package/coverage/html/backend/src/schema/subject/table.ts.html +499 -0
- package/coverage/html/backend/src/server.ts.html +475 -0
- package/coverage/html/backend/src/testing/contract-testing.ts.html +1348 -0
- package/coverage/html/backend/src/testing/index.html +116 -0
- package/coverage/html/base.css +224 -0
- package/coverage/html/block-navigation.js +87 -0
- package/coverage/html/favicon.png +0 -0
- package/coverage/html/index.html +626 -0
- package/coverage/html/prettify.css +1 -0
- package/coverage/html/prettify.js +2 -0
- package/coverage/html/sort-arrow-sprite.png +0 -0
- package/coverage/html/sorter.js +196 -0
- package/dist/contracts/consent/index.d.ts +2 -2
- package/dist/contracts/consent/post.contract.d.ts +2 -2
- package/dist/contracts/consent/post.contract.d.ts.map +1 -1
- package/dist/contracts/index.d.ts +5 -5
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/core.cjs +244 -388
- package/dist/core.d.ts +5 -3
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +244 -388
- package/dist/handlers/consent/index.d.ts +2 -2
- package/dist/handlers/consent/post.handler.d.ts +2 -2
- package/dist/handlers/consent/show-banner.handler.d.ts.map +1 -1
- package/dist/pkgs/api-router/utils/core.test.d.ts +2 -0
- package/dist/pkgs/api-router/utils/core.test.d.ts.map +1 -0
- package/dist/pkgs/api-router/utils/cors.d.ts +14 -0
- package/dist/pkgs/api-router/utils/cors.d.ts.map +1 -0
- package/dist/pkgs/data-model/fields/zod-fields.d.ts +32 -32
- package/dist/pkgs/data-model/index.cjs +39 -59
- package/dist/pkgs/data-model/index.js +39 -59
- package/dist/pkgs/data-model/schema/index.cjs +39 -59
- package/dist/pkgs/data-model/schema/index.js +39 -59
- package/dist/pkgs/db-adapters/adapters/drizzle-adapter/index.cjs +1 -0
- package/dist/pkgs/db-adapters/adapters/drizzle-adapter/index.js +1 -0
- package/dist/pkgs/db-adapters/adapters/kysely-adapter/index.cjs +1 -0
- package/dist/pkgs/db-adapters/adapters/kysely-adapter/index.js +1 -0
- package/dist/pkgs/db-adapters/adapters/memory-adapter/index.cjs +1 -0
- package/dist/pkgs/db-adapters/adapters/memory-adapter/index.js +1 -0
- package/dist/pkgs/db-adapters/adapters/prisma-adapter/index.cjs +1 -0
- package/dist/pkgs/db-adapters/adapters/prisma-adapter/index.js +1 -0
- package/dist/pkgs/db-adapters/index.cjs +1 -0
- package/dist/pkgs/db-adapters/index.js +1 -0
- package/dist/pkgs/migrations/index.cjs +1 -0
- package/dist/pkgs/migrations/index.js +1 -0
- package/dist/router.cjs +5 -3
- package/dist/router.d.ts +2 -2
- package/dist/router.js +5 -3
- package/dist/schema/consent-policy/registry.d.ts +4 -4
- package/dist/schema/consent-policy/registry.d.ts.map +1 -1
- package/dist/schema/consent-policy/schema.d.ts +2 -2
- package/dist/schema/consent-policy/table.d.ts +2 -2
- package/dist/schema/consent-purpose/registry.d.ts +2 -2
- package/dist/schema/consent-purpose/schema.d.ts +2 -2
- package/dist/schema/consent-purpose/table.d.ts +2 -2
- package/dist/schema/create-registry.d.ts +6 -6
- package/dist/schema/create-registry.d.ts.map +1 -1
- package/dist/schema/definition.d.ts +4 -4
- package/dist/schema/index.cjs +39 -59
- package/dist/schema/index.js +39 -59
- package/dist/schema/schemas.d.ts +4 -4
- package/package.json +2 -8
- package/rslib.config.ts +0 -1
- package/src/contracts/consent/post.contract.ts +6 -1
- package/src/contracts/index.ts +0 -2
- package/src/core.ts +195 -96
- package/src/handlers/consent/show-banner.handler.test.ts +1 -1
- package/src/handlers/consent/show-banner.handler.ts +2 -1
- package/src/{middleware/cors/is-origin-trusted.test.ts → pkgs/api-router/utils/core.test.ts} +1 -1
- package/src/pkgs/api-router/utils/cors.ts +73 -0
- package/src/schema/consent-policy/registry.ts +50 -76
- package/src/server.ts +5 -1
- package/dist/__tests__/server.test.d.ts +0 -2
- package/dist/__tests__/server.test.d.ts.map +0 -1
- package/dist/contracts.cjs +0 -708
- package/dist/contracts.js +0 -661
- package/dist/middleware/cors/cors.d.ts +0 -37
- package/dist/middleware/cors/cors.d.ts.map +0 -1
- package/dist/middleware/cors/cors.test.d.ts +0 -2
- package/dist/middleware/cors/cors.test.d.ts.map +0 -1
- package/dist/middleware/cors/index.d.ts +0 -30
- package/dist/middleware/cors/index.d.ts.map +0 -1
- package/dist/middleware/cors/is-origin-trusted.d.ts +0 -49
- package/dist/middleware/cors/is-origin-trusted.d.ts.map +0 -1
- package/dist/middleware/cors/is-origin-trusted.test.d.ts +0 -2
- package/dist/middleware/cors/is-origin-trusted.test.d.ts.map +0 -1
- package/dist/middleware/cors/process-cors.d.ts +0 -31
- package/dist/middleware/cors/process-cors.d.ts.map +0 -1
- package/dist/middleware/openapi/config.d.ts +0 -28
- package/dist/middleware/openapi/config.d.ts.map +0 -1
- package/dist/middleware/openapi/handlers.d.ts +0 -29
- package/dist/middleware/openapi/handlers.d.ts.map +0 -1
- package/dist/middleware/openapi/index.d.ts +0 -11
- package/dist/middleware/openapi/index.d.ts.map +0 -1
- package/src/__tests__/server.test.ts +0 -96
- package/src/middleware/cors/cors.test.ts +0 -419
- package/src/middleware/cors/cors.ts +0 -192
- package/src/middleware/cors/index.ts +0 -30
- package/src/middleware/cors/is-origin-trusted.ts +0 -126
- package/src/middleware/cors/process-cors.ts +0 -91
- package/src/middleware/openapi/config.ts +0 -28
- package/src/middleware/openapi/handlers.ts +0 -132
- package/src/middleware/openapi/index.ts +0 -11
|
@@ -1,419 +0,0 @@
|
|
|
1
|
-
import { setupServer } from 'msw/node';
|
|
2
|
-
import { afterAll, afterEach, beforeAll, describe, expect, it } from 'vitest';
|
|
3
|
-
import { c15tInstance } from '../../core';
|
|
4
|
-
|
|
5
|
-
// Create MSW server instance
|
|
6
|
-
const server = setupServer();
|
|
7
|
-
|
|
8
|
-
// Setup and teardown
|
|
9
|
-
beforeAll(() => server.listen());
|
|
10
|
-
afterEach(() => server.resetHandlers());
|
|
11
|
-
afterAll(() => server.close());
|
|
12
|
-
|
|
13
|
-
describe('C15T CORS Configuration', () => {
|
|
14
|
-
const baseUrl = 'https://api.example.com';
|
|
15
|
-
const testEndpoint = '/show-consent-banner';
|
|
16
|
-
|
|
17
|
-
// Helper function to create a test request
|
|
18
|
-
const createTestRequest = (origin?: string, method = 'GET') => {
|
|
19
|
-
const headers: Record<string, string> = {
|
|
20
|
-
'content-type': 'application/json',
|
|
21
|
-
};
|
|
22
|
-
if (origin) {
|
|
23
|
-
headers.origin = origin;
|
|
24
|
-
}
|
|
25
|
-
return new Request(`${baseUrl}${testEndpoint}`, {
|
|
26
|
-
method,
|
|
27
|
-
headers,
|
|
28
|
-
});
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
// Helper function to create a test instance
|
|
32
|
-
const createTestInstance = (trustedOrigins?: string[]) => {
|
|
33
|
-
return c15tInstance({
|
|
34
|
-
trustedOrigins,
|
|
35
|
-
appName: 'Test App',
|
|
36
|
-
});
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
describe('Wildcard Origin Configuration', () => {
|
|
40
|
-
it('should allow any origin when trustedOrigins includes "*"', async () => {
|
|
41
|
-
const c15t = createTestInstance(['*']);
|
|
42
|
-
const request = createTestRequest('http://localhost:3002');
|
|
43
|
-
|
|
44
|
-
const response = await c15t.handler(request);
|
|
45
|
-
expect(response.status).toBe(200);
|
|
46
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(
|
|
47
|
-
'http://localhost:3002'
|
|
48
|
-
);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('should handle requests without origin header', async () => {
|
|
52
|
-
const c15t = createTestInstance(['*']);
|
|
53
|
-
const request = createTestRequest();
|
|
54
|
-
|
|
55
|
-
const response = await c15t.handler(request);
|
|
56
|
-
expect(response.status).toBe(200);
|
|
57
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*');
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe('Specific Origin Configuration', () => {
|
|
62
|
-
it('should allow requests from trusted origins', async () => {
|
|
63
|
-
const c15t = createTestInstance(['http://localhost:3002']);
|
|
64
|
-
const request = createTestRequest('http://localhost:3002');
|
|
65
|
-
|
|
66
|
-
const response = await c15t.handler(request);
|
|
67
|
-
expect(response.status).toBe(200);
|
|
68
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(
|
|
69
|
-
'http://localhost:3002'
|
|
70
|
-
);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('should deny requests from untrusted origins', async () => {
|
|
74
|
-
const c15t = createTestInstance(['http://localhost:3002']);
|
|
75
|
-
const request = createTestRequest('http://malicious-site.com');
|
|
76
|
-
|
|
77
|
-
const response = await c15t.handler(request);
|
|
78
|
-
expect(response.status).toBe(200);
|
|
79
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(null);
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
describe('Default Configuration', () => {
|
|
84
|
-
it('should use default CORS settings when no trustedOrigins specified', async () => {
|
|
85
|
-
const c15t = createTestInstance();
|
|
86
|
-
const request = createTestRequest('http://localhost:3002');
|
|
87
|
-
|
|
88
|
-
const response = await c15t.handler(request);
|
|
89
|
-
expect(response.status).toBe(200);
|
|
90
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(
|
|
91
|
-
'http://localhost:3002'
|
|
92
|
-
);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('should handle undefined trustedOrigins gracefully', async () => {
|
|
96
|
-
const c15t = createTestInstance(undefined);
|
|
97
|
-
const request = createTestRequest('http://localhost:3002');
|
|
98
|
-
|
|
99
|
-
const response = await c15t.handler(request);
|
|
100
|
-
expect(response.status).toBe(200);
|
|
101
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(
|
|
102
|
-
'http://localhost:3002'
|
|
103
|
-
);
|
|
104
|
-
expect(response.headers.get('Access-Control-Allow-Credentials')).toBe(
|
|
105
|
-
'true'
|
|
106
|
-
);
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
describe('Preflight Requests', () => {
|
|
111
|
-
it('should handle OPTIONS requests correctly', async () => {
|
|
112
|
-
const c15t = createTestInstance(['http://localhost:3002']);
|
|
113
|
-
const request = createTestRequest('http://localhost:3002', 'OPTIONS');
|
|
114
|
-
|
|
115
|
-
const response = await c15t.handler(request);
|
|
116
|
-
expect(response.status).toBe(204);
|
|
117
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(
|
|
118
|
-
'http://localhost:3002'
|
|
119
|
-
);
|
|
120
|
-
expect(response.headers.get('Access-Control-Allow-Methods')).toContain(
|
|
121
|
-
'GET'
|
|
122
|
-
);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it('should handle preflight requests with undefined trustedOrigins', async () => {
|
|
126
|
-
const c15t = createTestInstance(undefined);
|
|
127
|
-
const request = createTestRequest('http://localhost:3002', 'OPTIONS');
|
|
128
|
-
|
|
129
|
-
const response = await c15t.handler(request);
|
|
130
|
-
expect(response.status).toBe(204);
|
|
131
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(
|
|
132
|
-
'http://localhost:3002'
|
|
133
|
-
);
|
|
134
|
-
expect(response.headers.get('Access-Control-Allow-Methods')).toBe(
|
|
135
|
-
'GET, HEAD, PUT, POST, DELETE, PATCH'
|
|
136
|
-
);
|
|
137
|
-
expect(response.headers.get('Access-Control-Allow-Headers')).toBe(
|
|
138
|
-
'Content-Type, Authorization, x-request-id'
|
|
139
|
-
);
|
|
140
|
-
expect(response.headers.get('Access-Control-Max-Age')).toBe('600');
|
|
141
|
-
expect(response.headers.get('Access-Control-Allow-Credentials')).toBe(
|
|
142
|
-
'true'
|
|
143
|
-
);
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it('should handle preflight requests without origin header when trustedOrigins is undefined', async () => {
|
|
147
|
-
const c15t = createTestInstance(undefined);
|
|
148
|
-
const request = createTestRequest(undefined, 'OPTIONS');
|
|
149
|
-
|
|
150
|
-
const response = await c15t.handler(request);
|
|
151
|
-
expect(response.status).toBe(204);
|
|
152
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*');
|
|
153
|
-
expect(response.headers.get('Access-Control-Allow-Methods')).toBe(
|
|
154
|
-
'GET, HEAD, PUT, POST, DELETE, PATCH'
|
|
155
|
-
);
|
|
156
|
-
expect(response.headers.get('Access-Control-Allow-Headers')).toBe(
|
|
157
|
-
'Content-Type, Authorization, x-request-id'
|
|
158
|
-
);
|
|
159
|
-
expect(response.headers.get('Access-Control-Max-Age')).toBe('600');
|
|
160
|
-
expect(response.headers.get('Access-Control-Allow-Credentials')).toBe(
|
|
161
|
-
'true'
|
|
162
|
-
);
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
describe('Method Support', () => {
|
|
167
|
-
it('should support all required HTTP methods', async () => {
|
|
168
|
-
const c15t = createTestInstance(['http://localhost:3002']);
|
|
169
|
-
const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'] as const;
|
|
170
|
-
|
|
171
|
-
for (const method of methods) {
|
|
172
|
-
const request = createTestRequest('http://localhost:3002', method);
|
|
173
|
-
const response = await c15t.handler(request);
|
|
174
|
-
|
|
175
|
-
// For methods other than GET, we expect 404 since we only defined GET endpoints
|
|
176
|
-
const expectedStatus = method === 'GET' ? 200 : 404;
|
|
177
|
-
expect(response.status).toBe(expectedStatus);
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
describe('CORS Blocking Scenarios', () => {
|
|
183
|
-
it('should block preflight requests from untrusted origins', async () => {
|
|
184
|
-
const c15t = createTestInstance(['http://localhost:3001']);
|
|
185
|
-
const request = createTestRequest('http://localhost:3002', 'OPTIONS');
|
|
186
|
-
|
|
187
|
-
const response = await c15t.handler(request);
|
|
188
|
-
expect(response.status).toBe(204);
|
|
189
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(null);
|
|
190
|
-
expect(response.headers.get('Access-Control-Allow-Methods')).toBe(
|
|
191
|
-
'GET, HEAD, PUT, POST, DELETE, PATCH'
|
|
192
|
-
);
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
it('should block actual requests from untrusted origins', async () => {
|
|
196
|
-
const c15t = createTestInstance(['http://localhost:3001']);
|
|
197
|
-
const request = createTestRequest('http://localhost:3002', 'POST');
|
|
198
|
-
|
|
199
|
-
const response = await c15t.handler(request);
|
|
200
|
-
expect(response.status).toBe(404);
|
|
201
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(null);
|
|
202
|
-
expect(response.headers.get('Access-Control-Allow-Credentials')).toBe(
|
|
203
|
-
null
|
|
204
|
-
);
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
it('should handle preflight requests with missing origin header', async () => {
|
|
208
|
-
const c15t = createTestInstance(['http://localhost:3001']);
|
|
209
|
-
const request = createTestRequest(undefined, 'OPTIONS');
|
|
210
|
-
|
|
211
|
-
const response = await c15t.handler(request);
|
|
212
|
-
expect(response.status).toBe(204);
|
|
213
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*');
|
|
214
|
-
expect(response.headers.get('Access-Control-Allow-Methods')).toContain(
|
|
215
|
-
'GET'
|
|
216
|
-
);
|
|
217
|
-
});
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
describe('CORS Header Requirements', () => {
|
|
221
|
-
it('should include all required CORS headers for preflight requests from trusted origins', async () => {
|
|
222
|
-
const c15t = createTestInstance(['http://localhost:3002']);
|
|
223
|
-
const request = createTestRequest('http://localhost:3002', 'OPTIONS');
|
|
224
|
-
const response = await c15t.handler(request);
|
|
225
|
-
expect(response.status).toBe(204);
|
|
226
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(
|
|
227
|
-
'http://localhost:3002'
|
|
228
|
-
);
|
|
229
|
-
expect(response.headers.get('Access-Control-Allow-Methods')).toContain(
|
|
230
|
-
'GET'
|
|
231
|
-
);
|
|
232
|
-
expect(response.headers.get('Access-Control-Allow-Headers')).toContain(
|
|
233
|
-
'Content-Type'
|
|
234
|
-
);
|
|
235
|
-
expect(response.headers.get('Access-Control-Allow-Headers')).toContain(
|
|
236
|
-
'Authorization'
|
|
237
|
-
);
|
|
238
|
-
expect(response.headers.get('Access-Control-Max-Age')).toBe('600');
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
it('should NOT include CORS headers for preflight requests from untrusted origins', async () => {
|
|
242
|
-
const c15t = createTestInstance(['http://localhost:3001']);
|
|
243
|
-
const request = createTestRequest('http://localhost:3002', 'OPTIONS');
|
|
244
|
-
const response = await c15t.handler(request);
|
|
245
|
-
expect(response.status).toBe(204);
|
|
246
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(null);
|
|
247
|
-
expect(response.headers.get('Access-Control-Allow-Methods')).toBe(
|
|
248
|
-
'GET, HEAD, PUT, POST, DELETE, PATCH'
|
|
249
|
-
);
|
|
250
|
-
expect(response.headers.get('Access-Control-Allow-Headers')).toBe(
|
|
251
|
-
'Content-Type, Authorization, x-request-id'
|
|
252
|
-
);
|
|
253
|
-
expect(response.headers.get('Access-Control-Max-Age')).toBe('600');
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
it('should include all required CORS headers for actual requests from trusted origins', async () => {
|
|
257
|
-
const c15t = createTestInstance(['http://localhost:3002']);
|
|
258
|
-
const request = createTestRequest('http://localhost:3002', 'GET');
|
|
259
|
-
const response = await c15t.handler(request);
|
|
260
|
-
expect(response.status).toBe(200);
|
|
261
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(
|
|
262
|
-
'http://localhost:3002'
|
|
263
|
-
);
|
|
264
|
-
expect(response.headers.get('Access-Control-Allow-Credentials')).toBe(
|
|
265
|
-
'true'
|
|
266
|
-
);
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
it('should NOT include Access-Control-Allow-Origin for actual requests from untrusted origins', async () => {
|
|
270
|
-
const c15t = createTestInstance(['http://localhost:3001']);
|
|
271
|
-
const request = createTestRequest('http://localhost:3002', 'GET');
|
|
272
|
-
const response = await c15t.handler(request);
|
|
273
|
-
expect(response.status).toBe(200);
|
|
274
|
-
expect(response.headers.get('Vary')).toBe('origin');
|
|
275
|
-
expect(response.headers.get('Access-Control-Allow-Credentials')).toBe(
|
|
276
|
-
'true'
|
|
277
|
-
);
|
|
278
|
-
});
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
describe('C15T CORS www/non-www Origin Handling', () => {
|
|
282
|
-
const baseUrl = 'https://api.example.com';
|
|
283
|
-
const testEndpoint = '/show-consent-banner';
|
|
284
|
-
const wwwOrigin = 'http://www.c15t.com';
|
|
285
|
-
const nonWwwOrigin = 'http://c15t.com';
|
|
286
|
-
|
|
287
|
-
const createTestRequest = (origin?: string, method = 'GET') => {
|
|
288
|
-
const headers: Record<string, string> = {
|
|
289
|
-
'content-type': 'application/json',
|
|
290
|
-
};
|
|
291
|
-
if (origin) {
|
|
292
|
-
headers.origin = origin;
|
|
293
|
-
}
|
|
294
|
-
return new Request(`${baseUrl}${testEndpoint}`, { method, headers });
|
|
295
|
-
};
|
|
296
|
-
|
|
297
|
-
it('should allow www origin if non-www is trusted', async () => {
|
|
298
|
-
const c15t = c15tInstance({
|
|
299
|
-
trustedOrigins: [nonWwwOrigin],
|
|
300
|
-
appName: 'Test App',
|
|
301
|
-
});
|
|
302
|
-
const request = createTestRequest(wwwOrigin);
|
|
303
|
-
const response = await c15t.handler(request);
|
|
304
|
-
expect(response.status).toBe(200);
|
|
305
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(
|
|
306
|
-
wwwOrigin
|
|
307
|
-
);
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
it('should allow non-www origin if www is trusted', async () => {
|
|
311
|
-
const c15t = c15tInstance({
|
|
312
|
-
trustedOrigins: [wwwOrigin],
|
|
313
|
-
appName: 'Test App',
|
|
314
|
-
});
|
|
315
|
-
const request = createTestRequest(nonWwwOrigin);
|
|
316
|
-
const response = await c15t.handler(request);
|
|
317
|
-
expect(response.status).toBe(200);
|
|
318
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(
|
|
319
|
-
nonWwwOrigin
|
|
320
|
-
);
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
it('should allow both www and non-www origins if both are trusted', async () => {
|
|
324
|
-
const c15t = c15tInstance({
|
|
325
|
-
trustedOrigins: [wwwOrigin, nonWwwOrigin],
|
|
326
|
-
appName: 'Test App',
|
|
327
|
-
});
|
|
328
|
-
const requestWww = createTestRequest(wwwOrigin);
|
|
329
|
-
const requestNonWww = createTestRequest(nonWwwOrigin);
|
|
330
|
-
const responseWww = await c15t.handler(requestWww);
|
|
331
|
-
const responseNonWww = await c15t.handler(requestNonWww);
|
|
332
|
-
expect(responseWww.status).toBe(200);
|
|
333
|
-
expect(responseWww.headers.get('Access-Control-Allow-Origin')).toBe(
|
|
334
|
-
wwwOrigin
|
|
335
|
-
);
|
|
336
|
-
expect(responseNonWww.status).toBe(200);
|
|
337
|
-
expect(responseNonWww.headers.get('Access-Control-Allow-Origin')).toBe(
|
|
338
|
-
nonWwwOrigin
|
|
339
|
-
);
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
it('should deny unrelated origins', async () => {
|
|
343
|
-
const c15t = c15tInstance({
|
|
344
|
-
trustedOrigins: [nonWwwOrigin],
|
|
345
|
-
appName: 'Test App',
|
|
346
|
-
});
|
|
347
|
-
const unrelatedOrigin = 'http://malicious.com';
|
|
348
|
-
const request = createTestRequest(unrelatedOrigin);
|
|
349
|
-
const response = await c15t.handler(request);
|
|
350
|
-
expect(response.status).toBe(200);
|
|
351
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(null);
|
|
352
|
-
});
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
describe('CORS trustedOrigins normalization and matching', () => {
|
|
356
|
-
const baseUrl = 'https://api.example.com';
|
|
357
|
-
const testEndpoint = '/show-consent-banner';
|
|
358
|
-
|
|
359
|
-
const createTestRequest = (origin?: string, method = 'GET') => {
|
|
360
|
-
const headers: Record<string, string> = {
|
|
361
|
-
'content-type': 'application/json',
|
|
362
|
-
};
|
|
363
|
-
if (origin) {
|
|
364
|
-
headers.origin = origin;
|
|
365
|
-
}
|
|
366
|
-
return new Request(`${baseUrl}${testEndpoint}`, { method, headers });
|
|
367
|
-
};
|
|
368
|
-
|
|
369
|
-
it('should match http and https with and without www', async () => {
|
|
370
|
-
const c15t = createTestInstance(['localhost:3002', 'example.com']);
|
|
371
|
-
// Should match both http and https, with and without www
|
|
372
|
-
const origins = [
|
|
373
|
-
'http://localhost:3002',
|
|
374
|
-
'https://localhost:3002',
|
|
375
|
-
'http://www.example.com',
|
|
376
|
-
'https://example.com',
|
|
377
|
-
];
|
|
378
|
-
for (const origin of origins) {
|
|
379
|
-
const request = createTestRequest(origin, 'OPTIONS');
|
|
380
|
-
const response = await c15t.handler(request);
|
|
381
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(
|
|
382
|
-
origin
|
|
383
|
-
);
|
|
384
|
-
}
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
it('should not match unrelated origins', async () => {
|
|
388
|
-
const c15t = createTestInstance(['localhost:3002']);
|
|
389
|
-
const request = createTestRequest('http://malicious.com', 'OPTIONS');
|
|
390
|
-
const response = await c15t.handler(request);
|
|
391
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(null);
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
it('should match wildcard *', async () => {
|
|
395
|
-
const c15t = createTestInstance(['*']);
|
|
396
|
-
const request = createTestRequest('http://any-origin.com', 'OPTIONS');
|
|
397
|
-
const response = await c15t.handler(request);
|
|
398
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(
|
|
399
|
-
'http://any-origin.com'
|
|
400
|
-
);
|
|
401
|
-
});
|
|
402
|
-
|
|
403
|
-
it('should match with port', async () => {
|
|
404
|
-
const c15t = createTestInstance(['localhost:3002']);
|
|
405
|
-
const request = createTestRequest('http://localhost:3002', 'OPTIONS');
|
|
406
|
-
const response = await c15t.handler(request);
|
|
407
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(
|
|
408
|
-
'http://localhost:3002'
|
|
409
|
-
);
|
|
410
|
-
});
|
|
411
|
-
|
|
412
|
-
it('should not match if port is different', async () => {
|
|
413
|
-
const c15t = createTestInstance(['localhost:3002']);
|
|
414
|
-
const request = createTestRequest('http://localhost:4000', 'OPTIONS');
|
|
415
|
-
const response = await c15t.handler(request);
|
|
416
|
-
expect(response.headers.get('Access-Control-Allow-Origin')).toBe(null);
|
|
417
|
-
});
|
|
418
|
-
});
|
|
419
|
-
});
|
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CORS middleware utility for c15t that handles origin validation and CORS headers
|
|
3
|
-
*
|
|
4
|
-
* @packageDocumentation
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/** Regular expression to match www prefix in domain names */
|
|
8
|
-
const WWW_REGEX = /^www\./;
|
|
9
|
-
|
|
10
|
-
/** Regular expression to match protocol and www prefix in URLs */
|
|
11
|
-
const PROTOCOL_WWW_REGEX = /^https?:\/\/(www\.)?/;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Supported HTTP methods for CORS
|
|
15
|
-
*/
|
|
16
|
-
const SUPPORTED_METHODS = [
|
|
17
|
-
'GET',
|
|
18
|
-
'POST',
|
|
19
|
-
'PUT',
|
|
20
|
-
'DELETE',
|
|
21
|
-
'PATCH',
|
|
22
|
-
'OPTIONS',
|
|
23
|
-
] as const;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Supported headers for CORS requests
|
|
27
|
-
*/
|
|
28
|
-
const SUPPORTED_HEADERS = [
|
|
29
|
-
'Content-Type',
|
|
30
|
-
'Authorization',
|
|
31
|
-
'x-request-id',
|
|
32
|
-
] as const;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* CORS configuration options type
|
|
36
|
-
*/
|
|
37
|
-
export interface CORSConfig {
|
|
38
|
-
/** Origin validation function */
|
|
39
|
-
origin: (origin: string) => Promise<string | null>;
|
|
40
|
-
/** Whether to allow credentials */
|
|
41
|
-
credentials: boolean;
|
|
42
|
-
/** Allowed headers */
|
|
43
|
-
allowHeaders: readonly string[];
|
|
44
|
-
/** Max age for preflight requests */
|
|
45
|
-
maxAge: number;
|
|
46
|
-
/** Allowed HTTP methods */
|
|
47
|
-
methods: readonly string[];
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Default CORS configuration for unrestricted access
|
|
52
|
-
*/
|
|
53
|
-
const DEFAULT_CORS_CONFIG: CORSConfig = {
|
|
54
|
-
origin: async (origin: string) => {
|
|
55
|
-
// For default config, always return the origin if it exists, or '*' if it doesn't
|
|
56
|
-
return await Promise.resolve(origin || '*');
|
|
57
|
-
},
|
|
58
|
-
credentials: true,
|
|
59
|
-
allowHeaders: SUPPORTED_HEADERS,
|
|
60
|
-
maxAge: 600,
|
|
61
|
-
methods: SUPPORTED_METHODS,
|
|
62
|
-
} as const;
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Creates CORS options configuration for the c15t middleware
|
|
66
|
-
*
|
|
67
|
-
* @param trustedOrigins - Array of allowed origin patterns or single string. Can include wildcards ('*').
|
|
68
|
-
* If undefined, defaults to allowing all origins without credentials.
|
|
69
|
-
*
|
|
70
|
-
* @returns CORS configuration object with origin validation function and header settings
|
|
71
|
-
*
|
|
72
|
-
* @example
|
|
73
|
-
* ```ts
|
|
74
|
-
* const corsOptions = createCORSOptions(['http://localhost:3000', 'https://example.com']);
|
|
75
|
-
* ```
|
|
76
|
-
*
|
|
77
|
-
* @throws {TypeError} When URL parsing fails in origin validation
|
|
78
|
-
*/
|
|
79
|
-
export function createCORSOptions(
|
|
80
|
-
trustedOrigins?: string[] | string
|
|
81
|
-
): CORSConfig {
|
|
82
|
-
// If trustedOrigins is undefined or empty, return default config that allows all origins
|
|
83
|
-
if (!trustedOrigins) {
|
|
84
|
-
return DEFAULT_CORS_CONFIG;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Convert string to array if needed
|
|
88
|
-
const origins = Array.isArray(trustedOrigins)
|
|
89
|
-
? trustedOrigins
|
|
90
|
-
: [trustedOrigins];
|
|
91
|
-
if (origins.length === 0) {
|
|
92
|
-
return DEFAULT_CORS_CONFIG;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Normalizes an origin string by removing protocol and www prefix
|
|
97
|
-
*
|
|
98
|
-
* @param origin - The origin URL to normalize
|
|
99
|
-
* @returns Normalized origin string without protocol and www prefix
|
|
100
|
-
*
|
|
101
|
-
* @internal
|
|
102
|
-
*/
|
|
103
|
-
function normalizeOrigin(origin: string): string {
|
|
104
|
-
try {
|
|
105
|
-
// Handle bare domains like 'localhost' or 'example.com'
|
|
106
|
-
if (
|
|
107
|
-
!origin.includes('://') &&
|
|
108
|
-
!origin.includes(':') &&
|
|
109
|
-
!origin.includes('/')
|
|
110
|
-
) {
|
|
111
|
-
return origin.toLowerCase();
|
|
112
|
-
}
|
|
113
|
-
// Add protocol if missing
|
|
114
|
-
const originWithProtocol =
|
|
115
|
-
origin.startsWith('http://') ||
|
|
116
|
-
origin.startsWith('https://') ||
|
|
117
|
-
origin.startsWith('ws://') ||
|
|
118
|
-
origin.startsWith('wss://')
|
|
119
|
-
? origin
|
|
120
|
-
: `http://${origin}`;
|
|
121
|
-
const url = new URL(originWithProtocol);
|
|
122
|
-
const hostname = url.hostname.replace(WWW_REGEX, '');
|
|
123
|
-
// Return without protocol to match both http and https
|
|
124
|
-
return `${hostname}${url.port ? `:${url.port}` : ''}`;
|
|
125
|
-
} catch {
|
|
126
|
-
// Fallback: remove www manually and protocol
|
|
127
|
-
return origin.replace(PROTOCOL_WWW_REGEX, '').replace(WWW_REGEX, '');
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Expands a list of origins to include www variants
|
|
133
|
-
*
|
|
134
|
-
* @param origins - Array of origin strings to expand
|
|
135
|
-
* @returns Array of origins including www variants
|
|
136
|
-
*
|
|
137
|
-
* @internal
|
|
138
|
-
*/
|
|
139
|
-
function expandWithWWW(origins: string[]): string[] {
|
|
140
|
-
const expanded = new Set<string>();
|
|
141
|
-
for (const origin of origins) {
|
|
142
|
-
if (origin === '*') {
|
|
143
|
-
expanded.add('*');
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
const normalized = normalizeOrigin(origin);
|
|
147
|
-
expanded.add(normalized);
|
|
148
|
-
// Add www version if not already present
|
|
149
|
-
if (!normalized.includes('www.')) {
|
|
150
|
-
expanded.add(`www.${normalized}`);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return Array.from(expanded);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const expandedTrusted = expandWithWWW(origins);
|
|
157
|
-
|
|
158
|
-
const returnConfig = {
|
|
159
|
-
origin: async (origin: string) => {
|
|
160
|
-
if (!origin) {
|
|
161
|
-
return '*';
|
|
162
|
-
}
|
|
163
|
-
const normalizedOrigin = normalizeOrigin(origin);
|
|
164
|
-
if (expandedTrusted.includes('*')) {
|
|
165
|
-
return origin;
|
|
166
|
-
}
|
|
167
|
-
// Check if the origin matches any trusted origin
|
|
168
|
-
const isTrusted = expandedTrusted.some((trusted) => {
|
|
169
|
-
const normalizedTrusted = normalizeOrigin(trusted);
|
|
170
|
-
// For localhost, match both with and without port
|
|
171
|
-
if (normalizedTrusted === 'localhost') {
|
|
172
|
-
return (
|
|
173
|
-
normalizedOrigin === 'localhost' ||
|
|
174
|
-
normalizedOrigin.startsWith('localhost:') ||
|
|
175
|
-
normalizedOrigin === '127.0.0.1' ||
|
|
176
|
-
normalizedOrigin.startsWith('127.0.0.1:') ||
|
|
177
|
-
normalizedOrigin === '[::1]' ||
|
|
178
|
-
normalizedOrigin.startsWith('[::1]:')
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
return normalizedTrusted === normalizedOrigin;
|
|
182
|
-
});
|
|
183
|
-
return isTrusted ? origin : null;
|
|
184
|
-
},
|
|
185
|
-
credentials: true,
|
|
186
|
-
allowHeaders: SUPPORTED_HEADERS,
|
|
187
|
-
maxAge: 600,
|
|
188
|
-
methods: SUPPORTED_METHODS,
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
return returnConfig;
|
|
192
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CORS middleware for c15t
|
|
3
|
-
*
|
|
4
|
-
* This module provides comprehensive CORS (Cross-Origin Resource Sharing) functionality including:
|
|
5
|
-
* - Origin validation with support for wildcards and subdomains
|
|
6
|
-
* - Flexible CORS options configuration
|
|
7
|
-
* - Context processing and enrichment
|
|
8
|
-
* - Protocol-agnostic matching
|
|
9
|
-
* - Support for www and non-www variants
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```ts
|
|
13
|
-
* import { createCORSOptions, isOriginTrusted, processCors } from '@c15t/backend/middleware/cors';
|
|
14
|
-
*
|
|
15
|
-
* // Create CORS options with trusted origins
|
|
16
|
-
* const corsOptions = createCORSOptions(['https://example.com', '*.trusted-domain.com']);
|
|
17
|
-
*
|
|
18
|
-
* // Process CORS for a request
|
|
19
|
-
* const enrichedContext = processCors(request, context, trustedOrigins);
|
|
20
|
-
*
|
|
21
|
-
* // Validate an origin directly
|
|
22
|
-
* const isTrusted = isOriginTrusted('https://api.trusted-domain.com', trustedOrigins);
|
|
23
|
-
* ```
|
|
24
|
-
*
|
|
25
|
-
* @packageDocumentation
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
export { createCORSOptions } from './cors';
|
|
29
|
-
export { isOriginTrusted } from './is-origin-trusted';
|
|
30
|
-
export { processCors } from './process-cors';
|