javascript - 如何发出 CORS 请求

标签 javascript ajax reactjs cors

我正在使用 React.js 制作一个天气应用程序,我想发出 CORS 请求以从地下天气网站获取数据。 我想要的是获取城市名称,使用自动完成 API 查找城市并获取该城市的数据。

问题是,每次我给出城市名称(例如:tehran)时,xhr.onerror 事件处理程序都会运行,并收到此错误:

XMLHttpRequest 无法加载 http://autocomplete.wunderground.com/aq?query=tehran。请求的资源上不存在“Access-Control-Allow-Origin” header 。因此,不允许访问源“http://localhost:3000”。

这是我获取数据的代码:

var axios = require('axios');

function createCORSRequest(method, url) {
    var xhr = new XMLHttpRequest();
    if ("withCredentials" in xhr) {
        xhr.open(method, url, true);
    }
    else if (typeof XDomainRequest != "undefined") {
        xhr = new XDomainRequest();
        xhr.open(method, url);
    }
    else {
        xhr = null;
    }
    return xhr;
}

function makeCorsRequest(url) {
    var autoCompleteText;
    var xhr = createCORSRequest('GET', url);
    if (!xhr) {
        alert('CORS not supported');
        return;
    }

    xhr.onload = function() {
        var text = xhr.responseText;
        autoCompleteText = text;
    }
    xhr.onerror = function() {
        alert('Woops, there was an error making the request.');
    }
    xhr.send();
    return autoCompleteText;
}

const WEATHER_UNDERGROUND_AUTOCOMPLETE = 'http://autocomplete.wunderground.com/aq?query=';
const WEATHER_UNDERGROUND_URL = 'http://api.wunderground.com/api/eda52d06d32d71e9/conditions/q/';

module.exports = {
    getTemp: function(city) {
        var encodedCity = encodeURIComponent(city);
        var requestAutoComplete = `${WEATHER_UNDERGROUND_AUTOCOMPLETE}${encodedCity}`;

        var autoCompleteText = makeCorsRequest(requestAutoComplete);
        var foundCity = autoCompleteText.RESULTS[0].name.split(', ');
        var requestUrl = `${WEATHER_UNDERGROUND_URL}${foundCity[1]}/${foundcity[0]}.json`;
        return axios.get(requestUrl).then(function(res) {
            return res.data.current_observation.temp_c;
        }, function(err) {
            throw new Error(res.data.error);
        });
    }
}

应用程序截图: localhost:3000/weather page

最佳答案

由于 http://autocomplete.wunderground.com/aq?query=tehran 不会发送 Access-Control-Allow-Origin 响应 header ,因此您必须更改您的前端代码以改为通过代理发出请求。通过更改 WEATHER_UNDERGROUND_AUTOCOMPLETE 值来实现此目的:

const WEATHER_UNDERGROUND_AUTOCOMPLETE =
  'https://cors-anywhere.herokuapp.com/http://autocomplete.wunderground.com/aq?query=';

https://cors-anywhere.herokuapp.com/http://autocomplete.wunderground.com/… URL 将导致请求转到 https://cors -anywhere.herokuapp.com,一个公共(public) CORS 代理,它将请求发送到您想要的 http://autocomplete.wunderground.com... URL。

该代理获取响应,接受它并向其添加 Access-Control-Allow-Origin 响应 header ,然后最终将其作为响应传递回您的请求前端代码。

最终,由于浏览器看到带有 Access-Control-Allow-Origin 响应 header 的响应,浏览器允许您的前端 JavaScript 代码访问该响应。

或者使用 https://github.com/Rob--W/cors-anywhere/ 中的代码或类似的方法来设置您自己的代理。

在这种情况下,您需要代理,因为 http://autocomplete.wunderground.com/... 本身不会发送 Access-Control-Allow-Origin 响应 header - 在这种情况下,您的浏览器将不允许您的前端 JavaScript 代码访问来自该服务器跨源的响应。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS有更多详细信息。

<小时/>

顺便说一句,您可以使用 curl 或其他一些工具来验证服务器没有发送 header :

$ curl -i -H 'Origin: http://localhost:3000' \
    'http://autocomplete.wunderground.com/aq?query=tehran'

HTTP/1.1 200 OK
Content-type: application/json; charset=utf-8
Content-Length: 2232
Connection: keep-alive

{ "RESULTS": [
    {
        "name": "Tehran Dasht, Iran",
        …

请注意,响应 header 中没有 Access-Control-Allow-Origin

关于javascript - 如何发出 CORS 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44347999/

相关文章:

javascript - 添加新消息时如何自动向下滚动

php - 我想在填写每个文本字段或使用 ajax 或 jQuery 选择类别后显示成功图像

reactjs - 我如何使用ant design在react js中禁用小屏幕上的1个选项卡

javascript - 如何用react-pose实现动画刻度线?

javascript - 带 React 的流动 tabindex

javascript - 获取父级信息并将其传递到隐藏表单

javascript - 将 json 数据附加到 HTML 列表框

javascript - JS/TS 装饰器命名约定

javascript - ajax请求到不同的主机

javascript - 使用基于 keydown() 的 tabindex 将焦点转移到下一个元素