【问题标题】:Can ajax use absolute urls' for calling web services?ajax 可以使用绝对 URL 来调用 Web 服务吗?
【发布时间】:2016-04-16 05:05:01
【问题描述】:

大多数 javascript ajax 教程/示例表明请求只能是相对路径,这意味着不能调用其他 Web 服务器。我想调用不包含在同一应用程序中的 Web 服务,并且需要具有绝对路径url.当我调用类似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");
      }

    }

  }

})();

【问题讨论】:

  • 应该在同一个域中
  • 是否可以有相同的主机和不同的域?

标签: javascript jquery ajax


【解决方案1】:

ajax 是否可以使用绝对 URL 来调用 Web 服务?

是的,如果接收服务器支持 CORS 或 JSONP 等跨源方案,并且您正确指定了 URL。

浏览器具有称为“同源保护”的安全功能。默认情况下,这种保护只允许您对与加载 Javascript 的网页完全相同的“来源”(相同的协议、相同的域、相同的端口)进行 Ajax 调用。

有几种方法可以绕过同源保护。

  1. CORS - 跨源资源共享是接收服务器告诉浏览器允许部分或所有跨源请求的方案。如果服务器启用这种类型的访问,那么来自其他域的浏览器网页可能会对该服务进行 Ajax 调用。 CORS 不是全有或全无,它具有许多功能,因此站点甚至可以仅启用某些类型的访问或仅启用来自某些其他站点的访问。

  2. JSONP - 在 CORS 存在之前,网络世界提出了一种称为 JSONP 的有点骇人听闻的解决方法。在此方案中,浏览器从所需的主机请求一个脚本文件(脚本文件不受同源安全限制),然后主机服务器返回一个浏览器将执行的实际 Javascript 文件。如果操作正确,则执行的脚本可以将结果返回给调用者。 JSONP 不是常规的 Ajax 调用,尽管一些 Ajax 库(如 jQuery)允许您使用它们的 Ajax 接口,即使您正在发出 JSONP 请求。

  3. 代理 - 同源限制只是浏览器中的一项功能,因此服务器可以不受限制地联系它想要的任何域。解决同源限制的一种方法是让您自己的服务器(在您自己的与网页域匹配的域上)为您发出外部请求(例如代理请求)。您向您自己的服务器发送一个 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) 修复错误处理。responseHandler() 函数中使用 throw 对您没有好处。那是一个异步回调,并且执行throw 只会进入 XMLHttpRequest 基础结构的内部。它不会是您可以用于任何有意义的事情的例外。您可能需要重组代码,以便通过回调将错误传达回调用者。

4) 使用已经过测试的 Ajax 库。 在这个时代,我不知道您为什么要从头开始编写自己的 Ajax 包装器。实际上已经有数以千计的可用了,你可以直接从架子上取下来,复制到你的项目中,而不必用你自己的代码解决所有这些类型的问题。如果我个人还没有使用任何支持 Ajax 的框架,我可能会为新的 fetch() API 获取一个 polyfill 并使用它,因为这是客户端 Ajax 的未来,它是一个非常干净的 API。

【讨论】:

  • @GayanPrasanna - 我们需要查看调用 ajax 函数的代码,并准确查看传递给它的 URL。此外,您的 Ajax 代码中有几个编码错误。我将在我的答案中添加一些关于它们的 cmets。
  • 通过您的修复,我解决了我的问题,问题是我的网址在修复后有空格和一些东西,并使您的更改完美运行。我被要求不要使用任何框架或库这行得通,这就是为什么我为 ajax 编写了一个包装器
【解决方案2】:

通过 AJAX 调用 CURL 脚本:

JQuery:

$.ajax({
    url: "assets/php/some_script.php",
    type: 'GET',
    path: //object to send to CURL request,            
    timeout: 1500,
    cache: false,         
    error: function(a, b, c){
        console.log("Error:", a, b, c);
    },
    success: function(data){
        //work with your data here
    }
});

PHP(即 some_script.php):

$path = filter_input(INPUT_GET, 'path');
$url = /*Your absolute URL here*/ . $path

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$json = curl_exec($ch);

if ($error = curl_error($ch)) {
    trigger_error("Failed to communicate with server: {$error}", E_USER_ERROR);
    return;
}
curl_close($ch);
return $json;

【讨论】:

  • 感谢您的帮助。但我没有使用 php .thanks 反正
猜你喜欢
  • 1970-01-01
  • 2016-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多