How to Find API Route Handlers in 9router: Next.js App Router Navigation Guide
9router implements its REST API using Next.js 13's App Router, where every endpoint is defined by a route.js file under src/app/api/ that exports async HTTP verb handlers (GET, POST, PUT, DELETE) returning NextResponse objects.
To find API route handlers in the decolua/9router repository, you must understand how the file-system-based routing maps URL paths to specific JavaScript files. The codebase follows Next.js 13 conventions where the directory structure under src/app/api/ directly mirrors the API's URL structure. This guide provides the exact file paths, function signatures, and patterns used to locate and inspect every handler.
Map URL Paths to the File System
The first step to find API route handlers in 9router is converting the endpoint URL to a file path. Remove the /api/ prefix and append /route.js to locate the handler file.
- Collection endpoints:
/api/providersmaps tosrc/app/api/providers/route.js - Dynamic segments: URLs with parameters like
/api/providers/[id]map to folders with bracket notation:src/app/api/providers/[id]/route.js
This convention applies throughout the repository. For example, the providers collection handler resides in src/app/api/providers/route.js, while individual provider operations exist in src/app/api/providers/[id]/route.js according to the source code.
Examine Collection-Level Route Files
Collection-level endpoints handle operations on the entire resource set. In src/app/api/providers/route.js, the file exports two primary handlers.
GET handler returns all provider connections:
// src/app/api/providers/route.js
export async function GET() {
const connections = await getProviderConnections();
// …sanitise and return…
return NextResponse.json({ connections: safeConnections });
}
POST handler creates new resources by parsing the request body:
export async function POST(request) {
const body = await request.json();
const { provider, apiKey, name } = body;
// validation logic …
const newConnection = await createProviderConnection({ provider, apiKey, name, … });
// hide secrets before responding
const result = { ...newConnection };
delete result.apiKey;
return NextResponse.json(result);
}
Both handlers import database functions from @/models, delegating data operations to getProviderConnections and createProviderConnection respectively.
Locate Dynamic Route Handlers
Dynamic routes handle specific resource instances using bracketed folder names like [id]. To find API route handlers for individual resources, navigate to the dynamic segment folder.
In src/app/api/providers/[id]/route.js, handlers receive the params argument to access the URL segment:
GET for specific ID:
export async function GET(request, { params }) {
const { id } = await params;
const connection = await getProviderConnectionById(id);
// hide secrets …
return NextResponse.json({ connection: result });
}
PUT handler updates existing connections:
export async function PUT(request, { params }) {
const { id } = await params;
const body = await request.json();
// merge fields, handle proxy config, update DB
const updated = await updateProviderConnection(id, updateData);
// hide secrets before responding
return NextResponse.json({ connection: result });
}
DELETE handler removes resources:
export async function DELETE(request, { params }) {
const { id } = await params;
const deleted = await deleteProviderConnection(id);
return NextResponse.json({ message: "Connection deleted successfully" });
}
The params object destructuring pattern ({ params }) is consistent across all dynamic route handlers in the 9router codebase.
Identify Supporting Files and Imports
Most handlers delegate database work to the models layer. When examining a route file, check the top-level imports for clues about data flow:
@/modelsimports such asgetProviderConnections,createProviderConnection,updateProviderConnection, anddeleteProviderConnectionindicate the business logic resides insrc/models/- Local utilities like
normalizeProxyConfigornormalizeProxyPoolIdmay be defined within the same route file for request preprocessing - Validation constants imported from
@/shared/constants(e.g.,APIKEY_PROVIDERS,FREE_TIER_PROVIDERS) enforce business rules before database operations
Additional endpoint categories follow the same pattern:
src/app/api/models/route.jshandles model-related operationssrc/app/api/v1/route.jsproxies to versioned sub-routessrc/app/api/usage/*contains streaming, logs, and chart endpoints
Summary
To find API route handlers in 9router:
- Replace
/api/withsrc/app/api/in the URL path and append/route.js - Collection endpoints use
route.jsfiles in the resource folder (e.g.,src/app/api/providers/route.js) - Dynamic segments use bracketed folders (e.g.,
[id]) containing their ownroute.jsfiles - Handlers export async functions named after HTTP verbs (
GET,POST,PUT,DELETE) - The
requestobject provides body data viarequest.json(), whileparamsprovides dynamic URL segments - Database operations are imported from
@/models, keeping route files focused on HTTP handling
Frequently Asked Questions
How do I find the handler for a specific API endpoint like /api/providers/123?
Navigate to src/app/api/providers/[id]/route.js. The dynamic segment [id] in the folder name corresponds to the 123 in your URL. Open the file and inspect the exported GET, PUT, or DELETE functions, which receive the ID value through the params argument destructured in the function signature.
What is the difference between route.js in a folder versus a subfolder with brackets?
A route.js file directly in a resource folder (like src/app/api/providers/route.js) handles collection-level operations on the entire set of resources. A route.js inside a bracketed subfolder (like [id]/route.js) handles individual resource operations where the bracket name becomes a parameter accessible via params in the handler function.
Where does 9router store the actual database logic for API handlers?
The route handlers in src/app/api/ import database functions from src/models/ (aliased as @/models). For example, handlers in providers/route.js import getProviderConnections, createProviderConnection, and similar functions from the models layer, maintaining separation between HTTP routing and data access logic.
How do I distinguish between HTTP methods in a 9router route file?
Each HTTP verb is exported as a separate async function from route.js. The function name matches the verb in uppercase: GET for retrieving data, POST for creating resources, PUT for updates, and DELETE for removals. Each function receives the request object, and dynamic routes also receive a params object containing URL segments.
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 →