diff --git a/package.json b/package.json
index 8ca6d90..15a5229 100644
--- a/package.json
+++ b/package.json
@@ -3,11 +3,13 @@
"version": "1.0.0",
"dependencies": {
"aws4fetch": "^1.0.13",
- "nanoid": "^3.3.4"
+ "nanoid": "^3.3.4",
+ "mime-types": "^2.1.35"
},
"devDependencies": {
"@cloudflare/workers-types": "^3.11.0",
"typescript": "^4.7.2",
- "wrangler": "^2.0.7"
+ "wrangler": "^2.0.7",
+ "@types/mime-types": "^2.1.1"
}
}
diff --git a/paste.html b/paste.html
index e36b606..7a730b0 100644
--- a/paste.html
+++ b/paste.html
@@ -28,7 +28,7 @@
Upload file
@@ -50,7 +50,7 @@
diff --git a/src/index.ts b/src/index.ts
index e06f8d7..72f80d5 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -17,7 +17,8 @@
*/
import {AwsClient} from "aws4fetch";
-import { customAlphabet } from 'nanoid'
+import {customAlphabet} from "nanoid";
+import {contentType} from "mime-types"
// Constants
const SERVICE_URL = "paste.nekoul.com"
@@ -93,7 +94,7 @@ export default {
}).then(value => {
let res = new Response(value.body, value);
// Add the correct content-type to response header
- res.headers.set("content-type", "text/html; charset=UTF-8");
+ res.headers.set("content-type", "text/html; charset=UTF-8;");
// Remove the default CSP header
res.headers.delete("content-security-policy");
return res;
@@ -102,15 +103,16 @@ export default {
// Create new paste
case "POST":
- let uuid = gen_id();
+ const uuid = gen_id();
let buffer: ArrayBuffer;
let title: string | undefined;
// Handle content-type
const content_type = headers.get("content-type") || "";
+ let mime: string | undefined;
// Content-Type: multipart/form-data
if (content_type.includes("form")) {
- let formdata = await request.formData();
- let data = formdata.get("upload-content");
+ const formdata = await request.formData();
+ const data = formdata.get("u");
if (data === null) {
return new Response("Invalid request.\n", {
status: 422
@@ -120,14 +122,20 @@ export default {
if (data instanceof File) {
title = data.name ?? undefined;
buffer = await data.arrayBuffer();
+ mime = data.type;
// Text
} else {
buffer = new TextEncoder().encode(data)
+ mime = "text/plain; charset=UTF-8;"
}
// Raw body
} else {
- title = headers.get("title") ?? undefined;
+ if (headers.has("title")) {
+ title = headers.get("title")!;
+ mime = contentType(title) || undefined;
+ }
+ mime = headers.get("content-type") ?? mime;
buffer = await request.arrayBuffer();
}
@@ -145,19 +153,20 @@ export default {
});
}
- let res = await s3.fetch(`${env.ENDPOINT}/${uuid}`, {
+ const res = await s3.fetch(`${env.ENDPOINT}/${uuid}`, {
method: "PUT",
body: buffer
});
if (res.ok) {
// Upload success
- let descriptor: PasteIndexEntry = {
+ const descriptor: PasteIndexEntry = {
title: title ?? undefined,
+ mime_type: mime,
last_modified: Date.now()
};
- let counter = await env.PASTE_INDEX.get("__count__") || "0";
+ const counter = await env.PASTE_INDEX.get("__count__") || "0";
await env.PASTE_INDEX.put(uuid, JSON.stringify(descriptor));
await env.PASTE_INDEX.put("__count__", (Number(counter) + 1).toString());
return new Response(get_paste_info(uuid, descriptor));
@@ -185,13 +194,13 @@ export default {
status: 442
})
}
- let val = await env.PASTE_INDEX.get(uuid);
+ const val = await env.PASTE_INDEX.get(uuid);
if (val === null) {
return new Response("Paste not found.\n", {
status: 404
});
}
- let descriptor: PasteIndexEntry = JSON.parse(val);
+ const descriptor: PasteIndexEntry = JSON.parse(val);
// Handling //settings
if (option === "settings") {
@@ -223,12 +232,6 @@ export default {
});
res = new Response(origin.body, origin);
- // Remove x-amz-* headers
- for (let [key, value] of res.headers.entries()) {
- if (key.startsWith("x-amz")) {
- res.headers.delete(key);
- }
- }
if (!res.ok) {
// UUID exists in index but not found in remote object storage service
@@ -237,10 +240,18 @@ export default {
});
}
- res.headers.append("Cache-Control", "max-age=3600");
+ // Remove x-amz-* headers
+ for (let [key, value] of res.headers.entries()) {
+ if (key.startsWith("x-amz")) {
+ res.headers.delete(key);
+ }
+ }
+
+ res.headers.set("cache-control", "public, max-age=18000");
+ res.headers.set("content-type", descriptor.mime_type ?? "application/octet-stream");
if (option === "download") {
- res.headers.append("Content-Disposition",
+ res.headers.set("content-disposition",
`attachment; filename="${encodeURIComponent(descriptor.title ?? uuid)}"`);
}
@@ -267,7 +278,7 @@ export default {
if (res.ok) {
await env.PASTE_INDEX.delete(uuid);
- let counter = await env.PASTE_INDEX.get("__count__") || "1";
+ const counter = await env.PASTE_INDEX.get("__count__") || "1";
await env.PASTE_INDEX.put("__count__", (Number(counter) - 1).toString());
// Invalidate CF cache
@@ -291,18 +302,20 @@ export default {
};
function get_paste_info(uuid: string, descriptor: PasteIndexEntry): string {
- let date = new Date(descriptor.last_modified)
+ const date = new Date(descriptor.last_modified)
return `https://${SERVICE_URL}/${uuid}
-ID: ${uuid}
-Title: ${descriptor.title || ""}
-Password: ${(!!descriptor.password)}
-Editable: ${descriptor.editable? descriptor.editable: true}
-Last modified at ${date.toISOString()}
+id: ${uuid}
+title: ${descriptor.title || ""}
+mime-type: ${descriptor.mime_type ?? "application/octet-stream"}
+password: ${(!!descriptor.password)}
+editable: ${descriptor.editable? descriptor.editable: true}
+last modified at ${date.toISOString()}
`
}
interface PasteIndexEntry {
- title?: string
+ title?: string,
+ mime_type?: string,
last_modified: number,
password?: string
editable?: boolean // Default: True
diff --git a/wrangler.toml b/wrangler.toml
index 9d8f8d6..2434279 100644
--- a/wrangler.toml
+++ b/wrangler.toml
@@ -1,6 +1,7 @@
name = "paste"
main = "src/index.ts"
compatibility_date = "2022-05-30"
+node_compat = true
kv_namespaces = [
{ binding = "PASTE_INDEX", id = "a578863da0564cd7beadd9ce4a2d53e8", preview_id = "66d9440e13124099a5e508fe1ff0a489" }
]