Next.js Discord

Discord Forum

Route handler not caching GET request

Answered
MooKorea posted this in #help-forum
Open in Discord
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 manually
View full answer

5 Replies

Answer
@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
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