JS:クロスドメインでAjax通信

JS:クロスドメインでAjax通信

author : koki

publish date :

Ajax通信する際、自分のサイト内のファイルへアクセスすることが多いと思いますが、違うドメインからもファイルを読み込みたい時があると思います。
そこで問題となってくるのが、ブラウザに実装されているクロスドメイン制約です。
クロスドメイン制約とは、ブラウザの機能で、閲覧しているページのドメイン以外のドメインからはAjax通信をさせないという機能です。

クロスドメイン制約を迂回するには3通りの方法があります。

Access-Control-Allow-Originを設定する

Access-Control-Allow-Originを設定するにはサーバーサイドでの設定が必要です。
読み込みたいファイルが置いてあるサーバーを自分で管理している場合は、.htaccessやPHPなどのプログラムなどでCORS(クロスオリジンリソースシェアリング、Cross-Origin Resource Sharing)の設定を変更します。

全てのサイトからのアクセスを許可する場合

.htaccessで設定をする場合

<IfModule mod_headers.c>
	Header set Access-Control-Allow-Origin: "*"
</IfModule>

PHPで設定をする場合

<?php
header('Access-Control-Allow-Origin: *');
?>

特定のサイトからのアクセスのみを許可する場合

.htaccessで設定をする場合

<IfModule mod_headers.c>
	Header set Access-Control-Allow-Origin: "http://www.example.com"
</IfModule>

PHPで設定をする場合

<?php
header('Access-Control-Allow-Origin: http://www.example.com');
?>
アクセス可能となるサイト
  • 自分のサイト
  • http://www.example.com

特定の複数のサイトからのアクセスを許可する場合

.htaccessで設定をする場合

<IfModule mod_headers.c>
	SetEnvIf Origin "^http(s)?://(www¥.example¥.com|www¥.example2¥.com)$" http_origin=$0
	Header always set Access-Control-Allow-Origin %{http_origin}e env=http_origin
</IfModule>

PHPで設定をする場合

<?php
$http_origin = $_SERVER['HTTP_ORIGIN'];
preg_match('/http(s)?:¥/¥/(www¥.example¥.com|www¥.example2¥.com)/', $http_origin, $matches);
if(count($matches) > 0){
	header('Access-Control-Allow-Origin: '.$http_origin);
}
?>
アクセス可能となるサイト
  • 自分のサイト
  • http://www.example.com
  • http://www.example2.com

特定のサイトの全てのサブドメインからのアクセスを許可する場合

.htaccessで設定をする場合

<IfModule mod_headers.c>
	SetEnvIf Origin "^(.*¥.example¥.com)$" http_origin=$0
	Header set Access-Control-Allow-Origin "%{http_origin}e" env=http_origin
</IfModule>

PHPで設定をする場合

<?php
$http_origin = $_SERVER['HTTP_ORIGIN'];
preg_match('/^.*¥.example¥.com$/', $http_origin, $matches);
if(count($matches) > 0){
	header('Access-Control-Allow-Origin: '.$http_origin);
}
?>
アクセス可能となるサイト
  • 自分のサイト
  • example.comの全てのサブドメイン

JSONPとして扱う

JSONファイルの場合のみで使える手ですが、JSONPとして読み込ませてクロスドメイン制約を迂回することができます。
JSONPとして扱う場合も読み込みたいファイルが置いてあるサーバーサイドの変更が必要です。

$outputに配列形式のデータが入るようにして、下記のように出力してください。

PHPコード

jsonp.php

<?php
$jsoncode = json_encode($output);
header('Content-Type: application/json; charset=utf-8');
if(isset($_GET['callback'])){
	echo $_GET['callback'] . '(' . $jsoncode . ')';
}else{
	echo $jsoncode;
}
?>

jQueryコード

ajax.js

jQuery(function($){
	var jsonURL = 'http://www.example.com/jsonp.php';
	var xhr = $.ajax({
		url: jsonURL,
		type: 'GET',
		dataType: 'jsonp',
		timeout: 30000
	});
	xhr.success(function(res){
		$('body').append('通信成功');
	});
	xhr.error(function(res){
		$('body').append('通信失敗');
	});
	xhr.complete(function(res){
	});
});

プログラムを経由させる

この方法が唯一、読み込みたいファイルが置いてあるサーバーの管理者でなくてもクロスドメイン制約を迂回できる方法です。

ajax.phpへAjax通信させるとブラウザは同じドメインへアクセスすることになるので、クロスドメイン制約を迂回することができます。

PHPコード

ajax.php

<?php
if(isset($_GET['url']) && preg_match('/^http(s)?:/', $_GET['url'])){
	echo file_get_contents($_GET['url']);
}
?>

JavaScriptコード

ajax.js

jQuery(function($){
	var targetURL = '/ajax.php?url=http://www.example.com/ajax.csv';
	var xhr = $.ajax({
		type: 'GET',
		url: targetURL,
		dataType: 'text',
		timeout: 30000
	});
	xhr.success(function(res){
		$('body').append('通信成功');
	});
	xhr.error(function(res){
		$('body').append('通信失敗');
	});
	xhr.complete(function(res){
	});
});

以上の3つの迂回方法で、快適なweb開発を!