194
182

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2014-07-09

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

気をつけること

  • 基本的に 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);
}
194
182
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
194
182

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?