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

NextJS14 Middleware调用serverless-mysql时出现undefined错误

问题分析与解决方案

错误根源

报错TypeError: Cannot read properties of undefined (reading 'slice')出现在serverless-mysql的connect方法中,核心原因有三点:

  1. serverless-mysql不兼容Edge Runtime
    Next.js Middleware默认运行在Edge Runtime环境,而serverless-mysql依赖Node.js专属API(如net、tls模块),这些在Edge环境中不可用,导致初始化连接时内部变量未定义,触发slice调用错误。

  2. Cookie获取方式错误
    在Middleware中,不能直接调用全局cookies()函数,必须从传入的NextRequest对象中获取Cookie,否则会导致Cookie读取失败,后续数据库查询的sessionId异常,间接引发连接逻辑错误。

  3. MySQL实例初始化缺失
    代码中直接使用mysql.connect(),但未展示mysql实例的初始化代码。若未正确配置数据库连接参数(如host、user、password等),serverless-mysql内部状态未正确初始化,也会触发此类错误。


修复步骤

1. 替换为Edge兼容的数据库客户端

由于serverless-mysql不支持Edge Runtime,建议改用兼容Edge的MySQL客户端,比如@planetscale/database(支持Edge环境):

// src/lib/db.ts
import { connect } from '@planetscale/database'

const config = {
  host: process.env.DATABASE_HOST,
  username: process.env.DATABASE_USERNAME,
  password: process.env.DATABASE_PASSWORD,
}

const conn = connect(config)

export async function isSessionValid(sessionId: string) {
  const results = await conn.execute('SELECT * FROM sessions WHERE id = ?', [sessionId])
  return results.rows.length > 0
}

export async function getUserBySessionId(sessionId: string) {
  const results = await conn.execute(`
    SELECT users.*
    FROM users 
    JOIN sessions ON users.id = sessions.user_id 
    WHERE sessions.id = ?
  `, [sessionId])
  
  if (results.rows.length === 0) {
    return null
  }
  return new User(results.rows[0].name, results.rows[0].role)
}

2. 修正Middleware中Cookie的获取逻辑

必须通过NextRequest对象传递并获取Cookie,同时确保Middleware为异步函数:

修改middleware.ts:

import { NextRequest, NextResponse } from "next/server";
import { isAuthenticated } from "@/lib/auth";

export async function middleware(request: NextRequest) {
  const authenticated = await isAuthenticated(request);
  if (!authenticated) {
    return NextResponse.redirect(new URL("/login", request.url));
  }
  return NextResponse.next();
}

修改auth.ts:

import { NextRequest } from "next/server";
import { isSessionValid, getUserBySessionId } from "@/lib/db";

export async function isAuthenticated(request: NextRequest) {
  const sessionId = request.cookies.get("sessionId")?.value;
  if (!sessionId) {
    return false;
  }
  if (!await isSessionValid(sessionId)) {
    return false;
  }
  return await getUserBySessionId(sessionId) !== null;
}

3. 若坚持使用serverless-mysql,强制使用Node.js Runtime

如果必须保留serverless-mysql,需让Middleware运行在Node.js环境,并正确初始化实例:

步骤1:配置Middleware使用Node.js Runtime

// middleware.ts
export const config = {
  runtime: 'nodejs', // 强制切换到Node.js Runtime
};

import { NextRequest, NextResponse } from "next/server";
import { isAuthenticated } from "@/lib/auth";

export async function middleware(request: NextRequest) {
  const authenticated = await isAuthenticated(request);
  if (!authenticated) {
    return NextResponse.redirect(new URL("/login", request.url));
  }
  return NextResponse.next();
}

步骤2:正确初始化serverless-mysql实例

// src/lib/db.ts
import mysql from 'serverless-mysql'

const db = mysql({
  config: {
    host: process.env.MYSQL_HOST,
    database: process.env.MYSQL_DATABASE,
    user: process.env.MYSQL_USER,
    password: process.env.MYSQL_PASSWORD,
  },
})

export async function isSessionValid(sessionId: string) {
  await db.connect();
  let results;
  try {
    results = await db.query(`SELECT * FROM sessions WHERE id = ?`, [sessionId]);
  } catch (e: any) {
    throw new Error("Error executing query: " + e.message);
  } finally {
    await db.end();
  }
  return results && results.length > 0;
}

// getUserBySessionId函数同理,使用db实例而非全局mysql

关键注意事项

  • Edge Runtime下避免使用依赖Node.js核心API的库,优先选择Edge兼容的工具。
  • Middleware中必须通过NextRequest对象获取请求相关数据,禁止使用全局函数。
  • 异步逻辑必须正确使用await,原代码中未等待isAuthenticated()会导致逻辑失效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 16:43:28