2017-08-24 33 views
2

我需要發送的XMLHttpRequest到Yandex的服務器獲取錯誤的請求錯誤400試圖發送XMLHttpRequest來http://api.lbs.yandex.net/geolocation

我得到的錯誤請求錯誤(400)和:

XMLHttpRequest無法加載http://api.lbs.yandex.net/geolocation。否 「訪問控制 - 允許來源」標題出現在請求的 資源中。因此不允許訪問原產地'http://localhost'。 響應了HTTP狀態代碼400

這裏是我的代碼:

var xhr = new XMLHttpRequest(); 
var url = "http://api.lbs.yandex.net/geolocation"; 

xhr.open("POST", url, true); 
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 

xhr.onreadystatechange = function() { 
    <some code> 
}; 

var data = JSON.stringify({ 
"common": { 
    "version": "1.0", 
    "api_key": <here goes API key> 
    }, 
    "gsm_cells": [ 
    { 
    "countrycode": params[0], 
    "operatorid": params[1], 
    "cellid": params[3], 
    "lac": params[2], 
    "age": 0 
    } 
    ] 
}); 

xhr.send(data); 

我無法找到解決方案,這樣簡單的事情(?)!

回答

1

該API預計application/x-www-form-urlencoded,看起來像這樣 - 格式化數據:

json={"common":{"version":"1.0","api_key":…}…} 

也就是說,它需要一個key=value對,以字符串json爲重點和一些JSON作爲值。

但問題中的代碼發送一些JSON,而在它之前沒有必要的json=。所以API端點以400響應,告訴你這是一個不好的請求。

所以,你可以解決這個問題,並通過使你的代碼,而不是爲此獲得迴應:

var data = 'json=' + JSON.stringify({…}); 

但是,你甚至在那之後,您的瀏覽器仍然不會讓你前端的JavaScript訪問響應服務器返回。相反,瀏覽器將記錄如下錯誤消息:

加載失敗https://api.lbs.yandex.net/geolocation:請求的資源上沒有「Access-Control-Allow-Origin」標頭。因此不允許訪問原產地https://foo.bar

...因爲CORS協議要求瀏覽器不允許前端JavaScript代碼訪問來自跨源請求的響應,除非響應有Access-Control-Allow-Origin

但是,您可以通過CORS代理來請求請求;完整的例子:然而

var xhr = new XMLHttpRequest(); 
 
var proxyurl = "https://cors-anywhere.herokuapp.com/"; 
 
var url = "https://api.lbs.yandex.net/geolocation"; 
 

 
xhr.open("POST", proxyurl + url, true); 
 
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 
 

 
xhr.onreadystatechange = function() { 
 
    console.log(xhr.responseText) 
 
}; 
 

 
var data = 'json=' + JSON.stringify({ 
 
    "common": { 
 
    "version": "1.0", 
 
    "api_key": "AAwkGkwBAAAA9muWLAMAKp9XjTBZtmOLeiBQJqHX6YEqNdUAAAAAAAAAAAAoEP1ZsBlcVFA_OpP55MK3Ek1r8A==" 
 
    }, 
 
    "gsm_cells": [{ 
 
    "countrycode": 250, 
 
    "operatorid": 99, 
 
    "cellid": 42332, 
 
    "lac": 36002, 
 
    "age": 0 
 
    }] 
 
}); 
 
xhr.send(data);

請注意,如果您發送過這樣的第三方代理的請求,代理的運營商有可能在你的api_key以及其他任何憑證窺探你可能發送。

所以,你最好不要設置使用https://github.com/Rob--W/cors-anywhere/


至於代理例如上述工程中如何自己代理:加前綴https://cors-anywhere.herokuapp.com/你的請求URL導致該請求獲得通過代理做,然後:

  1. 將請求轉發到任何https://api.lbs.yandex.net/geolocation
  2. 收到https://api.lbs.yandex.net/geolocation的回覆。
  3. Access-Control-Allow-Origin標頭添加到響應中。
  4. 將具有該添加標題的響應傳遞迴請求的前端代碼。

然後,瀏覽器將允許您的前端代碼訪問響應,因爲響應標頭爲Access-Control-Allow-Origin的響應是瀏覽器所看到的。


又見https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

+0

Thx爲快速和很好解釋的答案!你是對的,在數據​​查詢中加入「json = ...」可以修復第一個錯誤。 雖然我認爲必須有另一個解決方案,但代理來解決第二個問題,因爲yandex.geolocation是一個公共服務,並且必須處理來自不同服務器的請求。 –

+0

是的,它可以從任何非瀏覽器工具或後端編程運行時工作,但只要它能夠直接從瀏覽器中運行的前端JavaScript代碼生成請求,我保證絕對沒有任何其他方式可以使其工作以外的其他方式使用答案中描述的方式使用CORS代理。瀏覽器會阻止你的代碼進入響應,因爲瀏覽器在默認情況下會阻止對來自跨源請求的響應的所有訪問,並且唯一的方法就是讓它們不會像那樣阻塞,就是讓它們成爲Access-Control-Allow-Origin響應頭 – sideshowbarker

1

建議sulution不會在普通情況下正常工作,但工作正常的GCM細胞。這是因爲yandex.net/geolocation服務用於獲取基於WiFi網絡,gcm cell或ip地址的用戶位置。

當需要僅使用基於IP的方式時,則需要在您的Web服務器上配置CORS。

相關問題