Next.js中间件如何获取不含端口号的正确pathname值?
解决Next.js与Express配合时重定向带端口号的问题
问题原因
当Express与Next.js配合部署时,Next.js可能从请求头或内部解析逻辑中拿到带端口的主机名(比如默认开发端口3000),导致重定向时错误地将端口号附加到目标URL中。
解决方案
1. 在Next.js中间件中手动剥离端口并构造正确URL
直接在中间件里使用URL对象解析请求地址,提取不带端口的主机名和小写路径,构造正确的重定向URL:
import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' export function middleware(request: NextRequest) { const requestUrl = new URL(request.url) const lowerPath = requestUrl.pathname.toLowerCase() if (requestUrl.pathname !== lowerPath) { // 用原协议+不带端口的主机名+小写路径构造新URL const redirectUrl = new URL(lowerPath, `${requestUrl.protocol}//${requestUrl.hostname}`) // 保留原查询参数 redirectUrl.search = requestUrl.search return NextResponse.redirect(redirectUrl, { status: 301 }) } return NextResponse.next() }
2. 配置Express信任代理并传递正确Host头
如果是生产环境通过反向代理(如Nginx)部署,需要让Express信任代理,确保Next.js能获取到客户端真实的Host头(不带端口):
在Express服务代码中添加:
const express = require('express') const next = require('next') const app = express() // 信任所有代理,让Express能拿到真实的客户端请求头 app.set('trust proxy', true) const nextApp = next({ dev: process.env.NODE_ENV !== 'production' }) const handle = nextApp.getRequestHandler() nextApp.prepare().then(() => { app.all('*', (req, res) => handle(req, res)) app.listen(3000, () => console.log('Server running on port 3000')) })
如果使用Nginx反向代理,需配置传递正确的Host头:
location / { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }
关键说明
requestUrl.hostname会自动剥离端口号,只保留域名部分,用它来构造重定向URL就能避免端口号出现。- 生产环境务必配置反向代理传递正确的Host头,同时Express开启
trust proxy,这样Next.js能始终拿到客户端请求的真实域名(不带端口)。
内容的提问来源于stack exchange,提问作者Darshan Sachaniya
相关产品推荐
相关产品推荐

