繁体   English   中英

如何提出CORS要求

[英]How to make CORS Request

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

问题是,每次我输入城市名称(例如:德黑兰)时, xhr.onerror事件处理程序都会运行,并且会出现以下错误:

XMLHttpRequest cannot load http://autocomplete.wunderground.com/aq?query=tehran. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.

这是我获取数据的代码:

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页面

这是一个简单的react组件,它使用查询参数调用api并获取所需的结果。

import React, { Component } from 'react'
import axios from 'axios';

export default class App extends Component {

    componentDidMount() {
        axios.get('http://autocomplete.wunderground.com/aq?query=tehran')
            .then((response) => {
                console.log(response);
            })
            .catch((error) => {
                console.log(error);
            })
    }
    render () {
        return (
            <div>React simple starter</div>
        )
    }
}

因为http://autocomplete.wunderground.com/aq?query=tehran不会发送Access-Control-Allow-Origin响应标头,所以您必须更改前端代码以改为通过代理发出请求。 通过更改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/…将导致请求转到https://cors-anywhere.herokuapp.com ,该公共CORS代理发送将请求发送到所需的http://autocomplete.wunderground.com…

该代理获取响应,然后将其添加到Access-Control-Allow-Origin响应标头中,然后最终将其作为响应传递回您的请求前端代码。

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

或使用https://github.com/Rob--W/cors-anywhere/中的代码或诸如此类来设置您自己的代理。

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

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


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

$ 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",
        …

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

您一定要使用axios吗? 如果没有的话,我强烈推荐Mozilla的Fetch。 要使用访存进行cors api调用,请执行以下操作:

var myInit = { 
    method: 'GET',
    mode: 'cors',
    credentials: 'include'
};

fetch(YOUR_URL, myInit)
.then(function(response) {
    return response.json();
})
.then(function(json) {
    console.log(json)
});

您可以在此处了解更多信息: https : //developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch

如果您在提出CORS请求时遇到问题,请使用此简单的chrome扩展名 (允许控件允许原点)

这将使您发出CORS请求,而无需在headers/config添加任何额外的参数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM