[workers] Import upload worker (#2164)

This commit is contained in:
Manav Rathi
2024-06-17 09:12:15 +05:30
committed by GitHub
4 changed files with 141 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
{
"name": "uploader",
"private": true,
"devDependencies": {
"@cloudflare/workers-types": "^4.20240614.0",
"typescript": "^5",
"wrangler": "^3"
},
"packageManager": "yarn@1.22.22"
}

View File

@@ -0,0 +1,123 @@
/**
* Proxy file uploads.
*
* See: https://ente.io/blog/tech/making-uploads-faster/
*/
export default {
async fetch(request: Request) {
switch (request.method) {
case "OPTIONS":
return handleOPTIONS(request);
case "POST":
return handlePOSTOrPUT(request);
case "PUT":
return handlePOSTOrPUT(request);
default:
console.log(`Unsupported HTTP method ${request.method}`);
return new Response(null, { status: 405 });
}
},
} satisfies ExportedHandler;
const handleOPTIONS = (request: Request) => {
const origin = request.headers.get("Origin");
if (!isAllowedOrigin(origin)) console.warn("Unknown origin", origin);
const headers = request.headers.get("Access-Control-Request-Headers");
if (!areAllowedHeaders(headers))
console.warn("Unknown header in list", headers);
return new Response("", {
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "POST, PUT, OPTIONS",
"Access-Control-Max-Age": "86400",
// "Access-Control-Allow-Headers": "Content-Type", "UPLOAD-URL, X-Client-Package",
"Access-Control-Allow-Headers": "*",
"Access-Control-Expose-Headers": "X-Request-Id, CF-Ray",
},
});
};
const isAllowedOrigin = (origin: string | null) => {
const desktopApp = "ente://app";
const allowedHostnames = [
"web.ente.io",
"photos.ente.io",
"photos.ente.sh",
"localhost",
];
if (!origin) return false;
try {
const url = new URL(origin);
return origin == desktopApp || allowedHostnames.includes(url.hostname);
} catch {
// origin is likely an invalid URL
return false;
}
};
const areAllowedHeaders = (headers: string | null) => {
const allowed = ["Content-Type", "UPLOAD-URL", "X-Client-Package"];
if (!headers) return true;
for (const header of headers.split(",")) {
if (!allowed.includes(header.trim().toLowerCase())) return false;
}
return true;
};
const handlePOSTOrPUT = async (request: Request) => {
const url = new URL(request.url);
const uploadURL = request.headers.get("UPLOAD-URL");
if (!uploadURL) {
console.error("No uploadURL provided");
return new Response(null, { status: 400 });
}
let response: Response;
switch (url.pathname) {
case "/file-upload":
response = await fetch(uploadURL, {
method: request.method,
body: request.body,
});
break;
case "/multipart-upload":
response = await fetch(uploadURL, {
method: request.method,
body: request.body,
});
if (response.ok) {
const etag = response.headers.get("etag");
if (etag === null) {
console.log("No etag in response", response);
response = new Response(null, { status: 500 });
} else {
response = new Response(JSON.stringify({ etag }));
}
}
break;
case "/multipart-complete":
response = await fetch(uploadURL, {
method: request.method,
body: request.body,
headers: {
"Content-Type": "text/xml",
},
});
break;
default:
response = new Response(null, { status: 404 });
break;
}
response = new Response(response.body, response);
response.headers.set("Access-Control-Allow-Origin", "*");
response.headers.set(
"Access-Control-Expose-Headers",
"X-Request-Id, CF-Ray"
);
return response;
};

View File

@@ -0,0 +1 @@
{ "extends": "../tsconfig.base.json", "include": ["src"] }

View File

@@ -0,0 +1,7 @@
name = "uploader"
main = "src/index.ts"
compatibility_date = "2024-06-14"
routes = [{ pattern = "uploader.ente.io", custom_domain = true }]
tail_consumers = [{ service = "tail" }]