mirror of
https://github.com/rikkaneko/paste.git
synced 2025-06-06 16:45:41 +00:00
Add description text and file size check to paste.html
Add x-pass header to authentication method Add size to paste info Prefix the custom header key with x- Signed-off-by: Joe Ma <rikkaneko23@gmail.com>
This commit is contained in:
parent
78806e331d
commit
d1c43280d5
3 changed files with 67 additions and 15 deletions
18
paste.html
18
paste.html
|
@ -25,6 +25,17 @@
|
|||
|
||||
<body>
|
||||
<h2>Paste Service</h2>
|
||||
<p>
|
||||
<a href="https://pb.nekoul.com">pb.nekoul.com</a> is a pastebin-like service hosted on Cloudflare Worker.<br>
|
||||
This service is primaryly designed for own usage and interest only.<br>
|
||||
All data may be deleted or expired without any notification and guarantee. Please <b>DO NOT</b> abuse this service.<br>
|
||||
The limit for file upload is <b>10 MB</b> and the paste will be kept for <b>180 days</b> only by default.<br>
|
||||
The source code is available in my GitHub repository <a href="https://github.com/rikkaneko/paste">[here]</a>.<br>
|
||||
This webpage is designed for upload files only.
|
||||
For other operations like changing paste settings and deleting paste, please make use of the
|
||||
<a href="https://pb.nekoul.com/api">API call</a> with <a href="https://wiki.archlinux.org/title/CURL">curl</a>.
|
||||
</p>
|
||||
|
||||
<form id="upload_file_form" action="https://pb.nekoul.com" method="POST" enctype=multipart/form-data>
|
||||
<div>
|
||||
<h4>Upload file</h4>
|
||||
|
@ -92,6 +103,13 @@
|
|||
let select_file = elements.namedItem("upload_file");
|
||||
let text = elements.namedItem("text_input");
|
||||
if (!!select_file.value.length ^ !!text.value.length) {
|
||||
// Check file size
|
||||
const size = select_file.files[0]?.size ?? 0;
|
||||
if (size <= 0 || size > 10485760) {
|
||||
alert("Upload file size must not excess 10 MB.");
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
elements[i].disabled = elements[i].value.length === 0;
|
||||
}
|
||||
|
|
63
src/index.ts
63
src/index.ts
|
@ -39,25 +39,40 @@ const API_SPEC_TEXT =
|
|||
[API Specification]
|
||||
GET / Fetch the Web frontpage for uploading text/file [x]
|
||||
GET /api Fetch API specification
|
||||
|
||||
# Authentication support HTTP Basic access authentication (RFC 7617) or the x-pass header
|
||||
GET /<uuid> Fetch the paste by uuid [x]
|
||||
|
||||
GET /<uuid>/<lang> Fetch the paste (code) in rendered HTML with syntax highlighting [ ]
|
||||
GET /<uuid>/settings Fetch the paste information [x]
|
||||
GET /<uuid>/download Download the paste [x]
|
||||
POST / Create new paste [x] # Only support multipart/form-data and raw data
|
||||
|
||||
# Only support multipart/form-data and raw request
|
||||
# For form-data, u=<upload-data>, both title and content-type is deduced from the u
|
||||
# The following key is supported for both HTTP form request and headers
|
||||
# x-title: File title, i.e.,
|
||||
# content-type: The media type (MIME) of the data and encoding, i.e., text/plain; charset=UTF-8;
|
||||
# x-pass: Paste password
|
||||
# x-read-limit: Limit access times to paste to <read-limit>
|
||||
POST / Create new paste [x]
|
||||
|
||||
DELETE /<uuid> Delete paste by uuid [x]
|
||||
POST /<uuid>/settings Update paste setting, i.e., passcode and valid time [ ]
|
||||
|
||||
# For paste with password protected, all API call related to the pastes requires additional x-pass header
|
||||
|
||||
* uuid: [A-z0-9]{${UUID_LENGTH}}
|
||||
* option: Render language
|
||||
|
||||
Features
|
||||
* Password protection [ ]
|
||||
* Password protection [x]
|
||||
* Expiring paste [ ]
|
||||
|
||||
[ ] indicated not implemented
|
||||
|
||||
Limitation
|
||||
* Max. 10MB file size upload (Max. 100MB body size for free Cloudflare plan)
|
||||
* Max. 10MB file size upload
|
||||
* Paste will be kept for 180 days only
|
||||
|
||||
Last update on 2 June.
|
||||
`;
|
||||
|
@ -165,14 +180,14 @@ export default {
|
|||
|
||||
// Raw body
|
||||
} else {
|
||||
if (headers.has("title")) {
|
||||
title = headers.get("title") || "";
|
||||
if (headers.has("x-title")) {
|
||||
title = headers.get("x-title") || "";
|
||||
mime_type = contentType(title) || undefined;
|
||||
}
|
||||
mime_type = headers.get("content-type") || mime_type;
|
||||
password = headers.get("pass") || undefined;
|
||||
password = headers.get("x-pass") || undefined;
|
||||
// Handle read-limit:read_count_remain
|
||||
const count = headers.get("read-limit") || undefined;
|
||||
const count = headers.get("x-read-limit") || undefined;
|
||||
if (count !== undefined && !isNaN(+count)) {
|
||||
read_limit = Number(count) || undefined;
|
||||
}
|
||||
|
@ -188,7 +203,8 @@ export default {
|
|||
}
|
||||
|
||||
// Check request.body size <= 10MB
|
||||
if (buffer.byteLength > 10485760) {
|
||||
const size = buffer.byteLength;
|
||||
if (size > 10485760) {
|
||||
return new Response("Paste size must be under 10MB.\n", {
|
||||
status: 422
|
||||
});
|
||||
|
@ -212,6 +228,7 @@ export default {
|
|||
title: title ?? undefined,
|
||||
last_modified: Date.now(),
|
||||
password: password? sha256(password).slice(0, 16): undefined,
|
||||
size,
|
||||
read_count_remain: read_limit,
|
||||
mime_type
|
||||
};
|
||||
|
@ -277,24 +294,29 @@ export default {
|
|||
if (cert === null) {
|
||||
return new Response("Invalid Authorization header.", {
|
||||
status: 400
|
||||
})
|
||||
});
|
||||
}
|
||||
// Check password and username should be empty
|
||||
if (cert[0].length != 0 || descriptor.password !== sha256(cert[1]).slice(0, 16)) {
|
||||
return new Response(null, {
|
||||
return new Response("Incorrect password.\n", {
|
||||
status: 401,
|
||||
headers: {
|
||||
"WWW-Authenticate": "Basic realm=\"Requires password\""
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
// x-pass header
|
||||
} else if (headers.has("x-pass")) {
|
||||
if (descriptor.password !== sha256(headers.get("x-pass")!).slice(0, 16)) {
|
||||
return new Response("Incorrect password.\n");
|
||||
}
|
||||
} else {
|
||||
return new Response(null, {
|
||||
return new Response("This paste requires password.\n", {
|
||||
status: 401,
|
||||
headers: {
|
||||
"WWW-Authenticate": "Basic realm=\"Requires password\""
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,7 +325,7 @@ export default {
|
|||
if (descriptor.read_count_remain <= 0) {
|
||||
return new Response("Paste expired.\n", {
|
||||
status: 410
|
||||
})
|
||||
});
|
||||
}
|
||||
descriptor.read_count_remain--;
|
||||
ctx.waitUntil(env.PASTE_INDEX.put(uuid, JSON.stringify(descriptor)));
|
||||
|
@ -411,6 +433,7 @@ function get_paste_info(uuid: string, descriptor: PasteIndexEntry): string {
|
|||
id: ${uuid}
|
||||
title: ${descriptor.title || "<empty>"}
|
||||
mime-type: ${descriptor.mime_type ?? "application/octet-stream"}
|
||||
size: ${descriptor.size} bytes (${to_human_readable_size(descriptor.size)})
|
||||
password: ${(!!descriptor.password)}
|
||||
editable: ${descriptor.editable? descriptor.editable: true}
|
||||
remaining read count: ${descriptor.read_count_remain !== undefined?
|
||||
|
@ -449,11 +472,21 @@ function get_basic_auth(headers: Headers): [string, string] | null {
|
|||
}
|
||||
}
|
||||
|
||||
function to_human_readable_size(bytes: number): string {
|
||||
let size = bytes + " bytes";
|
||||
const units = ["KiB", "MiB", "GiB", "TiB"];
|
||||
for (let i = 0, approx = bytes / 1024; approx > 1; approx /= 1024, i++) {
|
||||
size = approx.toFixed(3) + " " + units[i];
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
interface PasteIndexEntry {
|
||||
title?: string,
|
||||
mime_type?: string,
|
||||
last_modified: number,
|
||||
password?: string
|
||||
size: number,
|
||||
password?: string,
|
||||
editable?: boolean, // Default: True
|
||||
read_count_remain?: number
|
||||
}
|
|
@ -2,6 +2,7 @@ name = "paste"
|
|||
main = "src/index.ts"
|
||||
compatibility_date = "2022-05-30"
|
||||
node_compat = true
|
||||
workers_dev = false
|
||||
kv_namespaces = [
|
||||
{ binding = "PASTE_INDEX", id = "a578863da0564cd7beadd9ce4a2d53e8", preview_id = "66d9440e13124099a5e508fe1ff0a489" }
|
||||
]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue