プロンプトと適用されるコンテキスト
Service Workerが同一オリジンの画像およびドキュメントのルートのみをインターセプトし、テナントIDとリソースIDを抽出する必要があります。コンポーネント境界、グループ、大文字小文字のルール、および非対応ブラウザ向けフォールバックを網羅したURLPatternマッチャーを設計してください。
URLPatternは、プロトコル、ホスト、ポート、pathname、search、hashコンポーネントを対象とし、名前付きまたは番号付きのキャプチャグループを備えた標準化されたURLパターンマッチャーです。ルーティング、Service Workerのキャッシュ、エッジルールに有用ですが、マッチすることは認可を意味するものではなく、正規化やアクセスチェックの代わりにはなりません。
面接官が評価するポイント
文字列全体のマッチングではなくコンポーネントごとのマッチング、ワイルドカードとグループの構文、相対パターンのためのbaseURL、コンポーネントごとの大文字小文字の動作、キャプチャの信頼境界、コンパイル失敗、およびクロスブラウザ互換性を網羅しているかを評価します。
明確化のための質問
許可されるプロトコル、ホスト、ポート、パスが大文字小文字を区別するかどうか、検索パラメータが関与するかどうか、テナントIDおよびリソースIDが完全である必要があるかを確認します。また、ページ、Service Worker、Workerのどのコンテキストか、ブラウザのサポート状況、マッチがキャッシュやセキュリティの判断に影響するかどうかも確認します。
30秒の回答フレームワーク
「プロトコル、ホスト、ポートのコンポーネントを固定し、パス内でのみ名前付きグループを使用し、相対パターンには明示的なbaseURLを設定します。コンパイル時の構築により構文エラーをキャッチし、実行時には完全なURLをマッチングして同一オリジンを強制し、キャプチャをルーティングやキャッシュキーに使用します。URLPatternはマッチングを提供するものであり、認可を提供するものではありません。非対応ブラウザには、URLセマンティクスを再実装する広範な正規表現ではなく、同一のテストでカバーされた制限付きのURLコンポーネントフォールバックを提供します。」
ステップごとの詳細解説
ステップ 1: コンポーネントを意識したパターンを構築する
URLPatternは、protocol、hostname、port、pathname、search、hashを含むオブジェクト、またはURL形式の文字列を受け入れます。セキュリティに敏感なルートでは、たまたまパスを共有しているだけの任意のオリジンを受け入れるのではなく、プロトコルとホストを固定する必要があります。
ステップ 2: 名前付きキャプチャグループを使用する
名前付きパスグループはexec()の結果から読み取り、テナントフィールドやリソースフィールドにマッピングできます。キャプチャは文字列が期待される形状を持っていることしか証明しないため、文字セット、長さ、およびビジネス上の存在確認を個別に検証してください。
const assetPattern = new URLPattern({
protocol: "https",
hostname: "cdn.example.com",
pathname: "/tenant/:tenantId/assets/:assetId.:ext",
});
const match = assetPattern.exec(request.url);
const assetId = match?.pathname.groups.assetId;ステップ 3: ワイルドカードとセパレータの境界を定義する
ワイルドカードはそのコンポーネント内の文字にマッチします。パスセパレータを越えたり、検索パラメータを自動的にカバーしたりすると思い込まないでください。各階層レベルを明示的に記述し、空の値、余分なスラッシュ、エンコードされた文字をテストしてください。
ステップ 4: baseURLと相対パターンを理解する
相対パターンは、プロトコル、ホスト、およびその他のコンポーネントを解決するためにbaseURLを必要とします。そのため、環境によって異なるマッチャーが生成される可能性があります。構築時にベースを固定し、開発、プレビュー、本番のドメインをテストしてください。
ステップ 5: 大文字小文字と正規化ルールを処理する
URLコンポーネントにはそれぞれ異なる大文字小文字のルールがあります。ホスト名は通常大文字小文字を区別しませんが、パスやその他のコンポーネントは区別する場合があります。マッチング前にURL全体を小文字に変換しないでください。リソースパスや署名入力が変更されてしまう可能性があります。
ステップ 6: マッチングと認可を分離する
URLPatternは、テナントがそのユーザーに属していることや、リソースが読み取り可能であることを証明しません。マッチング後には、オリジン、認証、認可、キャッシュの分離、およびレスポンスタイプのチェックを実施してください。キャプチャされたテナントIDは信頼できない入力のままです。
ステップ 7: コンパイルエラーとランタイムコスト
パターンは構築時に解析されるため、無効な構文は最初のリクエスト時ではなく、起動時や登録時に失敗するべきです。リクエストごとにインスタンスを構築するのではなく、コンパイル済みインスタンスを再利用し、ホットパスにおける実際のURL分布に対してマッチングコストを測定してください。
ステップ 8: 互換性フォールバックを設計する
非対応環境ではnew URL()を使用し、ビジネスに必要なコンポーネントのみをチェックします。プロトコル、ホスト、エンコーディング、検索の解析を再現するために広範な正規表現を使用しないでください。フォールバックはネイティブマッチャーのテストベクターを共有する必要があります。
質の高い模範解答
固定されたhttps、固定されたCDNホスト、明示的なパスコンポーネントを持ち、テナントIDとリソースIDに名前付きグループを使用したURLPatternを構築します。Service Workerは完全なURLをマッチングし、その後同一オリジン、認証、キャッシュのパーティショニングを実施します。キャプチャは信頼できない文字列のままであり、長さ、文字セット、認可のチェックが依然として必要です。パターンは一度だけ構築し、構文エラーに対してフェイルファストにします。baseURLをデプロイドメインに固定し、大文字小文字の違い、エンコードされたスラッシュ、余分な検索パラメータ、および各環境をテストします。古いブラウザには、完全なURLセマンティクスを再現すると主張する広範な正規表現ではなく、制限付きのURLコンポーネントフォールバックを使用します。
よくある間違い
pathnameのみをマッチングして同一オリジンだと見なす
どのプロトコルやホストでも同じパスを通過する可能性があります。セキュリティに敏感なマッチャーはオリジンコンポーネントを固定し、実行時にリクエストオリジンを再チェックする必要があります。
キャプチャを検証済みIDとして扱う
キャプチャは形状のみを証明します。文字セット、長さ、テナントの所有権、リソースの存在、および認可を検証してください。
すべてのURLを小文字化または正規表現で正規化する
コンポーネントの大文字小文字やエンコーディングのセマンティクスは異なります。文字列全体の小文字化はパスや署名を壊す可能性があり、広範な正規表現はセパレータを越えたり検索ルールを見逃したりする可能性があります。
追加の質問と回答
開発環境のbaseURLが本番環境に混入するのを防ぐには?
baseURLをデプロイ設定として注入し、起動時に許可されたプロトコルとホストを検証し、ビルドテストおよびエンドツーエンドテストで本番ドメインを固定します。ユーザー制御のURLからセキュリティマッチャーのベースを導出してはなりません。
任意の拡張子をサポートするにはどうすればよいですか?
パターン構文のオプション(optional)グループを使用し、拡張子あり、拡張子なし、余分なドット、エンコードされた文字を個別にテストします。キャプチャが存在しない場合は、明示的なコンテンツタイプとキャッシュポリシーを選択します。
URLPatternはルーティングライブラリとどのように共存できますか?
URLPatternにエッジやService Workerでの高速なフィルタリングを担当させ、アプリケーションルーターに完全なナビゲーションとパラメータの検証を実行させます。両方のレイヤーがルートを同一に解釈できるように、URLコントラクトテストを共有します。