How to Access Request Parameters in 9router API Handlers

In 9router, API handlers receive a NextRequest object from which you can extract path parameters via the params argument, query strings via request.nextUrl.searchParams, and JSON bodies via await request.json().

9router implements its API layer using Next.js App Router conventions, with endpoint handlers located in src/app/api/.../route.js files. To access request parameters in 9router API handlers, you work with the standard NextRequest object (typically named request) passed to every route function, alongside an optional context object containing dynamic path segments.

Accessing Path Parameters

Dynamic route segments in 9router follow the Next.js App Router file convention. When you create a route file with bracket notation—such as src/app/api/providers/[id]/route.js—the handler receives a params object as its second argument containing the parsed URL values.

As implemented in src/app/api/providers/[id]/route.js:

export async function GET(request, { params }) {
  const providerId = params.id;  // Extracts the [id] segment from the URL
  // Use providerId to fetch the specific provider record
}

Reading Query String Parameters

Query parameters are accessible through the nextUrl property of the request object. The searchParams interface provides standard Web API methods like get() and getAll().

From src/app/api/models/route.js, the codebase filters results using query strings:

export async function GET(request) {
  const searchTerm = request.nextUrl.searchParams.get('search');
  const limit = request.nextUrl.searchParams.get('limit');
  // Filter and paginate results based on these values
}

For boolean flags, compare the string value directly:

const includeSecrets = request.nextUrl.searchParams.get('secrets') === 'true';

Parsing JSON Request Bodies

For POST, PUT, and PATCH endpoints, 9router handlers read the request body using the asynchronous json() method. This returns a Promise that resolves to the parsed JavaScript object.

From src/app/api/translator/translate/route.js:

export async function POST(request) {
  const { text, targetLang } = await request.json();
  // Process the translation request using the extracted body properties
}

For raw text payloads or other formats, use await request.text() instead.

Working with Headers and Cookies

HTTP headers are available via the headers property, which returns a Web Headers object. Access specific values using the get() method:

export async function GET(request) {
  const authToken = request.headers.get('Authorization');
  const apiKey = request.headers.get('x-api-key');
}

Cookies follow a similar pattern through request.cookies.get():

const session = request.cookies.get('session');

The src/app/api/auth/logout/route.js file demonstrates reading session cookies to clear authentication state.

Complete Handler Example

A production handler in 9router often combines multiple parameter sources. The implementation in src/app/api/v1/chat/completions/route.js demonstrates gathering data from various request parts:

export async function POST(request) {
  // Extract JSON body
  const { messages, model } = await request.json();
  
  // Read query parameters
  const shouldStream = request.nextUrl.searchParams.get('stream') === 'true';
  
  // Verify authentication header
  const bearerToken = request.headers.get('Authorization');
  
  // Process the chat completion request...
}

Summary

  • Path parameters are accessed via the destructured params object in the second handler argument.
  • Query strings are available on request.nextUrl.searchParams using .get('key') for single values or .getAll('key') for arrays.
  • Request bodies require await request.json() for JSON payloads, returning the parsed object ready for use.
  • Headers use request.headers.get('header-name') and cookies use request.cookies.get('name').
  • All patterns follow Next.js App Router conventions as implemented in the decolua/9router repository.

Frequently Asked Questions

How do I access dynamic URL segments in a 9router handler?

Destruct the params object from the second argument of your handler function. For a route file located at src/app/api/providers/[id]/route.js, accessing params.id returns the value from that position in the URL path, as shown in the provider lookup implementation.

What is the correct way to read JSON POST data in 9router?

Use await request.json() inside your POST handler. This asynchronous method parses the incoming request body and returns a JavaScript object, consistent with the pattern used in src/app/api/translator/translate/route.js for processing translation payloads.

Can I access query parameters in POST requests?

Yes. Regardless of the HTTP method, query parameters remain available via request.nextUrl.searchParams. In src/app/api/v1/chat/completions/route.js, the stream query parameter is read from POST requests to determine the response format.

How do I check for API keys or authentication tokens?

Read the Authorization header or custom headers like x-api-key using request.headers.get('header-name'). The src/app/api/auth/login/route.js file demonstrates this pattern for validating authentication credentials before processing login requests.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →