クロスドメインでめちゃくちゃハマった話

Ajaxは奥が深い。仕事でWEBアプリ開発する中で、クロスドメインで苦労したので忘備録として記録しておく。

#1.Ajaxとは？
まずはAjax。実は、今までAjaxをそこまで理解していなかった。（同期通信でデータ取ってくる業務システム開発ばかりだったこともあるかも。）jqueryで書くと簡単ですね。

<b>【Ajax】</b>
① Asynchronous Javascript + XML の略。
② ページを遷移することなく、動的にページの一部を置き換えることが可能な技術

サンプル描いて見ました。
jqueryで書くと簡単なんですが、今回はあえてNativeで。


``` html
   <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リクエスト
を送っています。

```html

<!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
```

```javascript

// ライブラリ読み込み
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の結果が返ってくるはずなんですが。このようなエラーが。

![No 'Access-Control-Allow-Origin' header.png](https://qiita-image-store.s3.amazonaws.com/0/173505/ff033b59-cd68-b4a1-17ad-b035510d647c.png)

何だろ？と思って調べると、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通信を実装してしまって苦労しました。。