19

I need to create the following API end point using Next.js:

/api/products/[name]?keyword=${anykeyword}.

I know I need to create it inside pages/api/products/[name] directory in index.js. But how can I access keyword.

req.query only contains name.

following is my code:

import { connectToDatabase } from "../../../../util/mongodb";
import validate from "../../../../validation/product";
//capitalize first letter only to avoid errors
import capitalize from "lodash.capitalize";

export default async function productsHandler(req, res) {
const {
  query: { name, keyword }, // here i cannot access keyword//
  method,
} = req,
Name = capitalize(name),
{ db } = await connectToDatabase(),
searchCriteria = keyword ? keyword : "price";

switch (method) {
case "GET":
  // @route GET api/products/[name]
  // @desc get products of [name] from data base
  // @access public
  {
    const products = await db
      .collection("products")
      .find({ category: Name })
      .sort({ [searchCriteria]: 1 })
      .toArray();

    if (!products.length)
      return res.status(404).json({ error: "no such category" });

    res.status(200).json(products);
  }

  break;
4

6 Answers 6

16

To get the search parameters you can simply use req.nextUrl.searchParams.get("keyword")

async function GET(req:NextRequest){
 console.log(req.nextUrl.searchParams.get("keyword"))
}
Sign up to request clarification or add additional context in comments.

Comments

15

It probably has to do with how the request is being sent to the server side from the client. You probably need to revise that. I just tried out the example using Postman, and it correctly parsed the parameters:

import { NextApiRequest, NextApiResponse } from "next";

export default async (request: NextApiRequest, response: NextApiResponse) => {
  const {
    query: { name, keyword },
    method,
  } = request;
  console.log(name, keyword, method);

  // do nothing fancy and simply return a string concatenation
  return response.status(200).json({ query: name + " " + keyword });
};

Postman:

enter image description here

1 Comment

Is it possible to default a query parameter to something?
2
import { type NextRequest } from 'next/server'
 
export function GET(request: NextRequest) {
  const searchParams = request.nextUrl.searchParams
  const query = searchParams.get('query')
  // query is "hello" for /api/search?query=hello
}

I found this link
https://nextjs.org/docs/app/building-your-application/routing/route-handlers#url-query-parameters
which can solve your problem.

Comments

1

this worked for me:

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const qs = getQSParamFromURL("qs", req.url);
  return new Response(
    JSON.stringify({
      data: {
        hello: qs,
      },
    }),
    {
      status: 200,
      headers: {
        "content-type": "application/json",
        "cache-control": "public, s-maxage=1800, stale-while-revalidate=600",
      },
    }
  );
}

export function getQSParamFromURL(
  key: string,
  url: string | undefined
): string | null {
  if (!url) return "";
  const search = new URL(url).search;
  const urlParams = new URLSearchParams(search);
  return urlParams.get(key);
}

Comments

0

Below code might help the people who started learning nextjs api calls. to get dynamic routing id.

app/api/events/[event]/route.js
export async function GET(request, { params }) {
  const slug = (await params).event //event id
}

this slug will return to get [event] value

Comments

0

TypeScript strongly typed example of getting name and keyword from this url:

/api/products/productName?keyword=anykeyword

Note that the file needs to be placed in this directory for it to work:

{ROOT}/app/api/products/[name]/route.ts

{ROOT} is the project root folder.

[name] needs to actually be called that with the brackets and everything.

// {ROOT}/app/api/products/[name]/route.ts

import { NextRequest, NextResponse } from 'next/server'
import { getApiQueryParams } from '../path/to/utils.ts'

type QueryKey = 'keyword'
type Response = { params: { name: string } }

export async function GET(request: NextRequest, response: Response) {
    const { name } = response.params
    const { keyword } = getApiQueryParams<QueryKey>(request)

    return NextResponse.json({ name, keyword })
}

These can go into a seperate file to be reusable:

// utils.ts

export function getApiQueryParams<ExpectedParamKeys extends string>(
    request: NextRequest,
): UrlParams<ExpectedParamKeys> {
    const urlParams: UrlParams<ExpectedParamKeys> = {}
    request.nextUrl.searchParams.forEach((value, key) => {
        urlParams[key as ExpectedParamKeys] = value
    })
    return urlParams
}


export type UrlParams<ExpectedKeys extends string = string> = Partial<
    Record<ExpectedKeys, string>
>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.