Next.js第十章(Proxy)

Proxy代理

从 Next.js 16 开始,中间件Middleware更名为代理(Proxy),以更好地体现其用途。其功能保持不变

如果你想升级为16.x版本,Next.js提供了命令行工具来帮助你升级,只需要执行以下命令即可:

bash 复制代码
npx @next/codemod@canary middleware-to-proxy .

代码转换会将文件和函数名从middleware重命名为proxy。

ts 复制代码
// middleware.ts -> proxy.ts
 
- export function middleware() {
+ export function proxy() {

基本使用

应用场景:

  • 处理跨域请求
  • 接口转发例如/api/user -> (可能是其他服务器java/go/python等) -> /api/user
  • 限流例如配合第三方服务做限流
  • 鉴权/判断是否登录

Prxoy代理其实跟拦截器类似,它可以在请求完成之前进行拦截,然后进行一些处理,例如:修改请求头、修改请求体、修改响应体等。

src/proxy.ts

定义proxy函数导出即可,Next.js会自动调用这个函数。

ts 复制代码
import { NextRequest, NextResponse } from "next/server";
export async function proxy(request: NextRequest) {
    console.log(request.url,'url');
}

但是你会发现,他会拦截项目中所有的请求,包括静态资源、API请求、页面请求等。

txt 复制代码
http://localhost:3000/.well-known/appspecific/com.chrome.devtools.json url
http://localhost:3000/_next/static/chunks/src_app_globals_91e4631d.css url
http://localhost:3000/_next/static/chunks/%5Bturbopack%5D_browser_dev_hmr-client_hmr-client_ts_cedd0592._.js url
http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1e674e59._.js url
http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-server-dom-turbopack_9212ccad._.js url
http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_next-devtools_index_1dd7fb59.js url
http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_a0e4c7b4._.js url
http://localhost:3000/_next/static/chunks/node_modules_next_dist_client_a38d7d69._.js url
http://localhost:3000/_next/static/chunks/node_modules_next_dist_4b2403f5._.js url
http://localhost:3000/_next/static/chunks/src_app_globals_91e4631d.css.map url
http://localhost:3000/_next/static/chunks/node_modules_%40swc_helpers_cjs_d80fb378._.js url
http://localhost:3000/_next/static/chunks/_a0ff3932._.js url
http://localhost:3000/api/login url

配置(config)

例如我们只想匹配'/api'下面的路径去做一些事情,我们可以使用config配置来实现。

ts 复制代码
import { NextRequest, NextResponse } from "next/server";
export async function proxy(request: NextRequest) {
    console.log(request.url,'url');
}
//配置匹配路径
export const config = {
    matcher: '/api/:path*',
    //matcher: ['/api/:path*','/api/user/:path*'], 支持单个以及多个路径匹配
    //matcher: ['/((?!api|_next/static|_next/image|.*\\.png$).*)'], 同样支持正则表达式匹配
}

结合之前的案例,在cookie那一集,我们还需要单独定义check接口检查cookie,现在我们可以直接在proxy中实现。

ts 复制代码
import { NextRequest, NextResponse } from "next/server";
export async function proxy(request: NextRequest) {
    const cookie = request.cookies.get('token');
    if (request.nextUrl.pathname.startsWith('/home') && !cookie) {
        console.log('redirect to login');
        return NextResponse.redirect(new URL('/', request.url));
    }
    if (cookie && cookie.value) {
        return NextResponse.next();
    }
    return NextResponse.redirect(new URL('/', request.url));
}

export const config = {
    matcher: ['/api/:path*', '/home/:path*'],
}

复杂匹配

  • source: 表示匹配路径
  • has: 表示匹配路径中必须(包含)某些条件
  • missing: 表示匹配路径中(必须不包含)某些条件

type 只能匹配: header, query, cookie

ts 复制代码
import { NextRequest, NextResponse } from "next/server";
import { ProxyConfig } from "next/server";
export async function proxy(request: NextRequest) {
   console.log('start proxy')
   return NextResponse.next();
}

export const config: ProxyConfig = {
    matcher: [
        {
            source: '/home/:path*',
            //表示匹配路径中必须(包含)Authorization头和userId查询参数
            has: [
                { type: 'header', key: 'Authorization', value: 'Bearer 123456' },
                { type: 'query', key: 'userId', value: '123' }
            ],
            //表示匹配路径中(必须不包含)cookie和userId查询参数
            missing: [
                { type: 'cookie', key: 'token', value: '123456' },
                { type: 'query', key: 'userId', value: '456' },
            ]
        },
    ]
}

访问url为:http://localhost:3000/home?userId=123

案例实战(处理跨域)

只要是/api下面的接口都可以被任意访问

ts 复制代码
import { NextRequest, NextResponse } from "next/server";
import { ProxyConfig } from "next/server";
export async function proxy(request: NextRequest) {
    const response = NextResponse.next();
    Object.entries(corsHeaders).forEach(([key, value]) => {
        response.headers.set(key, value);
    })
    return response;
}

const corsHeaders = {
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
    'Access-Control-Allow-Headers': 'Content-Type, Authorization',
}

export const config: ProxyConfig = {
   matcher:'/api/:path*',
}
相关推荐
_杨瀚博1 分钟前
微信支付集成_JSAPI
前端
polaris_tl1 分钟前
react beginwork
前端
亮子AI12 分钟前
【css】列表的标号怎么实现居中对齐?
前端·css
梦想的旅途236 分钟前
媒体文件(图片/文件)的上传与管理:获取 Media ID 的技术细节
前端·http·servlet
一水鉴天1 小时前
整体设计 定稿 之22 dashboard.html 增加三层次动态记录体系仪表盘 之1
前端·html
张拭心1 小时前
程序员越想创业,越不要急着动手
前端·人工智能
舒一笑1 小时前
在低配云服务器上实现自动化部署:Drone CI + Gitee Webhook 的轻量级实践
前端·后端·程序员
龙国浪子1 小时前
从零到一:打造专业级小说地图设计工具的技术实践
前端·electron
一水鉴天2 小时前
整体设计 定稿 之24+ dashboard.html 增加三层次动态记录体系仪表盘 之2 程序 (Q208 之2)
开发语言·前端·javascript
IT_陈寒2 小时前
Java 21新特性实战:这5个改进让我的代码效率提升40%
前端·人工智能·后端