const express = require('express'); const axios = require('axios'); const router = express.Router(); const HF_API_BASE = 'https://huggingface.co/api'; /** * 验证 Authorization 请求头中的 Bearer Token * 支持两种方式传递 token(兼容创空间 Header 限制): * 1. Authorization: Bearer * 2. Query: ?access_token= */ const validateAuthHeader = (req, res, next) => { const authHeader = req.headers.authorization; let token = ''; if (authHeader && authHeader.startsWith('Bearer ')) { token = authHeader.substring(7); } else if (req.query.access_token) { token = req.query.access_token; } if (!token) { return res.status(401).json({ error: '缺少 access_token,可通过 Authorization 头或 ?access_token= 参数传递' }); } req.accessToken = token; next(); }; // 1. 获取当前登录用户信息 router.get('/whoami', validateAuthHeader, async (req, res) => { try { const response = await axios.get(`${HF_API_BASE}/whoami-v2`, { headers: { 'Authorization': `Bearer ${req.accessToken}`, 'Content-Type': 'application/json' } }); res.json({ status: response.status, data: response.data }); } catch (error) { console.error('Error fetching whoami:', error.response?.data || error.message); res.status(error.response?.status || 500).json({ error: 'Failed to fetch user info', details: error.response?.data || error.message }); } }); // 2. 获取指定用户的模型列表 router.get('/models/:owner', validateAuthHeader, async (req, res) => { try { const { owner } = req.params; const pageSize = req.query.page_size || 50; const response = await axios.get(`${HF_API_BASE}/models?author=${owner}&limit=${pageSize}`, { headers: { 'Authorization': `Bearer ${req.accessToken}`, 'Content-Type': 'application/json' } }); const models = Array.isArray(response.data) ? response.data : []; const processedModels = models.map(model => ({ id: model.id, name: model.id, private: model.private || false, gated: model.gated || false, ...model })); res.json({ total: processedModels.length, page_size: pageSize, data: processedModels }); } catch (error) { console.error('Error fetching models:', error.response?.data || error.message); res.status(error.response?.status || 500).json({ error: 'Failed to fetch models', details: error.response?.data || error.message }); } }); // 3. 获取指定用户的数据集列表 router.get('/datasets/:owner', validateAuthHeader, async (req, res) => { try { const { owner } = req.params; const pageSize = req.query.page_size || 50; const response = await axios.get(`${HF_API_BASE}/datasets?author=${owner}&limit=${pageSize}`, { headers: { 'Authorization': `Bearer ${req.accessToken}`, 'Content-Type': 'application/json' } }); const datasets = Array.isArray(response.data) ? response.data : []; const processedDatasets = datasets.map(dataset => ({ id: dataset.id, name: dataset.id, private: dataset.private || false, gated: dataset.gated || false, ...dataset })); res.json({ total: processedDatasets.length, page_size: pageSize, data: processedDatasets }); } catch (error) { console.error('Error fetching datasets:', error.response?.data || error.message); res.status(error.response?.status || 500).json({ error: 'Failed to fetch datasets', details: error.response?.data || error.message }); } }); // 4. 获取指定用户的 Spaces 列表 router.get('/spaces/:owner', validateAuthHeader, async (req, res) => { try { const { owner } = req.params; const pageSize = req.query.page_size || 50; const response = await axios.get(`${HF_API_BASE}/spaces?author=${owner}&limit=${pageSize}`, { headers: { 'Authorization': `Bearer ${req.accessToken}`, 'Content-Type': 'application/json' } }); const spaces = Array.isArray(response.data) ? response.data : []; const processedSpaces = spaces.map(space => ({ id: space.id, name: space.id, sdk: space.sdk, ...space })); res.json({ total: processedSpaces.length, page_size: pageSize, data: processedSpaces }); } catch (error) { console.error('Error fetching spaces:', error.response?.data || error.message); res.status(error.response?.status || 500).json({ error: 'Failed to fetch spaces', details: error.response?.data || error.message }); } }); // 5. 获取特定模型详情 router.get('/models/:owner/:repo_name', validateAuthHeader, async (req, res) => { try { const { owner, repo_name } = req.params; const response = await axios.get(`${HF_API_BASE}/models/${owner}/${repo_name}`, { headers: { 'Authorization': `Bearer ${req.accessToken}`, 'Content-Type': 'application/json' } }); res.json({ status: response.status, data: response.data }); } catch (error) { console.error('Error fetching model details:', error.response?.data || error.message); res.status(error.response?.status || 500).json({ error: 'Failed to fetch model details', details: error.response?.data || error.message }); } }); // 6. 获取特定数据集详情 router.get('/datasets/:owner/:repo_name', validateAuthHeader, async (req, res) => { try { const { owner, repo_name } = req.params; const response = await axios.get(`${HF_API_BASE}/datasets/${owner}/${repo_name}`, { headers: { 'Authorization': `Bearer ${req.accessToken}`, 'Content-Type': 'application/json' } }); res.json({ status: response.status, data: response.data }); } catch (error) { console.error('Error fetching dataset details:', error.response?.data || error.message); res.status(error.response?.status || 500).json({ error: 'Failed to fetch dataset details', details: error.response?.data || error.message }); } }); // 7. 获取特定 Space 详情 router.get('/spaces/:owner/:repo_name', validateAuthHeader, async (req, res) => { try { const { owner, repo_name } = req.params; const response = await axios.get(`${HF_API_BASE}/spaces/${owner}/${repo_name}`, { headers: { 'Authorization': `Bearer ${req.accessToken}`, 'Content-Type': 'application/json' } }); res.json({ status: response.status, data: response.data }); } catch (error) { console.error('Error fetching space details:', error.response?.data || error.message); res.status(error.response?.status || 500).json({ error: 'Failed to fetch space details', details: error.response?.data || error.message }); } }); module.exports = router;