LoginSignup
4
4

More than 5 years have passed since last update.

TableauWDCで CORSを回避する方法(超意訳)

Last updated at Posted at 2018-06-28

WDCをやっていると必ずと行っていいほど起きる問題が、CORS(cross-origin resource sharing)のようです。
それの対策について、まとまっていたので、つたないですが超意訳(?)してみます。


WDCではJavaScriptのコードで実装されていて、実際にこのコードが配置されるサーバ(ドメイン)とは別のWebサーバにAPIリクエストをして、データを取得する場合がほとんどと思います。
これはすなわちCORS(cross-origin resource sharing)と呼ばれるものですが、セキュリティ上、ブラウザはこのCORSを制限しています(特にChromeとか)
※WDCでは、Tableauの内部ブラウザを使っているので、CORSを回避するChromeのプラグインは利用できない・・・

CORS制限のために、ブラウザのコンソールに下記のようなエラーが出ると思います

XMLHttpRequest cannot load URL. No 'Access-Control-Allow-Origin' header is present on the requested resource.

このエラーを回避するのにいくつかの方法があるのでそちらを説明します

  • ローカルにプロキシを立てる(Make requests through a proxy server)
  • 利用するAPIサーバにCORSを許可するようにお願いする(Request CORS support from API Server)
  • JSONPをつかってAPIへリクエストを送る(Make requests with JSONP)

※注釈 Debugging in the Simulator and Tableau) でデバッグの方法が書いてますが、その中にもCORSのエラーについては書いてあるっぽい

ローカルにプロキシを立てる(Make requests through a proxy server)

ブラウザのCORS制限を回避するために、プロクシサーバを立てて、それを経由して、リクエストを送る方法があります。プロキシーは単純にデータを取得するだけの動きをします(データ加工などは一切しない)
このプロキシはブラウザで動くわけではないので、ブラウザのCORS制限には引っかからないのです

データの取得先のドメインが、WDCサーバと同じならCORS問題は起きませんが、別ドメインからのデータ取得だとCORS問題がおきます。
もしプロキシサーバのドメインが別なら、そのプロキシサーバで Access-Control-Allow-Origin をヘッダにセットすれば動きます。

WDCSDK には、そのまま使えるプロキシサーバが設定されています。

webdataconnectorのリポジトリの第一階層で、下記のコマンドをTerminalなどで打ちます。

npm start

これで、テストサーバとテストプロキシサーバが起動します

プロキシは下記のURLになる

http://localhost:8889

例えば earthquakeUSGS のコネクタの場合, $.getJSON の記載は

$.getJSON("http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_week.geojson"

となってますが、こちらを

$.getJSON("http://localhost:8889/earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_week.geojson"

と変更することで、プロクシ経由でCORS制限を回避してアクセスできます。
重要: httpのみしか対応してない。
※httpsのAPIにアクセスする場合は、 Tableau WDCの「Allow-Control-Allow-Origin: *」問題を回避してみるを参考にしてみてください。

フリーのプロキシ にはこんなのがある(らしい)。こちらを使うのも手

利用するAPIサーバにCORSを許可するようにお願いする

Access-Control-Allow-Origin をヘッダにつけてもらうようにAPI提供先にお願いする
(それで解決できるならこれが一番だとは思うが!)

JSONPを使う

CORS対策をしていないサーバでも、JSON with padding もしくは JSONP でデータが取得できる場合が多くあります。直接JavaScriptを使うとブロックされてていても、JSONPを使えば可能(?)
その代わりに、JavaScriptを使用して <script> 要素を動的に作成または更新し、src属性をデータを持つサイトを指すURLに設定します。URLには、コネクタページにあるコールバック関数の名前も含まれています。サイトがJSONPをサポートしている場合、レスポンスにはJSON形式のデータが含まれており、コールバック関数の呼び出しで「パディング」されます。

Webデータ・コネクターでjQueryを使用する場合は、ajax関数を使用してJSONP呼び出しを行うことができます。詳細は、jQueryサイトのjQuery.ajax()を参照してください。

jQueryを使用していない場合は、JavaScriptコードでJSONPを実装できます。たとえば、コネクタに次のJavaScriptコードが含まれていると、<script>要素が動的に作成され、src属性が架空のURLに設定されます。

var scriptTag = document.createElement('script');
scriptTag.src = "http://myserver/temperatures?city=Seattle&year=2014&callback=getTemperatures";
document.getElementsByTagName('head')[0].appendChild(scriptTag);

コネクタには、サイトが返す「埋め込まれた」JSONによって呼び出される次の関数も含まれている必要があります。 JSONデータはjsonpDataパラメータとして関数に渡され、関数内のコードはJSONブロックの場合と同じように値を抽出できます。


var getTemperatures = function(jsonpData) {
        alert(jsonpData.someProperty);
        // More code here to extract the JSON data
    }

参考 

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4