如何在电子应用程序中处理CORS

时间:2018-07-09 22:00:37

标签: node.js proxy cors electron reverse-proxy

我正在构建电子应用程序,需要在API提供程序未启用CORS的情况下调用API。通常建议的解决方案是使用反向代理,当通过使用node和cors进行本地运行时,这样做很简单:



let port = (process.argv.length > 2) ? parseInt (process.argv[2]) : 8080; 
require ('cors-anywhere').createServer ().listen (port, 'localhost');

然后可以将该应用程序配置为通过localhost:8080上的反向代理来代理所有请求。

所以,我的问题是:

  1. 是否可以在电子应用程序中的任何位置使用节点和cors来创建反向代理?我不想强迫应用程序调用远程服务器。

  2. 在Electron应用程序中,有没有更好或更标准的方法?我假设我不是第一个遇到CORS问题的人。 :)

6 个答案:

答案 0 :(得分:1)

今天刚发生此问题API calls with axios inside a React app bundled in Electron is returning 400

据我所见,Electron调用就像是对API URL的常规调用,这意味着它们不受CORS的影响。

现在,当您使用CORS代理包装呼叫并进行常规调用时,由于它不是CORS呼叫,它应该会出现400错误的错误。 该线程解释了为什么cors-anywhere会这样响应=> https://github.com/Rob--W/cors-anywhere/issues/39

实际上,在构建Electron之前,我已经从应用程序中删除了我的CORS代理。由于我正在浏览器中进行测试,因此我仍然需要CORS代理进行开发。

希望这会有所帮助。

答案 1 :(得分:1)

在我的应用程序中,仅删除请求中的Origin标头(将其设置为null)是不够的。我传递请求的服务器始终在响应中提供Access-Control-Allow-Origin头,无论请求中是否存在Origin头。因此,Chrome的嵌入式实例不喜欢ACAO标头与对来源的理解不匹配。

相反,我不得不更改请求上的Origin标头,然后将其恢复到响应上的Access-Control-Allow-Origin标头上。

app.on('ready', () => {
  // Modify the origin for all requests to the following urls.
  const filter = {
    urls: ['http://example.com/*']
  };

  session.defaultSession.webRequest.onBeforeSendHeaders(
    filter,
    (details, callback) => {
      console.log(details);
      details.requestHeaders['Origin'] = 'http://example.com';
      callback({ requestHeaders: details.requestHeaders });
    }
  );

  session.defaultSession.webRequest.onHeadersReceived(
    filter,
    (details, callback) => {
      console.log(details);
      details.responseHeaders['Access-Control-Allow-Origin'] = [
        'capacitor-electron://-'
      ];
      callback({ responseHeaders: details.responseHeaders });
    }
  );

  myCapacitorApp.init();
});

答案 2 :(得分:1)

您可以让主进程,即运行 Electron 的 NodeJS 服务器发送请求。这避免了 CORS,因为这是一个服务器到服务器的请求。您可以使用 IPC 从前端(渲染进程)向主进程发送事件。在主流程中,您可以listen到这个事件,发送 HTTP 请求,并向前端返回一个承诺。

在 main.js(创建 Electron 窗口的脚本)中:

import { app, protocol, BrowserWindow, ipcMain } from ‘electron’
import axios from 'axios'

ipcMain.handle('auth', async (event, ...args) => {
  console.log('main: auth', event, args)  const result = await axios.post(
    'https://api.com/auth',
    {
      username: args[0].username,
      password: args[0].password,
      auth_type: args[1],
    },
  )  console.log('main: auth result', result)
  console.log('main: auth result.data', result.data)  return result.data
})

在您的前端 JS 中:

import { ipcRenderer } from 'electron'

sendAuthRequestUsingIpc() {
  return ipcRenderer.invoke('auth',
    {
      username: AuthService.username,
      password: AuthService.password,
    },
    'password',
  ).then((data) => {
    AuthService.AUTH_TOKEN = data['access_token']
    return true
  }).catch((resp) => console.warn(resp))
}

我写了一篇更深入的文章here

答案 3 :(得分:1)

如果您在 localhost 中运行 Web 应用程序,请尝试此操作

const filter = {
  urls: ['http://example.com/*'] // Remote API URS for which you are getting CORS error
}

browserWindow.webContents.session.webRequest.onBeforeSendHeaders(
  filter,
  (details, callback) => {
    details.requestHeaders.Origin = `http://example.com/*`
    callback({ requestHeaders: details.requestHeaders })
  }
)

browserWindow.webContents.session.webRequest.onHeadersReceived(
  filter,
  (details, callback) => {
    details.responseHeaders['access-control-allow-origin'] = [
      'capacitor-electron://-',
      'http://localhost:3000' // URL your local electron app hosted
    ]
    callback({ responseHeaders: details.responseHeaders })
  }
)

答案 4 :(得分:0)

在发送请求之前先覆盖标头

const filter = {
  urls: ['*://*.google.com/*']
};
const session = electron.remote.session
          session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => {
                details.requestHeaders['Origin'] = null;
                details.headers['Origin'] = null;
                callback({ requestHeaders: details.requestHeaders })
});

将这些代码放入渲染器过程

答案 5 :(得分:-1)

您是否尝试过使用fetch() 在此处检查如何使用提取进行无要求的请求 https://developers.google.com/web/updates/2015/03/introduction-to-fetch?hl=en