fix(cors): add default fallback for allowedMethods to prevent undefined.join() error
Some checks failed
armco-org/node-starter-kit/pipeline/head There was a failure building this commit
Some checks failed
armco-org/node-starter-kit/pipeline/head There was a failure building this commit
- Add DEFAULT_METHODS array with common REST methods when allowedMethods not configured - Prevents crash on OPTIONS preflight requests when methods config is undefined - Add unit tests for: default methods fallback, explicit method constraints, undefined handling
This commit is contained in:
@@ -305,4 +305,71 @@ describe('CORS Middleware', () => {
|
||||
expect(res.headers['access-control-allow-origin']).toBe('http://any-origin.com')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Allowed Methods', () => {
|
||||
it('should use default methods when allowedMethods not specified', async () => {
|
||||
const app = await createAppWithCors({
|
||||
arOptions: {
|
||||
whitelist: ['http://localhost:3000'],
|
||||
},
|
||||
})
|
||||
|
||||
// OPTIONS preflight request should succeed and return allowed methods
|
||||
const res = await request(app)
|
||||
.options('/test')
|
||||
.set('Origin', 'http://localhost:3000')
|
||||
.set('Access-Control-Request-Method', 'POST')
|
||||
|
||||
expect(res.status).toBe(204)
|
||||
expect(res.headers['access-control-allow-methods']).toBeDefined()
|
||||
// Default methods should include common REST methods
|
||||
const methods = res.headers['access-control-allow-methods']
|
||||
expect(methods).toContain('GET')
|
||||
expect(methods).toContain('POST')
|
||||
expect(methods).toContain('PUT')
|
||||
expect(methods).toContain('DELETE')
|
||||
expect(methods).toContain('PATCH')
|
||||
expect(methods).toContain('OPTIONS')
|
||||
})
|
||||
|
||||
it('should constrain methods when allowedMethods is explicitly provided', async () => {
|
||||
const app = await createAppWithCors({
|
||||
allowedMethods: ['GET', 'POST'],
|
||||
arOptions: {
|
||||
whitelist: ['http://localhost:3000'],
|
||||
},
|
||||
})
|
||||
|
||||
const res = await request(app)
|
||||
.options('/test')
|
||||
.set('Origin', 'http://localhost:3000')
|
||||
.set('Access-Control-Request-Method', 'POST')
|
||||
|
||||
expect(res.status).toBe(204)
|
||||
const methods = res.headers['access-control-allow-methods']
|
||||
expect(methods).toBe('GET,POST')
|
||||
// Should NOT contain methods not in the explicit list
|
||||
expect(methods).not.toContain('DELETE')
|
||||
expect(methods).not.toContain('PUT')
|
||||
})
|
||||
|
||||
it('should not crash on OPTIONS request when allowedMethods is undefined', async () => {
|
||||
// This test ensures the fix for the undefined.join() error
|
||||
const app = await createAppWithCors({
|
||||
arOptions: {
|
||||
whitelist: ['http://localhost:3000'],
|
||||
},
|
||||
// Explicitly NOT setting allowedMethods
|
||||
})
|
||||
|
||||
// This should NOT throw "Cannot read properties of undefined (reading 'join')"
|
||||
const res = await request(app)
|
||||
.options('/test')
|
||||
.set('Origin', 'http://localhost:3000')
|
||||
.set('Access-Control-Request-Method', 'DELETE')
|
||||
|
||||
expect(res.status).toBe(204)
|
||||
expect(res.headers['access-control-allow-methods']).toBeDefined()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -147,11 +147,15 @@ export async function initCors(app: Application, config: CorsConfig, logger?: Lo
|
||||
return merged
|
||||
}
|
||||
|
||||
// Default HTTP methods if not specified - allow common REST methods
|
||||
// Not constraining by default as it may break existing apps; explicit config recommended
|
||||
const DEFAULT_METHODS = ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE', 'OPTIONS']
|
||||
|
||||
const corsOptions: CorsOptions = {
|
||||
...(config.libOptions || {}),
|
||||
credentials: globalCredentials,
|
||||
maxAge: config.maxAge,
|
||||
methods: config.allowedMethods,
|
||||
methods: config.allowedMethods ?? DEFAULT_METHODS,
|
||||
allowedHeaders: config.allowedHeaders,
|
||||
exposedHeaders: config.exposedHeaders,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user