Fix server crashing with malformed requests

It also adds tests to ensure there are no regressions.

Closes #381
This commit is contained in:
Bruno Bernardino 2022-02-17 14:33:07 +00:00
parent 858fc3a324
commit 83e6c74936
No known key found for this signature in database
GPG Key ID: D1B0A69ADD114ECE
3 changed files with 86 additions and 17 deletions

View File

@ -3,6 +3,7 @@
"password": "password",
"name": "The Dude",
"emailToken": "000000",
"serverUrl": "http://localhost:3000",
"v3_email": "user2@example.com",
"v3_url": "http://localhost:8081"
}

View File

@ -0,0 +1,63 @@
describe("Server", () => {
const { serverUrl } = Cypress.env();
it("can properly respond to valid and invalid requests", () => {
cy.request({ url: `${serverUrl}/`, method: "GET", failOnStatusCode: false }).then(
(response) => expect(response.status).to.eq(405) // method not allowed
);
cy.request({ url: `${serverUrl}/`, method: "PUT", failOnStatusCode: false }).then(
(response) => expect(response.status).to.eq(405) // method not allowed
);
cy.request({ url: `${serverUrl}/`, method: "OPTIONS" });
cy.request({ url: `${serverUrl}/`, method: "POST", failOnStatusCode: false }).then(
(response) => expect(response.status).to.eq(400) // bad request (no json)
);
cy.request({
url: `${serverUrl}/`,
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email: "user@example.com" }),
}).then((response) => {
expect(response.status).to.eq(200);
expect(JSON.stringify(response.body)).to.eq(
JSON.stringify({
result: null,
error: {
code: "invalid_request",
message: "",
},
kind: "response",
version: "3.1.0",
})
);
});
cy.request({
url: `${serverUrl}/`,
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
method: "getAuthInfo",
params: [],
device: {},
auth: {},
kind: "request",
version: "3.1.0",
}),
}).then((response) => {
expect(response.status).to.eq(200);
expect(JSON.stringify(response.body)).to.eq(
JSON.stringify({
result: null,
error: { code: "invalid_session", message: "" },
kind: "response",
version: "3.1.0",
})
);
});
});
});

View File

@ -60,24 +60,29 @@ export class HTTPReceiver implements Receiver {
httpRes.end();
break;
case "POST":
const body = await readBody(httpReq, this.config.maxRequestSize);
const req = new Request().fromRaw(unmarshal(body));
const ipAddress = httpReq.headers["x-forwarded-for"] || httpReq.socket?.remoteAddress;
req.ipAddress = Array.isArray(ipAddress) ? ipAddress[0] : ipAddress;
const location = req.ipAddress && (await getLocation(req.ipAddress));
req.location = location
? {
country: location.country?.names["en"],
city: location.city?.names["en"],
}
: undefined;
try {
const body = await readBody(httpReq, this.config.maxRequestSize);
const req = new Request().fromRaw(unmarshal(body));
const ipAddress = httpReq.headers["x-forwarded-for"] || httpReq.socket?.remoteAddress;
req.ipAddress = Array.isArray(ipAddress) ? ipAddress[0] : ipAddress;
const location = req.ipAddress && (await getLocation(req.ipAddress));
req.location = location
? {
country: location.country?.names["en"],
city: location.city?.names["en"],
}
: undefined;
const clientVersion = (req.device && req.device.appVersion) || undefined;
const res = await handler(req);
const resBody = marshal(res.toRaw(clientVersion));
httpRes.setHeader("Content-Type", "application/json; charset=utf-8");
httpRes.setHeader("Content-Length", Buffer.byteLength(resBody));
httpRes.write(resBody);
const clientVersion = (req.device && req.device.appVersion) || undefined;
const res = await handler(req);
const resBody = marshal(res.toRaw(clientVersion));
httpRes.setHeader("Content-Type", "application/json; charset=utf-8");
httpRes.setHeader("Content-Length", Buffer.byteLength(resBody));
httpRes.write(resBody);
} catch (error) {
console.error(error);
httpRes.statusCode = 400;
}
httpRes.end();
break;
default: