Next.js 13 App Router集成Socket.io遇404错误求助
Next.js 13 App Router 中 Socket.io 404 错误解决方法
问题重现
基于Pages Router的Socket.io示例,在Next.js 13 App Router的api/socket/route.ts中实现时,出现以下404错误:
polling.js:298 GET http://localhost:3000/socket.io?EIO=4&transport=polling&t=OkUN45A 404 (Not Found)
错误原因
App Router与Pages Router的API路由机制存在差异,用户代码存在以下问题:
- 参数错误:App Router的GET函数参数为
request和context,而非Pages Router的req/res,无法直接通过res.socket获取服务器实例。 - 返回值错误:直接返回
NextResponse类而非实例,未正确结束请求。 - 路径不匹配:Socket.io客户端默认请求
/socket.io,但服务器配置的路径为/api/socket,且未在客户端指定对应路径。
修复步骤及完整代码
1. 类型定义(可选)
在app/types/next.ts中添加类型声明,方便类型提示:
import { Server as NetServer } from "http"; import { Server as ServerIO } from "socket.io"; export type ExtendedServer = NetServer & { io?: ServerIO; };
2. 修复后的app/api/socket/route.ts
import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; import { Server as ServerIO } from "socket.io"; import type { ExtendedServer } from "@/app/types/next"; export const config = { api: { bodyParser: false, // 必须关闭,避免Socket.io请求被错误解析 }, }; export async function GET(request: NextRequest) { const server = request.socket.server as ExtendedServer; // 仅初始化一次Socket.io服务器 if (!server.io) { console.log("初始化新Socket.io服务器"); const io = new ServerIO(server, { path: "/api/socket", // 自定义Socket.io路径 addTrailingSlash: false, }); // 添加Socket.io事件监听示例 io.on("connection", (socket) => { console.log(`客户端连接:${socket.id}`); socket.on("message", (data) => { io.emit("message", data); // 广播消息给所有客户端 }); socket.on("disconnect", () => { console.log(`客户端断开:${socket.id}`); }); }); server.io = io; } return NextResponse.json({}, { status: 200 }); // 返回空响应结束请求 }
3. 客户端连接代码(客户端组件)
必须在客户端组件中使用Socket.io,确保路径与服务器配置一致:
"use client"; import { useEffect, useState } from "react"; import { io, Socket } from "socket.io-client"; export default function ChatComponent() { const [socket, setSocket] = useState<Socket | null>(null); const [inputMsg, setInputMsg] = useState(""); const [messageList, setMessageList] = useState<string[]>([]); useEffect(() => { // 连接时指定服务器配置的路径 const newSocket = io(window.location.origin, { path: "/api/socket", }); newSocket.on("message", (msg) => { setMessageList(prev => [...prev, msg]); }); setSocket(newSocket); return () => newSocket.close(); }, []); const sendMessage = () => { if (socket && inputMsg.trim()) { socket.emit("message", inputMsg); setInputMsg(""); } }; return ( <div className="chat-container"> <div className="messages"> {messageList.map((msg, idx) => ( <div key={idx} className="message">{msg}</div> ))} </div> <div className="input-area"> <input type="text" value={inputMsg} onChange={(e) => setInputMsg(e.target.value)} placeholder="输入消息..." /> <button onClick={sendMessage}>发送</button> </div> </div> ); }
关键注意事项
- 必须关闭
bodyParser:Socket.io使用自定义的请求格式,开启bodyParser会导致请求解析失败。 - 路径一致性:服务器配置的
path必须和客户端连接时指定的path完全一致,否则会触发404。 - 服务器单例:确保Socket.io服务器只初始化一次,避免重复创建实例。
内容的提问来源于stack exchange,提问作者thejon
相关产品推荐
相关产品推荐

