コンテンツにスキップ

SourceLoader

URI スキームの背後にあるバイト列を取得するポート。

英語版が原文です。

プロトコル:

  • SourceLoader.schemes -> tuple[str, ...]
  • SourceLoader.fetch(uri: str) -> Iterator[bytes]
  • SourceLoaderProvider.source_loaders() -> tuple[SourceLoader, ...]

SourceLoader は、URI の背後にあるバイト列を取得するための境界です。ローダーは自分が解決するスキームを宣言し、一つの URI の内容をチャンク単位で yield します。バイト列が何であるか、どこまで大きくてよいか、どんな同一性を持つかは決めません — その三つはすべて indx-source が所有し、誰が取得したかにかかわらず同じ方法で所有します。

ローダーを宣言するディストリビューションをインストールすることが、インストール環境に URI スキームを教えることです。file:data:http:https:s3: もこの経路で indx に到達します。indx-loader-fileindx-loader-httpindx-loader-s3 から、サードパーティが使うのと同じエントリーポイントグループを通じてです。ディスパッチは一つであり、拡張の経路が乖離していくためのビルトイン(builtin)の経路は存在しません。

その帰結は率直に述べておく価値があります。素の pip install indx は、いかなる URI も解決しません。これは観察がすでに持っていたのと同じ形です。「ディストリビューションをインストールすることがスキームを解決可能にする」が s3: と同様に https: についても真であるなら、こうでなければなりません。インラインのソースにローダーは不要です — 直接手渡されたバイト列は、そもそも取得されていないのですから。

indx_source.uri はハードコードされた SUPPORTED_SCHEMES の frozenset を持ち、その外側はすべて 415 でした。インストールされたディストリビューションは、機能、埋め込み空間、オブザーバーを持ち込めるのに、呼び出し側の s3:// バケットとそれらすべての間に立ちはだかる、たった一つのものだけは持ち込めませんでした。

エラー契約はすでにこのために作られていました。UnsupportedMediaErrorunsupported_source を独立したコードとして文書化しており、「s3:// は話せない」が「DXF をパースする機能がない」と分離できるようになっています。欠けていたのは、その背後の継ぎ目でした。

入力は URI 文字列です。出力は bytes のイテレーターです。

ボディではなくチャンク。 indx-source は消費しながらカウントし、公表された max_input_bytes を超えた最初のチャンクで拒否します。そのため、過大なソースは丸ごとバッファリングされた後ではなく、途中で拒否されます。ただしそれはチャンクが許す範囲でしか成り立ちません。レスポンス全体を一つのチャンクとして yield するローダーは、何かが異議を唱える前にすでに割り当てを終えています。だからこそ、有界なチャンクはこのポートの保証ではなく義務なのです。

ダイジェストはローダーが供給するものではない。 ダイジェストは、カウントと同じパスで、メディアタイプも検出するパッケージによって発行されます。計画はそのダイジェストに束縛されます。自前のダイジェストを供給できるローダーは、自分が返していない内容に同一性を名付けられてしまいます — source_digest をオブザーバーの手から遠ざけるのと同じ理屈です。LoadedSourceindx-source の非公開に留まるのも同じ理由です。

宣言されたスキームは飾りではありません。 これが、このポートが SourceObserver と異なる唯一の点です。オブザーバーは、尋ねられて何も返さないことで自分の担当範囲を明らかにします。ローダーは、何かが呼ばれる前に schemes によって選択され、同じ宣言が 415 の列挙するものであり、機能スナップショットの報告するものでもあります。小文字で、末尾のコロンなしです。

ローダーは使用場所では検出されない。 indx-source は両ステージの下に位置し、レジストリに到達できません — 第二の検出は、計画の決定根拠となったスナップショットと食い違い得ます。三つの load() 呼び出し箇所はすべてすでにスナップショットを持っているため、レジストリのローダーを、そこから取った上限とともに下へ手渡します。

認証情報は環境から。 INDX_* 変数からであり、記述子からでも URI の呼び出し側からでもありません。ホスト型のビジョンと埋め込みのレーンがすでに従っているルールです。

SourceLoaderProvider は、EmbeddingSpaceProviderSourceObserverProvider と同じように任意です。ページを読み取り、何も取得しないプロバイダーは決してこれを実装しません。逆に、取得だけして何も読み取らないプロバイダーもあり得ます — indx-loader-fileindx-loader-httpindx-loader-s3 はいずれも descriptors() -> () を宣言しています。

  • このローダーが解決するすべてのスキームを宣言し、ちょうどそれらだけを解決する。
  • 有界なチャンクで yield し、デプロイメントの入力上限を強制可能に保つ。
  • 取得できないソースについては raise する。すでに IndxError でないものは 422 source_unreadable としてラップされ、インストールされたディストリビューションのバグが 500 ではなく読み取れる形になります。
  • このデプロイメントが到達すべきでない宛先は 422 source_forbidden で拒否し、どの設定なら許可されるかをメッセージで伝える。
  • モジュールスコープを安価に保つ。検出はスナップショット構築中にすべてのプロバイダーモジュールをインポートするため、クライアントライブラリは fetch() の内側に置く。
  • 認証情報は INDX_* 環境変数から取る。

レジストリは、インストール済みローダーを indx が同梱するものより前に並べます。オブザーバーが使うのと同じ、任意の builtin = True 属性を使ってです。これはプロトコルの一部ではなく、False をデフォルトとして読まれるため、サードパーティが宣言することはありません — それを主張しても優先度を失うだけで、得ることは決してできません。一つのスキームを主張する二つのインストール済みローダーは、検出順で解決されます。ローダーは ID を宣言しないため、機能 ID の重複のように衝突するものが何もなく、致命的エラーではなく先勝ちのままです。

ローダーに委ねられているもの

Section titled “ローダーに委ねられているもの”

インストールされたローダーは、オペレーターがインストールを選んだコードであり、リクエストパス上でアウトバウンドのリクエストを行います。indx はそのバイト列に上限を課し、ダイジェストを発行します。どこへ接続するかは取り締まりませんし、できません。

indx が守るのは、自身の取得です。indx-loader-http は、INDX_LOADER_HTTP_ALLOW_PRIVATE_HOSTS が別段の許可をしない限り、ループバック、プライベート、リンクローカル、予約済み、マルチキャストの宛先を拒否し、すべてのリダイレクトホップを再チェックし、話せないスキームへのリダイレクトを拒否します。indx-loader-file はデフォルトでは任意のパスを読み取り、INDX_LOADER_FILE_ROOTS が設定されると設定されたルートのみを読み取ります。indx-loader-s3 は、INDX_LOADER_S3_BUCKETS が読み取ってよいバケットを名指しするまで、認証情報が届く任意のバケットから取得し、名指し後はそれ以外を拒否します。いずれの場合も、ログ行には実際に解決されたものと、許可するための変数名が載ります。レスポンスにはどちらも載りません — ホスト名がどの内部アドレスに解決されるかを信頼できない呼び出し側に伝えることは、まさに相手が探っていた答えだからです。

どちらも DNS リバインディングは塞ぎません。名前はチェックのために解決され、接続のために再度解決されます。この上限は check_destination に記されており、改善パスは検証済みアドレスへ明示的な Host ヘッダー付きで接続することです。

Router.planDocumentExecutor.encode は、何よりも先にロードを行います。したがって、何も解決しないスキームは、ソースが出会い得る最初の拒否です — どの機能も読み取れないメディアタイプの 415 より前、どのオブザーバーも観察できないメディアタイプの 422 より前です。三つすべてが、いま何がインストールされているかに依存します。

スナップショットは解決可能な集合を CapabilitySnapshot.resolvable で公表します。これは limits と同じ理由で、コンテンツハッシュから除外されています。スキームを得ることは、既存の計画が選択したものを変えずに、次に計画できるものを広げます。これをハッシュに含めると、無関係な理由で進行中のすべての計画が 409 で拒否されてしまいます。POLICY_VERSION も動きません — ここにあるものはどれもルーティングの決定ではないからです。