Send WebQuery action parameters as JSON instead of form data
All checks were successful
Testar e publicar imagem Docker / publish (push) Successful in 32s

This commit is contained in:
Bxio 2026-10-10 21:06:18 +01:00
parent 1be8a45dde
commit 52f44b368d
2 changed files with 37 additions and 6 deletions

View File

@ -994,6 +994,7 @@ export function query(connection, command, params = {}, { signal } = {}) {
command, command,
); );
if (readOnly) address.search = form.toString(); if (readOnly) address.search = form.toString();
const payload = readOnly ? null : Buffer.from(JSON.stringify(params), "utf8");
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const req = (address.protocol === "https:" ? https : http).request( const req = (address.protocol === "https:" ? https : http).request(
address, address,
@ -1003,7 +1004,10 @@ export function query(connection, command, params = {}, { signal } = {}) {
headers: { headers: {
"x-api-key": connection.apiKey, "x-api-key": connection.apiKey,
...(!readOnly ...(!readOnly
? { "Content-Type": "application/x-www-form-urlencoded" } ? {
"Content-Type": "application/json",
"Content-Length": payload.length,
}
: {}), : {}),
}, },
timeout: 10000, timeout: 10000,
@ -1058,7 +1062,7 @@ export function query(connection, command, params = {}, { signal } = {}) {
), ),
), ),
); );
if (!readOnly) req.write(form.toString()); if (payload) req.write(payload);
req.end(); req.end();
}); });
} }

View File

@ -4,7 +4,7 @@ import http from "node:http";
import { query } from "./studio.mjs"; import { query } from "./studio.mjs";
import { httpRequest } from "./flow-steps.mjs"; import { httpRequest } from "./flow-steps.mjs";
test("WebQuery uses authenticated GET and form POST, handles fragmented UTF-8 and server errors", async () => { test("WebQuery uses authenticated GET and JSON POST, handles fragmented UTF-8 and server errors", async () => {
const requests = []; const requests = [];
const server = http.createServer(async (req, res) => { const server = http.createServer(async (req, res) => {
const chunks = []; const chunks = [];
@ -13,10 +13,29 @@ test("WebQuery uses authenticated GET and form POST, handles fragmented UTF-8 an
method: req.method, method: req.method,
path: req.url, path: req.url,
key: req.headers["x-api-key"], key: req.headers["x-api-key"],
contentType: req.headers["content-type"],
contentLength: req.headers["content-length"],
transferEncoding: req.headers["transfer-encoding"],
body: Buffer.concat(chunks).toString(), body: Buffer.concat(chunks).toString(),
}); });
res.setHeader("Content-Type", "application/json"); res.setHeader("Content-Type", "application/json");
if (req.url.includes("channeledit")) { if (req.url.includes("channeledit")) {
let params;
try {
params = JSON.parse(Buffer.concat(chunks).toString());
} catch {}
if (
req.headers["content-type"] !== "application/json" ||
!params?.cid ||
typeof params.channel_description !== "string"
) {
res.end(
JSON.stringify({
status: { code: 1538, message: "invalid parameter" },
}),
);
return;
}
res.end(JSON.stringify({ status: { code: 0 }, body: [] })); res.end(JSON.stringify({ status: { code: 0 }, body: [] }));
return; return;
} }
@ -48,7 +67,8 @@ test("WebQuery uses authenticated GET and form POST, handles fragmented UTF-8 an
try { try {
const result = await query(connection, "serverinfo"); const result = await query(connection, "serverinfo");
assert.equal(result[0].virtualserver_name, "Olá | Portugal"); assert.equal(result[0].virtualserver_name, "Olá | Portugal");
const text = "Olá | linha\nmais = texto"; const text =
"[b]Informações do servidor[/b]\nOlá | linha\nmais = texto & + / \\ 🎵";
await query(connection, "channeledit", { await query(connection, "channeledit", {
cid: 21, cid: 21,
channel_description: text, channel_description: text,
@ -56,10 +76,17 @@ test("WebQuery uses authenticated GET and form POST, handles fragmented UTF-8 an
assert.equal(requests[0].method, "GET"); assert.equal(requests[0].method, "GET");
assert.equal(requests[0].key, "fixture-key"); assert.equal(requests[0].key, "fixture-key");
assert.equal(requests[1].method, "POST"); assert.equal(requests[1].method, "POST");
assert.equal(requests[1].key, "fixture-key");
assert.equal(requests[1].contentType, "application/json");
assert.equal( assert.equal(
new URLSearchParams(requests[1].body).get("channel_description"), Number(requests[1].contentLength),
text, Buffer.byteLength(requests[1].body),
); );
assert.equal(requests[1].transferEncoding, undefined);
assert.deepEqual(JSON.parse(requests[1].body), {
cid: 21,
channel_description: text,
});
await assert.rejects( await assert.rejects(
() => query(connection, "clientkick", { clid: 1, reasonid: 5 }), () => query(connection, "clientkick", { clid: 1, reasonid: 5 }),
/2568.*permissions/, /2568.*permissions/,