Electron应用需通过主进程代理调用Dify API以绕过CORS,配置Dify启用API权限并生成带“允许调用应用API”权限的密钥;主进程启动本地HTTP代理服务(端口8081),安全注入API Key;preload.js暴露IPC接口,主进程处理流式响应并拼接JSON,渲染进程实现打字效果。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜

你需要让Electron应用直接调用Dify后端服务,绕过浏览器同源限制和CORS问题,同时保证本地窗口能稳定接收流式响应。这要求Electron主进程充当代理层,而非前端直连Dify API。
配置Dify启用API访问权限
登录Dify控制台,在左侧导航栏点击“设置”→“API密钥管理”→“生成新密钥”。【密钥必须勾选“允许调用应用API”权限】,否则Electron发出的请求会被403拒绝。
复制生成的API Key,它只显示一次,丢失需重新生成。
进入目标应用编辑页,切换到“发布”标签页,确认“启用API访问”开关已打开。未开启时所有API调用返回404。
在Electron中创建安全的API代理服务
Electron渲染进程不能直接跨域请求localhost:5001(Dify默认端口),必须由主进程启动一个本地HTTP代理服务。
在main.js中添加以下代码:
const { app, BrowserWindow, net } = require('electron');
const http = require('http');
const url = require('url');
let proxyServer;
function startAPIServer() {
proxyServer = http.createServer((req, res) => {
const parsedUrl = url.parse(req.url, true);
const targetUrl = `http://localhost:5001${parsedUrl.pathname}${parsedUrl.search}`;
const request = net.request({
method: req.method,
url: targetUrl,
headers: {
'Authorization': 'Bearer ' + process.env.DIFY_API_KEY,
'Content-Type': req.headers['content-type'] || 'application/json'
}
});
request.on('response', (response) => {
res.writeHead(response.statusCode, response.headers);
response.pipe(res);
});
req.pipe(request);
});
proxyServer.listen(8081);
}
注意:DIFY_API_KEY必须通过process.env注入,绝不可硬编码在JS文件中,否则打包后密钥会暴露在asar包里。
构建流式响应处理模块
第一步:在preload.js中暴露安全API接口
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('difyAPI', {
sendQuery: (appId, input) => ipcRenderer.invoke('dify:query', appId, input)
});
第二步:主进程中注册IPC handler并处理流式chunk
ipcMain.handle('dify:query', async (event, appId, input) => {
return new Promise((resolve) => {
const chunks = [];
const req = http.request({
hostname: 'localhost',
port: 8081,
path: `/v1/chat-messages`,
method: 'POST',
headers: { 'Content-Type': 'application/json' }
}, (res) => {
res.on('data', chunk => chunks.push(chunk));
res.on('end', () => {
const fullResponse = Buffer.concat(chunks).toString();
try {
resolve(JSON.parse(fullResponse));
} catch (e) {
resolve({ error: 'Invalid JSON response' });
}
}
});
});
req.write(JSON.stringify({
inputs: {},
query: input,
response_mode: 'stream',
user: 'electron-user'
}));
req.end();
});
});
在渲染进程实现带打字效果的响应渲染
const responseElement = document.getElementById('response');
async function handleSend() {
const input = document.getElementById('input').value;
responseElement.innerHTML = '';
const result = await window.difyAPI.sendQuery('app-xxx', input);
if (result.answer) {
let i = 0;
const interval = setInterval(() => {
if (i responseElement.textContent += result.answer[i++];
} else {
clearInterval(interval);
}
}, 20);
}
}
这一步操作起来很简单,直接把handleSend绑定到发送按钮的onclick事件上就行。
打包前必须完成的三项校验
① 检查Dify服务是否监听0.0.0.0:5001而非127.0.0.1:5001——Electron主进程发起的请求来自localhost,但Dify默认绑定127.0.0.1会导致连接被拒绝。
② 在package.json的build配置中加入:
"extraResources": [{ "from": "node_modules/dify-sdk", "to": "dify-sdk", "type": "dir" }]
③ 运行electron-builder前,执行命令:export DIFY_API_KEY=sk-xxx(macOS/Linux)或set DIFY_API_KEY=sk-xxx(Windows),确保环境变量注入成功。


















