クロスオリジンアクセス

提供: svg2wiki
(版間での差分)
移動: 案内, 検索
(プロキシ経由のクロスオリジンアクセスを容易にするためのSVGMap.jsの支援機能)
(corsProxyMoule.js)
 
(1人の利用者による、間の55版が非表示)
1行: 1行:
XMLHttpRequestやfetchなどでwebappのあるサイトと異なるドメインにあるウェブサービス(webapi)にアクセスする場合、[https://developer.mozilla.org/ja/docs/Web/HTTP/CORS クロスオリジンアクセス]制限によるエラーが起きる場合があります。このエラーはWebApp側だけでは解決できず、サーバ側の設定を調整する必要があります。
+
ビットイメージの地図レイヤーに図法変換が必要な場合や、XMLHttpRequestやfetchなどでwebappのあるサイトと異なるドメインにあるウェブサービス(webapi)にアクセスする場合、[https://developer.mozilla.org/ja/docs/Web/HTTP/CORS クロスオリジンアクセス]制限によるエラーが起きる場合があります。このエラーはWebApp側だけでは解決できず、サーバ側の設定を調整する必要があります。
 +
 
 +
== 概要 ==
 +
SVGMapはハイパーレイヤリングアーキテクチャを持つため、[[解説書#フレームワークの呼び出し|ルートhtml文書]]で構成されるクライアントのSVGMapフレームワークウェブアプリは、異なるオリジンのサーバにアクセスすることが基本的に必要になります。これは一般的に「[https://developer.mozilla.org/ja/docs/Web/HTTP/CORS クロスオリジンリソース共有]」と呼ばれる処理が行われる可能性があり、この時[https://developer.mozilla.org/ja/docs/Web/HTTP/CORS/Errors ウェブブラウザのネイティブな機能によるCORSのエラー]が生じる可能性があることを意味します。
 +
 
 +
クロスオリジンアクセスのケースと、CORSのエラー発生の可能性を下表に示します。
 +
 
 +
{| class="wikitable" style="margin:auto"
 +
|+ クロスオリジンアクセスによるエラー
 +
|-
 +
! クロスオリジンアクセスするコンテンツの種類 !! コンテンツの処理 !! CORSエラー発生の可能性
 +
|-
 +
| ビットイメージ(タイルを含む) || 重ね合わせ || 発生しない
 +
|-
 +
| ビットイメージ(タイルを含む) || [[#非線形図法変換|非線形図法変換]]を伴う重ね合わせ || 発生する可能性あり
 +
|-
 +
| ビットイメージ(タイルを含む) || 地理空間情報処理等 || 発生する可能性あり
 +
|-
 +
| ベクトルデータやjson等ビットイメージ以外のデータ|| 重ね合わせ || 発生する可能性あり
 +
|-
 +
| ベクトルデータやjson等ビットイメージ以外のデータ|| 地理空間情報処理等 || 発生する可能性あり
 +
|-
 +
| 全ての種類のコンテンツ・データ || [[解説書#svgMapCesiumWrapper..E3.81.A7.E5.91.BC.E3.81.B3.E5.87.BA.E3.81.9B.E3.82.8BAPI|Cesium拡張を用いた表示]] || 発生する可能性あり
 +
|}
 +
 
 +
== エラーの確認方法 ==
 +
ウェブブラウザでSVGMapのページを開き、開発ツールのコンソールもしくはネットワーク画面からエラーが確認できます。(blocked by CORS policyなどといったメッセージが出ます)
  
 
== サーバ(サービス側での対処): CORSレスポンスヘッダを返すように設定する==
 
== サーバ(サービス側での対処): CORSレスポンスヘッダを返すように設定する==
5行: 31行:
 
** [https://phaier.github.io/school/engineering/platform/server/apache/how-to/cors.html apacheの例]
 
** [https://phaier.github.io/school/engineering/platform/server/apache/how-to/cors.html apacheの例]
 
** [https://enable-cors.org/server.html etc]
 
** [https://enable-cors.org/server.html etc]
* 外部からのアクセスを想定し 整備されたサービスでは、この設定がされており 下記プロキシの利用は不要です。
+
* 外部からのアクセスを想定し 整備されたサービスでは、この設定がされており(例:地理院地図やgitHubPagesのサイト) 下記プロキシの利用は不要です。
  
 
== プロキシサービスを用意し これを経由させる==
 
== プロキシサービスを用意し これを経由させる==
26行: 52行:
 
* [[解説書#setProxyURLFactory]]
 
* [[解説書#setProxyURLFactory]]
 
* [[解説書#setImageProxy]]
 
* [[解説書#setImageProxy]]
 +
これらのAPIを用いた[[#SVGMap.jsの初期化|初期化の例は次章]]で説明します。
  
一方、3.は厳密には各レイヤーのwebAppが、レイヤーのコンテンツを生成するためのデータを取得するときに(レイヤーwebAppがfetchやXMLHttpRequest等を使い)クロスオリジンアクセスするケースです。このようなクロスオリジンアクセスに対するケアは、基本的に個々のレイヤーwebAppの開発者が行う必要があります。<br>
+
==== WebApp Layerにおけるクロスオリジンアクセス ====
 +
 
 +
一方、3.は各レイヤーのwebApp([[%E8%A7%A3%E8%AA%AC%E6%9B%B8#.E3.82.A6.E3.82.A7.E3.83.96.E3.82.A2.E3.83.97.E3.83.AA.E3.82.B1.E3.83.BC.E3.82.B7.E3.83.A7.E3.83.B3.E3.81.AB.E3.82.88.E3.82.8B.E5.8B.95.E7.9A.84.E3.81.AA.E5.9C.B0.E5.9B.B3.E3.83.AC.E3.82.A4.E3.83.A4.E3.83.BC.E3.81.A8.E3.80.81.E3.81.9D.E3.81.AE.E3.83.8F.E3.82.A4.E3.83.91.E3.83.BC.E3.83.AC.E3.82.A4.E3.83.A4.E3.83.AA.E3.83.B3.E3.82.B0|webApp Layer]])が、レイヤーのコンテンツを生成するためのデータ(例えばjson形式の独自データ)を取得するときに(fetchやXMLHttpRequest等を使い)クロスオリジンアクセスするケースで、厳密にはSVGMap.jsが関与しない処理です。このようなクロスオリジンアクセスに対するケアは、基本的に個々のレイヤーwebAppの開発者が行う必要があります。<br>
 
しかしプロキシ経由のアクセスを行う場合、先の1.2.のケース用に使用するプロキシを全レイヤー共通のプロキシとしても利用する場合が考えられ、この時にはSVGMap.jsの初期化で設定したプロキシを共通の関数で呼び出せる関数が用意されています。
 
しかしプロキシ経由のアクセスを行う場合、先の1.2.のケース用に使用するプロキシを全レイヤー共通のプロキシとしても利用する場合が考えられ、この時にはSVGMap.jsの初期化で設定したプロキシを共通の関数で呼び出せる関数が用意されています。
 
* [[解説書#getCORSURL]]
 
* [[解説書#getCORSURL]]
 +
getCORSURLの使用法は[[#webAppレイヤーでのクロスオリジンアクセス|後の章で紹介]]します。
  
 
=== SVGMap.jsの初期化 ===
 
=== SVGMap.jsの初期化 ===
40行: 70行:
 
<html>
 
<html>
 
...
 
...
<script src="corsProxy.js"></script> <!-- クロスオリジンアクセス用プロキシライブラリ(下記) -->
+
<script type="module">
<script src="SVGMapLv0.1_r17.js"></script>
+
import { CorsProxy } from 'https://cdn.jsdelivr.net/gh/svgmap/svgmapjs@latest/CorsProxyModule.js';
...
+
import { svgMap } from 'https://cdn.jsdelivr.net/gh/svgmap/svgmapjs@latest/SVGMapLv0.1_r18module.js';
<script>
+
window.svgMap=svgMap
var proxyPath = "{セットアップしたCORS AnywhereのURL}"; // CORS anywhere for svgmap.org / service.svgmap.org
+
var corsProxy = new CorsProxy();
corsProxy.setService(proxyPath, null, true,false);
+
 
svgMap.setProxyURLFactory(null,null,null, corsProxy.getURL,true);
+
// プロキシの設定
 +
var proxyPath = "https://..url..of../simpleCORSproxy.php?file=";
 +
 
 +
corsProxy.setService(proxyPath, null, true, true); // 第4パラメータをtrueにするとアクセス先URLをエンコードする
 +
window.corsProxy = corsProxy;
 +
svgMap.setProxyURLFactory(null,null,null, corsProxy.getURLfunction(), true); // ビットイメージ非線形図法変換の時のみプロキシを使う
 
</script>
 
</script>
 
...
 
...
54行: 89行:
  
  
====corsProxy.js====
+
====corsProxyMoule.js====
初期化を容易に行うためのライブラリをご紹介します。[https://github.com/svgmap/svgMapDemo/blob/main/js/corsProxy.js gitHub]
+
初期化を容易に行うためのライブラリをご紹介します。[https://github.com/svgmap/svgmapjs/blob/main/CorsProxyModule.js gitHub]
 
* corsProxy.setService(pxUrl , directURLls , useAnonProxy, requireEncoding)
 
* corsProxy.setService(pxUrl , directURLls , useAnonProxy, requireEncoding)
 
** pxUrl : プロキシのURL
 
** pxUrl : プロキシのURL
61行: 96行:
 
** useAnonProxy : anonymous属性を付与するかどうか
 
** useAnonProxy : anonymous属性を付与するかどうか
 
** requireEncoding : プロキシサービスに渡すURLをURLエンコードするかどうか
 
** requireEncoding : プロキシサービスに渡すURLをURLエンコードするかどうか
* corsProxy.getURL(プロキシに取得させるURL)
+
* corsProxy.getURLfunction : プロキシ経由のURLを得るための関数を得る
  
<code>
+
===webAppレイヤーでのクロスオリジンアクセス===
<pre>
+
[[#SVGMap.jsの初期化|クロスオリジンアクセスのためのSVGMap.jsの初期化]]がなされた状態の[[解説書#.E3.83.95.E3.83.AC.E3.83.BC.E3.83.A0.E3.83.AF.E3.83.BC.E3.82.AF.E3.81.AE.E5.91.BC.E3.81.B3.E5.87.BA.E3.81.97|ルートHTML文書(SVGMapページ)]]に登録されている各レイヤーのwebAppsでは、[[解説書#getCORSURL|getCORSURL API]]を使用することができます。
var corsProxy = (function(){
+
 
var proxyUrl="";
+
このAPIは、アクセスしたいサービスのURLに対して、共通で準備されたクロスオリジンアクセス用サーバを経由したアクセスを可能にするURLが得られる機能で、たとえば以下のように利用します。
var anonProxy = false;
+
 
var directURLlist = [];
+
<code>var dataResponse = await fetch( svgMap.getCORSURL( serviceURL ) );</code>
var noEncode=true;
+
 
function setImageProxy( pxUrl , directURLls , useAnonProxy, requireEncoding){
+
 
if ( requireEncoding ){
+
一方、もしクロスオリジンアクセスの初期化をしていない[[解説書#.E3.83.95.E3.83.AC.E3.83.BC.E3.83.A0.E3.83.AF.E3.83.BC.E3.82.AF.E3.81.AE.E5.91.BC.E3.81.B3.E5.87.BA.E3.81.97|ルートHTML文書(SVGMapページ)]]では、各レイヤーのwebAppsが独自にクロスオリジンアクセスの解決を行う必要があります。例えば、クロスオリジンアクセス用のプロキシとして<code>https://[myproxy.mydomain.com]/proxy/</code> というプロキシが用意されており、<code>?targetURL=serviceURL</code> というクエリパラメータでアクセス先のサービスにアクセスする場合は、以下のようになるでしょう。
noEncode = false;
+
 
}
+
<code>var dataResponse = await fetch( "https://[myproxy.mydomain.com]/proxy/?targetURL=" + serviceURL );</code>
proxyUrl = pxUrl;
+
 
if ( directURLls ){
+
===非線形図法変換===
directURLlist = directURLls;
+
メルカトル図法と正距円筒図法の間の図法変換など、1次アフィン変換(matrix(a,b,c,d,e,f))では変換できない座標変換を伴うもの
} 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,
+
}
+
})();
+
</pre>
+
</code>
+

2024年11月5日 (火) 07:19時点における最新版

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

目次

[編集] 概要

SVGMapはハイパーレイヤリングアーキテクチャを持つため、ルートhtml文書で構成されるクライアントのSVGMapフレームワークウェブアプリは、異なるオリジンのサーバにアクセスすることが基本的に必要になります。これは一般的に「クロスオリジンリソース共有」と呼ばれる処理が行われる可能性があり、この時ウェブブラウザのネイティブな機能によるCORSのエラーが生じる可能性があることを意味します。

クロスオリジンアクセスのケースと、CORSのエラー発生の可能性を下表に示します。

クロスオリジンアクセスによるエラー
クロスオリジンアクセスするコンテンツの種類 コンテンツの処理 CORSエラー発生の可能性
ビットイメージ(タイルを含む) 重ね合わせ 発生しない
ビットイメージ(タイルを含む) 非線形図法変換を伴う重ね合わせ 発生する可能性あり
ビットイメージ(タイルを含む) 地理空間情報処理等 発生する可能性あり
ベクトルデータやjson等ビットイメージ以外のデータ 重ね合わせ 発生する可能性あり
ベクトルデータやjson等ビットイメージ以外のデータ 地理空間情報処理等 発生する可能性あり
全ての種類のコンテンツ・データ Cesium拡張を用いた表示 発生する可能性あり

[編集] エラーの確認方法

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

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

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

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

[編集] プロキシ経由のクロスオリジンアクセスを容易にするための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 type="module">
import { CorsProxy } from 'https://cdn.jsdelivr.net/gh/svgmap/svgmapjs@latest/CorsProxyModule.js';
import { svgMap } from 'https://cdn.jsdelivr.net/gh/svgmap/svgmapjs@latest/SVGMapLv0.1_r18module.js';
window.svgMap=svgMap
var corsProxy = new CorsProxy();

// プロキシの設定
var proxyPath = "https://..url..of../simpleCORSproxy.php?file=";

corsProxy.setService(proxyPath, null, true, true); // 第4パラメータをtrueにするとアクセス先URLをエンコードする
window.corsProxy = corsProxy;
svgMap.setProxyURLFactory(null,null,null, corsProxy.getURLfunction(), true); // ビットイメージ非線形図法変換の時のみプロキシを使う
</script>
...
</html>


[編集] corsProxyMoule.js

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

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

[編集] 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 );

[編集] 非線形図法変換

メルカトル図法と正距円筒図法の間の図法変換など、1次アフィン変換(matrix(a,b,c,d,e,f))では変換できない座標変換を伴うもの

個人用ツール
名前空間

変種
操作
案内
ツール
Translate