(edited)
I have a Next.js app deployed on Vercel and a WordPress blog running on an external server (nginx/Apache). I want every request to /blog/* on my Next.js site to be proxied to the external blog, but Vercel automatically strips trailing slashes while WordPress enforces them. This results in an infinite redirect loop:
Vercel strips the slash:
GET /blog/my-post/ ← HTTP/2 308 ← location: /blog/my-postWordPress redirects to add the slash:
GET /blog/my-post ← HTTP/2 301 ← location: https://example.com/blog/my-post/Back to step 1… ad infinitum.
What I’ve Tried
- vercel.json rewrite/redirect rules
- next.config.js with trailingSlash: true / false
- middleware.ts (Next.js Edge Middleware) to normalize slashes and proxy headers
None of these approaches have broken the slash‑removal ↔ slash‑addition ping‑pong.
configuration snippets I have tried: vercel.json
{ "redirects": [ { "source": "/blog/", "destination": "https://my-wp-blog.com/blog/", "permanent": true } ]}next.config.js
module.exports = { trailingSlash: true,}middleware.ts
import { NextResponse } from 'next/server'import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) { const url = request.nextUrl.clone()
// 1. Force trailing slash on all /blog paths if (url.pathname.startsWith('/blog') && !url.pathname.endsWith('/')) { url.pathname += '/' return NextResponse.redirect(url, 308) }
// 2. Proxy to external WordPress server const headers = new Headers(request.headers) headers.set('host', 'my-wp-blog.com')
const clientIP = request.ip || request.headers.get('x-forwarded-for') || '' headers.set('x-real-ip', clientIP) headers.set('x-forwarded-for', clientIP) headers.set('x-forwarded-proto', request.nextUrl.protocol.replace(':', '')) headers.set('x-forwarded-host', 'my-wp-blog.com')
const proxyUrl = new URL(request.url) proxyUrl.protocol = 'https:' proxyUrl.hostname = 'my-blog-server-ip' if (!proxyUrl.pathname.endsWith('/')) { proxyUrl.pathname += '/' }
return NextResponse.rewrite(proxyUrl, { request: { headers } })}
export const config = { matcher: '/blog/:path*',}None of these proposed solutions worked! Any help, would be appreciated.