跨域JSONP AJAX - “Uncaught SyntaxError:Unexpected token”

时间:2013-12-11 11:16:17

标签: jquery ajax json cross-domain jsonp

我正在为一个名为Mixi的平台构建一个简单的应用程序,就像日本的Facebook一样。现在,在Javascript API中,我尝试按照给定的API并在传递正确的身份验证令牌后获取用户的配置文件信息。

如果我从浏览器的地址栏触发API链接,则该链接非常有效。但是,经过几个小时的摆弄,尝试JSONP和我能找到的所有可能的变种,Chrome的控制台确实显示数据,但只有当我点击此错误时才会显示:

Uncaught SyntaxError: Unexpected token :

现在,我无法更改服务器端的任何内容,因为它是一个公共API,我需要跨域访问它。如果响应是JSON而不是JSONP,我认为是这样的,可以做些什么来解决?在这种情况下,出路是什么?

我的电话如下:

// token is coming correctly from code above
var reqUrl = "https://api.mixi-platform.com/2/people/@me/@self?access_token=" + token;

$.ajax({
           type:'GET',
           url: reqUrl,
           processData: true,
           data: {},
           dataType: "jsonp",
           success: function (data) {
               alert("Success");
               alert(data);
           },
           error: function() { alert("not working..."); },
           jsonp: 'jsonp'
});

1 个答案:

答案 0 :(得分:2)

除非您请求数据的社交网络启用了CORS(跨源资源共享),否则您无法使用AJAX从它们获取JSON格式的数据,因为它违反了同源策略(SOP)。但是,您可以请求JSONP,跨越原点,因为这不属于SOP裁决,但在查看他们的文档后,他们不提供JSONP格式的响应。

如果您查看其文档的示例代码页here,您将看到支持的语言列表。如果Javascript / jQuery就是其中之一,你会认为他们会给你一个例子。

enter image description here

我认为您需要使用服务器端语言来请求来自它们的数据。我认为你不能使用AJAX。如果您使用的是PHP,则可以使用CURLfileGetContents()。我在下面粘贴了一个PHP示例,可以在GitHub上找到。

PHP示例

<?php
define('CONSUMER_KEY', '[YOUR CONSUMER KEY]');
define('CONSUMER_SECRET', '[YOUR CONSUMER SECRET]');
define('REDIRECT_URI', '[YOUR REDIRECT URI]');

class MixiGraphAPIExample
{
    const MIXI_API_ENDPOINT = 'http://api.mixi-platform.com/2';
    const MIXI_TOKEN_ENDPOINT = 'https://secure.mixi-platform.com/2/token';

    private $token;

    public function __construct($auth_code) {
        $this->authorize($auth_code);
    }

    private function post($uri, $data) {
        $context = array('http' => array (
            'method' => 'POST',
            'header' => 'Content-Type: application/x-www-form-urlencoded',
            'content' => http_build_query($data, null, '&'),
            'ignore_errors' => true,
        ));
        $body = file_get_contents($uri, false, stream_context_create($context));
        $header = $this->parseHeader($http_response_header);
        if ($this->isHttpFail($header['Status'])) {
            throw new UnexpectedValueException('Post Request Fail:'.PHP_EOL.$uri.PHP_EOL.var_export($header, true));
        }
        return $body;
    }

    private function authorize($auth_code) {
        $data = array(
             'grant_type' => 'authorization_code',
             'client_id' => CONSUMER_KEY,
             'client_secret' => CONSUMER_SECRET,
             'code' => $auth_code,
             'redirect_uri' => REDIRECT_URI,
        );
        $this->token = json_decode($this->post(self::MIXI_TOKEN_ENDPOINT, $data), true);
    }

    private function refreshToken() {
        $data = array(
            'grant_type' => 'refresh_token',
            'client_id' => CONSUMER_KEY,
            'client_secret' => CONSUMER_SECRET,
            'refresh_token' => $this->token['refresh_token'],
        );
        $this->token = json_decode($this->post(self::MIXI_TOKEN_ENDPOINT, $data), true);
    }

    private function parseHeader($headers) {
        $statusLine = array_shift($headers);
        list(, $result['Status'], ) = explode(' ', $statusLine);
        foreach ($headers as $header) {
            list($key, $value) = explode(': ', $header);
            $result[$key] = $value;
        }
        return $result;
    }

    private function isHttpFail($status) {
        return (bool)(empty($status) || ($status >= 400));
    }

    private function isExpired($headers) {
        $result = false;
        if (array_key_exists('WWW-Authenticate', $headers)) {
            if (preg_match('/expired_token/', $headers['WWW-Authenticate'])) {
                $result = true;
            }
        }
        return $result;
    }

    private function call($location) {
        static $retry_count = 0;

        $uri = self::MIXI_API_ENDPOINT . $location . '?oauth_token=' . $this->token['access_token'];
        $response = file_get_contents($uri, false, stream_context_create(array('http' => array('ignore_errors' => true))));
        $header = $this->parseHeader($http_response_header);

        if ($this->isHttpFail($header['Status'])) {
            if ($this->isExpired($header)) {
                if ($retry_count++ > 1) {
                    throw new RangeException('Token Refresh Too many retry. '.PHP_EOL.var_export($this->token, true).PHP_EOL.var_export($header, true));
                }

                $this->refreshToken();
                $response = $this->call($location);
                $retry_count = 0;
            } else {
                throw new UnexpectedValueException('Invalid API Access:'.PHP_EOL.$uri.PHP_EOL.var_export($header, true));
            }
        }

        return $response;
    }

    public function execute($endpoint) {
        return json_decode($this->call($endpoint), true);
    }

    public static function getInstance($auth_code) {
        return new self($auth_code);
    }
}

if (debug_backtrace()) return;
if ($_SERVER['argc'] != 2) {
    exit("Please input your Authorization Code\n Usage : {$_SERVER['argv'][0]} [YOUR AUTHORIZATION CODE]\n");
}

try {
    $response = \MixiGraphAPIExample::getInstance($_SERVER['argv'][1])->execute('/people/@me/@self');
    var_dump($response);
} catch (Exception $e) {
    var_dump($e->getMessage());
}