JavaScript で AJAX を多く使ったことがある人にとって、「クロスドメイン問題」は一度は体験する、避けて通れない問題だと思います。
簡単に補足すると、例えば異なる aaa.com と bbb.net という2つのドメイン間で AJAX の実行を許可しない、という問題です。以下の例では aaa.com ドメイン内に www.aaa.com というアプリケーションサーバーと、api.aaa.com という API サーバーがあり、bbb.net というドメイン内に api.bbb.net という API サーバーがあることを想定しています。www.aaa.com と api.aaa.com は同一ドメインなので、何の制約もなく AJAX で API を実行できるのですが、ドメインの異なる api.bbb.net に用意された API を www.aaa.net から AJAX で実行しようとすると、このクロスドメイン問題の制約に引っかかって実行できない、というものです:

ちなみにこのクロスドメインの制約はあくまで「ウェブブラウザの制約」です。ドメインをまたいだ API を実行するような JavaScript はウェブブラウザが許可しない、という意味です。なので、例えば www.aaa.com 上の Java アプリケーションや PHP アプリケーション、はたまたサーバーサイド JavaScript である Node.js アプリケーションなどから api.bbb.net 上の API を実行する、という場合は何の制約もなく動きます。
またこの問題は api.bbb.net 側で「他のドメインからの AJAX 実行を許可する」という設定をしておけば回避することができます。具体的には API サーバーの HTTP レスポンスヘッダに Access-Control-Allow-Origin を含めるようにして、そこに "*"(どこからでも許可する)とか "*.aaa.com" (aaa.com からのリクエストは許可する)とかいった値が返されるような設定になっていれば使える、ということです(つまり API 側で許可するよう設定されている必要があります):

さて、先日 curl で IBM Watson の Visual Recognition API (画像認識 API)を使っていてふと気付いたことがあります。curl は -i オプションを使うと HTTP レスポンスヘッダが表示されるようになるので、これを ON にしてデバッグしていました・・・:

ん??

上記で説明した "Access-Control-Allow-Origin" が HTTP レスポンスヘッダに含まれてます。しかも値が * ということは、この API はどこからでも AJAX で呼べるということ!?
以前にこの記事を作ってた頃は、このヘッダはなかったと記憶してる(Chrome Extension なので回避できている、という認識でした)。いつ仕様が変わったんだろ・・・
試しに、curl で実行したのと同様の Visual Recognition API を実行する HTML ファイルを作ってみました(実行する場合、ソースコード内の (APIKEY) 部分は自分の Visual Recognition API サービスインスタンスの API キーを指定してください:
これをウェブブラウザからローカルファイル扱いで開き(URL は file:/// で始まる)、画像 URL をテキストボックスに入れて classify ボタンをクリックします。すると・・・

↑ 全く異なるドメイン(というかローカルファイルシステム)からの HTTP リクエストであるにも関わらず、AJAX 内で呼び出している Visual Recognition API が正しく実行され、画像認識結果を表示することができました。こりゃ便利!
簡単に補足すると、例えば異なる aaa.com と bbb.net という2つのドメイン間で AJAX の実行を許可しない、という問題です。以下の例では aaa.com ドメイン内に www.aaa.com というアプリケーションサーバーと、api.aaa.com という API サーバーがあり、bbb.net というドメイン内に api.bbb.net という API サーバーがあることを想定しています。www.aaa.com と api.aaa.com は同一ドメインなので、何の制約もなく AJAX で API を実行できるのですが、ドメインの異なる api.bbb.net に用意された API を www.aaa.net から AJAX で実行しようとすると、このクロスドメイン問題の制約に引っかかって実行できない、というものです:

ちなみにこのクロスドメインの制約はあくまで「ウェブブラウザの制約」です。ドメインをまたいだ API を実行するような JavaScript はウェブブラウザが許可しない、という意味です。なので、例えば www.aaa.com 上の Java アプリケーションや PHP アプリケーション、はたまたサーバーサイド JavaScript である Node.js アプリケーションなどから api.bbb.net 上の API を実行する、という場合は何の制約もなく動きます。
またこの問題は api.bbb.net 側で「他のドメインからの AJAX 実行を許可する」という設定をしておけば回避することができます。具体的には API サーバーの HTTP レスポンスヘッダに Access-Control-Allow-Origin を含めるようにして、そこに "*"(どこからでも許可する)とか "*.aaa.com" (aaa.com からのリクエストは許可する)とかいった値が返されるような設定になっていれば使える、ということです(つまり API 側で許可するよう設定されている必要があります):

さて、先日 curl で IBM Watson の Visual Recognition API (画像認識 API)を使っていてふと気付いたことがあります。curl は -i オプションを使うと HTTP レスポンスヘッダが表示されるようになるので、これを ON にしてデバッグしていました・・・:

ん??

上記で説明した "Access-Control-Allow-Origin" が HTTP レスポンスヘッダに含まれてます。しかも値が * ということは、この API はどこからでも AJAX で呼べるということ!?
以前にこの記事を作ってた頃は、このヘッダはなかったと記憶してる(Chrome Extension なので回避できている、という認識でした)。いつ仕様が変わったんだろ・・・
試しに、curl で実行したのと同様の Visual Recognition API を実行する HTML ファイルを作ってみました(実行する場合、ソースコード内の (APIKEY) 部分は自分の Visual Recognition API サービスインスタンスの API キーを指定してください:
<html>
<head>
<title>DHTML</title>
<script src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
<script>
function classify(){
var imgurl = $('#imgurl').val();
var url = "https://gateway-a.watsonplatform.net/visual-recognition/api/v3/classify?api_key=(APIKEY)&version=2016-05-20&url=" + encodeURI( imgurl );
$.ajax({
type: "GET",
url: url,
success: function( data ){
var html = "<img src=\"" + imgurl + "\"/><br/><table border=\"1\">";
var classes = data.images[0].classifiers[0].classes;
for( i = 0; i < classes.length; i ++ ){
var obj = classes[i];
var class_name = obj['class'];
var class_score = obj['score'];
html += ( "<tr><td>" + class_name + "</td><td>" + class_score + "</td></tr>" );
}
html += "</table>";
$('#result').html( html );
},
error: function( XMLHttpRequest, textStatus, errorThrown ){
console.log( "error: " + textStatus );
}
});
}
</script>
</head>
<body>
<input type="text" name="imgurl" id="imgurl" value=""/>
<input type="button" value="classify" onClick="classify();"/>
<hr/>
<div id="result"></div>
</body>
</html>
これをウェブブラウザからローカルファイル扱いで開き(URL は file:/// で始まる)、画像 URL をテキストボックスに入れて classify ボタンをクリックします。すると・・・

↑ 全く異なるドメイン(というかローカルファイルシステム)からの HTTP リクエストであるにも関わらず、AJAX 内で呼び出している Visual Recognition API が正しく実行され、画像認識結果を表示することができました。こりゃ便利!
コメント