Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions my-sonicjs-app/wrangler.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ id = "a16f8246fc294d809c90b0fb2df6d363"
# Environment variables
[vars]
ENVIRONMENT = "development"
CORS_ORIGINS = "http://localhost:8787"

# Observability
[observability]
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export interface Bindings {
IMAGES_ACCOUNT_ID?: string
IMAGES_API_TOKEN?: string
ENVIRONMENT?: string
CORS_ORIGINS?: string
BUCKET_NAME?: string
GOOGLE_MAPS_API_KEY?: string
}
Expand Down
9 changes: 7 additions & 2 deletions packages/core/src/routes/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,14 @@ apiRoutes.use('*', async (c, next) => {

// Add CORS middleware
apiRoutes.use('*', cors({
origin: '*',
origin: (origin, c) => {
const allowed = (c.env as any)?.CORS_ORIGINS as string | undefined
if (!allowed) return null // No env var = reject cross-origin (secure default)
const list = allowed.split(',').map((s: string) => s.trim())
return list.includes(origin) ? origin : null
},
allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowHeaders: ['Content-Type', 'Authorization']
allowHeaders: ['Content-Type', 'Authorization', 'X-API-Key']
}))

// Helper function to add timing metadata
Expand Down
1 change: 1 addition & 0 deletions packages/create-app/templates/starter/wrangler.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ bucket_name = "my-sonicjs-media"
# Environment variables
[vars]
ENVIRONMENT = "development"
CORS_ORIGINS = "http://localhost:8787"

# Production environment
[env.production]
Expand Down
11 changes: 6 additions & 5 deletions tests/e2e/07-api.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,18 @@ test.describe('API Endpoints', () => {
});

test('should handle CORS for API endpoints', async ({ request }) => {
// Use the origin configured in CORS_ORIGINS (wrangler.toml)
const response = await request.get('/api', {
headers: {
'Origin': 'http://localhost:3000'
'Origin': 'http://localhost:8787'
}
});

expect(response.ok()).toBeTruthy();
// Check for CORS headers

// Check for CORS headers — should echo back the allowed origin
const corsHeader = response.headers()['access-control-allow-origin'];
expect(corsHeader).toBeDefined();
expect(corsHeader).toBe('http://localhost:8787');
});

test('should handle content negotiation', async ({ request }) => {
Expand Down
8 changes: 5 additions & 3 deletions tests/e2e/08-collections-api.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,16 @@ test.describe('Collections API', () => {
});

test('should handle CORS headers', async ({ request }) => {
// Use the origin configured in CORS_ORIGINS (wrangler.toml)
const response = await request.get('/api/collections', {
headers: {
'Origin': 'https://example.com'
'Origin': 'http://localhost:8787'
}
});

expect(response.ok()).toBeTruthy();
expect(response.headers()['access-control-allow-origin']).toBe('*');
// CORS now echoes back the allowed origin instead of wildcard
expect(response.headers()['access-control-allow-origin']).toBe('http://localhost:8787');
});

test('should have consistent timestamp format', async ({ request }) => {
Expand Down
8 changes: 4 additions & 4 deletions tests/e2e/smoke.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,18 +248,18 @@ test.describe('Smoke Tests - Critical Path', () => {
});

test('CORS headers are present on API endpoints', async ({ request }) => {
// Use the origin configured in CORS_ORIGINS (wrangler.toml)
const response = await request.get('/api', {
headers: {
'Origin': 'http://localhost:3000'
'Origin': 'http://localhost:8787'
}
});

expect(response.ok()).toBeTruthy();

// Verify CORS header is present
// Verify CORS header echoes back the allowed origin
const corsHeader = response.headers()['access-control-allow-origin'];
expect(corsHeader).toBeDefined();
expect(corsHeader).toBeTruthy();
expect(corsHeader).toBe('http://localhost:8787');
});

test('API returns correct content-type headers', async ({ request }) => {
Expand Down