Skip to content
niryuu edited this page May 25, 2026 · 1 revision

transformRequest URL 書き換え仕様

embed が maplibre に渡す transformRequest 関数の完全仕様GeoloniaMap constructor 内 (src/lib/geolonia-map.ts:127-186) で組み立てられる。

書き直し時はこのテーブル全行を再現できれば挙動互換。

コンテキスト

  • transformRequest(url: string, resourceType: ResourceType): RequestParameters | void が maplibre から各リソースリクエスト前に呼ばれる
  • resourceType は maplibre が判定 (Source, Tile, SpriteJSON, SpriteImage, Glyphs, Style 等)
  • 戻り値が { url: ... } ならその URL でリクエスト、undefined ならオリジナル URL でそのまま
  • 既存 options.transformRequest (ユーザ指定) があれば、Geolonia 変換後に追加適用される (geolonia-map.ts:181-183)

事前準備された値

constructor 開始時に以下が固定される:

  • sessionId = getSessionId(40) (geolonia-map.ts:121) — 40 桁 hex、モジュールスコープにキャッシュ (2 回目以降のマップ生成時は同じ値)
  • sourcesUrl = new URL(\${atts.apiUrl}/sources`) (geolonia-map.ts:122`)
    • atts.apiUrlparse-atts.ts:59https://api.geolonia.com/${keyring.stage} に展開済み
  • sourcesUrl.searchParams.set('key', atts.key) (geolonia-map.ts:123)
  • sourcesUrl.searchParams.set('sessionId', sessionId) (geolonia-map.ts:124)

sourcesUrlhttps://api.geolonia.com/{stage}/sources?key={apiKey}&sessionId={sessionId} の形に固定 ({stage}v1 または dev)。

完全変換テーブル

transformRequest(url, resourceType) の処理を上から順に評価する。最初にマッチした分岐の戻り値を採用、マッチしなければ _transformRequest(既存) を呼んで終了。

# resourceType 入力 URL パターン 出力 URL 追加クエリ 条件 場所
1 Source url.startsWith('https://api.geolonia.com') sourcesUrl.toString() = https://api.geolonia.com/{stage}/sources?key={apiKey}&sessionId={sessionId} (既に含まれる) 常時 geolonia-map.ts:129-136
2 (前処理) 任意 url.startsWith('geolonia://') かつ regex ^geolonia:\/\/tiles\/(?<username>.+)\/(?<customtileId>.+) にマッチ transformedUrl = https://tileserver.geolonia.com/customtiles/{customtileId}/tiles.json (まだ何も) 常時 geolonia-map.ts:139-146
3 Source (前処理後の URL に対し) isGeoloniaTilesHost(URL) が true (5 の処理へ) — geolonia-map.ts:149-163
4 (副処理) (3 の条件) hostname === 'tileserver.geolonia.com' かつ atts.stage === 'dev' hostname を 'tileserver-dev.geolonia.com' に置換 dev stage のみ geolonia-map.ts:156-158
5 Source (3 の続き) (上記) transformedUrlObj.toString() (hostname 置換後) sessionId={sessionId}, key={apiKey} isGeoloniaTilesHost geolonia-map.ts:159-163
6 SpriteJSON または SpriteImage `url.match(/^https://api.geolonia.com/(dev v1)/sprites//)` pathname の pathParts[1] (= dev または v1) を String(atts.stage) で置換 → transformedUrlObj.toString() key={apiKey} 常時 (上記 regex マッチ時)
7 その他全て _transformRequest(transformedUrl, resourceType) を呼ぶ (定義されていれば) — その戻り値が undefined なら呼び出し元はオリジナル URL を使う geolonia-map.ts:181-183

isGeoloniaTilesHost(url) の判定 (util.ts:38-50):

return urlObj.hostname === 'tileserver.geolonia.com'
    || urlObj.hostname.endsWith('.tiles.geolonia.com');

実装上の罠

a. 1 の api.geolonia.com マッチは startsWith のみ

geolonia-map.ts:131url.startsWith('https://api.geolonia.com') のみで path を見ない。だから https://api.geolonia.com/v1/sprites/... のリクエストも resourceType が Source なら sources にリダイレクトされる(意図不明、おそらく sprite は resourceType が異なるので衝突しない)。

b. 2 の geolonia:// regex は tiles パス限定

^geolonia:\/\/tiles\/(?<username>.+)\/(?<customtileId>.+)tiles/ 以外のパス (例: geolonia://styles/...) はマッチしない → そのまま transformedUrl = url で 3 の isGeoloniaTilesHost 判定に進むが、new URL('geolonia://...')hostname を返さないので isGeoloniaTilesHost は false になり、最終的に 7 のフォールスルー。

c. 4 の dev hostname 置換は tileserver.geolonia.com のみ

*.tiles.geolonia.com のリクエストは dev でも置換されない。サーバ側で対称な dev サブドメインが存在するかは不明 (Suspicious-Logic 参照)。

d. 5 の searchParams.set既存値を上書き

URL に元から key=xxx が含まれていても atts.key に置き換わる。

e. 6 の sprite はホスト置換しない

sprite は api.geolonia.com のままで pathname の stage 部分だけ置換 (pathParts[1])。一方 1 と 5 はホストを書き換える。非対称(Suspicious-Logic 参照)。

f. 7 のフォールスルー時は transformedUrl が引き渡される

_transformRequest には url ではなく transformedUrl が渡される (geolonia-map.ts:182)。なので geolonia:// → tileserver URL 化された後の値が見える。

具体例 (実際にどう変換されるか)

stage = v1、apiKey = XXX、sessionId = abc... (40 桁) と仮定:

入力 resourceType 出力
https://api.geolonia.com/v1/styles/basic.json Source https://api.geolonia.com/v1/sources?key=XXX&sessionId=abc...
https://tileserver.geolonia.com/foo/tiles.json Source https://tileserver.geolonia.com/foo/tiles.json?sessionId=abc...&key=XXX
https://osm.v3.tiles.geolonia.com/{z}/{x}/{y}.pbf Source (同 URL) ?sessionId=abc...&key=XXX
geolonia://tiles/myuser/mytile Source https://tileserver.geolonia.com/customtiles/mytile/tiles.json?sessionId=abc...&key=XXX
https://api.geolonia.com/dev/sprites/basic.json SpriteJSON https://api.geolonia.com/v1/sprites/basic.json?key=XXX (stage が v1 の場合 path の devv1 置換)
https://api.geolonia.com/v1/sprites/basic.json SpriteJSON https://api.geolonia.com/v1/sprites/basic.json?key=XXX (path 同じ + key 付与)
https://example.com/external.json Source (変換なし、_transformRequest 経由)
https://cdn.geolonia.com/style/geolonia/basic-v2/ja.json Style (変換なし — 上記表のどれにも該当しない)

最後の行が重要: スタイル JSON のリクエストには key も sessionId も付かない。CDN は public 読み取り可能なので key 不要、というのが現状の前提。

stage の dev / v1 切替の影響範囲

MAP_PLATFORM_STAGE 環境変数 (webpack DefinePlugin で埋め込み、webpack.config.js:7) → keyring.stage → 以下に伝播:

  1. parse-atts.ts:59atts.apiUrl = https://api.geolonia.com/${stage}sourcesUrl (geolonia-map.ts:122)
  2. geolonia-map.ts:156 の dev hostname 置換 (tileserver のみ)
  3. geolonia-map.ts:171 の sprite path 置換

ビルド時固定なので、同一ビルドでステージを切り替えることは不可。書き直し時にランタイム可変にすると後方互換が崩れる可能性。

TypeScript シグネチャ (再実装時の契約)

type ResourceType = 'Unknown' | 'Style' | 'Source' | 'Tile' | 'Glyphs' | 'SpriteImage' | 'SpriteJSON' | 'Image';

type RequestParameters = {
  url: string;
  // 他フィールド(headers, credentials 等)もあるが embed は使っていない
};

type TransformRequestFunction = (
  url: string,
  resourceType: ResourceType,
) => RequestParameters | undefined | void;

検証

書き直し後、上記「具体例」表の全行を input → output で一致確認するテストを書けば再現性を担保できる。E2E から見る場合は:

  • https://api.geolonia.com/v1/sources への Source リクエスト発生 (タイル取得時)
  • ?key= クエリ付与
  • ?sessionId= クエリ付与 (タイルサーバ向け)

page.route でモックして観測 (e2e/helper.tsmockGeoloniaTiles がベース)。

Clone this wiki locally