Help us understand the problem. What is going on with this article?

CORS:クロスドメインなAjaxでJSON / JSONPの各種ブラウザ対応まとめ

More than 1 year has passed since last update.

忘れてしまうのでまとめておく。

気をつけること

  • 基本的に jsonp であれば動く
  • json + モダンブラウザは、Access-Control-Allow-Originを設定すれば動く
  • json + IE8,9では、XDomainRequestを使えば動く
  • IE6,7は死亡(もういいよね)
  • プロトコル(http|https) / FQDN / ポート番号、いずれかが違う場合、クロスドメイン
  • BASIC認証があると、別途対応が必要(後述)

JSON編

サーバサイド

jsonを返すサーバ側にAccess-Control-Allow-Originを設定する。

<?php
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');

    // CakePHPの場合
    $this->header('Access-Control-Allow-Origin: *');
    $this->header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');

BASIC認証をしている場合

クレデンシャルを許可するといけるが、Originにワイルドカードは指定できない。

<?php
    header('Access-Control-Allow-Origin: http://example.com');
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization');

クライアントサイド

jQuery版

ajax.js
// IE8,9でXMLHttpRequestの代わりにXDomainRequestを使う
(function( jQuery ) {

if ( window.XDomainRequest ) {
    jQuery.ajaxTransport(function( s ) {
        if ( s.crossDomain && s.async ) {
            if ( s.timeout ) {
                s.xdrTimeout = s.timeout;
                delete s.timeout;
            }
            var xdr;
            return {
                send: function( _, complete ) {
                    function callback( status, statusText, responses, responseHeaders ) {
                        xdr.onload = xdr.onerror = xdr.ontimeout = xdr.onprogress = jQuery.noop;
                        xdr = undefined;
                        complete( status, statusText, responses, responseHeaders );
                    }
                    xdr = new XDomainRequest();
                    xdr.open( s.type, s.url );
                    xdr.onload = function() {
                        callback( 200, "OK", { text: xdr.responseText }, "Content-Type: " + xdr.contentType );
                    };
                    xdr.onerror = function() {
                        callback( 404, "Not Found" );
                    };
                    xdr.onprogress = function() {};
                    if ( s.xdrTimeout ) {
                        xdr.ontimeout = function() {
                            callback( 0, "timeout" );
                        };
                        xdr.timeout = s.xdrTimeout;
                    }
                    xdr.send( ( s.hasContent && s.data ) || null );
                },
                abort: function() {
                    if ( xdr ) {
                        xdr.onerror = jQuery.noop();
                        xdr.abort();
                    }
                }
            };
        }
    });
}
})( jQuery );

jQuery.getJSON('http://example.com/search.json',
    {
        'hoge': 'piyo'
    },
    function (data) {
        console.log(data);
    }
});

参照 : https://github.com/tlianza/ajaxHooks/blob/master/src/ajax/xdr.js

JavaScript版

ajax.js
function createCORSRequest(method, url) {
    var xhr = new XMLHttpRequest();
    if ("withCredentials" in xhr) {
        xhr.open(method, url, true);
    } else if (typeof XDomainRequest != "undefined") {
        xhr = new XDomainRequest();
        xhr.open(method, url);
    } else {
        xhr = null;
    }
    return xhr;
}

var xhr = createCORSRequest('GET', 'http://example.com/search.json');
if (!xhr) {
    throw new Error('CORS not supported');
}
xhr.onload = function(){};
xhr.onerror = function(){};
xhr.send();

参照 : http://www.html5rocks.com/en/tutorials/cors/

JSONP編

jsonpの場合、サーバサイドではjsonp形式で返すだけで特に設定は必要ない。ただし、jsonと違いJavaScriptのコードをクライアントサイドで直接実行するため、jsonpの提供APIに悪意のあるコードが含まれていた場合は恐ろしいことになる。callbackで指定できるパラメータを制限するなど、ある程度の工夫が必要。

クライアントサイド

jQuery版

ajax.js
jQuery.getJSON('http://example.com/search.json?callback=?',
    {
        'hoge': 'piyo'
    },
    function (data) {
        console.log(data);
    }
});

calback=?とすることで、jQueryが勝手にコールバック名を生成してアクセスしてくれる。

JavaScript版

ajax.js
var target = document.createElement('script');
target.charset = 'utf-8';
target.src = 'http://example.com/search.json?callback=hoge';
document.body.appendChild(target);

function hoge(result) {
    console.log(result);
}
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away