How to Define GET Requests in 9router API Routes
In 9router, you define GET endpoints by exporting an async function named GET from a route.js file located inside your App Router directory structure, returning a standard Web Response object.
9router (decolua/9router) is built on Next.js 13's App Router, where each API endpoint corresponds to a physical file path under src/app/api/. This file-based routing system maps HTTP methods directly to exported JavaScript functions, making it straightforward to define GET requests for fetching data, handling query parameters, and managing dynamic URL segments.
The Route File Conventions
Every API route in 9router resides in a route.js (or route.ts) file within the App Router structure. The framework automatically maps the file path to a URL endpoint and the exported function names to HTTP verbs.
Key conventions from the source code include:
- File location:
src/app/api/[endpoint]/route.js - Function naming: Export async functions matching HTTP methods (
GET,POST,OPTIONS) - Response format: Return standard Web API
Responseobjects or useResponse.json()for JSON payloads
Basic GET Handler Structure
The fundamental pattern for defining GET requests in 9router follows this signature:
export async function GET(request, { params }) {
// Handler logic here
return Response.json({ data: "your data" });
}
The function accepts two arguments:
request: The standard Web Request object containing headers, URL, and bodyparams: An object containing dynamic route parameters (for routes with[slug]segments)
According to the implementation in src/app/api/health/route.js, the simplest health check endpoint requires minimal boilerplate:
export async function GET() {
return new Response("OK", { status: 200 });
}
Handling Static Routes with Business Logic
For endpoints that fetch and transform data, the GET handler typically integrates with internal helpers and includes comprehensive error handling. The models list endpoint in src/app/api/v1/models/route.js demonstrates this pattern:
export async function GET() {
try {
const data = await buildModelsList([LLM_KIND]);
return Response.json(
{ object: "list", data },
{
headers: { "Access-Control-Allow-Origin": "*" },
}
);
} catch (error) {
console.log("Error fetching models:", error);
return Response.json(
{ error: { message: error.message, type: "server_error" } },
{ status: 500 }
);
}
}
This implementation shows the standard 9router approach: wrap business logic in a try/catch block, call helper functions like buildModelsList to gather data, and return JSON with CORS headers for cross-origin compatibility.
Dynamic URL Parameters
When defining GET requests with dynamic segments (such as /v1/models/:kind), 9router uses square bracket notation in the directory name, like [kind]/route.js. The parameter values are accessed through the second argument's params property.
In src/app/api/v1/models/[kind]/route.js, the handler extracts and validates the dynamic segment:
export async function GET(_request, { params }) {
const { kind } = await params;
const kindFilter = KIND_SLUG_MAP[kind];
if (!kindFilter) {
return Response.json(
{ error: { message: `Unknown model kind: ${kind}` } },
{ status: 404 }
);
}
const data = await buildModelsList(kindFilter);
return Response.json(
{ object: "list", data },
{ headers: { "Access-Control-Allow-Origin": "*" } }
);
}
Note that params is awaited as a Promise in the current Next.js App Router implementation, ensuring dynamic parameters are resolved before use.
Query Parameter Handling
For GET requests that filter or lookup resources via query strings (like ?id=123), parse the URL from the request object. The model info endpoint in src/app/api/v1/models/info/route.js illustrates this technique:
export async function GET(request) {
const searchParams = new URL(request.url).searchParams;
const id = searchParams.get("id");
// Lookup logic based on id
// ...
return Response.json(
{ id, /* other properties */ },
{ headers: { "Access-Control-Allow-Origin": "*" } }
);
}
This approach uses the standard Web API URL constructor to extract searchParams, making it compatible with Edge runtime environments.
CORS and Preflight Configuration
Production 9router deployments typically export an OPTIONS handler alongside GET functions to handle CORS preflight requests. While not strictly part of the GET definition, this pattern appears consistently across route files to ensure the Access-Control-Allow-Origin header is properly set for all methods.
Summary
- File-based routing: Create
route.jsfiles undersrc/app/api/where the directory structure defines the URL path. - Named exports: Export an async function literally named
GETto handle GET requests in 9router. - Signature: Accept
(request, { params })whereparamscontains dynamic route segments. - Response handling: Return
Response.json()ornew Response(), always including appropriate CORS headers for API compatibility. - Error boundaries: Wrap data fetching logic in
try/catchblocks to return structured 500 error responses rather than unhandled exceptions. - Query access: Use
new URL(request.url).searchParamsto extract filter parameters from the request URL.
Frequently Asked Questions
Can I export multiple HTTP methods from the same route file?
Yes. A single route.js file can export multiple handler functions such as GET, POST, and OPTIONS. 9router automatically routes incoming requests to the function matching the HTTP method, allowing you to consolidate related endpoint logic in one location.
How do I access headers in a GET handler?
Access headers through the request object's headers property, which returns a Headers instance. For example: request.headers.get('authorization'). This standard Web API approach works consistently across all 9router GET implementations.
What happens if I don't export a GET function for a route?
If the client sends a GET request to a route that exists but lacks a GET export, Next.js returns a 405 Method Not Allowed response. This behavior ensures that only explicitly defined HTTP methods are exposed on your API endpoints, preventing accidental data leakage from undefined routes.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →