【问题标题】:Moves App API call works in browser but fails in program (URL included in post)Moves App API 调用在浏览器中有效,但在程序中失败(帖子中包含 URL)
【发布时间】:2015-07-31 17:59:16
【问题描述】:

目标:在变量中保存一个 JSON 参数以供 JavaScript 程序使用。

问题:URL 有效(在浏览器中显示 JSON),但我在下面的 AJAX 调用失败:成功功能不起作用。 (从我的测试帐户访问令牌。)

非常感谢您的提示。

谢谢

菲利克斯

$.ajax({
    type: "GET",
    dataType: "jsonp",
    url: "https://api.moves-app.com/api/1.1/user/profile?access_token=7hACUBaguM0UI497MrDKJlvYPHu5813EErwFM6UJ7wURsI2d8iLj1BZ0R7Hru2gH",
    success: function(data) {
        alert("Test"); // Not working
    }
});

【问题讨论】:

  • 你得到什么错误?由于将空格等特殊字符替换为等效字符,我已经看到在某些环境(android、windows)和其他环境(iOS)中发生了问题。例如,空格被“%20”替换。也许你想检查一下。
  • 奇怪的是调用正在运行(尝试在浏览器中打开 URL:api.moves-app.com/api/1.1/user/…)——但是 AJAX 调用以某种方式破坏了程序(成功函数内的代码未执行) )。谢谢
  • 浏览器无法调用此api。它不支持 CORS 或 JSONP,因此不可能。

标签: javascript jquery ajax json api


【解决方案1】:

我会尽力回答并帮助你。 这不起作用,因为浏览器不允许不同的域异步调用它是一种出于安全原因而使用的机制,它被称为same-domain-policy

您看不到响应,因为浏览器阻止了它,如果您使用 REST 插件 for firefox 或 chrome,例如 POSTMAN,您可以看到实际上有响应,我确实使用邮递员从您的链接中获得了响应:

{"userId":1368648652999913,"profile":{"firstDate":"20150202","currentTimeZone":{"id":"Europe/Berlin","offset":7200},"localization":{"language":"en","locale":"en_US","firstWeekDay":1,"metric":true},"caloriesAvailable":false,"platform":"ios"}}

您可以创建一个代理服务器(例如使用 php)为您进行调用,然后使用 jquery 为该代理服务器创建 ajax,我为您制作了一个简单的代理,它可以工作,并且 $.ajax call 将对其起作用,您可以根据需要使用它:

<?php

 function executeRequest($url, $parameters = array(), $http_method = 'GET', array $http_headers = null, $form_content_type = 'multipart/form-data', $getResponseHeaders = false)
    {
        $certificate_file = null;
        $curl_options = array(
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_CUSTOMREQUEST  => $http_method
        );

        if ($getResponseHeaders){
            $curl_options[CURLOPT_HEADER] = true;
        }

        switch($http_method) {
            case 'POST':
                $curl_options[CURLOPT_POST] = true;
                /* No break */
            case 'PUT':
            case 'PATCH':

                /**
                 * Passing an array to CURLOPT_POSTFIELDS will encode the data as multipart/form-data,
                 * while passing a URL-encoded string will encode the data as application/x-www-form-urlencoded.
                 * http://php.net/manual/en/function.curl-setopt.php
                 */
                if(is_array($parameters) && 'application/x-www-form-urlencoded' === $form_content_type) {
                    $parameters = http_build_query($parameters, null, '&');
                }
                $curl_options[CURLOPT_POSTFIELDS] = $parameters;
                break;
            case 'HEAD':
                $curl_options[CURLOPT_NOBODY] = true;
                /* No break */
            case 'DELETE':
            case 'GET':
                if (is_array($parameters)) {
                    $url .= '?' . http_build_query($parameters, null, '&');
                } elseif ($parameters) {
                    $url .= '?' . $parameters;
                }
                break;
            default:
                break;
        }

        $curl_options[CURLOPT_URL] = $url;

        if (is_array($http_headers)) {
            $header = array();
            foreach($http_headers as $key => $parsed_urlvalue) {
                $header[] = "$key: $parsed_urlvalue";
            }
            $curl_options[CURLOPT_HTTPHEADER] = $header;
        }

        $ch = curl_init();
        curl_setopt_array($ch, $curl_options);
        // https handling
        if (!empty($certificate_file)) {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
            curl_setopt($ch, CURLOPT_CAINFO, $certificate_file);
        } else {
            // bypass ssl verification
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        }
        if (!empty($curl_options)) {
            curl_setopt_array($ch, $curl_options);
        }
        $result = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $content_type = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
        if ($curl_error = curl_error($ch)) {
            throw new Exception($curl_error, null);
        } else {
            $json_decode = json_decode($result, true);
        }
        curl_close($ch);

        return array(
            'result' => (null === $json_decode) ? $result : $json_decode,
            'code' => $http_code,
            'content_type' => $content_type
        );
    }


function getUserProfile($url){

    $parameters = array();

    $http_headers = array('Accept'=>'application/json',
                          'Content-Type'=>'application/x-www-form-urlencoded');
    $result = executeRequest($url, $parameters, 'GET', $http_headers, 0);
    return $result;
}

$url = $_GET['url'];

$result = getUserProfile($url);

echo $result['result'];

//Example usage:
//index.php?url=https://api.moves-app.com/api/1.1/user/profile?access_token=7hACUBaguM0UI497MrDKJlvYPHu5813EErwFM6UJ7wURsI2d8iLj1BZ0R7Hru2gH

?>

【讨论】:

    【解决方案2】:

    您需要在从中加载页面的服务器上安装一个所谓的代理页面。 该页面应以 PHP/Java(或其他)的服务器端语言编写,没有跨域限制。例如,您可以致电cURL。所以你可以调用你的代理页面,使用ajax但datatype:'json',而不是'jsonp'。在您的代理页面中,您必须调用 https://api.moves-app.com 并将数据作为 json 字符串返回到 jour 脚本。看起来很复杂,其实不然。

    【讨论】:

    • 确实我的回答给了他一个我自己测试过的简单代理:) 但你说的完全正确
    【解决方案3】:

    问题是由于网络安全模型的same-domain policy。您的 javascript 只能调用与您的网络应用程序相同的域上的资源。因此,除非您的网络应用位于 https://api.moves-app.com 中,否则您无法对其进行 ajax。

    您需要了解如何按照 Reflective 的建议执行跨域调用。看看这些关于它是什么以及如何做的问题。

    1. What is JSONP all about?
    2. AJAX cross domain call
    3. How to make cross domain request

    其中一个答案导致创建此维基百科条目:JSONP

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-20
      • 2016-02-07
      • 2021-09-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多