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

NextJS+Bun环境中间件导出TextDecoderStream空值错误及IP白名单求助

解决Bun+NextJS 13.5.4中Middleware的TextDecoderStream错误并实现IP白名单

一、修复Middleware的TextDecoderStream错误

该错误由Bun 1.0.4与NextJS 13.5.4的Edge Runtime兼容性冲突导致,可尝试以下修复方案:

1. 升级NextJS版本

升级到NextJS 13.5.6及以上稳定版(或直接升级至14.x),官方已修复部分Edge Runtime与Bun的兼容问题:

bun add next@latest

2. 调整Middleware文件位置

将middleware.ts从/src目录移至项目根目录(与src文件夹同级),同时确保tsconfig.json的include配置包含根目录文件:

{
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "middleware.ts"]
}

3. 临时切换到Node.js Runtime(实验性)

在next.config.js中配置强制使用Node.js Runtime,绕过Edge环境的兼容性问题:

module.exports = {
  experimental: {
    edgeRuntime: 'nodejs',
  },
}

注意:该配置为实验性功能,可能影响部分Edge专属特性的使用。


二、IP白名单实现方案

方案1:修复后用Middleware实现

当Middleware恢复正常后,编写IP校验逻辑:

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

// 白名单IP列表
const ALLOWED_IPS = ['192.168.1.1', '127.0.0.1']

export function middleware(request: NextRequest) {
  // 获取客户端IP(部署到云平台时优先取代理头)
  const clientIp = request.ip || request.headers.get('x-forwarded-for')?.split(',')[0]?.trim()

  if (!clientIp || !ALLOWED_IPS.includes(clientIp)) {
    return new NextResponse('Access Denied', { status: 403 })
  }

  return NextResponse.next()
}

// 指定需要拦截的路由(匹配所有路由)
export const config = {
  matcher: '/:path*',
}

方案2:用根Layout组件替代(无需Middleware)

如果Middleware问题暂时无法解决,可在App Router的根Layout中添加IP校验:

// src/app/layout.tsx
import { headers } from 'next/headers'
import { redirect } from 'next/navigation'

const ALLOWED_IPS = ['192.168.1.1', '127.0.0.1']

export default function RootLayout({ children }: { children: React.ReactNode }) {
  const headerList = headers()
  // 获取客户端IP
  const clientIp = headerList.get('x-forwarded-for')?.split(',')[0]?.trim() 
    || headerList.get('x-real-ip') 
    || 'unknown'

  if (!ALLOWED_IPS.includes(clientIp)) {
    redirect('/access-denied')
  }

  return (
    <html lang="zh-CN">
      <body>{children}</body>
    </html>
  )
}

创建src/app/access-denied/page.tsx返回403页面:

export default function AccessDenied() {
  return <h1>403 访问被拒绝</h1>
}

注意:该方式仅拦截页面路由,API路由需单独添加校验逻辑。

方案3:自定义Bun服务器实现

如果使用Bun自定义服务器启动NextJS,可在服务器层直接做IP校验:

// server.ts
import { createServer } from 'bun'
import next from 'next'

const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

const ALLOWED_IPS = ['192.168.1.1', '127.0.0.1']

app.prepare().then(() => {
  createServer({
    async fetch(req) {
      const clientIp = req.headers.get('x-forwarded-for')?.split(',')[0]?.trim() || req.ip || 'unknown'
      
      if (!ALLOWED_IPS.includes(clientIp)) {
        return new Response('Access Denied', { status: 403 })
      }

      return handle(req)
    },
  }).listen({ port: 3000 }, () => {
    console.log('服务器运行在 http://localhost:3000')
  })
})

修改package.json的启动脚本:

{
  "scripts": {
    "dev": "bun run server.ts"
  }
}

内容的提问来源于stack exchange,提问作者Forgotten-Storm

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 07:57:56