2017-06-03 53 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請求。