大多数javascript ajax教程/示例都显示请求只能是相对路径,这意味着无法调用其他Web服务器。我想调用不包含在同一应用程序中且需要具有绝对URL的Web服务。我叫http://192.168.1.62:8080/TRACER-REST-API/webapi/projects/16/releases/2/issues之类的东西,而ajax xhr叫http:// localhost:8080 / app / http://192.168.1.62:8080/TRACER-REST-API/webapi/projects/16/releases/2/issues之类的东西
var XHR = null;
var $ajaxService = (function() {
function getXHRObject() {
var xmlHttpObject = null;
try {
//for old IE
xmlHttpObject = new ActiveXObject("Msxml2.XMLHTTP");
} catch (oldIEException) {
try {
// For IE 6.0+
xmlHttpObject = new ActiveXObject("Microsoft.XMLHTTP");
} catch (IESixPlusException) {
xmlHttpObject = false;
}
}
if (!xmlHttpObject && xmlHttpObject !== undefined) {
// firefox/chrome
xmlHttpObject = new XMLHttpRequest();
}
return xmlHttpObject;
}
return {
call: function makeServerCall(httpMethod, uri, isAsync, headers, postData, responseCallback) {
console.log(uri);
XHR = getXHRObject();
if (XHR != null) {
XHR.open(httpMethod, uri, isAsync);
if (headers != null) {
//XHR.setRequestHeader();
}
if (httpMethod === 'POST' && postData !== undefined) {
XHR.send(postData);
} else {
XHR.send();
}
XHR.onreadystatechange = responseHandler(responseCallback);
}
}
}
function responseHandler(callBack) {
if (XHR.readyState == 4) {
switch (XHR.state) {
case 200:
callBack();
break;
case 500:
throw new Error("Internal Server Error");
default:
throw new Error("Error occurred during server call");
}
}
}
})();
最佳答案
Ajax可以使用绝对URL来调用Web服务吗?
是的,如果接收服务器支持跨源方案(例如CORS或JSONP),并且您正确指定了URL。
浏览器具有称为“相同来源保护”的安全功能。默认情况下,此保护允许您仅对与运行Javascript的网页完全相同的“来源”(相同的协议,相同的域,相同的端口)进行Ajax调用。
围绕这种相同的原产地保护有两种方法。
CORS-跨源资源共享是一种方案,接收服务器通过该方案告诉浏览器允许部分或全部跨源请求。如果服务器启用了这种类型的访问,则来自其他域的浏览器网页可能会对此服务进行Ajax调用。 CORS不仅具有全部功能,还具有许多功能,因此,一个站点甚至可以仅启用某些类型的访问权限,或者仅启用来自某些其他站点的访问权限。
JSONP-在CORS出现之前,网络世界提出了一种有点黑的变通方法,称为JSONP。在此方案中,浏览器从所需的主机请求脚本文件(脚本文件不受相同的来源安全限制),然后主机服务器返回浏览器将执行的实际Javascript文件。如果操作正确,执行的脚本可以将结果传回给调用方。 JSONP不是常规的Ajax调用,尽管某些Ajax库(如jQuery)允许您即使在发出JSONP请求时也可以使用其Ajax接口。
代理-相同的来源限制仅是浏览器中的功能,因此服务器可以不受限制地联系其想要的任何域。解决相同来源限制的一种方法是让您自己的服务器(在与网页域匹配的自己的域上)为您发出外部请求(例如代理请求)。您将Ajax呼叫发送到您自己的服务器,要求它为您提出代理请求。然后,您的服务器与外部服务器联系,获取结果并将其作为Ajax响应返回给您。
如果您请求对以下URL的Ajax调用:http://192.168.1.62:8080/TRACER-REST-API/webapi/projects/16/releases/2/issues
您会看到实际使用的是http:localhost:8080/app/http://192.168.1.62:8080/TRACER-REST-API/webapi/projects/16/releases/2/issues
然后,您的代码可能出了点问题,因为如果您的代码正确,浏览器将不会自行执行此操作。您可能需要向我们展示您的实际代码,以了解您的代码出了什么问题。如果正确指定,则支持绝对URI。
在您的Ajax代码中,您需要进行一些更改:
1)隐式全局。在此处添加var
,这样XHR
不会是意外的全局变量,因此如果一次执行多个Ajax调用,则不会有变量冲突:
var XHR = getXHRObject();
2)修复XHR.onreadystatechange。更改此:
XHR.onreadystatechange = responseHandler(responseCallback);
为此,您不必立即调用它,而是要分配一个可以在以后调用的函数:
XHR.onreadystatechange = function() {
responseHandler(XHR, responseCallback);
}
然后,将额外的XHR参数添加到您的
responseHandler()
实现中。3)修正错误处理。从
throw
函数中对responseHandler()
进行操作对您没有好处。这是一个异步回调,并且执行throw
只会使XMLHttpRequest基础结构陷入困境。可用于任何有意义的事情也不例外。您可能需要重组代码,以便通过回调将错误传达回调用方。4)使用已经测试过的Ajax库。在当今时代,我不知道为什么要从头开始编写自己的Ajax包装器。实际上,已经有成千上万种可用,您可以直接使用它们,将其复制到您的项目中,而不必通过自己的代码来解决所有这些类型的问题。如果我个人还没有使用任何支持Ajax的框架,那么我可能会为新的
fetch()
API获取一个polyfill并使用它,因为这是客户端Ajax的未来,并且它是一个非常干净的API。