在Webpack开发服务器中调用Twitter api时出现CORS问题

4

我遇到了一个问题,无法从Twitter API(使用npm包Twitter)获取响应。在Chrome中,我得到以下错误信息:

无法加载https://api.twitter.com/1.1/search/tweets.json?q=node.js:预检请求的响应未通过访问控制检查:所请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,不允许从源“http://localhost:3000”访问。响应的HTTP状态码为400。如果不透明的响应满足您的需求,请将请求的模式设置为“no-cors”,以禁用CORS获取资源。

因此,我使用插件启用CORS,错误消息变为:

无法加载https://api.twitter.com/1.1/search/tweets.json?q=node.js:预检请求的响应具有无效的HTTP状态码400。

我不确定该怎么办。我尝试了一些不同的方法在我的webpack.config.js中:

var path = require('path');
var webpack = require('webpack');
var Dotenv = require('dotenv-webpack');

module.exports = {
    devServer: {
        inline: true,
        historyApiFallback: true,
        contentBase: './src',
        port: 3000,
        headers: {
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept",
            "Access-Control-Allow-Credentials": "true",
            "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS"
        },
        proxy: {
            "/api": "http://localhost:3000"
        }
    },
    devtool: 'cheap-module-eval-source-map',
    entry: './dev/js/index.js',
    module: {
        loaders: [
            {
                test: /\.js$/,
                loaders: ['babel'],
                exclude: /node_modules/
            },
            {
                test: /\.scss/,
                loader: 'style-loader!css-loader!sass-loader'
            },
            {
                loader: 'json-loader',
                test: /\.json$/ 
            }
        ]
    },
    output: {
        path: 'src',
        filename: 'js/bundle.min.js'
    },
    node: {
        console: false,
        fs: 'empty',
        net: 'empty',
        tls: 'empty'
    },
    plugins: [
        new webpack.optimize.OccurrenceOrderPlugin(),
        new Dotenv({
            path: './.env',
            safe: false
        })
    ]
};

这是我试图进行的调用

import Twitter from 'twitter';

const client = new Twitter({
  consumer_key: process.env.TWITTER_CONSUMER_KEY,
  consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
  bearer_token: process.env.TWITTER_BEARER_TOKEN
});

client.get('search/tweets', {q: 'node.js'}, function(error, tweets, response) {
   console.log(tweets);
});

我还在使用启用了CORS插件的Firefox中尝试过,但是我遇到了这个错误:

跨域请求被阻止:同源策略禁止读取远程资源https://api.twitter.com/1.1/search/tweets.json?q=node.js。(原因:CORS预检通道失败)。

3个回答

1
我在使用React时遇到了同样的问题。为了解决这个问题,我在Node中挂载了一个Express服务器,并创建了测试端点,然后在npm网站上按照步骤要求安装Twitter库。接下来,在前端使用fetch请求访问Express端点,然后从Twitter收集数据,并将Twitter的响应发送回前端。
我在本地使用localhost:4000运行Express服务器,同时使用localhost:3000运行create-react-app。然后我在package.json文件中添加了"proxy": "http://localhost:4000",放在"scripts" : {}之前(位置不太重要)。
成功解决了问题 ^_^

示例代码总是很好的。你能否提供给我们吗? - atbrakhi

1
我只能想到一个解决方法:
  • 使用chrome扩展程序Allow-Control-Allow-Origin
  • 使用代理:不要访问 https://api.twitter.com/1.1/search/tweets.json?q=node.js,而是使用代理作为前缀,例如:https://cors-anywhere.herokuapp.com/https://api.twitter.com/1.1/search/tweets.json?q=node.js

嗯...我在webpack中的代理配置写对了吗?proxy: {"/api": "https://cors-anywhere.herokuapp.com/"} 我已经将它添加到我的devServer对象中,但似乎没有起作用。 - Gerald Wangley
我不是100%确定,但我认为这不会起作用,因为像cors-anywhere这样的东西不允许身份验证标头。 - Clay
@GeraldWangley devServer.proxy 不是为这种情况设计的。它的设计目的是将请求代理到任何您配置的 URL 上的 webpack-dev-server。由于 Twitter 客户端直接请求 https://api.twitter.com,因此您的 devServer.proxy 将不会产生任何效果。只需尝试 @Rahamin 在此列出的方法,安装浏览器 CORS 扩展程序或使用外部 CORS 代理服务即可。 - loveky

0

当您的浏览器向Webpack开发服务器代理发出HTTP请求时,它会设置一个来源头(origin header),然后代理将此来源头转发给Twitter。很可能Twitter会基于其非法来源拒绝该请求。在请求被转发之前,您可以通过删除来源头来解决此问题:

devServer: {
  ...,
  proxy: {
    ...,
    onProxyReq: function onProxyReq(proxyReq, req, res) {
      proxyReq.removeHeader("origin")
    }
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接