import { Request, Response, NextFunction } from "express"; import axios from "axios"; export type UserInfo = { userId: number; nickname: string; avatarUrl: string; gender: 'MALE' |'FEMALE' | 'UNKNOWN'; nimToken: string; // NetEase Cloud Communication token nimAccountId: string; // NetEase Cloud Communication account ID createdAt: string; updatedAt: string; } // Extend Express Request type to add user information declare global { namespace Express { interface Request { userInfo?: UserInfo; } } } /** * Extract Bearer token from request header */ export const extractTokenFromHeader = (authHeader: string | undefined): string | null => { if (!authHeader) { return null; } const parts = authHeader.split(" "); if (parts.length !== 2 || parts[0] !== "Bearer") { return null; } return parts[1]; }; /** * Get user information by token */ export const getUserInfoByToken = async (token: string): Promise => { try { const response = await axios.post( "https://egret.byteawake.com/api/user/info", {}, // 请求体数据,这里为空对象 { headers: { Authorization: `Bearer ${token}`, }, timeout: 10000, // 10 second timeout } ); return response.data; } catch (error: any) { if (error.response) { // API returned error response throw new Error(`Failed to get user information: ${error.response.status} ${error.response.statusText}`); } else if (error.request) { // Request was sent but no response received throw new Error("Failed to get user information: timeout or network error"); } else { // Other errors throw new Error(`Failed to get user information: ${error.message}`); } } }; /** * User information middleware * Automatically extract token from request header and get user information, store result in req.userInfo */ export const userInfoMiddleware = async ( req: Request, res: Response, next: NextFunction ): Promise => { try { const authHeader = req.headers.authorization; const token = extractTokenFromHeader(authHeader); if (!token) { res.status(401).json({ error: "No valid access token provided", message: "Missing Bearer token in Authorization header", }); return; } // Get user information const userInfo = await getUserInfoByToken(token); req.userInfo = userInfo; next(); } catch (error: any) { res.status(401).json({ error: "User authentication failed", message: error.message, }); } }; /** * Optional user information middleware * If there is a token, get user information; if there is no token, the request will not be blocked */ export const optionalUserInfoMiddleware = async ( req: Request, res: Response, next: NextFunction ): Promise => { try { const authHeader = req.headers.authorization; const token = extractTokenFromHeader(authHeader); if (token) { try { const userInfo = await getUserInfoByToken(token); req.userInfo = userInfo; } catch (error) { // If getting user information fails, do not block the request from continuing, but do not set userInfo console.warn("Failed to get user information:", error); } } next(); } catch (error) { // If the middleware itself encounters an error, do not block the request from continuing console.error("User information middleware error:", error); next(); } };