如何配置以处理连接到 ganache 的 web3 中的 CORS 错误
How to configure to handle CORS errors in web3 connecting to ganache
我有一个 React 项目,我是 运行,位于 http:\localhost:3000
,它连接到位于 http:\localhost:7545
的 ganache 运行。
我在 ganache 上部署了一个小型智能合约,它会增加一个计数器并发出一个事件,就像这样...
// SPDX-License-Identifier: MIT
pragma solidity >0.8.0;
contract Pong {
uint public pong_count;
function ping() public returns (uint){
pong_count++;
emit Pinged(this, pong_count);
return pong_count;
}
event Pinged(Pong indexed me, uint count);
function pong() public returns (uint){
pong_count++;
emit Ponged(this, pong_count);
return pong_count;
}
event Ponged(Pong indexed me, uint count);
}
我想收听合约中的 Pinged
和 Ponged
事件。
因为这只是我正在做的其他事情的帮助项目,所以我从一个 ganache 帐户中嵌入了私钥,并从中创建了一个帐户...
var pk_account = w3.eth.accounts.privateKeyToAccount(pk);
然后在我的代码的其他地方,我创建了一个名为 ponger
的 Pong 合约实例,并将其存储在我的 React 应用程序的上下文对象中,并使用 send
调用 ping() 合约方法像这样...
ctx.ponger.methods
.ping()
.send({from:ctx.pk_account.address})
.then((result,err)=>{
if (err){
console.log("pong error: ", err);
}
else {
console.log("pong : ", result);
result.gas = 200000;
ctx.pk_account.signTransaction(result, sent);
}
});
这就像一个魅力,本地回调 sent
被正确调用。
我将事件侦听器添加到我的 ponger
实例...
function ev_Pong(ev, err){
console.log("got pong event", ev);
}
function ev_Ping(ev, err){
console.log("got ping event", ev);
}
ctx.ponger.events.Pinged(ev_Ping);
ctx.ponger.events.Ponged(ev_Pong);
这就是乐趣的开始。我在 ev_Ping
收到的消息是...
got ping event Error: The current provider doesn't support subscriptions: HttpProvider
at subscription.js:176:1
所以,呃,我需要使用 websockets 而不是 HTTP,对吗?这意味着我只连接到 ws:\localhost:7545
而不是 http:\localhost:7545
.
(另外:如果我使用 MetaMask 交付我的 web3,我不会遇到任何这些问题...)
但是我收到这样的 CORS 错误...
Access to XMLHttpRequest at 'ws://localhost:7545/' from origin 'http://localhost:3000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https.
所以我的问题是如何克服 CORS 错误?我不确定这是 ganache 问题还是老式的 CORS 问题,还是什么。
我还不想放弃事件监听和解析事件日志 - 虽然我意识到可能还有很长的路要走不同的解决方案。
我弄清楚出了什么问题,这是我的错。 web3 websocket 提供程序不强制执行 CORS,因此它可以在我的用例中使用。
我遇到的问题是,即使我更改了发送 web3 的 URI 中的协议,我仍然要求 HTTPProvider
而不是 WebsocketProvider
。
出于我的目的,我对 getWeb3.js 进行了一些更改...
const getWeb3 = (url) => {
...
if (url){
if (url.substring(0,2) === 'ws'){
const provider = new Web3.providers.WebsocketProvider(url);
const web3 = new Web3(provider);
console.log("Using WS URL for web3: ", url);
resolve(web3);
}
else {
const provider = new Web3.providers.HttpProvider(url);
const web3 = new Web3(provider);
console.log("Using HTTP URL for web3: ", url);
resolve(web3);
}
}
...
}
这很好用。
从好的方面来说,它让我更好地理解了 CORS。我真的不喜欢在浏览器中禁用任何东西。
我有一个 React 项目,我是 运行,位于 http:\localhost:3000
,它连接到位于 http:\localhost:7545
的 ganache 运行。
我在 ganache 上部署了一个小型智能合约,它会增加一个计数器并发出一个事件,就像这样...
// SPDX-License-Identifier: MIT
pragma solidity >0.8.0;
contract Pong {
uint public pong_count;
function ping() public returns (uint){
pong_count++;
emit Pinged(this, pong_count);
return pong_count;
}
event Pinged(Pong indexed me, uint count);
function pong() public returns (uint){
pong_count++;
emit Ponged(this, pong_count);
return pong_count;
}
event Ponged(Pong indexed me, uint count);
}
我想收听合约中的 Pinged
和 Ponged
事件。
因为这只是我正在做的其他事情的帮助项目,所以我从一个 ganache 帐户中嵌入了私钥,并从中创建了一个帐户...
var pk_account = w3.eth.accounts.privateKeyToAccount(pk);
然后在我的代码的其他地方,我创建了一个名为 ponger
的 Pong 合约实例,并将其存储在我的 React 应用程序的上下文对象中,并使用 send
调用 ping() 合约方法像这样...
ctx.ponger.methods
.ping()
.send({from:ctx.pk_account.address})
.then((result,err)=>{
if (err){
console.log("pong error: ", err);
}
else {
console.log("pong : ", result);
result.gas = 200000;
ctx.pk_account.signTransaction(result, sent);
}
});
这就像一个魅力,本地回调 sent
被正确调用。
我将事件侦听器添加到我的 ponger
实例...
function ev_Pong(ev, err){
console.log("got pong event", ev);
}
function ev_Ping(ev, err){
console.log("got ping event", ev);
}
ctx.ponger.events.Pinged(ev_Ping);
ctx.ponger.events.Ponged(ev_Pong);
这就是乐趣的开始。我在 ev_Ping
收到的消息是...
got ping event Error: The current provider doesn't support subscriptions: HttpProvider
at subscription.js:176:1
所以,呃,我需要使用 websockets 而不是 HTTP,对吗?这意味着我只连接到 ws:\localhost:7545
而不是 http:\localhost:7545
.
(另外:如果我使用 MetaMask 交付我的 web3,我不会遇到任何这些问题...)
但是我收到这样的 CORS 错误...
Access to XMLHttpRequest at 'ws://localhost:7545/' from origin 'http://localhost:3000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https.
所以我的问题是如何克服 CORS 错误?我不确定这是 ganache 问题还是老式的 CORS 问题,还是什么。
我还不想放弃事件监听和解析事件日志 - 虽然我意识到可能还有很长的路要走不同的解决方案。
我弄清楚出了什么问题,这是我的错。 web3 websocket 提供程序不强制执行 CORS,因此它可以在我的用例中使用。
我遇到的问题是,即使我更改了发送 web3 的 URI 中的协议,我仍然要求 HTTPProvider
而不是 WebsocketProvider
。
出于我的目的,我对 getWeb3.js 进行了一些更改...
const getWeb3 = (url) => {
...
if (url){
if (url.substring(0,2) === 'ws'){
const provider = new Web3.providers.WebsocketProvider(url);
const web3 = new Web3(provider);
console.log("Using WS URL for web3: ", url);
resolve(web3);
}
else {
const provider = new Web3.providers.HttpProvider(url);
const web3 = new Web3(provider);
console.log("Using HTTP URL for web3: ", url);
resolve(web3);
}
}
...
}
这很好用。
从好的方面来说,它让我更好地理解了 CORS。我真的不喜欢在浏览器中禁用任何东西。