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開発を!