//https://docs.github.com/en/rest/repos/contents export const onRequest = async (context: RouteContext): Promise => { const request = context.request; const env = context.env as Env; // 从 Authorization header 中获取 token const authHeader = request.headers.get('Authorization'); if (!authHeader || (!authHeader.startsWith('Bearer ') && !authHeader.startsWith('token '))) { return new Response(JSON.stringify({ error: '未提供有效的授权令牌' }), { status: 401, headers: { 'Content-Type': 'application/json' } }); } const githubToken = authHeader.startsWith('Bearer ') ? authHeader.replace('Bearer ', '') : authHeader.replace('token ', ''); console.log('Request URL:', request.url); try { const url = new URL(request.url); // 提取仓库所有者和仓库名称 const pathParts = url.pathname.split('/').filter(Boolean); const owner = pathParts[2] || url.searchParams.get('owner'); // 仓库所有者 const repo = pathParts[3] || url.searchParams.get('repo'); // 仓库名称 // 获取剩余的所有路径部分 const path = pathParts.length > 4 ? pathParts.slice(4).join('/') : (url.searchParams.get('path') || ""); if (!owner || !repo) { return new Response(JSON.stringify({ error: '缺少仓库所有者或仓库名称' }), { status: 400, headers: { 'Content-Type': 'application/json' } }); } // GitHub API 基础 URL const githubApiBase = 'https://api.github.com'; if (request.method === 'GET') { const ref = url.searchParams.get('ref'); // 分支或标签 // 获取文件内容或列出目录 const githubUrl = `${githubApiBase}/repos/${owner}/${repo}/contents/${path}${ref ? '?ref=' + ref : ''}`; console.log(githubUrl); const response = await fetch(githubUrl, { headers: { 'Authorization': `token ${githubToken}`, 'Accept': 'application/vnd.github.v3+json', 'User-Agent': 'Cloudflare-Worker' } }); const data = await response.json(); return new Response(JSON.stringify(data), { status: response.status, headers: { 'Content-Type': 'application/json' } }); } if (request.method === 'POST') { // 创建新文件 const body = await request.json() as any; const { content, message, branch } = body; if (!path || content === undefined) { return new Response(JSON.stringify({ error: '缺少必要参数: path, content' }), { status: 400, headers: { 'Content-Type': 'application/json' } }); } // Base64 编码内容 let encodedContent; try { // 检查内容是否已经是 Base64 编码 atob(content); encodedContent = content; } catch (e) { // 如果不是,则编码它 const encoder = new TextEncoder(); const bytes = encoder.encode(content); encodedContent = btoa(String.fromCharCode.apply(null, [...new Uint8Array(bytes)])); } const githubUrl = `${githubApiBase}/repos/${owner}/${repo}/contents/${path}`; const response = await fetch(githubUrl, { method: 'PUT', headers: { 'Authorization': `token ${githubToken}`, 'Accept': 'application/vnd.github.v3+json', 'Content-Type': 'application/json', 'User-Agent': 'Cloudflare-Worker' }, body: JSON.stringify({ message: message || `Create file ${path}`, content: encodedContent, branch: branch }) }); const data = await response.json(); return new Response(JSON.stringify(data), { status: response.status, headers: { 'Content-Type': 'application/json' } }); } if (request.method === 'PUT') { // 更新现有文件 const body = await request.json() as any; const { content, message, sha, branch } = body; if (!path || content === undefined || !sha) { return new Response(JSON.stringify({ error: '缺少必要参数: path, content, sha' }), { status: 400, headers: { 'Content-Type': 'application/json' } }); } // Base64 编码内容 let encodedContent; try { atob(content); encodedContent = content; } catch (e) { encodedContent = btoa(unescape(encodeURIComponent(content))); } const githubUrl = `${githubApiBase}/repos/${owner}/${repo}/contents/${path}`; const response = await fetch(githubUrl, { method: 'PUT', headers: { 'Authorization': `token ${githubToken}`, 'Accept': 'application/vnd.github.v3+json', 'Content-Type': 'application/json', 'User-Agent': 'Cloudflare-Worker' }, body: JSON.stringify({ message: message || `Update file ${path}`, content: encodedContent, sha: sha, branch: branch }) }); const data = await response.json(); return new Response(JSON.stringify(data), { status: response.status, headers: { 'Content-Type': 'application/json' } }); } if (request.method === 'DELETE') { const body = await request.json() as any; // 单个文件删除 const { message, sha, branch } = body; if (!path || !sha) { return new Response(JSON.stringify({ error: '缺少必要参数: path, sha' }), { status: 400, headers: { 'Content-Type': 'application/json' } }); } const githubUrl = `${githubApiBase}/repos/${owner}/${repo}/contents/${path}`; const response = await fetch(githubUrl, { method: 'DELETE', headers: { 'Authorization': `token ${githubToken}`, 'Accept': 'application/vnd.github.v3+json', 'Content-Type': 'application/json', 'User-Agent': 'Cloudflare-Worker' }, body: JSON.stringify({ message: message || `Delete file ${path}`, sha: sha, branch: branch }) }); const data = await response.json(); return new Response(JSON.stringify(data), { status: response.status, headers: { 'Content-Type': 'application/json' } }); } // 不支持的请求方法 return new Response(JSON.stringify({ error: '不支持的请求方法' }), { status: 405, headers: { 'Content-Type': 'application/json' } }); } catch (error: any) { return new Response(JSON.stringify({ error: '服务器内部错误', details: error.message }), { status: 500, headers: { 'Content-Type': 'application/json' } }); } };