fix(drop): stream every dropped file to disk; no local size cap

- POST /api/run/drop-file pipes the body to its file as it arrives in every
  case — a member's (S3) through `write-as … replace` with the bytes on
  stdin — instead of buffering up to 20 MB in memory for a remote browser.
- Remote limit (server mode, a LAN browser) 20 MB → 500 MB, as a Files upload.
- A loopback browser in local mode has no cap any more, only the data dir's
  free space less a 1 GB reserve; ETOOBIG's max_bytes is what still fits, so
  the UI's "at most N MB" stays true.
- drop-image keeps its 20 MB in-memory limit, now checked on its own.
- fake-sudo gains a spawn for run-as.__setSpawnImpl.
This commit is contained in:
2026-10-26 16:36:29 +07:00
parent a0cd808456
commit dce32b96b7
6 changed files with 98 additions and 73 deletions
+6 -4
View File
@@ -334,12 +334,12 @@ describe("POST /api/run/drop-image", () => {
});
it("refuses a file declared over the limit before its body arrives", async () => {
// 4 GB announced, 1 KB sent: the answer must come without the rest.
// A petabyte announced, 1 KB sent: the answer must come without the rest.
const { status, body } = await new Promise((resolve, reject) => {
const url = new URL("/api/run/drop-file?name=big.mp4", BASE);
const req = http.request(url, {
method: "POST",
headers: { "Content-Type": "video/mp4", "Content-Length": 4 * 1024 ** 3 },
headers: { "Content-Type": "video/mp4", "Content-Length": 1024 ** 5 },
});
req.on("response", (res) => {
let text = "";
@@ -354,8 +354,10 @@ describe("POST /api/run/drop-image", () => {
});
assert.equal(status, 413);
assert.equal(body.error.code, "ETOOBIG");
// The UI shows the server's limit: a loopback browser's, here.
assert.equal(body.error.max_bytes, 2 * 1024 ** 3);
// A loopback browser has no cap, only the disk's free space (less a
// reserve) — and that is the limit the UI shows.
const st = fs.statfsSync(process.env.DASHBOARD_DATA_DIR);
assert.ok(body.error.max_bytes <= st.bavail * st.bsize, String(body.error.max_bytes));
});
it("streams a loopback drop over the remote limit to disk", async () => {