Claude-skill-registry-data migrating-middleware-to-proxy
Teach middleware.ts to proxy.ts migration in Next.js 16. Use when migrating middleware, encountering middleware errors, or implementing request proxying.
git clone https://github.com/majiayu000/claude-skill-registry-data
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry-data "$T" && mkdir -p ~/.claude/skills && cp -r "$T/data/migrating-middleware-to-proxy" ~/.claude/skills/majiayu000-claude-skill-registry-data-migrating-middleware-to-proxy && rm -rf "$T"
data/migrating-middleware-to-proxy/SKILL.mdMIGRATION: middleware.ts to proxy.ts
Overview
Next.js 16 renames
middleware.ts to proxy.ts and the middleware export to proxy. This is a breaking change with security implications (CVE-2025-29927).
Why This Change Matters
CVE-2025-29927: Middleware-based authentication is fundamentally broken in Next.js. Middleware cannot reliably protect routes because:
- Middleware runs at the edge, but authentication state lives in databases/sessions
- Race conditions between middleware checks and route handlers
- Middleware can be bypassed through direct route access
- Edge runtime limitations prevent proper session verification
The rename to "proxy" clarifies that this API is for request/response manipulation, not security.
Migration Steps
1. Rename the File
# Old location src/middleware.ts # New location src/proxy.ts
2. Rename the Export
Before (Next.js 15):
export function middleware(request: NextRequest) { return NextResponse.next(); } export const config = { matcher: ['/api/:path*', '/dashboard/:path*'], };
After (Next.js 16):
export function proxy(request: NextRequest) { return NextResponse.next(); } export const config = { matcher: ['/api/:path*', '/dashboard/:path*'], };
3. Update Configuration
If using
next.config.js or next.config.ts:
const nextConfig = { experimental: { }, };
No configuration changes needed for proxy. The framework detects
proxy.ts automatically.
Security Migration
If you were using middleware for authentication, you must migrate to route-level protection.
Before (Insecure)
export function middleware(request: NextRequest) { const token = request.cookies.get('auth-token'); if (!token) { return NextResponse.redirect(new URL('/login', request.url)); } return NextResponse.next(); } export const config = { matcher: ['/dashboard/:path*'], };
After (Secure)
proxy.ts:
export function proxy(request: NextRequest) { const response = NextResponse.next(); response.headers.set('x-custom-header', 'value'); return response; }
app/dashboard/layout.tsx:
import { redirect } from 'next/navigation'; import { verifySession } from '@/lib/auth'; export default async function DashboardLayout({ children, }: { children: React.ReactNode; }) { const session = await verifySession(); if (!session) { redirect('/login'); } return <>{children}</>; }
Key differences:
- Authentication logic moves to Server Components
- Session verification happens in the same runtime as data access
- No race conditions between auth check and data fetch
- Can access database/session store reliably
Valid Use Cases for proxy.ts
Use
proxy.ts for:
-
Request/response header manipulation
export function proxy(request: NextRequest) { const response = NextResponse.next(); response.headers.set('x-frame-options', 'DENY'); return response; } -
Request logging/monitoring
export function proxy(request: NextRequest) { console.log(`${request.method} ${request.url}`); return NextResponse.next(); } -
URL rewriting
export function proxy(request: NextRequest) { if (request.nextUrl.pathname === '/old-path') { return NextResponse.rewrite(new URL('/new-path', request.url)); } return NextResponse.next(); } -
Geolocation routing
export function proxy(request: NextRequest) { const country = request.geo?.country; if (country === 'US') { return NextResponse.rewrite(new URL('/us', request.url)); } return NextResponse.next(); }
Do NOT Use proxy.ts For
- Authentication/authorization checks
- Session validation
- Database queries
- Complex business logic
- Rate limiting (use route handlers instead)
Migration Checklist
- Rename
tomiddleware.tsproxy.ts - Rename
export tomiddlewareproxy - Remove authentication logic from proxy
- Move authentication to Server Components/Route Handlers
- Test that routes are properly protected
- Verify edge cases (direct route access, API routes, etc.)
- Update tests that reference middleware
Common Errors
Error: "middleware is not exported"
You forgot to rename the export from
middleware to proxy.
Error: "proxy is not a function"
Ensure you're exporting a function named
proxy, not a default export.
Error: "Cannot access database in proxy"
Proxy runs at the edge runtime. Move database access to route handlers or Server Components.
Additional Resources
- CVE-2025-29927: Next.js Middleware Authentication Vulnerability
- Next.js 16 Migration Guide: Proxy API
- Next.js Security Best Practices: Route-Level Protection