diff --git a/src/server/index.ts b/src/server/index.ts index f281ceb..fc139ce 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -87,7 +87,7 @@ apiRouter.loadAPIMethods().then(() => { console.log("API OK!") // moved here to ensure it's matched last - app.get("/:fileId", (ctx) => app.fetch(ctx.req.raw, ctx.env, ctx.executionCtx)) + app.get("/:fileId", async (ctx) => app.fetch(ctx.req.raw, ctx.env)) // listen on 3000 or MONOFILE_PORT // moved here to prevent a crash if someone manages to access monofile before api routes are mounted diff --git a/src/server/lib/files.ts b/src/server/lib/files.ts index 09b8aef..207a00f 100644 --- a/src/server/lib/files.ts +++ b/src/server/lib/files.ts @@ -70,6 +70,8 @@ export interface FilePointer { visibility?: FileVisibility reserved?: boolean chunkSize?: number + lastModified?: number + md5?: string } export interface StatusCodeError { @@ -315,6 +317,8 @@ export class UploadStream extends Writable { error?: Error + hash: crypto.Hash = crypto.createHash("md5") + constructor(files: Files, owner?: string) { super() this.owner = owner @@ -328,6 +332,8 @@ export class UploadStream extends Writable { if (this.filled + data.byteLength > (this.files.config.maxDiscordFileSize*this.files.config.maxDiscordFiles)) return this.destroy(new WebError(413, "maximum file size exceeded")) + this.hash.update(data) + // cut up the buffer into message sized chunks let position = 0 @@ -431,7 +437,10 @@ export class UploadStream extends Writable { // so that json.stringify doesnt include tag:undefined ...((ogf||{}).tag ? {tag:ogf.tag} : {}), - chunkSize: this.files.config.maxDiscordFileSize + chunkSize: this.files.config.maxDiscordFileSize, + + md5: this.hash.digest("hex"), + lastModified: Date.now() } delete this.files.locks[this.uploadId!] diff --git a/src/server/routes/api/v0/primaryApi.ts b/src/server/routes/api/v0/primaryApi.ts index 4bb3726..1dfe106 100644 --- a/src/server/routes/api/v0/primaryApi.ts +++ b/src/server/routes/api/v0/primaryApi.ts @@ -32,6 +32,8 @@ export default function (files: Files) { ctx.header("Access-Control-Allow-Origin", "*") ctx.header("Content-Security-Policy", "sandbox allow-scripts") ctx.header("Content-Disposition", `${ctx.req.query("attachment") == "1" ? "attachment" : "inline"}; filename="${encodeURI(file.filename.replaceAll("\n","\\n"))}"`) + ctx.header("ETag", file.md5) + //if (file.lastModified) ctx.header("Last-Modified", new Date(file.lastModified).toTimeString()) if (file) { if (file.visibility == "private") {