-
Notifications
You must be signed in to change notification settings - Fork 7
URL Rewrite Spec
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.apiUrlはparse-atts.ts:59でhttps://api.geolonia.com/${keyring.stage}に展開済み
-
-
sourcesUrl.searchParams.set('key', atts.key)(geolonia-map.ts:123) -
sourcesUrl.searchParams.set('sessionId', sessionId)(geolonia-map.ts:124)
→ sourcesUrl は https://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');geolonia-map.ts:131 は url.startsWith('https://api.geolonia.com') のみで path を見ない。だから https://api.geolonia.com/v1/sprites/... のリクエストも resourceType が Source なら sources にリダイレクトされる(意図不明、おそらく sprite は resourceType が異なるので衝突しない)。
^geolonia:\/\/tiles\/(?<username>.+)\/(?<customtileId>.+) で tiles/ 以外のパス (例: geolonia://styles/...) はマッチしない → そのまま transformedUrl = url で 3 の isGeoloniaTilesHost 判定に進むが、new URL('geolonia://...') が hostname を返さないので isGeoloniaTilesHost は false になり、最終的に 7 のフォールスルー。
*.tiles.geolonia.com のリクエストは dev でも置換されない。サーバ側で対称な dev サブドメインが存在するかは不明 (Suspicious-Logic 参照)。
URL に元から key=xxx が含まれていても atts.key に置き換わる。
sprite は api.geolonia.com のままで pathname の stage 部分だけ置換 (pathParts[1])。一方 1 と 5 はホストを書き換える。非対称(Suspicious-Logic 参照)。
_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 の dev → v1 置換) |
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 不要、というのが現状の前提。
MAP_PLATFORM_STAGE 環境変数 (webpack DefinePlugin で埋め込み、webpack.config.js:7) → keyring.stage → 以下に伝播:
-
parse-atts.ts:59→atts.apiUrl = https://api.geolonia.com/${stage}→sourcesUrl(geolonia-map.ts:122) -
geolonia-map.ts:156の dev hostname 置換 (tileserverのみ) -
geolonia-map.ts:171の sprite path 置換
ビルド時固定なので、同一ビルドでステージを切り替えることは不可。書き直し時にランタイム可変にすると後方互換が崩れる可能性。
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.ts の mockGeoloniaTiles がベース)。