Skip to content

Commit

Permalink
fix request validation to accept arrays or primitives (#54331)
Browse files Browse the repository at this point in the history
  • Loading branch information
pgayvallet authored Jan 10, 2020
1 parent 9191261 commit d8f94b1
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 1 deletion.
55 changes: 55 additions & 0 deletions src/core/server/http/integration_tests/router.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,61 @@ describe('Handler', () => {
statusCode: 400,
});
});

it('accept to receive an array payload', async () => {
const { server: innerServer, createRouter } = await server.setup(setupDeps);
const router = createRouter('/');

let body: any = null;
router.post(
{
path: '/',
validate: {
body: schema.arrayOf(schema.object({ foo: schema.string() })),
},
},
(context, req, res) => {
body = req.body;
return res.ok({ body: 'ok' });
}
);
await server.start();

await supertest(innerServer.listener)
.post('/')
.send([{ foo: 'bar' }, { foo: 'dolly' }])
.expect(200);

expect(body).toEqual([{ foo: 'bar' }, { foo: 'dolly' }]);
});

it('accept to receive a json primitive payload', async () => {
const { server: innerServer, createRouter } = await server.setup(setupDeps);
const router = createRouter('/');

let body: any = null;
router.post(
{
path: '/',
validate: {
body: schema.number(),
},
},
(context, req, res) => {
body = req.body;
return res.ok({ body: 'ok' });
}
);
await server.start();

await supertest(innerServer.listener)
.post('/')
.type('json')
.send('12')
.expect(200);

expect(body).toEqual(12);
});
});

describe('handleLegacyErrors', () => {
Expand Down
58 changes: 58 additions & 0 deletions src/core/server/http/router/validator/validator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,62 @@ describe('Router validator', () => {
'The validation rule provided in the handler is not valid'
);
});

it('should validate and infer type when data is an array', () => {
expect(
RouteValidator.from({
body: schema.arrayOf(schema.string()),
}).getBody(['foo', 'bar'])
).toStrictEqual(['foo', 'bar']);
expect(
RouteValidator.from({
body: schema.arrayOf(schema.number()),
}).getBody([1, 2, 3])
).toStrictEqual([1, 2, 3]);
expect(
RouteValidator.from({
body: schema.arrayOf(schema.object({ foo: schema.string() })),
}).getBody([{ foo: 'bar' }, { foo: 'dolly' }])
).toStrictEqual([{ foo: 'bar' }, { foo: 'dolly' }]);

expect(() =>
RouteValidator.from({
body: schema.arrayOf(schema.number()),
}).getBody(['foo', 'bar', 'dolly'])
).toThrowError('[0]: expected value of type [number] but got [string]');
expect(() =>
RouteValidator.from({
body: schema.arrayOf(schema.number()),
}).getBody({ foo: 'bar' })
).toThrowError('expected value of type [array] but got [Object]');
});

it('should validate and infer type when data is a primitive', () => {
expect(
RouteValidator.from({
body: schema.string(),
}).getBody('foobar')
).toStrictEqual('foobar');
expect(
RouteValidator.from({
body: schema.number(),
}).getBody(42)
).toStrictEqual(42);
expect(
RouteValidator.from({
body: schema.boolean(),
}).getBody(true)
).toStrictEqual(true);

expect(() =>
RouteValidator.from({
body: schema.string(),
}).getBody({ foo: 'bar' })
).toThrowError('expected value of type [string] but got [Object]');
expect(() =>
RouteValidator.from({
body: schema.number(),
}).getBody('foobar')
).toThrowError('expected value of type [number] but got [string]');
});
});
2 changes: 1 addition & 1 deletion src/core/server/http/router/validator/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ export class RouteValidator<P = {}, Q = {}, B = {}> {
// if options.body.output === 'stream'
return schema.stream();
} else {
return schema.maybe(schema.nullable(schema.object({}, { allowUnknowns: true })));
return schema.maybe(schema.nullable(schema.any({})));
}
}
}

0 comments on commit d8f94b1

Please sign in to comment.