2017-06-03 94 views
1

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

问题是,每次我给一个城市的名称(例如:德黑兰),该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 page

+0

你可以尝试做 axios.get(requestAutoComplete) 。然后(功能(响应){ 的console.log(响应);} .catch(功能(错误){ 的console.log(错误); }); – VivekN

+0

我在发布这个问题之前做了这个,但它没有工作 –

+0

你想屏幕共享吗?我可以更好地检查这个 – VivekN

回答

0

因为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/… URL会导致请求去https://cors-anywhere.herokuapp.com,它发送到你想要的http://autocomplete.wunderground.com… URL请求公众CORS代理。

该代理获取响应并将其添加并添加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/en-US/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

0

这里是一个简单的反应组件,它用查询参数调用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> 
     ) 
    } 
} 
0

你一定会使用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/en-US/docs/Web/API/Fetch_API/Using_Fetch

0

如果你正面临做CORS要求的问题,然后用这个简单的chrome extension(允许控制允许起源)

这会让你在headers/config没有增加任何额外的参数CORS请求。