mirror of
https://github.com/rikkaneko/paste.git
synced 2025-06-06 00:25:38 +00:00
Use request forwarding for large paste
Signed-off-by: Joe Ma <rikkaneko23@gmail.com>
This commit is contained in:
parent
63578bcf9d
commit
1fb3076115
4 changed files with 41 additions and 25 deletions
55
src/index.ts
55
src/index.ts
|
@ -19,7 +19,7 @@
|
||||||
import { AwsClient } from 'aws4fetch';
|
import { AwsClient } from 'aws4fetch';
|
||||||
import { sha256 } from 'js-sha256';
|
import { sha256 } from 'js-sha256';
|
||||||
import { Router, error } from 'itty-router';
|
import { Router, error } from 'itty-router';
|
||||||
import { ERequest, Env, PasteIndexEntry, PASTE_TYPES } from './types';
|
import { ERequest, Env, PasteIndexEntry } from './types';
|
||||||
import { serve_static } from './proxy';
|
import { serve_static } from './proxy';
|
||||||
import { check_password_rules, get_paste_info, get_basic_auth, gen_id } from './utils';
|
import { check_password_rules, get_paste_info, get_basic_auth, gen_id } from './utils';
|
||||||
import { UUID_LENGTH, PASTE_WEB_URL, SERVICE_URL, CORS_DOMAIN } from './constant';
|
import { UUID_LENGTH, PASTE_WEB_URL, SERVICE_URL, CORS_DOMAIN } from './constant';
|
||||||
|
@ -334,6 +334,7 @@ router.get('/:uuid/:option?', async (request, env, ctx) => {
|
||||||
|
|
||||||
// New added in 2.0
|
// New added in 2.0
|
||||||
// Handle large_paste
|
// Handle large_paste
|
||||||
|
// Use presigned url generation only if the file size larger than 200MB, use request forwarding instead
|
||||||
if (descriptor.type === 'large_paste') {
|
if (descriptor.type === 'large_paste') {
|
||||||
if (!descriptor.upload_completed) {
|
if (!descriptor.upload_completed) {
|
||||||
return new Response('This paste is not yet finalized.\n', {
|
return new Response('This paste is not yet finalized.\n', {
|
||||||
|
@ -341,21 +342,23 @@ router.get('/:uuid/:option?', async (request, env, ctx) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const signed_url = await get_presign_url(uuid, descriptor, env);
|
if (descriptor.size >= 209715200) {
|
||||||
|
const signed_url = await get_presign_url(uuid, descriptor, env);
|
||||||
|
|
||||||
ctx.waitUntil(
|
ctx.waitUntil(
|
||||||
env.PASTE_INDEX.put(uuid, JSON.stringify(descriptor), {
|
env.PASTE_INDEX.put(uuid, JSON.stringify(descriptor), {
|
||||||
expiration: descriptor.expiration! / 1000,
|
expiration: descriptor.expiration! / 1000,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
return new Response(null, {
|
return new Response(null, {
|
||||||
status: 301,
|
status: 301,
|
||||||
headers: {
|
headers: {
|
||||||
location: signed_url,
|
location: signed_url,
|
||||||
'cache-control': 'no-store',
|
'cache-control': 'no-store',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable CF cache for authorized request
|
// Enable CF cache for authorized request
|
||||||
|
@ -375,13 +378,20 @@ router.get('/:uuid/:option?', async (request, env, ctx) => {
|
||||||
|
|
||||||
let res = await cache.match(req_key);
|
let res = await cache.match(req_key);
|
||||||
if (res === undefined) {
|
if (res === undefined) {
|
||||||
|
// Use althernative endpoint and credentials for large_type
|
||||||
|
const endpoint = descriptor.type === 'large_paste' ? env.LARGE_DOWNLOAD_ENDPOINT : env.ENDPOINT;
|
||||||
|
const access_key_id = descriptor.type === 'large_paste' ? env.LARGE_AWS_ACCESS_KEY_ID! : env.AWS_ACCESS_KEY_ID;
|
||||||
|
const secret_access_key =
|
||||||
|
descriptor.type === 'large_paste' ? env.LARGE_AWS_SECRET_ACCESS_KEY! : env.AWS_SECRET_ACCESS_KEY;
|
||||||
|
|
||||||
const s3 = new AwsClient({
|
const s3 = new AwsClient({
|
||||||
accessKeyId: env.AWS_ACCESS_KEY_ID,
|
accessKeyId: access_key_id,
|
||||||
secretAccessKey: env.AWS_SECRET_ACCESS_KEY,
|
secretAccessKey: secret_access_key,
|
||||||
service: 's3', // required
|
service: 's3', // required
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fetch form origin if not hit cache
|
// Fetch form origin if not hit cache
|
||||||
let origin = await s3.fetch(`${env.ENDPOINT}/${uuid}`, {
|
let origin = await s3.fetch(`${endpoint}/${uuid}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: match_etag
|
headers: match_etag
|
||||||
? {
|
? {
|
||||||
|
@ -527,12 +537,19 @@ router.delete('/:uuid', async (request, env, ctx) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use althernative endpoint and credentials for large_type
|
||||||
const endpoint = descriptor.type === 'large_paste' ? env.LARGE_DOWNLOAD_ENDPOINT : env.ENDPOINT;
|
const endpoint = descriptor.type === 'large_paste' ? env.LARGE_DOWNLOAD_ENDPOINT : env.ENDPOINT;
|
||||||
|
const access_key_id = descriptor.type === 'large_paste' ? env.LARGE_AWS_ACCESS_KEY_ID! : env.AWS_ACCESS_KEY_ID;
|
||||||
|
const secret_access_key =
|
||||||
|
descriptor.type === 'large_paste' ? env.LARGE_AWS_SECRET_ACCESS_KEY! : env.AWS_SECRET_ACCESS_KEY;
|
||||||
|
|
||||||
const s3 = new AwsClient({
|
const s3 = new AwsClient({
|
||||||
accessKeyId: descriptor.type === 'large_paste' ? env.LARGE_AWS_ACCESS_KEY_ID! : env.AWS_ACCESS_KEY_ID,
|
accessKeyId: access_key_id,
|
||||||
secretAccessKey: descriptor.type === 'large_paste' ? env.LARGE_AWS_SECRET_ACCESS_KEY! : env.AWS_SECRET_ACCESS_KEY,
|
secretAccessKey: secret_access_key,
|
||||||
service: 's3', // required
|
service: 's3', // required
|
||||||
});
|
});
|
||||||
|
|
||||||
let res = await s3.fetch(`${endpoint}/${uuid}`, {
|
let res = await s3.fetch(`${endpoint}/${uuid}`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
});
|
});
|
||||||
|
|
3
src/types.d.ts
vendored
3
src/types.d.ts
vendored
|
@ -6,7 +6,7 @@ export type ERequest = {
|
||||||
// match_etag?: string;
|
// match_etag?: string;
|
||||||
} & IRequest;
|
} & IRequest;
|
||||||
|
|
||||||
export type PASTE_TYPES = 'paste' | 'link' | 'large_paste';
|
export type PASTE_TYPES = 'paste' | 'text' | 'link' | 'large_paste';
|
||||||
|
|
||||||
export interface PasteIndexEntry {
|
export interface PasteIndexEntry {
|
||||||
title?: string;
|
title?: string;
|
||||||
|
@ -20,7 +20,6 @@ export interface PasteIndexEntry {
|
||||||
type: PASTE_TYPES;
|
type: PASTE_TYPES;
|
||||||
// Only apply when large_paste
|
// Only apply when large_paste
|
||||||
upload_completed?: boolean;
|
upload_completed?: boolean;
|
||||||
sha256_hash?: string;
|
|
||||||
cached_presigned_url?: string;
|
cached_presigned_url?: string;
|
||||||
cached_presigned_url_expiration?: number;
|
cached_presigned_url_expiration?: number;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ import { PasteIndexEntry, Env } from './types';
|
||||||
|
|
||||||
export const gen_id = customAlphabet('1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', UUID_LENGTH);
|
export const gen_id = customAlphabet('1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', UUID_LENGTH);
|
||||||
|
|
||||||
export function get_paste_info_obj(uuid: string, descriptor: PasteIndexEntry, env: Env) {
|
export function get_paste_info_obj(uuid: string, descriptor: PasteIndexEntry) {
|
||||||
const created = new Date(descriptor.last_modified);
|
const created = new Date(descriptor.last_modified);
|
||||||
const expired = new Date(descriptor.expiration ?? descriptor.last_modified + 2419200000);
|
const expired = new Date(descriptor.expiration ?? descriptor.last_modified + 2419200000);
|
||||||
const link = `https://${SERVICE_URL}/${uuid}`;
|
const link = `https://${SERVICE_URL}/${uuid}`;
|
||||||
|
@ -53,7 +53,7 @@ export async function get_paste_info(
|
||||||
need_qr: boolean = false,
|
need_qr: boolean = false,
|
||||||
reply_json = false
|
reply_json = false
|
||||||
): Promise<Response> {
|
): Promise<Response> {
|
||||||
const paste_info = get_paste_info_obj(uuid, descriptor, env);
|
const paste_info = get_paste_info_obj(uuid, descriptor);
|
||||||
|
|
||||||
// Reply with JSON
|
// Reply with JSON
|
||||||
if (reply_json) {
|
if (reply_json) {
|
||||||
|
@ -167,6 +167,7 @@ export function get_basic_auth(headers: Headers): [string, string] | null {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function to_human_readable_size(bytes: number): string {
|
function to_human_readable_size(bytes: number): string {
|
||||||
let size = bytes + ' bytes';
|
let size = bytes + ' bytes';
|
||||||
const units = ['KiB', 'MiB', 'GiB', 'TiB'];
|
const units = ['KiB', 'MiB', 'GiB', 'TiB'];
|
||||||
|
|
|
@ -165,7 +165,6 @@ router.post('/create', async (request, env, ctx) => {
|
||||||
type: 'large_paste',
|
type: 'large_paste',
|
||||||
size: file_size,
|
size: file_size,
|
||||||
upload_completed: false,
|
upload_completed: false,
|
||||||
sha256_hash: file_hash,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ctx.waitUntil(
|
ctx.waitUntil(
|
||||||
|
@ -250,7 +249,7 @@ router.post('/complete/:uuid', async (request, env, ctx) => {
|
||||||
const paste_info = {
|
const paste_info = {
|
||||||
upload_completed: true,
|
upload_completed: true,
|
||||||
expired: new Date(expriation).toISOString(),
|
expired: new Date(expriation).toISOString(),
|
||||||
paste_info: get_paste_info_obj(uuid, descriptor, env),
|
paste_info: get_paste_info_obj(uuid, descriptor),
|
||||||
};
|
};
|
||||||
|
|
||||||
return new Response(JSON.stringify(paste_info));
|
return new Response(JSON.stringify(paste_info));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue