getting 1042 error from calling a "fetch" call within my React Router application

I'm deploying my React Router (version 7 latest) application as a Worker and it doesn't allow me to fetch an endpoint which is exactly what I need because I'm adding Cache-Control headers to make it incredibly fast
headers: {
"Cache-Control": `s-maxage=${31536000}`,
},
headers: {
"Cache-Control": `s-maxage=${31536000}`,
},
I need this to be this way because there are many JOINs involved when calling this endpoint, I want to cache and revalidate, not compute every time. what's the recommendation here? understood that it's about security, but then what? I need my native WebAPIs and techniques to work, right?
5 Replies
Walshy
Walshy2w ago
1042 should only ever be returned if you're fetching the origin for workers.dev Which, won't do what you expect if you think that'll return a cache-control header Can you give more context on what you're trying to do and where?
niconiahi
niconiahiOP2w ago
here is the full ordeal: context: React Router 7 application, just migrated from Remix, in which context said problem was not existent. Only after the migration it has arised. I also had to go from deploying to Pages to Workers, as recommended in Discord by the React Router team I have a home page which renders a list of products. This products are gotten via a fetch call to this endpoint (https://morfar.niconiahi.workers.dev/en-US/restaurant/1/products/get) like this
export async function loader({ request, context, params }: LoaderFunctionArgs) {
const env = getEnv(context)
const origin = getOrigin(env)
const restaurantId = params.restaurantId
const locale = params.locale
const products = await fetchProducts({ origin, locale, restaurantId })
return {
products
}
}
export async function loader({ request, context, params }: LoaderFunctionArgs) {
const env = getEnv(context)
const origin = getOrigin(env)
const restaurantId = params.restaurantId
const locale = params.locale
const products = await fetchProducts({ origin, locale, restaurantId })
return {
products
}
}
this is the code for the /products/get endpoint
export async function loader({ context, params }: LoaderFunctionArgs) {
const queryBuilder = context.queryBuilder
const restaurantId = params.restaurantId
const locale = params.locale
const products = await getProducts({ locale, queryBuilder, restaurantId })
return data(products, {
headers: {
"Cache-Control": `s-maxage=${31536000}`,
},
})
}
export async function getProducts({
queryBuilder,
restaurantId,
locale,
}: {
queryBuilder: QueryBuilder
restaurantId: number
locale: Locale
}) {
// very heavy D1 computation here
})
export async function loader({ context, params }: LoaderFunctionArgs) {
const queryBuilder = context.queryBuilder
const restaurantId = params.restaurantId
const locale = params.locale
const products = await getProducts({ locale, queryBuilder, restaurantId })
return data(products, {
headers: {
"Cache-Control": `s-maxage=${31536000}`,
},
})
}
export async function getProducts({
queryBuilder,
restaurantId,
locale,
}: {
queryBuilder: QueryBuilder
restaurantId: number
locale: Locale
}) {
// very heavy D1 computation here
})
as you can see it's a simple flow, in my head this should be completely possible. I mean, every call is isolated from each other, what would be the purpose I wonder if this is not allowed this is the wrapper function to be reused when calling this endpoint, very simple as well
export async function fetchProducts({
origin,
restaurantId,
locale,
}: {
origin: string
restaurantId: number
locale: Locale
}) {
const products = await fetch(`${origin}/${locale}/restaurant/${restaurantId}/products/get`, {
headers: {
"Content-Type": "application/json",
},
})
.then(async (response) => {
return response.json()
})
.then((data) => {
return data as Product[]
})
return products
}
export async function fetchProducts({
origin,
restaurantId,
locale,
}: {
origin: string
restaurantId: number
locale: Locale
}) {
const products = await fetch(`${origin}/${locale}/restaurant/${restaurantId}/products/get`, {
headers: {
"Content-Type": "application/json",
},
})
.then(async (response) => {
return response.json()
})
.then((data) => {
return data as Product[]
})
return products
}
i'm thinking about replacing such caching capabilities with KV but I would prefer relying on web technologies the most i can, to be honest
Walshy
Walshy2w ago
So yeah, you're trying to fetch behind the Worker but there's nothing behind Workers on workers.dev Are you just trying to fetch from a different path within your Worker? You should just invoke a function for that rather than try to do a fetch call and cache wouldn't be applied either way here as Workers are before cache So basically I think the flow will be: * home page calls loader func for productsGet * loader for products get has a cache API match call * if hit, return cached products * if miss, get the products, put into the cache and return
niconiahi
niconiahiOP2w ago
and cache wouldn't be applied either way here as Workers are before cache
really good to know, I noticed problems before where the cache wouldn't HIT even after just a few days, even having the highest TTL value possible (which is about a month or year, I don't remember) two more questions if possible one: for caching you are recommending KV or what? two: would it ever a Cache-Control header work with a Worker? under which circumstance?
Walshy
Walshy2w ago
KV works too but cache API works too - https://developers.cloudflare.com/workers/runtime-apis/cache/ for 2, we use it for external requests, we'll cache the response for those and it's also read when inserting into cache

Did you find this page helpful?