Ajaxは奥が深い。仕事でWEBアプリ開発する中で、クロスドメインで苦労したので忘備録として記録しておく。
1.Ajaxとは?
まずはAjax。実は、今までAjaxをそこまで理解していなかった。(同期通信でデータ取ってくる業務システム開発ばかりだったこともあるかも。)jqueryで書くと簡単ですね。
【Ajax】
① Asynchronous Javascript + XML の略。
② ページを遷移することなく、動的にページの一部を置き換えることが可能な技術
サンプル描いて見ました。
jqueryで書くと簡単なんですが、今回はあえてNativeで。
<script>
window.onload = function () {
var xhr = new XMLHttpRequest();
xhr.addEventListener('loadend', function () {
if (xhr.status === 200) {
console.log(xhr.response);
} else {
console.error(xhr.status + ' ' + xhr.statusText);
}
});
xhr.open('GET', 'http://localhost:3000/api/test/');
xhr.send(null);
}
</script>
●XMLHttpRequestは、「HTTPプロトコルを使用して通信し、テキスト形式やXML形式のデータを送受信するオブジェクト」普段はjqueryで書いちゃっているけど、内部的に何をやっているかは実際に書いてみないとわかんないし、実際のリファレンス見るの大事ですね。
《参考》XMLHttpRequest - Web API インターフェイス | MDN
https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest
2.クロスドメイン制約とは?
簡単なサンプルを作ってみました。構成はこんな感じ。
【フロント】
HTML5 + JavascriptでAjaxを実装。後述の簡易APIサーバーにGETリクエスト
を送っています。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<script>
window.onload = function () {
// HTTPプロトコルを使用して通信し、テキスト形式やXML形式のデータを送受信するオブジェクト
var xhr = new XMLHttpRequest();
xhr.addEventListener('loadend', function () {
if (xhr.status === 200) {
console.log(xhr.response);
} else {
console.error(xhr.status + ' ' + xhr.statusText);
}
});
xhr.open('GET', 'http://localhost:3000/api/test/');
xhr.send(null);
}
</script>
</body>
</html>
【サーバーサイド】
《参考》サルでも分かるExpressでのjsonAPIサーバーの作り方
https://qiita.com/leafia78/items/73cc7160d002a4989416
Node.js とExpressで簡易APIサーバーを作成。特にDBとかは用意してません。
URLにアクセスしたら、jsonを返すだけの簡単なコード。ほぼ参考リンクのサンプル通りです。
api
┣ app.js
┣ package.json
// ライブラリ読み込み
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
//body-parserの設定
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
var port = process.env.PORT || 3000; // port番号を指定
// GET http://localhost:3000/api/test/
app.get('/api/test/',function(req,res){
res.json({
message:"Hello,world"
});
});
//サーバ起動
app.listen(port);
console.log('listen on port ' + port);
htmlをブラウザで開いた瞬間にAjaxが実行されるようになっているので、
本来ならばapiの結果が返ってくるはずなんですが。このようなエラーが。
何だろ?と思って調べると、XMLHttpRequestの呼び出しは、同一ドメインからしかできないようになっているとのこと。フロントエンドとバックエンドを異なるアプリケーションでデバッグする場合、同一のポート番号は使用できないため、異なるoriginと認識され、エラーとなってしまいました。
※クロスオリジンの制約は、ブラウザのアドレスバーに表示される URL と JavascriptからアクセスさるURLを比べて、プロトコル、ドメイン、ポート のどれかが違えば別のオリジンということになるそうです。ドメインが同じでも片方だけ https だったり、ポート番号が違う場合は別のオリジンと判断されるみたい。
参考サイトをたくさん貼っておきます。
《参考》
【解説付き】chromeでXMLHttpRequestをローカルのファイルで行う方法
https://qiita.com/growsic/items/a919a7e2a665557d9cf4クロスドメインアクセスを理解してWeb APIを楽しく使おう - SlideShare
https://www.slideshare.net/kitfactory/web-api-34814937
これを知らなくて、ドメイン違いのAjax通信を実装してしまって苦労しました。。