| 15 | const publicNpmRegistry = "https://registry.npmjs.org"; |
| 16 | |
| 17 | export async function handleRequest(request: Request, env: Env, context: ExecutionContext): Promise<Response> { |
| 18 | if (request.method === "OPTIONS") { |
| 19 | return new Response(null, { |
| 20 | headers: { Allow: "GET, HEAD, OPTIONS" }, |
| 21 | }); |
| 22 | } |
| 23 | if (request.method !== "GET" && request.method !== "HEAD") { |
| 24 | return new Response(`Invalid request method: ${request.method}`, { status: 405 }); |
| 25 | } |
| 26 | |
| 27 | let url = new URL(request.url); |
| 28 | |
| 29 | if (url.pathname === "/_health") { |
| 30 | return new Response("OK"); |
| 31 | } |
| 32 | if (url.pathname === "/favicon.ico") { |
| 33 | return notFound(); |
| 34 | } |
| 35 | if (url.pathname === "/" || url.pathname === "/index.html") { |
| 36 | return redirect(env.WWW_ORIGIN, 301); |
| 37 | } |
| 38 | |
| 39 | let parsed = parsePackagePathname(url.pathname); |
| 40 | if (parsed == null) { |
| 41 | return notFound(`Invalid package pathname: ${url.pathname}`); |
| 42 | } |
| 43 | |
| 44 | let packageName = parsed.package.toLowerCase(); |
| 45 | let packageInfo = await getPackageInfo(context, publicNpmRegistry, packageName); |
| 46 | if (packageInfo == null) { |
| 47 | return notFound(`Package not found: "${packageName}"`); |
| 48 | } |
| 49 | |
| 50 | let requestedVersion = parsed.version ?? "latest"; |
| 51 | let version = resolvePackageVersion(packageInfo, requestedVersion); |
| 52 | if (version == null || packageInfo.versions == null || packageInfo.versions[version] == null) { |
| 53 | return notFound(`Package version not found: ${packageName}@${requestedVersion}`); |
| 54 | } |
| 55 | |
| 56 | if (parsed.filename != null && parsed.filename.endsWith("/")) { |
| 57 | let noTrailingSlash = parsed.filename.replace(/\/+$/, ""); |
| 58 | return redirect(`/${packageName}@${version}${noTrailingSlash}`, 301); |
| 59 | } |
| 60 | if (parsed.filename === "/files") { |
| 61 | return redirect(`/${packageName}@${version}`, 301); |
| 62 | } |
| 63 | if (version !== parsed.version) { |
| 64 | return redirect(`/${packageName}@${version}${parsed.filename ?? ""}`, { |
| 65 | headers: { |
| 66 | "Cache-Control": "public, max-age=60, s-maxage=300", |
| 67 | }, |
| 68 | }); |
| 69 | } |
| 70 | |
| 71 | let files = await listFiles(context, env.FILES_ORIGIN, packageName, version, "/"); |
| 72 | let filename = parsed.filename ?? "/"; |
| 73 | |
| 74 | if (filename === "/") { |