クロスオリジンアクセス

提供: svg2wiki
移動: 案内, 検索

ビットイメージの地図レイヤーに図法変換が必要な場合や、XMLHttpRequestやfetchなどでwebappのあるサイトと異なるドメインにあるウェブサービス(webapi)にアクセスする場合、クロスオリジンアクセス制限によるエラーが起きる場合があります。このエラーはWebApp側だけでは解決できず、サーバ側の設定を調整する必要があります。

目次

エラーの確認方法

ウェブブラウザでSVGMapのページを開き、開発ツールのコンソールもしくはネットワーク画面からエラーが確認できます。(blocked by CORS policyなどといったメッセージが出ます)

サーバ(サービス側での対処): CORSレスポンスヘッダを返すように設定する

  • Access-Control-Allow-Origin *(もしくは指定オリジン)のレスポンスヘッダを返すようにサーバを設定します。
  • 外部からのアクセスを想定し 整備されたサービスでは、この設定がされており 下記プロキシの利用は不要です。

プロキシサービスを用意し これを経由させる

プロキシ経由のクロスオリジンアクセスを容易にするためのSVGMap.jsの支援機能

プロキシ経由のクロスオリジンアクセスの対応を容易にするためのいくつかの機能がSVGMap.jsに備わっています。

SVGMap.jsがクロスオリジンアクセスを必要とするケースは主に3つあります。

  1. ビットイメージ(含タイル)データの図法変換
  2. ラスターGIS
  3. webAppレイヤーでの独自の通信

1.と2.はSVGMap.jsの管理下でクロスオリジンアクセスを行う必要があるもので、SVGMap.jsの初期化時にクロスオリジンアクセスのための設定(クロスオリジンアクセスのためのプロキシの設定)を行うAPIが用意されています。

これらのAPIを用いた初期化の例は次章で説明します。

WebApp Layerにおけるクロスオリジンアクセス

一方、3.は各レイヤーのwebApp(webApp Layer)が、レイヤーのコンテンツを生成するためのデータ(例えばjson形式の独自データ)を取得するときに(fetchやXMLHttpRequest等を使い)クロスオリジンアクセスするケースで、厳密にはSVGMap.jsが関与しない処理です。このようなクロスオリジンアクセスに対するケアは、基本的に個々のレイヤーwebAppの開発者が行う必要があります。
しかしプロキシ経由のアクセスを行う場合、先の1.2.のケース用に使用するプロキシを全レイヤー共通のプロキシとしても利用する場合が考えられ、この時にはSVGMap.jsの初期化で設定したプロキシを共通の関数で呼び出せる関数が用意されています。

getCORSURLの使用法は後の章で紹介します。

SVGMap.jsの初期化

  • 先述の機能を用いて、容易にクロスオリジンアクセスを可能にするためのルートHTML文書の初期化手順を紹介します。corsProxy.jsは次章参照
    • ルートHTML文書の完全な実装例 : GitHub 

<!doctype html>
<html>
...
<script src="corsProxy.js"></script> <!-- クロスオリジンアクセス用プロキシライブラリ(下記) -->
<script src="SVGMapLv0.1_r17.js"></script>
...
<script>
var proxyPath = "{セットアップしたCORS AnywhereのURL}"; // CORS anywhere for svgmap.org / service.svgmap.org
corsProxy.setService(proxyPath, null, true,false);
svgMap.setProxyURLFactory(null,null,null, corsProxy.getURL,true);
</script>
...
</html>


corsProxy.js

初期化を容易に行うためのライブラリをご紹介します。gitHub

  • corsProxy.setService(pxUrl , directURLls , useAnonProxy, requireEncoding)
    • pxUrl : プロキシのURL
    • directURLls : [プロキシを使用しないURLのリスト]
    • useAnonProxy : anonymous属性を付与するかどうか
    • requireEncoding : プロキシサービスに渡すURLをURLエンコードするかどうか
  • corsProxy.getURL(プロキシに取得させるURL)

var corsProxy = (function(){
	var proxyUrl="";
	var anonProxy = false;
	var directURLlist = [];
	var noEncode=true;
	function setImageProxy( pxUrl , directURLls , useAnonProxy, requireEncoding){
		if ( requireEncoding ){
			noEncode = false;
		}
		proxyUrl = pxUrl;
		if ( directURLls ){
			directURLlist = directURLls;
		} else {
			directURLlist = [];
		}
		if ( pxUrl.indexOf("http")==0){
			var pxDomain = pxUrl.substring(0,pxUrl.indexOf("/",8));
			directURLlist.push(pxDomain);
		}
		
		if ( useAnonProxy ){
			anonProxy = true;
		} else {
			anonProxy = false;
		}
	}
	
	function isDirectURL(url){
		// urlに、directURLlistが含まれていたら、true 含まれていなかったらfalse
		var ans = false;
		for ( var i = 0 ; i < directURLlist.length ; i++ ){
			if ( url.indexOf(directURLlist[i])>=0){
				ans = true;
				break;
			}
		}
		return ( ans );
	}
	
	function getImageURL(imageUrl){
		// ローカル(同一ドメイン)コンテンツもしくはそれと見做せる(directURLlistにあるもの)もの以外をproxy経由のURLに変換する
		// proxyの仕様は、 encodeURIComponent(imageUrl)でオリジナルのURLをエンコードしたものをURL末尾(もしくはクエリパート)につけたGETリクエストを受け付けるタイプ
		if ( proxyUrl && imageUrl.indexOf("http") == 0){
			if (isDirectURL(imageUrl)){
				// Do nothing (Direct Connection)
			} else {
				if ( noEncode ){
					imageUrl = proxyUrl + (imageUrl);
				} else {
					imageUrl = proxyUrl + encodeURIComponent(imageUrl);
				}
//				console.log("via proxy url:",imageUrl);
			}
		} else {
			// Do nothing..
		}
		return (imageUrl);
	}
	return {
		setService:setImageProxy,
		getURL:getImageURL,
	}
})();


webAppレイヤーでのクロスオリジンアクセス

クロスオリジンアクセスのためのSVGMap.jsの初期化がなされた状態のルートHTML文書(SVGMapページ)に登録されている各レイヤーのwebAppsでは、getCORSURL APIを使用することができます。

このAPIは、アクセスしたいサービスのURLに対して、共通で準備されたクロスオリジンアクセス用サーバを経由したアクセスを可能にするURLが得られる機能で、たとえば以下のように利用します。

var dataResponse = await fetch( svgMap.getCORSURL( serviceURL ) );


一方、もしクロスオリジンアクセスの初期化をしていないルートHTML文書(SVGMapページ)では、各レイヤーのwebAppsが独自にクロスオリジンアクセスの解決を行う必要があります。例えば、クロスオリジンアクセス用のプロキシとしてhttps://[myproxy.mydomain.com]/proxy/ というプロキシが用意されており、?targetURL=serviceURL というクエリパラメータでアクセス先のサービスにアクセスする場合は、以下のようになるでしょう。

var dataResponse = await fetch( "https://[myproxy.mydomain.com]/proxy/?targetURL=" + serviceURL );

個人用ツール
名前空間

変種
操作
案内
ツール
Translate