From a9641a98ee58b66a2d9a76bc2527979ed93716ba Mon Sep 17 00:00:00 2001 From: nflaig Date: Tue, 14 Mar 2023 19:36:46 +0100 Subject: [PATCH] Fix array query string parsing --- packages/api/package.json | 4 ++-- packages/api/test/utils/utils.ts | 4 ++-- packages/beacon-node/package.json | 2 ++ packages/beacon-node/src/api/rest/base.ts | 12 ++++++++++-- packages/light-client/package.json | 2 ++ packages/light-client/test/utils/server.ts | 4 ++-- yarn.lock | 17 ++++++++++++----- 7 files changed, 32 insertions(+), 13 deletions(-) diff --git a/packages/api/package.json b/packages/api/package.json index 55ca29a34f54..1c24e9ea4f61 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -76,11 +76,11 @@ "@lodestar/utils": "^1.5.1", "cross-fetch": "^3.1.4", "eventsource": "^2.0.2", - "qs": "^6.10.1" + "qs": "^6.11.1" }, "devDependencies": { "@types/eventsource": "^1.1.5", - "@types/qs": "^6.9.6", + "@types/qs": "^6.9.7", "ajv": "^8.11.0", "fastify": "3.29.4" }, diff --git a/packages/api/test/utils/utils.ts b/packages/api/test/utils/utils.ts index 669580b3f58a..6dec3eb3947c 100644 --- a/packages/api/test/utils/utils.ts +++ b/packages/api/test/utils/utils.ts @@ -1,4 +1,4 @@ -import querystring from "querystring"; +import qs from "qs"; import fastify, {FastifyInstance} from "fastify"; import Sinon from "sinon"; import {mapValues} from "@lodestar/utils"; @@ -10,7 +10,7 @@ export function getTestServer(): {baseUrl: string; server: FastifyInstance} { const server = fastify({ ajv: {customOptions: {coerceTypes: "array"}}, - querystringParser: querystring.parse, + querystringParser: (str) => qs.parse(str, {comma: true}), }); server.addHook("onError", (request, reply, error, done) => { diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index cb93a470a0ed..f4047583fec2 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -147,6 +147,7 @@ "libp2p": "0.42.2", "prom-client": "^14.1.0", "prometheus-gc-stats": "^0.6.3", + "qs": "^6.11.1", "snappyjs": "^0.7.0", "stream-to-it": "^0.2.0", "strict-event-emitter-types": "^2.0.0", @@ -164,6 +165,7 @@ "@types/eventsource": "^1.1.5", "@types/leveldown": "^4.0.2", "@types/prometheus-gc-stats": "^0.6.1", + "@types/qs": "^6.9.7", "@types/supertest": "^2.0.12", "@types/tmp": "^0.2.0", "@types/varint": "^6.0.0", diff --git a/packages/beacon-node/src/api/rest/base.ts b/packages/beacon-node/src/api/rest/base.ts index fabcb6eb3d74..63ee77b3f00e 100644 --- a/packages/beacon-node/src/api/rest/base.ts +++ b/packages/beacon-node/src/api/rest/base.ts @@ -1,4 +1,4 @@ -import querystring from "querystring"; +import qs from "qs"; import fastify, {FastifyError, FastifyInstance} from "fastify"; import fastifyCors from "fastify-cors"; import bearerAuthPlugin from "fastify-bearer-auth"; @@ -43,7 +43,15 @@ export class RestApiServer { const server = fastify({ logger: false, ajv: {customOptions: {coerceTypes: "array"}}, - querystringParser: querystring.parse, + querystringParser: (str) => + qs.parse(str, { + // defaults to 20 but Beacon API spec allows max items of 30 + arrayLimit: 30, + // array as comma-separated values must be supported to be OpenAPI spec compliant + comma: true, + // default limit of 1000 seems unnecessarily high, let's reduce it a bit + parameterLimit: 100, + }), bodyLimit: opts.bodyLimit, }); diff --git a/packages/light-client/package.json b/packages/light-client/package.json index 1f3e65e2414f..f9f8067a4601 100644 --- a/packages/light-client/package.json +++ b/packages/light-client/package.json @@ -77,6 +77,8 @@ }, "devDependencies": { "@chainsafe/as-sha256": "^0.3.1", + "@types/qs": "^6.9.7", + "qs": "^6.11.1", "uint8arrays": "^4.0.2" }, "keywords": [ diff --git a/packages/light-client/test/utils/server.ts b/packages/light-client/test/utils/server.ts index 41a2e9ca60ad..48da67b8c6c1 100644 --- a/packages/light-client/test/utils/server.ts +++ b/packages/light-client/test/utils/server.ts @@ -1,4 +1,4 @@ -import querystring from "querystring"; +import qs from "qs"; import fastify, {FastifyInstance} from "fastify"; import fastifyCors from "fastify-cors"; import {Api, ServerApi} from "@lodestar/api"; @@ -18,7 +18,7 @@ export async function startServer( const server = fastify({ logger: false, ajv: {customOptions: {coerceTypes: "array"}}, - querystringParser: querystring.parse, + querystringParser: (str) => qs.parse(str, {comma: true}), }); registerRoutes(server, config, api, ["lightclient", "proof", "events"]); diff --git a/yarn.lock b/yarn.lock index 2c69e797b857..f051298e1516 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3406,10 +3406,10 @@ resolved "https://registry.npmjs.org/@types/prometheus-gc-stats/-/prometheus-gc-stats-0.6.1.tgz" integrity sha512-tSj7MRNgEJCSqVRgPL4WIIcslZChgL6gVwnVFsAj2nTx0RdcG7iSpWm+0fkAKEe7e/YQ08TZH4wQWxpFODYqJw== -"@types/qs@^6.9.6": - version "6.9.6" - resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.6.tgz" - integrity sha512-0/HnwIfW4ki2D8L8c9GVcG5I72s9jP5GSLVF0VIXDW00kmIpA6O33G7a8n59Tmh7Nz0WUC3rSb7PTY/sdW2JzA== +"@types/qs@^6.9.7": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== "@types/readable-stream@*": version "2.3.11" @@ -10992,13 +10992,20 @@ qs@6.9.3: resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.3.tgz#bfadcd296c2d549f1dffa560619132c977f5008e" integrity sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw== -qs@^6.10.1, qs@^6.10.3: +qs@^6.10.3: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== dependencies: side-channel "^1.0.4" +qs@^6.11.1: + version "6.11.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.1.tgz#6c29dff97f0c0060765911ba65cbc9764186109f" + integrity sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ== + dependencies: + side-channel "^1.0.4" + querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz"