Route handler not caching GET request
Answered
MooKorea posted this in #help-forum
MooKoreaOP
A similar question was asked here https://nextjs-forum.com/post/1254075664202469386, but I think it's better to create a new thread. According to the docs here https://nextjs.org/docs/app/building-your-application/routing/route-handlers#caching, route handlers are supposed to be cached. However, when deploying to Vercel it's not being cached at all and I hit the ratelimit on my API (a new request was being called whenever the page was refreshed, which happens a lot during development). Here is my code:
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const query = searchParams.get("query");
if (query === null) {
return new Response("Error: query not provided", { status: 400 });
}
const url = `https://financialmodelingprep.com/api/v3/search?query=${query.toUpperCase()}&limit=10&apikey=${
process.env.FINANCIAL_MODELING_PREP_KEY
}`;
try {
const res = await fetch(url, {
headers: {
"Content-Type": "application/json",
},
});
const data = await res.json();
return Response.json(
{ data },
{
status: 200,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
},
}
);
} catch (error) {
console.error(error)
}
}Answered by joulev
GET handlers are cached by default indeed, but here you are reading the
searchParams which opts out of caching. perhaps you need unstable_cache here to cache the query manually5 Replies
@MooKorea A similar question was asked here https://discord.com/channels/752553802359505017/1254075664202469386, but I think it's better to create a new thread. According to the docs here https://nextjs.org/docs/app/building-your-application/routing/route-handlers#caching, route handlers are supposed to be cached. However, when deploying to Vercel it's not being cached at all and I hit the ratelimit on my API (a new request was being called whenever the page was refreshed, which happens a lot during development). Here is my code:
ts
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const query = searchParams.get("query");
if (query === null) {
return new Response("Error: query not provided", { status: 400 });
}
const url = `https://financialmodelingprep.com/api/v3/search?query=${query.toUpperCase()}&limit=10&apikey=${
process.env.FINANCIAL_MODELING_PREP_KEY
}`;
try {
const res = await fetch(url, {
headers: {
"Content-Type": "application/json",
},
});
const data = await res.json();
return Response.json(
{ data },
{
status: 200,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
},
}
);
} catch (error) {
console.error(error)
}
}
GET handlers are cached by default indeed, but here you are reading the
searchParams which opts out of caching. perhaps you need unstable_cache here to cache the query manuallyAnswer
MooKoreaOP
@joulev I didn't know searchParams opts out of caching, since that wasn't clear in the documentation. In any case, how does this look?
import { unstable_cache } from "next/cache";
const getCachedSymbol = unstable_cache(async (query) => {
const url = `https://financialmodelingprep.com/api/v3/search?query=${query.toUpperCase()}&limit=10&apikey=${
process.env.FINANCIAL_MODELING_PREP_KEY
}`;
return fetch(url, {
headers: {
"Content-Type": "application/json",
},
});
});
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const query = searchParams.get("query");
if (query === null) {
return new Response("Error: query not provided", { status: 400 });
}
try {
const res = await getCachedSymbol(query);
const data = await res.json();
return Response.json(
{ data },
{
status: 200,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
},
}
);
} catch (error) {
console.error(error);
}
}not sure honestly, but i have this from a different forum post which should work
async function getData(query: string) {
console.log("this is run once for each unique value of `query`");
// ...
}
export async function GET() {
const query = ...
const data = await unstable_cache(
() => getData(query),
[query]
)();
// ...
}you are using search params from request, this will make it not cache.
https://nextjs.org/docs/app/building-your-application/routing/route-handlers#opting-out-of-caching
Yes, your unstable cache should work, you can also put the res.json() stuff inside unstable cache, upto you.
Edited from #Route handler not keeping fetch cache
https://nextjs.org/docs/app/building-your-application/routing/route-handlers#opting-out-of-caching
Yes, your unstable cache should work, you can also put the res.json() stuff inside unstable cache, upto you.
Edited from #Route handler not keeping fetch cache
MooKoreaOP
thanks, I updated the code to include the keyParts array
since I hit the ratelimit on my api I can't really test if it's working until tomorrow though
since I hit the ratelimit on my api I can't really test if it's working until tomorrow though