2017-08-24 35 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。

相关问题