Skip to content

Commit 4cefbdc

Browse files
feat(requestInput): allow to receive array request body (#2648)
1 parent 6b343d9 commit 4cefbdc

File tree

5 files changed

+54
-7
lines changed

5 files changed

+54
-7
lines changed

lib/api/controllers/securityController.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import Bluebird from "bluebird";
2222
import { isEmpty, isNil } from "lodash";
2323
import { v4 as uuidv4 } from "uuid";
24+
import { JSONObject } from "kuzzle-sdk";
2425

2526
import { BadRequestError, KuzzleError } from "../../kerror/errors";
2627
import { KuzzleRequest, Request } from "../request";
@@ -662,8 +663,8 @@ export default class SecurityController extends NativeController {
662663

663664
if (
664665
request.input.body &&
665-
request.input.body.ids &&
666-
Object.keys(request.input.body.ids).length
666+
(request.input.body as JSONObject).ids &&
667+
Object.keys((request.input.body as JSONObject).ids).length
667668
) {
668669
ids = request.getBodyArray("ids");
669670
} else {

lib/api/request/requestInput.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -290,12 +290,12 @@ export class RequestInput {
290290
* body <== that
291291
* }
292292
*/
293-
get body(): JSONObject | null {
293+
get body(): JSONObject | Array<any> | null {
294294
return this[_body];
295295
}
296296

297-
set body(obj: JSONObject) {
298-
this[_body] = assert.assertObject("body", obj);
297+
set body(obj: JSONObject | Array<any>) {
298+
this[_body] = assert.assertArrayOrObject("body", obj);
299299
}
300300

301301
/**

lib/core/realtime/hotelClerk.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ export class HotelClerk {
321321
* filters will be fetched from the cluster.
322322
*/
323323
async join(request: KuzzleRequest): Promise<{ channel; roomId }> {
324-
const roomId = request.input.body.roomId;
324+
const roomId = (request.input.body as JSONObject).roomId;
325325

326326
if (!this.rooms.has(roomId)) {
327327
const normalized: NormalizedFilter = await global.kuzzle.ask(

lib/util/assertType.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,29 @@ function assertObject(attr, data) {
4444
return data;
4545
}
4646

47+
/**
48+
* Throws if the provided data is not an object or an array.
49+
* Returns the unmodified data if validated
50+
*
51+
* @throws
52+
* @param {string} attr - tested attribute name
53+
* @param {*} data
54+
* @return {object|array}
55+
*/
56+
function assertArrayOrObject(attr, data) {
57+
if (data === null || data === undefined) {
58+
return null;
59+
}
60+
61+
if (typeof data !== "object") {
62+
throw new BadRequestError(
63+
`Attribute ${attr} must be of type "object" or "array"`,
64+
);
65+
}
66+
67+
return data;
68+
}
69+
4770
/**
4871
* Throws if the provided data is not an array containing exclusively
4972
* values of the specified "type"
@@ -120,6 +143,7 @@ function assertInteger(attr, data) {
120143

121144
module.exports = {
122145
assertArray,
146+
assertArrayOrObject,
123147
assertInteger,
124148
assertObject,
125149
assertString,

test/api/request/requestInput.test.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ describe("#RequestInput", () => {
7878

7979
it("should throw if an invalid data parameter is provided", () => {
8080
// testing object-only parameters
81-
["volatile", "body"].forEach((k) => {
81+
["volatile"].forEach((k) => {
8282
should(function () {
8383
new RequestInput({ [k]: [] });
8484
}).throw(`Attribute ${k} must be of type "object"`);
@@ -93,6 +93,18 @@ describe("#RequestInput", () => {
9393
}).throw(`Attribute ${k} must be of type "object"`);
9494
});
9595

96+
["body"].forEach((k) => {
97+
should(function () {
98+
new RequestInput({ [k]: 123 });
99+
}).throw(`Attribute ${k} must be of type "object" or "array"`);
100+
should(function () {
101+
new RequestInput({ [k]: false });
102+
}).throw(`Attribute ${k} must be of type "object" or "array"`);
103+
should(function () {
104+
new RequestInput({ [k]: "foobar" });
105+
}).throw(`Attribute ${k} must be of type "object" or "array"`);
106+
});
107+
96108
// testing string-only parameters
97109
["controller", "action", "jwt"].forEach((k) => {
98110
should(function () {
@@ -133,4 +145,14 @@ describe("#RequestInput", () => {
133145

134146
should(input.action).eql("foo");
135147
});
148+
149+
it("should accept both array and object for body property", () => {
150+
let input = new RequestInput({ body: { some: "content" } });
151+
152+
should(input.body).be.deepEqual({ some: "content" });
153+
154+
input = new RequestInput({ body: [1, 2, 3] });
155+
156+
should(input.body).be.deepEqual([1, 2, 3]);
157+
});
136158
});

0 commit comments

Comments
 (0)