No 'Access-Control-Allow-Origin' header is present on the requested resource. /  CORSを回避するテストサーバーをNode.jsで立ててみた


[Livedoor の お天気Webサービス API は、JSON のテストするのに重宝しています。](http://ginpro.winofsql.jp/article/419510275.html)の記事の通り、Livedoorのお天気WebサービスAPIは簡単にAjax通信を試すときに役立っています。

> http://weather.livedoor.com/weather_hacks/

普段はNode.jsからのアクセスしか試さないのですが、最近ブラウザ側(jQuery)からアクセスするときがあって見事にCORSでハマりました。タイトル通り。(CORS回避なのか対策なのか言葉の使い方曖昧ですが)

ということで`Access-Control-Allow-Origin`を回避するサーバーを立ててみました。
あくまでもAPIのテスト目的です。

## エンドポイント

http://cors-allow.azurewebsites.net

(しばらくは起動してると思いますが、メンテはしない予定)

> Azure Web Appsのフリープランで立ててます

## 使い方

urlパラメータに利用するAPIのアドレスを追加してGETリクエストします。

* http://cors-allow.azurewebsites.net/?url=<使うAPIのアドレス>

例: http://cors-allow.azurewebsites.net/?url=http://weather.livedoor.com/forecast/webservice/json/v1?city=030010

## jQueryから使ってみる

コピペで動くと思います。 

> 執筆時はChrome 58

```index.html
<html>
    <head></head>
    <body>
        <script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
        <script>
            'use strict';

            const AREA = `030010`; //盛岡市の天気
            let target = `http://weather.livedoor.com/forecast/webservice/json/v1?city=${AREA}`;
            target = `http://cors-allow.azurewebsites.net/?url=${target}`;
            $.ajax({
                url: target,
                data: 'json'
            })
            .done((res) => {
                console.log(res);
            });
        </script>
    </body>
</html>
```

![](https://i.gyazo.com/f8b29847af6eefb877e70844c7b37082.png)

### ※ちなみに 通常だとエラーが出ます

cros-allow.azurewebsite.net側には向けてる部分をコメントアウトして、通常アクセスにしてみるとエラーです。

```index.html
<html>
    <head></head>
    <body>
        <script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
        <script>
            'use strict';

            const AREA = `030010`;
            let target = `http://weather.livedoor.com/forecast/webservice/json/v1?city=${AREA}`;
            // target = `http://cors-allow.azurewebsites.net/?url=${target}`;
            $.ajax({
                url: target,
                data: 'json'
            })
            .done((res) => {
                console.log(res);
            });
        </script>
    </body>
</html>
```

`No 'Access-Control-Allow-Origin' header is present on the requested resource.`

![](https://i.gyazo.com/a1f737358a29ef0c8dbd54aa643207c3.png)



## 一応、中身

expressとaxiosを使ったうすいサーバーです。
Node.js v8.0

```server.js
'use strict';

const axios = require('axios');
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser());

const PORT = process.env.PORT || 3000;

// CORSを許可する
app.use((req, res, next) => {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

app.get('/', (req, res) => {
  if(!req.query.url){
    const result = {
      error: 'You must parameter -> /?url=<API Address>'
    };
    res.send(result);
    return;
  }
  
  axios.get(req.query.url)
  .then((result) => {
    console.log(result);
    res.send(result.data);
  }).catch((err) => {
    console.error(err.response);
    console.error(err.response.data);
    const result = {
      error: {
        status: err.response.status,
        statusText: err.response.statusText
      }
    };
    res.send(result);
  });
});

app.listen(PORT);
console.log(`Server running at ${PORT}`);
```

##ちなみに

このchromeエクステンションを使うとこんなことやらなくてもテストできたりします。参考までに

`Allow-Control-Allow-Origin: *`っていう名前です。そのまま笑

https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi

### 追記: WebAppsの機能

WebAppsの機能にCORSの制御があるみたいなので、アプリケーション側で`Access-Control-Allow-Origin: *`を指定しなくても、こちらの設定だけでもいけるかも。

![](https://i.gyazo.com/e428aac4e8a80a7785ca7f3a315c5275.png)