diff --git a/src/rollup/plugins/public-assets.ts b/src/rollup/plugins/public-assets.ts index dda85a2006..b060f59086 100644 --- a/src/rollup/plugins/public-assets.ts +++ b/src/rollup/plugins/public-assets.ts @@ -114,6 +114,30 @@ export function isPublicAssetURL(id = '') { return false } +const keyStartsWith = (literalObj, needle) => Object.keys(literalObj).some((k) => k.startsWith(needle)); +const findKey = (literalObj, needle) => Object.keys(literalObj).find((k) => k.startsWith(needle)); + +export const isInKv = (id = "") => { + if ( + assets[id] || + keyStartsWith(assets, id) || + keyStartsWith(publicAssetBases, id) + ) { + return true + } + return false +} + +export const getKVMatch = (id = "") => { + const assetMatch = findKey(assets, id) + if(assetMatch) return [assetMatch, assets[assetMatch]] + + const publicAssetMatch = findKey(publicAssetBases, id) + if(publicAssetMatch) return [publicAssetMatch, publicAssetBases[publicAssetMatch]] + + return null +} + export function getPublicAssetMeta(id = '') { for (const base in publicAssetBases) { if (id.startsWith(base)) { return publicAssetBases[base] } diff --git a/src/runtime/entries/cloudflare-module.ts b/src/runtime/entries/cloudflare-module.ts index 7815519361..b26d83f652 100644 --- a/src/runtime/entries/cloudflare-module.ts +++ b/src/runtime/entries/cloudflare-module.ts @@ -12,10 +12,10 @@ import { requestHasBody } from "../utils"; import { nitroApp } from "#internal/nitro/app"; import { useRuntimeConfig } from "#internal/nitro"; import { + getKVMatch, getPublicAssetMeta, - publicAssetBases, + isInKv, } from "#internal/nitro/virtual/public-assets"; -import assets from "#internal/nitro/virtual/public-assets-data"; interface CFModuleEnv { [key: string]: any; @@ -30,10 +30,11 @@ export default { const url = new URL(request.url); try { if (isInKv(url.pathname)) { + const [match] = getKVMatch(url.pathname); // https://github.com/cloudflare/kv-asset-handler#es-modules return await getAssetFromKV( { - request, + request: new Request(new URL("http://localhost" + match)), waitUntil(promise) { return context.waitUntil(promise); }, @@ -47,7 +48,8 @@ export default { ); } } catch { - // Ignore + // getAssetFromKV fail to return files with no extensions, + // so we can catch here and let Nitro handle it. } let body; @@ -91,16 +93,3 @@ const baseURLModifier = (request: Request) => { const url = withoutBase(request.url, useRuntimeConfig().app.baseURL); return mapRequestToAsset(new Request(url, request)); }; - -const keyStartsWith = (literalObj: Record, needle: string) => - Object.keys(literalObj).some((k) => k.startsWith(needle)); -const isInKv = (id = "") => { - if ( - assets[id] || - keyStartsWith(assets, id) || - keyStartsWith(publicAssetBases, id) - ) { - return true; - } - return false; -}; diff --git a/src/runtime/entries/cloudflare-pages.ts b/src/runtime/entries/cloudflare-pages.ts index 3fd0548352..20b4c41295 100644 --- a/src/runtime/entries/cloudflare-pages.ts +++ b/src/runtime/entries/cloudflare-pages.ts @@ -5,7 +5,7 @@ import type { } from "@cloudflare/workers-types"; import { requestHasBody } from "#internal/nitro/utils"; import { nitroApp } from "#internal/nitro/app"; -import { isPublicAssetURL } from "#internal/nitro/virtual/public-assets"; +import { isInKv, getKVMatch } from "#internal/nitro/virtual/public-assets"; /** * Reference: https://developers.cloudflare.com/workers/runtime-apis/fetch-event/#parameters @@ -27,8 +27,16 @@ export default { context: EventContext ) { const url = new URL(request.url); - if (isPublicAssetURL(url.pathname)) { - return env.ASSETS.fetch(request); + if (isInKv(url.pathname)) { + try { + const [match] = getKVMatch(url.pathname); + return await env.ASSETS.fetch( + new Request(new URL("http://localhost" + match)) + ); + } catch (error) { + console.error(error); + throw error; + } } let body; diff --git a/src/runtime/entries/cloudflare.ts b/src/runtime/entries/cloudflare.ts index a9f1436360..d08d07afcb 100644 --- a/src/runtime/entries/cloudflare.ts +++ b/src/runtime/entries/cloudflare.ts @@ -9,9 +9,8 @@ import { nitroApp } from "#internal/nitro/app"; import { useRuntimeConfig } from "#internal/nitro"; import { getPublicAssetMeta, - publicAssetBases, + isInKv, } from "#internal/nitro/virtual/public-assets"; -import assets from "#internal/nitro/virtual/public-assets-data"; addEventListener("fetch", (event: any) => { event.respondWith(handleEvent(event)); @@ -83,16 +82,3 @@ function normalizeOutgoingHeaders( Array.isArray(v) ? v.join(",") : v, ]); } - -const keyStartsWith = (literalObj: Record, needle: string) => - Object.keys(literalObj).some((k) => k.startsWith(needle)); -const isInKv = (id = "") => { - if ( - assets[id] || - keyStartsWith(assets, id) || - keyStartsWith(publicAssetBases, id) - ) { - return true; - } - return false; -}; diff --git a/src/runtime/virtual/public-assets.d.ts b/src/runtime/virtual/public-assets.d.ts index bc24635a2b..f88a888a79 100644 --- a/src/runtime/virtual/public-assets.d.ts +++ b/src/runtime/virtual/public-assets.d.ts @@ -3,3 +3,5 @@ export const isPublicAssetURL: (id: string) => boolean; export const getPublicAssetMeta: (id: string) => { maxAge?: number }; export const readAsset: (id: string) => Promise; export const getAsset: (id: string) => any; +export const isInKv: (id: string) => boolean; +export const getKVMatch: (id: string) => [string, string] | null;