Route Handlers and Proxy
APIs with route.ts, the standard Request/Response and proxy.ts.
Updated
What a Route Handler is
A Route Handler is an HTTP endpoint written in app/: a route.ts file that exports functions named after HTTP methods. It receives a standard Request and returns a standard Response — exactly the Web APIs from the fetch lesson.
// app/api/posts/route.ts → /api/posts
export async function GET(request: Request) {
const q = new URL(request.url).searchParams.get('q') ?? ''
return Response.json(await searchPosts(q))
}
export async function POST(request: Request) {
const body = await request.json()
return Response.json(await createPost(body), { status: 201 })
}- Supported methods:
GET,POST,PUT,PATCH,DELETE,HEAD,OPTIONS. - A
route.tsand apage.tsxcan't live in the same folder. - Dynamic segments work the same:
app/api/posts/[id]/route.ts.
When to use Route Handlers
| Situation | Route Handler? |
|---|---|
| a webhook from Stripe, a CMS, GitHub | yes |
| an API consumed by a mobile app / by partners | yes |
| RSS, a custom sitemap, generated files, images | yes |
| a proxy to an external API (hiding the key, avoiding CORS) | yes |
| a form in your app | no → a Server Action |
| a page's data | no → a Server Component |
What Proxy is
Proxy (proxy.ts at the project root — formerly middleware) is code that runs before every matching request, before it reaches the page. It can redirect, rewrite the URL, change headers and cookies, or respond directly.
// proxy.ts
import { NextResponse, type NextRequest } from 'next/server'
export function proxy(request: NextRequest) {
if (!request.cookies.has('session') && request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL(`/login?next=${request.nextUrl.pathname}`, request.url))
}
}
export const config = { matcher: ['/dashboard/:path*'] }This app uses proxy.ts to give you the anonymous vid cookie and to send you to the right language.
What goes in the proxy — and what doesn't
| Yes | No |
|---|---|
| redirects based on the URL / cookies | slow DB queries |
| optimistic auth checks ("is there a session cookie?") | full authorization — redo it in the page / action |
| security headers, A/B testing, i18n | business logic |
| setting cookies | cached fetches |
Summary
- A Route Handler =
route.tswithGET/POSTfunctions,Request→Response. - For webhooks and external APIs; your own forms go through Server Actions.
- Proxy runs before the request: redirects, headers, cookies — fast and simple.