Remove phin without introducing new dependencies (#755)

This commit is contained in:
Cooldude2606 authored and GitHub committed 2025-04-15 19:09:25 +01:00
1 parent eafbc32d3d
commit a9def876e8
7 files changed
+220 -297

No files matched your search

+4 -8
View File
@@ -6,7 +6,6 @@ const fs = require("fs-extra");
const inquirer = require("inquirer");
const os = require("os");
const path = require("path");
const phin = require("phin");
const stream = require("stream");
const util = require("util");
const yargs = require("yargs");
@@ -624,7 +623,7 @@ async function inquirerMissingArgs(args) {
answers.publicAddress = args.publicAddress;
} else {
try {
let result = await phin("https://api.ipify.org/");
let result = await fetch("https://api.ipify.org/");
myIp = result.body.toString();
} catch (err) { /* ignore */ }
}
@@ -741,7 +740,7 @@ async function inquirerMissingArgs(args) {
}
async function downloadLinuxServer() {
let res = await phin("https://factorio.com/get-download/stable/headless/linux64");
let res = await fetch("https://factorio.com/get-download/stable/headless/linux64");
const url = new URL(res.headers.location);
// get the filename of the latest factorio archive from redirected url
@@ -764,14 +763,11 @@ async function downloadLinuxServer() {
await fs.ensureDir(tmpDir);
// follow the redirect
res = await phin({
url: url.href,
stream: true,
});
res = await fetch(url.href);
logger.info("Downloading latest Factorio server release. This may take a while.");
const writeStream = fs.createWriteStream(tmpArchivePath);
res.pipe(writeStream);
stream.Readable.fromWeb(res.body).pipe(writeStream);
await finished(writeStream);
-1
View File
@@ -19,7 +19,6 @@
"chalk": "^4.1.2",
"fs-extra": "^11.3.0",
"inquirer": "^8.2.4",
"phin": "^3.7.0",
"yargs": "^17.7.2"
},
"publishConfig": {
-1
View File
@@ -38,7 +38,6 @@
"@types/node": "^20.17.19",
"@types/react": "^18.3.18",
"antd": "^5.24.2",
"phin": "^3.7.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"typescript": "^5.7.3",
+86 -152
View File
@@ -1,6 +1,5 @@
"use strict";
const assert = require("assert").strict;
const phin = require("phin");
const jwt = require("jsonwebtoken");
const mock = require("../../../test/mock");
@@ -11,6 +10,13 @@ const info = require("../dist/node/index").plugin;
const { FetchPlayerCodeRequest, SetVerifyCodeRequest } = require("../dist/node/messages");
const lib = require("@clusterio/lib");
function postJSON(url, body) {
return fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
}
describe("player_auth", function() {
describe("controller.js", function() {
@@ -39,6 +45,7 @@ describe("player_auth", function() {
describe("ControllerPlugin", function() {
let controllerPlugin;
let controllerUrl;
let endpoint;
before(async function() {
controllerPlugin = await mock.createControllerPlugin(controller.ControllerPlugin, info);
controllerPlugin.controller.mockConfigEntries.set("player_auth.code_length", 10);
@@ -75,11 +82,8 @@ describe("player_auth", function() {
addInstance(3, "running", false, "running unloaded");
addInstance(4, "stopped", false, "stopped unloaded");
addInstance(5, "running", true, undefined);
let result = await phin({
url: `${controllerUrl}/api/player_auth/servers`,
parse: "json",
});
assert.deepEqual(result.body, ["running loaded", "unnamed server"]);
const result = await fetch(`${controllerUrl}/api/player_auth/servers`);
assert.deepEqual(await result.json(), ["running loaded", "unnamed server"]);
for (let id of [1, 2, 3, 4, 5]) {
controllerPlugin.controller.instances.delete(id);
}
@@ -87,128 +91,81 @@ describe("player_auth", function() {
});
describe("/api/player_auth/player_code", function() {
before(function() {
endpoint = `${controllerUrl}/api/player_auth/player_code`;
});
it("should return 400 on invalid json", async function() {
let result = await phin({
url: `${controllerUrl}/api/player_auth/player_code`,
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: "invalid",
});
assert.equal(result.statusCode, 400);
const result = await postJSON(endpoint, "invalid");
assert.equal(result.status, 400);
});
it("should return 400 on valid json which is not an object", async function() {
for (let obj of [true, false, null, "string", 123, ["an", "array"]]) {
let result = await phin({
url: `${controllerUrl}/api/player_auth/player_code`,
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: JSON.stringify(obj),
});
assert.equal(result.statusCode, 400);
const result = await postJSON(endpoint, obj);
assert.equal(result.status, 400);
}
});
it("should return 400 if player_code is not a string", async function() {
for (let obj of [true, false, null, 123, [], {}]) {
let result = await phin({
url: `${controllerUrl}/api/player_auth/player_code`,
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: JSON.stringify({ player_code: obj }),
});
assert.equal(result.statusCode, 400);
const result = await postJSON(endpoint, { player_code: obj });
assert.equal(result.status, 400);
}
});
it("should return invalid player_code if the code is expired", async function() {
let expiresMs = Date.now() - 1000;
controllerPlugin.players.set("expired", { playerCode: "expired", verifyCode: null, expiresMs });
let result = await phin({
url: `${controllerUrl}/api/player_auth/player_code`,
method: "POST",
data: { player_code: "expired" },
parse: "json",
});
assert.deepEqual(result.body, { error: true, message: "invalid player_code" });
const result = await postJSON(endpoint, { player_code: "expired" });
assert.deepEqual(await result.json(), { error: true, message: "invalid player_code" });
});
it("should return a verify code and token if code is valid", async function() {
let expiresMs = Date.now() + 1000;
controllerPlugin.players.set("valid", { playerCode: "valid", verifyCode: null, expiresMs });
let result = await phin({
url: `${controllerUrl}/api/player_auth/player_code`,
method: "POST",
data: { player_code: "valid" },
parse: "json",
});
assert.equal(typeof result.body.verify_code, "string");
assert.equal(typeof result.body.verify_token, "string");
const result = await postJSON(endpoint, { player_code: "valid" });
const body = await result.json();
assert.equal(typeof body.verify_code, "string");
assert.equal(typeof body.verify_token, "string");
});
});
describe("/api/player_auth/verify", function() {
before(function() {
endpoint = `${controllerUrl}/api/player_auth/verify`;
});
it("should return 400 on invalid json", async function() {
let result = await phin({
url: `${controllerUrl}/api/player_auth/verify`,
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: "invalid",
});
assert.equal(result.statusCode, 400);
const result = await postJSON(endpoint, "invalid");
assert.equal(result.status, 400);
});
it("should return 400 on valid json which is not an object", async function() {
for (let obj of [true, false, null, "string", 123, ["an", "array"]]) {
let result = await phin({
url: `${controllerUrl}/api/player_auth/verify`,
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: JSON.stringify(obj),
});
assert.equal(result.statusCode, 400);
const result = await postJSON(endpoint, obj);
assert.equal(result.status, 400);
}
});
it("should return 400 if player_code, verify_code or verify_token are not strings", async function() {
for (let obj of [true, false, null, 123, [], {}]) {
for (let field of ["player_code", "verify_code", "verify_token"]) {
let result = await phin({
url: `${controllerUrl}/api/player_auth/verify`,
method: "POST",
data: {
player_code: "str",
verify_code: "str",
verify_token: "str",
[field]: obj,
},
const result = await postJSON(endpoint, {
player_code: "str",
verify_code: "str",
verify_token: "str",
[field]: obj,
});
assert.equal(result.statusCode, 400);
assert.equal(result.status, 400);
}
}
});
it("should return error if verify_token is not valid", async function() {
async function verify(tokenParams, error) {
let result = await phin({
url: `${controllerUrl}/api/player_auth/verify`,
method: "POST",
data: {
const result = await postJSON(endpoint, {
player_code: "player",
verify_code: "verify",
verify_token: jwt.sign({
aud: "player_auth.verify_code",
player_code: "player",
verify_code: "verify",
verify_token: jwt.sign({
aud: "player_auth.verify_code",
player_code: "player",
verify_code: "verify",
...tokenParams,
}, Buffer.from(tokenParams.secret || "TestSecretDoNotUse", "base64")),
},
parse: "json",
...tokenParams,
}, Buffer.from(tokenParams.secret || "TestSecretDoNotUse", "base64")),
});
assert.deepEqual(result.body.error, true);
assert.deepEqual((await result.json()).error, true);
}
await verify({ secret: "InvalidSecret" });
await verify({ verify_code: "bad" });
@@ -218,21 +175,16 @@ describe("player_auth", function() {
it("should return invalid player_code if the code is expired", async function() {
let expiresMs = Date.now() - 1000;
controllerPlugin.players.set("expired", { playerCode: "expired", verifyCode: "verify", expiresMs });
let result = await phin({
url: `${controllerUrl}/api/player_auth/verify`,
method: "POST",
data: {
const result = await postJSON(endpoint, {
player_code: "expired",
verify_code: "verify",
verify_token: jwt.sign({
aud: "player_auth.verify_code",
player_code: "expired",
verify_code: "verify",
verify_token: jwt.sign({
aud: "player_auth.verify_code",
player_code: "expired",
verify_code: "verify",
}, Buffer.from("TestSecretDoNotUse", "base64")),
},
parse: "json",
}, Buffer.from("TestSecretDoNotUse", "base64")),
});
assert.deepEqual(result.body, { error: true, message: "invalid player_code" });
assert.deepEqual(await result.json(), { error: true, message: "invalid player_code" });
});
it("should return verified false if verify code has not yet been set", async function() {
let expiresMs = Date.now() + 1000;
@@ -240,60 +192,46 @@ describe("player_auth", function() {
"unverified",
{ playerCode: "unverified", verifyCode: null, expiresMs },
);
let result = await phin({
url: `${controllerUrl}/api/player_auth/verify`,
method: "POST",
data: {
const result = await postJSON(endpoint, {
player_code: "unverified",
verify_code: "verify",
verify_token: jwt.sign({
aud: "player_auth.verify_code",
player_code: "unverified",
verify_code: "verify",
verify_token: jwt.sign({
aud: "player_auth.verify_code",
player_code: "unverified",
verify_code: "verify",
}, Buffer.from("TestSecretDoNotUse", "base64")),
},
parse: "json",
}, Buffer.from("TestSecretDoNotUse", "base64")),
});
assert.deepEqual(result.body, { verified: false });
assert.deepEqual(await result.json(), { verified: false });
});
it("should return error if user is missing", async function() {
let expiresMs = Date.now() + 1000;
controllerPlugin.players.set("missing", { playerCode: "missing", verifyCode: "verify", expiresMs });
let result = await phin({
url: `${controllerUrl}/api/player_auth/verify`,
method: "POST",
data: {
const result = await postJSON(endpoint, {
player_code: "missing",
verify_code: "verify",
verify_token: jwt.sign({
aud: "player_auth.verify_code",
player_code: "missing",
verify_code: "verify",
verify_token: jwt.sign({
aud: "player_auth.verify_code",
player_code: "missing",
verify_code: "verify",
}, Buffer.from("TestSecretDoNotUse", "base64")),
},
parse: "json",
}, Buffer.from("TestSecretDoNotUse", "base64")),
});
assert.deepEqual(result.body, { error: true, message: "invalid user" });
assert.deepEqual(await result.json(), { error: true, message: "invalid user" });
});
it("should return verified true with token if valid verification", async function() {
let expiresMs = Date.now() + 1000;
controllerPlugin.players.set("player", { playerCode: "player", verifyCode: "verify", expiresMs });
let result = await phin({
url: `${controllerUrl}/api/player_auth/verify`,
method: "POST",
data: {
const result = await postJSON(endpoint, {
player_code: "player",
verify_code: "verify",
verify_token: jwt.sign({
aud: "player_auth.verify_code",
player_code: "player",
verify_code: "verify",
verify_token: jwt.sign({
aud: "player_auth.verify_code",
player_code: "player",
verify_code: "verify",
}, Buffer.from("TestSecretDoNotUse", "base64")),
},
parse: "json",
}, Buffer.from("TestSecretDoNotUse", "base64")),
});
assert.equal(result.body.verified, true);
assert.deepEqual(typeof result.body.token, "string", "missing token");
const body = await result.json();
assert.equal(body.verified, true);
assert.deepEqual(typeof body.token, "string", "missing token");
});
});
@@ -338,25 +276,21 @@ describe("player_auth", function() {
new FetchPlayerCodeRequest("test")
);
let playerCodeResult = await phin({
url: `${controllerUrl}/api/player_auth/player_code`,
method: "POST",
data: { player_code: playerCode },
parse: "json",
});
const playerCodeResult = await postJSON(
`${controllerUrl}/api/player_auth/player_code`,
{ player_code: playerCode }
);
let { verify_code, verify_token } = playerCodeResult.body;
let { verify_code, verify_token } = await playerCodeResult.json();
await controllerPlugin.handleSetVerifyCodeRequest(
new SetVerifyCodeRequest("test", verify_code)
);
let verifyResult = await phin({
url: `${controllerUrl}/api/player_auth/verify`,
method: "POST",
data: { player_code: playerCode, verify_code, verify_token },
parse: "json",
});
assert.equal(verifyResult.body.verified, true);
const verifyResult = await postJSON(
`${controllerUrl}/api/player_auth/verify`,
{ player_code: playerCode, verify_code, verify_token }
);
assert.equal((await verifyResult.json()).verified, true);
});
});
});
+126 -127
View File
@@ -4,13 +4,11 @@ const events = require("events");
const FormData = require("form-data");
const jwt = require("jsonwebtoken");
const http = require("http");
const phin = require("phin");
const { wait } = require("@clusterio/lib");
const routes = require("@clusterio/controller/dist/node/src/routes");
const mock = require("../mock");
describe("controller/src/routes", function() {
let controller;
let server;
@@ -27,20 +25,23 @@ describe("controller/src/routes", function() {
server.close();
});
describe("/api/stream/:id", function() {
let endpoint;
beforeEach(function() {
endpoint = `http://localhost:${port}/api/stream`;
});
it("should respond with 404 if stream doesn't exist", async function() {
let response;
response = await phin(`http://localhost:${port}/api/stream/01020304`);
assert.equal(response.statusCode, 404);
response = await phin({
url: `http://localhost:${port}/api/stream/01020304`, method: "PUT",
data: "test stream",
response = await fetch(`${endpoint}/01020304`);
assert.equal(response.status, 404);
response = await fetch(`${endpoint}/01020304`, {
method: "PUT", body: "test stream",
});
assert.equal(response.statusCode, 404);
assert.equal(response.status, 404);
});
it("should respond with 500 if stream times out", async function() {
let stream = await routes.createProxyStream(controller.app);
let response = await phin(`http://localhost:${port}/api/stream/${stream.id}`);
assert.equal(response.statusCode, 500);
let response = await fetch(`${endpoint}/${stream.id}`);
assert.equal(response.status, 500);
});
it("should passthrough a stream", async function() {
let stream;
@@ -49,121 +50,123 @@ describe("controller/src/routes", function() {
responses = await Promise.all([
(async function() {
await wait(100);
return await phin({
url: `http://localhost:${port}/api/stream/${stream.id}`, method: "PUT",
data: "test content",
return await fetch(`${endpoint}/${stream.id}`, {
method: "PUT", body: "test content",
});
}()),
phin(`http://localhost:${port}/api/stream/${stream.id}`),
fetch(`${endpoint}/${stream.id}`),
]);
assert.equal(responses[0].statusCode, 200);
assert.equal(responses[1].statusCode, 200);
assert.equal(responses[1].body.toString(), "test content");
assert.equal(responses[0].status, 200);
assert.equal(responses[1].status, 200);
assert.equal(await responses[1].text(), "test content");
stream = await routes.createProxyStream(controller.app);
responses = await Promise.all([
phin({
url: `http://localhost:${port}/api/stream/${stream.id}`, method: "PUT",
data: "test content",
fetch(`${endpoint}/${stream.id}`, {
method: "PUT", body: "test content",
}),
(async function() {
await wait(100);
return await phin(`http://localhost:${port}/api/stream/${stream.id}`);
return await fetch(`${endpoint}/${stream.id}`);
}()),
]);
assert.equal(responses[0].statusCode, 200);
assert.equal(responses[1].statusCode, 200);
assert.equal(responses[1].body.toString(), "test content");
assert.equal(responses[0].status, 200);
assert.equal(responses[1].status, 200);
assert.equal(await responses[1].text(), "test content");
});
});
describe("/api/upload-save", function() {
let endpoint;
beforeEach(function() {
endpoint = `http://localhost:${port}/api/upload-save`;
});
it("should respond with 401 with invalid token", async function() {
let response;
response = await phin({
url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=file.zip`, method: "POST",
response = await fetch(`${endpoint}?instance_id=123&filename=file.zip`, {
method: "POST",
headers: { "Content-Type": "application/zip" },
data: "totally a zip file",
body: "totally a zip file",
});
assert.equal(response.statusCode, 401);
response = await phin({
url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=file.zip`, method: "POST",
assert.equal(response.status, 401);
response = await fetch(`${endpoint}?instance_id=123&filename=file.zip`, {
method: "POST",
headers: {
"Content-Type": "application/zip",
"X-Access-Token": "invalid",
},
data: "totally a zip file",
body: "totally a zip file",
});
assert.equal(response.statusCode, 401);
response = await phin({
url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=file.zip`, method: "POST",
assert.equal(response.status, 401);
response = await fetch(`${endpoint}?instance_id=123&filename=file.zip`, {
method: "POST",
headers: {
"Content-Type": "application/zip",
"X-Access-Token": jwt.sign(
{ aud: "user", user: "invalid" }, Buffer.from("TestSecretDoNotUse", "base64")
),
},
data: "totally a zip file",
body: "totally a zip file",
});
assert.equal(response.statusCode, 401);
assert.equal(response.status, 401);
controller.userManager.getByName("test").tokenValidAfter = Math.floor((Date.now() + 60e3) / 1000);
response = await phin({
url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=file.zip`, method: "POST",
response = await fetch(`${endpoint}?instance_id=123&filename=file.zip`, {
method: "POST",
headers: {
"Content-Type": "application/zip",
"X-Access-Token": jwt.sign(
{ aud: "user", user: "test" }, Buffer.from("TestSecretDoNotUse", "base64")
),
},
data: "totally a zip file",
body: "totally a zip file",
});
assert.equal(response.statusCode, 401);
assert.equal(response.status, 401);
});
it("should respond with 403 when user has insufficient permission", async function() {
let response = await phin({
url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=file.zip`, method: "POST",
let response = await fetch(`${endpoint}?instance_id=123&filename=file.zip`, {
method: "POST",
headers: {
"Content-Type": "application/zip",
"X-Access-Token": jwt.sign(
{ aud: "user", user: "player" }, Buffer.from("TestSecretDoNotUse", "base64")
),
},
data: "totally a zip file",
body: "totally a zip file",
});
assert.equal(response.statusCode, 403);
assert.equal(response.status, 403);
});
let testToken = jwt.sign({ aud: "user", user: "test" }, Buffer.from("TestSecretDoNotUse", "base64"));
it("should respond with 415 if content type is missing or invalid", async function() {
let response;
response = await phin({
url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=file.zip`, method: "POST",
response = await fetch(`${endpoint}?instance_id=123&filename=file.zip`, {
method: "POST",
headers: {
"X-Access-Token": testToken,
},
data: "totally a zip file",
body: "totally a zip file",
});
assert.equal(response.statusCode, 415);
assert.deepEqual(JSON.parse(response.body), { request_errors: ["invalid Content-Type"] });
response = await phin({
url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=file.zip`, method: "POST",
assert.equal(response.status, 415);
assert.deepEqual(await response.json(), { request_errors: ["invalid Content-Type"] });
response = await fetch(`${endpoint}?instance_id=123&filename=file.zip`, {
method: "POST",
headers: {
"X-Access-Token": testToken,
"Content-Type": "invalid",
},
data: "totally a zip file",
body: "totally a zip file",
});
assert.equal(response.statusCode, 415);
assert.deepEqual(JSON.parse(response.body), { request_errors: ["invalid Content-Type"] });
response = await phin({
url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=file.zip`, method: "POST",
assert.equal(response.status, 415);
assert.deepEqual(await response.json(), { request_errors: ["invalid Content-Type"] });
response = await fetch(`${endpoint}?instance_id=123&filename=file.zip`, {
method: "POST",
headers: {
"X-Access-Token": testToken,
"Content-Type": "text/plain",
},
data: "totally a zip file",
body: "totally a zip file",
});
assert.equal(response.statusCode, 415);
assert.deepEqual(JSON.parse(response.body), { request_errors: ["invalid Content-Type"] });
assert.equal(response.status, 415);
assert.deepEqual(await response.json(), { request_errors: ["invalid Content-Type"] });
});
it("should respond with 400 if invalid multipart request", async function() {
@@ -172,96 +175,96 @@ describe("controller/src/routes", function() {
form = new FormData();
form.append("instance_id", "123");
form.append("file", "totally a zip file", { filename: "test.zip", contentType: "text/plain" });
response = await phin({
url: `http://localhost:${port}/api/upload-save`, method: "POST",
response = await fetch(endpoint, {
method: "POST",
headers: {
"X-Access-Token": testToken,
...form.getHeaders(),
},
data: form.getBuffer(),
body: form.getBuffer(),
});
assert.equal(response.statusCode, 400);
assert.deepEqual(JSON.parse(response.body), { request_errors: ["invalid file Content-Type"] });
assert.equal(response.status, 400);
assert.deepEqual(await response.json(), { request_errors: ["invalid file Content-Type"] });
form = new FormData();
form.append("file", "totally a zip file", { filename: "test.zip", contentType: "application/zip" });
form.append("instance_id", "123");
response = await phin({
url: `http://localhost:${port}/api/upload-save`, method: "POST",
response = await fetch(endpoint, {
method: "POST",
headers: {
"X-Access-Token": testToken,
...form.getHeaders(),
},
data: form.getBuffer(),
body: form.getBuffer(),
});
assert.equal(response.statusCode, 400);
assert.equal(response.status, 400);
assert.deepEqual(
JSON.parse(response.body), { request_errors: ["instance_id must come before files uploaded"] }
await response.json(), { request_errors: ["instance_id must come before files uploaded"] }
);
form = new FormData();
form.append("instance_id", "123");
form.append("file", "totally a zip file", { filename: "test.txt", contentType: "application/zip" });
response = await phin({
url: `http://localhost:${port}/api/upload-save`, method: "POST",
response = await fetch(endpoint, {
method: "POST",
headers: {
"X-Access-Token": testToken,
...form.getHeaders(),
},
data: form.getBuffer(),
body: form.getBuffer(),
});
assert.equal(response.statusCode, 400);
assert.equal(response.status, 400);
assert.deepEqual(
JSON.parse(response.body), { request_errors: ["filename must end with .zip"] }
await response.json(), { request_errors: ["filename must end with .zip"] }
);
form = new FormData();
form.append("instance_id", "invalid");
form.append("file", "totally a zip file", { filename: "test.zip", contentType: "application/zip" });
response = await phin({
url: `http://localhost:${port}/api/upload-save`, method: "POST",
response = await fetch(endpoint, {
method: "POST",
headers: {
"X-Access-Token": testToken,
...form.getHeaders(),
},
data: form.getBuffer(),
body: form.getBuffer(),
});
assert.equal(response.statusCode, 400);
assert.equal(response.status, 400);
assert.deepEqual(
JSON.parse(response.body), { request_errors: ["invalid instance_id"] }
await response.json(), { request_errors: ["invalid instance_id"] }
);
});
it("should respond with 400 if invalid file request", async function() {
let response;
response = await phin({
url: `http://localhost:${port}/api/upload-save?instance_id=123`, method: "POST",
response = await fetch(`${endpoint}?instance_id=123`, {
method: "POST",
headers: {
"X-Access-Token": testToken,
"Content-Type": "application/zip",
},
data: "totally a zip file",
body: "totally a zip file",
});
assert.equal(response.statusCode, 400);
assert.deepEqual(JSON.parse(response.body), { request_errors: ["Missing or invalid filename parameter"] });
response = await phin({
url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=test.txt`, method: "POST",
assert.equal(response.status, 400);
assert.deepEqual(await response.json(), { request_errors: ["Missing or invalid filename parameter"] });
response = await fetch(`${endpoint}?instance_id=123&filename=test.txt`, {
method: "POST",
headers: {
"X-Access-Token": testToken,
"Content-Type": "application/zip",
},
data: "totally a zip file",
body: "totally a zip file",
});
assert.equal(response.statusCode, 400);
assert.deepEqual(JSON.parse(response.body), { request_errors: ["filename must end with .zip"] });
response = await phin({
url: `http://localhost:${port}/api/upload-save?filename=test.zip`, method: "POST",
assert.equal(response.status, 400);
assert.deepEqual(await response.json(), { request_errors: ["filename must end with .zip"] });
response = await fetch(`${endpoint}?filename=test.zip`, {
method: "POST",
headers: {
"X-Access-Token": testToken,
"Content-Type": "application/zip",
},
data: "totally a zip file",
body: "totally a zip file",
});
assert.equal(response.statusCode, 400);
assert.equal(response.status, 400);
assert.deepEqual(
JSON.parse(response.body), { request_errors: ["Missing or invalid instance_id parameter"] }
await response.json(), { request_errors: ["Missing or invalid instance_id parameter"] }
);
});
@@ -274,82 +277,78 @@ describe("controller/src/routes", function() {
form = new FormData();
form.append("instance_id", "123");
form.append("file", "totally a zip file", { filename: "test.zip", contentType: "application/zip" });
response = await phin({
url: `http://localhost:${port}/api/upload-save`, method: "POST",
response = await fetch(endpoint, {
method: "POST",
headers: {
"X-Access-Token": testToken,
...form.getHeaders(),
},
data: form.getBuffer(),
body: form.getBuffer(),
});
assert.equal(response.statusCode, 500);
assert.deepEqual(JSON.parse(response.body), { errors: ["Something went wrong"], request_errors: [] });
response = await phin({
url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=test.zip`, method: "POST",
assert.equal(response.status, 500);
assert.deepEqual(await response.json(), { errors: ["Something went wrong"], request_errors: [] });
response = await fetch(`${endpoint}?instance_id=123&filename=test.zip`, {
method: "POST",
headers: {
"X-Access-Token": testToken,
"Content-Type": "application/zip",
},
data: "totally a zip file",
body: "totally a zip file",
});
assert.equal(response.statusCode, 500);
assert.deepEqual(JSON.parse(response.body), { errors: ["Something went wrong"], request_errors: [] });
assert.equal(response.status, 500);
assert.deepEqual(await response.json(), { errors: ["Something went wrong"], request_errors: [] });
controller.sendToHostByInstanceId = async (request) => {
await new Promise(() => {});
};
response = await phin({
url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=test.zip`, method: "POST",
response = await fetch(`${endpoint}?instance_id=123&filename=test.zip`, {
method: "POST",
headers: {
"X-Access-Token": testToken,
"Content-Type": "application/zip",
},
data: "totally a zip file",
body: "totally a zip file",
});
assert.equal(response.statusCode, 500);
assert.equal(response.status, 500);
assert.deepEqual(
JSON.parse(response.body), { errors: ["Timed out establishing stream to host"], request_errors: [] }
await response.json(), { errors: ["Timed out establishing stream to host"], request_errors: [] }
);
});
it("should complete a valid transfer", async function() {
controller.sendToHostByInstanceId = async (request) => {
let stream = await phin({
url: `http://localhost:${port}/api/stream/${request.streamId}`,
});
assert.equal(stream.body.toString(), "totally a zip file");
const stream = await fetch(`http://localhost:${port}/api/stream/${request.streamId}`);
assert.equal(await stream.text(), "totally a zip file");
return request.name;
};
let response;
response = await phin({
url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=test.zip`, method: "POST",
response = await fetch(`${endpoint}?instance_id=123&filename=test.zip`, {
method: "POST",
headers: {
"X-Access-Token": testToken,
"Content-Type": "application/zip",
},
data: "totally a zip file",
body: "totally a zip file",
});
assert.deepEqual(JSON.parse(response.body), { saves: ["test.zip"] });
assert.equal(response.statusCode, 200);
assert.deepEqual(await response.json(), { saves: ["test.zip"] });
assert.equal(response.status, 200);
});
it("should complete a valid transfer with non-standerd mime type", async function() {
controller.sendToHostByInstanceId = async (request) => {
let stream = await phin({
url: `http://localhost:${port}/api/stream/${request.streamId}`,
});
assert.equal(stream.body.toString(), "totally a zip file");
const stream = await fetch(`http://localhost:${port}/api/stream/${request.streamId}`);
assert.equal(await stream.text(), "totally a zip file");
return request.name;
};
let response;
response = await phin({
url: `http://localhost:${port}/api/upload-save?instance_id=123&filename=test.zip`, method: "POST",
response = await fetch(`${endpoint}?instance_id=123&filename=test.zip`, {
method: "POST",
headers: {
"X-Access-Token": testToken,
"Content-Type": "application/x-zip-compressed",
},
data: "totally a zip file",
body: "totally a zip file",
});
assert.deepEqual(JSON.parse(response.body), { saves: ["test.zip"] });
assert.equal(response.statusCode, 200);
assert.deepEqual(await response.json(), { saves: ["test.zip"] });
assert.equal(response.status, 200);
});
});
});
-1
View File
@@ -4,7 +4,6 @@ const fs = require("fs-extra");
const jwt = require("jsonwebtoken");
const path = require("path");
const events = require("events");
const phin = require("phin");
const child_process = require("child_process");
const util = require("util");
+4 -7
View File
@@ -7,15 +7,8 @@ const JSZip = require("jszip"); // Added for creating mock zips
// Capture native fetch before any potential mocks are applied
const nativeFetch = global.fetch;
// Removed logger mocking setup
const { ModStore, ModInfo } = require("@clusterio/lib"); // Adjust path based on compiled output
// Mock fetch function
global.fetch = async (url, options) => {
throw new Error(`fetch mock not implemented for ${url}`);
};
const MODS_DIR = path.join("temp", "test", "mod_store", "mods");
const CACHE_FILE = path.join(MODS_DIR, "mod-info-cache.json");
@@ -49,6 +42,10 @@ describe("lib/ModStore", function () {
await fs.ensureDir(MODS_DIR);
});
after(function() {
global.fetch = nativeFetch;
});
beforeEach(function () {
// Reset mocks before each test
global.fetch = async (url, options) => {