CORS ライブラリ関数の使用

Flex Gateway ポリシー開発キット (PDK) のクロスオリジンリソース共有 (CORS) ライブラリを使用したポリシープロジェクトの例は、 「CORS Validation Policy Example (CORS 検証ポリシーの例)」​を参照してください。

CORS は、Web アプリケーションが別のドメインで定義されたリソースにアクセスするためのメカニズムです。ブラウザーでは、デフォルトで CORS がサポートされています。PDK CORS ライブラリは、 CORS W3C 勧告​の標準に準拠しており、受信要求を検証してリソースを保護する一連のツールが用意されています。

CORS 設定インスタンスを定義する

CORS ライブラリは、​pdk::cors​ モジュールから使用できます。このモジュールでは、受信要求の検証メソッドを定義するための ​cors::Configuration​、​cors::OriginGroup​、​cors::AllowedMethod​ 構造とそれらのビルダーが提供されます。たとえば、次のコードスニペットでは、​cors::Configuration​ インスタンスをハードコード化する関数を定義します。

use pdk::cors;

fn create_cors_configuration() -> cors:Configuration {
    cors::Configuration::builder()
        .public_resource(false)
        .support_credentials(true)
        .origin_groups(vec![cors::OriginGroup::builder()
            .origin_group_name("default group".to_string())
            .plain_origins(vec!["http://www.the-origin-of-time.com".to_string()])
            .access_control_max_age(60)
            .headers(vec![
                "x-allow-origin".to_string(),
                "x-yet-another-valid-header".to_string(),
            ])
            .exposed_headers(vec!["x-forwarded-for".to_string()])
            .allowed_methods(vec![
                cors::AllowedMethod::builder()
                    .method_name("POST".to_string())
                    .allowed(true)
                    .build()
                    .unwrap(),
                cors::AllowedMethod::builder()
                    .method_name("PUT".to_string())
                    .allowed(true)
                    .build()
                    .unwrap(),
            ])
            .build()
            .unwrap()])
        .build()
        .unwrap();
}

cors::Configuration 構造の設定パラメーター

プロパティ 必須または省略可能 デフォルト値 説明

origin_groups

省略可能

空の ​Vec

cors::OriginGroup​ で設定可能なオリジンのグループが含まれる ​Vec​。

public_resource

省略可能

false

CORS 設定が公開リソースとして適用されるかどうかを示すブール値。

support_credentials

省略可能

false

CORS 設定が Cookie、認証ヘッダー、TLS クライアント証明書などのログイン情報をサポートするかどうかを示すブール値。

cors::OriginGroup 構造の設定パラメーター

プロパティ 必須または省略可能 デフォルト値 説明

plain_origins

省略可能

空の ​Vec

グループに含まれるオリジンの ​Vec​。例: http://www.the-origin-of-time.com​。

access_control_max_age

省略可能

30

新しいプレフライト要求を送信する前にプレフライト応答をキャッシュする期間 (秒)。

allowed_methods

省略可能

空の ​Vec

cors::AllowedMethod​ で設定可能な許可される HTTP メソッドの ​Vec​。

headers

省略可能

空の ​Vec

プレフライト要求の HTTP ヘッダーの ​Vec​。

exposed_headers

省略可能

空の ​Vec

ブラウザーの JavaScript でアクセスできるヘッダーの ​Vec​。

cors::AllowedMethod 構造の設定パラメーター

プロパティ 必須または省略可能 説明

method_name

必須

メソッド名。

is_allowed

必須

メソッドが許可されるかどうかを示すブール値。サポートされている値は、​CONNECT​、​DELETE​、​GET​、​OPTIONS​、​PATCH​、​POST​、​PUT​、または ​TRACE​ です。

CORS 検証メソッド

cors::Cors​ 構造には、指定された ​cors::Configuration​ インスタンスに対して受信ヘッダーを検証する ​check_headers()​ メソッドが含まれます。​cors::Cors::check_headers()​ メソッドは、​Result<cors::Check, cors::CorsError>​ 構造を返します。CORS 検証に失敗した場合の結果は ​Err​ になります。検証に通過すると、要求は ​Ok​ になり、​cors::Check​ 構造を評価できます。

cors::Check​ 構造の使用可能なメソッド

メソッド 種別 説明

response_type()

cors::ResponseType

受信要求に必要なアクションの種別が含まれる列挙を返します。列挙値についての詳細は、​cors::ResponseType​ 列挙応答値​を参照してください。

headers()

&[(String, String)]

応答に追加するヘッダーのリスト。

into_headers()

Vec<(String, String)>

cors::Check​ 構造をコンシュームして、応答に追加するヘッダーのリストを返します。

cors::ResponseType​ 列挙応答値

説明

Preflight

受信要求は CORS プレフライト要求であるため、ポリシーで早期に応答する必要があります。

Main

受信要求は CORS メイン要求であるため、要求はアップストリームに進みます。

CORS 検証ポリシーを記述する

CORS 検証ポリシーを記述する手順は、次のとおりです。

  1. cors::Configuration​ インスタンスを定義する ​#[entrypoint]​ 関数を定義します。次の例の ​create_cors_configuration()​ は、CORS 設定インスタンスを定義するの例で定義された関数です。

    use pdk::*;
    use pdk::cors;
    
    #[entrypoint]
    async fn configure(launcher: Launcher) -> Result<(), LaunchError> {
    
        let cors_configuration = create_cors_configuration();
    
        let filter = on_request(|rs| request_filter(rs, &cors_configuration))
            .on_response(response_filter);
    
        launcher.launch(filter).await
    }
  2. CORS 検証メソッドを使用して受信要求を検証する ​request_filter()​ 関数を定義します。返される​フロー​には、​cors::Cors::check_headers()​ から返されたヘッダーを ​response_filter()​ に渡す ​Vec<(String, String)>​ が含まれている必要があります。

    async fn request_filter(
        request_headers_state: RequestHeadersState,
        cors_configuration: &cors::Configuration<'_>,
    ) -> Flow<Vec<(String, String)>> {
    
        // Create a new CORS checker.
        let cors = cors::Cors::new(cors_configuration);
    
        let request_headers = request_headers_state.handler().headers();
    
        let cors_result = cors.check(&request_headers);
    
        match cors_result {
    
            // The CORS validation was succesful.
            Ok(cors_check) => match cors_check.response_type() {
    
                // A CORS preflight fetch was requested, return an early response.
                cors::ResponseType::Preflight => {
                    Flow::Break(Response::new(200).with_headers(check.into_headers()))
                }
    
                // This is a CORS main request, continue and pass the headers to the response.
                cors::ResponseType::Main => {
                    logger::info!("Main CORS response.");
                    Flow::Continue(check.into_headers())
                }
            },
    
            // The CORS validation failed. The request must be refused.
            Err(cors_error) => {
                Flow::Break(Response::new(200))
            }
        }
    }
  3. CORS 検証メソッドを使用して応答を検証する ​response_filter()​ 関数を定義します。 RequestData​ には、​cors::Cors::check_headers()​ で返されるヘッダーが含まれます。

    async fn response_filter(state: ResponseHeadersState, data: RequestData<Vec<(String, String)>>) {
    
        // Take the headers to add from the request data.
        let RequestData::Continue(headers_to_add) = data else {
            return;
        };
    
        // Add the headers to the response
        for (name, value) in headers_to_add.iter() {
            state.handler().set_header(name, value);
        }
    }