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; } declare global { namespace Express { interface Request { userInfo?: UserInfo | null; groupInfo?: { groupId: number; users: UserInfo[]; } | null; } } } /** * 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 userInfoRes = await getUserInfoByToken(token); req.userInfo = userInfoRes.code === 200 ? userInfoRes.data : null; next(); } catch (error: any) { res.status(401).json({ error: "User authentication failed", message: error.message, }); } }; //////// group /** * Get group users */ export const getGroupUsers = async (groupId: number, token: string): Promise => { try { const response = await axios.post( "https://egret.byteawake.com/api/group/members", {groupId}, { 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}`); } } }; /** * group information middleware */ export const groupInfoMiddleware = async ( req: Request, res: Response, next: NextFunction ): Promise => { try { const authHeader = req.headers.authorization; const token = extractTokenFromHeader(authHeader); const groupId = req.headers.groupid; if (token && groupId) { try { const usersRes = await getGroupUsers(Number(groupId), token); const users: UserInfo[] = usersRes.code === 200 ? usersRes.data : []; req.groupInfo = { groupId: Number(groupId), users, } } catch (error) { // If getting user information fails, do not block the request from continuing, but do not set userInfo console.warn("Failed to get group user information:", error); } } next(); } catch (error: any) { res.status(400).json({ error: "Get Group Users failed", message: error.message, }); } };