diff --git a/src/tests/with-contact.test.ts b/src/tests/with-contact.test.ts index e319686..0cd2020 100644 --- a/src/tests/with-contact.test.ts +++ b/src/tests/with-contact.test.ts @@ -549,9 +549,17 @@ describe('withContract', () => { expect(response.status).toBe(400); expect(response.body.error).toBe( - 'Unsupported content-type. Allowed: application/x-www-form-urlencoded', + 'Unsupported content-type. Allowed: application/x-www-form-urlencoded, got: application/json', ); }); + + it('should bypass content-type check if request has no body', async () => { + const response = await request(app).post('/custom-content-type'); // No .send() and no Content-Type header + + expect(response.status).toBe(400); + // The error should be from Zod validation, not the Content-Type check + expect(response.body.error).toBe('Invalid request data'); + }); }); describe('Schema-less Responses', () => { diff --git a/src/validator/with-contract.ts b/src/validator/with-contract.ts index 1965107..4979876 100644 --- a/src/validator/with-contract.ts +++ b/src/validator/with-contract.ts @@ -167,16 +167,23 @@ export function withContract< // Check content type if body validation is required if (config.request?.body) { - const contentType = expressReq.headers['content-type']; - const allowedContentTypes = config.request?.contentType ?? ['application/json']; - - if ( - !contentType || - !allowedContentTypes.some((type) => contentType.includes(type)) - ) { - throw new ValidationError( - `Unsupported content-type. Allowed: ${allowedContentTypes.join(', ')}`, - ); + const hasBody = + expressReq.headers['transfer-encoding'] !== undefined || + (expressReq.headers['content-length'] !== undefined && + expressReq.headers['content-length'] !== '0'); + + if (hasBody) { + const contentType = expressReq.headers['content-type']; + const allowedContentTypes = config.request?.contentType ?? ['application/json']; + + if ( + !contentType || + !allowedContentTypes.some((type) => contentType.includes(type)) + ) { + throw new ValidationError( + `Unsupported content-type. Allowed: ${allowedContentTypes.join(', ')}, got: ${contentType}`, + ); + } } }