Electron Forge+React+TS中如何正确调用GitHub公开API?
Electron Forge + React + TypeScript 渲染进程调用GitHub公开API解决方案
问题背景
使用Electron Forge + ReactJS + TypeScript技术栈,主进程中通过Octokit调用GitHub公开API(https://api.github.com/repos/nzhul/tic-tac-toe-online/releases/latest)正常,但在React渲染进程中执行相同代码时先后出现两个报错:
- 初始报错:CSP(内容安全策略)限制,未允许连接GitHub API域名
- 修改CSP后报错:GitHub的CORS策略不允许跨域请求携带
X-GitHub-Api-Version自定义头
报错详情
初始CSP报错
Refused to connect to 'https://api.github.com/repos/nzhul/tic-tac-toe-online/releases/latest?owner=OWNER&repo=REPO' because it violates the following Content Security Policy directive: "default-src 'self' 'unsafe-inline' data:". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.
修改CSP后的CORS报错
Access to fetch at 'https://api.github.com/repos/nzhul/tic-tac-toe-online/releases/latest?owner=OWNER&repo=REPO' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field x-github-api-version is not allowed by Access-Control-Allow-Headers in preflight response.
解决方案
方案一:主进程IPC转发请求(推荐)
Electron主进程不受浏览器CORS限制,通过IPC(进程间通信)让渲染进程委托主进程发起API请求,彻底规避CORS和CSP问题:
1. 主进程(main.ts)注册IPC handler
将Octokit请求逻辑移到主进程,并通过ipcMain.handle暴露给渲染进程:
import { app, BrowserWindow, ipcMain } from 'electron'; import { Octokit } from '@octokit/rest'; // ...其他主进程代码 // 注册IPC方法,处理渲染进程的API请求 ipcMain.handle('get-latest-release', async () => { const octokit = new Octokit(); try { const response = await octokit.request("GET /repos/nzhul/tic-tac-toe-online/releases/latest", { owner: "nzhul", // 替换为实际仓库所有者 repo: "tic-tac-toe-online", // 替换为实际仓库名 headers: { "X-GitHub-Api-Version": "2022-11-28", }, }); return response.data; } catch (error) { console.error('获取最新版本失败:', error); throw error; // 抛出错误让渲染进程处理 } });
2. 渲染进程(React组件)调用IPC方法
在React组件中使用ipcRenderer.invoke调用主进程的API:
import { ipcRenderer } from 'electron'; import { useEffect, useState } from 'react'; const ReleaseInfo = () => { const [releaseData, setReleaseData] = useState<any>(null); const [error, setError] = useState<string | null>(null); useEffect(() => { const fetchRelease = async () => { try { const data = await ipcRenderer.invoke('get-latest-release'); setReleaseData(data); } catch (err) { setError('获取版本信息失败'); console.error(err); } }; fetchRelease(); }, []); return ( <div> {releaseData ? ( <div> <h3>最新版本: {releaseData.name}</h3> <p>发布时间: {releaseData.published_at}</p> </div> ) : error ? ( <p>{error}</p> ) : ( <p>加载中...</p> )} </div> ); }; export default ReleaseInfo;
方案二:调整渲染进程请求配置(临时/非推荐)
如果必须在渲染进程直接请求,需修改两个点:
- 移除
X-GitHub-Api-Version自定义头(GitHub公开API默认使用最新版本,若需指定版本仍建议用方案一) - 收紧CSP配置,精准允许GitHub API域名,避免过度开放:
修改forge.config.ts的CSP配置
export default { // ...其他配置 plugins: [ { name: '@electron-forge/plugin-react', config: { devContentSecurityPolicy: "default-src 'self' 'unsafe-inline' data:; connect-src 'self' https://api.github.com;", }, }, // ...其他插件 ], };
渲染进程修改后的Octokit代码
const getRepoInfo = async () => { const octokit = new Octokit(); try { const response = await octokit.request("GET /repos/nzhul/tic-tac-toe-online/releases/latest", { owner: "nzhul", repo: "tic-tac-toe-online", // 移除X-GitHub-Api-Version头 }); return response; } catch (error) { console.error('请求失败:', error); throw error; } };
内容的提问来源于stack exchange,提问作者Dobromir Ivanov
相关产品推荐
相关产品推荐

