You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js Rewrites场景下服务端Axios动态请求头配置咨询

解决方案:通过Middleware传递原始请求路径,实现动态Axios请求头

核心思路

利用Next.js的Middleware捕获原始请求URL,将其存入服务端可读取的自定义请求头和客户端可读取的Cookie,然后在Axios拦截器或服务端请求逻辑中读取该值,动态设置city请求头。

步骤1:编写Middleware捕获原始路径

在项目根目录创建_middleware.js,拦截所有城市前缀的请求,保存原始路径:

import { NextResponse } from 'next/server';

export function middleware(request) {
  // 获取完整原始请求路径(包含城市前缀)
  const originalPath = request.nextUrl.pathname;
  const response = NextResponse.next();

  // 给服务端后续请求设置自定义头(仅服务端可见)
  response.headers.set('x-original-path', originalPath);
  // 给客户端设置Cookie,供客户端Axios拦截器读取
  response.cookies.set('original-path', originalPath, {
    path: '/',
    httpOnly: false, // 允许客户端读取
    sameSite: 'lax'
  });

  return response;
}

// 匹配需要处理的城市路径(根据你的需求扩展)
export const config = {
  matcher: ['/new-york/:path*', '/beijing/:path*']
};

步骤2:服务端Axios请求处理

在服务端逻辑(如getServerSideProps、API路由)中,从请求头读取原始路径,设置Axios请求头:

示例:getServerSideProps中使用

import apiQr from '../utils/apiQr';

export async function getServerSideProps(context) {
  // 从请求头获取原始路径
  const originalPath = context.req.headers['x-original-path'];
  const cityId = originalPath?.includes('/new-york') ? '2' : '1';

  // 动态设置Axios请求头
  const apiResponse = await apiQr.get('/your-api-endpoint', {
    headers: { city: cityId }
  });

  return { props: { data: apiResponse.data } };
}

示例:API路由中全局设置

// pages/api/xxx.js
import apiQr from '../../utils/apiQr';

export default async function handler(req, res) {
  const originalPath = req.headers['x-original-path'];
  const cityId = originalPath?.includes('/new-york') ? '2' : '1';

  // 给当前Axios实例全局设置city头
  apiQr.defaults.headers.common['city'] = cityId;

  const data = await apiQr.get('/external-api');
  res.status(200).json(data);
}

步骤3:客户端Axios拦截器处理

在_app.js中,从Cookie读取原始路径,设置客户端Axios请求头:

import { useEffect } from 'react';
import apiQr from '../utils/apiQr';
import Cookies from 'js-cookie'; // 需安装:npm install js-cookie

export default function MyApp({ Component, pageProps }) {
  useEffect(() => {
    // 客户端Axios请求拦截器
    const interceptor = apiQr.interceptors.request.use((config) => {
      const originalPath = Cookies.get('original-path');
      const cityId = originalPath?.includes('/new-york') ? '2' : '1';
      config.headers['city'] = cityId;
      return config;
    }, (error) => Promise.reject(error));

    // 组件卸载时移除拦截器,避免重复注册
    return () => apiQr.interceptors.request.eject(interceptor);
  }, []);

  return <Component {...pageProps} />;
}

替代方案(可选):Rewrites传递查询参数

如果允许URL携带城市参数,可以修改next.config.js的Rewrites规则,将城市信息作为查询参数传递:

async rewrites() {
  return [
    {
      source: '/new-york/:path*',
      destination: '/:path*?city=new-york',
    },
  ];
}

然后在服务端通过context.query.city、客户端通过router.query.city获取城市标识,再设置Axios头。缺点是URL会暴露查询参数,适合对URL美观要求不高的场景。


内容的提问来源于stack exchange,提问作者Danial

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 05:55:15