# mulesoft Omni Gateway Policy Development Kit (PDK) - Full Documentation --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Accessing Policy Metadata > For the full documentation index, see: https://docs.mulesoft.com/llms.txt PDK exposes a `Metadata` injectable that provides metadata about the policy, the Flex instance, the API instance, and the Anypoint Organization. The `Metadata` struct is as follows: ```Rust pub struct Metadata { pub flex_metadata: FlexMetadata, pub policy_metadata: PolicyMetadata, pub api_metadata: ApiMetadata, pub platform_metadata: PlatformMetadata, } ``` The `Metadata` struct references the following structures: - `FlexMetadata`: ```Rust pub struct FlexMetadata { pub flex_name: String, pub flex_version: String, } ``` - `PolicyMetadata`: ```Rust pub struct PolicyMetadata { pub policy_name: String, pub policy_namespace: String, } ``` - `ApiMetadata`: ```Rust pub struct ApiMetadata { pub id: Option, pub name: Option, pub version: Option, pub slas: Option>, // API SLA tiers in the platform } // Each ApiSla contains the limits for each SLA. pub struct ApiSla { pub id: String, pub tiers: Vec, // Limits within an API SLA tier in the platform } ``` - `PlatformMetadata`: ```Rust pub struct PlatformMetadata { pub organization_id: String, pub environment_id: String, pub root_organization_id: String, } ``` ## Inject Metadata into the #\[entrypoint\] To inject metadata into the `#[entrypoint]` configuration function, see the following code snippet: ```Rust #[entrypoint] async fn configure(launcher: Launcher, metadata: Metadata) -> Result<()> { logger::info!("Flex instance name is: {}", metadata.flex_metadata.flex_name.to_string()); launcher .launch(on_request(filter)) .await?; Ok(()) } ``` ## Inject Metadata into the Wrapped Functions You cannot directly inject metadata into the wrapped functions. To use metadata in the wrapped functions, first inject the data into the `#[entrypoint]` function and then the wrapped function: ```Rust #[entrypoint] async fn configure(launcher: Launcher, metadata: Metadata) -> Result<()> { launcher .launch(on_request(|r| request_filter(r, &metadata))) .await?; Ok(()) } async fn request_filter(_: RequestState, metadata: &Metadata) -> Flow<()> { let mut vec = Vec::new(); let headers = &mut vec; headers.push(( "flex_name".to_string(), metadata.flex_metadata.flex_name.to_string(), )); headers.push(( "policy_name".to_string(), metadata.policy_metadata.policy_name.to_string(), )); Flow::Break(Response::new(201).with_headers(vec)) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Accessing Policy Metadata > For the full documentation index, see: https://docs.mulesoft.com/llms.txt PDK exposes a `Metadata` injectable that provides metadata about the policy, the Flex instance, the API instance, and the Anypoint Organization. The `Metadata` struct is as follows: ```Rust pub struct Metadata { pub flex_metadata: FlexMetadata, pub policy_metadata: PolicyMetadata, pub api_metadata: ApiMetadata, pub platform_metadata: PlatformMetadata, } ``` The `Metadata` struct references the following structures: - `FlexMetadata`: ```Rust pub struct FlexMetadata { pub flex_name: String, pub flex_version: String, } ``` - `PolicyMetadata`: ```Rust pub struct PolicyMetadata { pub policy_name: String, pub policy_namespace: String, } ``` - `ApiMetadata`: ```Rust pub struct ApiMetadata { pub id: Option, pub name: Option, pub version: Option, pub slas: Option>, // API SLA tiers in the platform } // Each ApiSla contains the limits for each SLA. pub struct ApiSla { pub id: String, pub tiers: Vec, // Limits within an API SLA tier in the platform } ``` - `PlatformMetadata`: ```Rust pub struct PlatformMetadata { pub organization_id: String, pub environment_id: String, pub root_organization_id: String, } ``` ## Inject Metadata into the #\[entrypoint\] To inject metadata into the `#[entrypoint]` configuration function, see the following code snippet: ```Rust #[entrypoint] async fn configure(launcher: Launcher, metadata: Metadata) -> Result<()> { logger::info!("Flex instance name is: {}", metadata.flex_metadata.flex_name.to_string()); launcher .launch(on_request(filter)) .await?; Ok(()) } ``` ## Inject Metadata into the Wrapped Functions You cannot directly inject metadata into the wrapped functions. To use metadata in the wrapped functions, first inject the data into the `#[entrypoint]` function and then the wrapped function: ```Rust #[entrypoint] async fn configure(launcher: Launcher, metadata: Metadata) -> Result<()> { launcher .launch(on_request(|r| request_filter(r, &metadata))) .await?; Ok(()) } async fn request_filter(_: RequestState, metadata: &Metadata) -> Flow<()> { let mut vec = Vec::new(); let headers = &mut vec; headers.push(( "flex_name".to_string(), metadata.flex_metadata.flex_name.to_string(), )); headers.push(( "policy_name".to_string(), metadata.policy_metadata.policy_name.to_string(), )); Flow::Break(Response::new(201).with_headers(vec)) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Accessing Policy Metadata > For the full documentation index, see: https://docs.mulesoft.com/llms.txt PDK exposes a `Metadata` injectable that provides metadata about the policy, the Flex instance, the API instance, and the Anypoint Organization. The `Metadata` struct is as follows: ```Rust pub struct Metadata { pub flex_metadata: FlexMetadata, pub policy_metadata: PolicyMetadata, pub api_metadata: ApiMetadata, pub platform_metadata: PlatformMetadata, } ``` The `Metadata` struct references the following structures: - `FlexMetadata`: ```Rust pub struct FlexMetadata { pub flex_name: String, pub flex_version: String, } ``` - `PolicyMetadata`: ```Rust pub struct PolicyMetadata { pub policy_name: String, pub policy_namespace: String, } ``` - `ApiMetadata`: ```Rust pub struct ApiMetadata { pub id: Option, pub name: Option, pub version: Option, pub slas: Option>, // API SLA tiers in the platform } // Each ApiSla contains the limits for each SLA. pub struct ApiSla { pub id: String, pub tiers: Vec, // Limits within an API SLA tier in the platform } ``` - `PlatformMetadata`: ```Rust pub struct PlatformMetadata { pub organization_id: String, pub environment_id: String, pub root_organization_id: String, } ``` ## Inject Metadata into the #\[entrypoint\] To inject metadata into the `#[entrypoint]` configuration function, see the following code snippet: ```Rust #[entrypoint] async fn configure(launcher: Launcher, metadata: Metadata) -> Result<()> { logger::info!("Flex instance name is: {}", metadata.flex_metadata.flex_name.to_string()); launcher .launch(on_request(filter)) .await?; Ok(()) } ``` ## Inject Metadata into the Wrapped Functions You cannot directly inject metadata into the wrapped functions. To use metadata in the wrapped functions, first inject the data into the `#[entrypoint]` function and then the wrapped function: ```Rust #[entrypoint] async fn configure(launcher: Launcher, metadata: Metadata) -> Result<()> { launcher .launch(on_request(|r| request_filter(r, &metadata))) .await?; Ok(()) } async fn request_filter(_: RequestState, metadata: &Metadata) -> Flow<()> { let mut vec = Vec::new(); let headers = &mut vec; headers.push(( "flex_name".to_string(), metadata.flex_metadata.flex_name.to_string(), )); headers.push(( "policy_name".to_string(), metadata.policy_metadata.policy_name.to_string(), )); Flow::Break(Response::new(201).with_headers(vec)) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Accessing Policy Metadata > For the full documentation index, see: https://docs.mulesoft.com/llms.txt PDK exposes a `Metadata` injectable that provides metadata about the policy, the Flex instance, the API instance, and the Anypoint Organization. The `Metadata` struct is as follows: ```Rust pub struct Metadata { pub flex_metadata: FlexMetadata, pub policy_metadata: PolicyMetadata, pub api_metadata: ApiMetadata, pub platform_metadata: PlatformMetadata, } ``` The `Metadata` struct references the following structures: - `FlexMetadata`: ```Rust pub struct FlexMetadata { pub flex_name: String, pub flex_version: String, } ``` - `PolicyMetadata`: ```Rust pub struct PolicyMetadata { pub policy_name: String, pub policy_namespace: String, } ``` - `ApiMetadata`: ```Rust pub struct ApiMetadata { pub id: Option, pub name: Option, pub version: Option, pub slas: Option>, // API SLA tiers in the platform } // Each ApiSla contains the limits for each SLA. pub struct ApiSla { pub id: String, pub tiers: Vec, // Limits within an API SLA tier in the platform } ``` - `PlatformMetadata`: ```Rust pub struct PlatformMetadata { pub organization_id: String, pub environment_id: String, pub root_organization_id: String, } ``` ## Inject Metadata into the #\[entrypoint\] To inject metadata into the `#[entrypoint]` configuration function, see the following code snippet: ```Rust #[entrypoint] async fn configure(launcher: Launcher, metadata: Metadata) -> Result<()> { logger::info!("Flex instance name is: {}", metadata.flex_metadata.flex_name.to_string()); launcher .launch(on_request(filter)) .await?; Ok(()) } ``` ## Inject Metadata into the Wrapped Functions You cannot directly inject metadata into the wrapped functions. To use metadata in the wrapped functions, first inject the data into the `#[entrypoint]` function and then the wrapped function: ```Rust #[entrypoint] async fn configure(launcher: Launcher, metadata: Metadata) -> Result<()> { launcher .launch(on_request(|r| request_filter(r, &metadata))) .await?; Ok(()) } async fn request_filter(_: RequestState, metadata: &Metadata) -> Flow<()> { let mut vec = Vec::new(); let headers = &mut vec; headers.push(( "flex_name".to_string(), metadata.flex_metadata.flex_name.to_string(), )); headers.push(( "policy_name".to_string(), metadata.policy_metadata.policy_name.to_string(), )); Flow::Break(Response::new(201).with_headers(vec)) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Accessing Policy Metadata > For the full documentation index, see: https://docs.mulesoft.com/llms.txt PDK exposes a `Metadata` injectable that provides metadata about the policy, the Flex instance, the API instance, and the Anypoint Organization. The `Metadata` struct is as follows: ```Rust pub struct Metadata { pub flex_metadata: FlexMetadata, pub policy_metadata: PolicyMetadata, pub api_metadata: ApiMetadata, pub platform_metadata: PlatformMetadata, } ``` The `Metadata` struct references the following structures: - `FlexMetadata`: ```Rust pub struct FlexMetadata { pub flex_name: String, pub flex_version: String, } ``` - `PolicyMetadata`: ```Rust pub struct PolicyMetadata { pub policy_name: String, pub policy_namespace: String, } ``` - `ApiMetadata`: ```Rust pub struct ApiMetadata { pub id: Option, pub name: Option, pub version: Option, pub slas: Option>, // API SLA tiers in the platform } // Each ApiSla contains the limits for each SLA. pub struct ApiSla { pub id: String, pub tiers: Vec, // Limits within an API SLA tier in the platform } ``` - `PlatformMetadata`: ```Rust pub struct PlatformMetadata { pub organization_id: String, pub environment_id: String, pub root_organization_id: String, } ``` ## Inject Metadata into the #\[entrypoint\] To inject metadata into the `#[entrypoint]` configuration function, see the following code snippet: ```Rust #[entrypoint] async fn configure(launcher: Launcher, metadata: Metadata) -> Result<()> { logger::info!("Flex instance name is: {}", metadata.flex_metadata.flex_name.to_string()); launcher .launch(on_request(filter)) .await?; Ok(()) } ``` ## Inject Metadata into the Wrapped Functions You cannot directly inject metadata into the wrapped functions. To use metadata in the wrapped functions, first inject the data into the `#[entrypoint]` function and then the wrapped function: ```Rust #[entrypoint] async fn configure(launcher: Launcher, metadata: Metadata) -> Result<()> { launcher .launch(on_request(|r| request_filter(r, &metadata))) .await?; Ok(()) } async fn request_filter(_: RequestState, metadata: &Metadata) -> Flow<()> { let mut vec = Vec::new(); let headers = &mut vec; headers.push(( "flex_name".to_string(), metadata.flex_metadata.flex_name.to_string(), )); headers.push(( "policy_name".to_string(), metadata.policy_metadata.policy_name.to_string(), )); Flow::Break(Response::new(201).with_headers(vec)) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Accessing Policy Metadata > For the full documentation index, see: https://docs.mulesoft.com/llms.txt PDK exposes a `Metadata` injectable that provides metadata about the policy, the Flex instance, the API instance, and the Anypoint Organization. The `Metadata` struct is as follows: ```Rust pub struct Metadata { pub flex_metadata: FlexMetadata, pub policy_metadata: PolicyMetadata, pub api_metadata: ApiMetadata, pub platform_metadata: PlatformMetadata, } ``` The `Metadata` struct references the following structures: - `FlexMetadata`: ```Rust pub struct FlexMetadata { pub flex_name: String, pub flex_version: String, } ``` - `PolicyMetadata`: ```Rust pub struct PolicyMetadata { pub policy_name: String, pub policy_namespace: String, } ``` - `ApiMetadata`: ```Rust pub struct ApiMetadata { pub id: Option, pub name: Option, pub version: Option, pub slas: Option>, // API SLA tiers in the platform } // Each ApiSla contains the limits for each SLA. pub struct ApiSla { pub id: String, pub tiers: Vec, // Limits within an API SLA tier in the platform } ``` - `PlatformMetadata`: ```Rust pub struct PlatformMetadata { pub organization_id: String, pub environment_id: String, pub root_organization_id: String, } ``` ## Inject Metadata into the #\[entrypoint\] To inject metadata into the `#[entrypoint]` configuration function, see the following code snippet: ```Rust #[entrypoint] async fn configure(launcher: Launcher, metadata: Metadata) -> Result<()> { logger::info!("Flex instance name is: {}", metadata.flex_metadata.flex_name.to_string()); launcher .launch(on_request(filter)) .await?; Ok(()) } ``` ## Inject Metadata into the Wrapped Functions You cannot directly inject metadata into the wrapped functions. To use metadata in the wrapped functions, first inject the data into the `#[entrypoint]` function and then the wrapped function: ```Rust #[entrypoint] async fn configure(launcher: Launcher, metadata: Metadata) -> Result<()> { launcher .launch(on_request(|r| request_filter(r, &metadata))) .await?; Ok(()) } async fn request_filter(_: RequestState, metadata: &Metadata) -> Flow<()> { let mut vec = Vec::new(); let headers = &mut vec; headers.push(( "flex_name".to_string(), metadata.flex_metadata.flex_name.to_string(), )); headers.push(( "policy_name".to_string(), metadata.policy_metadata.policy_name.to_string(), )); Flow::Break(Response::new(201).with_headers(vec)) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Accessing Policy Metadata > For the full documentation index, see: https://docs.mulesoft.com/llms.txt PDK exposes a `Metadata` injectable that provides metadata about the policy, the Omni instance, the API instance, and the Anypoint Organization. The `Metadata` struct is as follows: ```Rust pub struct Metadata { pub flex_metadata: FlexMetadata, pub policy_metadata: PolicyMetadata, pub api_metadata: ApiMetadata, pub platform_metadata: PlatformMetadata, } ``` The `Metadata` struct references the following structures: - `FlexMetadata`: ```Rust pub struct FlexMetadata { pub flex_name: String, pub flex_version: String, } ``` - `PolicyMetadata`: ```Rust pub struct PolicyMetadata { pub policy_name: String, pub policy_namespace: String, } ``` - `ApiMetadata`: ```Rust pub struct ApiMetadata { pub id: Option, pub name: Option, pub version: Option, pub slas: Option>, // API SLA tiers in the platform } // Each ApiSla contains the limits for each SLA. pub struct ApiSla { pub id: String, pub tiers: Vec, // Limits within an API SLA tier in the platform } ``` - `PlatformMetadata`: ```Rust pub struct PlatformMetadata { pub organization_id: String, pub environment_id: String, pub root_organization_id: String, } ``` ## Inject Metadata into the #\[entrypoint\] To inject metadata into the `#[entrypoint]` configuration function, see the following code snippet: ```Rust #[entrypoint] async fn configure(launcher: Launcher, metadata: Metadata) -> Result<()> { logger::info!("Flex instance name is: {}", metadata.flex_metadata.flex_name.to_string()); launcher .launch(on_request(filter)) .await?; Ok(()) } ``` ## Inject Metadata into the Wrapped Functions You cannot directly inject metadata into the wrapped functions. To use metadata in the wrapped functions, first inject the data into the `#[entrypoint]` function and then the wrapped function: ```Rust #[entrypoint] async fn configure(launcher: Launcher, metadata: Metadata) -> Result<()> { launcher .launch(on_request(|r| request_filter(r, &metadata))) .await?; Ok(()) } async fn request_filter(_: RequestState, metadata: &Metadata) -> Flow<()> { let mut vec = Vec::new(); let headers = &mut vec; headers.push(( "flex_name".to_string(), metadata.flex_metadata.flex_name.to_string(), )); headers.push(( "policy_name".to_string(), metadata.policy_metadata.policy_name.to_string(), )); Flow::Break(Response::new(201).with_headers(vec)) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Accessing Policy Metadata > For the full documentation index, see: https://docs.mulesoft.com/llms.txt PDK exposes a `Metadata` injectable that provides metadata about the policy, the Omni instance, the API instance, and the Anypoint Organization. The `Metadata` struct is as follows: ```Rust pub struct Metadata { pub flex_metadata: FlexMetadata, pub policy_metadata: PolicyMetadata, pub api_metadata: ApiMetadata, pub platform_metadata: PlatformMetadata, } ``` The `Metadata` struct references the following structures: - `FlexMetadata`: ```Rust pub struct FlexMetadata { pub flex_name: String, pub flex_version: String, } ``` - `PolicyMetadata`: ```Rust pub struct PolicyMetadata { pub policy_name: String, pub policy_namespace: String, } ``` - `ApiMetadata`: ```Rust pub struct ApiMetadata { pub id: Option, pub name: Option, pub version: Option, pub slas: Option>, // API SLA tiers in the platform } // Each ApiSla contains the limits for each SLA. pub struct ApiSla { pub id: String, pub tiers: Vec, // Limits within an API SLA tier in the platform } ``` - `PlatformMetadata`: ```Rust pub struct PlatformMetadata { pub organization_id: String, pub environment_id: String, pub root_organization_id: String, } ``` ## Inject Metadata into the #\[entrypoint\] To inject metadata into the `#[entrypoint]` configuration function, see the following code snippet: ```Rust #[entrypoint] async fn configure(launcher: Launcher, metadata: Metadata) -> Result<()> { logger::info!("Flex instance name is: {}", metadata.flex_metadata.flex_name.to_string()); launcher .launch(on_request(filter)) .await?; Ok(()) } ``` ## Inject Metadata into the Wrapped Functions You cannot directly inject metadata into the wrapped functions. To use metadata in the wrapped functions, first inject the data into the `#[entrypoint]` function and then the wrapped function: ```Rust #[entrypoint] async fn configure(launcher: Launcher, metadata: Metadata) -> Result<()> { launcher .launch(on_request(|r| request_filter(r, &metadata))) .await?; Ok(()) } async fn request_filter(_: RequestState, metadata: &Metadata) -> Flow<()> { let mut vec = Vec::new(); let headers = &mut vec; headers.push(( "flex_name".to_string(), metadata.flex_metadata.flex_name.to_string(), )); headers.push(( "policy_name".to_string(), metadata.policy_metadata.policy_name.to_string(), )); Flow::Break(Response::new(201).with_headers(vec)) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Accessing Policy Metadata > For the full documentation index, see: https://docs.mulesoft.com/llms.txt PDK exposes a `Metadata` injectable that provides metadata about the policy, the Omni instance, the API instance, and the Anypoint Organization. The `Metadata` struct is as follows: ```Rust pub struct Metadata { pub flex_metadata: FlexMetadata, pub policy_metadata: PolicyMetadata, pub api_metadata: ApiMetadata, pub platform_metadata: PlatformMetadata, } ``` The `Metadata` struct references the following structures: - `FlexMetadata`: ```Rust pub struct FlexMetadata { pub flex_name: String, pub flex_version: String, } ``` - `PolicyMetadata`: ```Rust pub struct PolicyMetadata { pub policy_name: String, pub policy_namespace: String, } ``` - `ApiMetadata`: ```Rust pub struct ApiMetadata { pub id: Option, pub name: Option, pub version: Option, pub slas: Option>, // API SLA tiers in the platform } // Each ApiSla contains the limits for each SLA. pub struct ApiSla { pub id: String, pub tiers: Vec, // Limits within an API SLA tier in the platform } ``` - `PlatformMetadata`: ```Rust pub struct PlatformMetadata { pub organization_id: String, pub environment_id: String, pub root_organization_id: String, } ``` ## Inject Metadata into the #\[entrypoint\] To inject metadata into the `#[entrypoint]` configuration function, see the following code snippet: ```Rust #[entrypoint] async fn configure(launcher: Launcher, metadata: Metadata) -> Result<()> { logger::info!("Flex instance name is: {}", metadata.flex_metadata.flex_name.to_string()); launcher .launch(on_request(filter)) .await?; Ok(()) } ``` ## Inject Metadata into the Wrapped Functions You cannot directly inject metadata into the wrapped functions. To use metadata in the wrapped functions, first inject the data into the `#[entrypoint]` function and then the wrapped function: ```Rust #[entrypoint] async fn configure(launcher: Launcher, metadata: Metadata) -> Result<()> { launcher .launch(on_request(|r| request_filter(r, &metadata))) .await?; Ok(()) } async fn request_filter(_: RequestState, metadata: &Metadata) -> Flow<()> { let mut vec = Vec::new(); let headers = &mut vec; headers.push(( "flex_name".to_string(), metadata.flex_metadata.flex_name.to_string(), )); headers.push(( "policy_name".to_string(), metadata.policy_metadata.policy_name.to_string(), )); Flow::Break(Response::new(201).with_headers(vec)) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Accessing Request Authentication Information > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The `Authentication` injectable provides an interface to: - Propagate authentication data for consumption by other policies. - Consume authentication data already set by another policy. To share data, `Authentication` implements the `AuthenticationHandler` trait: ```Rust pub trait AuthenticationHandler { fn authentication(&self) -> Option; fn set_authentication(&self, authentication: Option<&AuthenticationData>); } ``` The `AuthenticationData` struct contains the following authentication data: ```Rust pub struct AuthenticationData { pub principal: Option, pub client_id: Option, pub client_name: Option, pub properties: Value, } ``` For example, the following code reads the `Authentication` data and modifies it by overriding the `client_id` and `client_name`: ```Rust async fn request_filter(state: RequestState, authentication: Authentication) -> Flow<()> { let state = state.into_headers_state().await; let header_handler = state.handler(); let auth = authentication.authentication().unwrap_or_default(); let properties = auth.properties.as_object().cloned().unwrap_or_default(); let client_id = header_handler .header("custom_client_id_header") .unwrap_or_default(); let client_name = header_handler .header("custom_client_name_header") .unwrap_or_default(); let auth = AuthenticationData::new( auth.principal, Some(client_id), Some(client_name), properties ); authentication.set_authentication(Some(&auth)); Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher) -> Result<()> { let filter = on_request(|rs, auth| request_filter(rs, auth)); launcher.launch(filter).await?; Ok(()) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Accessing Request Authentication Information > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The `Authentication` injectable provides an interface to: - Propagate authentication data for consumption by other policies. - Consume authentication data already set by another policy. To share data, `Authentication` implements the `AuthenticationHandler` trait: ```Rust pub trait AuthenticationHandler { fn authentication(&self) -> Option; fn set_authentication(&self, authentication: Option<&AuthenticationData>); } ``` The `AuthenticationData` struct contains the following authentication data: ```Rust pub struct AuthenticationData { pub principal: Option, pub client_id: Option, pub client_name: Option, pub properties: Value, } ``` For example, the following code reads the `Authentication` data and modifies it by overriding the `client_id` and `client_name`: ```Rust async fn request_filter(state: RequestState, authentication: Authentication) -> Flow<()> { let state = state.into_headers_state().await; let header_handler = state.handler(); let auth = authentication.authentication().unwrap_or_default(); let properties = auth.properties.as_object().cloned().unwrap_or_default(); let client_id = header_handler .header("custom_client_id_header") .unwrap_or_default(); let client_name = header_handler .header("custom_client_name_header") .unwrap_or_default(); let auth = AuthenticationData::new( auth.principal, Some(client_id), Some(client_name), properties ); authentication.set_authentication(Some(&auth)); Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher) -> Result<()> { let filter = on_request(|rs, auth| request_filter(rs, auth)); launcher.launch(filter).await?; Ok(()) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Accessing Request Authentication Information > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The `Authentication` injectable provides an interface to: - Propagate authentication data for consumption by other policies. - Consume authentication data already set by another policy. To share data, `Authentication` implements the `AuthenticationHandler` trait: ```Rust pub trait AuthenticationHandler { fn authentication(&self) -> Option; fn set_authentication(&self, authentication: Option<&AuthenticationData>); } ``` The `AuthenticationData` struct contains the following authentication data: ```Rust pub struct AuthenticationData { pub principal: Option, pub client_id: Option, pub client_name: Option, pub properties: Value, } ``` For example, the following code reads the `Authentication` data and modifies it by overriding the `client_id` and `client_name`: ```Rust async fn request_filter(state: RequestState, authentication: Authentication) -> Flow<()> { let state = state.into_headers_state().await; let header_handler = state.handler(); let auth = authentication.authentication().unwrap_or_default(); let properties = auth.properties.as_object().cloned().unwrap_or_default(); let client_id = header_handler .header("custom_client_id_header") .unwrap_or_default(); let client_name = header_handler .header("custom_client_name_header") .unwrap_or_default(); let auth = AuthenticationData::new( auth.principal, Some(client_id), Some(client_name), properties ); authentication.set_authentication(Some(&auth)); Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher) -> Result<()> { let filter = on_request(|rs, auth| request_filter(rs, auth)); launcher.launch(filter).await?; Ok(()) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Accessing Request Authentication Information > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The `Authentication` injectable provides an interface to: - Propagate authentication data for consumption by other policies. - Consume authentication data already set by another policy. To share data, `Authentication` implements the `AuthenticationHandler` trait: ```Rust pub trait AuthenticationHandler { fn authentication(&self) -> Option; fn set_authentication(&self, authentication: Option<&AuthenticationData>); } ``` The `AuthenticationData` struct contains the following authentication data: ```Rust pub struct AuthenticationData { pub principal: Option, pub client_id: Option, pub client_name: Option, pub properties: Value, } ``` For example, the following code reads the `Authentication` data and modifies it by overriding the `client_id` and `client_name`: ```Rust async fn request_filter(state: RequestState, authentication: Authentication) -> Flow<()> { let state = state.into_headers_state().await; let header_handler = state.handler(); let auth = authentication.authentication().unwrap_or_default(); let properties = auth.properties.as_object().cloned().unwrap_or_default(); let client_id = header_handler .header("custom_client_id_header") .unwrap_or_default(); let client_name = header_handler .header("custom_client_name_header") .unwrap_or_default(); let auth = AuthenticationData::new( auth.principal, Some(client_id), Some(client_name), properties ); authentication.set_authentication(Some(&auth)); Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher) -> Result<()> { let filter = on_request(|rs, auth| request_filter(rs, auth)); launcher.launch(filter).await?; Ok(()) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Accessing Request Authentication Information > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The `Authentication` injectable provides an interface to: - Propagate authentication data for consumption by other policies. - Consume authentication data already set by another policy. To share data, `Authentication` implements the `AuthenticationHandler` trait: ```Rust pub trait AuthenticationHandler { fn authentication(&self) -> Option; fn set_authentication(&self, authentication: Option<&AuthenticationData>); } ``` The `AuthenticationData` struct contains the following authentication data: ```Rust pub struct AuthenticationData { pub principal: Option, pub client_id: Option, pub client_name: Option, pub properties: Value, } ``` For example, the following code reads the `Authentication` data and modifies it by overriding the `client_id` and `client_name`: ```Rust async fn request_filter(state: RequestState, authentication: Authentication) -> Flow<()> { let state = state.into_headers_state().await; let header_handler = state.handler(); let auth = authentication.authentication().unwrap_or_default(); let properties = auth.properties.as_object().cloned().unwrap_or_default(); let client_id = header_handler .header("custom_client_id_header") .unwrap_or_default(); let client_name = header_handler .header("custom_client_name_header") .unwrap_or_default(); let auth = AuthenticationData::new( auth.principal, Some(client_id), Some(client_name), properties ); authentication.set_authentication(Some(&auth)); Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher) -> Result<()> { let filter = on_request(|rs, auth| request_filter(rs, auth)); launcher.launch(filter).await?; Ok(()) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Accessing Request Authentication Information > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The `Authentication` injectable provides an interface to: - Propagate authentication data for consumption by other policies. - Consume authentication data already set by another policy. To share data, `Authentication` implements the `AuthenticationHandler` trait: ```Rust pub trait AuthenticationHandler { fn authentication(&self) -> Option; fn set_authentication(&self, authentication: Option<&AuthenticationData>); } ``` The `AuthenticationData` struct contains the following authentication data: ```Rust pub struct AuthenticationData { pub principal: Option, pub client_id: Option, pub client_name: Option, pub properties: Value, } ``` For example, the following code reads the `Authentication` data and modifies it by overriding the `client_id` and `client_name`: ```Rust async fn request_filter(state: RequestState, authentication: Authentication) -> Flow<()> { let state = state.into_headers_state().await; let header_handler = state.handler(); let auth = authentication.authentication().unwrap_or_default(); let properties = auth.properties.as_object().cloned().unwrap_or_default(); let client_id = header_handler .header("custom_client_id_header") .unwrap_or_default(); let client_name = header_handler .header("custom_client_name_header") .unwrap_or_default(); let auth = AuthenticationData::new( auth.principal, Some(client_id), Some(client_name), properties ); authentication.set_authentication(Some(&auth)); Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher) -> Result<()> { let filter = on_request(|rs, auth| request_filter(rs, auth)); launcher.launch(filter).await?; Ok(()) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Accessing Request Authentication Information > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The `Authentication` injectable provides an interface to: - Propagate authentication data for consumption by other policies. - Consume authentication data already set by another policy. To share data, `Authentication` implements the `AuthenticationHandler` trait: ```Rust pub trait AuthenticationHandler { fn authentication(&self) -> Option; fn set_authentication(&self, authentication: Option<&AuthenticationData>); } ``` The `AuthenticationData` struct contains the following authentication data: ```Rust pub struct AuthenticationData { pub principal: Option, pub client_id: Option, pub client_name: Option, pub properties: Value, } ``` For example, the following code reads the `Authentication` data and modifies it by overriding the `client_id` and `client_name`: ```Rust async fn request_filter(state: RequestState, authentication: Authentication) -> Flow<()> { let state = state.into_headers_state().await; let header_handler = state.handler(); let auth = authentication.authentication().unwrap_or_default(); let properties = auth.properties.as_object().cloned().unwrap_or_default(); let client_id = header_handler .header("custom_client_id_header") .unwrap_or_default(); let client_name = header_handler .header("custom_client_name_header") .unwrap_or_default(); let auth = AuthenticationData::new( auth.principal, Some(client_id), Some(client_name), properties ); authentication.set_authentication(Some(&auth)); Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher) -> Result<()> { let filter = on_request(|rs, auth| request_filter(rs, auth)); launcher.launch(filter).await?; Ok(()) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Accessing Request Authentication Information > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The `Authentication` injectable provides an interface to: - Propagate authentication data for consumption by other policies. - Consume authentication data already set by another policy. To share data, `Authentication` implements the `AuthenticationHandler` trait: ```Rust pub trait AuthenticationHandler { fn authentication(&self) -> Option; fn set_authentication(&self, authentication: Option<&AuthenticationData>); } ``` The `AuthenticationData` struct contains the following authentication data: ```Rust pub struct AuthenticationData { pub principal: Option, pub client_id: Option, pub client_name: Option, pub properties: Value, } ``` For example, the following code reads the `Authentication` data and modifies it by overriding the `client_id` and `client_name`: ```Rust async fn request_filter(state: RequestState, authentication: Authentication) -> Flow<()> { let state = state.into_headers_state().await; let header_handler = state.handler(); let auth = authentication.authentication().unwrap_or_default(); let properties = auth.properties.as_object().cloned().unwrap_or_default(); let client_id = header_handler .header("custom_client_id_header") .unwrap_or_default(); let client_name = header_handler .header("custom_client_name_header") .unwrap_or_default(); let auth = AuthenticationData::new( auth.principal, Some(client_id), Some(client_name), properties ); authentication.set_authentication(Some(&auth)); Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher) -> Result<()> { let filter = on_request(|rs, auth| request_filter(rs, auth)); launcher.launch(filter).await?; Ok(()) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Accessing Request Authentication Information > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The `Authentication` injectable provides an interface to: - Propagate authentication data for consumption by other policies. - Consume authentication data already set by another policy. To share data, `Authentication` implements the `AuthenticationHandler` trait: ```Rust pub trait AuthenticationHandler { fn authentication(&self) -> Option; fn set_authentication(&self, authentication: Option<&AuthenticationData>); } ``` The `AuthenticationData` struct contains the following authentication data: ```Rust pub struct AuthenticationData { pub principal: Option, pub client_id: Option, pub client_name: Option, pub properties: Value, } ``` For example, the following code reads the `Authentication` data and modifies it by overriding the `client_id` and `client_name`: ```Rust async fn request_filter(state: RequestState, authentication: Authentication) -> Flow<()> { let state = state.into_headers_state().await; let header_handler = state.handler(); let auth = authentication.authentication().unwrap_or_default(); let properties = auth.properties.as_object().cloned().unwrap_or_default(); let client_id = header_handler .header("custom_client_id_header") .unwrap_or_default(); let client_name = header_handler .header("custom_client_name_header") .unwrap_or_default(); let auth = AuthenticationData::new( auth.principal, Some(client_id), Some(client_name), properties ); authentication.set_authentication(Some(&auth)); Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher) -> Result<()> { let filter = on_request(|rs, auth| request_filter(rs, auth)); launcher.launch(filter).await?; Ok(()) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Applying Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Applying custom policies is the same as applying [included policies](https://docs.mulesoft.com/gateway/latest/policies-included-directory). When applying custom policies, the configuration parameters are defined in `definition/gcl.yaml`. To learn more about defining configuration parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.2/policies-pdk-create-schema-definition). ## Before You Begin - [Compile your custom policy](https://docs.mulesoft.com/pdk/1.2/policies-pdk-compile-policies). - If applying your custom policy to Flex Gateway running in Connected Mode, [upload your custom policy to Exchange](https://docs.mulesoft.com/pdk/1.2/policies-pdk-publish-policies). ## Apply Policies in Connected Mode When you apply a custom policy in Connected Mode, the configuration parameters and metadata defined in `gcl.yaml` appear in the API Manager UI. To apply a custom policy in Connected Mode, see [Applying Policies for Managed Omni Gateways and Connected Mode](https://docs.mulesoft.com/gateway/latest/gateway-secure-conn). ### Update Policies in Connected Mode To update a custom policy in API Manager: 1. Go to **Anypoint Platform > API Manager**. 2. In **API Administration** click the name of the API to which to apply a policy. 3. From the left navigation menu, click **Policies**. 4. Click the more options button (![1%](/mulesoft/current/en-us/pdk/1.2/_images/more-options-menu.png)) of the policy you want to update, and then click **Edit configuration**. 5. Select the **latest** version for **Policy version** configuration parameter. 6. Click **Save**. 7. Click the more options button (![1%](/mulesoft/current/en-us/pdk/1.2/_images/more-options-menu.png)) of the policy you want to update, and then click **Check for implementation updates**. For more information about implementation updates, see [Update Policy Implementations](https://docs.mulesoft.com/exchange/manage-versions#update-policy-implementations). 8. In the confirmation dialog box, click **Update all**. ## Apply Policies in Local Mode For Flex Gateway running in Local Mode, you apply custom policies using [local declarative configuration files](https://docs.mulesoft.com/gateway/latest/local-configuration-reference-guide). You specify the location of these configuration files when you first run Flex Gateway. To create the local declarative files: 1. In the `target/wasm32-wasi/release` PDK directory, copy both of the following files: - `_definition.yaml` - `_implementation.yaml` 2. Paste the two files in the `/etc/mulesoft/flex-gateway/conf.d/` Flex Gateway configuration directory. 3. Create a policy binding configuration file with a `.yaml` file extension to bind the policy to an API instance: - Give the file a custom name. - Save the file in the Flex Gateway configuration directory `/etc/mulesoft/flex-gateway/conf.d/custom`. This directory can contain multiple configuration files. 4. Copy and paste the following YAML snippet into the file, substituting your values where indicated: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: PolicyBinding metadata: name: spec: targetRef: kind: ApiInstance name: policyRef: kind: Extension name: --impl config: : "your parameter" ``` - `metadata.name`: The custom policy instance name. - `spec.targetRef.name`: The name of the API instance of which to apply the custom policy. The API instance must already have been defined and applied. - `spec.policyRef.name`: The custom policy implementation ID. To get the policy ID, run the `make show-policy-ref-name` command from the policy’s root directory. - `spec.config`: Your policy configuration data. 5. Save the file. The gateway automatically refreshes the configuration. ### Update Policies in Local Mode To update a custom policy for Flex Gateway running in Local Mode: - If you did not edit the configuration parameters, replace your old `_implementation.yaml` in your Flex Gateway configuration directory with the implementation file from your `target/wasm32-wasi/release` PDK directory. - If you did edit the configuration parameters, repeat the steps in [Apply Policies in Local Mode](#apply-policies-in-local-mode) to update your configuration parameters. ## Reorder Custom Policies Reordering custom policies is the same as reordering included policies. To reorder policies, see [Ordering Policies](https://docs.mulesoft.com/gateway/latest/policies-reorder). Polices execute in order on the request and then in inverse order on the response. However, some policies do not execute on both the request and the response. For example, policies ordered: 1. Policy X 2. Policy Y Execute Policy X then Policy Y on the request, and Policy Y then Policy X on the response. ## See Also - [Declarative Configuration Reference Guide](https://docs.mulesoft.com/gateway/latest/local-configuration-reference-guide) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Applying Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Applying custom policies is the same as applying [included policies](https://docs.mulesoft.com/gateway/latest/policies-included-directory). When applying custom policies, the configuration parameters are defined in `definition/gcl.yaml`. To learn more about defining configuration parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.3/policies-pdk-create-schema-definition). ## Before You Begin - [Compile your custom policy](https://docs.mulesoft.com/pdk/1.3/policies-pdk-compile-policies). - If applying your custom policy to Flex Gateway running in Connected Mode, [upload your custom policy to Exchange](https://docs.mulesoft.com/pdk/1.3/policies-pdk-publish-policies). ## Apply Policies in Connected Mode When you apply a custom policy in Connected Mode, the configuration parameters and metadata defined in `gcl.yaml` appear in the API Manager UI. To apply a custom policy in Connected Mode, see [Applying Policies for Managed Omni Gateways and Connected Mode](https://docs.mulesoft.com/gateway/latest/gateway-secure-conn). ### Update Policies in Connected Mode To update a custom policy in API Manager: 1. Go to **Anypoint Platform > API Manager**. 2. In **API Administration** click the name of the API to which to apply a policy. 3. From the left navigation menu, click **Policies**. 4. Click the more options button (![1%](/mulesoft/current/en-us/pdk/1.3/_images/more-options-menu.png)) of the policy you want to update, and then click **Edit configuration**. 5. Select the **latest** version for **Policy version** configuration parameter. 6. Click **Save**. 7. Click the more options button (![1%](/mulesoft/current/en-us/pdk/1.3/_images/more-options-menu.png)) of the policy you want to update, and then click **Check for implementation updates**. For more information about implementation updates, see [Update Policy Implementations](https://docs.mulesoft.com/exchange/manage-versions#update-policy-implementations). 8. In the confirmation dialog box, click **Update all**. ## Apply Policies in Local Mode For Flex Gateway running in Local Mode, you apply custom policies using [local declarative configuration files](https://docs.mulesoft.com/gateway/latest/local-configuration-reference-guide). You specify the location of these configuration files when you first run Flex Gateway. To create the local declarative files: 1. In the `target/wasm32-wasi/release` PDK directory, copy both of the following files: - `_definition.yaml` - `_implementation.yaml` 2. Paste the two files in the `/etc/mulesoft/flex-gateway/conf.d/` Flex Gateway configuration directory. 3. Create a policy binding configuration file with a `.yaml` file extension to bind the policy to an API instance: - Give the file a custom name. - Save the file in the Flex Gateway configuration directory `/etc/mulesoft/flex-gateway/conf.d/custom`. This directory can contain multiple configuration files. 4. Copy and paste the following YAML snippet into the file, substituting your values where indicated: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: PolicyBinding metadata: name: spec: targetRef: kind: ApiInstance name: policyRef: kind: Extension name: --impl config: : "your parameter" ``` - `metadata.name`: The custom policy instance name. - `spec.targetRef.name`: The name of the API instance of which to apply the custom policy. The API instance must already have been defined and applied. - `spec.policyRef.name`: The custom policy implementation ID. To get the policy ID, run the `make show-policy-ref-name` command from the policy’s root directory. - `spec.config`: Your policy configuration data. 5. Save the file. The gateway automatically refreshes the configuration. ### Update Policies in Local Mode To update a custom policy for Flex Gateway running in Local Mode: - If you did not edit the configuration parameters, replace your old `_implementation.yaml` in your Flex Gateway configuration directory with the implementation file from your `target/wasm32-wasi/release` PDK directory. - If you did edit the configuration parameters, repeat the steps in [Apply Policies in Local Mode](#apply-policies-in-local-mode) to update your configuration parameters. ## Reorder Custom Policies Reordering custom policies is the same as reordering included policies. To reorder policies, see [Ordering Policies](https://docs.mulesoft.com/gateway/latest/policies-reorder). Polices execute in order on the request and then in inverse order on the response. However, some policies do not execute on both the request and the response. For example, policies ordered: 1. Policy X 2. Policy Y Execute Policy X then Policy Y on the request, and Policy Y then Policy X on the response. ## See Also - [Declarative Configuration Reference Guide](https://docs.mulesoft.com/gateway/latest/local-configuration-reference-guide) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Applying Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Applying custom policies is the same as applying [included policies](https://docs.mulesoft.com/gateway/latest/policies-included-directory). When applying custom policies, the configuration parameters are defined in `definition/gcl.yaml`. To learn more about defining configuration parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.4/policies-pdk-create-schema-definition). ## Before You Begin - [Compile your custom policy](https://docs.mulesoft.com/pdk/1.4/policies-pdk-compile-policies). - If applying your custom policy to Flex Gateway running in Connected Mode, [upload your custom policy to Exchange](https://docs.mulesoft.com/pdk/1.4/policies-pdk-publish-policies). ## Apply Policies in Connected Mode When you apply a custom policy in Connected Mode, the configuration parameters and metadata defined in `gcl.yaml` appear in the API Manager UI. To apply a custom policy in Connected Mode, see [Applying Policies for Managed Omni Gateways and Connected Mode](https://docs.mulesoft.com/gateway/latest/gateway-secure-conn). ### Update Policies in Connected Mode To update a custom policy in API Manager: 1. Go to **Anypoint Platform > API Manager**. 2. In **API Administration** click the name of the API to which to apply a policy. 3. From the left navigation menu, click **Policies**. 4. Click the more options button (![1%](/mulesoft/current/en-us/pdk/1.4/_images/more-options-menu.png)) of the policy you want to update, and then click **Edit configuration**. 5. Select the **latest** version for **Policy version** configuration parameter. 6. Click **Save**. 7. Click the more options button (![1%](/mulesoft/current/en-us/pdk/1.4/_images/more-options-menu.png)) of the policy you want to update, and then click **Check for implementation updates**. For more information about implementation updates, see [Update Policy Implementations](https://docs.mulesoft.com/exchange/manage-versions#update-policy-implementations). 8. In the confirmation dialog box, click **Update all**. ## Apply Policies in Local Mode For Flex Gateway running in Local Mode, you apply custom policies using [local declarative configuration files](https://docs.mulesoft.com/gateway/latest/local-configuration-reference-guide). You specify the location of these configuration files when you first run Flex Gateway. To create the local declarative files: 1. In the `target/wasm32-wasip1/release` PDK directory, copy both of the following files: - `_definition.yaml` - `_implementation.yaml` 2. Paste the two files in the `/etc/mulesoft/flex-gateway/conf.d/` Flex Gateway configuration directory. 3. Create a policy binding configuration file with a `.yaml` file extension to bind the policy to an API instance: - Give the file a custom name. - Save the file in the Flex Gateway configuration directory `/etc/mulesoft/flex-gateway/conf.d/custom`. This directory can contain multiple configuration files. 4. Copy and paste the following YAML snippet into the file, substituting your values where indicated: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: PolicyBinding metadata: name: spec: targetRef: kind: ApiInstance name: policyRef: kind: Extension name: --impl config: : "your parameter" ``` - `metadata.name`: The custom policy instance name. - `spec.targetRef.name`: The name of the API instance of which to apply the custom policy. The API instance must already have been defined and applied. - `spec.policyRef.name`: The custom policy implementation ID. To get the policy ID, run the `make show-policy-ref-name` command from the policy’s root directory. - `spec.config`: Your policy configuration data. 5. Save the file. The gateway automatically refreshes the configuration. ### Update Policies in Local Mode To update a custom policy for Flex Gateway running in Local Mode: - If you did not edit the configuration parameters, replace your old `_implementation.yaml` in your Flex Gateway configuration directory with the implementation file from your `target/wasm32-wasip1/release` PDK directory. - If you did edit the configuration parameters, repeat the steps in [Apply Policies in Local Mode](#apply-policies-in-local-mode) to update your configuration parameters. ## Reorder Custom Policies Reordering custom policies is the same as reordering included policies. To reorder policies, see [Ordering Policies](https://docs.mulesoft.com/gateway/latest/policies-reorder). Polices execute in order on the request and then in inverse order on the response. However, some policies do not execute on both the request and the response. For example, policies ordered: 1. Policy X 2. Policy Y Execute Policy X then Policy Y on the request, and Policy Y then Policy X on the response. ## See Also - [Declarative Configuration Reference Guide](https://docs.mulesoft.com/gateway/latest/local-configuration-reference-guide) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Applying Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Applying custom policies is the same as applying [included policies](https://docs.mulesoft.com/gateway/latest/policies-included-directory). When applying custom policies, the configuration parameters are defined in `definition/gcl.yaml`. To learn more about defining configuration parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.5/policies-pdk-create-schema-definition). ## Before You Begin - [Compile your custom policy](https://docs.mulesoft.com/pdk/1.5/policies-pdk-compile-policies). - If applying your custom policy to Flex Gateway running in Connected Mode, [upload your custom policy to Exchange](https://docs.mulesoft.com/pdk/1.5/policies-pdk-publish-policies). ## Apply Policies in Connected Mode When you apply a custom policy in Connected Mode, the configuration parameters and metadata defined in `gcl.yaml` appear in the API Manager UI. To apply a custom policy in Connected Mode, see [Applying Policies for Managed Omni Gateways and Connected Mode](https://docs.mulesoft.com/gateway/latest/gateway-secure-conn). ### Update Policies in Connected Mode To update a custom policy in API Manager: 1. Go to **Anypoint Platform > API Manager**. 2. In **API Administration** click the name of the API to which to apply a policy. 3. From the left navigation menu, click **Policies**. 4. Click the more options button (![1%](/mulesoft/current/en-us/pdk/1.5/_images/more-options-menu.png)) of the policy you want to update, and then click **Edit configuration**. 5. Select the **latest** version for **Policy version** configuration parameter. 6. Click **Save**. 7. Click the more options button (![1%](/mulesoft/current/en-us/pdk/1.5/_images/more-options-menu.png)) of the policy you want to update, and then click **Check for implementation updates**. For more information about implementation updates, see [Update Policy Implementations](https://docs.mulesoft.com/exchange/manage-versions#update-policy-implementations). 8. In the confirmation dialog box, click **Update all**. ## Apply Policies in Local Mode For Flex Gateway running in Local Mode, you apply custom policies using [local declarative configuration files](https://docs.mulesoft.com/gateway/latest/local-configuration-reference-guide). You specify the location of these configuration files when you first run Flex Gateway. To create the local declarative files: 1. In the `target/wasm32-wasip1/release` PDK directory, copy both of the following files: - `_definition.yaml` - `_implementation.yaml` 2. Paste the two files in the `/etc/mulesoft/flex-gateway/conf.d/` Flex Gateway configuration directory. 3. Create a policy binding configuration file with a `.yaml` file extension to bind the policy to an API instance: - Give the file a custom name. - Save the file in the Flex Gateway configuration directory `/etc/mulesoft/flex-gateway/conf.d/custom`. This directory can contain multiple configuration files. 4. Copy and paste the following YAML snippet into the file, substituting your values where indicated: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: PolicyBinding metadata: name: spec: targetRef: kind: ApiInstance name: policyRef: kind: Extension name: --impl config: : "your parameter" ``` - `metadata.name`: The custom policy instance name. - `spec.targetRef.name`: The name of the API instance of which to apply the custom policy. The API instance must already have been defined and applied. - `spec.policyRef.name`: The custom policy implementation ID. To get the policy ID, run the `make show-policy-ref-name` command from the policy’s root directory. - `spec.config`: Your policy configuration data. 5. Save the file. The gateway automatically refreshes the configuration. ### Update Policies in Local Mode To update a custom policy for Flex Gateway running in Local Mode: - If you did not edit the configuration parameters, replace your old `_implementation.yaml` in your Flex Gateway configuration directory with the implementation file from your `target/wasm32-wasip1/release` PDK directory. - If you did edit the configuration parameters, repeat the steps in [Apply Policies in Local Mode](#apply-policies-in-local-mode) to update your configuration parameters. ## Reorder Custom Policies Reordering custom policies is the same as reordering included policies. To reorder policies, see [Ordering Policies](https://docs.mulesoft.com/gateway/latest/policies-reorder). Polices execute in order on the request and then in inverse order on the response. However, some policies do not execute on both the request and the response. For example, policies ordered: 1. Policy X 2. Policy Y Execute Policy X then Policy Y on the request, and Policy Y then Policy X on the response. ## See Also - [Declarative Configuration Reference Guide](https://docs.mulesoft.com/gateway/latest/local-configuration-reference-guide) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Applying Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Applying custom policies is the same as applying [included policies](https://docs.mulesoft.com/gateway/latest/policies-included-directory). When applying custom policies, the configuration parameters are defined in `definition/gcl.yaml`. To learn more about defining configuration parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.6/policies-pdk-create-schema-definition). ## Before You Begin - [Compile your custom policy](https://docs.mulesoft.com/pdk/1.6/policies-pdk-compile-policies). - If applying your custom policy to Flex Gateway running in Connected Mode, [upload your custom policy to Exchange](https://docs.mulesoft.com/pdk/1.6/policies-pdk-publish-policies). ## Apply Policies in Connected Mode When you apply a custom policy in Connected Mode, the configuration parameters and metadata defined in `gcl.yaml` appear in the API Manager UI. To apply a custom policy in Connected Mode, see [Applying Policies for Managed Omni Gateways and Connected Mode](https://docs.mulesoft.com/gateway/latest/gateway-secure-conn). ### Update Policies in Connected Mode To update a custom policy in API Manager: 1. Go to **Anypoint Platform > API Manager**. 2. In **API Administration** click the name of the API to which to apply a policy. 3. From the left navigation menu, click **Policies**. 4. Click the more options button (![1%](/mulesoft/current/en-us/pdk/1.6/_images/more-options-menu.png)) of the policy you want to update, and then click **Edit configuration**. 5. Select the **latest** version for **Policy version** configuration parameter. 6. Click **Save**. 7. Click the more options button (![1%](/mulesoft/current/en-us/pdk/1.6/_images/more-options-menu.png)) of the policy you want to update, and then click **Check for implementation updates**. For more information about implementation updates, see [Update Policy Implementations](https://docs.mulesoft.com/exchange/manage-versions#update-policy-implementations). 8. In the confirmation dialog box, click **Update all**. ## Apply Policies in Local Mode For Flex Gateway running in Local Mode, you apply custom policies using [local declarative configuration files](https://docs.mulesoft.com/gateway/latest/local-configuration-reference-guide). You specify the location of these configuration files when you first run Flex Gateway. To create the local declarative files: 1. In the `target/wasm32-wasip1/release` PDK directory, copy both of the following files: - `_definition.yaml` - `_implementation.yaml` 2. Paste the two files in the `/etc/mulesoft/flex-gateway/conf.d/` Flex Gateway configuration directory. 3. Create a policy binding configuration file with a `.yaml` file extension to bind the policy to an API instance: - Give the file a custom name. - Save the file in the Flex Gateway configuration directory `/etc/mulesoft/flex-gateway/conf.d/custom`. This directory can contain multiple configuration files. 4. Copy and paste the following YAML snippet into the file, substituting your values where indicated: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: PolicyBinding metadata: name: spec: targetRef: kind: ApiInstance name: policyRef: kind: Extension name: --impl config: : "your parameter" ``` - `metadata.name`: The custom policy instance name. - `spec.targetRef.name`: The name of the API instance of which to apply the custom policy. The API instance must already have been defined and applied. - `spec.policyRef.name`: The custom policy implementation ID. To get the policy ID, run the `make show-policy-ref-name` command from the policy’s root directory. - `spec.config`: Your policy configuration data. 5. Save the file. The gateway automatically refreshes the configuration. ### Update Policies in Local Mode To update a custom policy for Flex Gateway running in Local Mode: - If you did not edit the configuration parameters, replace your old `_implementation.yaml` in your Flex Gateway configuration directory with the implementation file from your `target/wasm32-wasip1/release` PDK directory. - If you did edit the configuration parameters, repeat the steps in [Apply Policies in Local Mode](#apply-policies-in-local-mode) to update your configuration parameters. ## Reorder Custom Policies Reordering custom policies is the same as reordering included policies. To reorder policies, see [Ordering Policies](https://docs.mulesoft.com/gateway/latest/policies-reorder). Polices execute in order on the request and then in inverse order on the response. However, some policies do not execute on both the request and the response. For example, policies ordered: 1. Policy X 2. Policy Y Execute Policy X then Policy Y on the request, and Policy Y then Policy X on the response. ## See Also - [Declarative Configuration Reference Guide](https://docs.mulesoft.com/gateway/latest/local-configuration-reference-guide) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Applying Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Applying custom policies is the same as applying [included policies](https://docs.mulesoft.com/gateway/latest/policies-included-directory). When applying custom policies, the configuration parameters are defined in `definition/gcl.yaml`. To learn more about defining configuration parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-schema-definition). ## Before You Begin - [Compile your custom policy](https://docs.mulesoft.com/pdk/1.7/policies-pdk-compile-policies). - If applying your custom policy to Flex Gateway running in Connected Mode, [upload your custom policy to Exchange](https://docs.mulesoft.com/pdk/1.7/policies-pdk-publish-policies). ## Apply Policies in Connected Mode When you apply a custom policy in Connected Mode, the configuration parameters and metadata defined in `gcl.yaml` appear in the API Manager UI. To apply a custom policy in Connected Mode, see [Applying Policies for Managed Omni Gateways and Connected Mode](https://docs.mulesoft.com/gateway/latest/gateway-secure-conn). ### Update Policies in Connected Mode To update a custom policy in API Manager: 1. Go to **Anypoint Platform > API Manager**. 2. In **API Administration** click the name of the API to which to apply a policy. 3. From the left navigation menu, click **Policies**. 4. Click the more options button (![1%](/mulesoft/current/en-us/pdk/1.7/_images/more-options-menu.png)) of the policy you want to update, and then click **Edit configuration**. 5. Select the **latest** version for **Policy version** configuration parameter. 6. Click **Save**. 7. Click the more options button (![1%](/mulesoft/current/en-us/pdk/1.7/_images/more-options-menu.png)) of the policy you want to update, and then click **Check for implementation updates**. For more information about implementation updates, see [Update Policy Implementations](https://docs.mulesoft.com/exchange/manage-versions#update-policy-implementations). 8. In the confirmation dialog box, click **Update all**. ## Apply Policies in Local Mode For Flex Gateway running in Local Mode, you apply custom policies using [local declarative configuration files](https://docs.mulesoft.com/gateway/latest/local-configuration-reference-guide). You specify the location of these configuration files when you first run Flex Gateway. To create the local declarative files: 1. In the `target/wasm32-wasip1/release` PDK directory, copy both of the following files: - `_definition.yaml` - `_implementation.yaml` 2. Paste the two files in the `/etc/mulesoft/flex-gateway/conf.d/` Flex Gateway configuration directory. 3. Create a policy binding configuration file with a `.yaml` file extension to bind the policy to an API instance: - Give the file a custom name. - Save the file in the Flex Gateway configuration directory `/etc/mulesoft/flex-gateway/conf.d/custom`. This directory can contain multiple configuration files. 4. Copy and paste the following YAML snippet into the file, substituting your values where indicated: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: PolicyBinding metadata: name: spec: targetRef: kind: ApiInstance name: policyRef: kind: Extension name: --impl config: : "your parameter" ``` - `metadata.name`: The custom policy instance name. - `spec.targetRef.name`: The name of the API instance of which to apply the custom policy. The API instance must already have been defined and applied. - `spec.policyRef.name`: The custom policy implementation ID. To get the policy ID, run the `make show-policy-ref-name` command from the policy’s root directory. - `spec.config`: Your policy configuration data. 5. Save the file. The gateway automatically refreshes the configuration. ### Update Policies in Local Mode To update a custom policy for Flex Gateway running in Local Mode: - If you did not edit the configuration parameters, replace your old `_implementation.yaml` in your Flex Gateway configuration directory with the implementation file from your `target/wasm32-wasip1/release` PDK directory. - If you did edit the configuration parameters, repeat the steps in [Apply Policies in Local Mode](#apply-policies-in-local-mode) to update your configuration parameters. ## Reorder Custom Policies Reordering custom policies is the same as reordering included policies. To reorder policies, see [Ordering Policies](https://docs.mulesoft.com/gateway/latest/policies-reorder). Polices execute in order on the request and then in inverse order on the response. However, some policies do not execute on both the request and the response. For example, policies ordered: 1. Policy X 2. Policy Y Execute Policy X then Policy Y on the request, and Policy Y then Policy X on the response. ## See Also - [Declarative Configuration Reference Guide](https://docs.mulesoft.com/gateway/latest/local-configuration-reference-guide) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Applying Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Applying custom policies is the same as applying [included policies](https://docs.mulesoft.com/gateway/latest/policies-included-directory). When applying custom policies, the configuration parameters are defined in `definition/gcl.yaml`. To learn more about defining configuration parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-schema-definition). ## Before You Begin - [Compile your custom policy](https://docs.mulesoft.com/pdk/1.8/policies-pdk-compile-policies). - If applying your custom policy to Omni Gateway running in Connected Mode, [upload your custom policy to Exchange](https://docs.mulesoft.com/pdk/1.8/policies-pdk-publish-policies). ## Apply Policies in Connected Mode When you apply a custom policy in Connected Mode, the configuration parameters and metadata defined in `gcl.yaml` appear in the API Manager UI. To apply a custom policy in Connected Mode, see [Applying Policies for Managed Omni Gateways and Connected Mode](https://docs.mulesoft.com/gateway/latest/gateway-secure-conn). ### Update Policies in Connected Mode To update a custom policy in API Manager: 1. Go to **Anypoint Platform > API Manager**. 2. In **API Administration** click the name of the API to which to apply a policy. 3. From the left navigation menu, click **Policies**. 4. Click the more options button (![1%](/mulesoft/current/en-us/pdk/1.8/_images/more-options-menu.png)) of the policy you want to update, and then click **Edit configuration**. 5. Select the **latest** version for **Policy version** configuration parameter. 6. Click **Save**. 7. Click the more options button (![1%](/mulesoft/current/en-us/pdk/1.8/_images/more-options-menu.png)) of the policy you want to update, and then click **Check for implementation updates**. For more information about implementation updates, see [Update Policy Implementations](https://docs.mulesoft.com/exchange/manage-versions#update-policy-implementations). 8. In the confirmation dialog box, click **Update all**. ## Apply Policies in Local Mode For Omni Gateway running in Local Mode, you apply custom policies using [local declarative configuration files](https://docs.mulesoft.com/gateway/latest/local-configuration-reference-guide). You specify the location of these configuration files when you first run Omni Gateway. To create the local declarative files: 1. In the `target/wasm32-wasip1/release` PDK directory, copy both of the following files: - `_definition.yaml` - `_implementation.yaml` 2. Paste the two files in the `/etc/mulesoft/flex-gateway/conf.d/` Omni Gateway configuration directory. 3. Create a policy binding configuration file with a `.yaml` file extension to bind the policy to an API instance: - Give the file a custom name. - Save the file in the Omni Gateway configuration directory `/etc/mulesoft/flex-gateway/conf.d/custom`. This directory can contain multiple configuration files. 4. Copy and paste the following YAML snippet into the file, substituting your values where indicated: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: PolicyBinding metadata: name: spec: targetRef: kind: ApiInstance name: policyRef: kind: Extension name: --impl config: : "your parameter" ``` - `metadata.name`: The custom policy instance name. - `spec.targetRef.name`: The name of the API instance of which to apply the custom policy. The API instance must already have been defined and applied. - `spec.policyRef.name`: The custom policy implementation ID. To get the policy ID, run the `make show-policy-ref-name` command from the policy’s root directory. - `spec.config`: Your policy configuration data. 5. Save the file. The gateway automatically refreshes the configuration. ### Update Policies in Local Mode To update a custom policy for Omni Gateway running in Local Mode: - If you did not edit the configuration parameters, replace your old `_implementation.yaml` in your Omni Gateway configuration directory with the implementation file from your `target/wasm32-wasip1/release` PDK directory. - If you did edit the configuration parameters, repeat the steps in [Apply Policies in Local Mode](#apply-policies-in-local-mode) to update your configuration parameters. ## Reorder Custom Policies Reordering custom policies is the same as reordering included policies. To reorder policies, see [Ordering Policies](https://docs.mulesoft.com/gateway/latest/policies-reorder). Polices execute in order on the request and then in inverse order on the response. However, some policies do not execute on both the request and the response. For example, policies ordered: 1. Policy X 2. Policy Y Execute Policy X then Policy Y on the request, and Policy Y then Policy X on the response. ## See Also - [Declarative Configuration Reference Guide](https://docs.mulesoft.com/gateway/latest/local-configuration-reference-guide) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Applying Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Applying custom policies is the same as applying [included policies](https://docs.mulesoft.com/gateway/latest/policies-included-directory). When applying custom policies, the configuration parameters are defined in `definition/gcl.yaml`. To learn more about defining configuration parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-schema-definition). ## Before You Begin - [Compile your custom policy](https://docs.mulesoft.com/pdk/1.9/policies-pdk-compile-policies). - If applying your custom policy to Omni Gateway running in Connected Mode, [upload your custom policy to Exchange](https://docs.mulesoft.com/pdk/1.9/policies-pdk-publish-policies). ## Apply Policies in Connected Mode When you apply a custom policy in Connected Mode, the configuration parameters and metadata defined in `gcl.yaml` appear in the API Manager UI. To apply a custom policy in Connected Mode, see [Applying Policies for Managed Omni Gateways and Connected Mode](https://docs.mulesoft.com/gateway/latest/gateway-secure-conn). ### Update Policies in Connected Mode To update a custom policy in API Manager: 1. Go to **Anypoint Platform > API Manager**. 2. In **API Administration** click the name of the API to which to apply a policy. 3. From the left navigation menu, click **Policies**. 4. Click the more options button (![1%](/mulesoft/current/en-us/pdk/1.9/_images/more-options-menu.png)) of the policy you want to update, and then click **Edit configuration**. 5. Select the **latest** version for **Policy version** configuration parameter. 6. Click **Save**. 7. Click the more options button (![1%](/mulesoft/current/en-us/pdk/1.9/_images/more-options-menu.png)) of the policy you want to update, and then click **Check for implementation updates**. For more information about implementation updates, see [Update Policy Implementations](https://docs.mulesoft.com/exchange/manage-versions#update-policy-implementations). 8. In the confirmation dialog box, click **Update all**. ## Apply Policies in Local Mode For Omni Gateway running in Local Mode, you apply custom policies using [local declarative configuration files](https://docs.mulesoft.com/gateway/latest/local-configuration-reference-guide). You specify the location of these configuration files when you first run Omni Gateway. To create the local declarative files: 1. In the `target/wasm32-wasip1/release` PDK directory, copy both of the following files: - `_definition.yaml` - `_implementation.yaml` 2. Paste the two files in the `/etc/mulesoft/flex-gateway/conf.d/` Omni Gateway configuration directory. 3. Create a policy binding configuration file with a `.yaml` file extension to bind the policy to an API instance: - Give the file a custom name. - Save the file in the Omni Gateway configuration directory `/etc/mulesoft/flex-gateway/conf.d/custom`. This directory can contain multiple configuration files. 4. Copy and paste the following YAML snippet into the file, substituting your values where indicated: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: PolicyBinding metadata: name: spec: targetRef: kind: ApiInstance name: policyRef: kind: Extension name: --impl config: : "your parameter" ``` - `metadata.name`: The custom policy instance name. - `spec.targetRef.name`: The name of the API instance of which to apply the custom policy. The API instance must already have been defined and applied. - `spec.policyRef.name`: The custom policy implementation ID. To get the policy ID, run the `make show-policy-ref-name` command from the policy’s root directory. - `spec.config`: Your policy configuration data. 5. Save the file. The gateway automatically refreshes the configuration. ### Update Policies in Local Mode To update a custom policy for Omni Gateway running in Local Mode: - If you did not edit the configuration parameters, replace your old `_implementation.yaml` in your Omni Gateway configuration directory with the implementation file from your `target/wasm32-wasip1/release` PDK directory. - If you did edit the configuration parameters, repeat the steps in [Apply Policies in Local Mode](#apply-policies-in-local-mode) to update your configuration parameters. ## Reorder Custom Policies Reordering custom policies is the same as reordering included policies. To reorder policies, see [Ordering Policies](https://docs.mulesoft.com/gateway/latest/policies-reorder). Polices execute in order on the request and then in inverse order on the response. However, some policies do not execute on both the request and the response. For example, policies ordered: 1. Policy X 2. Policy Y Execute Policy X then Policy Y on the request, and Policy Y then Policy X on the response. ## See Also - [Declarative Configuration Reference Guide](https://docs.mulesoft.com/gateway/latest/local-configuration-reference-guide) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Applying Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Applying custom policies is the same as applying [included policies](https://docs.mulesoft.com/gateway/latest/policies-included-directory). When applying custom policies, the configuration parameters are defined in `definition/gcl.yaml`. To learn more about defining configuration parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-schema-definition). ## Before You Begin - [Compile your custom policy](https://docs.mulesoft.com/pdk/latest/policies-pdk-compile-policies). - If applying your custom policy to Omni Gateway running in Connected Mode, [upload your custom policy to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies). ## Apply Policies in Connected Mode When you apply a custom policy in Connected Mode, the configuration parameters and metadata defined in `gcl.yaml` appear in the API Manager UI. To apply a custom policy in Connected Mode, see [Applying Policies for Managed Omni Gateways and Connected Mode](https://docs.mulesoft.com/gateway/latest/gateway-secure-conn). ### Update Policies in Connected Mode To update a custom policy in API Manager: 1. Go to **Anypoint Platform > API Manager**. 2. In **API Administration** click the name of the API to which to apply a policy. 3. From the left navigation menu, click **Policies**. 4. Click the more options button (![1%](/mulesoft/current/en-us/pdk/latest/_images/more-options-menu.png)) of the policy you want to update, and then click **Edit configuration**. 5. Select the **latest** version for **Policy version** configuration parameter. 6. Click **Save**. 7. Click the more options button (![1%](/mulesoft/current/en-us/pdk/latest/_images/more-options-menu.png)) of the policy you want to update, and then click **Check for implementation updates**. For more information about implementation updates, see [Update Policy Implementations](https://docs.mulesoft.com/exchange/manage-versions#update-policy-implementations). 8. In the confirmation dialog box, click **Update all**. ## Apply Policies in Local Mode For Omni Gateway running in Local Mode, you apply custom policies using [local declarative configuration files](https://docs.mulesoft.com/gateway/latest/local-configuration-reference-guide). You specify the location of these configuration files when you first run Omni Gateway. To create the local declarative files: 1. In the `target/wasm32-wasip1/release` PDK directory, copy both of the following files: - `_definition.yaml` - `_implementation.yaml` 2. Paste the two files in the `/etc/mulesoft/flex-gateway/conf.d/` Omni Gateway configuration directory. 3. Create a policy binding configuration file with a `.yaml` file extension to bind the policy to an API instance: - Give the file a custom name. - Save the file in the Omni Gateway configuration directory `/etc/mulesoft/flex-gateway/conf.d/custom`. This directory can contain multiple configuration files. 4. Copy and paste the following YAML snippet into the file, substituting your values where indicated: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: PolicyBinding metadata: name: spec: targetRef: kind: ApiInstance name: policyRef: kind: Extension name: --impl config: : "your parameter" ``` - `metadata.name`: The custom policy instance name. - `spec.targetRef.name`: The name of the API instance of which to apply the custom policy. The API instance must already have been defined and applied. - `spec.policyRef.name`: The custom policy implementation ID. To get the policy ID, run the `make show-policy-ref-name` command from the policy’s root directory. - `spec.config`: Your policy configuration data. 5. Save the file. The gateway automatically refreshes the configuration. ### Update Policies in Local Mode To update a custom policy for Omni Gateway running in Local Mode: - If you did not edit the configuration parameters, replace your old `_implementation.yaml` in your Omni Gateway configuration directory with the implementation file from your `target/wasm32-wasip1/release` PDK directory. - If you did edit the configuration parameters, repeat the steps in [Apply Policies in Local Mode](#apply-policies-in-local-mode) to update your configuration parameters. ## Reorder Custom Policies Reordering custom policies is the same as reordering included policies. To reorder policies, see [Ordering Policies](https://docs.mulesoft.com/gateway/latest/policies-reorder). Polices execute in order on the request and then in inverse order on the response. However, some policies do not execute on both the request and the response. For example, policies ordered: 1. Policy X 2. Policy Y Execute Policy X then Policy Y on the request, and Policy Y then Policy X on the response. ## See Also - [Declarative Configuration Reference Guide](https://docs.mulesoft.com/gateway/latest/local-configuration-reference-guide) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Compiling Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Compile your custom policy to create the policies binary target files by using the `make build` command. You must compile your custom policy after every time you edit the policy’s source code before you can deploy the policy to a Flex Gateway. ## Before You Begin Ensure you have completed all the steps in [Creating a New Project](https://docs.mulesoft.com/pdk/1.2/policies-pdk-create-project). ## Compile Using Build Command To compile the policy, run the `make build` command from the policy’s root folder: ```ssh make build ``` The `make build` command preforms the following actions: 1. Runs the `make build-asset-files` script 2. Runs the `make build` command to compile the policy to a `WebAssembly` binary file 3. Generates additional configuration files that are not generated by the `make build-asset-files` script and are required to execute the policy The `make build` command outputs the generated files to the `target` directories. You can execute the `make build` command as many times as necessary to generate compiled artifacts. You must compile the custom policy for your source code and configuration edits to be present in the compiled artifacts. > [!NOTE] When compiling your policy the first time, Rust fetches the latest version dependencies. > If a dependency requires a Rust version later than v1.83.0, pin the latest compatible version of > the dependency with this command: > > cargo update -p --precise ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.2/policies-pdk-debug-local) - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.2/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.2/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Compiling Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Compile your custom policy to create the policies binary target files by using the `make build` command. You must compile your custom policy after every time you edit the policy’s source code before you can deploy the policy to a Flex Gateway. ## Before You Begin Ensure you have completed all the steps in [Creating a New Project](https://docs.mulesoft.com/pdk/1.3/policies-pdk-create-project). ## Compile Using Build Command To compile the policy, run the `make build` command from the policy’s root folder: ```ssh make build ``` The `make build` command preforms the following actions: 1. Runs the `make build-asset-files` script 2. Runs the `make build` command to compile the policy to a `WebAssembly` binary file 3. Generates additional configuration files that are not generated by the `make build-asset-files` script and are required to execute the policy The `make build` command outputs the generated files to the `target` directories. You can execute the `make build` command as many times as necessary to generate compiled artifacts. You must compile the custom policy for your source code and configuration edits to be present in the compiled artifacts. > [!NOTE] When compiling your policy the first time, Rust fetches the latest version dependencies. > If a dependency requires a Rust version later than v1.83.0, pin the latest compatible version of > the dependency with this command: > > cargo update -p --precise ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.3/policies-pdk-debug-local) - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.3/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.3/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Compiling Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Compile your custom policy to create the policies binary target files by using the `make build` command. You must compile your custom policy after every time you edit the policy’s source code before you can deploy the policy to a Flex Gateway. ## Before You Begin Ensure you have completed all the steps in [Creating a New Project](https://docs.mulesoft.com/pdk/1.4/policies-pdk-create-project). ## Compile Using Build Command To compile the policy, run the `make build` command from the policy’s root folder: ```ssh make build ``` The `make build` command preforms the following actions: 1. Runs the `make build-asset-files` script 2. Runs the `make build` command to compile the policy to a `WebAssembly` binary file 3. Generates additional configuration files that are not generated by the `make build-asset-files` script and are required to execute the policy The `make build` command outputs the generated files to the `target` directories. You can execute the `make build` command as many times as necessary to generate compiled artifacts. You must compile the custom policy for your source code and configuration edits to be present in the compiled artifacts. > [!NOTE] When compiling your policy the first time, Rust fetches the latest version dependencies. > If a dependency requires a Rust version later than {rust-ver-max-var}, pin the latest compatible > version of the dependency with this command: > > cargo update -p --precise ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.4/policies-pdk-debug-local) - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.4/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.4/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Compiling Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Compile your custom policy to create the policies binary target files by using the `make build` command. You must compile your custom policy after every time you edit the policy’s source code before you can deploy the policy to a Flex Gateway. ## Before You Begin Ensure you have completed all the steps in [Creating a New Project](https://docs.mulesoft.com/pdk/1.5/policies-pdk-create-project). ## Compile Using Build Command To compile the policy, run the `make build` command from the policy’s root folder: ```ssh make build ``` The `make build` command preforms the following actions: 1. Runs the `make build-asset-files` script 2. Runs the `make build` command to compile the policy to a `WebAssembly` binary file 3. Generates additional configuration files that are not generated by the `make build-asset-files` script and are required to execute the policy The `make build` command outputs the generated files to the `target` directories. You can execute the `make build` command as many times as necessary to generate compiled artifacts. You must compile the custom policy for your source code and configuration edits to be present in the compiled artifacts. > [!NOTE] When compiling your policy the first time, Rust fetches the latest version dependencies. > If a dependency requires a Rust version later than {rust-ver-max-var}, pin the latest compatible > version of the dependency with this command: > > cargo update -p --precise ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.5/policies-pdk-debug-local) - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.5/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.5/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Compiling Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Compile your custom policy to create the policies binary target files by using the `make build` command. You must compile your custom policy after every time you edit the policy’s source code before you can deploy the policy to a Flex Gateway. ## Before You Begin Ensure you have completed all the steps in [Creating a New Project](https://docs.mulesoft.com/pdk/1.6/policies-pdk-create-project). ## Compile Using Build Command To compile the policy, run the `make build` command from the policy’s root folder: ```ssh make build ``` The `make build` command preforms the following actions: 1. Runs the `make build-asset-files` script 2. Runs the `make build` command to compile the policy to a `WebAssembly` binary file 3. Generates additional configuration files that are not generated by the `make build-asset-files` script and are required to execute the policy The `make build` command outputs the generated files to the `target` directories. You can execute the `make build` command as many times as necessary to generate compiled artifacts. You must compile the custom policy for your source code and configuration edits to be present in the compiled artifacts. > [!NOTE] When compiling your policy the first time, Rust fetches the latest version dependencies. > If a dependency requires a Rust version later than {rust-ver-max-var}, pin the latest compatible > version of the dependency with this command: > > cargo update -p --precise ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.6/policies-pdk-debug-local) - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.6/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.6/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Compiling Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Compile your custom policy to create the policies binary target files by using the `make build` command. You must compile your custom policy after every time you edit the policy’s source code before you can deploy the policy to a Flex Gateway. ## Before You Begin Ensure you have completed all the steps in [Creating a Unified-Model (Regular) Policy Project](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-project). ## Compile Using Build Command To compile the policy, run the `make build` command from the policy’s root folder: ```ssh make build ``` The `make build` command preforms the following actions: 1. Runs the `make build-asset-files` script 2. Runs the `make build` command to compile the policy to a `WebAssembly` binary file 3. Generates additional configuration files that are not generated by the `make build-asset-files` script and are required to execute the policy The `make build` command outputs the generated files to the `target` directories. You can execute the `make build` command as many times as necessary to generate compiled artifacts. You must compile the custom policy for your source code and configuration edits to be present in the compiled artifacts. > [!NOTE] When compiling your policy the first time, Rust fetches the latest version dependencies. > If a dependency requires a Rust version later than {rust-ver-max-var}, pin the latest compatible > version of the dependency with this command: > > cargo update -p --precise ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.7/policies-pdk-debug-local) - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.7/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Compiling Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Compile your custom policy to create the policies binary target files by using the `make build` command. You must compile your custom policy after every time you edit the policy’s source code before you can deploy the policy to an Omni Gateway. ## Before You Begin Ensure you have completed all the steps in [Creating a Unified-Model (Regular) Policy Project](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-project). ## Compile Using Build Command To compile the policy, run the `make build` command from the policy’s root folder: ```ssh make build ``` The `make build` command preforms the following actions: 1. Runs the `make build-asset-files` script 2. Runs the `make build` command to compile the policy to a `WebAssembly` binary file 3. Generates additional configuration files that are not generated by the `make build-asset-files` script and are required to execute the policy The `make build` command outputs the generated files to the `target` directories. You can execute the `make build` command as many times as necessary to generate compiled artifacts. You must compile the custom policy for your source code and configuration edits to be present in the compiled artifacts. > [!NOTE] When compiling your policy the first time, Rust fetches the latest version dependencies. > If a dependency requires a Rust version later than {rust-ver-max-var}, pin the latest compatible > version of the dependency with this command: > > cargo update -p --precise ## See Also - [Testing and Debugging Custom Policies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-test-debug-overview) - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.8/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Compiling Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Compile your custom policy to create the policies binary target files by using the `make build` command. You must compile your custom policy after every time you edit the policy’s source code before you can deploy the policy to an Omni Gateway. ## Before You Begin Ensure you have completed all the steps in [Creating a Unified-Model (Regular) Policy Project](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-project). ## Compile Using Build Command To compile the policy, run the `make build` command from the policy’s root folder: ```ssh make build ``` The `make build` command preforms the following actions: 1. Runs the `make build-asset-files` script 2. Runs the `make build` command to compile the policy to a `WebAssembly` binary file 3. Generates additional configuration files that are not generated by the `make build-asset-files` script and are required to execute the policy The `make build` command outputs the generated files to the `target` directories. You can execute the `make build` command as many times as necessary to generate compiled artifacts. You must compile the custom policy for your source code and configuration edits to be present in the compiled artifacts. > [!NOTE] When compiling your policy the first time, Rust fetches the latest version dependencies. > If a dependency requires a Rust version later than {rust-ver-max-var}, pin the latest compatible > version of the dependency with this command: > > cargo update -p --precise ## See Also - [Testing and Debugging Custom Policies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-test-debug-overview) - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.9/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Compiling Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Compile your custom policy to create the policies binary target files by using the `make build` command. You must compile your custom policy after every time you edit the policy’s source code before you can deploy the policy to an Omni Gateway. ## Before You Begin Ensure you have completed all the steps in [Creating a Unified-Model (Regular) Policy Project](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-project). ## Compile Using Build Command To compile the policy, run the `make build` command from the policy’s root folder: ```ssh make build ``` The `make build` command preforms the following actions: 1. Runs the `make build-asset-files` script 2. Runs the `make build` command to compile the policy to a `WebAssembly` binary file 3. Generates additional configuration files that are not generated by the `make build-asset-files` script and are required to execute the policy The `make build` command outputs the generated files to the `target` directories. You can execute the `make build` command as many times as necessary to generate compiled artifacts. You must compile the custom policy for your source code and configuration edits to be present in the compiled artifacts. > [!NOTE] When compiling your policy the first time, Rust fetches the latest version dependencies. > If a dependency requires a Rust version later than {rust-ver-max-var}, pin the latest compatible > version of the dependency with this command: > > cargo update -p --precise ## See Also - [Testing and Debugging Custom Policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-test-debug-overview) - [Applying Custom Policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/latest/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Configuring a Network Proxy for PDK > For the full documentation index, see: https://docs.mulesoft.com/llms.txt If you use a network proxy to connect to the internet, you might have to define the network proxy for the software tools used by Flex Gateway Policy Development Kit (PDK). Besides Docker, all tools downloaded in [PDK prerequisites](https://docs.mulesoft.com/pdk/1.2/policies-pdk-prerequisites) accept the `HTTP_PROXY` and `HTTPS_PROXY` environment variables. To configure your environment variable, refer to [Configure a Network Proxy](#configure-a-network-proxy). To use Docker with a network proxy, see [Configure a Network Proxy for Docker](#configure-a-network-proxy-for-docker). > [!NOTE] Depending on your network proxy, you might have to define the domains the PDK tools access > in your proxy’s allowlist. ## Configure a Network Proxy Configure your `HTTP_PROXY` or `HTTPS_PROXY` environment variables by running one of the following commands after replacing the variable values with your information: - `HTTP_PROXY`: ```ssh export HTTP_PROXY=://: ``` - `HTTPS_PROXY`: ```ssh export HTTPS_PROXY=://: ``` - If your network proxy requires authentication, use the following command: ```ssh export HTTPS_PROXY=://:@: ``` ## Configure a Network Proxy for Docker [Integration testing](https://docs.mulesoft.com/pdk/1.2/policies-pdk-integration-tests) and [the debugging environment](https://docs.mulesoft.com/pdk/1.2/policies-pdk-debug-local) require Docker. Docker requires access to the internet to pull Docker images. To configure a network proxy for Docker, refer to the following Docker documentation for your relevant use case: - [Docker CLI Client](https://docs.docker.com/engine/cli/proxy/) - [Docker Desktop on Mac](https://docs.docker.com/desktop/settings-and-maintenance/settings/) - [Docker Desktop on Windows](https://docs.docker.com/desktop/settings-and-maintenance/settings/) - [Docker Desktop on Linux](https://docs.docker.com/desktop/settings-and-maintenance/settings/) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Configuring a Network Proxy for PDK > For the full documentation index, see: https://docs.mulesoft.com/llms.txt If you use a network proxy to connect to the internet, you might have to define the network proxy for the software tools used by Flex Gateway Policy Development Kit (PDK). Besides Docker, all tools downloaded in [PDK prerequisites](https://docs.mulesoft.com/pdk/1.3/policies-pdk-prerequisites) accept the `HTTP_PROXY` and `HTTPS_PROXY` environment variables. To configure your environment variable, refer to [Configure a Network Proxy](#configure-a-network-proxy). To use Docker with a network proxy, see [Configure a Network Proxy for Docker](#configure-a-network-proxy-for-docker). > [!NOTE] Depending on your network proxy, you might have to define the domains the PDK tools access > in your proxy’s allowlist. ## Configure a Network Proxy Configure your `HTTP_PROXY` or `HTTPS_PROXY` environment variables by running one of the following commands after replacing the variable values with your information: - `HTTP_PROXY`: ```ssh export HTTP_PROXY=://: ``` - `HTTPS_PROXY`: ```ssh export HTTPS_PROXY=://: ``` - If your network proxy requires authentication, use the following command: ```ssh export HTTPS_PROXY=://:@: ``` ## Configure a Network Proxy for Docker [Integration testing](https://docs.mulesoft.com/pdk/1.3/policies-pdk-integration-tests) and [the debugging environment](https://docs.mulesoft.com/pdk/1.3/policies-pdk-debug-local) require Docker. Docker requires access to the internet to pull Docker images. To configure a network proxy for Docker, refer to the following Docker documentation for your relevant use case: - [Docker CLI Client](https://docs.docker.com/engine/cli/proxy/) - [Docker Desktop on Mac](https://docs.docker.com/desktop/settings-and-maintenance/settings/) - [Docker Desktop on Windows](https://docs.docker.com/desktop/settings-and-maintenance/settings/) - [Docker Desktop on Linux](https://docs.docker.com/desktop/settings-and-maintenance/settings/) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Configuring a Network Proxy for PDK > For the full documentation index, see: https://docs.mulesoft.com/llms.txt If you use a network proxy to connect to the internet, you might have to define the network proxy for the software tools used by Flex Gateway Policy Development Kit (PDK). Besides Docker, all tools downloaded in [PDK prerequisites](https://docs.mulesoft.com/pdk/1.4/policies-pdk-prerequisites) accept the `HTTP_PROXY` and `HTTPS_PROXY` environment variables. To configure your environment variable, refer to [Configure a Network Proxy](#configure-a-network-proxy). To use Docker with a network proxy, see [Configure a Network Proxy for Docker](#configure-a-network-proxy-for-docker). > [!NOTE] Depending on your network proxy, you might have to define the domains the PDK tools access > in your proxy’s allowlist. ## Configure a Network Proxy Configure your `HTTP_PROXY` or `HTTPS_PROXY` environment variables by running one of the following commands after replacing the variable values with your information: - `HTTP_PROXY`: ```ssh export HTTP_PROXY=://: ``` - `HTTPS_PROXY`: ```ssh export HTTPS_PROXY=://: ``` - If your network proxy requires authentication, use the following command: ```ssh export HTTPS_PROXY=://:@: ``` ## Configure a Network Proxy for Docker [Integration testing](https://docs.mulesoft.com/pdk/1.4/policies-pdk-integration-tests) and [the debugging environment](https://docs.mulesoft.com/pdk/1.4/policies-pdk-debug-local) require Docker. Docker requires access to the internet to pull Docker images. To configure a network proxy for Docker, refer to the following Docker documentation for your relevant use case: - [Docker CLI Client](https://docs.docker.com/engine/cli/proxy/) - [Docker Desktop on Mac](https://docs.docker.com/desktop/settings-and-maintenance/settings/) - [Docker Desktop on Windows](https://docs.docker.com/desktop/settings-and-maintenance/settings/) - [Docker Desktop on Linux](https://docs.docker.com/desktop/settings-and-maintenance/settings/) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Configuring a Network Proxy for PDK > For the full documentation index, see: https://docs.mulesoft.com/llms.txt If you use a network proxy to connect to the internet, you might have to define the network proxy for the software tools used by Flex Gateway Policy Development Kit (PDK). Besides Docker, all tools downloaded in [PDK prerequisites](https://docs.mulesoft.com/pdk/1.5/policies-pdk-prerequisites) accept the `HTTP_PROXY` and `HTTPS_PROXY` environment variables. To configure your environment variable, refer to [Configure a Network Proxy](#configure-a-network-proxy). To use Docker with a network proxy, see [Configure a Network Proxy for Docker](#configure-a-network-proxy-for-docker). > [!NOTE] Depending on your network proxy, you might have to define the domains the PDK tools access > in your proxy’s allowlist. ## Configure a Network Proxy Configure your `HTTP_PROXY` or `HTTPS_PROXY` environment variables by running one of the following commands after replacing the variable values with your information: - `HTTP_PROXY`: ```ssh export HTTP_PROXY=://: ``` - `HTTPS_PROXY`: ```ssh export HTTPS_PROXY=://: ``` - If your network proxy requires authentication, use the following command: ```ssh export HTTPS_PROXY=://:@: ``` ## Configure a Network Proxy for Docker [Integration testing](https://docs.mulesoft.com/pdk/1.5/policies-pdk-integration-tests) and [the debugging environment](https://docs.mulesoft.com/pdk/1.5/policies-pdk-debug-local) require Docker. Docker requires access to the internet to pull Docker images. To configure a network proxy for Docker, refer to the following Docker documentation for your relevant use case: - [Docker CLI Client](https://docs.docker.com/engine/cli/proxy/) - [Docker Desktop on Mac](https://docs.docker.com/desktop/settings-and-maintenance/settings/) - [Docker Desktop on Windows](https://docs.docker.com/desktop/settings-and-maintenance/settings/) - [Docker Desktop on Linux](https://docs.docker.com/desktop/settings-and-maintenance/settings/) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Configuring a Network Proxy for PDK > For the full documentation index, see: https://docs.mulesoft.com/llms.txt If you use a network proxy to connect to the internet, you might have to define the network proxy for the software tools used by Flex Gateway Policy Development Kit (PDK). Besides Docker, all tools downloaded in [PDK prerequisites](https://docs.mulesoft.com/pdk/1.6/policies-pdk-prerequisites) accept the `HTTP_PROXY` and `HTTPS_PROXY` environment variables. To configure your environment variable, refer to [Configure a Network Proxy](#configure-a-network-proxy). To use Docker with a network proxy, see [Configure a Network Proxy for Docker](#configure-a-network-proxy-for-docker). > [!NOTE] Depending on your network proxy, you might have to define the domains the PDK tools access > in your proxy’s allowlist. ## Configure a Network Proxy Configure your `HTTP_PROXY` or `HTTPS_PROXY` environment variables by running one of the following commands after replacing the variable values with your information: - `HTTP_PROXY`: ```ssh export HTTP_PROXY=://: ``` - `HTTPS_PROXY`: ```ssh export HTTPS_PROXY=://: ``` - If your network proxy requires authentication, use the following command: ```ssh export HTTPS_PROXY=://:@: ``` ## Configure a Network Proxy for Docker [Integration testing](https://docs.mulesoft.com/pdk/1.6/policies-pdk-integration-tests) and [the debugging environment](https://docs.mulesoft.com/pdk/1.6/policies-pdk-debug-local) require Docker. Docker requires access to the internet to pull Docker images. To configure a network proxy for Docker, refer to the following Docker documentation for your relevant use case: - [Docker CLI Client](https://docs.docker.com/engine/cli/proxy/) - [Docker Desktop on Mac](https://docs.docker.com/desktop/settings-and-maintenance/settings/) - [Docker Desktop on Windows](https://docs.docker.com/desktop/settings-and-maintenance/settings/) - [Docker Desktop on Linux](https://docs.docker.com/desktop/settings-and-maintenance/settings/) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Configuring a Network Proxy for PDK > For the full documentation index, see: https://docs.mulesoft.com/llms.txt If you use a network proxy to connect to the internet, you might have to define the network proxy for the software tools used by Flex Gateway Policy Development Kit (PDK). Besides Docker, all tools downloaded in [PDK prerequisites](https://docs.mulesoft.com/pdk/1.7/policies-pdk-prerequisites) accept the `HTTP_PROXY` and `HTTPS_PROXY` environment variables. To configure your environment variable, refer to [Configure a Network Proxy](#configure-a-network-proxy). To use Docker with a network proxy, see [Configure a Network Proxy for Docker](#configure-a-network-proxy-for-docker). > [!NOTE] Depending on your network proxy, you might have to define the domains the PDK tools access > in your proxy’s allowlist. ## Configure a Network Proxy Configure your `HTTP_PROXY` or `HTTPS_PROXY` environment variables by running one of the following commands after replacing the variable values with your information: - `HTTP_PROXY`: ```ssh export HTTP_PROXY=://: ``` - `HTTPS_PROXY`: ```ssh export HTTPS_PROXY=://: ``` - If your network proxy requires authentication, use the following command: ```ssh export HTTPS_PROXY=://:@: ``` ## Configure a Network Proxy for Docker [Integration testing](https://docs.mulesoft.com/pdk/1.7/policies-pdk-integration-tests) and [the debugging environment](https://docs.mulesoft.com/pdk/1.7/policies-pdk-debug-local) require Docker. Docker requires access to the internet to pull Docker images. To configure a network proxy for Docker, refer to the following Docker documentation for your relevant use case: - [Docker CLI Client](https://docs.docker.com/network/proxy/) - [Docker Desktop on Mac](https://docs.docker.com/desktop/settings/mac/#proxies) - [Docker Desktop on Windows](https://docs.docker.com/desktop/settings/windows/#proxies) - [Docker Desktop on Linux](https://docs.docker.com/desktop/settings/linux/#proxies) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Configuring a Network Proxy for PDK > For the full documentation index, see: https://docs.mulesoft.com/llms.txt If you use a network proxy to connect to the internet, you might have to define the network proxy for the software tools used by Omni Gateway Policy Development Kit (PDK). Besides Docker, all tools downloaded in [PDK prerequisites](https://docs.mulesoft.com/pdk/1.8/policies-pdk-prerequisites) accept the `HTTP_PROXY` and `HTTPS_PROXY` environment variables. To configure your environment variable, refer to [Configure a Network Proxy](#configure-a-network-proxy). To use Docker with a network proxy, see [Configure a Network Proxy for Docker](#configure-a-network-proxy-for-docker). > [!NOTE] Depending on your network proxy, you might have to define the domains the PDK tools access > in your proxy’s allowlist. ## Configure a Network Proxy Configure your `HTTP_PROXY` or `HTTPS_PROXY` environment variables by running one of the following commands after replacing the variable values with your information: - `HTTP_PROXY`: ```ssh export HTTP_PROXY=://: ``` - `HTTPS_PROXY`: ```ssh export HTTPS_PROXY=://: ``` - If your network proxy requires authentication, use the following command: ```ssh export HTTPS_PROXY=://:@: ``` ## Configure a Network Proxy for Docker [Integration testing](https://docs.mulesoft.com/pdk/1.8/policies-pdk-integration-tests) and [the debugging environment](https://docs.mulesoft.com/pdk/1.8/policies-pdk-debug-local) require Docker. Docker requires access to the internet to pull Docker images. To configure a network proxy for Docker, refer to the following Docker documentation for your relevant use case: - [Docker CLI Client](https://docs.docker.com/network/proxy/) - [Docker Desktop on Mac](https://docs.docker.com/desktop/settings/mac/#proxies) - [Docker Desktop on Windows](https://docs.docker.com/desktop/settings/windows/#proxies) - [Docker Desktop on Linux](https://docs.docker.com/desktop/settings/linux/#proxies) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Configuring a Network Proxy for PDK > For the full documentation index, see: https://docs.mulesoft.com/llms.txt If you use a network proxy to connect to the internet, you might have to define the network proxy for the software tools used by Omni Gateway Policy Development Kit (PDK). Besides Docker, all tools downloaded in [PDK prerequisites](https://docs.mulesoft.com/pdk/1.9/policies-pdk-prerequisites) accept the `HTTP_PROXY` and `HTTPS_PROXY` environment variables. To configure your environment variable, refer to [Configure a Network Proxy](#configure-a-network-proxy). To use Docker with a network proxy, see [Configure a Network Proxy for Docker](#configure-a-network-proxy-for-docker). > [!NOTE] Depending on your network proxy, you might have to define the domains the PDK tools access > in your proxy’s allowlist. ## Configure a Network Proxy Configure your `HTTP_PROXY` or `HTTPS_PROXY` environment variables by running one of the following commands after replacing the variable values with your information: - `HTTP_PROXY`: ```ssh export HTTP_PROXY=://: ``` - `HTTPS_PROXY`: ```ssh export HTTPS_PROXY=://: ``` - If your network proxy requires authentication, use the following command: ```ssh export HTTPS_PROXY=://:@: ``` ## Configure a Network Proxy for Docker [Integration testing](https://docs.mulesoft.com/pdk/1.9/policies-pdk-integration-tests) and [the debugging environment](https://docs.mulesoft.com/pdk/1.9/policies-pdk-debug-local) require Docker. Docker requires access to the internet to pull Docker images. To configure a network proxy for Docker, refer to the following Docker documentation for your relevant use case: - [Docker CLI Client](https://docs.docker.com/network/proxy/) - [Docker Desktop on Mac](https://docs.docker.com/desktop/settings/mac/#proxies) - [Docker Desktop on Windows](https://docs.docker.com/desktop/settings/windows/#proxies) - [Docker Desktop on Linux](https://docs.docker.com/desktop/settings/linux/#proxies) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Configuring a Network Proxy for PDK > For the full documentation index, see: https://docs.mulesoft.com/llms.txt If you use a network proxy to connect to the internet, you might have to define the network proxy for the software tools used by Omni Gateway Policy Development Kit (PDK). Besides Docker, all tools downloaded in [PDK prerequisites](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites) accept the `HTTP_PROXY` and `HTTPS_PROXY` environment variables. To configure your environment variable, refer to [Configure a Network Proxy](#configure-a-network-proxy). To use Docker with a network proxy, see [Configure a Network Proxy for Docker](#configure-a-network-proxy-for-docker). > [!NOTE] Depending on your network proxy, you might have to define the domains the PDK tools access > in your proxy’s allowlist. ## Configure a Network Proxy Configure your `HTTP_PROXY` or `HTTPS_PROXY` environment variables by running one of the following commands after replacing the variable values with your information: - `HTTP_PROXY`: ```ssh export HTTP_PROXY=://: ``` - `HTTPS_PROXY`: ```ssh export HTTPS_PROXY=://: ``` - If your network proxy requires authentication, use the following command: ```ssh export HTTPS_PROXY=://:@: ``` ## Configure a Network Proxy for Docker [Integration testing](https://docs.mulesoft.com/pdk/latest/policies-pdk-integration-tests) and [the debugging environment](https://docs.mulesoft.com/pdk/latest/policies-pdk-debug-local) require Docker. Docker requires access to the internet to pull Docker images. To configure a network proxy for Docker, refer to the following Docker documentation for your relevant use case: - [Docker CLI Client](https://docs.docker.com/network/proxy/) - [Docker Desktop on Mac](https://docs.docker.com/desktop/settings/mac/#proxies) - [Docker Desktop on Windows](https://docs.docker.com/desktop/settings/windows/#proxies) - [Docker Desktop on Linux](https://docs.docker.com/desktop/settings/linux/#proxies) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Configuring Data Storage > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use PDK’s `DataStorageBuilder` to implement data storage in custom policies. Choose local in-memory storage for single-replica deployments or shared Redis storage for multi-replica deployments or deployments that require persistent data storage. Store and retrieve data with thread-safe operations including Compare-And-Swap (CAS), Absent, and Always operations. Configure namespaces for key isolation and set time-to-live values for automatic data expiration in shared storage. For multi-replica deployments or persistent data storage, you must configure shared storage. To configure shared storage, see: - [Configuring Redis Shared Storage for Omni Gateway in Connected Mode](https://docs.mulesoft.com/gateway/latest/conn-shared-storage-config) - [Configuring Redis Shared Storage for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-shared-storage-config) To use data storage functionality, inject the `DataStorageBuilder` in your the `entrypoint` and pass the storage instance to your request handlers: ```Rust // for local storage let storage = store_builder.local(namespace); // or for remote storage let storage = store_builder.remote(namespace, ttl_millis); ``` Storage builder parameters: - `namespace`: a string prefix for key isolation (required) - `ttl_millis`: time-to-live in milliseconds for automatic data expiration (only required for remote storage) After creating the storage instance, store and retrieve data with support for CAS, Absent, and Always operations for thread safety: ```Rust // Store data with CAS operation let (current_data, version) = storage.get::(&key).await?; let mode = StoreMode::Cas(version); storage.store(&key, &mode, &new_data).await?; // Retrieve data - Generic type parameter specifies the expected data type let (data, version) = storage.get::(&key).await?; ``` The `StoreMode` enum supports these operations: - `Cas` (Compare-And-Swap): Updates the value only if the current version matches the expected version. Use this operation for thread-safe conditional updates to ensure data hasn’t changed since you last read it. - `Absent`: Stores the value only if the key doesn’t exist. Use this operation to initialize values without overwriting existing data. - `Always`: Always stores the value, overwriting any existing value regardless of version. Use this operation to unconditionally update or create a key. ## Data Storage Configuration Examples PDK provides the [Data Storage Stats Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.5.0/data-storage-stats) to demonstrate how to configure data storage in Rust code. Within the example policy, see these functions for further configuration details: - [`entrypoint` function](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/data-storage-stats/src/lib.rs) for how to configure the `DataStorageBuilder`. - [`update_request_stats` function](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/data-storage-stats/src/lib.rs) for how the policy uses CAS operations with retry logic for concurrent updates. - [`get_all_stats` function](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/data-storage-stats/src/lib.rs) for how the policy retrieves stored data. ## Redis Shared Storage Configuration Example For an example of how to configure Redis shared storage for testing, see the example [`playground/config/shared-storage-redis.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/data-storage-stats/playground/config/shared-storage-redis.yaml) and [`playground/docker-compose.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/data-storage-stats/playground/docker-compose.yaml) files. ## See Also - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-share-data) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Configuring Data Storage > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use PDK’s `DataStorageBuilder` to implement data storage in custom policies. Choose local in-memory storage for single-replica deployments or shared Redis storage for multi-replica deployments or deployments that require persistent data storage. Store and retrieve data with thread-safe operations including Compare-And-Swap (CAS), Absent, and Always operations. Configure namespaces for key isolation and set time-to-live values for automatic data expiration in shared storage. For multi-replica deployments or persistent data storage, you must configure shared storage. To configure shared storage, see: - [Configuring Redis Shared Storage for Omni Gateway in Connected Mode](https://docs.mulesoft.com/gateway/latest/conn-shared-storage-config) - [Configuring Redis Shared Storage for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-shared-storage-config) To use data storage functionality, inject the `DataStorageBuilder` in your the `entrypoint` and pass the storage instance to your request handlers: ```Rust // for local storage let storage = store_builder.local(namespace); // or for remote storage let storage = store_builder.remote(namespace, ttl_millis); ``` Storage builder parameters: - `namespace`: a string prefix for key isolation (required) - `ttl_millis`: time-to-live in milliseconds for automatic data expiration (only required for remote storage) After creating the storage instance, store and retrieve data with support for CAS, Absent, and Always operations for thread safety: ```Rust // Store data with CAS operation let (current_data, version) = storage.get::(&key).await?; let mode = StoreMode::Cas(version); storage.store(&key, &mode, &new_data).await?; // Retrieve data - Generic type parameter specifies the expected data type let (data, version) = storage.get::(&key).await?; ``` The `StoreMode` enum supports these operations: - `Cas` (Compare-And-Swap): Updates the value only if the current version matches the expected version. Use this operation for thread-safe conditional updates to ensure data hasn’t changed since you last read it. - `Absent`: Stores the value only if the key doesn’t exist. Use this operation to initialize values without overwriting existing data. - `Always`: Always stores the value, overwriting any existing value regardless of version. Use this operation to unconditionally update or create a key. ## Data Storage Configuration Examples PDK provides the [Data Storage Stats Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.6.0/data-storage-stats) to demonstrate how to configure data storage in Rust code. Within the example policy, see these functions for further configuration details: - [`entrypoint` function](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/data-storage-stats/src/lib.rs) for how to configure the `DataStorageBuilder`. - [`update_request_stats` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.6.0/data-storage-stats/src/lib.rs#L58) for how the policy uses CAS operations with retry logic for concurrent updates. - [`get_all_stats` function](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/data-storage-stats/src/lib.rs) for how the policy retrieves stored data. ## Redis Shared Storage Configuration Example For an example of how to configure Redis shared storage for testing, see the example [`playground/config/shared-storage-redis.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/data-storage-stats/playground/config/shared-storage-redis.yaml) and [`playground/docker-compose.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/data-storage-stats/playground/docker-compose.yaml) files. ## See Also - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-share-data) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Configuring Data Storage > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use PDK’s `DataStorageBuilder` to implement data storage in custom policies. Choose local in-memory storage for single-replica deployments or shared Redis storage for multi-replica deployments or deployments that require persistent data storage. Store and retrieve data with thread-safe operations including Compare-And-Swap (CAS), Absent, and Always operations. Configure namespaces for key isolation and set time-to-live values for automatic data expiration in shared storage. For multi-replica deployments or persistent data storage, you must configure shared storage. To configure shared storage, see: - [Configuring Redis Shared Storage for Omni Gateway in Connected Mode](https://docs.mulesoft.com/gateway/latest/conn-shared-storage-config) - [Configuring Redis Shared Storage for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-shared-storage-config) To use data storage functionality, inject the `DataStorageBuilder` in your the `entrypoint` and pass the storage instance to your request handlers: ```Rust // for local storage let storage = store_builder.local(namespace); // or for remote storage let storage = store_builder.remote(namespace, ttl_millis); ``` Storage builder parameters: - `namespace`: a string prefix for key isolation (required) - `ttl_millis`: time-to-live in milliseconds for automatic data expiration (only required for remote storage) After creating the storage instance, store and retrieve data with support for CAS, Absent, and Always operations for thread safety: ```Rust // Store data with CAS operation let (current_data, version) = storage.get::(&key).await?; let mode = StoreMode::Cas(version); storage.store(&key, &mode, &new_data).await?; // Retrieve data - Generic type parameter specifies the expected data type let (data, version) = storage.get::(&key).await?; ``` The `StoreMode` enum supports these operations: - `Cas` (Compare-And-Swap): Updates the value only if the current version matches the expected version. Use this operation for thread-safe conditional updates to ensure data hasn’t changed since you last read it. - `Absent`: Stores the value only if the key doesn’t exist. Use this operation to initialize values without overwriting existing data. - `Always`: Always stores the value, overwriting any existing value regardless of version. Use this operation to unconditionally update or create a key. ## Data Storage Configuration Examples PDK provides the [Data Storage Stats Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.6.0/data-storage-stats) to demonstrate how to configure data storage in Rust code. Within the example policy, see these functions for further configuration details: - [`entrypoint` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.6.0/data-storage-stats/src/lib.rs#L210) for how to configure the `DataStorageBuilder`. - [`update_request_stats` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.6.0/data-storage-stats/src/lib.rs#L58) for how the policy uses CAS operations with retry logic for concurrent updates. - [`get_all_stats` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.6.0/data-storage-stats/src/lib.rs#L111) for how the policy retrieves stored data. ## Redis Shared Storage Configuration Example For an example of how to configure Redis shared storage for testing, see the example [`playground/config/shared-storage-redis.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/data-storage-stats/playground/config/shared-storage-redis.yaml) and [`playground/docker-compose.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/data-storage-stats/playground/docker-compose.yaml) files. ## See Also - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-share-data) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Configuring Data Storage > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use PDK’s `DataStorageBuilder` to implement data storage in custom policies. Choose local in-memory storage for single-replica deployments or shared Redis storage for multi-replica deployments or deployments that require persistent data storage. Store and retrieve data with thread-safe operations including Compare-And-Swap (CAS), Absent, and Always operations. Configure namespaces for key isolation and set time-to-live values for automatic data expiration in shared storage. For multi-replica deployments or persistent data storage, you must configure shared storage. To configure shared storage, see: - [Configuring Redis Shared Storage for Omni Gateway in Connected Mode](https://docs.mulesoft.com/gateway/latest/conn-shared-storage-config) - [Configuring Redis Shared Storage for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-shared-storage-config) To use data storage functionality, inject the `DataStorageBuilder` in your the `entrypoint` and pass the storage instance to your request handlers: ```Rust // for local storage let storage = store_builder.local(namespace); // or for remote storage let storage = store_builder.remote(namespace, ttl_millis); ``` Storage builder parameters: - `namespace`: a string prefix for key isolation (required) - `ttl_millis`: time-to-live in milliseconds for automatic data expiration (only required for remote storage) After creating the storage instance, store and retrieve data with support for CAS, Absent, and Always operations for thread safety: ```Rust // Store data with CAS operation let (current_data, version) = storage.get::(&key).await?; let mode = StoreMode::Cas(version); storage.store(&key, &mode, &new_data).await?; // Retrieve data - Generic type parameter specifies the expected data type let (data, version) = storage.get::(&key).await?; ``` The `StoreMode` enum supports these operations: - `Cas` (Compare-And-Swap): Updates the value only if the current version matches the expected version. Use this operation for thread-safe conditional updates to ensure data hasn’t changed since you last read it. - `Absent`: Stores the value only if the key doesn’t exist. Use this operation to initialize values without overwriting existing data. - `Always`: Always stores the value, overwriting any existing value regardless of version. Use this operation to unconditionally update or create a key. ## Data Storage Configuration Examples PDK provides the [Data Storage Stats Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.8.0/data-storage-stats) to demonstrate how to configure data storage in Rust code. Within the example policy, see these functions for further configuration details: - [`entrypoint` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.8.0/data-storage-stats/src/lib.rs#L210) for how to configure the `DataStorageBuilder`. - [`update_request_stats` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.8.0/data-storage-stats/src/lib.rs#L58) for how the policy uses CAS operations with retry logic for concurrent updates. - [`get_all_stats` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.8.0/data-storage-stats/src/lib.rs#L111) for how the policy retrieves stored data. ## Redis Shared Storage Configuration Example For an example of how to configure Redis shared storage for testing, see the example [`playground/config/shared-storage-redis.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/data-storage-stats/playground/config/shared-storage-redis.yaml) and [`playground/docker-compose.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/data-storage-stats/playground/docker-compose.yaml) files. ## See Also - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-share-data) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Configuring Data Storage > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use PDK’s `DataStorageBuilder` to implement data storage in custom policies. Choose local in-memory storage for single-replica deployments or shared Redis storage for multi-replica deployments or deployments that require persistent data storage. Store and retrieve data with thread-safe operations including Compare-And-Swap (CAS), Absent, and Always operations. Configure namespaces for key isolation and set time-to-live values for automatic data expiration in shared storage. For multi-replica deployments or persistent data storage, you must configure shared storage. To configure shared storage, see: - [Configuring Redis Shared Storage for Omni Gateway in Connected Mode](https://docs.mulesoft.com/gateway/latest/conn-shared-storage-config) - [Configuring Redis Shared Storage for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-shared-storage-config) To use data storage functionality, inject the `DataStorageBuilder` in your the `entrypoint` and pass the storage instance to your request handlers: ```Rust // for local storage let storage = store_builder.local(namespace); // or for remote storage let storage = store_builder.remote(namespace, ttl_millis); ``` Storage builder parameters: - `namespace`: a string prefix for key isolation (required) - `ttl_millis`: time-to-live in milliseconds for automatic data expiration (only required for remote storage) After creating the storage instance, store and retrieve data with support for CAS, Absent, and Always operations for thread safety: ```Rust // Store data with CAS operation let (current_data, version) = storage.get::(&key).await?; let mode = StoreMode::Cas(version); storage.store(&key, &mode, &new_data).await?; // Retrieve data - Generic type parameter specifies the expected data type let (data, version) = storage.get::(&key).await?; ``` The `StoreMode` enum supports these operations: - `Cas` (Compare-And-Swap): Updates the value only if the current version matches the expected version. Use this operation for thread-safe conditional updates to ensure data hasn’t changed since you last read it. - `Absent`: Stores the value only if the key doesn’t exist. Use this operation to initialize values without overwriting existing data. - `Always`: Always stores the value, overwriting any existing value regardless of version. Use this operation to unconditionally update or create a key. ## Data Storage Configuration Examples PDK provides the [Data Storage Stats Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.9.0/data-storage-stats) to demonstrate how to configure data storage in Rust code. Within the example policy, see these functions for further configuration details: - [`entrypoint` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.9.0/data-storage-stats/src/lib.rs#L210) for how to configure the `DataStorageBuilder`. - [`update_request_stats` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.9.0/data-storage-stats/src/lib.rs#L58) for how the policy uses CAS operations with retry logic for concurrent updates. - [`get_all_stats` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.9.0/data-storage-stats/src/lib.rs#L111) for how the policy retrieves stored data. ## Redis Shared Storage Configuration Example For an example of how to configure Redis shared storage for testing, see the example [`playground/config/shared-storage-redis.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/data-storage-stats/playground/config/shared-storage-redis.yaml) and [`playground/docker-compose.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/data-storage-stats/playground/docker-compose.yaml) files. ## See Also - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-share-data) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Configuring Data Storage > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use PDK’s `DataStorageBuilder` to implement data storage in custom policies. Choose local in-memory storage for single-replica deployments or shared Redis storage for multi-replica deployments or deployments that require persistent data storage. Store and retrieve data with thread-safe operations including Compare-And-Swap (CAS), Absent, and Always operations. Configure namespaces for key isolation and set time-to-live values for automatic data expiration in shared storage. For multi-replica deployments or persistent data storage, you must configure shared storage. To configure shared storage, see: - [Configuring Redis Shared Storage for Omni Gateway in Connected Mode](https://docs.mulesoft.com/gateway/latest/conn-shared-storage-config) - [Configuring Redis Shared Storage for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-shared-storage-config) To use data storage functionality, inject the `DataStorageBuilder` in your the `entrypoint` and pass the storage instance to your request handlers: ```Rust // for local storage let storage = store_builder.local(namespace); // or for remote storage let storage = store_builder.remote(namespace, ttl_millis); ``` Storage builder parameters: - `namespace`: a string prefix for key isolation (required) - `ttl_millis`: time-to-live in milliseconds for automatic data expiration (only required for remote storage) After creating the storage instance, store and retrieve data with support for CAS, Absent, and Always operations for thread safety: ```Rust // Store data with CAS operation let (current_data, version) = storage.get::(&key).await?; let mode = StoreMode::Cas(version); storage.store(&key, &mode, &new_data).await?; // Retrieve data - Generic type parameter specifies the expected data type let (data, version) = storage.get::(&key).await?; ``` The `StoreMode` enum supports these operations: - `Cas` (Compare-And-Swap): Updates the value only if the current version matches the expected version. Use this operation for thread-safe conditional updates to ensure data hasn’t changed since you last read it. - `Absent`: Stores the value only if the key doesn’t exist. Use this operation to initialize values without overwriting existing data. - `Always`: Always stores the value, overwriting any existing value regardless of version. Use this operation to unconditionally update or create a key. ## Data Storage Configuration Examples PDK provides the [Data Storage Stats Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.10.0/data-storage-stats) to demonstrate how to configure data storage in Rust code. Within the example policy, see these functions for further configuration details: - [`entrypoint` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.10.0/data-storage-stats/src/lib.rs#L210) for how to configure the `DataStorageBuilder`. - [`update_request_stats` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.10.0/data-storage-stats/src/lib.rs#L58) for how the policy uses CAS operations with retry logic for concurrent updates. - [`get_all_stats` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.10.0/data-storage-stats/src/lib.rs#L111) for how the policy retrieves stored data. ## Redis Shared Storage Configuration Example For an example of how to configure Redis shared storage for testing, see the example [`playground/config/shared-storage-redis.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/data-storage-stats/playground/config/shared-storage-redis.yaml) and [`playground/docker-compose.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/data-storage-stats/playground/docker-compose.yaml) files. ## See Also - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-share-data) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Configuring Delayed, Periodic, and Synchronous Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the `Clock` injectable to build a timer to enable delayed, periodic, and synchronous functions. Each policy supports only one timer. Each timer provides the following two functions: ```rust pub async fn next_tick(&self) -> bool; pub async fn sleep(&self, interval: Duration) -> bool; ``` - `next_tick`: Sleeps for the minimum amount of time the timer is capable of distinguishing. - `sleep`: Sleeps for an amount of ticks where the elapsed time is greater or equal than the provided `Duration`. For example, if you configure the period of the clock to 10 seconds, calling `timer.sleep(Duration::from_secs(1))` sleeps for 10 seconds. Both functions return `true` when the specified time has passed or `false` if the policy is unapplied or edited during execution. ## Configure the Timer To inject a timer in your policy, insert a `Clock` into your policy configuration function and define a timer with a time period: ```rust #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, clock: Clock, // Inject the clock to be able to launch async tasks. client: HttpClient, ) -> Result<()> { // set the period between ticks of the timer. let timer = clock.period(Duration::from_secs(10)); ``` After you inject the timer, share a its reference with the `on_request` and `on_response` functions to begin creating delayed functions: ```rust launcher .launch(on_request(|rs| request_filter(rs, &timer, &config))) .await?; ``` You can now await timer functions in `on_request` and `on_response` functions, for example: ```rust let slept = timer.sleep(duration).await; let tick = timer.next_tick().await; ``` > [!NOTE] To view an example policy project that launches delayed functions, see > [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/spike/README.md). ## Launch Asynchronous Tasks Use the timer to execute tasks independent of the request flow. To execute asynchronous tasks: 1. Define your task inside an `async` function. 2. In the policy configuration function, call your function but don’t await the returned future. 3. In the policy configuration function, call the `launch` function with the `on_request` and `on_response` filter functions but don’t await the returned future. 4. Use the `join!` macro to await both futures of your task function and `launch` function at the same time. > [!NOTE] To use the `join` macro, add the ‘futures’ crate as dependency in your `cargo.toml` > file. Each worker executes a copy of the task. Configure a loop inside the function to execute periodic tasks. For example, the following code example awaits both functions: ```rust let task = my_async_task(&timer, &config); let launched = launcher.launch(filter); let joined = join!(launched, task); ``` Adding a loop to the `my_async_task` function creates periodic tasks, for example: ```rust async fn my_async_task(timer: &Timer, config: &Config) { // While the policy is still running. // Wait for the next cycle. while timer.next_tick().await { // Execute periodic task } } ``` To launch multiple asynchronous tasks, send a reference of the timer to your `async` functions and join them with the `launch` task, for example: ```rust let task1 = my_async_task1(&timer, &config); let task2 = my_async_task2(&timer, &config); let launched = launcher.launch(filter); let joined = join!(launched, task1, task2); ``` > [!NOTE] To view an example policy project that launches asynchronous periodic tasks, see > [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/metrics/README.md). ## Sync Asynchronous Tasks between Workers Use the PDK `LockBuilder` to sync workers. The lock ensures that only one worker is completing a task in a time period. Each policy supports multiple locks. Locks are useful when a policy consumes an HTTP service that has usage limits. A single worker can fetch data and then share the data with other workers to reduce service requests. To configure a lock: 1. Inject the `LockBuilder` into your policy configuration function: ```rust #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, clock: Clock, // Inject the clock to be able to launch async tasks. lock: LockBuilder, // Inject the lock to be able to synchronize the workers. ) -> Result<()> { ``` 2. Configure the lock and share a reference of it with your asynchronous function: ```rust let lock = lock .new(ID.to_string()) .expiration(Duration::from_secs(20)) .build(); let task = my_async_task(&timer, &lock); ``` If the asynchronous task executes additional `async` function calls inside the task, configure the `expiration` of the lock to a duration longer than the total time needed to complete the nested `async` function calls. 3. Inside the asynchronous function, acquire the lock before executing the desired task. If no other worker has the lock, the current worker acquires the lock. Otherwise, you must omit the execution of the task and wait for the next task loop, for example: ```rust async fn my_async_task( timer: &Timer, lock: &TryLock, ) { while timer.next_tick().await { if let Some(acquired) = lock.try_lock() { // execute task. } } } ``` After obtaining the lock, if you execute code that requires you await a result, you must call the `refresh_lock` function to ensure the lock hasn’t expired. If the lock has expired, the worker is considered unresponsive. Abort the execution of your task because another worker is running the same task execution. > [!NOTE] To view an example policy project that synchronizes asynchronous periodic tasks and shares > information between workers, see > [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/block/README.md). ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Configuring Delayed, Periodic, and Synchronous Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the `Clock` injectable to build a timer to enable delayed, periodic, and synchronous functions. Each policy supports only one timer. Each timer provides the following async methods: ```rust pub async fn next_tick(&self) -> bool; pub async fn sleep(&self, interval: Duration) -> bool; ``` - `next_tick`: Sleeps for the minimum amount of time the timer is capable of distinguishing. - `sleep`: Sleeps for an amount of ticks where the elapsed time is greater or equal than the provided `Duration`. For example, if you configure the period of the clock to 10 seconds, calling `timer.sleep(Duration::from_secs(1))` sleeps for 10 seconds. Both functions return `true` when the specified time has passed or `false` if the policy is unapplied or edited during execution. ## Configure the Timer To inject a timer in your policy, insert a `Clock` into your policy configuration function and define a timer with a time period: ```rust #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, clock: Clock, // Inject the clock to be able to launch async tasks. client: HttpClient, ) -> Result<()> { // set the period between ticks of the timer. let timer = clock.period(Duration::from_secs(10)); ``` After you inject the timer, share a its reference with the `on_request` and `on_response` functions to begin creating delayed functions: ```rust launcher .launch(on_request(|rs| request_filter(rs, &timer, &config))) .await?; ``` You can now await timer functions in `on_request` and `on_response` functions, for example: ```rust let slept = timer.sleep(duration).await; let tick = timer.next_tick().await; ``` > [!NOTE] To view an example policy project that launches delayed functions, see > [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/spike/README.md). ## Release the Clock To create a new timer with a different tick period, release the `Clock` by using the following method: ```rust pub fn release(self) -> Clock; ``` The following code snippet creates a timer and then releases the clock to create a new timer: ```rust // Configure an initial tick period. let initial_timer = clock.period(Duration::from_millis(500)); some_initial_task(&other_timer).await; // Configure another tick period. let other_timer = initial_timer.release().period(Duration::from_millis(3000); some_other_task(&other_timer).await; // Get the clock back. let clock = other_timer.release(); ``` ## Launch Asynchronous Tasks Use the timer to execute tasks independent of the request flow. To execute asynchronous tasks: 1. Define your task inside an `async` function. 2. In the policy configuration function, call your function but don’t await the returned future. 3. In the policy configuration function, call the `launch` function with the `on_request` and `on_response` filter functions but don’t await the returned future. 4. Use the `join!` macro to await both futures of your task function and `launch` function at the same time. > [!NOTE] To use the `join` macro, add the ‘futures’ crate as dependency in your `cargo.toml` > file. Each worker executes a copy of the task. Configure a loop inside the function to execute periodic tasks. For example, the following code example awaits both functions: ```rust let task = my_async_task(&timer, &config); let launched = launcher.launch(filter); let joined = join!(launched, task); ``` Adding a loop to the `my_async_task` function creates periodic tasks, for example: ```rust async fn my_async_task(timer: &Timer, config: &Config) { // While the policy is still running. // Wait for the next cycle. while timer.next_tick().await { // Execute periodic task } } ``` To launch multiple asynchronous tasks, send a reference of the timer to your `async` functions and join them with the `launch` task, for example: ```rust let task1 = my_async_task1(&timer, &config); let task2 = my_async_task2(&timer, &config); let launched = launcher.launch(filter); let joined = join!(launched, task1, task2); ``` > [!NOTE] To view an example policy project that launches asynchronous periodic tasks, see > [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/metrics/README.md). ## Sync Asynchronous Tasks between Workers Use the PDK `LockBuilder` to sync workers. The lock ensures that only one worker is completing a task in a time period. Each policy supports multiple locks. Locks are useful when a policy consumes an HTTP service that has usage limits. A single worker can fetch data and then share the data with other workers to reduce service requests. To configure a lock: 1. Inject the `LockBuilder` into your policy configuration function: ```rust #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, clock: Clock, // Inject the clock to be able to launch async tasks. lock: LockBuilder, // Inject the lock to be able to synchronize the workers. ) -> Result<()> { ``` 2. Configure the lock and share a reference of it with your asynchronous function: ```rust let lock = lock .new(ID.to_string()) .expiration(Duration::from_secs(20)) .build(); let task = my_async_task(&timer, &lock); ``` If the asynchronous task executes additional `async` function calls inside the task, configure the `expiration` of the lock to a duration longer than the total time needed to complete the nested `async` function calls. 3. Inside the asynchronous function, acquire the lock before executing the desired task. If no other worker has the lock, the current worker acquires the lock. Otherwise, you must omit the execution of the task and wait for the next task loop, for example: ```rust async fn my_async_task( timer: &Timer, lock: &TryLock, ) { while timer.next_tick().await { if let Some(acquired) = lock.try_lock() { // execute task. } } } ``` After obtaining the lock, if you execute code that requires you await a result, you must call the `refresh_lock` function to ensure the lock hasn’t expired. If the lock has expired, the worker is considered unresponsive. Abort the execution of your task because another worker is running the same task execution. > [!NOTE] To view an example policy project that synchronizes asynchronous periodic tasks and shares > information between workers, see > [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/block/README.md). ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Configuring Delayed, Periodic, and Synchronous Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the `Clock` injectable to build a timer to enable delayed, periodic, and synchronous functions. Each policy supports only one timer. Each timer provides the following async methods: ```rust pub async fn next_tick(&self) -> bool; pub async fn sleep(&self, interval: Duration) -> bool; ``` - `next_tick`: Sleeps for the minimum amount of time the timer is capable of distinguishing. - `sleep`: Sleeps for an amount of ticks where the elapsed time is greater or equal than the provided `Duration`. For example, if you configure the period of the clock to 10 seconds, calling `timer.sleep(Duration::from_secs(1))` sleeps for 10 seconds. Both functions return `true` when the specified time has passed or `false` if the policy is unapplied or edited during execution. ## Configure the Timer To inject a timer in your policy, insert a `Clock` into your policy configuration function and define a timer with a time period: ```rust #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, clock: Clock, // Inject the clock to be able to launch async tasks. client: HttpClient, ) -> Result<()> { // set the period between ticks of the timer. let timer = clock.period(Duration::from_secs(10)); ``` After you inject the timer, share a its reference with the `on_request` and `on_response` functions to begin creating delayed functions: ```rust launcher .launch(on_request(|rs| request_filter(rs, &timer, &config))) .await?; ``` You can now await timer functions in `on_request` and `on_response` functions, for example: ```rust let slept = timer.sleep(duration).await; let tick = timer.next_tick().await; ``` > [!NOTE] To view an example policy project that launches delayed functions, see > [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/spike/README.md). ## Release the Clock To create a new timer with a different tick period, release the `Clock` by using the following method: ```rust pub fn release(self) -> Clock; ``` The following code snippet creates a timer and then releases the clock to create a new timer: ```rust // Configure an initial tick period. let initial_timer = clock.period(Duration::from_millis(500)); some_initial_task(&other_timer).await; // Configure another tick period. let other_timer = initial_timer.release().period(Duration::from_millis(3000); some_other_task(&other_timer).await; // Get the clock back. let clock = other_timer.release(); ``` ## Launch Asynchronous Tasks Use the timer to execute tasks independent of the request flow. To execute asynchronous tasks: 1. Define your task inside an `async` function. 2. In the policy configuration function, call your function but don’t await the returned future. 3. In the policy configuration function, call the `launch` function with the `on_request` and `on_response` filter functions but don’t await the returned future. 4. Use the `join!` macro to await both futures of your task function and `launch` function at the same time. > [!NOTE] To use the `join` macro, add the ‘futures’ crate as dependency in your `cargo.toml` > file. Each worker executes a copy of the task. Configure a loop inside the function to execute periodic tasks. For example, the following code example awaits both functions: ```rust let task = my_async_task(&timer, &config); let launched = launcher.launch(filter); let joined = join!(launched, task); ``` Adding a loop to the `my_async_task` function creates periodic tasks, for example: ```rust async fn my_async_task(timer: &Timer, config: &Config) { // While the policy is still running. // Wait for the next cycle. while timer.next_tick().await { // Execute periodic task } } ``` To launch multiple asynchronous tasks, send a reference of the timer to your `async` functions and join them with the `launch` task, for example: ```rust let task1 = my_async_task1(&timer, &config); let task2 = my_async_task2(&timer, &config); let launched = launcher.launch(filter); let joined = join!(launched, task1, task2); ``` > [!NOTE] To view an example policy project that launches asynchronous periodic tasks, see > [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/metrics/README.md). ## Sync Asynchronous Tasks between Workers Use the PDK `LockBuilder` to sync workers. The lock ensures that only one worker is completing a task in a time period. Each policy supports multiple locks. Locks are useful when a policy consumes an HTTP service that has usage limits. A single worker can fetch data and then share the data with other workers to reduce service requests. To configure a lock: 1. Inject the `LockBuilder` into your policy configuration function: ```rust #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, clock: Clock, // Inject the clock to be able to launch async tasks. lock: LockBuilder, // Inject the lock to be able to synchronize the workers. ) -> Result<()> { ``` 2. Configure the lock and share a reference of it with your asynchronous function: ```rust let lock = lock .new(ID.to_string()) .expiration(Duration::from_secs(20)) .build(); let task = my_async_task(&timer, &lock); ``` If the asynchronous task executes additional `async` function calls inside the task, configure the `expiration` of the lock to a duration longer than the total time needed to complete the nested `async` function calls. 3. Inside the asynchronous function, acquire the lock before executing the desired task. If no other worker has the lock, the current worker acquires the lock. Otherwise, you must omit the execution of the task and wait for the next task loop, for example: ```rust async fn my_async_task( timer: &Timer, lock: &TryLock, ) { while timer.next_tick().await { if let Some(acquired) = lock.try_lock() { // execute task. } } } ``` After obtaining the lock, if you execute code that requires you await a result, you must call the `refresh_lock` function to ensure the lock hasn’t expired. If the lock has expired, the worker is considered unresponsive. Abort the execution of your task because another worker is running the same task execution. > [!NOTE] To view an example policy project that synchronizes asynchronous periodic tasks and shares > information between workers, see > [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/block/README.md). ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Configuring Delayed, Periodic, and Synchronous Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the `Clock` injectable to build a timer to enable delayed, periodic, and synchronous functions. Each policy supports only one timer. Each timer provides the following async methods: ```rust pub async fn next_tick(&self) -> bool; pub async fn sleep(&self, interval: Duration) -> bool; ``` - `next_tick`: Sleeps for the minimum amount of time the timer is capable of distinguishing. - `sleep`: Sleeps for an amount of ticks where the elapsed time is greater or equal than the provided `Duration`. For example, if you configure the period of the clock to 10 seconds, calling `timer.sleep(Duration::from_secs(1))` sleeps for 10 seconds. Both functions return `true` when the specified time has passed or `false` if the policy is unapplied or edited during execution. ## Configure the Timer To inject a timer in your policy, insert a `Clock` into your policy configuration function and define a timer with a time period: ```rust #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, clock: Clock, // Inject the clock to be able to launch async tasks. client: HttpClient, ) -> Result<()> { // set the period between ticks of the timer. let timer = clock.period(Duration::from_secs(10)); ``` After you inject the timer, share a its reference with the `on_request` and `on_response` functions to begin creating delayed functions: ```rust launcher .launch(on_request(|rs| request_filter(rs, &timer, &config))) .await?; ``` You can now await timer functions in `on_request` and `on_response` functions, for example: ```rust let slept = timer.sleep(duration).await; let tick = timer.next_tick().await; ``` > [!NOTE] To view an example policy project that launches delayed functions, see > [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/spike/README.md). ## Release the Clock To create a new timer with a different tick period, release the `Clock` by using the following method: ```rust pub fn release(self) -> Clock; ``` The following code snippet creates a timer and then releases the clock to create a new timer: ```rust // Configure an initial tick period. let initial_timer = clock.period(Duration::from_millis(500)); some_initial_task(&other_timer).await; // Configure another tick period. let other_timer = initial_timer.release().period(Duration::from_millis(3000); some_other_task(&other_timer).await; // Get the clock back. let clock = other_timer.release(); ``` ## Launch Asynchronous Tasks Use the timer to execute tasks independent of the request flow. To execute asynchronous tasks: 1. Define your task inside an `async` function. 2. In the policy configuration function, call your function but don’t await the returned future. 3. In the policy configuration function, call the `launch` function with the `on_request` and `on_response` filter functions but don’t await the returned future. 4. Use the `join!` macro to await both futures of your task function and `launch` function at the same time. > [!NOTE] To use the `join` macro, add the ‘futures’ crate as dependency in your `cargo.toml` > file. Each worker executes a copy of the task. Configure a loop inside the function to execute periodic tasks. For example, the following code example awaits both functions: ```rust let task = my_async_task(&timer, &config); let launched = launcher.launch(filter); let joined = join!(launched, task); ``` Adding a loop to the `my_async_task` function creates periodic tasks, for example: ```rust async fn my_async_task(timer: &Timer, config: &Config) { // While the policy is still running. // Wait for the next cycle. while timer.next_tick().await { // Execute periodic task } } ``` To launch multiple asynchronous tasks, send a reference of the timer to your `async` functions and join them with the `launch` task, for example: ```rust let task1 = my_async_task1(&timer, &config); let task2 = my_async_task2(&timer, &config); let launched = launcher.launch(filter); let joined = join!(launched, task1, task2); ``` > [!NOTE] To view an example policy project that launches asynchronous periodic tasks, see > [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/metrics/README.md). ## Sync Asynchronous Tasks between Workers Use the PDK `LockBuilder` to sync workers. The lock ensures that only one worker is completing a task in a time period. Each policy supports multiple locks. Locks are useful when a policy consumes an HTTP service that has usage limits. A single worker can fetch data and then share the data with other workers to reduce service requests. To configure a lock: 1. Inject the `LockBuilder` into your policy configuration function: ```rust #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, clock: Clock, // Inject the clock to be able to launch async tasks. lock: LockBuilder, // Inject the lock to be able to synchronize the workers. ) -> Result<()> { ``` 2. Configure the lock and share a reference of it with your asynchronous function: ```rust let lock = lock .new(ID.to_string()) .expiration(Duration::from_secs(20)) .build(); let task = my_async_task(&timer, &lock); ``` If the asynchronous task executes additional `async` function calls inside the task, configure the `expiration` of the lock to a duration longer than the total time needed to complete the nested `async` function calls. 3. Inside the asynchronous function, acquire the lock before executing the desired task. If no other worker has the lock, the current worker acquires the lock. Otherwise, you must omit the execution of the task and wait for the next task loop, for example: ```rust async fn my_async_task( timer: &Timer, lock: &TryLock, ) { while timer.next_tick().await { if let Some(acquired) = lock.try_lock() { // execute task. } } } ``` After obtaining the lock, if you execute code that requires you await a result, you must call the `refresh_lock` function to ensure the lock hasn’t expired. If the lock has expired, the worker is considered unresponsive. Abort the execution of your task because another worker is running the same task execution. > [!NOTE] To view an example policy project that synchronizes asynchronous periodic tasks and shares > information between workers, see > [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/block/README.md). ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-inject-parameters) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Configuring Delayed, Periodic, and Synchronous Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the `Clock` injectable to build a timer to enable delayed, periodic, and synchronous functions. Each policy supports only one timer. Each timer provides the following async methods: ```rust pub async fn next_tick(&self) -> bool; pub async fn sleep(&self, interval: Duration) -> bool; ``` - `next_tick`: Sleeps for the minimum amount of time the timer is capable of distinguishing. - `sleep`: Sleeps for an amount of ticks where the elapsed time is greater or equal than the provided `Duration`. For example, if you configure the period of the clock to 10 seconds, calling `timer.sleep(Duration::from_secs(1))` sleeps for 10 seconds. Both functions return `true` when the specified time has passed or `false` if the policy is unapplied or edited during execution. ## Configure the Timer To inject a timer in your policy, insert a `Clock` into your policy configuration function and define a timer with a time period: ```rust #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, clock: Clock, // Inject the clock to be able to launch async tasks. client: HttpClient, ) -> Result<()> { // set the period between ticks of the timer. let timer = clock.period(Duration::from_secs(10)); ``` After you inject the timer, share a its reference with the `on_request` and `on_response` functions to begin creating delayed functions: ```rust launcher .launch(on_request(|rs| request_filter(rs, &timer, &config))) .await?; ``` You can now await timer functions in `on_request` and `on_response` functions, for example: ```rust let slept = timer.sleep(duration).await; let tick = timer.next_tick().await; ``` > [!NOTE] To view an example policy project that launches delayed functions, see > [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/spike/README.md). ## Release the Clock To create a new timer with a different tick period, release the `Clock` by using the following method: ```rust pub fn release(self) -> Clock; ``` The following code snippet creates a timer and then releases the clock to create a new timer: ```rust // Configure an initial tick period. let initial_timer = clock.period(Duration::from_millis(500)); some_initial_task(&other_timer).await; // Configure another tick period. let other_timer = initial_timer.release().period(Duration::from_millis(3000); some_other_task(&other_timer).await; // Get the clock back. let clock = other_timer.release(); ``` ## Launch Asynchronous Tasks Use the timer to execute tasks independent of the request flow. To execute asynchronous tasks: 1. Define your task inside an `async` function. 2. In the policy configuration function, call your function but don’t await the returned future. 3. In the policy configuration function, call the `launch` function with the `on_request` and `on_response` filter functions but don’t await the returned future. 4. Use the `join!` macro to await both futures of your task function and `launch` function at the same time. > [!NOTE] To use the `join` macro, add the ‘futures’ crate as dependency in your `cargo.toml` > file. Each worker executes a copy of the task. Configure a loop inside the function to execute periodic tasks. For example, the following code example awaits both functions: ```rust let task = my_async_task(&timer, &config); let launched = launcher.launch(filter); let joined = join!(launched, task); ``` Adding a loop to the `my_async_task` function creates periodic tasks, for example: ```rust async fn my_async_task(timer: &Timer, config: &Config) { // While the policy is still running. // Wait for the next cycle. while timer.next_tick().await { // Execute periodic task } } ``` To launch multiple asynchronous tasks, send a reference of the timer to your `async` functions and join them with the `launch` task, for example: ```rust let task1 = my_async_task1(&timer, &config); let task2 = my_async_task2(&timer, &config); let launched = launcher.launch(filter); let joined = join!(launched, task1, task2); ``` > [!NOTE] To view an example policy project that launches asynchronous periodic tasks, see > [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/metrics/README.md). ## Sync Asynchronous Tasks between Workers Use the PDK `LockBuilder` to sync workers. The lock ensures that only one worker is completing a task in a time period. Each policy supports multiple locks. Locks are useful when a policy consumes an HTTP service that has usage limits. A single worker can fetch data and then share the data with other workers to reduce service requests. To configure a lock: 1. Inject the `LockBuilder` into your policy configuration function: ```rust #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, clock: Clock, // Inject the clock to be able to launch async tasks. lock: LockBuilder, // Inject the lock to be able to synchronize the workers. ) -> Result<()> { ``` 2. Configure the lock and share a reference of it with your asynchronous function: ```rust let lock = lock .new(ID.to_string()) .expiration(Duration::from_secs(20)) .build(); let task = my_async_task(&timer, &lock); ``` If the asynchronous task executes additional `async` function calls inside the task, configure the `expiration` of the lock to a duration longer than the total time needed to complete the nested `async` function calls. 3. Inside the asynchronous function, acquire the lock before executing the desired task. If no other worker has the lock, the current worker acquires the lock. Otherwise, you must omit the execution of the task and wait for the next task loop, for example: ```rust async fn my_async_task( timer: &Timer, lock: &TryLock, ) { while timer.next_tick().await { if let Some(acquired) = lock.try_lock() { // execute task. } } } ``` After obtaining the lock, if you execute code that requires you await a result, you must call the `refresh_lock` function to ensure the lock hasn’t expired. If the lock has expired, the worker is considered unresponsive. Abort the execution of your task because another worker is running the same task execution. > [!NOTE] To view an example policy project that synchronizes asynchronous periodic tasks and shares > information between workers, see > [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/block/README.md). ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-inject-parameters) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Configuring Delayed, Periodic, and Synchronous Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the `Clock` injectable to build a timer to enable delayed, periodic, and synchronous functions. Each policy supports only one timer. Each timer provides the following async methods: ```rust pub async fn next_tick(&self) -> bool; pub async fn sleep(&self, interval: Duration) -> bool; ``` - `next_tick`: Sleeps for the minimum amount of time the timer is capable of distinguishing. - `sleep`: Sleeps for an amount of ticks where the elapsed time is greater or equal than the provided `Duration`. For example, if you configure the period of the clock to 10 seconds, calling `timer.sleep(Duration::from_secs(1))` sleeps for 10 seconds. Both functions return `true` when the specified time has passed or `false` if the policy is unapplied or edited during execution. ## Configure the Timer To inject a timer in your policy, insert a `Clock` into your policy configuration function and define a timer with a time period: ```rust #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, clock: Clock, // Inject the clock to be able to launch async tasks. client: HttpClient, ) -> Result<()> { // set the period between ticks of the timer. let timer = clock.period(Duration::from_secs(10)); ``` After you inject the timer, share a its reference with the `on_request` and `on_response` functions to begin creating delayed functions: ```rust launcher .launch(on_request(|rs| request_filter(rs, &timer, &config))) .await?; ``` You can now await timer functions in `on_request` and `on_response` functions, for example: ```rust let slept = timer.sleep(duration).await; let tick = timer.next_tick().await; ``` > [!NOTE] To view an example policy project that launches delayed functions, see > [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/spike/README.md). ## Release the Clock To create a new timer with a different tick period, release the `Clock` by using the following method: ```rust pub fn release(self) -> Clock; ``` The following code snippet creates a timer and then releases the clock to create a new timer: ```rust // Configure an initial tick period. let initial_timer = clock.period(Duration::from_millis(500)); some_initial_task(&other_timer).await; // Configure another tick period. let other_timer = initial_timer.release().period(Duration::from_millis(3000); some_other_task(&other_timer).await; // Get the clock back. let clock = other_timer.release(); ``` ## Launch Asynchronous Tasks Use the timer to execute tasks independent of the request flow. To execute asynchronous tasks: 1. Define your task inside an `async` function. 2. In the policy configuration function, call your function but don’t await the returned future. 3. In the policy configuration function, call the `launch` function with the `on_request` and `on_response` filter functions but don’t await the returned future. 4. Use the `join!` macro to await both futures of your task function and `launch` function at the same time. > [!NOTE] To use the `join` macro, add the ‘futures’ crate as dependency in your `cargo.toml` > file. Each worker executes a copy of the task. Configure a loop inside the function to execute periodic tasks. For example, the following code example awaits both functions: ```rust let task = my_async_task(&timer, &config); let launched = launcher.launch(filter); let joined = join!(launched, task); ``` Adding a loop to the `my_async_task` function creates periodic tasks, for example: ```rust async fn my_async_task(timer: &Timer, config: &Config) { // While the policy is still running. // Wait for the next cycle. while timer.next_tick().await { // Execute periodic task } } ``` To launch multiple asynchronous tasks, send a reference of the timer to your `async` functions and join them with the `launch` task, for example: ```rust let task1 = my_async_task1(&timer, &config); let task2 = my_async_task2(&timer, &config); let launched = launcher.launch(filter); let joined = join!(launched, task1, task2); ``` > [!NOTE] To view an example policy project that launches asynchronous periodic tasks, see > [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/metrics/README.md). ## Sync Asynchronous Tasks between Workers Use the PDK `LockBuilder` to sync workers. The lock ensures that only one worker is completing a task in a time period. Each policy supports multiple locks. Locks are useful when a policy consumes an HTTP service that has usage limits. A single worker can fetch data and then share the data with other workers to reduce service requests. To configure a lock: 1. Inject the `LockBuilder` into your policy configuration function: ```rust #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, clock: Clock, // Inject the clock to be able to launch async tasks. lock: LockBuilder, // Inject the lock to be able to synchronize the workers. ) -> Result<()> { ``` 2. Configure the lock and share a reference of it with your asynchronous function: ```rust let lock = lock .new(ID.to_string()) .expiration(Duration::from_secs(20)) .build(); let task = my_async_task(&timer, &lock); ``` If the asynchronous task executes additional `async` function calls inside the task, configure the `expiration` of the lock to a duration longer than the total time needed to complete the nested `async` function calls. 3. Inside the asynchronous function, acquire the lock before executing the desired task. If no other worker has the lock, the current worker acquires the lock. Otherwise, you must omit the execution of the task and wait for the next task loop, for example: ```rust async fn my_async_task( timer: &Timer, lock: &TryLock, ) { while timer.next_tick().await { if let Some(acquired) = lock.try_lock() { // execute task. } } } ``` After obtaining the lock, if you execute code that requires you await a result, you must call the `refresh_lock` function to ensure the lock hasn’t expired. If the lock has expired, the worker is considered unresponsive. Abort the execution of your task because another worker is running the same task execution. > [!NOTE] To view an example policy project that synchronizes asynchronous periodic tasks and shares > information between workers, see > [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/block/README.md). ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-inject-parameters) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Configuring Delayed, Periodic, and Synchronous Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the `Clock` injectable to build a timer to enable delayed, periodic, and synchronous functions. Each policy supports only one timer. Each timer provides the following async methods: ```rust pub async fn next_tick(&self) -> bool; pub async fn sleep(&self, interval: Duration) -> bool; pub fn now(&self) -> bool; ``` - `next_tick`: Sleeps for the minimum amount of time the timer is capable of distinguishing. - `sleep`: Sleeps for an amount of ticks where the elapsed time is greater or equal than the provided `Duration`. For example, if you configure the period of the clock to 10 seconds, calling `timer.sleep(Duration::from_secs(1))` sleeps for 10 seconds. - `now`: Returns the current date and time. Both functions return `true` when the specified time has passed or `false` if the policy is unapplied or edited during execution. ## Configure the Timer To inject a timer in your policy, insert a `Clock` into your policy configuration function and define a timer with a time period: ```rust #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, clock: Clock, // Inject the clock to be able to launch async tasks. client: HttpClient, ) -> Result<()> { // set the period between ticks of the timer. let timer = clock.period(Duration::from_secs(10)); ``` After you inject the timer, share a its reference with the `on_request` and `on_response` functions to begin creating delayed functions: ```rust launcher .launch(on_request(|rs| request_filter(rs, &timer, &config))) .await?; ``` You can now await timer functions in `on_request` and `on_response` functions, for example: - Use the `.sleep` or `.next_tick` function: ```rust let slept = timer.sleep(duration).await; let tick = timer.next_tick().await; ``` - Use the `.now` function: ```rust async fn filter( state: RequestState, timer: &Timer, ) { let state = state.into_headers_state().await; let now: chrono::DateTime = timer.now().into(); state.handler().set_header("Date", now.format("%a, %d %b %Y %H:%M:%S GMT").to_string().as_str()); } ``` > [!NOTE] To view an example policy project that launches delayed functions, see > [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/spike/README.md). ## Release the Clock To create a new timer with a different tick period, release the `Clock` by using the following method: ```rust pub fn release(self) -> Clock; ``` The following code snippet creates a timer and then releases the clock to create a new timer: ```rust // Configure an initial tick period. let initial_timer = clock.period(Duration::from_millis(500)); some_initial_task(&other_timer).await; // Configure another tick period. let other_timer = initial_timer.release().period(Duration::from_millis(3000); some_other_task(&other_timer).await; // Get the clock back. let clock = other_timer.release(); ``` ## Launch Asynchronous Tasks Use the timer to execute tasks independent of the request flow. To execute asynchronous tasks: 1. Define your task inside an `async` function. 2. In the policy configuration function, call your function but don’t await the returned future. 3. In the policy configuration function, call the `launch` function with the `on_request` and `on_response` filter functions but don’t await the returned future. 4. Use the `join!` macro to await both futures of your task function and `launch` function at the same time. > [!NOTE] To use the `join` macro, add the ‘futures’ crate as dependency in your `cargo.toml` > file. Each worker executes a copy of the task. Configure a loop inside the function to execute periodic tasks. For example, the following code example awaits both functions: ```rust let task = my_async_task(&timer, &config); let launched = launcher.launch(filter); let joined = join!(launched, task); ``` Adding a loop to the `my_async_task` function creates periodic tasks, for example: ```rust async fn my_async_task(timer: &Timer, config: &Config) { // While the policy is still running. // Wait for the next cycle. while timer.next_tick().await { // Execute periodic task } } ``` To launch multiple asynchronous tasks, send a reference of the timer to your `async` functions and join them with the `launch` task, for example: ```rust let task1 = my_async_task1(&timer, &config); let task2 = my_async_task2(&timer, &config); let launched = launcher.launch(filter); let joined = join!(launched, task1, task2); ``` > [!NOTE] To view an example policy project that launches asynchronous periodic tasks, see > [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/metrics/README.md). ## Sync Asynchronous Tasks between Workers Use the PDK `LockBuilder` to sync workers. The lock ensures that only one worker is completing a task in a time period. Each policy supports multiple locks. Locks are useful when a policy consumes an HTTP service that has usage limits. A single worker can fetch data and then share the data with other workers to reduce service requests. To configure a lock: 1. Inject the `LockBuilder` into your policy configuration function: ```rust #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, clock: Clock, // Inject the clock to be able to launch async tasks. lock: LockBuilder, // Inject the lock to be able to synchronize the workers. ) -> Result<()> { ``` 2. Configure the lock and share a reference of it with your asynchronous function: ```rust let lock = lock .new(ID.to_string()) .expiration(Duration::from_secs(20)) .build(); let task = my_async_task(&timer, &lock); ``` If the asynchronous task executes additional `async` function calls inside the task, configure the `expiration` of the lock to a duration longer than the total time needed to complete the nested `async` function calls. 3. Inside the asynchronous function, acquire the lock before executing the desired task. If no other worker has the lock, the current worker acquires the lock. Otherwise, you must omit the execution of the task and wait for the next task loop, for example: ```rust async fn my_async_task( timer: &Timer, lock: &TryLock, ) { while timer.next_tick().await { if let Some(acquired) = lock.try_lock() { // execute task. } } } ``` After obtaining the lock, if you execute code that requires you await a result, you must call the `refresh_lock` function to ensure the lock hasn’t expired. If the lock has expired, the worker is considered unresponsive. Abort the execution of your task because another worker is running the same task execution. > [!NOTE] To view an example policy project that synchronizes asynchronous periodic tasks and shares > information between workers, see > [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/block/README.md). ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-inject-parameters) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Configuring Delayed, Periodic, and Synchronous Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the `Clock` injectable to build a timer to enable delayed, periodic, and synchronous functions. Each policy supports only one timer. Each timer provides the following async methods: ```rust pub async fn next_tick(&self) -> bool; pub async fn sleep(&self, interval: Duration) -> bool; pub fn now(&self) -> bool; ``` - `next_tick`: Sleeps for the minimum amount of time the timer is capable of distinguishing. - `sleep`: Sleeps for an amount of ticks where the elapsed time is greater or equal than the provided `Duration`. For example, if you configure the period of the clock to 10 seconds, calling `timer.sleep(Duration::from_secs(1))` sleeps for 10 seconds. - `now`: Returns the current date and time. Both functions return `true` when the specified time has passed or `false` if the policy is unapplied or edited during execution. ## Configure the Timer To inject a timer in your policy, insert a `Clock` into your policy configuration function and define a timer with a time period: ```rust #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, clock: Clock, // Inject the clock to be able to launch async tasks. client: HttpClient, ) -> Result<()> { // set the period between ticks of the timer. let timer = clock.period(Duration::from_secs(10)); ``` After you inject the timer, share a its reference with the `on_request` and `on_response` functions to begin creating delayed functions: ```rust launcher .launch(on_request(|rs| request_filter(rs, &timer, &config))) .await?; ``` You can now await timer functions in `on_request` and `on_response` functions, for example: - Use the `.sleep` or `.next_tick` function: ```rust let slept = timer.sleep(duration).await; let tick = timer.next_tick().await; ``` - Use the `.now` function: ```rust async fn filter( state: RequestState, timer: &Timer, ) { let state = state.into_headers_state().await; let now: chrono::DateTime = timer.now().into(); state.handler().set_header("Date", now.format("%a, %d %b %Y %H:%M:%S GMT").to_string().as_str()); } ``` > [!NOTE] To view an example policy project that launches delayed functions, see > [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/spike/README.md). ## Release the Clock To create a new timer with a different tick period, release the `Clock` by using the following method: ```rust pub fn release(self) -> Clock; ``` The following code snippet creates a timer and then releases the clock to create a new timer: ```rust // Configure an initial tick period. let initial_timer = clock.period(Duration::from_millis(500)); some_initial_task(&other_timer).await; // Configure another tick period. let other_timer = initial_timer.release().period(Duration::from_millis(3000); some_other_task(&other_timer).await; // Get the clock back. let clock = other_timer.release(); ``` ## Launch Asynchronous Tasks Use the timer to execute tasks independent of the request flow. To execute asynchronous tasks: 1. Define your task inside an `async` function. 2. In the policy configuration function, call your function but don’t await the returned future. 3. In the policy configuration function, call the `launch` function with the `on_request` and `on_response` filter functions but don’t await the returned future. 4. Use the `join!` macro to await both futures of your task function and `launch` function at the same time. > [!NOTE] To use the `join` macro, add the ‘futures’ crate as dependency in your `cargo.toml` > file. Each worker executes a copy of the task. Configure a loop inside the function to execute periodic tasks. For example, the following code example awaits both functions: ```rust let task = my_async_task(&timer, &config); let launched = launcher.launch(filter); let joined = join!(launched, task); ``` Adding a loop to the `my_async_task` function creates periodic tasks, for example: ```rust async fn my_async_task(timer: &Timer, config: &Config) { // While the policy is still running. // Wait for the next cycle. while timer.next_tick().await { // Execute periodic task } } ``` To launch multiple asynchronous tasks, send a reference of the timer to your `async` functions and join them with the `launch` task, for example: ```rust let task1 = my_async_task1(&timer, &config); let task2 = my_async_task2(&timer, &config); let launched = launcher.launch(filter); let joined = join!(launched, task1, task2); ``` > [!NOTE] To view an example policy project that launches asynchronous periodic tasks, see > [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/metrics/README.md). ## Sync Asynchronous Tasks between Workers Use the PDK `LockBuilder` to sync workers. The lock ensures that only one worker is completing a task in a time period. Each policy supports multiple locks. Locks are useful when a policy consumes an HTTP service that has usage limits. A single worker can fetch data and then share the data with other workers to reduce service requests. To configure a lock: 1. Inject the `LockBuilder` into your policy configuration function: ```rust #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, clock: Clock, // Inject the clock to be able to launch async tasks. lock: LockBuilder, // Inject the lock to be able to synchronize the workers. ) -> Result<()> { ``` 2. Configure the lock and share a reference of it with your asynchronous function: ```rust let lock = lock .new(ID.to_string()) .expiration(Duration::from_secs(20)) .build(); let task = my_async_task(&timer, &lock); ``` If the asynchronous task executes additional `async` function calls inside the task, configure the `expiration` of the lock to a duration longer than the total time needed to complete the nested `async` function calls. 3. Inside the asynchronous function, acquire the lock before executing the desired task. If no other worker has the lock, the current worker acquires the lock. Otherwise, you must omit the execution of the task and wait for the next task loop, for example: ```rust async fn my_async_task( timer: &Timer, lock: &TryLock, ) { while timer.next_tick().await { if let Some(acquired) = lock.try_lock() { // execute task. } } } ``` After obtaining the lock, if you execute code that requires you await a result, you must call the `refresh_lock` function to ensure the lock hasn’t expired. If the lock has expired, the worker is considered unresponsive. Abort the execution of your task because another worker is running the same task execution. > [!NOTE] To view an example policy project that synchronizes asynchronous periodic tasks and shares > information between workers, see > [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/block/README.md). ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-inject-parameters) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Configuring Delayed, Periodic, and Synchronous Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the `Clock` injectable to build a timer to enable delayed, periodic, and synchronous functions. Each policy supports only one timer. Each timer provides the following async methods: ```rust pub async fn next_tick(&self) -> bool; pub async fn sleep(&self, interval: Duration) -> bool; pub fn now(&self) -> bool; ``` - `next_tick`: Sleeps for the minimum amount of time the timer is capable of distinguishing. - `sleep`: Sleeps for an amount of ticks where the elapsed time is greater or equal than the provided `Duration`. For example, if you configure the period of the clock to 10 seconds, calling `timer.sleep(Duration::from_secs(1))` sleeps for 10 seconds. - `now`: Returns the current date and time. Both functions return `true` when the specified time has passed or `false` if the policy is unapplied or edited during execution. ## Configure the Timer To inject a timer in your policy, insert a `Clock` into your policy configuration function and define a timer with a time period: ```rust #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, clock: Clock, // Inject the clock to be able to launch async tasks. client: HttpClient, ) -> Result<()> { // set the period between ticks of the timer. let timer = clock.period(Duration::from_secs(10)); ``` After you inject the timer, share a its reference with the `on_request` and `on_response` functions to begin creating delayed functions: ```rust launcher .launch(on_request(|rs| request_filter(rs, &timer, &config))) .await?; ``` You can now await timer functions in `on_request` and `on_response` functions, for example: - Use the `.sleep` or `.next_tick` function: ```rust let slept = timer.sleep(duration).await; let tick = timer.next_tick().await; ``` - Use the `.now` function: ```rust async fn filter( state: RequestState, timer: &Timer, ) { let state = state.into_headers_state().await; let now: chrono::DateTime = timer.now().into(); state.handler().set_header("Date", now.format("%a, %d %b %Y %H:%M:%S GMT").to_string().as_str()); } ``` > [!NOTE] To view an example policy project that launches delayed functions, see > [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/spike/README.md). ## Release the Clock To create a new timer with a different tick period, release the `Clock` by using the following method: ```rust pub fn release(self) -> Clock; ``` The following code snippet creates a timer and then releases the clock to create a new timer: ```rust // Configure an initial tick period. let initial_timer = clock.period(Duration::from_millis(500)); some_initial_task(&other_timer).await; // Configure another tick period. let other_timer = initial_timer.release().period(Duration::from_millis(3000); some_other_task(&other_timer).await; // Get the clock back. let clock = other_timer.release(); ``` ## Launch Asynchronous Tasks Use the timer to execute tasks independent of the request flow. To execute asynchronous tasks: 1. Define your task inside an `async` function. 2. In the policy configuration function, call your function but don’t await the returned future. 3. In the policy configuration function, call the `launch` function with the `on_request` and `on_response` filter functions but don’t await the returned future. 4. Use the `join!` macro to await both futures of your task function and `launch` function at the same time. > [!NOTE] To use the `join` macro, add the ‘futures’ crate as dependency in your `cargo.toml` > file. Each worker executes a copy of the task. Configure a loop inside the function to execute periodic tasks. For example, the following code example awaits both functions: ```rust let task = my_async_task(&timer, &config); let launched = launcher.launch(filter); let joined = join!(launched, task); ``` Adding a loop to the `my_async_task` function creates periodic tasks, for example: ```rust async fn my_async_task(timer: &Timer, config: &Config) { // While the policy is still running. // Wait for the next cycle. while timer.next_tick().await { // Execute periodic task } } ``` To launch multiple asynchronous tasks, send a reference of the timer to your `async` functions and join them with the `launch` task, for example: ```rust let task1 = my_async_task1(&timer, &config); let task2 = my_async_task2(&timer, &config); let launched = launcher.launch(filter); let joined = join!(launched, task1, task2); ``` > [!NOTE] To view an example policy project that launches asynchronous periodic tasks, see > [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/metrics/README.md). ## Sync Asynchronous Tasks between Workers Use the PDK `LockBuilder` to sync workers. The lock ensures that only one worker is completing a task in a time period. Each policy supports multiple locks. Locks are useful when a policy consumes an HTTP service that has usage limits. A single worker can fetch data and then share the data with other workers to reduce service requests. To configure a lock: 1. Inject the `LockBuilder` into your policy configuration function: ```rust #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, clock: Clock, // Inject the clock to be able to launch async tasks. lock: LockBuilder, // Inject the lock to be able to synchronize the workers. ) -> Result<()> { ``` 2. Configure the lock and share a reference of it with your asynchronous function: ```rust let lock = lock .new(ID.to_string()) .expiration(Duration::from_secs(20)) .build(); let task = my_async_task(&timer, &lock); ``` If the asynchronous task executes additional `async` function calls inside the task, configure the `expiration` of the lock to a duration longer than the total time needed to complete the nested `async` function calls. 3. Inside the asynchronous function, acquire the lock before executing the desired task. If no other worker has the lock, the current worker acquires the lock. Otherwise, you must omit the execution of the task and wait for the next task loop, for example: ```rust async fn my_async_task( timer: &Timer, lock: &TryLock, ) { while timer.next_tick().await { if let Some(acquired) = lock.try_lock() { // execute task. } } } ``` After obtaining the lock, if you execute code that requires you await a result, you must call the `refresh_lock` function to ensure the lock hasn’t expired. If the lock has expired, the worker is considered unresponsive. Abort the execution of your task because another worker is running the same task execution. > [!NOTE] To view an example policy project that synchronizes asynchronous periodic tasks and shares > information between workers, see > [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/block/README.md). ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-inject-parameters) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Configuring Policy Logging > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides a logging mechanism that generates a log message enriched with the API instance ID, policy ID, and request ID. Insert custom logs with the following macros by using the `pdk::logger;` package: - `logger::debug!` - `logger::info!` - `logger::warn!` - `logger::error!` The macros behave the same as the [Rust std::format! macro](https://doc.rust-lang.org/std/macro.format.html). The first parameter must be a format string literal. Use `{}` in the literal to pass parameters, for example: ```Rust use pdk::logger; // [...] let value = "there!"; logger::debug!("Hello there!"); logger::info!("Hello {}", value); logger::warn!("Hello {value}"); logger::error!("Hello {}", "there!"); ``` All examples appear in the Flex Gateway logs in the following format: \[flex-gateway-envoy\]\[\] wasm log . main: \[policy: \]\[api: \]\[req: \] Hello there! For more information about viewing Flex Gateway logs, see [Monitoring Omni Gateway](https://docs.mulesoft.com/gateway/latest/gateway-monitor). --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Configuring Policy Logging > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides a logging mechanism that generates a log message enriched with the API instance ID, policy ID, and request ID. Insert custom logs with the following macros by using the `pdk::logger;` package: - `logger::debug!` - `logger::info!` - `logger::warn!` - `logger::error!` The macros behave the same as the [Rust std::format! macro](https://doc.rust-lang.org/std/macro.format.html). The first parameter must be a format string literal. Use `{}` in the literal to pass parameters, for example: ```Rust use pdk::logger; // [...] let value = "there!"; logger::debug!("Hello there!"); logger::info!("Hello {}", value); logger::warn!("Hello {value}"); logger::error!("Hello {}", "there!"); ``` All examples appear in the Flex Gateway logs in the following format: \[flex-gateway-envoy\]\[\] wasm log . main: \[policy: \]\[api: \]\[req: \] Hello there! For more information about viewing Flex Gateway logs, see [Monitoring Omni Gateway](https://docs.mulesoft.com/gateway/latest/gateway-monitor). --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Configuring Policy Logging > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides a logging mechanism that generates a log message enriched with the API instance ID, policy ID, and request ID. Insert custom logs with the following macros by using the `pdk::logger;` package: - `logger::debug!` - `logger::info!` - `logger::warn!` - `logger::error!` The macros behave the same as the [Rust std::format! macro](https://doc.rust-lang.org/std/macro.format.html). The first parameter must be a format string literal. Use `{}` in the literal to pass parameters, for example: ```Rust use pdk::logger; // [...] let value = "there!"; logger::debug!("Hello there!"); logger::info!("Hello {}", value); logger::warn!("Hello {value}"); logger::error!("Hello {}", "there!"); ``` All examples appear in the Flex Gateway logs in the following format: \[flex-gateway-envoy\]\[\] wasm log . main: \[policy: \]\[api: \]\[req: \] Hello there! For more information about viewing Flex Gateway logs, see [Monitoring Omni Gateway](https://docs.mulesoft.com/gateway/latest/gateway-monitor). --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Configuring Policy Logging > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides a logging mechanism that generates a log message enriched with the API instance ID, policy ID, and request ID. Insert custom logs with the following macros by using the `pdk::logger;` package: - `logger::debug!` - `logger::info!` - `logger::warn!` - `logger::error!` The macros behave the same as the [Rust std::format! macro](https://doc.rust-lang.org/std/macro.format.html). The first parameter must be a format string literal. Use `{}` in the literal to pass parameters, for example: ```Rust use pdk::logger; // [...] let value = "there!"; logger::debug!("Hello there!"); logger::info!("Hello {}", value); logger::warn!("Hello {value}"); logger::error!("Hello {}", "there!"); ``` All examples appear in the Flex Gateway logs in the following format: \[flex-gateway-envoy\]\[\] wasm log . main: \[policy: \]\[api: \]\[req: \] Hello there! For more information about viewing Flex Gateway logs, see [Monitoring Omni Gateway](https://docs.mulesoft.com/gateway/latest/gateway-monitor). --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Configuring Policy Logging > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides a logging mechanism that generates a log message enriched with the API instance ID, policy ID, and request ID. Insert custom logs with the following macros by using the `pdk::logger;` package: - `logger::debug!` - `logger::info!` - `logger::warn!` - `logger::error!` The macros behave the same as the [Rust std::format! macro](https://doc.rust-lang.org/std/macro.format.html). The first parameter must be a format string literal. Use `{}` in the literal to pass parameters, for example: ```Rust use pdk::logger; // [...] let value = "there!"; logger::debug!("Hello there!"); logger::info!("Hello {}", value); logger::warn!("Hello {value}"); logger::error!("Hello {}", "there!"); ``` All examples appear in the Flex Gateway logs in the following format: \[flex-gateway-envoy\]\[\] wasm log . main: \[policy: \]\[api: \]\[req: \] Hello there! For more information about viewing Flex Gateway logs, see [Monitoring Omni Gateway](https://docs.mulesoft.com/gateway/latest/gateway-monitor). --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Configuring Policy Logging > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides a logging mechanism that generates a log message enriched with the API instance ID, policy ID, and request ID. Insert custom logs with the following macros by using the `pdk::logger;` package: - `logger::debug!` - `logger::info!` - `logger::warn!` - `logger::error!` The macros behave the same as the [Rust std::format! macro](https://doc.rust-lang.org/std/macro.format.html). The first parameter must be a format string literal. Use `{}` in the literal to pass parameters, for example: ```Rust use pdk::logger; // [...] let value = "there!"; logger::debug!("Hello there!"); logger::info!("Hello {}", value); logger::warn!("Hello {value}"); logger::error!("Hello {}", "there!"); ``` All examples appear in the Flex Gateway logs in the following format: \[flex-gateway-envoy\]\[\] wasm log . main: \[policy: \]\[api: \]\[req: \] Hello there! For more information about viewing Flex Gateway logs, see [Monitoring Omni Gateway](https://docs.mulesoft.com/gateway/latest/gateway-monitor). --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Configuring Policy Logging > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) provides a logging mechanism that generates a log message enriched with the API instance ID, policy ID, and request ID. Insert custom logs with the following macros by using the `pdk::logger;` package: - `logger::debug!` - `logger::info!` - `logger::warn!` - `logger::error!` The macros behave the same as the [Rust std::format! macro](https://doc.rust-lang.org/std/macro.format.html). The first parameter must be a format string literal. Use `{}` in the literal to pass parameters, for example: ```Rust use pdk::logger; // [...] let value = "there!"; logger::debug!("Hello there!"); logger::info!("Hello {}", value); logger::warn!("Hello {value}"); logger::error!("Hello {}", "there!"); ``` All examples appear in the Omni Gateway logs in the following format: \[flex-gateway-envoy\]\[\] wasm log . main: \[policy: \]\[api: \]\[req: \] Hello there! For more information about viewing Omni Gateway logs, see [Monitoring Omni Gateway](https://docs.mulesoft.com/gateway/latest/gateway-monitor). --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Configuring Policy Logging > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) provides a logging mechanism that generates a log message enriched with the API instance ID, policy ID, and request ID. Insert custom logs with the following macros by using the `pdk::logger;` package: - `logger::debug!` - `logger::info!` - `logger::warn!` - `logger::error!` The macros behave the same as the [Rust std::format! macro](https://doc.rust-lang.org/std/macro.format.html). The first parameter must be a format string literal. Use `{}` in the literal to pass parameters, for example: ```Rust use pdk::logger; // [...] let value = "there!"; logger::debug!("Hello there!"); logger::info!("Hello {}", value); logger::warn!("Hello {value}"); logger::error!("Hello {}", "there!"); ``` All examples appear in the Omni Gateway logs in the following format: \[flex-gateway-envoy\]\[\] wasm log . main: \[policy: \]\[api: \]\[req: \] Hello there! For more information about viewing Omni Gateway logs, see [Monitoring Omni Gateway](https://docs.mulesoft.com/gateway/latest/gateway-monitor). --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Configuring Policy Logging > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) provides a logging mechanism that generates a log message enriched with the API instance ID, policy ID, and request ID. Insert custom logs with the following macros by using the `pdk::logger;` package: - `logger::debug!` - `logger::info!` - `logger::warn!` - `logger::error!` The macros behave the same as the [Rust std::format! macro](https://doc.rust-lang.org/std/macro.format.html). The first parameter must be a format string literal. Use `{}` in the literal to pass parameters, for example: ```Rust use pdk::logger; // [...] let value = "there!"; logger::debug!("Hello there!"); logger::info!("Hello {}", value); logger::warn!("Hello {value}"); logger::error!("Hello {}", "there!"); ``` All examples appear in the Omni Gateway logs in the following format: \[flex-gateway-envoy\]\[\] wasm log . main: \[policy: \]\[api: \]\[req: \] Hello there! For more information about viewing Omni Gateway logs, see [Monitoring Omni Gateway](https://docs.mulesoft.com/gateway/latest/gateway-monitor). --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Creating a New Policy Project > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The source code for Flex Gateway Policy Development Kit (PDK) policies is comprised of two versioned parts: - **Definition**: The policy’s metadata and configuration properties. The definition contains the policy’s parameters specified in `gcl.yaml` and the related JSON schema. It does not contain the code that runs at runtime. - **Implementation**: The policy’s runtime behavior. It is the code (Rust, compiled to WebAssembly) that runs on Flex Gateway when the policy is applied. The implementation uses the definition so its configuration matches the schema’s parameters and publishes a separate Exchange asset that gateways use to execute the policy. PDK enables you to version and manage the two parts of the policy source code using two project models: - Unified-Model (Regular) Policy: The policy definition and implementation are versioned together and share a version number. When you publish the policy, the definition and implementation are published together. - Split-Model Policy: The policy definition and implementation are versioned separately. When you publish the policy, the definition and implementation are published separately. This enables you to update the policy implementation for bug fixes or performance updates without updating the policy definition. To create a new policy project, choose the project model that best fits your needs: - [Creating a Unified-Model Policy Project](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-project) - [Creating a Split-Model Policy Project](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-project-split) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Creating a New Policy Project > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The source code for Omni Gateway Policy Development Kit (PDK) policies is comprised of two versioned parts: - **Definition**: The policy’s metadata and configuration properties. The definition contains the policy’s parameters specified in `gcl.yaml` and the related JSON schema. It does not contain the code that runs at runtime. - **Implementation**: The policy’s runtime behavior. It is the code (Rust, compiled to WebAssembly) that runs on Omni Gateway when the policy is applied. The implementation uses the definition so its configuration matches the schema’s parameters and publishes a separate Exchange asset that gateways use to execute the policy. PDK enables you to version and manage the two parts of the policy source code using two project models: - Unified-Model (Regular) Policy: The policy definition and implementation are versioned together and share a version number. When you publish the policy, the definition and implementation are published together. - Split-Model Policy: The policy definition and implementation are versioned separately. When you publish the policy, the definition and implementation are published separately. This enables you to update the policy implementation for bug fixes or performance updates without updating the policy definition. To create a new policy project, choose the project model that best fits your needs: - [Creating a Unified-Model Policy Project](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-project) - [Creating a Split-Model Policy Project](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-project-split) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Creating a New Policy Project > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The source code for Omni Gateway Policy Development Kit (PDK) policies is comprised of two versioned parts: - **Definition**: The policy’s metadata and configuration properties. The definition contains the policy’s parameters specified in `gcl.yaml` and the related JSON schema. It does not contain the code that runs at runtime. - **Implementation**: The policy’s runtime behavior. It is the code (Rust, compiled to WebAssembly) that runs on Omni Gateway when the policy is applied. The implementation uses the definition so its configuration matches the schema’s parameters and publishes a separate Exchange asset that gateways use to execute the policy. PDK enables you to version and manage the two parts of the policy source code using two project models: - Unified-Model (Regular) Policy: The policy definition and implementation are versioned together and share a version number. When you publish the policy, the definition and implementation are published together. - Split-Model Policy: The policy definition and implementation are versioned separately. When you publish the policy, the definition and implementation are published separately. This enables you to update the policy implementation for bug fixes or performance updates without updating the policy definition. To create a new policy project, choose the project model that best fits your needs: - [Creating a Unified-Model Policy Project](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-project) - [Creating a Split-Model Policy Project](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-project-split) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Creating a New Policy Project > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The source code for Omni Gateway Policy Development Kit (PDK) policies is comprised of two versioned parts: - **Definition**: The policy’s metadata and configuration properties. The definition contains the policy’s parameters specified in `gcl.yaml` and the related JSON schema. It does not contain the code that runs at runtime. - **Implementation**: The policy’s runtime behavior. It is the code (Rust, compiled to WebAssembly) that runs on Omni Gateway when the policy is applied. The implementation uses the definition so its configuration matches the schema’s parameters and publishes a separate Exchange asset that gateways use to execute the policy. PDK enables you to version and manage the two parts of the policy source code using two project models: - Unified-Model (Regular) Policy: The policy definition and implementation are versioned together and share a version number. When you publish the policy, the definition and implementation are published together. - Split-Model Policy: The policy definition and implementation are versioned separately. When you publish the policy, the definition and implementation are published separately. This enables you to update the policy implementation for bug fixes or performance updates without updating the policy definition. To create a new policy project, choose the project model that best fits your needs: - [Creating a Unified-Model Policy Project](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-project) - [Creating a Split-Model Policy Project](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-project-split) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Creating a New Project > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To begin developing a new custom policy with Flex Gateway Policy Development Kit (PDK), generate a new custom policy project. To create a new project, complete the following tasks: 1. [Before You Begin](#before-you-begin) 2. [Create a New Policy Project](#create-a-new-policy-project) 3. [Set Up the PDK Build Environment](#setup-the-pdk-build-environment) 4. Review [Project Structure](#project-structure) ## Before You Begin Before you can create a custom policy project, ensure that you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/1.2/policies-pdk-prerequisites). ## Create a New Policy Project To create a custom policy project, run the PDK CLI `create` command, replacing `` with the name of your new policy: ```ssh anypoint-cli-v4 pdk policy-project create --name ``` > [!NOTE] If you receive a prompt requesting your group ID, see > [Troubleshooting Group ID](https://docs.mulesoft.com/pdk/1.2/policies-pdk-troubleshooting#group-id-error). Running the `create` command creates a custom policy project with the specified name. The project appears in a new directory with the same name as your policy or a directory specified using the `--output-dir` flag. The following tutorials refer to this as your project’s root directory. The `assetID` of the new policy is the policy’s name in lower case with the spaces amended together with a `-`. For example, a policy with the name `My Header Injection Policy` has the `assetID` of `my-header-injection-policy`. The `groupID` of the new policy is the ID of the organization configured in Anypoint CLI. The `create` command supports the following flags:
FlagDefault ValueRequiredDescription

--name=<value> or -n

N/A

Yes

Name of the new policy.

--description=<value> or -d

N/A

No

Description of the new policy.

--output-dir=<value> of -o

assetID

No

Directory the new policy is created in.
If the directory does not exist, it is created. If no directory is specified, the directory name is the policy assetID.

--version=<value>

1.0.0

No

Version of the new policy.
The version format is <major-release>.<minor-release>.<patch-release>.

--group-id=<value>

N/A

No

Organization ID of the organization that owns the policy.
For additional information about this flag, see Troubleshooting Group ID.

## Set Up the PDK Build Environment After you [create a new policy project](#create-a-new-policy-project), you must run the `make setup` command to download additional software dependencies: ```ssh make setup ``` ## Project Structure After running the `make setup` command, the policy’s root directory contains the following directories and files shown in the directory tree: ├─ definition/ # Contains the files that describe the policy Definition │ ├── target/ # Contains the build definition asset files │ └── gcl.yaml # GCL file managed by the developer that describes the policy Definition ├─ target/ # Contains the implementation asset files and the output of the policy build ├─ src/ # Contains the implementation source code ├─ playground/ # Contains the artifacts required for running the policy locally ├─ tests/ # Contains the source and configuration files to write and run integration tests ├─ Makefile # Provides all the callable actions required during the policy development lifecycle ├─ Cargo.toml # Rust language standard file that contains the metadata required to build the policy └─.project.yaml # Project manifest used by PDK ### target/ and definition/target/ There are two separate `target` directories: - `definition/target/`: Contains the policy asset definition published to Exchange. - `target/`: Contains the files for the policy’s Exchange asset implementation and the output of the project build. Both target directories and their content are included in the `.gitignore` file. You must compile the targets on each individual devices using the `make build` command. For example, if you develop a policy as part of the team, your team can publish the policy and its source code to a remote repository, but each team member must build the target on their device to work with the policy. ### definition/ The `definition` directory contains the `gcl.yaml` file that defines the policy’s metadata and the configuration properties. To configure the `gcl.yaml` file, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.2/policies-pdk-create-schema-definition). ### Cargo.toml Custom policies for Flex Gateway are developed in the Rust programming language and compiled to a WebAssembly binary. The `Cargo.toml` is the Rust project manifest. Its `[package]` section contains the basic information about the policy implementation. The version specified in `Cargo.toml` matches the policy asset version. You can manage the policy version by editing the version number in `Cargo.toml`. The version follows the format `..`. ### src/ The `src` directory contains the policy’s source code: - `lib.rs`: Contains a set of methods that implement the behavior of the policy. PDK includes these methods to implement custom policies behavior. For additional information about these methods, see [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features). For complete policy examples, see [Custom Policy Examples](https://docs.mulesoft.com/pdk/1.2/policies-pdk-policy-templates). - `generated/config.rs` and `generated/mod.rs`: Auto-generated modules that make the policy configuration, as defined in the `gcl.yaml`, available for use in the `lib.rs` and any of the policy source files. ### Makefile The Makefile contains all the callable actions, such as `make` commands, required for the policy development lifecycle. Execute all `make` commands at the root level of your custom policy directory directory: - `make setup`: Installs PDK internal dependencies for the rest of the Makefile goals. For more information about setting up your project, see [Set Up the PDK Build Environment](#setup-the-pdk-build-environment). - `make build-asset-files`: Generates all the policy asset files required to build, execute, and publish the policy. This command also updates the `config.rs` source code file with the latest configurations defined in the `gcl.yaml` file. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.2/policies-pdk-compile-policies). - `make build`: Runs the `make build-asset-files` command and compiles the WebAssembly binary of the policy. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.2/policies-pdk-compile-policies). - `make run`: Provides a simple way to execute the current build of the policy in a Docker containerized environment. For more information about running and debugging your policy, see [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.2/policies-pdk-debug-local). - `make test`: Executes the tests contained in `tests/` by using the testing framework provided by PDK. For more information about testing your policy, see [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.2/policies-pdk-integration-tests). - `make publish`: Publishes the policy asset in Exchange. For more information about publishing policies in Exchange, see [Uploading Custom Policies to Exchange](https://docs.mulesoft.com/pdk/1.2/policies-pdk-publish-policies). - `make release`: Releases the policy asset in Exchange. For more information about releasing policies in Exchange, see [Uploading Custom Policies to Exchange](https://docs.mulesoft.com/pdk/1.2/policies-pdk-publish-policies). - `make help`: Lists all the `make` commands provided by PDK. ## See Also - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.2/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Creating a New Project > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To begin developing a new custom policy with Flex Gateway Policy Development Kit (PDK), generate a new custom policy project. To create a new project, complete the following tasks: 1. [Before You Begin](#before-you-begin) 2. [Create a New Policy Project](#create-a-new-policy-project) 3. [Set Up the PDK Build Environment](#setup-the-pdk-build-environment) 4. Review [Project Structure](#project-structure) ## Before You Begin Before you can create a custom policy project, ensure that you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/1.3/policies-pdk-prerequisites). ## Create a New Policy Project To create a custom policy project, run the PDK CLI `create` command, replacing `` with the name of your new policy: ```ssh anypoint-cli-v4 pdk policy-project create --name ``` > [!NOTE] If you receive a prompt requesting your group ID, see > [Troubleshooting Group ID](https://docs.mulesoft.com/pdk/1.3/policies-pdk-troubleshooting#group-id-error). Running the `create` command creates a custom policy project with the specified name. The project appears in a new directory with the same name as your policy or a directory specified using the `--output-dir` flag. The following tutorials refer to this as your project’s root directory. The `assetID` of the new policy is the policy’s name in lower case with the spaces amended together with a `-`. For example, a policy with the name `My Header Injection Policy` has the `assetID` of `my-header-injection-policy`. The `groupID` of the new policy is the ID of the organization configured in Anypoint CLI. The `create` command supports the following flags:
FlagDefault ValueRequiredDescription

--name=<value> or -n

N/A

Yes

Name of the new policy.

--description=<value> or -d

N/A

No

Description of the new policy.

--output-dir=<value> of -o

assetID

No

Directory the new policy is created in.
If the directory does not exist, it is created. If no directory is specified, the directory name is the policy assetID.

--version=<value>

1.0.0

No

Version of the new policy.
The version format is <major-release>.<minor-release>.<patch-release>.

--group-id=<value>

N/A

No

Organization ID of the organization that owns the policy.
For additional information about this flag, see Troubleshooting Group ID.

## Set Up the PDK Build Environment After you [create a new policy project](#create-a-new-policy-project), you must run the `make setup` command to download additional software dependencies: ```ssh make setup ``` ## Project Structure After running the `make setup` command, the policy’s root directory contains the following directories and files shown in the directory tree: ├─ definition/ # Contains the files that describe the policy Definition │ ├── target/ # Contains the build definition asset files │ └── gcl.yaml # GCL file managed by the developer that describes the policy Definition ├─ target/ # Contains the implementation asset files and the output of the policy build ├─ src/ # Contains the implementation source code ├─ playground/ # Contains the artifacts required for running the policy locally ├─ tests/ # Contains the source and configuration files to write and run integration tests ├─ Makefile # Provides all the callable actions required during the policy development lifecycle ├─ Cargo.toml # Rust language standard file that contains the metadata required to build the policy └─.project.yaml # Project manifest used by PDK ### target/ and definition/target/ There are two separate `target` directories: - `definition/target/`: Contains the policy asset definition published to Exchange. - `target/`: Contains the files for the policy’s Exchange asset implementation and the output of the project build. Both target directories and their content are included in the `.gitignore` file. You must compile the targets on each individual devices using the `make build` command. For example, if you develop a policy as part of the team, your team can publish the policy and its source code to a remote repository, but each team member must build the target on their device to work with the policy. ### definition/ The `definition` directory contains the `gcl.yaml` file that defines the policy’s metadata and the configuration properties. To configure the `gcl.yaml` file, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.3/policies-pdk-create-schema-definition). ### Cargo.toml Custom policies for Flex Gateway are developed in the Rust programming language and compiled to a WebAssembly binary. The `Cargo.toml` is the Rust project manifest. Its `[package]` section contains the basic information about the policy implementation. The version specified in `Cargo.toml` matches the policy asset version. You can manage the policy version by editing the version number in `Cargo.toml`. The version follows the format `..`. ### src/ The `src` directory contains the policy’s source code: - `lib.rs`: Contains a set of methods that implement the behavior of the policy. PDK includes these methods to implement custom policies behavior. For additional information about these methods, see [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features). For complete policy examples, see [Custom Policy Examples](https://docs.mulesoft.com/pdk/1.3/policies-pdk-policy-templates). - `generated/config.rs` and `generated/mod.rs`: Auto-generated modules that make the policy configuration, as defined in the `gcl.yaml`, available for use in the `lib.rs` and any of the policy source files. ### Makefile The Makefile contains all the callable actions, such as `make` commands, required for the policy development lifecycle. Execute all `make` commands at the root level of your custom policy directory directory: - `make setup`: Installs PDK internal dependencies for the rest of the Makefile goals. For more information about setting up your project, see [Set Up the PDK Build Environment](#setup-the-pdk-build-environment). - `make build-asset-files`: Generates all the policy asset files required to build, execute, and publish the policy. This command also updates the `config.rs` source code file with the latest configurations defined in the `gcl.yaml` file. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.3/policies-pdk-compile-policies). - `make build`: Runs the `make build-asset-files` command and compiles the WebAssembly binary of the policy. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.3/policies-pdk-compile-policies). - `make run`: Provides a simple way to execute the current build of the policy in a Docker containerized environment. For more information about running and debugging your policy, see [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.3/policies-pdk-debug-local). - `make test`: Executes the tests contained in `tests/` by using the testing framework provided by PDK. For more information about testing your policy, see [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.3/policies-pdk-integration-tests). - `make publish`: Publishes the policy asset in Exchange. For more information about publishing policies in Exchange, see [Uploading Custom Policies to Exchange](https://docs.mulesoft.com/pdk/1.3/policies-pdk-publish-policies). - `make release`: Releases the policy asset in Exchange. For more information about releasing policies in Exchange, see [Uploading Custom Policies to Exchange](https://docs.mulesoft.com/pdk/1.3/policies-pdk-publish-policies). - `make help`: Lists all the `make` commands provided by PDK. ## See Also - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.3/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Creating a New Project > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To begin developing a new custom policy with Flex Gateway Policy Development Kit (PDK), generate a new custom policy project. To create a new project, complete the following tasks: 1. [Before You Begin](#before-you-begin) 2. [Create a New Policy Project](#create-a-new-policy-project) 3. [Set Up the PDK Build Environment](#setup-the-pdk-build-environment) 4. Review [Project Structure](#project-structure) ## Before You Begin Before you can create a custom policy project, ensure that you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/1.4/policies-pdk-prerequisites). ## Create a New Policy Project To create a custom policy project, run the PDK CLI `create` command, replacing `` with the name of your new policy: ```ssh anypoint-cli-v4 pdk policy-project create --name ``` > [!NOTE] If you receive a prompt requesting your group ID, see > [Troubleshooting Group ID](https://docs.mulesoft.com/pdk/1.4/policies-pdk-troubleshooting#group-id-error). Running the `create` command creates a custom policy project with the specified name. The project appears in a new directory with the same name as your policy or a directory specified using the `--output-dir` flag. The following tutorials refer to this as your project’s root directory. The `assetID` of the new policy is the policy’s name in lower case with the spaces amended together with a `-`. For example, a policy with the name `My Header Injection Policy` has the `assetID` of `my-header-injection-policy`. The `groupID` of the new policy is the ID of the organization configured in Anypoint CLI. The `create` command supports the following flags:
FlagDefault ValueRequiredDescription

--name=<value> or -n

N/A

Yes

Name of the new policy.

--description=<value> or -d

N/A

No

Description of the new policy.

--output-dir=<value> of -o

assetID

No

Directory the new policy is created in.
If the directory does not exist, it is created. If no directory is specified, the directory name is the policy assetID.

--version=<value>

1.0.0

No

Version of the new policy.
The version format is <major-release>.<minor-release>.<patch-release>.

--group-id=<value>

N/A

No

Organization ID of the organization that owns the policy.
For additional information about this flag, see Troubleshooting Group ID.

## Set Up the PDK Build Environment After you [create a new policy project](#create-a-new-policy-project), you must run the `make setup` command to download additional software dependencies: ```ssh make setup ``` ## Project Structure After running the `make setup` command, the policy’s root directory contains the following directories and files shown in the directory tree: ├─ definition/ # Contains the files that describe the policy Definition │ ├── target/ # Contains the build definition asset files │ └── gcl.yaml # GCL file managed by the developer that describes the policy Definition ├─ target/ # Contains the implementation asset files and the output of the policy build ├─ src/ # Contains the implementation source code ├─ playground/ # Contains the artifacts required for running the policy locally ├─ tests/ # Contains the source and configuration files to write and run integration tests ├─ Makefile # Provides all the callable actions required during the policy development lifecycle ├─ Cargo.toml # Rust language standard file that contains the metadata required to build the policy └─.project.yaml # Project manifest used by PDK ### target/ and definition/target/ There are two separate `target` directories: - `definition/target/`: Contains the policy asset definition published to Exchange. - `target/`: Contains the files for the policy’s Exchange asset implementation and the output of the project build. Both target directories and their content are included in the `.gitignore` file. You must compile the targets on each individual devices using the `make build` command. For example, if you develop a policy as part of the team, your team can publish the policy and its source code to a remote repository, but each team member must build the target on their device to work with the policy. ### definition/ The `definition` directory contains the `gcl.yaml` file that defines the policy’s metadata and the configuration properties. To configure the `gcl.yaml` file, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.4/policies-pdk-create-schema-definition). ### Cargo.toml Custom policies for Flex Gateway are developed in the Rust programming language and compiled to a WebAssembly binary. The `Cargo.toml` is the Rust project manifest. Its `[package]` section contains the basic information about the policy implementation. The version specified in `Cargo.toml` matches the policy asset version. You can manage the policy version by editing the version number in `Cargo.toml`. The version follows the format `..`. ### src/ The `src` directory contains the policy’s source code: - `lib.rs`: Contains a set of methods that implement the behavior of the policy. PDK includes these methods to implement custom policies behavior. For additional information about these methods, see [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features). For complete policy examples, see [Custom Policy Examples](https://docs.mulesoft.com/pdk/1.4/policies-pdk-policy-templates). - `generated/config.rs` and `generated/mod.rs`: Auto-generated modules that make the policy configuration, as defined in the `gcl.yaml`, available for use in the `lib.rs` and any of the policy source files. ### Makefile The Makefile contains all the callable actions, such as `make` commands, required for the policy development lifecycle. Execute all `make` commands at the root level of your custom policy directory directory: - `make setup`: Installs PDK internal dependencies for the rest of the Makefile goals. For more information about setting up your project, see [Set Up the PDK Build Environment](#setup-the-pdk-build-environment). - `make build-asset-files`: Generates all the policy asset files required to build, execute, and publish the policy. This command also updates the `config.rs` source code file with the latest configurations defined in the `gcl.yaml` file. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.4/policies-pdk-compile-policies). - `make build`: Runs the `make build-asset-files` command and compiles the WebAssembly binary of the policy. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.4/policies-pdk-compile-policies). - `make run`: Provides a simple way to execute the current build of the policy in a Docker containerized environment. For more information about running and debugging your policy, see [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.4/policies-pdk-debug-local). - `make test`: Executes the tests contained in `tests/` by using the testing framework provided by PDK. For more information about testing your policy, see [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.4/policies-pdk-integration-tests). - `make publish`: Publishes the policy asset in Exchange. For more information about publishing policies in Exchange, see [Uploading Custom Policies to Exchange](https://docs.mulesoft.com/pdk/1.4/policies-pdk-publish-policies). - `make release`: Releases the policy asset in Exchange. For more information about releasing policies in Exchange, see [Uploading Custom Policies to Exchange](https://docs.mulesoft.com/pdk/1.4/policies-pdk-publish-policies). - `make help`: Lists all the `make` commands provided by PDK. ## See Also - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.4/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Creating a New Project > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To begin developing a new custom policy with Flex Gateway Policy Development Kit (PDK), generate a new custom policy project. To create a new project, complete the following tasks: 1. [Before You Begin](#before-you-begin) 2. [Create a New Policy Project](#create-a-new-policy-project) 3. [Set Up the PDK Build Environment](#setup-the-pdk-build-environment) 4. Review [Project Structure](#project-structure) ## Before You Begin Before you can create a custom policy project, ensure that you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/1.5/policies-pdk-prerequisites). ## Create a New Policy Project To create a custom policy project, run the PDK CLI `create` command, replacing `` with the name of your new policy: ```ssh anypoint-cli-v4 pdk policy-project create --name ``` > [!NOTE] If you receive a prompt requesting your group ID, see > [Troubleshooting Group ID](https://docs.mulesoft.com/pdk/1.5/policies-pdk-troubleshooting#group-id-error). Running the `create` command creates a custom policy project with the specified name. The project appears in a new directory with the same name as your policy or a directory specified using the `--output-dir` flag. The following tutorials refer to this as your project’s root directory. The `assetID` of the new policy is the policy’s name in lower case with the spaces amended together with a `-`. For example, a policy with the name `My Header Injection Policy` has the `assetID` of `my-header-injection-policy`. The `groupID` of the new policy is the ID of the organization configured in Anypoint CLI. The `create` command supports the following flags:
FlagDefault ValueRequiredDescription

--name=<value> or -n

N/A

Yes

Name of the new policy.

--description=<value> or -d

N/A

No

Description of the new policy.

--output-dir=<value> of -o

assetID

No

Directory the new policy is created in.
If the directory does not exist, it is created. If no directory is specified, the directory name is the policy assetID.

--version=<value>

1.0.0

No

Version of the new policy.
The version format is <major-release>.<minor-release>.<patch-release>.

--group-id=<value>

N/A

No

Organization ID of the organization that owns the policy.
For additional information about this flag, see Troubleshooting Group ID.

## Set Up the PDK Build Environment After you [create a new policy project](#create-a-new-policy-project), you must run the `make setup` command to download additional software dependencies: ```ssh make setup ``` ## Project Structure After running the `make setup` command, the policy’s root directory contains the following directories and files shown in the directory tree: ├─ definition/ # Contains the files that describe the policy Definition │ ├── target/ # Contains the build definition asset files │ └── gcl.yaml # GCL file managed by the developer that describes the policy Definition ├─ target/ # Contains the implementation asset files and the output of the policy build ├─ src/ # Contains the implementation source code ├─ playground/ # Contains the artifacts required for running the policy locally ├─ tests/ # Contains the source and configuration files to write and run integration tests ├─ Makefile # Provides all the callable actions required during the policy development lifecycle ├─ Cargo.toml # Rust language standard file that contains the metadata required to build the policy └─.project.yaml # Project manifest used by PDK ### target/ and definition/target/ There are two separate `target` directories: - `definition/target/`: Contains the policy asset definition published to Exchange. - `target/`: Contains the files for the policy’s Exchange asset implementation and the output of the project build. Both target directories and their content are included in the `.gitignore` file. You must compile the targets on each individual devices using the `make build` command. For example, if you develop a policy as part of the team, your team can publish the policy and its source code to a remote repository, but each team member must build the target on their device to work with the policy. ### definition/ The `definition` directory contains the `gcl.yaml` file that defines the policy’s metadata and the configuration properties. To configure the `gcl.yaml` file, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.5/policies-pdk-create-schema-definition). ### Cargo.toml Custom policies for Flex Gateway are developed in the Rust programming language and compiled to a WebAssembly binary. The `Cargo.toml` is the Rust project manifest. Its `[package]` section contains the basic information about the policy implementation. The version specified in `Cargo.toml` matches the policy asset version. You can manage the policy version by editing the version number in `Cargo.toml`. The version follows the format `..`. ### src/ The `src` directory contains the policy’s source code: - `lib.rs`: Contains a set of methods that implement the behavior of the policy. PDK includes these methods to implement custom policies behavior. For additional information about these methods, see [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features). For complete policy examples, see [Custom Policy Examples](https://docs.mulesoft.com/pdk/1.5/policies-pdk-policy-templates). - `generated/config.rs` and `generated/mod.rs`: Auto-generated modules that make the policy configuration, as defined in the `gcl.yaml`, available for use in the `lib.rs` and any of the policy source files. ### Makefile The Makefile contains all the callable actions, such as `make` commands, required for the policy development lifecycle. Execute all `make` commands at the root level of your custom policy directory directory: - `make setup`: Installs PDK internal dependencies for the rest of the Makefile goals. For more information about setting up your project, see [Set Up the PDK Build Environment](#setup-the-pdk-build-environment). - `make build-asset-files`: Generates all the policy asset files required to build, execute, and publish the policy. This command also updates the `config.rs` source code file with the latest configurations defined in the `gcl.yaml` file. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.5/policies-pdk-compile-policies). - `make build`: Runs the `make build-asset-files` command and compiles the WebAssembly binary of the policy. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.5/policies-pdk-compile-policies). - `make run`: Provides a simple way to execute the current build of the policy in a Docker containerized environment. For more information about running and debugging your policy, see [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.5/policies-pdk-debug-local). - `make test`: Executes the tests contained in `tests/` by using the testing framework provided by PDK. For more information about testing your policy, see [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.5/policies-pdk-integration-tests). - `make publish`: Publishes the policy asset in Exchange. For more information about publishing policies in Exchange, see [Uploading Custom Policies to Exchange](https://docs.mulesoft.com/pdk/1.5/policies-pdk-publish-policies). - `make release`: Releases the policy asset in Exchange. For more information about releasing policies in Exchange, see [Uploading Custom Policies to Exchange](https://docs.mulesoft.com/pdk/1.5/policies-pdk-publish-policies). - `make help`: Lists all the `make` commands provided by PDK. ## See Also - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.5/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Creating a New Project > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To begin developing a new custom policy with Flex Gateway Policy Development Kit (PDK), generate a new custom policy project. To create a new project, complete the following tasks: 1. [Before You Begin](#before-you-begin) 2. [Create a New Policy Project](#create-a-new-policy-project) 3. [Set Up the PDK Build Environment](#setup-the-pdk-build-environment) 4. Review [Project Structure](#project-structure) ## Before You Begin Before you can create a custom policy project, ensure that you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/1.6/policies-pdk-prerequisites). ## Create a New Policy Project To create a custom policy project, run the PDK CLI `create` command, replacing `` with the name of your new policy: ```ssh anypoint-cli-v4 pdk policy-project create --name ``` > [!NOTE] If you receive a prompt requesting your group ID, see > [Troubleshooting Group ID](https://docs.mulesoft.com/pdk/1.6/policies-pdk-troubleshooting#group-id-error). Running the `create` command creates a custom policy project with the specified name. The project appears in a new directory with the same name as your policy or a directory specified using the `--output-dir` flag. The following tutorials refer to this as your project’s root directory. The `assetID` of the new policy is the policy’s name in lower case with the spaces amended together with a `-`. For example, a policy with the name `My Header Injection Policy` has the `assetID` of `my-header-injection-policy`. The `groupID` of the new policy is the ID of the organization configured in Anypoint CLI. The `create` command supports the following flags:
FlagDefault ValueRequiredDescription

--name=<value> or -n

N/A

Yes

Name of the new policy.

--description=<value> or -d

N/A

No

Description of the new policy.

--output-dir=<value> of -o

assetID

No

Directory the new policy is created in.
If the directory does not exist, it is created. If no directory is specified, the directory name is the policy assetID.

--version=<value>

1.0.0

No

Version of the new policy.
The version format is <major-release>.<minor-release>.<patch-release>.

--group-id=<value>

N/A

No

Organization ID of the organization that owns the policy.
For additional information about this flag, see Troubleshooting Group ID.

## Set Up the PDK Build Environment After you [create a new policy project](#create-a-new-policy-project), you must run the `make setup` command to download additional software dependencies: ```ssh make setup ``` ## Project Structure After running the `make setup` command, the policy’s root directory contains the following directories and files shown in the directory tree: ├─ definition/ # Contains the files that describe the policy Definition │ ├── target/ # Contains the build definition asset files │ └── gcl.yaml # GCL file managed by the developer that describes the policy Definition ├─ target/ # Contains the implementation asset files and the output of the policy build ├─ src/ # Contains the implementation source code ├─ playground/ # Contains the artifacts required for running the policy locally ├─ tests/ # Contains the source and configuration files to write and run integration tests ├─ Makefile # Provides all the callable actions required during the policy development lifecycle ├─ Cargo.toml # Rust language standard file that contains the metadata required to build the policy └─.project.yaml # Project manifest used by PDK ### target/ and definition/target/ There are two separate `target` directories: - `definition/target/`: Contains the policy asset definition published to Exchange. - `target/`: Contains the files for the policy’s Exchange asset implementation and the output of the project build. Both target directories and their content are included in the `.gitignore` file. You must compile the targets on each individual devices using the `make build` command. For example, if you develop a policy as part of the team, your team can publish the policy and its source code to a remote repository, but each team member must build the target on their device to work with the policy. ### definition/ The `definition` directory contains the `gcl.yaml` file that defines the policy’s metadata and the configuration properties. To configure the `gcl.yaml` file, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.6/policies-pdk-create-schema-definition). ### Cargo.toml Custom policies for Flex Gateway are developed in the Rust programming language and compiled to a WebAssembly binary. The `Cargo.toml` is the Rust project manifest. Its `[package]` section contains the basic information about the policy implementation. The version specified in `Cargo.toml` matches the policy asset version. You can manage the policy version by editing the version number in `Cargo.toml`. The version follows the format `..`. ### src/ The `src` directory contains the policy’s source code: - `lib.rs`: Contains a set of methods that implement the behavior of the policy. PDK includes these methods to implement custom policies behavior. For additional information about these methods, see [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features). For complete policy examples, see [Custom Policy Examples](https://docs.mulesoft.com/pdk/1.6/policies-pdk-policy-templates). - `generated/config.rs` and `generated/mod.rs`: Auto-generated modules that make the policy configuration, as defined in the `gcl.yaml`, available for use in the `lib.rs` and any of the policy source files. ### Makefile The Makefile contains all the callable actions, such as `make` commands, required for the policy development lifecycle. Execute all `make` commands at the root level of your custom policy directory directory: - `make setup`: Installs PDK internal dependencies for the rest of the Makefile goals. For more information about setting up your project, see [Set Up the PDK Build Environment](#setup-the-pdk-build-environment). - `make build-asset-files`: Generates all the policy asset files required to build, execute, and publish the policy. This command also updates the `config.rs` source code file with the latest configurations defined in the `gcl.yaml` file. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.6/policies-pdk-compile-policies). - `make build`: Runs the `make build-asset-files` command and compiles the WebAssembly binary of the policy. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.6/policies-pdk-compile-policies). - `make run`: Provides a simple way to execute the current build of the policy in a Docker containerized environment. For more information about running and debugging your policy, see [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.6/policies-pdk-debug-local). - `make test`: Executes the tests contained in `tests/` by using the testing framework provided by PDK. For more information about testing your policy, see [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.6/policies-pdk-integration-tests). - `make publish`: Publishes the policy asset in Exchange. For more information about publishing policies in Exchange, see [Uploading Custom Policies to Exchange](https://docs.mulesoft.com/pdk/1.6/policies-pdk-publish-policies). - `make release`: Releases the policy asset in Exchange. For more information about releasing policies in Exchange, see [Uploading Custom Policies to Exchange](https://docs.mulesoft.com/pdk/1.6/policies-pdk-publish-policies). - `make help`: Lists all the `make` commands provided by PDK. ## See Also - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.6/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Creating a Split-Model Policy Project > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To begin developing a new Split-Model custom policy with Flex Gateway Policy Development Kit (PDK), generate a new custom policy project. To create a Split-Model project, complete these tasks: 1. [Before You Begin](#before-you-begin) 2. [Create a New Policy Definition Project](#create-a-new-policy-definition-project) 3. Review [Definition Project Structure](#definition-project-structure) to learn about the different parts of the policy definition. 4. [Create a New Policy Implementation Project](#create-a-new-policy-implementation-project) 5. [Set Up the PDK Build Environment](#setup-the-pdk-build-environment) 6. Review [Implementation Project Structure](#implementation-project-structure) to learn about the different parts of the policy implementation. ## Before You Begin Before you can create a custom policy project, ensure that you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/1.7/policies-pdk-prerequisites). ## Create a New Policy Definition Project To create a custom policy definition project, run the PDK CLI `create` command, with the `--project-mode definition` flag, replacing `` with the name of your new policy: ```ssh anypoint-cli-v4 pdk policy-project create --name --project-mode definition ``` Running the `create` command creates a custom policy project with the specified name. The project appears in a new directory with the same name as your policy with the `-definition` suffix or a directory specified using the `--output-dir` flag. ## Definition Project Structure After running the `make build` command, the policy’s root directory contains the following directories and files shown in the directory tree: ├─ gcl.yaml # GCL file managed by the developer that describes the policy Definition ├─ exchange.json # Coordinates of the asset ├─ target/ # Contains the output of the policy definition build ├─ Makefile # Provides all the callable actions required during the policy definition development lifecycle ├─ README.md # Information regarding general help of available actions └─.gitignore # Configuration for git Version Control system to ignore built assets ### exchange.json Contains the exchange asset coordinate of the policy definition. ### target Contains the policy asset definition published to Exchange. The directory and its content are included in the `.gitignore` file. ### Definition Makefile The Makefile contains all the callable actions, such as `make` commands, required for the policy development lifecycle. Execute all `make` commands at the root level of your custom policy directory: - `make build`: Compiles the definition and generates the assets to be deployed. - `make publish`: Publishes the policy definition asset in Exchange. Since the publish goal is intended to publish a policy asset in development, the _assetId_ and name published explicitly say `dev`, and the versions published include a timestamp at the end of the version. For example: - groupId: your configured organization id - visible name: {Your policy name} Dev - assetId: {your-policy-asset-id}-dev - version: {your-policy-version}-20230618115723 For more information about publishing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.7/policies-pdk-publish-policies). - `make release`: Releases the policy definition asset in Exchange. For more information about releasing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.7/policies-pdk-publish-policies). - `make release-local`: Publishes the policy definition as a release asset to the local cache (no actual release to Exchange is made). You can override it. This target is useful if you’re also developing the policy implementation. - `make help`: Lists all the `make` commands provided by PDK. ## Create a New Policy Implementation Project To create a custom policy implementation project, run the PDK CLI `create` command, with the `--project-mode implementation` flag, replacing `` with the name of your new policy: ```ssh anypoint-cli-v4 pdk policy-project create --name --project-mode implementation ``` Running the `create` command creates a custom policy project with the specified name. The project appears in a new directory with the same name as your policy with the `-implementation` suffix or a directory specified using the `--output-dir` flag. > [!NOTE] If your implementation and definition projects have different names, link them by making > sure the `definition_asset_id.name` field in the implementation project’s `Cargo.toml` file > matches the asset ID in the definition project’s `exchange.json` file. ## Set Up the PDK Build Environment After you [create a new policy project](#create-a-new-policy-implementation-project), you must run the `make setup` command to download additional software dependencies: ```ssh make setup ``` ## Implementation Project Structure After running the `make setup` command, the policy’s root directory contains these directories and files shown in the directory tree: ├─ target/ # Contains the implementation asset files and the output of the policy build ├─ src/ # Contains the implementation source code ├─ playground/ # Contains the artifacts required for running the policy locally ├─ tests/ # Contains the source and configuration files to write and run integration tests ├─ Makefile # Provides all the callable actions required during the policy development lifecycle └─ Cargo.toml # Rust language standard file that contains the metadata required to build the policy ### target Contains the files for the policy’s Exchange asset implementation and the output of the project build. The target directory and its content are included in the `.gitignore` file. ### Cargo.toml Custom policies for Flex Gateway are developed in the Rust programming language and compiled to a WebAssembly binary. The `Cargo.toml` is the Rust project manifest. Its `[package]` section contains the basic information about the policy implementation. The version specified in `Cargo.toml` matches the policy asset version. You can manage the policy version by editing the version number in `Cargo.toml`. The version follows the format `..`. The toml also contains a section `[package.metadata.anypoint]` where you can specify: - `group_id`: The policy group ID, which should match your Anypoint organization. - `definition_asset_id`: The name of the policy definition and the version this implementation uses. If you need to work with a development version, append the `-DEV` (case sensitive) suffix, for example: `version = "1.0.0-DEV"`. - `implementation_asset_id`: The asset ID that’s used to release the policy. ```toml [package.metadata.anypoint] group_id = "43573332-0364-41f2-9486-d1248f3b4023" definition_asset_id = { name = "party-planner-split", version = "1.0.0" } implementation_asset_id = "team-planner-split-flex" ``` ### src/ The `src` directory contains the policy’s source code: - `lib.rs`: Contains a set of methods that implement the behavior of the policy. PDK includes these methods to implement custom policy behavior. For additional information about these methods, see [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.7/policies-pdk-develop-custom-policies). For complete policy examples, see [Custom Policy Examples](https://docs.mulesoft.com/pdk/1.7/policies-pdk-policy-templates). - `generated/config.rs` and `generated/mod.rs`: Auto-generated modules that make the policy configuration, as defined in the `gcl.yaml`, available for use in the `lib.rs` and any of the policy source files. ### Implementation Makefile The Makefile contains all the callable actions, such as `make` commands, required for the policy development lifecycle. Execute all `make` commands at the root level of your custom policy directory: - `make setup`: Installs PDK internal dependencies for the rest of the Makefile goals. For more information about setting up your project, see [Set Up the PDK Build Environment](https://docs.mulesoft.com/pdk/1.7/policies-pdk-prerequisites). - `make build-asset-files`: Generates all the policy asset files required to build, execute, and publish the policy. This command also updates the `config.rs` source code file with the latest configurations defined in the `gcl.yaml` file. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-compile-policies). > [!NOTE] If you modify the `definition_asset_id` field in the `Cargo.toml`, re-run this target > manually. - `make build`: Compiles the WebAssembly binary of the policy. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-compile-policies). - `make run`: Provides a simple way to execute the current build of the policy in a Docker containerized environment. For more information about running and debugging your policy, see [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.7/policies-pdk-debug-local). - `make test`: Executes the tests contained in `tests/` by using the testing framework provided by PDK. For more information about testing your policy, see [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.7/policies-pdk-integration-tests). - `make publish`: Publishes the policy asset in Exchange. For more information about publishing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.7/policies-pdk-publish-policies). - `make release`: Releases the policy asset in Exchange. For more information about releasing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.7/policies-pdk-publish-policies). - `make help`: Lists all the `make` commands provided by PDK. ## See Also - [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.7/policies-pdk-publish-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.7/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Creating a Split-Model Policy Project > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To begin developing a new Split-Model custom policy with Omni Gateway Policy Development Kit (PDK), generate a new custom policy project. To create a Split-Model project, complete these tasks: 1. [Before You Begin](#before-you-begin) 2. [Create a New Policy Definition Project](#create-a-new-policy-definition-project) 3. Review [Definition Project Structure](#definition-project-structure) to learn about the different parts of the policy definition. 4. [Create a New Policy Implementation Project](#create-a-new-policy-implementation-project) 5. [Set Up the PDK Build Environment](#setup-the-pdk-build-environment) 6. Review [Implementation Project Structure](#implementation-project-structure) to learn about the different parts of the policy implementation. ## Before You Begin Before you can create a custom policy project, ensure that you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/1.8/policies-pdk-prerequisites). ## Create a New Policy Definition Project To create a custom policy definition project, run the PDK CLI `create` command, with the `--project-mode definition` flag, replacing `` with the name of your new policy: ```ssh anypoint-cli-v4 pdk policy-project create --name --project-mode definition ``` Running the `create` command creates a custom policy project with the specified name. The project appears in a new directory with the same name as your policy with the `-definition` suffix or a directory specified using the `--output-dir` flag. ## Definition Project Structure After running the `make build` command, the policy’s root directory contains the following directories and files shown in the directory tree: ├─ gcl.yaml # GCL file managed by the developer that describes the policy Definition ├─ exchange.json # Coordinates of the asset ├─ target/ # Contains the output of the policy definition build ├─ Makefile # Provides all the callable actions required during the policy definition development lifecycle ├─ README.md # Information regarding general help of available actions └─.gitignore # Configuration for git Version Control system to ignore built assets ### exchange.json Contains the exchange asset coordinate of the policy definition. ### target Contains the policy asset definition published to Exchange. The directory and its content are included in the `.gitignore` file. ### Definition Makefile The Makefile contains all the callable actions, such as `make` commands, required for the policy development lifecycle. Execute all `make` commands at the root level of your custom policy directory: - `make build`: Compiles the definition and generates the assets to be deployed. - `make publish`: Publishes the policy definition asset in Exchange. Since the publish goal is intended to publish a policy asset in development, the _assetId_ and name published explicitly say `dev`, and the versions published include a timestamp at the end of the version. For example: - groupId: your configured organization id - visible name: {Your policy name} Dev - assetId: {your-policy-asset-id}-dev - version: {your-policy-version}-20230618115723 For more information about publishing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.8/policies-pdk-publish-policies). - `make release`: Releases the policy definition asset in Exchange. For more information about releasing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.8/policies-pdk-publish-policies). - `make release-local`: Publishes the policy definition as a release asset to the local cache (no actual release to Exchange is made). You can override it. This target is useful if you’re also developing the policy implementation. - `make help`: Lists all the `make` commands provided by PDK. ## Create a New Policy Implementation Project To create a custom policy implementation project, run the PDK CLI `create` command, with the `--project-mode implementation` flag, replacing `` with the name of your new policy: ```ssh anypoint-cli-v4 pdk policy-project create --name --project-mode implementation ``` Running the `create` command creates a custom policy project with the specified name. The project appears in a new directory with the same name as your policy with the `-implementation` suffix or a directory specified using the `--output-dir` flag. > [!NOTE] If your implementation and definition projects have different names, link them by making > sure the `definition_asset_id.name` field in the implementation project’s `Cargo.toml` file > matches the asset ID in the definition project’s `exchange.json` file. ## Set Up the PDK Build Environment After you [create a new policy project](#create-a-new-policy-implementation-project), you must run the `make setup` command to download additional software dependencies: ```ssh make setup ``` ## Implementation Project Structure After running the `make setup` command, the policy’s root directory contains these directories and files shown in the directory tree: ├─ target/ # Contains the implementation asset files and the output of the policy build ├─ src/ # Contains the implementation source code ├─ playground/ # Contains the artifacts required for running the policy locally ├─ tests/ # Contains the source and configuration files to write and run integration tests ├─ Makefile # Provides all the callable actions required during the policy development lifecycle └─ Cargo.toml # Rust language standard file that contains the metadata required to build the policy ### target Contains the files for the policy’s Exchange asset implementation and the output of the project build. The target directory and its content are included in the `.gitignore` file. ### Cargo.toml Custom policies for Omni Gateway are developed in the Rust programming language and compiled to a WebAssembly binary. The `Cargo.toml` is the Rust project manifest. Its `[package]` section contains the basic information about the policy implementation. The version specified in `Cargo.toml` matches the policy asset version. You can manage the policy version by editing the version number in `Cargo.toml`. The version follows the format `..`. The toml also contains a section `[package.metadata.anypoint]` where you can specify: - `group_id`: The policy group ID, which should match your Anypoint organization. - `definition_asset_id`: The name of the policy definition and the version this implementation uses. If you need to work with a development version, append the `-DEV` (case sensitive) suffix, for example: `version = "1.0.0-DEV"`. - `implementation_asset_id`: The asset ID that’s used to release the policy. ```toml [package.metadata.anypoint] group_id = "43573332-0364-41f2-9486-d1248f3b4023" definition_asset_id = { name = "party-planner-split", version = "1.0.0" } implementation_asset_id = "team-planner-split-flex" ``` ### src/ The `src` directory contains the policy’s source code: - `lib.rs`: Contains a set of methods that implement the behavior of the policy. PDK includes these methods to implement custom policy behavior. For additional information about these methods, see [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-develop-custom-policies). For complete policy examples, see [Custom Policy Examples](https://docs.mulesoft.com/pdk/1.8/policies-pdk-policy-templates). - `generated/config.rs` and `generated/mod.rs`: Auto-generated modules that make the policy configuration, as defined in the `gcl.yaml`, available for use in the `lib.rs` and any of the policy source files. ### Implementation Makefile The Makefile contains all the callable actions, such as `make` commands, required for the policy development lifecycle. Execute all `make` commands at the root level of your custom policy directory: - `make setup`: Installs PDK internal dependencies for the rest of the Makefile goals. For more information about setting up your project, see [Set Up the PDK Build Environment](https://docs.mulesoft.com/pdk/1.8/policies-pdk-prerequisites). - `make build-asset-files`: Generates all the policy asset files required to build, execute, and publish the policy. This command also updates the `config.rs` source code file with the latest configurations defined in the `gcl.yaml` file. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-compile-policies). > [!NOTE] If you modify the `definition_asset_id` field in the `Cargo.toml`, re-run this target > manually. - `make build`: Compiles the WebAssembly binary of the policy. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-compile-policies). - `make run`: Provides a simple way to execute the current build of the policy in a Docker containerized environment. For more information about running and debugging your policy, see [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.8/policies-pdk-debug-local). - `make test`: Executes the tests contained in `tests/` by using the testing framework provided by PDK. For more information about testing your policy, see [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.8/policies-pdk-integration-tests). - `make publish`: Publishes the policy asset in Exchange. For more information about publishing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.8/policies-pdk-publish-policies). - `make release`: Releases the policy asset in Exchange. For more information about releasing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.8/policies-pdk-publish-policies). - `make help`: Lists all the `make` commands provided by PDK. ## See Also - [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.8/policies-pdk-publish-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.8/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Creating a Split-Model Policy Project > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To begin developing a new Split-Model custom policy with Omni Gateway Policy Development Kit (PDK), generate a new custom policy project. To create a Split-Model project, complete these tasks: 1. [Before You Begin](#before-you-begin) 2. [Create a New Policy Definition Project](#create-a-new-policy-definition-project) 3. Review [Definition Project Structure](#definition-project-structure) to learn about the different parts of the policy definition. 4. [Create a New Policy Implementation Project](#create-a-new-policy-implementation-project) 5. [Set Up the PDK Build Environment](#setup-the-pdk-build-environment) 6. Review [Implementation Project Structure](#implementation-project-structure) to learn about the different parts of the policy implementation. ## Before You Begin Before you can create a custom policy project, ensure that you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/1.9/policies-pdk-prerequisites). ## Create a New Policy Definition Project To create a custom policy definition project, run the PDK CLI `create` command, with the `--project-mode definition` flag, replacing `` with the name of your new policy: ```ssh anypoint-cli-v4 pdk policy-project create --name --project-mode definition ``` Running the `create` command creates a custom policy project with the specified name. The project appears in a new directory with the same name as your policy with the `-definition` suffix or a directory specified using the `--output-dir` flag. ## Definition Project Structure After running the `make build` command, the policy’s root directory contains the following directories and files shown in the directory tree: ├─ gcl.yaml # GCL file managed by the developer that describes the policy Definition ├─ exchange.json # Coordinates of the asset ├─ target/ # Contains the output of the policy definition build ├─ Makefile # Provides all the callable actions required during the policy definition development lifecycle ├─ README.md # Information regarding general help of available actions └─.gitignore # Configuration for git Version Control system to ignore built assets ### exchange.json Contains the exchange asset coordinate of the policy definition. ### target Contains the policy asset definition published to Exchange. The directory and its content are included in the `.gitignore` file. ### Definition Makefile The Makefile contains all the callable actions, such as `make` commands, required for the policy development lifecycle. Execute all `make` commands at the root level of your custom policy directory: - `make build`: Compiles the definition and generates the assets to be deployed. - `make publish`: Publishes the policy definition asset in Exchange. Since the publish goal is intended to publish a policy asset in development, the _assetId_ and name published explicitly say `dev`, and the versions published include a timestamp at the end of the version. For example: - groupId: your configured organization id - visible name: {Your policy name} Dev - assetId: {your-policy-asset-id}-dev - version: {your-policy-version}-20230618115723 For more information about publishing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.9/policies-pdk-publish-policies). - `make release`: Releases the policy definition asset in Exchange. For more information about releasing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.9/policies-pdk-publish-policies). - `make release-local`: Publishes the policy definition as a release asset to the local cache (no actual release to Exchange is made). You can override it. This target is useful if you’re also developing the policy implementation. - `make help`: Lists all the `make` commands provided by PDK. ## Create a New Policy Implementation Project To create a custom policy implementation project, run the PDK CLI `create` command, with the `--project-mode implementation` flag, replacing `` with the name of your new policy: ```ssh anypoint-cli-v4 pdk policy-project create --name --project-mode implementation ``` Running the `create` command creates a custom policy project with the specified name. The project appears in a new directory with the same name as your policy with the `-implementation` suffix or a directory specified using the `--output-dir` flag. > [!NOTE] If your implementation and definition projects have different names, link them by making > sure the `definition_asset_id.name` field in the implementation project’s `Cargo.toml` file > matches the asset ID in the definition project’s `exchange.json` file. ## Set Up the PDK Build Environment After you [create a new policy project](#create-a-new-policy-implementation-project), you must run the `make setup` command to download additional software dependencies: ```ssh make setup ``` ## Implementation Project Structure After running the `make setup` command, the policy’s root directory contains these directories and files shown in the directory tree: ├─ target/ # Contains the implementation asset files and the output of the policy build ├─ src/ # Contains the implementation source code ├─ playground/ # Contains the artifacts required for running the policy locally ├─ tests/ # Contains the source and configuration files to write and run integration tests ├─ Makefile # Provides all the callable actions required during the policy development lifecycle ├─ Cargo.toml # Rust language standard file that contains the metadata required to build the policy └─ AGENTS.md # Documentation for AI coding agents working with the policy project ### target Contains the files for the policy’s Exchange asset implementation and the output of the project build. The target directory and its content are included in the `.gitignore` file. ### Cargo.toml Custom policies for Omni Gateway are developed in the Rust programming language and compiled to a WebAssembly binary. The `Cargo.toml` is the Rust project manifest. Its `[package]` section contains the basic information about the policy implementation. The version specified in `Cargo.toml` matches the policy asset version. You can manage the policy version by editing the version number in `Cargo.toml`. The version follows the format `..`. The toml also contains a section `[package.metadata.anypoint]` where you can specify: - `group_id`: The policy group ID, which should match your Anypoint organization. - `definition_asset_id`: The name of the policy definition and the version this implementation uses. If you need to work with a development version, append the `-DEV` (case sensitive) suffix, for example: `version = "1.0.0-DEV"`. - `implementation_asset_id`: The asset ID that’s used to release the policy. ```toml [package.metadata.anypoint] group_id = "43573332-0364-41f2-9486-d1248f3b4023" definition_asset_id = { name = "party-planner-split", version = "1.0.0" } implementation_asset_id = "team-planner-split-flex" ``` ### src/ The `src` directory contains the policy’s source code: - `lib.rs`: Contains a set of methods that implement the behavior of the policy. PDK includes these methods to implement custom policy behavior. For additional information about these methods, see [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-develop-custom-policies). For complete policy examples, see [Custom Policy Examples](https://docs.mulesoft.com/pdk/1.9/policies-pdk-policy-templates). - `generated/config.rs` and `generated/mod.rs`: Auto-generated modules that make the policy configuration, as defined in the `gcl.yaml`, available for use in the `lib.rs` and any of the policy source files. ### Implementation Makefile The Makefile contains all the callable actions, such as `make` commands, required for the policy development lifecycle. Execute all `make` commands at the root level of your custom policy directory: - `make setup`: Installs PDK internal dependencies for the rest of the Makefile goals. For more information about setting up your project, see [Set Up the PDK Build Environment](https://docs.mulesoft.com/pdk/1.9/policies-pdk-prerequisites). - `make build-asset-files`: Generates all the policy asset files required to build, execute, and publish the policy. This command also updates the `config.rs` source code file with the latest configurations defined in the `gcl.yaml` file. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-compile-policies). > [!NOTE] If you modify the `definition_asset_id` field in the `Cargo.toml`, re-run this target > manually. - `make build`: Compiles the WebAssembly binary of the policy. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-compile-policies). - `make run`: Provides a simple way to execute the current build of the policy in a Docker containerized environment. For more information about running and debugging your policy, see [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.9/policies-pdk-debug-local). - `make test`: Executes the tests contained in `tests/` by using the testing framework provided by PDK. For more information about testing your policy, see [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.9/policies-pdk-integration-tests). - `make publish`: Publishes the policy asset in Exchange. For more information about publishing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.9/policies-pdk-publish-policies). - `make release`: Releases the policy asset in Exchange. For more information about releasing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.9/policies-pdk-publish-policies). - `make help`: Lists all the `make` commands provided by PDK. ### AGENTS.md The `AGENTS.md` file provides documentation and guidance for AI coding agents (such as Claude Code, GitHub Copilot, or other AI assistants) working with the custom policy project. This documentation enables AI assistants to provide more accurate code suggestions and helps prevent common errors when working with PDK projects. This file includes: - Repository purpose and architecture overview - Project structure explanation - proxy-wasm runtime constraints and limitations - Coding rules and best practices specific to PDK policies - Critical pitfalls to avoid when developing policies - Links to relevant PDK documentation and policy examples ## See Also - [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.9/policies-pdk-publish-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.9/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Creating a Split-Model Policy Project > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To begin developing a new Split-Model custom policy with Omni Gateway Policy Development Kit (PDK), generate a new custom policy project. To create a Split-Model project, complete these tasks: 1. [Before You Begin](#before-you-begin) 2. [Create a New Policy Definition Project](#create-a-new-policy-definition-project) 3. Review [Definition Project Structure](#definition-project-structure) to learn about the different parts of the policy definition. 4. [Create a New Policy Implementation Project](#create-a-new-policy-implementation-project) 5. [Set Up the PDK Build Environment](#setup-the-pdk-build-environment) 6. Review [Implementation Project Structure](#implementation-project-structure) to learn about the different parts of the policy implementation. ## Before You Begin Before you can create a custom policy project, ensure that you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites). ## Create a New Policy Definition Project To create a custom policy definition project, run the PDK CLI `create` command, with the `--project-mode definition` flag, replacing `` with the name of your new policy: ```ssh anypoint-cli-v4 pdk policy-project create --name --project-mode definition ``` Running the `create` command creates a custom policy project with the specified name. The project appears in a new directory with the same name as your policy with the `-definition` suffix or a directory specified using the `--output-dir` flag. ## Definition Project Structure After running the `make build` command, the policy’s root directory contains the following directories and files shown in the directory tree: ├─ gcl.yaml # GCL file managed by the developer that describes the policy Definition ├─ exchange.json # Coordinates of the asset ├─ target/ # Contains the output of the policy definition build ├─ Makefile # Provides all the callable actions required during the policy definition development lifecycle ├─ README.md # Information regarding general help of available actions └─.gitignore # Configuration for git Version Control system to ignore built assets ### exchange.json Contains the exchange asset coordinate of the policy definition. ### target Contains the policy asset definition published to Exchange. The directory and its content are included in the `.gitignore` file. ### Definition Makefile The Makefile contains all the callable actions, such as `make` commands, required for the policy development lifecycle. Execute all `make` commands at the root level of your custom policy directory: - `make build`: Compiles the definition and generates the assets to be deployed. - `make publish`: Publishes the policy definition asset in Exchange. Since the publish goal is intended to publish a policy asset in development, the _assetId_ and name published explicitly say `dev`, and the versions published include a timestamp at the end of the version. For example: - groupId: your configured organization id - visible name: {Your policy name} Dev - assetId: {your-policy-asset-id}-dev - version: {your-policy-version}-20230618115723 For more information about publishing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies). - `make release`: Releases the policy definition asset in Exchange. For more information about releasing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies). - `make release-local`: Publishes the policy definition as a release asset to the local cache (no actual release to Exchange is made). You can override it. This target is useful if you’re also developing the policy implementation. - `make help`: Lists all the `make` commands provided by PDK. ## Create a New Policy Implementation Project To create a custom policy implementation project, run the PDK CLI `create` command, with the `--project-mode implementation` flag, replacing `` with the name of your new policy: ```ssh anypoint-cli-v4 pdk policy-project create --name --project-mode implementation ``` Running the `create` command creates a custom policy project with the specified name. The project appears in a new directory with the same name as your policy with the `-implementation` suffix or a directory specified using the `--output-dir` flag. > [!NOTE] If your implementation and definition projects have different names, link them by making > sure the `definition_asset_id.name` field in the implementation project’s `Cargo.toml` file > matches the asset ID in the definition project’s `exchange.json` file. ## Set Up the PDK Build Environment After you [create a new policy project](#create-a-new-policy-implementation-project), you must run the `make setup` command to download additional software dependencies: ```ssh make setup ``` ## Implementation Project Structure After running the `make setup` command, the policy’s root directory contains these directories and files shown in the directory tree: ├─ target/ # Contains the implementation asset files and the output of the policy build ├─ src/ # Contains the implementation source code ├─ playground/ # Contains the artifacts required for running the policy locally ├─ tests/ # Contains the source and configuration files to write and run integration tests ├─ Makefile # Provides all the callable actions required during the policy development lifecycle ├─ Cargo.toml # Rust language standard file that contains the metadata required to build the policy └─ AGENTS.md # Documentation for AI coding agents working with the policy project ### target Contains the files for the policy’s Exchange asset implementation and the output of the project build. The target directory and its content are included in the `.gitignore` file. ### Cargo.toml Custom policies for Omni Gateway are developed in the Rust programming language and compiled to a WebAssembly binary. The `Cargo.toml` is the Rust project manifest. Its `[package]` section contains the basic information about the policy implementation. The version specified in `Cargo.toml` matches the policy asset version. You can manage the policy version by editing the version number in `Cargo.toml`. The version follows the format `..`. The toml also contains a section `[package.metadata.anypoint]` where you can specify: - `group_id`: The policy group ID, which should match your Anypoint organization. - `definition_asset_id`: The name of the policy definition and the version this implementation uses. If you need to work with a development version, append the `-DEV` (case sensitive) suffix, for example: `version = "1.0.0-DEV"`. - `implementation_asset_id`: The asset ID that’s used to release the policy. ```toml [package.metadata.anypoint] group_id = "43573332-0364-41f2-9486-d1248f3b4023" definition_asset_id = { name = "party-planner-split", version = "1.0.0" } implementation_asset_id = "team-planner-split-flex" ``` ### src/ The `src` directory contains the policy’s source code: - `lib.rs`: Contains a set of methods that implement the behavior of the policy. PDK includes these methods to implement custom policy behavior. For additional information about these methods, see [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-develop-custom-policies). For complete policy examples, see [Custom Policy Examples](https://docs.mulesoft.com/pdk/latest/policies-pdk-policy-templates). - `generated/config.rs` and `generated/mod.rs`: Auto-generated modules that make the policy configuration, as defined in the `gcl.yaml`, available for use in the `lib.rs` and any of the policy source files. ### Implementation Makefile The Makefile contains all the callable actions, such as `make` commands, required for the policy development lifecycle. Execute all `make` commands at the root level of your custom policy directory: - `make setup`: Installs PDK internal dependencies for the rest of the Makefile goals. For more information about setting up your project, see [Set Up the PDK Build Environment](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites). - `make build-asset-files`: Generates all the policy asset files required to build, execute, and publish the policy. This command also updates the `config.rs` source code file with the latest configurations defined in the `gcl.yaml` file. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-compile-policies). > [!NOTE] If you modify the `definition_asset_id` field in the `Cargo.toml`, re-run this target > manually. - `make build`: Compiles the WebAssembly binary of the policy. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-compile-policies). - `make run`: Provides a simple way to execute the current build of the policy in a Docker containerized environment. For more information about running and debugging your policy, see [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/latest/policies-pdk-debug-local). - `make test`: Executes the tests contained in `tests/` by using the testing framework provided by PDK. For more information about testing your policy, see [Writing Integration Tests](https://docs.mulesoft.com/pdk/latest/policies-pdk-integration-tests). - `make publish`: Publishes the policy asset in Exchange. For more information about publishing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies). - `make release`: Releases the policy asset in Exchange. For more information about releasing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies). - `make help`: Lists all the `make` commands provided by PDK. ### AGENTS.md The `AGENTS.md` file provides documentation and guidance for AI coding agents (such as Claude Code, GitHub Copilot, or other AI assistants) working with the custom policy project. This documentation enables AI assistants to provide more accurate code suggestions and helps prevent common errors when working with PDK projects. This file includes: - Repository purpose and architecture overview - Project structure explanation - proxy-wasm runtime constraints and limitations - Coding rules and best practices specific to PDK policies - Critical pitfalls to avoid when developing policies - Links to relevant PDK documentation and policy examples ## See Also - [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/latest/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Creating a Unified-Model (Regular) Policy Project > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To begin developing a new custom policy with Flex Gateway Policy Development Kit (PDK), generate a new custom policy project. To create a new project, complete the following tasks: 1. [Before You Begin](#before-you-begin) 2. [Create a New Policy Project](#create-a-new-policy-project) 3. [Set Up the PDK Build Environment](#setup-the-pdk-build-environment) 4. Review [Project Structure](#project-structure) ## Before You Begin Before you can create a custom policy project, ensure that you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/1.7/policies-pdk-prerequisites). ## Create a New Policy Project To create a custom policy project, run the PDK CLI `create` command, replacing `` with the name of your new policy: ```ssh anypoint-cli-v4 pdk policy-project create --name ``` > [!NOTE] If you receive a prompt requesting your group ID, see > [Troubleshooting Group ID](https://docs.mulesoft.com/pdk/1.7/policies-pdk-troubleshooting#group-id-error). Running the `create` command creates a custom policy project with the specified name. The project appears in a new directory with the same name as your policy or a directory specified using the `--output-dir` flag. The following tutorials refer to this as your project’s root directory. The `assetID` of the new policy is the policy’s name in lower case with the spaces amended together with a `-`. For example, a policy with the name `My Header Injection Policy` has the `assetID` of `my-header-injection-policy`. The `groupID` of the new policy is the ID of the organization configured in Anypoint CLI. The `create` command supports the following flags:
FlagDefault ValueRequiredDescription

--name=<value> or -n

N/A

Yes

Name of the new policy.

--description=<value> or -d

N/A

No

Description of the new policy.

--output-dir=<value> of -o

assetID

No

Directory the new policy is created in.
If the directory does not exist, it is created. If no directory is specified, the directory name is the policy assetID.

--version=<value>

1.0.0

No

Version of the new policy.
The version format is <major-release>.<minor-release>.<patch-release>.

--group-id=<value>

N/A

No

Organization ID of the organization that owns the policy.
For additional information about this flag, see Troubleshooting Group ID.

## Set Up the PDK Build Environment After you [create a new policy project](#create-a-new-policy-project), you must run the `make setup` command to download additional software dependencies: ```ssh make setup ``` ## Project Structure After running the `make setup` command, the policy’s root directory contains the following directories and files shown in the directory tree: ├─ definition/ # Contains the files that describe the policy Definition │ ├── target/ # Contains the build definition asset files │ └── gcl.yaml # GCL file managed by the developer that describes the policy Definition ├─ target/ # Contains the implementation asset files and the output of the policy build ├─ src/ # Contains the implementation source code ├─ playground/ # Contains the artifacts required for running the policy locally ├─ tests/ # Contains the source and configuration files to write and run integration tests ├─ Makefile # Provides all the callable actions required during the policy development lifecycle ├─ Cargo.toml # Rust language standard file that contains the metadata required to build the policy └─.project.yaml # Project manifest used by PDK ### target/ and definition/target/ There are two separate `target` directories: - `definition/target/`: Contains the policy asset definition published to Exchange. - `target/`: Contains the files for the policy’s Exchange asset implementation and the output of the project build. Both target directories and their content are included in the `.gitignore` file. You must compile the targets on each individual devices using the `make build` command. For example, if you develop a policy as part of the team, your team can publish the policy and its source code to a remote repository, but each team member must build the target on their device to work with the policy. ### definition/ The `definition` directory contains the `gcl.yaml` file that defines the policy’s metadata and the configuration properties. To configure the `gcl.yaml` file, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-schema-definition). ### Cargo.toml Custom policies for Flex Gateway are developed in the Rust programming language and compiled to a WebAssembly binary. The `Cargo.toml` is the Rust project manifest. Its `[package]` section contains the basic information about the policy implementation. The version specified in `Cargo.toml` matches the policy asset version. You can manage the policy version by editing the version number in `Cargo.toml`. The version follows the format `..`. ### src/ The `src` directory contains the policy’s source code: - `lib.rs`: Contains a set of methods that implement the behavior of the policy. PDK includes these methods to implement custom policies behavior. For additional information about these methods, see [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features). For complete policy examples, see [Custom Policy Examples](https://docs.mulesoft.com/pdk/1.7/policies-pdk-policy-templates). - `generated/config.rs` and `generated/mod.rs`: Auto-generated modules that make the policy configuration, as defined in the `gcl.yaml`, available for use in the `lib.rs` and any of the policy source files. ### Makefile The Makefile contains all the callable actions, such as `make` commands, required for the policy development lifecycle. Execute all `make` commands at the root level of your custom policy directory directory: - `make setup`: Installs PDK internal dependencies for the rest of the Makefile goals. For more information about setting up your project, see [Set Up the PDK Build Environment](#setup-the-pdk-build-environment). - `make build-asset-files`: Generates all the policy asset files required to build, execute, and publish the policy. This command also updates the `config.rs` source code file with the latest configurations defined in the `gcl.yaml` file. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-compile-policies). - `make build`: Runs the `make build-asset-files` command and compiles the WebAssembly binary of the policy. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-compile-policies). - `make run`: Provides a simple way to execute the current build of the policy in a Docker containerized environment. For more information about running and debugging your policy, see [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.7/policies-pdk-debug-local). - `make test`: Executes the tests contained in `tests/` by using the testing framework provided by PDK. For more information about testing your policy, see [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.7/policies-pdk-integration-tests). - `make publish`: Publishes the policy asset in Exchange. For more information about publishing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.7/policies-pdk-publish-policies). - `make release`: Releases the policy asset in Exchange. For more information about releasing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.7/policies-pdk-publish-policies). - `make help`: Lists all the `make` commands provided by PDK. ## See Also - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.7/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Creating a Unified-Model (Regular) Policy Project > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To begin developing a new custom policy with Omni Gateway Policy Development Kit (PDK), generate a new custom policy project. To create a new project, complete the following tasks: 1. [Before You Begin](#before-you-begin) 2. [Create a New Policy Project](#create-a-new-policy-project) 3. [Set Up the PDK Build Environment](#setup-the-pdk-build-environment) 4. Review [Project Structure](#project-structure) ## Before You Begin Before you can create a custom policy project, ensure that you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/1.8/policies-pdk-prerequisites). ## Create a New Policy Project To create a custom policy project, run the PDK CLI `create` command, replacing `` with the name of your new policy: ```ssh anypoint-cli-v4 pdk policy-project create --name ``` > [!NOTE] If you receive a prompt requesting your group ID, see > [Troubleshooting Group ID](https://docs.mulesoft.com/pdk/1.8/policies-pdk-troubleshooting#group-id-error). Running the `create` command creates a custom policy project with the specified name. The project appears in a new directory with the same name as your policy or a directory specified using the `--output-dir` flag. The following tutorials refer to this as your project’s root directory. The `assetID` of the new policy is the policy’s name in lower case with the spaces amended together with a `-`. For example, a policy with the name `My Header Injection Policy` has the `assetID` of `my-header-injection-policy`. The `groupID` of the new policy is the ID of the organization configured in Anypoint CLI. The `create` command supports the following flags:
FlagDefault ValueRequiredDescription

--name=<value> or -n

N/A

Yes

Name of the new policy.

--description=<value> or -d

N/A

No

Description of the new policy.

--output-dir=<value> of -o

assetID

No

Directory the new policy is created in.
If the directory does not exist, it is created. If no directory is specified, the directory name is the policy assetID.

--version=<value>

1.0.0

No

Version of the new policy.
The version format is <major-release>.<minor-release>.<patch-release>.

--group-id=<value>

N/A

No

Organization ID of the organization that owns the policy.
For additional information about this flag, see Troubleshooting Group ID.

## Set Up the PDK Build Environment After you [create a new policy project](#create-a-new-policy-project), you must run the `make setup` command to download additional software dependencies: ```ssh make setup ``` ## Project Structure After running the `make setup` command, the policy’s root directory contains the following directories and files shown in the directory tree: ├─ definition/ # Contains the files that describe the policy Definition │ ├── target/ # Contains the build definition asset files │ └── gcl.yaml # GCL file managed by the developer that describes the policy Definition ├─ target/ # Contains the implementation asset files and the output of the policy build ├─ src/ # Contains the implementation source code ├─ playground/ # Contains the artifacts required for running the policy locally ├─ tests/ # Contains the source and configuration files to write and run integration tests ├─ Makefile # Provides all the callable actions required during the policy development lifecycle ├─ Cargo.toml # Rust language standard file that contains the metadata required to build the policy └─.project.yaml # Project manifest used by PDK ### target/ and definition/target/ There are two separate `target` directories: - `definition/target/`: Contains the policy asset definition published to Exchange. - `target/`: Contains the files for the policy’s Exchange asset implementation and the output of the project build. Both target directories and their content are included in the `.gitignore` file. You must compile the targets on each individual devices using the `make build` command. For example, if you develop a policy as part of the team, your team can publish the policy and its source code to a remote repository, but each team member must build the target on their device to work with the policy. ### definition/ The `definition` directory contains the `gcl.yaml` file that defines the policy’s metadata and the configuration properties. To configure the `gcl.yaml` file, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-schema-definition). ### Cargo.toml Custom policies for Omni Gateway are developed in the Rust programming language and compiled to a WebAssembly binary. The `Cargo.toml` is the Rust project manifest. Its `[package]` section contains the basic information about the policy implementation. The version specified in `Cargo.toml` matches the policy asset version. You can manage the policy version by editing the version number in `Cargo.toml`. The version follows the format `..`. ### src/ The `src` directory contains the policy’s source code: - `lib.rs`: Contains a set of methods that implement the behavior of the policy. PDK includes these methods to implement custom policies behavior. For additional information about these methods, see [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features). For complete policy examples, see [Custom Policy Examples](https://docs.mulesoft.com/pdk/1.8/policies-pdk-policy-templates). - `generated/config.rs` and `generated/mod.rs`: Auto-generated modules that make the policy configuration, as defined in the `gcl.yaml`, available for use in the `lib.rs` and any of the policy source files. ### Makefile The Makefile contains all the callable actions, such as `make` commands, required for the policy development lifecycle. Execute all `make` commands at the root level of your custom policy directory directory: - `make setup`: Installs PDK internal dependencies for the rest of the Makefile goals. For more information about setting up your project, see [Set Up the PDK Build Environment](#setup-the-pdk-build-environment). - `make build-asset-files`: Generates all the policy asset files required to build, execute, and publish the policy. This command also updates the `config.rs` source code file with the latest configurations defined in the `gcl.yaml` file. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-compile-policies). - `make build`: Runs the `make build-asset-files` command and compiles the WebAssembly binary of the policy. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-compile-policies). - `make run`: Provides a simple way to execute the current build of the policy in a Docker containerized environment. For more information about running and debugging your policy, see [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.8/policies-pdk-debug-local). - `make test`: Executes the tests contained in `tests/` by using the testing framework provided by PDK. For more information about testing your policy, see [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.8/policies-pdk-integration-tests). - `make publish`: Publishes the policy asset in Exchange. For more information about publishing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.8/policies-pdk-publish-policies). - `make release`: Releases the policy asset in Exchange. For more information about releasing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.8/policies-pdk-publish-policies). - `make help`: Lists all the `make` commands provided by PDK. ## See Also - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.8/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Creating a Unified-Model (Regular) Policy Project > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To begin developing a new custom policy with Omni Gateway Policy Development Kit (PDK), generate a new custom policy project. To create a new project, complete the following tasks: 1. [Before You Begin](#before-you-begin) 2. [Create a New Policy Project](#create-a-new-policy-project) 3. [Set Up the PDK Build Environment](#setup-the-pdk-build-environment) 4. Review [Project Structure](#project-structure) ## Before You Begin Before you can create a custom policy project, ensure that you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/1.9/policies-pdk-prerequisites). ## Create a New Policy Project To create a custom policy project, run the PDK CLI `create` command, replacing `` with the name of your new policy: ```ssh anypoint-cli-v4 pdk policy-project create --name ``` > [!NOTE] If you receive a prompt requesting your group ID, see > [Troubleshooting Group ID](https://docs.mulesoft.com/pdk/1.9/policies-pdk-troubleshooting#group-id-error). Running the `create` command creates a custom policy project with the specified name. The project appears in a new directory with the same name as your policy or a directory specified using the `--output-dir` flag. The following tutorials refer to this as your project’s root directory. The `assetID` of the new policy is the policy’s name in lower case with the spaces amended together with a `-`. For example, a policy with the name `My Header Injection Policy` has the `assetID` of `my-header-injection-policy`. The `groupID` of the new policy is the ID of the organization configured in Anypoint CLI. The `create` command supports the following flags:
FlagDefault ValueRequiredDescription

--name=<value> or -n

N/A

Yes

Name of the new policy.

--description=<value> or -d

N/A

No

Description of the new policy.

--output-dir=<value> of -o

assetID

No

Directory the new policy is created in.
If the directory does not exist, it is created. If no directory is specified, the directory name is the policy assetID.

--version=<value>

1.0.0

No

Version of the new policy.
The version format is <major-release>.<minor-release>.<patch-release>.

--group-id=<value>

N/A

No

Organization ID of the organization that owns the policy.
For additional information about this flag, see Troubleshooting Group ID.

--fips

N/A

No

Creates the policy project with FIPS compliance enabled.
Configures the PDK to use FIPS-compliant modules. To maintain FIPS compliance, make sure any additional dependencies you add are compliant.

## Set Up the PDK Build Environment After you [create a new policy project](#create-a-new-policy-project), you must run the `make setup` command to download additional software dependencies: ```ssh make setup ``` ## Project Structure After running the `make setup` command, the policy’s root directory contains the following directories and files shown in the directory tree: ├─ definition/ # Contains the files that describe the policy Definition │ ├── target/ # Contains the build definition asset files │ └── gcl.yaml # GCL file managed by the developer that describes the policy Definition ├─ target/ # Contains the implementation asset files and the output of the policy build ├─ src/ # Contains the implementation source code ├─ playground/ # Contains the artifacts required for running the policy locally ├─ tests/ # Contains the source and configuration files to write and run integration tests ├─ Makefile # Provides all the callable actions required during the policy development lifecycle ├─ Cargo.toml # Rust language standard file that contains the metadata required to build the policy ├─ AGENTS.md # Documentation for AI coding agents working with the policy project └─.project.yaml # Project manifest used by PDK ### target/ and definition/target/ There are two separate `target` directories: - `definition/target/`: Contains the policy asset definition published to Exchange. - `target/`: Contains the files for the policy’s Exchange asset implementation and the output of the project build. Both target directories and their content are included in the `.gitignore` file. You must compile the targets on each individual devices using the `make build` command. For example, if you develop a policy as part of the team, your team can publish the policy and its source code to a remote repository, but each team member must build the target on their device to work with the policy. ### definition/ The `definition` directory contains the `gcl.yaml` file that defines the policy’s metadata and the configuration properties. To configure the `gcl.yaml` file, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-schema-definition). ### Cargo.toml Custom policies for Omni Gateway are developed in the Rust programming language and compiled to a WebAssembly binary. The `Cargo.toml` is the Rust project manifest. Its `[package]` section contains the basic information about the policy implementation. The version specified in `Cargo.toml` matches the policy asset version. You can manage the policy version by editing the version number in `Cargo.toml`. The version follows the format `..`. #### Configure PDK Features in Cargo.toml The JWT and XML Validator libraries are gated behind Cargo features to reduce compiled WASM size. Both features are enabled by default (`default = ["jwt", "xml_validator"]`). If you don’t require JWT or XML validation functionality in your custom policy, you can disable these features by editing the PDK dependency in your `Cargo.toml`: ```toml # Disable both JWT and XML Validator: pdk = { version = "1.9.1", default-features = false } # Keep only JWT: pdk = { version = "1.9.1", default-features = false, features = ["jwt"] } # Keep only XML Validator: pdk = { version = "1.9.1", default-features = false, features = ["xml_validator"] } ``` ### src/ The `src` directory contains the policy’s source code: - `lib.rs`: Contains a set of methods that implement the behavior of the policy. PDK includes these methods to implement custom policies behavior. For additional information about these methods, see [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features). For complete policy examples, see [Custom Policy Examples](https://docs.mulesoft.com/pdk/1.9/policies-pdk-policy-templates). - `generated/config.rs` and `generated/mod.rs`: Auto-generated modules that make the policy configuration, as defined in the `gcl.yaml`, available for use in the `lib.rs` and any of the policy source files. ### Makefile The Makefile contains all the callable actions, such as `make` commands, required for the policy development lifecycle. Execute all `make` commands at the root level of your custom policy directory directory: - `make setup`: Installs PDK internal dependencies for the rest of the Makefile goals. For more information about setting up your project, see [Set Up the PDK Build Environment](#setup-the-pdk-build-environment). - `make build-asset-files`: Generates all the policy asset files required to build, execute, and publish the policy. This command also updates the `config.rs` source code file with the latest configurations defined in the `gcl.yaml` file. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-compile-policies). - `make build`: Runs the `make build-asset-files` command and compiles the WebAssembly binary of the policy. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-compile-policies). - `make run`: Provides a simple way to execute the current build of the policy in a Docker containerized environment. For more information about running and debugging your policy, see [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.9/policies-pdk-debug-local). - `make test`: Executes the tests contained in `tests/` by using the testing framework provided by PDK. For more information about testing your policy, see [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.9/policies-pdk-integration-tests). - `make publish`: Publishes the policy asset in Exchange. For more information about publishing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.9/policies-pdk-publish-policies). - `make release`: Releases the policy asset in Exchange. For more information about releasing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.9/policies-pdk-publish-policies). - `make help`: Lists all the `make` commands provided by PDK. ### AGENTS.md The `AGENTS.md` file provides documentation and guidance for AI coding agents (such as Claude Code, GitHub Copilot, or other AI assistants) working with the custom policy project. This documentation enables AI assistants to provide more accurate code suggestions and helps prevent common errors when working with PDK projects. This file includes: - Repository purpose and architecture overview - Project structure explanation - proxy-wasm runtime constraints and limitations - Coding rules and best practices specific to PDK policies - Critical pitfalls to avoid when developing policies - Links to relevant PDK documentation and policy examples ## See Also - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.9/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Creating a Unified-Model (Regular) Policy Project > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To begin developing a new custom policy with Omni Gateway Policy Development Kit (PDK), generate a new custom policy project. To create a new project, complete the following tasks: 1. [Before You Begin](#before-you-begin) 2. [Create a New Policy Project](#create-a-new-policy-project) 3. [Set Up the PDK Build Environment](#setup-the-pdk-build-environment) 4. Review [Project Structure](#project-structure) ## Before You Begin Before you can create a custom policy project, ensure that you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites). ## Create a New Policy Project To create a custom policy project, run the PDK CLI `create` command, replacing `` with the name of your new policy: ```ssh anypoint-cli-v4 pdk policy-project create --name ``` > [!NOTE] If you receive a prompt requesting your group ID, see > [Troubleshooting Group ID](https://docs.mulesoft.com/pdk/latest/policies-pdk-troubleshooting#group-id-error). Running the `create` command creates a custom policy project with the specified name. The project appears in a new directory with the same name as your policy or a directory specified using the `--output-dir` flag. The following tutorials refer to this as your project’s root directory. The `assetID` of the new policy is the policy’s name in lower case with the spaces amended together with a `-`. For example, a policy with the name `My Header Injection Policy` has the `assetID` of `my-header-injection-policy`. The `groupID` of the new policy is the ID of the organization configured in Anypoint CLI. The `create` command supports the following flags:
FlagDefault ValueRequiredDescription

--name=<value> or -n

N/A

Yes

Name of the new policy.

--description=<value> or -d

N/A

No

Description of the new policy.

--output-dir=<value> of -o

assetID

No

Directory the new policy is created in.
If the directory does not exist, it is created. If no directory is specified, the directory name is the policy assetID.

--version=<value>

1.0.0

No

Version of the new policy.
The version format is <major-release>.<minor-release>.<patch-release>.

--group-id=<value>

N/A

No

Organization ID of the organization that owns the policy.
For additional information about this flag, see Troubleshooting Group ID.

--fips

N/A

No

Creates the policy project with FIPS compliance enabled.
Configures the PDK to use FIPS-compliant modules. To maintain FIPS compliance, make sure any additional dependencies you add are compliant.

## Set Up the PDK Build Environment After you [create a new policy project](#create-a-new-policy-project), you must run the `make setup` command to download additional software dependencies: ```ssh make setup ``` ## Project Structure After running the `make setup` command, the policy’s root directory contains the following directories and files shown in the directory tree: ├─ definition/ # Contains the files that describe the policy Definition │ ├── target/ # Contains the build definition asset files │ └── gcl.yaml # GCL file managed by the developer that describes the policy Definition ├─ target/ # Contains the implementation asset files and the output of the policy build ├─ src/ # Contains the implementation source code ├─ playground/ # Contains the artifacts required for running the policy locally ├─ tests/ # Contains the source and configuration files to write and run integration tests ├─ Makefile # Provides all the callable actions required during the policy development lifecycle ├─ Cargo.toml # Rust language standard file that contains the metadata required to build the policy ├─ AGENTS.md # Documentation for AI coding agents working with the policy project └─.project.yaml # Project manifest used by PDK ### target/ and definition/target/ There are two separate `target` directories: - `definition/target/`: Contains the policy asset definition published to Exchange. - `target/`: Contains the files for the policy’s Exchange asset implementation and the output of the project build. Both target directories and their content are included in the `.gitignore` file. You must compile the targets on each individual devices using the `make build` command. For example, if you develop a policy as part of the team, your team can publish the policy and its source code to a remote repository, but each team member must build the target on their device to work with the policy. ### definition/ The `definition` directory contains the `gcl.yaml` file that defines the policy’s metadata and the configuration properties. To configure the `gcl.yaml` file, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-schema-definition). ### Cargo.toml Custom policies for Omni Gateway are developed in the Rust programming language and compiled to a WebAssembly binary. The `Cargo.toml` is the Rust project manifest. Its `[package]` section contains the basic information about the policy implementation. The version specified in `Cargo.toml` matches the policy asset version. You can manage the policy version by editing the version number in `Cargo.toml`. The version follows the format `..`. #### Configure PDK Features in Cargo.toml The JWT and XML Validator libraries are gated behind Cargo features to reduce compiled WASM size. Both features are enabled by default (`default = ["jwt", "xml_validator"]`). If you don’t require JWT or XML validation functionality in your custom policy, you can disable these features by editing the PDK dependency in your `Cargo.toml`: ```toml # Disable both JWT and XML Validator: pdk = { version = "1.10.0", default-features = false } # Keep only JWT: pdk = { version = "1.10.0", default-features = false, features = ["jwt"] } # Keep only XML Validator: pdk = { version = "1.10.0", default-features = false, features = ["xml_validator"] } ``` ### src/ The `src` directory contains the policy’s source code: - `lib.rs`: Contains a set of methods that implement the behavior of the policy. PDK includes these methods to implement custom policies behavior. For additional information about these methods, see [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features). For complete policy examples, see [Custom Policy Examples](https://docs.mulesoft.com/pdk/latest/policies-pdk-policy-templates). - `generated/config.rs` and `generated/mod.rs`: Auto-generated modules that make the policy configuration, as defined in the `gcl.yaml`, available for use in the `lib.rs` and any of the policy source files. ### Makefile The Makefile contains all the callable actions, such as `make` commands, required for the policy development lifecycle. Execute all `make` commands at the root level of your custom policy directory directory: - `make setup`: Installs PDK internal dependencies for the rest of the Makefile goals. For more information about setting up your project, see [Set Up the PDK Build Environment](#setup-the-pdk-build-environment). - `make build-asset-files`: Generates all the policy asset files required to build, execute, and publish the policy. This command also updates the `config.rs` source code file with the latest configurations defined in the `gcl.yaml` file. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-compile-policies). - `make build`: Runs the `make build-asset-files` command and compiles the WebAssembly binary of the policy. For more information about compiling a policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-compile-policies). - `make run`: Provides a simple way to execute the current build of the policy in a Docker containerized environment. For more information about running and debugging your policy, see [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/latest/policies-pdk-debug-local). - `make test`: Executes the tests contained in `tests/` by using the testing framework provided by PDK. For more information about testing your policy, see [Writing Integration Tests](https://docs.mulesoft.com/pdk/latest/policies-pdk-integration-tests). - `make publish`: Publishes the policy asset in Exchange. For more information about publishing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies). - `make release`: Releases the policy asset in Exchange. For more information about releasing policies in Exchange, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies). - `make help`: Lists all the `make` commands provided by PDK. ### AGENTS.md The `AGENTS.md` file provides documentation and guidance for AI coding agents (such as Claude Code, GitHub Copilot, or other AI assistants) working with the custom policy project. This documentation enables AI assistants to provide more accurate code suggestions and helps prevent common errors when working with PDK projects. This file includes: - Repository purpose and architecture overview - Project structure explanation - proxy-wasm runtime constraints and limitations - Coding rules and best practices specific to PDK policies - Critical pitfalls to avoid when developing policies - Links to relevant PDK documentation and policy examples ## See Also - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/latest/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Creating Mule Gateway PDK Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) supports creating Mule Gateway policies to enhance your experience: - Creating policies - Defining the configuration schema - Deploying policies to Exchange The PDK Anypoint CLI plugin generates custom policy folders with all required policy files. In the folder, PDK includes a Makefile with commands to build the policy UI and deploy to Exchange. To create Mule custom policies: 1. Ensure you meet the [Before You Begin](#before-you-begin) prerequisites. 2. [Create a custom policy](#create-policy). 3. [Define a policy schema](#define-schema). 4. [Define policy logic](#define-policy-logic). 5. [Publish and release the policy](#publish-policies). ## Before You Begin Before you begin, ensure you meet the these prerequisites: - PDK supported operating system with Make installed See [Supported Operating Systems](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites#supported-operating-systems). - Anypoint CLI See [Anypoint CLI PDK Requirements](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites#cli). - Java For supported Java versions, see [Java Support](https://docs.mulesoft.com/general/java-support). - [Apache Maven](https://maven.apache.org/) Apache Maven is a prerequisite for the [Mule Maven Plugin](https://docs.mulesoft.com/mule-runtime/latest/mmp-concept). PDK Mule Policy projects include an embedded Mule Maven Plugin so downloading the plugin is not required. To ensure your Maven version is compatible with the latest plugin, see [Mule Maven Plugin Release Notes](https://docs.mulesoft.com/release-notes/mule-maven-plugin/mule-maven-plugin-release-notes). - MuleSoft’s Maven archetype Configure MuleSoft’s Maven archetype by adding the following code section to Maven’s `settings.xml` file: ```xml archetype-repository archetype Mule Repository https://repository.mulesoft.org/nexus/content/repositories/public true fail true warn ``` ## Create a Mule Custom Policy with PDK To create your custom policy execute: ```cmd pdk policy-project create --name --implementation-technology mule4 ``` Running this command generates a custom policy folder with the policy name. The folder contains a makefile that provides all the callable actions required during the policy development lifecycle. ## Define a Policy Schema Use the `gcl.yaml` file inside you policy project to define the policy’s schema. PDK generates your policy’s UI json from the parameters defined in the schema definition. This replaces the previous need of manually writing a `config.json` schema file. To define a schema definition, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.4/policies-pdk-create-schema-definition). Include all parameters in schema that you reference in you `template.xml` file. > [!NOTE] Mule Gateway custom policies support the Dataweave format, but don’t support DataWeave > Bindings. For more information, see > [DataWeave Expressions](https://docs.mulesoft.com/pdk/1.4/policies-pdk-create-schema-definition#dataweave-expressions). ## Define the Policy Logic Define the policy logic in the `template.xml` file. The `template.xml` file, by default, contains the logic for a basic policy that sets the returned HTTP Response payload to a “Hello World!” message. View the file to see the logic. For more policy logic examples, see: - [Developing a Custom Response Policy](https://docs.mulesoft.com/mule-gateway/policies-custom-response-example) - [Developing a Custom Policy Using the Event Authentication Extension](https://docs.mulesoft.com/mule-gateway/policies-custom-set-authentication-example) ## Publish and Release Policies PDK publishes Mule Gateway and Flex Gateway policies in the same way. To publish and release policies, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies). ## See Also - [Mule Gateway Custom Policies](https://docs.mulesoft.com/mule-gateway/policies-custom-overview) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Creating Mule Gateway PDK Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) supports creating Mule Gateway policies to enhance your experience: - Creating policies - Defining the configuration schema - Deploying policies to Exchange The PDK Anypoint CLI plugin generates custom policy folders with all required policy files. In the folder, PDK includes a Makefile with commands to build the policy UI and deploy to Exchange. To create Mule custom policies: 1. Ensure you meet the [Before You Begin](#before-you-begin) prerequisites. 2. [Create a custom policy](#create-policy). 3. [Define a policy schema](#define-schema). 4. [Define policy logic](#define-policy-logic). 5. [Publish and release the policy](#publish-policies). ## Before You Begin Before you begin, ensure you meet the these prerequisites: - PDK supported operating system with Make installed See [Supported Operating Systems](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites#supported-operating-systems). - Anypoint CLI See [Anypoint CLI PDK Requirements](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites#cli). - Java For supported Java versions, see [Java Support](https://docs.mulesoft.com/general/java-support). - [Apache Maven](https://maven.apache.org/) Apache Maven is a prerequisite for the [Mule Maven Plugin](https://docs.mulesoft.com/mule-runtime/latest/mmp-concept). PDK Mule Policy projects include an embedded Mule Maven Plugin so downloading the plugin is not required. To ensure your Maven version is compatible with the latest plugin, see [Mule Maven Plugin Release Notes](https://docs.mulesoft.com/release-notes/mule-maven-plugin/mule-maven-plugin-release-notes). - MuleSoft’s Maven archetype Configure MuleSoft’s Maven archetype by adding the following code section to Maven’s `settings.xml` file: ```xml archetype-repository archetype Mule Repository https://repository.mulesoft.org/nexus/content/repositories/public true fail true warn ``` ## Create a Mule Custom Policy with PDK To create your custom policy execute: ```cmd pdk policy-project create --name --implementation-technology mule4 ``` Running this command generates a custom policy folder with the policy name. The folder contains a makefile that provides all the callable actions required during the policy development lifecycle. ## Define a Policy Schema Use the `gcl.yaml` file inside you policy project to define the policy’s schema. PDK generates your policy’s UI json from the parameters defined in the schema definition. This replaces the previous need of manually writing a `config.json` schema file. To define a schema definition, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.5/policies-pdk-create-schema-definition). Include all parameters in schema that you reference in you `template.xml` file. > [!NOTE] Mule Gateway custom policies support the Dataweave format, but don’t support DataWeave > Bindings. For more information, see > [DataWeave Expressions](https://docs.mulesoft.com/pdk/1.5/policies-pdk-create-schema-definition#dataweave-expressions). ## Define the Policy Logic Define the policy logic in the `template.xml` file. The `template.xml` file, by default, contains the logic for a basic policy that sets the returned HTTP Response payload to a “Hello World!” message. View the file to see the logic. For more policy logic examples, see: - [Developing a Custom Response Policy](https://docs.mulesoft.com/mule-gateway/policies-custom-response-example) - [Developing a Custom Policy Using the Event Authentication Extension](https://docs.mulesoft.com/mule-gateway/policies-custom-set-authentication-example) ## Publish and Release Policies PDK publishes Mule Gateway and Flex Gateway policies in the same way. To publish and release policies, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies). ## See Also - [Mule Gateway Custom Policies](https://docs.mulesoft.com/mule-gateway/policies-custom-overview) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Creating Mule Gateway PDK Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) supports creating Mule Gateway policies to enhance your experience: - Creating policies - Defining the configuration schema - Deploying policies to Exchange The PDK Anypoint CLI plugin generates custom policy folders with all required policy files. In the folder, PDK includes a Makefile with commands to build the policy UI and deploy to Exchange. To create Mule custom policies: 1. Ensure you meet the [Before You Begin](#before-you-begin) prerequisites. 2. [Create a custom policy](#create-policy). 3. [Define a policy schema](#define-schema). 4. [Define policy logic](#define-policy-logic). 5. [Publish and release the policy](#publish-policies). ## Before You Begin Before you begin, ensure you meet the these prerequisites: - PDK supported operating system with Make installed See [Supported Operating Systems](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites#supported-operating-systems). - Anypoint CLI See [Anypoint CLI PDK Requirements](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites#cli). - Java For supported Java versions, see [Java Support](https://docs.mulesoft.com/general/java-support). - [Apache Maven](https://maven.apache.org/) Apache Maven is a prerequisite for the [Mule Maven Plugin](https://docs.mulesoft.com/mule-runtime/latest/mmp-concept). PDK Mule Policy projects include an embedded Mule Maven Plugin so downloading the plugin is not required. To ensure your Maven version is compatible with the latest plugin, see [Mule Maven Plugin Release Notes](https://docs.mulesoft.com/release-notes/mule-maven-plugin/mule-maven-plugin-release-notes). - MuleSoft’s Maven archetype Configure MuleSoft’s Maven archetype by adding the following code section to Maven’s `settings.xml` file: ```xml archetype-repository archetype Mule Repository https://repository.mulesoft.org/nexus/content/repositories/public true fail true warn ``` ## Create a Mule Custom Policy with PDK To create your custom policy execute: ```cmd pdk policy-project create --name --implementation-technology mule4 ``` Running this command generates a custom policy folder with the policy name. The folder contains a makefile that provides all the callable actions required during the policy development lifecycle. ## Define a Policy Schema Use the `gcl.yaml` file inside you policy project to define the policy’s schema. PDK generates your policy’s UI json from the parameters defined in the schema definition. This replaces the previous need of manually writing a `config.json` schema file. To define a schema definition, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.6/policies-pdk-create-schema-definition). Include all parameters in schema that you reference in you `template.xml` file. > [!NOTE] Mule Gateway custom policies support the Dataweave format, but don’t support DataWeave > Bindings. For more information, see > [DataWeave Expressions](https://docs.mulesoft.com/pdk/1.6/policies-pdk-create-schema-definition#dataweave-expressions). ## Define the Policy Logic Define the policy logic in the `template.xml` file. The `template.xml` file, by default, contains the logic for a basic policy that sets the returned HTTP Response payload to a “Hello World!” message. View the file to see the logic. For more policy logic examples, see: - [Developing a Custom Response Policy](https://docs.mulesoft.com/mule-gateway/policies-custom-response-example) - [Developing a Custom Policy Using the Event Authentication Extension](https://docs.mulesoft.com/mule-gateway/policies-custom-set-authentication-example) ## Publish and Release Policies PDK publishes Mule Gateway and Flex Gateway policies in the same way. To publish and release policies, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies). ## See Also - [Mule Gateway Custom Policies](https://docs.mulesoft.com/mule-gateway/policies-custom-overview) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Creating Mule Gateway PDK Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) supports creating Mule Gateway policies to enhance your experience: - Creating policies - Defining the configuration schema - Deploying policies to Exchange The PDK Anypoint CLI plugin generates custom policy folders with all required policy files. In the folder, PDK includes a Makefile with commands to build the policy UI and deploy to Exchange. To create Mule custom policies: 1. Ensure you meet the [Before You Begin](#before-you-begin) prerequisites. 2. [Create a custom policy](#create-policy). 3. [Define a policy schema](#define-schema). 4. [Define policy logic](#define-policy-logic). 5. [Publish and release the policy](#publish-policies). ## Before You Begin Before you begin, ensure you meet the these prerequisites: - PDK supported operating system with Make installed See [Supported Operating Systems](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites#supported-operating-systems). - Anypoint CLI See [Anypoint CLI PDK Requirements](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites#cli). - Java For supported Java versions, see [Java Support](https://docs.mulesoft.com/general/java-support). - [Apache Maven](https://maven.apache.org/) Apache Maven is a prerequisite for the [Mule Maven Plugin](https://docs.mulesoft.com/mule-runtime/latest/mmp-concept). PDK Mule Policy projects include an embedded Mule Maven Plugin so downloading the plugin is not required. To ensure your Maven version is compatible with the latest plugin, see [Mule Maven Plugin Release Notes](https://docs.mulesoft.com/release-notes/mule-maven-plugin/mule-maven-plugin-release-notes). - MuleSoft’s Maven archetype Configure MuleSoft’s Maven archetype by adding the following code section to Maven’s `settings.xml` file: ```xml archetype-repository archetype Mule Repository https://repository.mulesoft.org/nexus/content/repositories/public true fail true warn ``` ## Create a Mule Custom Policy with PDK To create your custom policy execute: ```cmd pdk policy-project create --name --implementation-technology mule4 ``` Running this command generates a custom policy folder with the policy name. The folder contains a makefile that provides all the callable actions required during the policy development lifecycle. ## Define a Policy Schema Use the `gcl.yaml` file inside you policy project to define the policy’s schema. PDK generates your policy’s UI json from the parameters defined in the schema definition. This replaces the previous need of manually writing a `config.json` schema file. To define a schema definition, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-schema-definition). Include all parameters in schema that you reference in you `template.xml` file. > [!NOTE] Mule Gateway custom policies support the Dataweave format, but don’t support DataWeave > Bindings. For more information, see > [DataWeave Expressions](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-schema-definition#dataweave-expressions). ## Define the Policy Logic Define the policy logic in the `template.xml` file. The `template.xml` file, by default, contains the logic for a basic policy that sets the returned HTTP Response payload to a “Hello World!” message. View the file to see the logic. For more policy logic examples, see: - [Developing a Custom Response Policy](https://docs.mulesoft.com/mule-gateway/policies-custom-response-example) - [Developing a Custom Policy Using the Event Authentication Extension](https://docs.mulesoft.com/mule-gateway/policies-custom-set-authentication-example) ## Publish and Release Policies PDK publishes Mule Gateway and Flex Gateway policies in the same way. To publish and release policies, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies). ## See Also - [Mule Gateway Custom Policies](https://docs.mulesoft.com/mule-gateway/policies-custom-overview) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Creating Mule Gateway PDK Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) supports creating Mule Gateway policies to enhance your experience: - Creating policies - Defining the configuration schema - Deploying policies to Exchange The PDK Anypoint CLI plugin generates custom policy folders with all required policy files. In the folder, PDK includes a Makefile with commands to build the policy UI and deploy to Exchange. To create Mule custom policies: 1. Ensure you meet the [Before You Begin](#before-you-begin) prerequisites. 2. [Create a custom policy](#create-policy). 3. [Define a policy schema](#define-schema). 4. [Define policy logic](#define-policy-logic). 5. [Publish and release the policy](#publish-policies). ## Before You Begin Before you begin, ensure you meet the these prerequisites: - PDK supported operating system with Make installed See [Supported Operating Systems](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites#supported-operating-systems). - Anypoint CLI See [Anypoint CLI PDK Requirements](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites#cli). - Java For supported Java versions, see [Java Support](https://docs.mulesoft.com/general/java-support). - [Apache Maven](https://maven.apache.org/) Apache Maven is a prerequisite for the [Mule Maven Plugin](https://docs.mulesoft.com/mule-runtime/latest/mmp-concept). PDK Mule Policy projects include an embedded Mule Maven Plugin so downloading the plugin is not required. To ensure your Maven version is compatible with the latest plugin, see [Mule Maven Plugin Release Notes](https://docs.mulesoft.com/release-notes/mule-maven-plugin/mule-maven-plugin-release-notes). - MuleSoft’s Maven archetype Configure MuleSoft’s Maven archetype by adding the following code section to Maven’s `settings.xml` file: ```xml archetype-repository archetype Mule Repository https://repository.mulesoft.org/nexus/content/repositories/public true fail true warn ``` ## Create a Mule Custom Policy with PDK To create your custom policy execute: ```cmd pdk policy-project create --name --implementation-technology mule4 ``` Running this command generates a custom policy folder with the policy name. The folder contains a makefile that provides all the callable actions required during the policy development lifecycle. ## Define a Policy Schema Use the `gcl.yaml` file inside you policy project to define the policy’s schema. PDK generates your policy’s UI json from the parameters defined in the schema definition. This replaces the previous need of manually writing a `config.json` schema file. To define a schema definition, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-schema-definition). Include all parameters in schema that you reference in you `template.xml` file. > [!NOTE] Mule Gateway custom policies support the Dataweave format, but don’t support DataWeave > Bindings. For more information, see > [DataWeave Expressions](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-schema-definition#dataweave-expressions). ## Define the Policy Logic Define the policy logic in the `template.xml` file. The `template.xml` file, by default, contains the logic for a basic policy that sets the returned HTTP Response payload to a “Hello World!” message. View the file to see the logic. For more policy logic examples, see: - [Developing a Custom Response Policy](https://docs.mulesoft.com/mule-gateway/policies-custom-response-example) - [Developing a Custom Policy Using the Event Authentication Extension](https://docs.mulesoft.com/mule-gateway/policies-custom-set-authentication-example) ## Publish and Release Policies PDK publishes Mule Gateway and Omni Gateway policies in the same way. To publish and release policies, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies). ## See Also - [Mule Gateway Custom Policies](https://docs.mulesoft.com/mule-gateway/policies-custom-overview) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Creating Mule Gateway PDK Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) supports creating Mule Gateway policies to enhance your experience: - Creating policies - Defining the configuration schema - Deploying policies to Exchange The PDK Anypoint CLI plugin generates custom policy folders with all required policy files. In the folder, PDK includes a Makefile with commands to build the policy UI and deploy to Exchange. To create Mule custom policies: 1. Ensure you meet the [Before You Begin](#before-you-begin) prerequisites. 2. [Create a custom policy](#create-policy). 3. [Define a policy schema](#define-schema). 4. [Define policy logic](#define-policy-logic). 5. [Publish and release the policy](#publish-policies). ## Before You Begin Before you begin, ensure you meet the these prerequisites: - PDK supported operating system with Make installed See [Supported Operating Systems](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites#supported-operating-systems). - Anypoint CLI See [Anypoint CLI PDK Requirements](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites#cli). - Java For supported Java versions, see [Java Support](https://docs.mulesoft.com/general/java-support). - [Apache Maven](https://maven.apache.org/) Apache Maven is a prerequisite for the [Mule Maven Plugin](https://docs.mulesoft.com/mule-runtime/latest/mmp-concept). PDK Mule Policy projects include an embedded Mule Maven Plugin so downloading the plugin is not required. To ensure your Maven version is compatible with the latest plugin, see [Mule Maven Plugin Release Notes](https://docs.mulesoft.com/release-notes/mule-maven-plugin/mule-maven-plugin-release-notes). - MuleSoft’s Maven archetype Configure MuleSoft’s Maven archetype by adding the following code section to Maven’s `settings.xml` file: ```xml archetype-repository archetype Mule Repository https://repository.mulesoft.org/nexus/content/repositories/public true fail true warn ``` ## Create a Mule Custom Policy with PDK To create your custom policy execute: ```cmd pdk policy-project create --name --implementation-technology mule4 ``` Running this command generates a custom policy folder with the policy name. The folder contains a makefile that provides all the callable actions required during the policy development lifecycle. ## Define a Policy Schema Use the `gcl.yaml` file inside you policy project to define the policy’s schema. PDK generates your policy’s UI json from the parameters defined in the schema definition. This replaces the previous need of manually writing a `config.json` schema file. To define a schema definition, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-schema-definition). Include all parameters in schema that you reference in you `template.xml` file. > [!NOTE] Mule Gateway custom policies support the Dataweave format, but don’t support DataWeave > Bindings. For more information, see > [DataWeave Expressions](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-schema-definition#dataweave-expressions). ## Define the Policy Logic Define the policy logic in the `template.xml` file. The `template.xml` file, by default, contains the logic for a basic policy that sets the returned HTTP Response payload to a “Hello World!” message. View the file to see the logic. For more policy logic examples, see: - [Developing a Custom Response Policy](https://docs.mulesoft.com/mule-gateway/policies-custom-response-example) - [Developing a Custom Policy Using the Event Authentication Extension](https://docs.mulesoft.com/mule-gateway/policies-custom-set-authentication-example) ## Publish and Release Policies PDK publishes Mule Gateway and Omni Gateway policies in the same way. To publish and release policies, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies). ## See Also - [Mule Gateway Custom Policies](https://docs.mulesoft.com/mule-gateway/policies-custom-overview) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Creating Mule Gateway PDK Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) supports creating Mule Gateway policies to enhance your experience: - Creating policies - Defining the configuration schema - Deploying policies to Exchange The PDK Anypoint CLI plugin generates custom policy folders with all required policy files. In the folder, PDK includes a Makefile with commands to build the policy UI and deploy to Exchange. To create Mule custom policies: 1. Ensure you meet the [Before You Begin](#before-you-begin) prerequisites. 2. [Create a custom policy](#create-policy). 3. [Define a policy schema](#define-schema). 4. [Define policy logic](#define-policy-logic). 5. [Publish and release the policy](#publish-policies). ## Before You Begin Before you begin, ensure you meet the these prerequisites: - PDK supported operating system with Make installed See [Supported Operating Systems](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites#supported-operating-systems). - Anypoint CLI See [Anypoint CLI PDK Requirements](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites#cli). - Java For supported Java versions, see [Java Support](https://docs.mulesoft.com/general/java-support). - [Apache Maven](https://maven.apache.org/) Apache Maven is a prerequisite for the [Mule Maven Plugin](https://docs.mulesoft.com/mule-runtime/latest/mmp-concept). PDK Mule Policy projects include an embedded Mule Maven Plugin so downloading the plugin is not required. To ensure your Maven version is compatible with the latest plugin, see [Mule Maven Plugin Release Notes](https://docs.mulesoft.com/release-notes/mule-maven-plugin/mule-maven-plugin-release-notes). - MuleSoft’s Maven archetype Configure MuleSoft’s Maven archetype by adding the following code section to Maven’s `settings.xml` file: ```xml archetype-repository archetype Mule Repository https://repository.mulesoft.org/nexus/content/repositories/public true fail true warn ``` ## Create a Mule Custom Policy with PDK To create your custom policy execute: ```cmd pdk policy-project create --name --implementation-technology mule4 ``` Running this command generates a custom policy folder with the policy name. The folder contains a makefile that provides all the callable actions required during the policy development lifecycle. ## Define a Policy Schema Use the `gcl.yaml` file inside you policy project to define the policy’s schema. PDK generates your policy’s UI json from the parameters defined in the schema definition. This replaces the previous need of manually writing a `config.json` schema file. To define a schema definition, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-schema-definition). Include all parameters in schema that you reference in you `template.xml` file. > [!NOTE] Mule Gateway custom policies support the Dataweave format, but don’t support DataWeave > Bindings. For more information, see > [DataWeave Expressions](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-schema-definition#dataweave-expressions). ## Define the Policy Logic Define the policy logic in the `template.xml` file. The `template.xml` file, by default, contains the logic for a basic policy that sets the returned HTTP Response payload to a “Hello World!” message. View the file to see the logic. For more policy logic examples, see: - [Developing a Custom Response Policy](https://docs.mulesoft.com/mule-gateway/policies-custom-response-example) - [Developing a Custom Policy Using the Event Authentication Extension](https://docs.mulesoft.com/mule-gateway/policies-custom-set-authentication-example) ## Publish and Release Policies PDK publishes Mule Gateway and Omni Gateway policies in the same way. To publish and release policies, see [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies). ## See Also - [Mule Gateway Custom Policies](https://docs.mulesoft.com/mule-gateway/policies-custom-overview) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Custom Policy Examples > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides example policy projects to get started configuring your Rust source code. Find all policy examples and their documentation in the [PDK Custom Policy GitHub Repository](https://github.com/mulesoft/pdk-custom-policy-examples). PDK offers the following example policies: - [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/block/README.md): Use the Block Policy as an example of how to block IP ranges by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-timer) and [HTTP calls](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-http-request). - [Certification Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/certs/README.md): Use the Certification Policy as an example of how to obtain data concerning connection certificates. - [CORS Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/cors-validation/README.md): Use the CORS Validation Policy as an example of how to use functions of the [CORS Library](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-cors) in your custom policy. - [Crypto Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/crypto/README.md): Use the Crypto Policy as an example of how to use [third-party libraries](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-libraries) that provide cryptography capabilities in your custom policy. - [Data Caching Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/data-caching/README.md): Use the Data Caching Policy as an example of how to implement [data caching](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-caching) in your custom policy. - [JWT Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/jwt-validation/README.md): Use the JWT Validation Policy as an example of how to use functions of the [JWT Library](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-jwt) in your custom policy. - [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/metrics/README.md): Use the Metrics Policy as an example of how to periodically send data to a metric ingestion service by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-timer) and [HTTP calls](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-http-request). - [Query Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/query/README.md): Use the Query Policy as an example of how to handle [DataWeave expressions](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-dataweave) in your custom policy. - [Simple OAuth 2.0 Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/simple-oauth-2-validation/README.md): Use the Simple OAuth 2.0 Validation Policy as an example of how to implement [HTTP calls](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-http-request) in your custom policy. - [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/spike/README.md): Use the Spike Policy as an example of how to configure worker spike control by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-timer). - [TLS Calls Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/tls-calls/README.md): Use the TLS Calls Policy as an example of how to make HTTPS calls in your policy without installing certificates on the operating system running Flex Gateway. ## Set Up an Example Policy Project To begin using an example policy project: 1. Ensure you have installed all the [PDK prerequisites](https://docs.mulesoft.com/pdk/1.2/policies-pdk-prerequisites). 2. Clone the [PDK Custom Policy GitHub Repository](https://github.com/mulesoft/pdk-custom-policy-examples) with the following command or your preferred GitHub interface: ```ssh git clone https://github.com/mulesoft/pdk-custom-policy-examples.git ``` 3. Navigate to the newly cloned directory, then copy and paste the directory of your desired policy into a new location. 4. In the `cargo.toml` file of the copied policy example, replace the `group-id` with your group ID, for example: ```toml group_id = "" ``` 5. Run the `make setup` command. ```ssh make setup ``` 6. Navigate to the `README.md` file in the example policy to read more about the policy and how to test it. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Custom Policy Examples > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides example policy projects to help you start configuring your Rust source code. You can find all example policies and their documentation in the [PDK Custom Policy GitHub Repository](https://github.com/mulesoft/pdk-custom-policy-examples). ## API Policy Examples PDK includes the following API example policies: - [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/block/README.md): Use the Block Policy as an example of how to block IP ranges by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-timer) and [HTTP calls](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-http-request). - [Certification Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/certs/README.md): Use the Certification Policy as an example of how to obtain data concerning connection certificates. - [CORS Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/cors-validation/README.md): Use the CORS Validation Policy as an example of how to use functions of the [CORS Library](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-cors) in your custom policy. - [Crypto Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/crypto/README.md): Use the Crypto Policy as an example of how to use [third-party libraries](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-libraries) that provide cryptography capabilities in your custom policy. - [Data Caching Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/data-caching/README.md): Use the Data Caching Policy as an example of how to implement [data caching](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-caching) in your custom policy. - [JWT Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/jwt-validation/README.md): Use the JWT Validation Policy as an example of how to use functions of the [JWT Library](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-jwt) in your custom policy. - [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/metrics/README.md): Use the Metrics Policy as an example of how to periodically send data to a metric ingestion service by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-timer) and [HTTP calls](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-http-request). - [Query Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/query/README.md): Use the Query Policy as an example of how to handle [DataWeave expressions](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-dataweave) in your custom policy. - [Simple OAuth 2.0 Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/simple-oauth-2-validation/README.md): Use the Simple OAuth 2.0 Validation Policy as an example of how to implement [HTTP calls](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-http-request) in your custom policy. - [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/spike/README.md): Use the Spike Policy as an example of how to configure worker spike control by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-timer). - [TLS Calls Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/tls-calls/README.md): Use the TLS Calls Policy as an example of how to make HTTPS calls in your policy without installing certificates on the operating system running Flex Gateway. ## A2A and MCP Server Policy Examples PDK includes the following A2A and MCP example policies: - [A2A Support Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-support-policy/README.md): Demonstrates how to add A2A support. - [MCP Support Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/mcp-support-policy/README.md): Shows how to add MCP support. - [A2A PII Detector Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-pii-detector-policy/README.md): Demonstrates how to log or block sensitive information in A2A agent interactions. - [A2A Prompt Decorator Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-prompt-decorator-policy/README.md): Shows how to modify prompts sent to an A2A agent. ## Set Up an Example Policy Project To use an example policy project: 1. Make sure you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/1.3/policies-pdk-prerequisites). 2. Clone the [PDK Custom Policy GitHub Repository](https://github.com/mulesoft/pdk-custom-policy-examples) using the following command or your preferred GitHub interface: ```ssh git clone https://github.com/mulesoft/pdk-custom-policy-examples.git ``` 3. Navigate to the newly cloned directory, then copy and paste the directory of your desired policy into a new location. 4. In the `cargo.toml` file of the copied policy example, replace the `group-id` with your group ID, for example: ```toml group_id = "" ``` 5. Run the `make setup` command: ```ssh make setup ``` 6. Navigate to the `README.md` file in the example policy to read more about the policy and how to test it. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Custom Policy Examples > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides example policy projects to help you start configuring your Rust source code. You can find all example policies and their documentation in the [PDK Custom Policy GitHub Repository](https://github.com/mulesoft/pdk-custom-policy-examples). ## API Policy Examples PDK includes the following API example policies: - [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/block/README.md): Use the Block Policy as an example of how to block IP ranges by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-timer) and [HTTP calls](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-http-request). - [Certification Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/certs/README.md): Use the Certification Policy as an example of how to obtain data concerning connection certificates. - [CORS Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/cors-validation/README.md): Use the CORS Validation Policy as an example of how to use functions of the [CORS Library](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-cors) in your custom policy. - [Crypto Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/crypto/README.md): Use the Crypto Policy as an example of how to use [third-party libraries](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-libraries) that provide cryptography capabilities in your custom policy. - [Data Caching Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/data-caching/README.md): Use the Data Caching Policy as an example of how to implement [data caching](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-caching) in your custom policy. - [DataWeave Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/dataweave/README.md): Use the DataWeave Policy as an example of how to handle [custom DataWeave expressions](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-dataweave) in your custom policy. - [JWT Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/jwt-validation/README.md): Use the JWT Validation Policy as an example of how to use functions of the [JWT Library](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-jwt) in your custom policy. - [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/metrics/README.md): Use the Metrics Policy as an example of how to periodically send data to a metric ingestion service by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-timer) and [HTTP calls](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-http-request). - [Query Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/query/README.md): Use the Query Policy as an example of how to handle query parameters in your custom policy. - [Simple OAuth 2.0 Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/simple-oauth-2-validation/README.md): Use the Simple OAuth 2.0 Validation Policy as an example of how to implement [HTTP calls](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-http-request) in your custom policy. - [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/spike/README.md): Use the Spike Policy as an example of how to configure worker spike control by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-timer). - [Stream Payload Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/stream-payload/README.md): Use the Stream Payload Policy as an example of how to [read payload bodies larger than 1MB](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-headers#streaming-bodies). - [TLS Calls Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/tls-calls/README.md): Use the TLS Calls Policy as an example of how to make HTTPS calls in your policy without installing certificates on the operating system running Flex Gateway. ## A2A and MCP Server Policy Examples PDK includes the following A2A and MCP example policies: - [A2A Support Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-support-policy/README.md): Demonstrates how to add A2A support. - [MCP Support Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/mcp-support-policy/README.md): Shows how to add MCP support. - [A2A PII Detector Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-pii-detector-policy/README.md): Demonstrates how to log or block sensitive information in A2A agent interactions. - [A2A Prompt Decorator Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-prompt-decorator-policy/README.md): Shows how to modify prompts sent to an A2A agent. ## Set Up an Example Policy Project To use an example policy project: 1. Make sure you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/1.4/policies-pdk-prerequisites). 2. Clone the [PDK Custom Policy GitHub Repository](https://github.com/mulesoft/pdk-custom-policy-examples) using the following command or your preferred GitHub interface: ```ssh git clone https://github.com/mulesoft/pdk-custom-policy-examples.git ``` 3. Navigate to the newly cloned directory, then copy and paste the directory of your desired policy into a new location. 4. In the `cargo.toml` file of the copied policy example, replace the `group-id` with your group ID, for example: ```toml group_id = "" ``` 5. Run the `make setup` command: ```ssh make setup ``` 6. Navigate to the `README.md` file in the example policy to read more about the policy and how to test it. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Custom Policy Examples > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides example policy projects to help you start configuring your Rust source code. You can find all example policies and their documentation in the [PDK Custom Policy GitHub Repository](https://github.com/mulesoft/pdk-custom-policy-examples). ## API Policy Examples PDK includes the following API example policies: - [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/block/README.md): Use the Block Policy as an example of how to block IP ranges by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-timer) and [HTTP calls](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-http-request). - [Certification Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/certs/README.md): Use the Certification Policy as an example of how to obtain data concerning connection certificates. - [CORS Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/cors-validation/README.md): Use the CORS Validation Policy as an example of how to use functions of the [CORS Library](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-cors) in your custom policy. - [Crypto Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/crypto/README.md): Use the Crypto Policy as an example of how to use [third-party libraries](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-libraries) that provide cryptography capabilities in your custom policy. - [Data Caching Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/data-caching/README.md): Use the Data Caching Policy as an example of how to implement [data caching](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-caching) in your custom policy. - [Data Storage Stats Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/data-storage-stats/README.md): Use the Data Storage Stats Policy as an example of how to implement [data storage](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-data-storage) with both local (in-memory) and shared (Redis) data storage. - [DataWeave Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/dataweave/README.md): Use the DataWeave Policy as an example of how to handle [custom DataWeave expressions](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-dataweave) in your custom policy. - [JWT Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/jwt-validation/README.md): Use the JWT Validation Policy as an example of how to use functions of the [JWT Library](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-jwt) in your custom policy. - [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/metrics/README.md): Use the Metrics Policy as an example of how to periodically send data to a metric ingestion service by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-timer) and [HTTP calls](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-http-request). - [Query Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/query/README.md): Use the Query Policy as an example of how to handle query parameters in your custom policy. - [Simple OAuth 2.0 Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/simple-oauth-2-validation/README.md): Use the Simple OAuth 2.0 Validation Policy as an example of how to implement [HTTP calls](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-http-request) in your custom policy. - [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/spike/README.md): Use the Spike Policy as an example of how to configure worker spike control by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-timer). - [Stream Payload Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/stream-payload/README.md): Use the Stream Payload Policy as an example of how to [read payload bodies larger than 1MB](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-headers#streaming-bodies). - [TLS Calls Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/tls-calls/README.md): Use the TLS Calls Policy as an example of how to make HTTPS calls in your policy without installing certificates on the operating system running Flex Gateway. ## A2A and MCP Server Policy Examples PDK includes the following A2A and MCP example policies: - [A2A Support Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-support-policy/README.md): Demonstrates how to add A2A support. - [MCP Support Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/mcp-support-policy/README.md): Shows how to add MCP support. - [A2A PII Detector Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-pii-detector-policy/README.md): Demonstrates how to log or block sensitive information in A2A agent interactions. - [A2A Prompt Decorator Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-prompt-decorator-policy/README.md): Shows how to modify prompts sent to an A2A agent. ## Set Up an Example Policy Project To use an example policy project: 1. Make sure you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/1.5/policies-pdk-prerequisites). 2. Clone the [PDK Custom Policy GitHub Repository](https://github.com/mulesoft/pdk-custom-policy-examples) using the following command or your preferred GitHub interface: ```ssh git clone https://github.com/mulesoft/pdk-custom-policy-examples.git ``` 3. Navigate to the newly cloned directory, then copy and paste the directory of your desired policy into a new location. 4. In the `cargo.toml` file of the copied policy example, replace the `group-id` with your group ID, for example: ```toml group_id = "" ``` 5. Run the `make setup` command: ```ssh make setup ``` 6. Navigate to the `README.md` file in the example policy to read more about the policy and how to test it. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Custom Policy Examples > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides example policy projects to help you start configuring your Rust source code. You can find all example policies and their documentation in the [PDK Custom Policy GitHub Repository](https://github.com/mulesoft/pdk-custom-policy-examples). ## API Policy Examples PDK includes the following API example policies: - [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/block/README.md): Use the Block Policy as an example of how to block IP ranges by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-timer) and [HTTP calls](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-http-request). - [Certification Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/certs/README.md): Use the Certification Policy as an example of how to obtain data concerning connection certificates. - [CORS Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/cors-validation/README.md): Use the CORS Validation Policy as an example of how to use functions of the [CORS Library](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-cors) in your custom policy. - [Crypto Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/crypto/README.md): Use the Crypto Policy as an example of how to use [third-party libraries](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-libraries) that provide cryptography capabilities in your custom policy. - [Data Caching Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/data-caching/README.md): Use the Data Caching Policy as an example of how to implement [data caching](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-caching) in your custom policy. - [Data Storage Stats Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/data-storage-stats/README.md): Use the Data Storage Stats Policy as an example of how to implement [data storage](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-data-storage) with both local (in-memory) and shared (Redis) data storage. - [DataWeave Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/dataweave/README.md): Use the DataWeave Policy as an example of how to handle [custom DataWeave expressions](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-dataweave) in your custom policy. - [JWT Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/jwt-validation/README.md): Use the JWT Validation Policy as an example of how to use functions of the [JWT Library](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-jwt) in your custom policy. - [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/metrics/README.md): Use the Metrics Policy as an example of how to periodically send data to a metric ingestion service by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-timer) and [HTTP calls](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-http-request). - [Query Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/query/README.md): Use the Query Policy as an example of how to handle query parameters in your custom policy. - [Simple OAuth 2.0 Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/simple-oauth-2-validation/README.md): Use the Simple OAuth 2.0 Validation Policy as an example of how to implement [HTTP calls](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-http-request) in your custom policy. - [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/spike/README.md): Use the Spike Policy as an example of how to configure worker spike control by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-timer). - [Stream Payload Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/stream-payload/README.md): Use the Stream Payload Policy as an example of how to [read payload bodies larger than 1MB](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-headers#streaming-bodies). - [TLS Calls Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/tls-calls/README.md): Use the TLS Calls Policy as an example of how to make HTTPS calls in your policy without installing certificates on the operating system running Flex Gateway. ## A2A and MCP Server Policy Examples PDK includes the following A2A and MCP example policies: - [A2A Support Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-support-policy/README.md): Demonstrates how to add A2A support. - [MCP Support Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/mcp-support-policy/README.md): Shows how to add MCP support. - [A2A PII Detector Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-pii-detector-policy/README.md): Demonstrates how to log or block sensitive information in A2A agent interactions. - [A2A Prompt Decorator Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-prompt-decorator-policy/README.md): Shows how to modify prompts sent to an A2A agent. ## Set Up an Example Policy Project To use an example policy project: 1. Make sure you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/1.6/policies-pdk-prerequisites). 2. Clone the [PDK Custom Policy GitHub Repository](https://github.com/mulesoft/pdk-custom-policy-examples) using the following command or your preferred GitHub interface: ```ssh git clone https://github.com/mulesoft/pdk-custom-policy-examples.git ``` 3. Navigate to the newly cloned directory, then copy and paste the directory of your desired policy into a new location. 4. In the `cargo.toml` file of the copied policy example, replace the `group-id` with your group ID, for example: ```toml group_id = "" ``` 5. Run the `make setup` command: ```ssh make setup ``` 6. Navigate to the `README.md` file in the example policy to read more about the policy and how to test it. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Custom Policy Examples > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides example policy projects to help you start configuring your Rust source code. You can find all example policies and their documentation in the [PDK Custom Policy GitHub Repository](https://github.com/mulesoft/pdk-custom-policy-examples). ## API Policy Examples PDK includes the following API example policies: - [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/block/README.md): Use the Block Policy as an example of how to block IP ranges by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-timer) and [HTTP calls](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-http-request). - [Certification Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/certs/README.md): Use the Certification Policy as an example of how to obtain data concerning connection certificates. - [CORS Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/cors-validation/README.md): Use the CORS Validation Policy as an example of how to use functions of the [CORS Library](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-cors) in your custom policy. - [Crypto Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/crypto/README.md): Use the Crypto Policy as an example of how to use [third-party libraries](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-libraries) that provide cryptography capabilities in your custom policy. - [Data Caching Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/data-caching/README.md): Use the Data Caching Policy as an example of how to implement [data caching](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-caching) in your custom policy. - [Data Storage Stats Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/data-storage-stats/README.md): Use the Data Storage Stats Policy as an example of how to implement [data storage](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-data-storage) with both local (in-memory) and shared (Redis) data storage. - [DataWeave Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/dataweave/README.md): Use the DataWeave Policy as an example of how to handle [custom DataWeave expressions](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-dataweave) in your custom policy. - [JWT Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/jwt-validation/README.md): Use the JWT Validation Policy as an example of how to use functions of the [JWT Library](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-jwt) in your custom policy. - [JWT Generation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/jwt-generation/README.md): Use the JWT Generation Policy as an example of how to generate JWT tokens using the [JWT generation function](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-jwt#create-jwt-token). - [OAuth 2.0 Token Introspection Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/oauth-2-token-introspection/README.md): Use the OAuth 2.0 Token Introspection Policy as an example of how to use [Token Introspection](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-token-introspection) in your custom policy. - [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/metrics/README.md): Use the Metrics Policy as an example of how to periodically send data to a metric ingestion service by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-timer) and [HTTP calls](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-http-request). - [IP Filter Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/ip-filter/README.md): Use the IP Filter Policy as an example of how to extract client IPs from request headers and implement IP-based access control using PDK’s [IP Filter feature](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-ip-filter). - [Query Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/query/README.md): Use the Query Policy as an example of how to handle query parameters in your custom policy. - [Simple OAuth 2.0 Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/simple-oauth-2-validation/README.md): Use the Simple OAuth 2.0 Validation Policy as an example of how to implement [HTTP calls](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-http-request) in your custom policy. - [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/spike/README.md): Use the Spike Policy as an example of how to configure worker spike control by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-timer). - [Stream Payload Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/stream-payload/README.md): Use the Stream Payload Policy as an example of how to [read payload bodies larger than 1MB](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-headers#streaming-bodies). - [TLS Calls Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/tls-calls/README.md): Use the TLS Calls Policy as an example of how to make HTTPS calls in your policy without installing certificates on the operating system running Flex Gateway. ## A2A and MCP Server Policy Examples PDK includes the following A2A and MCP example policies: - [A2A Support Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-support-policy/README.md): Demonstrates how to add A2A support. - [MCP Support Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/mcp-support-policy/README.md): Shows how to add MCP support. - [A2A PII Detector Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-pii-detector-policy/README.md): Demonstrates how to log or block sensitive information in A2A agent interactions. - [A2A Prompt Decorator Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-prompt-decorator-policy/README.md): Shows how to modify prompts sent to an A2A agent. ## Set Up an Example Policy Project To use an example policy project: 1. Make sure you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/1.7/policies-pdk-prerequisites). 2. Clone the [PDK Custom Policy GitHub Repository](https://github.com/mulesoft/pdk-custom-policy-examples) using the following command or your preferred GitHub interface: ```ssh git clone https://github.com/mulesoft/pdk-custom-policy-examples.git ``` 3. Navigate to the newly cloned directory, then copy and paste the directory of your desired policy into a new location. 4. In the `cargo.toml` file of the copied policy example, replace the `group-id` with your group ID, for example: ```toml group_id = "" ``` 5. Run the `make setup` command: ```ssh make setup ``` 6. Navigate to the `README.md` file in the example policy to read more about the policy and how to test it. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Custom Policy Examples > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) provides example policy projects to help you start configuring your Rust source code. You can find all example policies and their documentation in the [PDK Custom Policy GitHub Repository](https://github.com/mulesoft/pdk-custom-policy-examples). ## API Policy Examples PDK includes the following API example policies: - [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/block/README.md): Use the Block Policy as an example of how to block IP ranges by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-timer) and [HTTP calls](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-http-request). - [Certification Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/certs/README.md): Use the Certification Policy as an example of how to obtain data concerning connection certificates. - [CORS Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/cors-validation/README.md): Use the CORS Validation Policy as an example of how to use functions of the [CORS Library](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-cors) in your custom policy. - [Crypto Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/crypto/README.md): Use the Crypto Policy as an example of how to use [third-party libraries](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-libraries) that provide cryptography capabilities in your custom policy. - [Data Caching Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/data-caching/README.md): Use the Data Caching Policy as an example of how to implement [data caching](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-caching) in your custom policy. - [Data Storage Stats Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/data-storage-stats/README.md): Use the Data Storage Stats Policy as an example of how to implement [data storage](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-data-storage) with both local (in-memory) and shared (Redis) data storage. - [DataWeave Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/dataweave/README.md): Use the DataWeave Policy as an example of how to handle [custom DataWeave expressions](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-dataweave) in your custom policy. - [IP Filter Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/ip-filter/README.md): Use the IP Filter Policy as an example of how to extract client IPs from request headers and implement IP-based access control using PDK’s [IP Filter feature](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-ip-filter). - [JSON Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/json-validation/README.md): Use the JSON Validation Policy as an example of how to enforce JSON payload limits with the [JSON Validator library](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-json-validator). - [JWT Generation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/jwt-generation/README.md): Use the JWT Generation Policy as an example of how to generate JWT tokens using the [JWT generation function](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-jwt#create-jwt-token). - [JWT Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/jwt-validation/README.md): Use the JWT Validation Policy as an example of how to use functions of the [JWT Library](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-jwt) in your custom policy. - [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/metrics/README.md): Use the Metrics Policy as an example of how to periodically send data to a metric ingestion service by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-timer) and [HTTP calls](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-http-request). - [OAuth 2.0 Token Introspection Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/oauth-2-token-introspection/README.md): Use the OAuth 2.0 Token Introspection Policy as an example of how to use [Token Introspection](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-token-introspection) in your custom policy. - [Query Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/query/README.md): Use the Query Policy as an example of how to handle query parameters in your custom policy. - [Simple OAuth 2.0 Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/simple-oauth-2-validation/README.md): Use the Simple OAuth 2.0 Validation Policy as an example of how to implement [HTTP calls](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-http-request) in your custom policy. - [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/spike/README.md): Use the Spike Policy as an example of how to implement spike arrest with the [Spike Control library](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-spike-control) and periodic ticking with [Timer functions](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-timer). - [Stream Payload Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/stream-payload/README.md): Use the Stream Payload Policy as an example of how to [read payload bodies larger than 1MB](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-headers#streaming-bodies). - [TLS Calls Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/tls-calls/README.md): Use the TLS Calls Policy as an example of how to make HTTPS calls in your policy without installing certificates on the operating system running Omni Gateway. - [XML Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/xml-validation/README.md): Use the XML Validation Policy as an example of how to enforce XML payload limits with the [XML Validator library](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-xml-validator). ## A2A and MCP Server Policy Examples PDK includes the following A2A and MCP example policies: - [A2A PII Detector Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-pii-detector-policy/README.md): Demonstrates how to log or block sensitive information in A2A agent interactions. - [A2A Prompt Decorator Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-prompt-decorator-policy/README.md): Shows how to modify prompts sent to an A2A agent. - [A2A Support Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-support-policy/README.md): Demonstrates how to add A2A support. - [MCP Support Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/mcp-support-policy/README.md): Shows how to add MCP support. ## Set Up an Example Policy Project To use an example policy project: 1. Make sure you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/1.8/policies-pdk-prerequisites). 2. Clone the [PDK Custom Policy GitHub Repository](https://github.com/mulesoft/pdk-custom-policy-examples) using the following command or your preferred GitHub interface: ```ssh git clone https://github.com/mulesoft/pdk-custom-policy-examples.git ``` 3. Navigate to the newly cloned directory, then copy and paste the directory of your desired policy into a new location. 4. In the `cargo.toml` file of the copied policy example, replace the `group-id` with your group ID, for example: ```toml group_id = "" ``` 5. Run the `make setup` command: ```ssh make setup ``` 6. Navigate to the `README.md` file in the example policy to read more about the policy and how to test it. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Custom Policy Examples > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) provides example policy projects to help you start configuring your Rust source code. You can find all example policies and their documentation in the [PDK Custom Policy GitHub Repository](https://github.com/mulesoft/pdk-custom-policy-examples). ## API Policy Examples PDK includes the following API example policies: - [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/block/README.md): Use the Block Policy as an example of how to block IP ranges by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-timer) and [HTTP calls](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-http-request). - [Certification Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/certs/README.md): Use the Certification Policy as an example of how to obtain data concerning connection certificates. - [CORS Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/cors-validation/README.md): Use the CORS Validation Policy as an example of how to use functions of the [CORS Library](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-cors) in your custom policy. - [Crypto Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/crypto/README.md): Use the Crypto Policy as an example of how to use [third-party libraries](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-libraries) that provide cryptography capabilities in your custom policy. - [Data Caching Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/data-caching/README.md): Use the Data Caching Policy as an example of how to implement [data caching](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-caching) in your custom policy. - [Data Storage Stats Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/data-storage-stats/README.md): Use the Data Storage Stats Policy as an example of how to implement [data storage](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-data-storage) with both local (in-memory) and shared (Redis) data storage. - [DataWeave Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/dataweave/README.md): Use the DataWeave Policy as an example of how to handle [custom DataWeave expressions](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-dataweave) in your custom policy. - [IP Filter Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/ip-filter/README.md): Use the IP Filter Policy as an example of how to extract client IPs from request headers and implement IP-based access control using PDK’s [IP Filter feature](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-ip-filter). - [JSON Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/json-validation/README.md): Use the JSON Validation Policy as an example of how to enforce JSON payload limits with the [JSON Validator library](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-json-validator). - [JWT Generation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/jwt-generation/README.md): Use the JWT Generation Policy as an example of how to generate JWT tokens using the [JWT generation function](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-jwt#create-jwt-token). - [JWT Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/jwt-validation/README.md): Use the JWT Validation Policy as an example of how to use functions of the [JWT Library](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-jwt) in your custom policy. - [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/metrics/README.md): Use the Metrics Policy as an example of how to periodically send data to a metric ingestion service by implementing [periodic functions](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-timer) and [HTTP calls](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-http-request). - [OAuth 2.0 Token Introspection Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/oauth-2-token-introspection/README.md): Use the OAuth 2.0 Token Introspection Policy as an example of how to use [Token Introspection](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-token-introspection) in your custom policy. - [Query Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/query/README.md): Use the Query Policy as an example of how to handle query parameters in your custom policy. - [Simple OAuth 2.0 Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/simple-oauth-2-validation/README.md): Use the Simple OAuth 2.0 Validation Policy as an example of how to implement [HTTP calls](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-http-request) in your custom policy. - [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/spike/README.md): Use the Spike Policy as an example of how to implement spike arrest with the [Spike Control library](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-spike-control) and periodic ticking with [Timer functions](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-timer). - [Stream Payload Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/stream-payload/README.md): Use the Stream Payload Policy as an example of how to [read payload bodies larger than 1MB](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-headers#streaming-bodies). - [TLS Calls Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/tls-calls/README.md): Use the TLS Calls Policy as an example of how to make HTTPS calls in your policy without installing certificates on the operating system running Omni Gateway. - [WebSocket Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/websocket/README.md): Use the WebSocket Policy as an example of how to [support WebSocket APIs](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-websocket) and process bidirectional frames in your custom policy. - [XML Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/xml-validation/README.md): Use the XML Validation Policy as an example of how to enforce XML payload limits with the [XML Validator library](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-xml-validator). ## A2A and MCP Server Policy Examples PDK includes the following A2A and MCP example policies: - [A2A PII Detector Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-pii-detector-policy/README.md): Demonstrates how to log or block sensitive information in A2A agent interactions. - [A2A Prompt Decorator Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-prompt-decorator-policy/README.md): Shows how to modify prompts sent to an A2A agent. - [A2A Support Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-support-policy/README.md): Demonstrates how to add A2A support. - [MCP Support Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/mcp-support-policy/README.md): Shows how to add MCP support. ## Set Up an Example Policy Project To use an example policy project: 1. Make sure you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/1.9/policies-pdk-prerequisites). 2. Clone the [PDK Custom Policy GitHub Repository](https://github.com/mulesoft/pdk-custom-policy-examples) using the following command or your preferred GitHub interface: ```ssh git clone https://github.com/mulesoft/pdk-custom-policy-examples.git ``` 3. Navigate to the newly cloned directory, then copy and paste the directory of your desired policy into a new location. 4. In the `cargo.toml` file of the copied policy example, replace the `group-id` with your group ID, for example: ```toml group_id = "" ``` 5. Run the `make setup` command: ```ssh make setup ``` 6. Navigate to the `README.md` file in the example policy to read more about the policy and how to test it. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Custom Policy Examples > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) provides example policy projects to help you start configuring your Rust source code. You can find all example policies and their documentation in the [PDK Custom Policy GitHub Repository](https://github.com/mulesoft/pdk-custom-policy-examples). ## API Policy Examples PDK includes the following API example policies: - [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/block/README.md): Use the Block Policy as an example of how to block IP ranges by implementing [periodic functions](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-timer) and [HTTP calls](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-http-request). - [Certification Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/certs/README.md): Use the Certification Policy as an example of how to obtain data concerning connection certificates. - [CORS Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/cors-validation/README.md): Use the CORS Validation Policy as an example of how to use functions of the [CORS Library](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-cors) in your custom policy. - [Crypto Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/crypto/README.md): Use the Crypto Policy as an example of how to use [third-party libraries](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-libraries) that provide cryptography capabilities in your custom policy. - [Data Caching Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/data-caching/README.md): Use the Data Caching Policy as an example of how to implement [data caching](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-caching) in your custom policy. - [Data Storage Stats Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/data-storage-stats/README.md): Use the Data Storage Stats Policy as an example of how to implement [data storage](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-data-storage) with both local (in-memory) and shared (Redis) data storage. - [DataWeave Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/dataweave/README.md): Use the DataWeave Policy as an example of how to handle [custom DataWeave expressions](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-dataweave) in your custom policy. - [IP Filter Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/ip-filter/README.md): Use the IP Filter Policy as an example of how to extract client IPs from request headers and implement IP-based access control using PDK’s [IP Filter feature](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-ip-filter). - [JSON Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/json-validation/README.md): Use the JSON Validation Policy as an example of how to enforce JSON payload limits with the [JSON Validator library](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-json-validator). - [JWT Generation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/jwt-generation/README.md): Use the JWT Generation Policy as an example of how to generate JWT tokens using the [JWT generation function](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-jwt#create-jwt-token). - [JWT Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/jwt-validation/README.md): Use the JWT Validation Policy as an example of how to use functions of the [JWT Library](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-jwt) in your custom policy. - [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/metrics/README.md): Use the Metrics Policy as an example of how to periodically send data to a metric ingestion service by implementing [periodic functions](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-timer) and [HTTP calls](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-http-request). - [OAuth 2.0 Token Introspection Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/oauth-2-token-introspection/README.md): Use the OAuth 2.0 Token Introspection Policy as an example of how to use [Token Introspection](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-token-introspection) in your custom policy. - [Query Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/query/README.md): Use the Query Policy as an example of how to handle query parameters in your custom policy. - [Simple OAuth 2.0 Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/simple-oauth-2-validation/README.md): Use the Simple OAuth 2.0 Validation Policy as an example of how to implement [HTTP calls](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-http-request) in your custom policy. - [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/spike/README.md): Use the Spike Policy as an example of how to implement spike arrest with the [Spike Control library](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-spike-control) and periodic ticking with [Timer functions](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-timer). - [Stream Payload Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/stream-payload/README.md): Use the Stream Payload Policy as an example of how to [read payload bodies larger than 1MB](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-headers#streaming-bodies). - [TLS Calls Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/tls-calls/README.md): Use the TLS Calls Policy as an example of how to make HTTPS calls in your policy without installing certificates on the operating system running Omni Gateway. - [WebSocket Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/websocket/README.md): Use the WebSocket Policy as an example of how to [support WebSocket APIs](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-websocket) and process bidirectional frames in your custom policy. - [XML Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/xml-validation/README.md): Use the XML Validation Policy as an example of how to enforce XML payload limits with the [XML Validator library](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-xml-validator). ## A2A and MCP Server Policy Examples PDK includes the following A2A and MCP example policies: - [A2A PII Detector Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-pii-detector-policy/README.md): Demonstrates how to log or block sensitive information in A2A agent interactions. - [A2A Prompt Decorator Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-prompt-decorator-policy/README.md): Shows how to modify prompts sent to an A2A agent. - [A2A Support Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/a2a-support-policy/README.md): Demonstrates how to add A2A support. - [MCP Support Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/main/agent-policies/mcp-support-policy/README.md): Shows how to add MCP support. ## Set Up an Example Policy Project To use an example policy project: 1. Make sure you have installed all [PDK prerequisites](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites). 2. Clone the [PDK Custom Policy GitHub Repository](https://github.com/mulesoft/pdk-custom-policy-examples) using the following command or your preferred GitHub interface: ```ssh git clone https://github.com/mulesoft/pdk-custom-policy-examples.git ``` 3. Navigate to the newly cloned directory, then copy and paste the directory of your desired policy into a new location. 4. In the `cargo.toml` file of the copied policy example, replace the `group-id` with your group ID, for example: ```toml group_id = "" ``` 5. Run the `make setup` command: ```ssh make setup ``` 6. Navigate to the `README.md` file in the example policy to read more about the policy and how to test it. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Debugging Custom Policies with the PDK Debugging Playground > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To test the functionality of your policy, Flex Gateway Policy Development Kit (PDK) provides a pre-configured API instance located in the `/playground/config` directory. The PDK Debugging Playground only supports Flex Gateway running in Local Mode in a Docker container. If you plan to deploy or policy to Flex Gateway running in Connected Mode or to a different platform, you should still first test your policy in PDK by using Flex Gateway running in Local Mode in a Docker container. > [!IMPORTANT] You can run Flex Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Flex Gateway does not support Windows in production environments. To test your policy, complete the following tasks: 1. [Before You Begin](#before-you-begin) 2. [Register a Flex Gateway Instance in Local Mode](#register) 3. [Configure the Policy](#configure-the-policy) 4. [Add Additional Policies](#add-additional-policies) if necessary 5. [Deploy the Policy with PDK](#deploy-the-policy-with-pdk) ## Before You Begin Ensure that you have: - [Installed Docker](https://www.docker.com/). - [Compiled your custom policy project](https://docs.mulesoft.com/pdk/1.2/policies-pdk-compile-policies). ## Register a Flex Gateway Instance in Local Mode To begin using the `make run` command to debug your custom policy, register a Flex Gateway in Local Mode. For the `run` command to work, a Flex Gateway `registration.yaml` file must exist in the `/playground/config` directory. Create this file by running the registration command in the directory, or move a `registration.yaml` file of a previously registered Flex Gateway to the directory. The `make run` command only supports Flex Gateways running in Local Mode in a Docker Container. To register Flex Gateway, see: - [Register and Run with a Username and Password in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-up#docker) - [Register and Run with a Connected App in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-app#docker) - [Register and Run with a Token in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-token#docker) > [!IMPORTANT] Run only the registration command. Do not run the Docker start command because the > `make run` command completes this step. Create a different registration file on each device testing the policy. The registration file is ignored for storage in remote repositories and is listed in the `.gitignore` file located at the root of the project directory. ## Configure the Policy Depending on the configurations listed in the `definition/gcl.yaml` file you configured in [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.2/policies-pdk-create-schema-definition), you may have to configure some parameters before running the policy locally. For example, if the `gcl.yaml` file is as follows: ```yaml apiVersion: gateway.mulesoft.com.v1alpha1 kind: Extension metadata: labels: title: my-custom-policy category: Security spec: extends: - name: extension-definition properties: user: type: string default: user1 password: type: string description: type: string required: - user - password ``` Update the `/playground/config/api.yaml` file with your configuration value: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: ApiInstance metadata: name: ingress-http spec: address: http://0.0.0.0:8081 services: upstream: address: http://backend routes: - config: destinationPath: /anything/echo/ policies: - policyRef: name: my-custom-policy config: password: 12345678 ``` In this example, the `user` is set to the default value `user1`, the `password` is set to `12345678`, and no description is provided. ## Add Additional Policies You can also apply additional policies to the test API instance to test your custom policies behavior alongside other policies. However, your custom policy under development must be the first policy specified, for example: ```yaml policies: - policyRef: name: my-custom-policy config: password: 12345678 - policyRef: name: additional-policy config: ``` ## Deploy the Policy with PDK After you complete the previous steps, run the `make run` command from the policy’s root directory to deploy policy: ```cmd make run ``` This command starts the two Docker containers in the `/playground/docker-compose.yaml` file: - `Local-flex`: The Flex Gateway instance Docker container that executes the custom policy. This Flex Gateway listens for requests made to `localhost:8081`. - `Backend`: The Docker Container that runs the backend service for the Flex Gateway instance. This backend service echoes any request it receives. > [!NOTE] To stop the Docker containers, press `Cmd+c` or `Ctrl+c` depending on your device from the > terminal running the containers. Once the containers are running, you can make requests to the API instance, for example: ```cmd curl --location --request POST 'http://0.0.0.0:8081/some/route' \ --header 'Token: mytoken' ``` The backend service returns an echo response including the requests’s route, body, and headers sent with any modification performed by the custom policy or additional policies. Any logs included in the custom policy’s source code are visible in the terminal running the containers. ## Configure the Loglevel By default, PDK’s debugging environment enables logs with the `debug` `loglevel` configured. To change the `loglevel`, edit the `logging.runtimeLogs.logLevel` value in `/playground/config/logging.yaml`. To learn more about editing a Flex Gateway’s logging configuration file, see [Configuring External Logs for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-third-party-logs-config). ## Use the Rust Debugger Visual Studio Code (VS Code) includes a Rust debugger that can run unit tests. You cannot use the VS Code Debugger while the policy is deployed on a Flex Gateway. To create the API mocking, you must use unit tests for the specific logic you need to debug. To debug Rust code in VS Code, you must install the [CodeLLDB Debugger Extension](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) or a different VS Code extension with the same functionality. To learn more about debugging Rust in VS Code, see [Rust in Visual Studio Code](https://code.visualstudio.com/docs/languages/rust#_debugging). ## See Also - [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.2/policies-pdk-integration-tests) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.2/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Debugging Custom Policies with the PDK Debugging Playground > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To test the functionality of your policy, Flex Gateway Policy Development Kit (PDK) provides a pre-configured API instance located in the `/playground/config` directory. The PDK Debugging Playground only supports Flex Gateway running in Local Mode in a Docker container. If you plan to deploy or policy to Flex Gateway running in Connected Mode or to a different platform, you should still first test your policy in PDK by using Flex Gateway running in Local Mode in a Docker container. > [!IMPORTANT] You can run Flex Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Flex Gateway does not support Windows in production environments. To test your policy, complete the following tasks: 1. [Before You Begin](#before-you-begin) 2. [Register a Flex Gateway Instance in Local Mode](#register) 3. [Configure the Policy](#configure-the-policy) 4. [Add Additional Policies](#add-additional-policies) if necessary 5. [Deploy the Policy with PDK](#deploy-the-policy-with-pdk) ## Before You Begin Ensure that you have: - [Installed Docker](https://www.docker.com/). - [Compiled your custom policy project](https://docs.mulesoft.com/pdk/1.3/policies-pdk-compile-policies). ## Register a Flex Gateway Instance in Local Mode To begin using the `make run` command to debug your custom policy, register a Flex Gateway in Local Mode. For the `run` command to work, a Flex Gateway `registration.yaml` file must exist in the `/playground/config` directory. Create this file by running the registration command in the directory, or move a `registration.yaml` file of a previously registered Flex Gateway to the directory. The `make run` command only supports Flex Gateways running in Local Mode in a Docker Container. To register Flex Gateway, see: - [Register and Run with a Username and Password in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-up#docker) - [Register and Run with a Connected App in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-app#docker) - [Register and Run with a Token in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-token#docker) > [!IMPORTANT] Run only the registration command. Do not run the Docker start command because the > `make run` command completes this step. Create a different registration file on each device testing the policy. The registration file is ignored for storage in remote repositories and is listed in the `.gitignore` file located at the root of the project directory. ## Configure the Policy Depending on the configurations listed in the `definition/gcl.yaml` file you configured in [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.3/policies-pdk-create-schema-definition), you may have to configure some parameters before running the policy locally. For example, if the `gcl.yaml` file is as follows: ```yaml apiVersion: gateway.mulesoft.com.v1alpha1 kind: Extension metadata: labels: title: my-custom-policy category: Security spec: extends: - name: extension-definition properties: user: type: string default: user1 password: type: string description: type: string required: - user - password ``` Update the `/playground/config/api.yaml` file with your configuration value: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: ApiInstance metadata: name: ingress-http spec: address: http://0.0.0.0:8081 services: upstream: address: http://backend routes: - config: destinationPath: /anything/echo/ policies: - policyRef: name: my-custom-policy config: password: 12345678 ``` In this example, the `user` is set to the default value `user1`, the `password` is set to `12345678`, and no description is provided. ## Add Additional Policies You can also apply additional policies to the test API instance to test your custom policies behavior alongside other policies. However, your custom policy under development must be the first policy specified, for example: ```yaml policies: - policyRef: name: my-custom-policy config: password: 12345678 - policyRef: name: additional-policy config: ``` ## Deploy the Policy with PDK After you complete the previous steps, run the `make run` command from the policy’s root directory to deploy policy: ```cmd make run ``` This command starts the two Docker containers in the `/playground/docker-compose.yaml` file: - `Local-flex`: The Flex Gateway instance Docker container that executes the custom policy. This Flex Gateway listens for requests made to `localhost:8081`. - `Backend`: The Docker Container that runs the backend service for the Flex Gateway instance. This backend service echoes any request it receives. > [!NOTE] To stop the Docker containers, press `Cmd+c` or `Ctrl+c` depending on your device from the > terminal running the containers. Once the containers are running, you can make requests to the API instance, for example: ```cmd curl --location --request POST 'http://0.0.0.0:8081/some/route' \ --header 'Token: mytoken' ``` The backend service returns an echo response including the requests’s route, body, and headers sent with any modification performed by the custom policy or additional policies. Any logs included in the custom policy’s source code are visible in the terminal running the containers. ## Configure the Loglevel By default, PDK’s debugging environment enables logs with the `debug` `loglevel` configured. To change the `loglevel`, edit the `logging.runtimeLogs.logLevel` value in `/playground/config/logging.yaml`. To learn more about editing a Flex Gateway’s logging configuration file, see [Configuring External Logs for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-third-party-logs-config). ## Use the Rust Debugger Visual Studio Code (VS Code) includes a Rust debugger that can run unit tests. You cannot use the VS Code Debugger while the policy is deployed on a Flex Gateway. To create the API mocking, you must use unit tests for the specific logic you need to debug. To debug Rust code in VS Code, you must install the [CodeLLDB Debugger Extension](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) or a different VS Code extension with the same functionality. To learn more about debugging Rust in VS Code, see [Rust in Visual Studio Code](https://code.visualstudio.com/docs/languages/rust#_debugging). ## See Also - [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.3/policies-pdk-integration-tests) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.3/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Debugging Custom Policies with the PDK Debugging Playground > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To test the functionality of your policy, Flex Gateway Policy Development Kit (PDK) provides a pre-configured API instance located in the `/playground/config` directory. The PDK Debugging Playground only supports Flex Gateway running in Local Mode in a Docker container. If you plan to deploy or policy to Flex Gateway running in Connected Mode or to a different platform, you should still first test your policy in PDK by using Flex Gateway running in Local Mode in a Docker container. > [!IMPORTANT] You can run Flex Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Flex Gateway does not support Windows in production environments. To test your policy, complete the following tasks: 1. [Before You Begin](#before-you-begin) 2. [Register a Flex Gateway Instance in Local Mode](#register) 3. [Configure the Policy](#configure-the-policy) 4. [Add Additional Policies](#add-additional-policies) if necessary 5. [Deploy the Policy with PDK](#deploy-the-policy-with-pdk) ## Before You Begin Ensure that you have: - [Installed Docker](https://www.docker.com/). - [Compiled your custom policy project](https://docs.mulesoft.com/pdk/1.4/policies-pdk-compile-policies). ## Register a Flex Gateway Instance in Local Mode To begin using the `make run` command to debug your custom policy, register a Flex Gateway in Local Mode. For the `run` command to work, a Flex Gateway `registration.yaml` file must exist in the `/playground/config` directory. Create this file by running the registration command in the directory, or move a `registration.yaml` file of a previously registered Flex Gateway to the directory. The `make run` command only supports Flex Gateways running in Local Mode in a Docker Container. To register Flex Gateway, see: - [Register and Run with a Username and Password in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-up#docker) - [Register and Run with a Connected App in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-app#docker) - [Register and Run with a Token in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-token#docker) > [!IMPORTANT] Run only the registration command. Do not run the Docker start command because the > `make run` command completes this step. Create a different registration file on each device testing the policy. The registration file is ignored for storage in remote repositories and is listed in the `.gitignore` file located at the root of the project directory. ## Configure the Policy Depending on the configurations listed in the `definition/gcl.yaml` file you configured in [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.4/policies-pdk-create-schema-definition), you may have to configure some parameters before running the policy locally. For example, if the `gcl.yaml` file is as follows: ```yaml apiVersion: gateway.mulesoft.com.v1alpha1 kind: Extension metadata: labels: title: my-custom-policy category: Security spec: extends: - name: extension-definition properties: user: type: string default: user1 password: type: string description: type: string required: - user - password ``` Update the `/playground/config/api.yaml` file with your configuration value: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: ApiInstance metadata: name: ingress-http spec: address: http://0.0.0.0:8081 services: upstream: address: http://backend routes: - config: destinationPath: /anything/echo/ policies: - policyRef: name: my-custom-policy config: password: 12345678 ``` In this example, the `user` is set to the default value `user1`, the `password` is set to `12345678`, and no description is provided. ## Add Additional Policies You can also apply additional policies to the test API instance to test your custom policies behavior alongside other policies. However, your custom policy under development must be the first policy specified, for example: ```yaml policies: - policyRef: name: my-custom-policy config: password: 12345678 - policyRef: name: additional-policy config: ``` ## Deploy the Policy with PDK After you complete the previous steps, run the `make run` command from the policy’s root directory to deploy policy: ```cmd make run ``` This command starts the two Docker containers in the `/playground/docker-compose.yaml` file: - `Local-flex`: The Flex Gateway instance Docker container that executes the custom policy. This Flex Gateway listens for requests made to `localhost:8081`. - `Backend`: The Docker Container that runs the backend service for the Flex Gateway instance. This backend service echoes any request it receives. > [!NOTE] To stop the Docker containers, press `Cmd+c` or `Ctrl+c` depending on your device from the > terminal running the containers. Once the containers are running, you can make requests to the API instance, for example: ```cmd curl --location --request POST 'http://0.0.0.0:8081/some/route' \ --header 'Token: mytoken' ``` The backend service returns an echo response including the requests’s route, body, and headers sent with any modification performed by the custom policy or additional policies. Any logs included in the custom policy’s source code are visible in the terminal running the containers. ## Configure the Loglevel By default, PDK’s debugging environment enables logs with the `debug` `loglevel` configured. To change the `loglevel`, edit the `logging.runtimeLogs.logLevel` value in `/playground/config/logging.yaml`. To learn more about editing a Flex Gateway’s logging configuration file, see [Configuring External Logs for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-third-party-logs-config). ## Use the Rust Debugger Visual Studio Code (VS Code) includes a Rust debugger that can run unit tests. You cannot use the VS Code Debugger while the policy is deployed on a Flex Gateway. To create the API mocking, you must use unit tests for the specific logic you need to debug. To debug Rust code in VS Code, you must install the [CodeLLDB Debugger Extension](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) or a different VS Code extension with the same functionality. To learn more about debugging Rust in VS Code, see [Rust in Visual Studio Code](https://code.visualstudio.com/docs/languages/rust#_debugging). ## See Also - [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.4/policies-pdk-integration-tests) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.4/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Debugging Custom Policies with the PDK Debugging Playground > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To test the functionality of your policy, Flex Gateway Policy Development Kit (PDK) provides a pre-configured API instance located in the `/playground/config` directory. The PDK Debugging Playground only supports Flex Gateway running in Local Mode in a Docker container. If you plan to deploy or policy to Flex Gateway running in Connected Mode or to a different platform, you should still first test your policy in PDK by using Flex Gateway running in Local Mode in a Docker container. > [!IMPORTANT] You can run Flex Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Flex Gateway does not support Windows in production environments. To test your policy, complete the following tasks: 1. [Before You Begin](#before-you-begin) 2. [Register a Flex Gateway Instance in Local Mode](#register) 3. [Configure the Policy](#configure-the-policy) 4. [Add Additional Policies](#add-additional-policies) if necessary 5. [Deploy the Policy with PDK](#deploy-the-policy-with-pdk) ## Before You Begin Ensure that you have: - [Installed Docker](https://www.docker.com/). - [Compiled your custom policy project](https://docs.mulesoft.com/pdk/1.5/policies-pdk-compile-policies). ## Register a Flex Gateway Instance in Local Mode To begin using the `make run` command to debug your custom policy, register a Flex Gateway in Local Mode. For the `run` command to work, a Flex Gateway `registration.yaml` file must exist in the `/playground/config` directory. Create this file by running the registration command in the directory, or move a `registration.yaml` file of a previously registered Flex Gateway to the directory. The `make run` command only supports Flex Gateways running in Local Mode in a Docker Container. To register Flex Gateway, see: - [Register and Run with a Username and Password in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-up#docker) - [Register and Run with a Connected App in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-app#docker) - [Register and Run with a Token in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-token#docker) > [!IMPORTANT] Run only the registration command. Do not run the Docker start command because the > `make run` command completes this step. Create a different registration file on each device testing the policy. The registration file is ignored for storage in remote repositories and is listed in the `.gitignore` file located at the root of the project directory. ## Configure the Policy Depending on the configurations listed in the `definition/gcl.yaml` file you configured in [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.5/policies-pdk-create-schema-definition), you may have to configure some parameters before running the policy locally. For example, if the `gcl.yaml` file is as follows: ```yaml apiVersion: gateway.mulesoft.com.v1alpha1 kind: Extension metadata: labels: title: my-custom-policy category: Security spec: extends: - name: extension-definition properties: user: type: string default: user1 password: type: string description: type: string required: - user - password ``` Update the `/playground/config/api.yaml` file with your configuration value: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: ApiInstance metadata: name: ingress-http spec: address: http://0.0.0.0:8081 services: upstream: address: http://backend routes: - config: destinationPath: /anything/echo/ policies: - policyRef: name: my-custom-policy config: password: 12345678 ``` In this example, the `user` is set to the default value `user1`, the `password` is set to `12345678`, and no description is provided. ## Add Additional Policies You can also apply additional policies to the test API instance to test your custom policies behavior alongside other policies. However, your custom policy under development must be the first policy specified, for example: ```yaml policies: - policyRef: name: my-custom-policy config: password: 12345678 - policyRef: name: additional-policy config: ``` ## Deploy the Policy with PDK After you complete the previous steps, run the `make run` command from the policy’s root directory to deploy policy: ```cmd make run ``` This command starts the two Docker containers in the `/playground/docker-compose.yaml` file: - `Local-flex`: The Flex Gateway instance Docker container that executes the custom policy. This Flex Gateway listens for requests made to `localhost:8081`. - `Backend`: The Docker Container that runs the backend service for the Flex Gateway instance. This backend service echoes any request it receives. > [!NOTE] To stop the Docker containers, press `Cmd+c` or `Ctrl+c` depending on your device from the > terminal running the containers. Once the containers are running, you can make requests to the API instance, for example: ```cmd curl --location --request POST 'http://0.0.0.0:8081/some/route' \ --header 'Token: mytoken' ``` The backend service returns an echo response including the requests’s route, body, and headers sent with any modification performed by the custom policy or additional policies. Any logs included in the custom policy’s source code are visible in the terminal running the containers. ## Configure the Loglevel By default, PDK’s debugging environment enables logs with the `debug` `loglevel` configured. To change the `loglevel`, edit the `logging.runtimeLogs.logLevel` value in `/playground/config/logging.yaml`. To learn more about editing a Flex Gateway’s logging configuration file, see [Configuring External Logs for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-third-party-logs-config). ## Use the Rust Debugger Visual Studio Code (VS Code) includes a Rust debugger that can run unit tests. You cannot use the VS Code Debugger while the policy is deployed on a Flex Gateway. To create the API mocking, you must use unit tests for the specific logic you need to debug. To debug Rust code in VS Code, you must install the [CodeLLDB Debugger Extension](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) or a different VS Code extension with the same functionality. To learn more about debugging Rust in VS Code, see [Rust in Visual Studio Code](https://code.visualstudio.com/docs/languages/rust#_debugging). ## See Also - [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.5/policies-pdk-integration-tests) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.5/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Debugging Custom Policies with the PDK Debugging Playground > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To test the functionality of your policy, Flex Gateway Policy Development Kit (PDK) provides a pre-configured API instance located in the `/playground/config` directory. The PDK Debugging Playground only supports Flex Gateway running in Local Mode in a Docker container. If you plan to deploy or policy to Flex Gateway running in Connected Mode or to a different platform, you should still first test your policy in PDK by using Flex Gateway running in Local Mode in a Docker container. > [!IMPORTANT] You can run Flex Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Flex Gateway does not support Windows in production environments. To test your policy, complete the following tasks: 1. [Before You Begin](#before-you-begin) 2. [Register a Flex Gateway Instance in Local Mode](#register) 3. [Configure the Policy](#configure-the-policy) 4. [Add Additional Policies](#add-additional-policies) if necessary 5. [Deploy the Policy with PDK](#deploy-the-policy-with-pdk) ## Before You Begin Ensure that you have: - [Installed Docker](https://www.docker.com/). - [Compiled your custom policy project](https://docs.mulesoft.com/pdk/1.6/policies-pdk-compile-policies). ## Register a Flex Gateway Instance in Local Mode To begin using the `make run` command to debug your custom policy, register a Flex Gateway in Local Mode. For the `run` command to work, a Flex Gateway `registration.yaml` file must exist in the `/playground/config` directory. Create this file by running the registration command in the directory, or move a `registration.yaml` file of a previously registered Flex Gateway to the directory. The `make run` command only supports Flex Gateways running in Local Mode in a Docker Container. To register Flex Gateway, see: - [Register and Run with a Username and Password in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-up#docker) - [Register and Run with a Connected App in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-app#docker) - [Register and Run with a Token in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-token#docker) > [!IMPORTANT] Run only the registration command. Do not run the Docker start command because the > `make run` command completes this step. Create a different registration file on each device testing the policy. The registration file is ignored for storage in remote repositories and is listed in the `.gitignore` file located at the root of the project directory. ## Configure the Policy Depending on the configurations listed in the `definition/gcl.yaml` file you configured in [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.6/policies-pdk-create-schema-definition), you may have to configure some parameters before running the policy locally. For example, if the `gcl.yaml` file is as follows: ```yaml apiVersion: gateway.mulesoft.com.v1alpha1 kind: Extension metadata: labels: title: my-custom-policy category: Security spec: extends: - name: extension-definition properties: user: type: string default: user1 password: type: string description: type: string required: - user - password ``` Update the `/playground/config/api.yaml` file with your configuration value: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: ApiInstance metadata: name: ingress-http spec: address: http://0.0.0.0:8081 services: upstream: address: http://backend routes: - config: destinationPath: /anything/echo/ policies: - policyRef: name: my-custom-policy config: password: 12345678 ``` In this example, the `user` is set to the default value `user1`, the `password` is set to `12345678`, and no description is provided. ## Add Additional Policies You can also apply additional policies to the test API instance to test your custom policies behavior alongside other policies. However, your custom policy under development must be the first policy specified, for example: ```yaml policies: - policyRef: name: my-custom-policy config: password: 12345678 - policyRef: name: additional-policy config: ``` ## Deploy the Policy with PDK After you complete the previous steps, run the `make run` command from the policy’s root directory to deploy policy: ```cmd make run ``` This command starts the two Docker containers in the `/playground/docker-compose.yaml` file: - `Local-flex`: The Flex Gateway instance Docker container that executes the custom policy. This Flex Gateway listens for requests made to `localhost:8081`. - `Backend`: The Docker Container that runs the backend service for the Flex Gateway instance. This backend service echoes any request it receives. > [!NOTE] To stop the Docker containers, press `Cmd+c` or `Ctrl+c` depending on your device from the > terminal running the containers. Once the containers are running, you can make requests to the API instance, for example: ```cmd curl --location --request POST 'http://0.0.0.0:8081/some/route' \ --header 'Token: mytoken' ``` The backend service returns an echo response including the requests’s route, body, and headers sent with any modification performed by the custom policy or additional policies. Any logs included in the custom policy’s source code are visible in the terminal running the containers. ## Configure the Loglevel By default, PDK’s debugging environment enables logs with the `debug` `loglevel` configured. To change the `loglevel`, edit the `logging.runtimeLogs.logLevel` value in `/playground/config/logging.yaml`. To learn more about editing a Flex Gateway’s logging configuration file, see [Configuring External Logs for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-third-party-logs-config). ## Use the Rust Debugger Visual Studio Code (VS Code) includes a Rust debugger that can run unit tests. You cannot use the VS Code Debugger while the policy is deployed on a Flex Gateway. To create the API mocking, you must use unit tests for the specific logic you need to debug. To debug Rust code in VS Code, you must install the [CodeLLDB Debugger Extension](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) or a different VS Code extension with the same functionality. To learn more about debugging Rust in VS Code, see [Rust in Visual Studio Code](https://code.visualstudio.com/docs/languages/rust#_debugging). ## See Also - [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.6/policies-pdk-integration-tests) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.6/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Debugging Custom Policies with the PDK Debugging Playground > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To test the functionality of your policy, Flex Gateway Policy Development Kit (PDK) provides a pre-configured API instance located in the `/playground/config` directory. The PDK Debugging Playground only supports Flex Gateway running in Local Mode in a Docker container. If you plan to deploy or policy to Flex Gateway running in Connected Mode or to a different platform, you should still first test your policy in PDK by using Flex Gateway running in Local Mode in a Docker container. > [!IMPORTANT] You can run Flex Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Flex Gateway does not support Windows in production environments. To test your policy, complete the following tasks: 1. [Before You Begin](#before-you-begin) 2. [Register a Flex Gateway Instance in Local Mode](#register) 3. [Configure the Policy](#configure-the-policy) 4. [Add Additional Policies](#add-additional-policies) if necessary 5. [Deploy the Policy with PDK](#deploy-the-policy-with-pdk) ## Before You Begin Ensure that you have: - [Installed Docker](https://www.docker.com/). - [Compiled your custom policy project](https://docs.mulesoft.com/pdk/1.7/policies-pdk-compile-policies). ## Register a Flex Gateway Instance in Local Mode To begin using the `make run` command to debug your custom policy, register a Flex Gateway in Local Mode. For the `run` command to work, a Flex Gateway `registration.yaml` file must exist in the `/playground/config` directory. Create this file by running the registration command in the directory, or move a `registration.yaml` file of a previously registered Flex Gateway to the directory. The `make run` command only supports Flex Gateways running in Local Mode in a Docker Container. To register Flex Gateway, see: - [Register and Run with a Username and Password in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-up#docker) - [Register and Run with a Connected App in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-app#docker) - [Register and Run with a Token in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-token#docker) > [!IMPORTANT] Run only the registration command. Do not run the Docker start command because the > `make run` command completes this step. Create a different registration file on each device testing the policy. The registration file is ignored for storage in remote repositories and is listed in the `.gitignore` file located at the root of the project directory. ## Configure the Policy Depending on the configurations listed in the `definition/gcl.yaml` file you configured in [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-schema-definition), you may have to configure some parameters before running the policy locally. For example, if the `gcl.yaml` file is as follows: ```yaml apiVersion: gateway.mulesoft.com.v1alpha1 kind: Extension metadata: labels: title: my-custom-policy category: Security spec: extends: - name: extension-definition properties: user: type: string default: user1 password: type: string description: type: string required: - user - password ``` Update the `/playground/config/api.yaml` file with your configuration value: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: ApiInstance metadata: name: ingress-http spec: address: http://0.0.0.0:8081 services: upstream: address: http://backend routes: - config: destinationPath: /anything/echo/ policies: - policyRef: name: my-custom-policy config: password: 12345678 ``` In this example, the `user` is set to the default value `user1`, the `password` is set to `12345678`, and no description is provided. ## Add Additional Policies You can also apply additional policies to the test API instance to test your custom policies behavior alongside other policies. However, your custom policy under development must be the first policy specified, for example: ```yaml policies: - policyRef: name: my-custom-policy config: password: 12345678 - policyRef: name: additional-policy config: ``` ## Deploy the Policy with PDK After you complete the previous steps, run the `make run` command from the policy’s root directory to deploy policy: ```cmd make run ``` This command starts the two Docker containers in the `/playground/docker-compose.yaml` file: - `Local-flex`: The Flex Gateway instance Docker container that executes the custom policy. This Flex Gateway listens for requests made to `localhost:8081`. - `Backend`: The Docker Container that runs the backend service for the Flex Gateway instance. This backend service echoes any request it receives. > [!NOTE] To stop the Docker containers, press `Cmd+c` or `Ctrl+c` depending on your device from the > terminal running the containers. Once the containers are running, you can make requests to the API instance, for example: ```cmd curl --location --request POST 'http://0.0.0.0:8081/some/route' \ --header 'Token: mytoken' ``` The backend service returns an echo response including the requests’s route, body, and headers sent with any modification performed by the custom policy or additional policies. Any logs included in the custom policy’s source code are visible in the terminal running the containers. ## Configure the Loglevel By default, PDK’s debugging environment enables logs with the `debug` `loglevel` configured. To change the `loglevel`, edit the `logging.runtimeLogs.logLevel` value in `/playground/config/logging.yaml`. To learn more about editing a Flex Gateway’s logging configuration file, see [Configuring External Logs for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-third-party-logs-config). ## Use the Rust Debugger Visual Studio Code (VS Code) includes a Rust debugger that can run unit tests. You cannot use the VS Code Debugger while the policy is deployed on a Flex Gateway. To create the API mocking, you must use unit tests for the specific logic you need to debug. To debug Rust code in VS Code, you must install the [CodeLLDB Debugger Extension](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) or a different VS Code extension with the same functionality. To learn more about debugging Rust in VS Code, see [Rust in Visual Studio Code](https://code.visualstudio.com/docs/languages/rust#_debugging). ## See Also - [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.7/policies-pdk-integration-tests) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.7/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Debugging Custom Policies with the PDK Debugging Playground > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To test the functionality of your policy, Omni Gateway Policy Development Kit (PDK) provides a pre-configured API instance located in the `/playground/config` directory. The PDK Debugging Playground only supports Omni Gateway running in Local Mode in a Docker container. If you plan to deploy or policy to Omni Gateway running in Connected Mode or to a different platform, you should still first test your policy in PDK by using Omni Gateway running in Local Mode in a Docker container. > [!IMPORTANT] You can run Omni Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Omni Gateway does not support Windows in production environments. To test your policy, complete the following tasks: 1. [Before You Begin](#before-you-begin) 2. [Register an Omni Gateway Instance in Local Mode](#register) 3. [Configure the Policy](#configure-the-policy) 4. [Add Additional Policies](#add-additional-policies) if necessary 5. [Deploy the Policy with PDK](#deploy-the-policy-with-pdk) ## Before You Begin Ensure that you have: - [Installed Docker](https://www.docker.com/). - [Compiled your custom policy project](https://docs.mulesoft.com/pdk/1.8/policies-pdk-compile-policies). ## Register an Omni Gateway Instance in Local Mode To begin using the `make run` command to debug your custom policy, register an Omni Gateway in Local Mode. For the `run` command to work, an Omni Gateway `registration.yaml` file must exist in the `/playground/config` directory. Create this file by running the registration command in the directory, or move a `registration.yaml` file of a previously registered Omni Gateway to the directory. The `make run` command only supports Omni Gateways running in Local Mode in a Docker Container. To register Omni Gateway, see: - [Register and Run with a Username and Password in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-up#docker) - [Register and Run with a Connected App in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-app#docker) - [Register and Run with a Token in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-token#docker) > [!IMPORTANT] Run only the registration command. Do not run the Docker start command because the > `make run` command completes this step. Create a different registration file on each device testing the policy. The registration file is ignored for storage in remote repositories and is listed in the `.gitignore` file located at the root of the project directory. ## Configure the Policy Depending on the configurations listed in the `definition/gcl.yaml` file you configured in [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-schema-definition), you may have to configure some parameters before running the policy locally. For example, if the `gcl.yaml` file is as follows: ```yaml apiVersion: gateway.mulesoft.com.v1alpha1 kind: Extension metadata: labels: title: my-custom-policy category: Security spec: extends: - name: extension-definition properties: user: type: string default: user1 password: type: string description: type: string required: - user - password ``` Update the `/playground/config/api.yaml` file with your configuration value: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: ApiInstance metadata: name: ingress-http spec: address: http://0.0.0.0:8081 services: upstream: address: http://backend routes: - config: destinationPath: /anything/echo/ policies: - policyRef: name: my-custom-policy config: password: 12345678 ``` In this example, the `user` is set to the default value `user1`, the `password` is set to `12345678`, and no description is provided. ## Add Additional Policies You can also apply additional policies to the test API instance to test your custom policies behavior alongside other policies. However, your custom policy under development must be the first policy specified, for example: ```yaml policies: - policyRef: name: my-custom-policy config: password: 12345678 - policyRef: name: additional-policy config: ``` ## Deploy the Policy with PDK After you complete the previous steps, run the `make run` command from the policy’s root directory to deploy policy: ```cmd make run ``` This command starts the two Docker containers in the `/playground/docker-compose.yaml` file: - `Local-flex`: The Omni Gateway instance Docker container that executes the custom policy. This Omni Gateway listens for requests made to `localhost:8081`. - `Backend`: The Docker Container that runs the backend service for the Omni Gateway instance. This backend service echoes any request it receives. > [!NOTE] To stop the Docker containers, press `Cmd+c` or `Ctrl+c` depending on your device from the > terminal running the containers. Once the containers are running, you can make requests to the API instance, for example: ```cmd curl --location --request POST 'http://0.0.0.0:8081/some/route' \ --header 'Token: mytoken' ``` The backend service returns an echo response including the requests’s route, body, and headers sent with any modification performed by the custom policy or additional policies. Any logs included in the custom policy’s source code are visible in the terminal running the containers. ## Configure the Loglevel By default, PDK’s debugging environment enables logs with the `debug` `loglevel` configured. To change the `loglevel`, edit the `logging.runtimeLogs.logLevel` value in `/playground/config/logging.yaml`. To learn more about editing an Omni Gateway’s logging configuration file, see [Configuring External Logs for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-third-party-logs-config). ## Use the Rust Debugger Visual Studio Code (VS Code) includes a Rust debugger that can run unit tests. You cannot use the VS Code Debugger while the policy is deployed on an Omni Gateway. To create the API mocking, you must use unit tests for the specific logic you need to debug. To debug Rust code in VS Code, you must install the [CodeLLDB Debugger Extension](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) or a different VS Code extension with the same functionality. To learn more about debugging Rust in VS Code, see [Rust in Visual Studio Code](https://code.visualstudio.com/docs/languages/rust#_debugging). ## See Also - [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.8/policies-pdk-integration-tests) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.8/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Debugging Custom Policies with the PDK Debugging Playground > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To test the functionality of your policy, Omni Gateway Policy Development Kit (PDK) provides a pre-configured API instance located in the `/playground/config` directory. The PDK Debugging Playground only supports Omni Gateway running in Local Mode in a Docker container. If you plan to deploy or policy to Omni Gateway running in Connected Mode or to a different platform, you should still first test your policy in PDK by using Omni Gateway running in Local Mode in a Docker container. > [!IMPORTANT] You can run Omni Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Omni Gateway does not support Windows in production environments. To test your policy, complete the following tasks: 1. [Before You Begin](#before-you-begin) 2. [Register an Omni Gateway Instance in Local Mode](#register) 3. [Configure the Policy](#configure-the-policy) 4. [Add Additional Policies](#add-additional-policies) if necessary 5. [Deploy the Policy with PDK](#deploy-the-policy-with-pdk) ## Before You Begin Ensure that you have: - [Installed Docker](https://www.docker.com/). - [Compiled your custom policy project](https://docs.mulesoft.com/pdk/1.9/policies-pdk-compile-policies). ## Register an Omni Gateway Instance in Local Mode To begin using the `make run` command to debug your custom policy, register an Omni Gateway in Local Mode. For the `run` command to work, an Omni Gateway `registration.yaml` file must exist in the `/playground/config` directory. Create this file by running the registration command in the directory, or move a `registration.yaml` file of a previously registered Omni Gateway to the directory. The `make run` command only supports Omni Gateways running in Local Mode in a Docker Container. To register Omni Gateway, see: - [Register and Run with a Username and Password in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-up#docker) - [Register and Run with a Connected App in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-app#docker) - [Register and Run with a Token in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-token#docker) > [!IMPORTANT] Run only the registration command. Do not run the Docker start command because the > `make run` command completes this step. Create a different registration file on each device testing the policy. The registration file is ignored for storage in remote repositories and is listed in the `.gitignore` file located at the root of the project directory. ## Configure the Policy Depending on the configurations listed in the `definition/gcl.yaml` file you configured in [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-schema-definition), you may have to configure some parameters before running the policy locally. For example, if the `gcl.yaml` file is as follows: ```yaml apiVersion: gateway.mulesoft.com.v1alpha1 kind: Extension metadata: labels: title: my-custom-policy category: Security spec: extends: - name: extension-definition properties: user: type: string default: user1 password: type: string description: type: string required: - user - password ``` Update the `/playground/config/api.yaml` file with your configuration value: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: ApiInstance metadata: name: ingress-http spec: address: http://0.0.0.0:8081 services: upstream: address: http://backend routes: - config: destinationPath: /anything/echo/ policies: - policyRef: name: my-custom-policy config: password: 12345678 ``` In this example, the `user` is set to the default value `user1`, the `password` is set to `12345678`, and no description is provided. ## Add Additional Policies You can also apply additional policies to the test API instance to test your custom policies behavior alongside other policies. However, your custom policy under development must be the first policy specified, for example: ```yaml policies: - policyRef: name: my-custom-policy config: password: 12345678 - policyRef: name: additional-policy config: ``` ## Deploy the Policy with PDK After you complete the previous steps, run the `make run` command from the policy’s root directory to deploy policy: ```cmd make run ``` This command starts the two Docker containers in the `/playground/docker-compose.yaml` file: - `Local-flex`: The Omni Gateway instance Docker container that executes the custom policy. This Omni Gateway listens for requests made to `localhost:8081`. - `Backend`: The Docker Container that runs the backend service for the Omni Gateway instance. This backend service echoes any request it receives. > [!NOTE] To stop the Docker containers, press `Cmd+c` or `Ctrl+c` depending on your device from the > terminal running the containers. Once the containers are running, you can make requests to the API instance, for example: ```cmd curl --location --request POST 'http://0.0.0.0:8081/some/route' \ --header 'Token: mytoken' ``` The backend service returns an echo response including the requests’s route, body, and headers sent with any modification performed by the custom policy or additional policies. Any logs included in the custom policy’s source code are visible in the terminal running the containers. ## Configure the Loglevel By default, PDK’s debugging environment enables logs with the `debug` `loglevel` configured. To change the `loglevel`, edit the `logging.runtimeLogs.logLevel` value in `/playground/config/logging.yaml`. To learn more about editing an Omni Gateway’s logging configuration file, see [Configuring External Logs for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-third-party-logs-config). ## Use the Rust Debugger Visual Studio Code (VS Code) includes a Rust debugger that can run unit tests. You cannot use the VS Code Debugger while the policy is deployed on an Omni Gateway. To create the API mocking, you must use unit tests for the specific logic you need to debug. To debug Rust code in VS Code, you must install the [CodeLLDB Debugger Extension](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) or a different VS Code extension with the same functionality. To learn more about debugging Rust in VS Code, see [Rust in Visual Studio Code](https://code.visualstudio.com/docs/languages/rust#_debugging). ## See Also - [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.9/policies-pdk-integration-tests) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.9/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Debugging Custom Policies with the PDK Debugging Playground > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To test the functionality of your policy, Omni Gateway Policy Development Kit (PDK) provides a pre-configured API instance located in the `/playground/config` directory. The PDK Debugging Playground only supports Omni Gateway running in Local Mode in a Docker container. If you plan to deploy or policy to Omni Gateway running in Connected Mode or to a different platform, you should still first test your policy in PDK by using Omni Gateway running in Local Mode in a Docker container. > [!IMPORTANT] You can run Omni Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Omni Gateway does not support Windows in production environments. To test your policy, complete the following tasks: 1. [Before You Begin](#before-you-begin) 2. [Register an Omni Gateway Instance in Local Mode](#register) 3. [Configure the Policy](#configure-the-policy) 4. [Add Additional Policies](#add-additional-policies) if necessary 5. [Deploy the Policy with PDK](#deploy-the-policy-with-pdk) ## Before You Begin Ensure that you have: - [Installed Docker](https://www.docker.com/). - [Compiled your custom policy project](https://docs.mulesoft.com/pdk/latest/policies-pdk-compile-policies). ## Register an Omni Gateway Instance in Local Mode To begin using the `make run` command to debug your custom policy, register an Omni Gateway in Local Mode. For the `run` command to work, an Omni Gateway `registration.yaml` file must exist in the `/playground/config` directory. Create this file by running the registration command in the directory, or move a `registration.yaml` file of a previously registered Omni Gateway to the directory. > [!NOTE] A registration file is generated automatically when you run the debugging playground if no > `registration.yaml` file is provided. The `make run` command only supports Omni Gateways running in Local Mode in a Docker Container. To register Omni Gateway, see: - [Register and Run with a Username and Password in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-up#docker) - [Register and Run with a Connected App in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-app#docker) - [Register and Run with a Token in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-token#docker) > [!IMPORTANT] Run only the registration command. Do not run the Docker start command because the > `make run` command completes this step. Create a different registration file on each device testing the policy. The registration file is ignored for storage in remote repositories and is listed in the `.gitignore` file located at the root of the project directory. ## Configure the Policy Depending on the configurations listed in the `definition/gcl.yaml` file you configured in [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-schema-definition), you may have to configure some parameters before running the policy locally. For example, if the `gcl.yaml` file is as follows: ```yaml apiVersion: gateway.mulesoft.com.v1alpha1 kind: Extension metadata: labels: title: my-custom-policy category: Security spec: extends: - name: extension-definition properties: user: type: string default: user1 password: type: string description: type: string required: - user - password ``` Update the `/playground/config/api.yaml` file with your configuration value: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: ApiInstance metadata: name: ingress-http spec: address: http://0.0.0.0:8081 services: upstream: address: http://backend routes: - config: destinationPath: /anything/echo/ policies: - policyRef: name: my-custom-policy config: password: 12345678 ``` In this example, the `user` is set to the default value `user1`, the `password` is set to `12345678`, and no description is provided. ## Add Additional Policies You can also apply additional policies to the test API instance to test your custom policies behavior alongside other policies. However, your custom policy under development must be the first policy specified, for example: ```yaml policies: - policyRef: name: my-custom-policy config: password: 12345678 - policyRef: name: additional-policy config: ``` ## Deploy the Policy with PDK After you complete the previous steps, run the `make run` command from the policy’s root directory to deploy policy: ```cmd make run ``` This command starts the two Docker containers in the `/playground/docker-compose.yaml` file: - `Local-flex`: The Omni Gateway instance Docker container that executes the custom policy. This Omni Gateway listens for requests made to `localhost:8081`. - `Backend`: The Docker Container that runs the backend service for the Omni Gateway instance. This backend service echoes any request it receives. > [!NOTE] To stop the Docker containers, press `Cmd+c` or `Ctrl+c` depending on your device from the > terminal running the containers. Once the containers are running, you can make requests to the API instance, for example: ```cmd curl --location --request POST 'http://0.0.0.0:8081/some/route' \ --header 'Token: mytoken' ``` The backend service returns an echo response including the requests’s route, body, and headers sent with any modification performed by the custom policy or additional policies. Any logs included in the custom policy’s source code are visible in the terminal running the containers. ## Configure the Loglevel By default, PDK’s debugging environment enables logs with the `debug` `loglevel` configured. To change the `loglevel`, edit the `logging.runtimeLogs.logLevel` value in `/playground/config/logging.yaml`. To learn more about editing an Omni Gateway’s logging configuration file, see [Configuring External Logs for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-third-party-logs-config). ## Use the Rust Debugger Visual Studio Code (VS Code) includes a Rust debugger that can run unit tests. You cannot use the VS Code Debugger while the policy is deployed on an Omni Gateway. To create the API mocking, you must use unit tests for the specific logic you need to debug. To debug Rust code in VS Code, you must install the [CodeLLDB Debugger Extension](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) or a different VS Code extension with the same functionality. To learn more about debugging Rust in VS Code, see [Rust in Visual Studio Code](https://code.visualstudio.com/docs/languages/rust#_debugging). ## See Also - [Writing Integration Tests](https://docs.mulesoft.com/pdk/latest/policies-pdk-integration-tests) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/latest/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Debugging Deployed Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Errors that are not present in the PDK debugging playground or PDK’s integration might be present when the policy is [applied to an API instance](https://docs.mulesoft.com/pdk/1.2/policies-pdk-apply-policies) in a production environment. To use debug logs in a production environment, see [Troubleshooting Self-Managed Gateway with Debug Logs](https://docs.mulesoft.com/gateway/latest/troubleshoot-debug-logs). For more information about monitoring Flex Gateway, see [Monitoring Omni Gateway](https://docs.mulesoft.com/gateway/latest/gateway-monitor). ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.2/policies-pdk-debug-local) - [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.2/policies-pdk-integration-tests) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Debugging Deployed Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Errors that are not present in the PDK debugging playground or PDK’s integration might be present when the policy is [applied to an API instance](https://docs.mulesoft.com/pdk/1.3/policies-pdk-apply-policies) in a production environment. To use debug logs in a production environment, see [Troubleshooting Self-Managed Gateway with Debug Logs](https://docs.mulesoft.com/gateway/latest/troubleshoot-debug-logs). For more information about monitoring Flex Gateway, see [Monitoring Omni Gateway](https://docs.mulesoft.com/gateway/latest/gateway-monitor). ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.3/policies-pdk-debug-local) - [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.3/policies-pdk-integration-tests) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Debugging Deployed Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Errors that are not present in the PDK debugging playground or PDK’s integration might be present when the policy is [applied to an API instance](https://docs.mulesoft.com/pdk/1.4/policies-pdk-apply-policies) in a production environment. To use debug logs in a production environment, see [Troubleshooting Self-Managed Gateway with Debug Logs](https://docs.mulesoft.com/gateway/latest/troubleshoot-debug-logs). For more information about monitoring Flex Gateway, see [Monitoring Omni Gateway](https://docs.mulesoft.com/gateway/latest/gateway-monitor). ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.4/policies-pdk-debug-local) - [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.4/policies-pdk-integration-tests) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Debugging Deployed Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Errors that are not present in the PDK debugging playground or PDK’s integration might be present when the policy is [applied to an API instance](https://docs.mulesoft.com/pdk/1.5/policies-pdk-apply-policies) in a production environment. To use debug logs in a production environment, see [Troubleshooting Self-Managed Gateway with Debug Logs](https://docs.mulesoft.com/gateway/latest/troubleshoot-debug-logs). For more information about monitoring Flex Gateway, see [Monitoring Omni Gateway](https://docs.mulesoft.com/gateway/latest/gateway-monitor). ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.5/policies-pdk-debug-local) - [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.5/policies-pdk-integration-tests) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Debugging Deployed Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Errors that are not present in the PDK debugging playground or PDK’s integration might be present when the policy is [applied to an API instance](https://docs.mulesoft.com/pdk/1.6/policies-pdk-apply-policies) in a production environment. To use debug logs in a production environment, see [Troubleshooting Self-Managed Gateway with Debug Logs](https://docs.mulesoft.com/gateway/latest/troubleshoot-debug-logs). For more information about monitoring Flex Gateway, see [Monitoring Omni Gateway](https://docs.mulesoft.com/gateway/latest/gateway-monitor). ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.6/policies-pdk-debug-local) - [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.6/policies-pdk-integration-tests) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Debugging Deployed Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Errors that are not present in the PDK debugging playground or PDK’s integration might be present when the policy is [applied to an API instance](https://docs.mulesoft.com/pdk/1.7/policies-pdk-apply-policies) in a production environment. To use debug logs in a production environment, see [Troubleshooting Self-Managed Gateway with Debug Logs](https://docs.mulesoft.com/gateway/latest/troubleshoot-debug-logs). For more information about monitoring Flex Gateway, see [Monitoring Omni Gateway](https://docs.mulesoft.com/gateway/latest/gateway-monitor). ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.7/policies-pdk-debug-local) - [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.7/policies-pdk-integration-tests) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Debugging Deployed Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Errors that aren’t present in the PDK’s debugging and testing environments might be present when the policy is [applied to an API instance](https://docs.mulesoft.com/pdk/1.8/policies-pdk-apply-policies) in a production environment. To use debug logs in a production environment, see [Troubleshooting Self-Managed Gateway with Debug Logs](https://docs.mulesoft.com/gateway/latest/troubleshoot-debug-logs). For more information about monitoring Omni Gateway, see [Monitoring Omni Gateway](https://docs.mulesoft.com/gateway/latest/gateway-monitor). ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.8/policies-pdk-debug-local) - [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.8/policies-pdk-integration-tests) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Debugging Deployed Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Errors that aren’t present in the PDK’s debugging and testing environments might be present when the policy is [applied to an API instance](https://docs.mulesoft.com/pdk/1.9/policies-pdk-apply-policies) in a production environment. To use debug logs in a production environment, see [Troubleshooting Self-Managed Gateway with Debug Logs](https://docs.mulesoft.com/gateway/latest/troubleshoot-debug-logs). For more information about monitoring Omni Gateway, see [Monitoring Omni Gateway](https://docs.mulesoft.com/gateway/latest/gateway-monitor). ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.9/policies-pdk-debug-local) - [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.9/policies-pdk-integration-tests) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Debugging Deployed Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Errors that aren’t present in the PDK’s debugging and testing environments might be present when the policy is [applied to an API instance](https://docs.mulesoft.com/pdk/latest/policies-pdk-apply-policies) in a production environment. To use debug logs in a production environment, see [Troubleshooting Self-Managed Gateway with Debug Logs](https://docs.mulesoft.com/gateway/latest/troubleshoot-debug-logs). For more information about monitoring Omni Gateway, see [Monitoring Omni Gateway](https://docs.mulesoft.com/gateway/latest/gateway-monitor). ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/latest/policies-pdk-debug-local) - [Writing Integration Tests](https://docs.mulesoft.com/pdk/latest/policies-pdk-integration-tests) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Defining a Policy Schema Definition > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Similar to the policies listed in the [Inbound Policies Directory](https://docs.mulesoft.com/gateway/latest/policies-included-directory), custom policies have configuration parameters. Use the configuration parameters to improve the usability of your custom policy and support a wider range of API configurations. To define custom configuration parameters, edit the `definition/gcl.yaml` file. The `gcl.yaml` file is written in the Gateway Configuration Language (GCL). However, you do not need prior GCL knowledge to use this tutorial. The configuration parameters you define in the `gcl.yaml` appear as variables in the `src/generated/config.rs` file after you run the `make build-asset-file` command. You set any user input you need for implementing the Rust source code in the `gcl.yaml` file. Configuration parameters appear in the API Manager UI when applying a policy to Flex Gateway running in Connected Mode. When applying the policy to Flex Gateway running in Local Mode, it is your responsibility to distribute a configuration `yaml` file for your policy. The default `gcl.yaml` file has the following content: ```yaml apiVersion: gateway.mulesoft.com.v1alpha1 kind: Extension metadata: labels: title: my-custom-policy category: Custom spec: extends: - name: extension-definition properties: stringProperty: type: string ``` The `gcl.yaml` file contains two sections: - `metadata`: Defines information about the policy - `properties`: Defines the policy’s configuration parameters To define a schema definition: 1. [Define Metadata](#define-metadata) 2. [Define Parameters](#define-parameters) 3. [Use Custom Parameters in Rust Source Code](#use-custom-parameters-in-rust-source-code) ## Define Metadata Add labels in the metadata section to enrich the data shown in the UI when applying the policy. To define the metadata, edit the `metadata` in the `gcl.yaml` file. The supported labels are: - `title`: The policy name that appears in the UI. - `description`: A brief explanation of the policy’s behavior. - `category`: The category the of the policy. The possible categories are `security`, `compliance`, `transformation`, `quality of service`, and `troubleshooting`. For example: ```yaml metadata: labels: title: JSON Threat Protection description: Protects against malicious JSON in API requests. category: Security ``` `labels` are suggested but not required. ## Define Outbound Policies By default, PDK creates policies as inbound policies. To create an outbound policy, edit the `labels` section in the `gcl.yaml` file. Add the `metadata/capabilities/injectionPoint: outbound` label, for example: ```yaml metadata: labels: title: My Outbound Policy description: An outbound security policy category: Security metadata/capabilities/injectionPoint: outbound ``` ## Define Parameters To add parameters, edit the `spec.properties` section in the `gcl.yaml` file. For example: ```yaml properties: username: type: string password: type: string ``` After defining your properties, you can: - [Define Required Properties and Default Values](#define-required-properties-and-default-values) - [Define Supported Types](#define-supported-types) ### Define Required Properties and Default Values You can define each property listed in the `gcl.yaml` file as `required` and set a `default` value for the property. To define properties as required, list them in the `spec.required` object. For example, the following policy requires a `password` but not a `username`: ```yaml properties: username: type: string password: type: string required: - password ``` In the above configuration example, applying a policy without a password results in a failed configuration. The following example defines a default value for each property: ```yaml properties: username: type: string default: user1 password: type: string default: 12345678 required: - password ``` If you do not set a value for a required property when applying a policy, the property uses the default value. For non-required properties, the API Manager UI suggests the configured default value for properties. If you do not specify the value for non-required properties, the property is not configured. In the following configuration table, if the policy was applied in API Manager, `user2` would appear as a suggested value for `username` but is not configured if the value is omitted:

Policy Configuration

Effective Configuration

Configuration Status

{}

{"password": "12345678"}

Success

{"username": "user2"}

{"password": "12345678",
"username": "user2"}

Success

{"password": "password"}

{"password": "password"}

Success

{"password": "password",
"username": "user2"}

{"password": "password",
"username": "user2"}

Success

### Define Sensitive Data Protect sensitive data, such as passwords or certificates, by adding the `security:sensitive` characteristic: ```yaml properties: key: type: string default: "YourKey" "@context": { "@characteristics": [ "security:sensitive" ] } ``` When applying the policy, the input value to the sensitive parameter is not visible to the user: ![The character inputs to the key parameter appear as black dots.](/mulesoft/current/en-us/pdk/1.2/_images/sensitive-data.png) Toggling **Show** reveals any new data currently being entered. However, you cannot reveal previously stored data. For example, if you configure the example **Key** parameter and apply the policy, you cannot view the parameter if you edit the policy’s configuration in the future. ### Define Conditional Parameters Render policy configuration parameters dynamically by establishing conditions to make fields visible. In the following code example, the `encryptionKey` parameter appears if the user selects `true` for the `encryptBody` parameter: ```yaml properties: encryptBody: type: boolean default: false encryptionKey: type: string "@rendering": "@visibleOn": - property: encryptBody value: true ``` In the following code example, the `encryptionKey` parameter is initially visible and disappears if the user selects `false` for the for the `encryptBody` parameter: ```yaml properties: encryptBody: type: boolean default: true encryptionKey: type: string "@rendering": "@visibleOn": - property: encryptBody value: true ``` Conditional parameters have the following restrictions: - You can only define a single condition per parameter. - Only `string`, `boolean`, or `integer` parameters are supported as the condition parameter. - The conditionally rendered parameter cannot be an `object` or `enum`. - Required properties that are conditionally rendered must have a default value defined. In the above examples, if `encryptionKey` is required, it requires a default value. - Only root-level parameters support conditional rendering. Inner properties of arrays or objects do not support conditional rendering. ### Define Enumerated Parameters Limit user’s input values by defining parameters with the `enum` property, for example: ```yaml properties: signingMethod: type: string enum: - rsa - hmac ``` In the API Manager UI, `enum` parameters render as radio buttons for three or fewer enumerated values and as a dropdown field for more. For Flex Gateway running in Local Mode, the user must configure the parameter as one of the enumerated values or the policy configuration fails. Enumerated parameters don’t support the `@visibleOn` tag. To learn more about how to render variables dynamically, see [Define Conditional Parameters](#define-conditional-parameters). ### Define Supported Types Define a supported data type for each policy parameter to ensure the policy receives the correct data. The supported types are: String The string type specifies that the data is text. ```yaml properties: password: type: string ``` The `string` type also supports enables you to configure a `format` type. The supported formatting types are: - `dataweave`: Specifies the input parameter is a DataWeave variable and notifies Flex Gateway to transform the input. For more information about DataWeave expressions, see [Define DataWeave Expressions](#dataweave-expressions). - `service`: Specifies the input parameter is a URI and automatically creates a Flex Gateway service to enable HTTP calls from the policy. - `ipRange`: Specifies the expected text is a range of IPs and provides additional validation on the input. - `uri`: Specifies the expected text is a URI and provides additional validation on the input. Only use `uri` when the URI is not a service making HTTP calls from the policy. The following yaml snippet demonstrates all string formats: ```yaml properties: externalService: type: string format: service default: "https://auth-service:9000/login" token: type: string format: dataweave default: "#[splitBy(attributes.headers['Authorization'], ' ')[1]]" blockedIps: type: string format: ipRange default: "192.168.3.1/30" loginUrl: type: string format: uri default: "https://anypoint.mulesoft.com/login" ``` Number The `number` type specifies data as a floating point value. For example: ```yaml properties: squareRoot: type: number default: 1.414213562 seconds: type: number default: 10 ``` Integer The `integer` type specifies data as an integer value. For example: ```yaml properties: maxHeaders: type: integer default: 10 ``` Boolean The `boolean` type specifies data as a boolean value. Supported values are `true` or `false`. For example: ```yaml properties: skipValidation: type: boolean default: false requireCredentials: type: boolean default: true ``` Array The `array` type specifies the data as a list of ordered elements. For the `array` type, you must also specify `items.type` to specify the data type of the items in the array. For example: ```yaml properties: scopes: type: array items: type: string default: ["READ", "WRITE"] ``` Object The `object` type specifies the data as a list of ordered elements with multiple properties. For the `object` type, you must also specify `properties.type` for each element in the object. For example: ```yaml properties: user: type: object properties: id: type: string name: type: string required: - id - name default: { "id": "1", "name": "John Doe" } ``` ### Define DataWeave Expressions The `dataweave` format for `string` type parameters specifies the input parameter as a DataWeave expression. The `dataweave` variable supports the following expression bindings: ```yaml : type: string format: dataweave bindings: payload: mimeType: text attributes: true authentication: false vars: [] ``` - `payload`: The body of the incoming request. Define the `mimeType` as either `text` or `json` to set how to read the payload. By default, `mimeType` is set to `text`. To restrict the use of the `payload` variable, you must exclude the payload variable, for example: ```yaml bindings: attributes: true authentication: false vars: [] ``` - `attributes`: Attributes, such as headers, of the incoming request. Set `attributes` to `true` to enable the policy to read the attributes of the incoming request. By default, `attributes` is set to `true`. - `authentication`: Authentication information of the incoming request. Set `authentication` to `true` to enable the policy to read authentication details of the incoming request. By default, `authentication` is set to `false`. - `vars`: Specifies the names of the variables that are available for the policy to use. By default, `vars` is empty. When the policy is applied, if the user inputs a variable that is not defined in the schema, the policy evaluates the variable as `null`. For more information about the supported expression bindings, see [Predefined Variables](https://docs.mulesoft.com/dataweave/latest/dataweave-variables-context). If the user’s expression contains bindings that are not defined in the policy’s schema when applying the policy, the policy configuration fails. For example, if the user expression is `[authentication.principal]` and `authentication` is not set to `true`, an error similar to the following occurs: test-local-flex-1 | \[flex-gateway-envoy\]\[error\] wasm log main: \[policy: ingress-http-jwt-auth-v1-0-impl-1.default\]\[api: ingress-http.default.svc\] Launcher problem: Failed to parse configuration '{"dw":"P\[\[\\".\\", \\"0-24\\", \[\\":ref\\", \\"0-14\\", \\"authentication\\"\], \[\\":str\\", \\"15-24\\", \\"principal\\"\]\], \\"#\[authentication.principal\]\\"\]"}'. Cause: Error compiling expression: Unknown symbol \`authentication\` at line 1 column 141 When evaluating the DataWeave expression in your policy, you must provide the script to resolve the expression. To learn how to implement DataWeave expressions in your Rust source code, see [Implement DataWeave Expressions](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features#use-dataweave-expressions). For more information about DataWeave support for Flex Gateway, see [DataWeave Support in Omni Gateway Policies](https://docs.mulesoft.com/gateway/latest/policies-dataweave-support). ## Use Custom Parameters in Rust Source Code After you modify the `gcl.yaml` file, run one of the following commands to propagate the changes to the `src/generated/config.rs` rust file and the JSON schema for the API Manager UI: - `make build-asset-files` only propagates the changes to `src/generated/config.rs`. ```cmd make build-asset-files ``` - `make build` propagates the changes to `src/generated/config.rs` and generates the policy’s target files. Do not run `make build` if you do not want to override your policy’s target file: ```cmd make build ``` For more information about compiling your policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.2/policies-pdk-compile-policies). Properties defined in the `gcl.yaml` files are mapped to the Rust data types in the `config.rs` Rust file as follows:
gcl.yamlconfig.rs

string

String

uri string

String

ipRange string

String

dataweave string

pdk::script::Script

number

f64

integer

i64

boolean

bool

array

vec containing the specified item type

object

struct containing the specified property types

> [!IMPORTANT] If a parameter in `gcl.yaml` is not defined as ‘required’, the parameter’s > counterpart in the `config.rs` is wrapped in an ‘Option’ object. > > Validate that the parameter is present before unwrapping. Unwrapping a parameter that is not > present may cause a `panic!`. > > Use one of the following validation examples to ensure the parameter is present: > > - `if let Some(val) = myValue` > > - `if myValue.is_some() {myValue.unwrap()}` For example, the following `gcl.yaml` files produces the following `struct` in `config.rs`: 1. `gcl.yaml`: ```yaml properties: tokenExtractor: type: string format: dataweave default: "#[dw::core::Strings::substringAfter(attributes.headers['Authorization'], 'Bearer ')]" reject_missing_tokens: type: boolean max_chars: type: number required: - tokenExtractor ``` 2. `config.rs`: ```rust pub struct Config { #[serde(alias = "max_chars")] pub max_chars: Option, #[serde(alias = "reject_missing_tokens")] pub reject_missing_tokens: Option, #[serde(alias = "tokenExtractor")] pub token_extractor: pdk::script::Script, } ``` For example, you can access the values in `struct Config` with the following `.operators` in the `entrypoint` function: ```rust #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration,) -> Result<(), LaunchError> { let config: Config = serde_json::from_slice(&configuration)?; match config.reject_missing_tokens { ``` ## See Also - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.2/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Defining a Policy Schema Definition > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Similar to the policies listed in the [Inbound Policies Directory](https://docs.mulesoft.com/gateway/latest/policies-included-directory), custom policies have configuration parameters. Use the configuration parameters to improve the usability of your custom policy and support a wider range of API configurations. To define custom configuration parameters, edit the `definition/gcl.yaml` file. The `gcl.yaml` file is written in the Gateway Configuration Language (GCL). However, you do not need prior GCL knowledge to use this tutorial. The configuration parameters you define in the `gcl.yaml` appear as variables in the `src/generated/config.rs` file after you run the `make build-asset-file` command. You set any user input you need for implementing the Rust source code in the `gcl.yaml` file. Configuration parameters appear in the API Manager UI when applying a policy to Flex Gateway running in Connected Mode. When applying the policy to Flex Gateway running in Local Mode, it is your responsibility to distribute a configuration `yaml` file for your policy. The default `gcl.yaml` file has the following content: ```yaml apiVersion: gateway.mulesoft.com.v1alpha1 kind: Extension metadata: labels: title: my-custom-policy category: Custom spec: extends: - name: extension-definition properties: stringProperty: type: string ``` The `gcl.yaml` file contains two sections: - `metadata`: Defines information about the policy - `properties`: Defines the policy’s configuration parameters To define a schema definition: 1. [Define Metadata](#define-metadata) 2. [Define Parameters](#define-parameters) 3. [Use Custom Parameters in Rust Source Code](#use-custom-parameters-in-rust-source-code) ## Define Metadata Add labels in the metadata section to enrich the data shown in the UI when applying the policy. To define the metadata, edit the `metadata` in the `gcl.yaml` file. The supported labels are: - `title`: The policy name that appears in the UI. - `description`: A brief explanation of the policy’s behavior. - `category`: The category the of the policy. The possible categories are `security`, `compliance`, `transformation`, `quality of service`, and `troubleshooting`. For example: ```yaml metadata: labels: title: JSON Threat Protection description: Protects against malicious JSON in API requests. category: Security ``` `labels` are suggested but not required. ## Define Outbound Policies By default, PDK creates policies as inbound policies. To create an outbound policy, edit the `labels` section in the `gcl.yaml` file. Add the `metadata/capabilities/injectionPoint: outbound` label, for example: ```yaml metadata: labels: title: My Outbound Policy description: An outbound security policy category: Security metadata/capabilities/injectionPoint: outbound ``` ## Define Parameters To add parameters, edit the `spec.properties` section in the `gcl.yaml` file. For example: ```yaml properties: username: type: string password: type: string ``` After defining your properties, you can: - [Define Required Properties and Default Values](#define-required-properties-and-default-values) - [Define Supported Types](#define-supported-types) ### Define Required Properties and Default Values You can define each property listed in the `gcl.yaml` file as `required` and set a `default` value for the property. To define properties as required, list them in the `spec.required` object. For example, the following policy requires a `password` but not a `username`: ```yaml properties: username: type: string password: type: string required: - password ``` In the above configuration example, applying a policy without a password results in a failed configuration. The following example defines a default value for each property: ```yaml properties: username: type: string default: user1 password: type: string default: 12345678 required: - password ``` If you do not set a value for a required property when applying a policy, the property uses the default value. For non-required properties, the API Manager UI suggests the configured default value for properties. If you do not specify the value for non-required properties, the property is not configured. In the following configuration table, if the policy was applied in API Manager, `user2` would appear as a suggested value for `username` but is not configured if the value is omitted:

Policy Configuration

Effective Configuration

Configuration Status

{}

{"password": "12345678"}

Success

{"username": "user2"}

{"password": "12345678",
"username": "user2"}

Success

{"password": "password"}

{"password": "password"}

Success

{"password": "password",
"username": "user2"}

{"password": "password",
"username": "user2"}

Success

### Define Sensitive Data Protect sensitive data, such as passwords or certificates, by adding the `security:sensitive` characteristic: ```yaml properties: key: type: string default: "YourKey" "@context": { "@characteristics": [ "security:sensitive" ] } ``` When applying the policy, the input value to the sensitive parameter is not visible to the user: ![The character inputs to the key parameter appear as black dots.](/mulesoft/current/en-us/pdk/1.3/_images/sensitive-data.png) Toggling **Show** reveals any new data currently being entered. However, you cannot reveal previously stored data. For example, if you configure the example **Key** parameter and apply the policy, you cannot view the parameter if you edit the policy’s configuration in the future. ### Define Conditional Parameters Render policy configuration parameters dynamically by establishing conditions to make fields visible. In the following code example, the `encryptionKey` parameter appears if the user selects `true` for the `encryptBody` parameter: ```yaml properties: encryptBody: type: boolean default: false encryptionKey: type: string "@rendering": "@visibleOn": - property: encryptBody value: true ``` In the following code example, the `encryptionKey` parameter is initially visible and disappears if the user selects `false` for the for the `encryptBody` parameter: ```yaml properties: encryptBody: type: boolean default: true encryptionKey: type: string "@rendering": "@visibleOn": - property: encryptBody value: true ``` Conditional parameters have the following restrictions: - You can only define a single condition per parameter. - Only `string`, `boolean`, or `integer` parameters are supported as the condition parameter. - The conditionally rendered parameter cannot be an `object` or `enum`. - Required properties that are conditionally rendered must have a default value defined. In the above examples, if `encryptionKey` is required, it requires a default value. - Only root-level parameters support conditional rendering. Inner properties of arrays or objects do not support conditional rendering. ### Define Enumerated Parameters Limit user’s input values by defining parameters with the `enum` property, for example: ```yaml properties: signingMethod: type: string enum: - rsa - hmac ``` In the API Manager UI, `enum` parameters render as radio buttons for three or fewer enumerated values and as a dropdown field for more. For Flex Gateway running in Local Mode, the user must configure the parameter as one of the enumerated values or the policy configuration fails. Enumerated parameters don’t support the `@visibleOn` tag. To learn more about how to render variables dynamically, see [Define Conditional Parameters](#define-conditional-parameters). ### Define Supported Types Define a supported data type for each policy parameter to ensure the policy receives the correct data. The supported types are: String The string type specifies that the data is text. ```yaml properties: password: type: string ``` The `string` type also supports enables you to configure a `format` type. The supported formatting types are: - `dataweave`: Specifies the input parameter is a DataWeave variable and notifies Flex Gateway to transform the input. For more information about DataWeave expressions, see [Define DataWeave Expressions](#dataweave-expressions). - `service`: Specifies the input parameter is a URI and automatically creates a Flex Gateway service to enable HTTP calls from the policy. - `ipRange`: Specifies the expected text is a range of IPs and provides additional validation on the input. - `uri`: Specifies the expected text is a URI and provides additional validation on the input. Only use `uri` when the URI is not a service making HTTP calls from the policy. The following yaml snippet demonstrates all string formats: ```yaml properties: externalService: type: string format: service default: "https://auth-service:9000/login" token: type: string format: dataweave default: "#[splitBy(attributes.headers['Authorization'], ' ')[1]]" blockedIps: type: string format: ipRange default: "192.168.3.1/30" loginUrl: type: string format: uri default: "https://anypoint.mulesoft.com/login" ``` Number The `number` type specifies data as a floating point value. For example: ```yaml properties: squareRoot: type: number default: 1.414213562 seconds: type: number default: 10 ``` Integer The `integer` type specifies data as an integer value. For example: ```yaml properties: maxHeaders: type: integer default: 10 ``` Boolean The `boolean` type specifies data as a boolean value. Supported values are `true` or `false`. For example: ```yaml properties: skipValidation: type: boolean default: false requireCredentials: type: boolean default: true ``` Array The `array` type specifies the data as a list of ordered elements. For the `array` type, you must also specify `items.type` to specify the data type of the items in the array. For example: ```yaml properties: scopes: type: array items: type: string default: ["READ", "WRITE"] ``` Object The `object` type specifies the data as a list of ordered elements with multiple properties. For the `object` type, you must also specify `properties.type` for each element in the object. For example: ```yaml properties: user: type: object properties: id: type: string name: type: string required: - id - name default: { "id": "1", "name": "John Doe" } ``` ### Define DataWeave Expressions The `dataweave` format for `string` type parameters specifies the input parameter as a DataWeave expression. The `dataweave` variable supports the following expression bindings: ```yaml : type: string format: dataweave bindings: payload: mimeType: text attributes: true authentication: false vars: [] ``` - `payload`: The body of the incoming request. Define the `mimeType` as either `text` or `json` to set how to read the payload. By default, `mimeType` is set to `text`. To restrict the use of the `payload` variable, you must exclude the payload variable, for example: ```yaml bindings: attributes: true authentication: false vars: [] ``` - `attributes`: Attributes, such as headers, of the incoming request. Set `attributes` to `true` to enable the policy to read the attributes of the incoming request. By default, `attributes` is set to `true`. - `authentication`: Authentication information of the incoming request. Set `authentication` to `true` to enable the policy to read authentication details of the incoming request. By default, `authentication` is set to `false`. - `vars`: Specifies the names of the variables that are available for the policy to use. By default, `vars` is empty. When the policy is applied, if the user inputs a variable that is not defined in the schema, the policy evaluates the variable as `null`. For more information about the supported expression bindings, see [Predefined Variables](https://docs.mulesoft.com/dataweave/latest/dataweave-variables-context). If the user’s expression contains bindings that are not defined in the policy’s schema when applying the policy, the policy configuration fails. For example, if the user expression is `[authentication.principal]` and `authentication` is not set to `true`, an error similar to the following occurs: test-local-flex-1 | \[flex-gateway-envoy\]\[error\] wasm log main: \[policy: ingress-http-jwt-auth-v1-0-impl-1.default\]\[api: ingress-http.default.svc\] Launcher problem: Failed to parse configuration '{"dw":"P\[\[\\".\\", \\"0-24\\", \[\\":ref\\", \\"0-14\\", \\"authentication\\"\], \[\\":str\\", \\"15-24\\", \\"principal\\"\]\], \\"#\[authentication.principal\]\\"\]"}'. Cause: Error compiling expression: Unknown symbol \`authentication\` at line 1 column 141 When evaluating the DataWeave expression in your policy, you must provide the script to resolve the expression. To learn how to implement DataWeave expressions in your Rust source code, see [Implement DataWeave Expressions](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features#use-dataweave-expressions). For more information about DataWeave support for Flex Gateway, see [DataWeave Support in Omni Gateway Policies](https://docs.mulesoft.com/gateway/latest/policies-dataweave-support). ## Use Custom Parameters in Rust Source Code After you modify the `gcl.yaml` file, run one of the following commands to propagate the changes to the `src/generated/config.rs` rust file and the JSON schema for the API Manager UI: - `make build-asset-files` only propagates the changes to `src/generated/config.rs`. ```cmd make build-asset-files ``` - `make build` propagates the changes to `src/generated/config.rs` and generates the policy’s target files. Do not run `make build` if you do not want to override your policy’s target file: ```cmd make build ``` For more information about compiling your policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.3/policies-pdk-compile-policies). Properties defined in the `gcl.yaml` files are mapped to the Rust data types in the `config.rs` Rust file as follows:
gcl.yamlconfig.rs

string

String

uri string

String

ipRange string

String

dataweave string

pdk::script::Script

number

f64

integer

i64

boolean

bool

array

vec containing the specified item type

object

struct containing the specified property types

> [!IMPORTANT] If a parameter in `gcl.yaml` is not defined as ‘required’, the parameter’s > counterpart in the `config.rs` is wrapped in an ‘Option’ object. > > Validate that the parameter is present before unwrapping. Unwrapping a parameter that is not > present may cause a `panic!`. > > Use one of the following validation examples to ensure the parameter is present: > > - `if let Some(val) = myValue` > > - `if myValue.is_some() {myValue.unwrap()}` For example, the following `gcl.yaml` files produces the following `struct` in `config.rs`: 1. `gcl.yaml`: ```yaml properties: tokenExtractor: type: string format: dataweave default: "#[dw::core::Strings::substringAfter(attributes.headers['Authorization'], 'Bearer ')]" reject_missing_tokens: type: boolean max_chars: type: number required: - tokenExtractor ``` 2. `config.rs`: ```rust pub struct Config { #[serde(alias = "max_chars")] pub max_chars: Option, #[serde(alias = "reject_missing_tokens")] pub reject_missing_tokens: Option, #[serde(alias = "tokenExtractor")] pub token_extractor: pdk::script::Script, } ``` For example, you can access the values in `struct Config` with the following `.operators` in the `entrypoint` function: ```rust #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration,) -> Result<(), LaunchError> { let config: Config = serde_json::from_slice(&configuration)?; match config.reject_missing_tokens { ``` ## See Also - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.3/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Defining a Policy Schema Definition > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Similar to the policies listed in the [Inbound Policies Directory](https://docs.mulesoft.com/gateway/latest/policies-included-directory), custom policies have configuration parameters. Use the configuration parameters to improve the usability of your custom policy and support a wider range of API configurations. To define custom configuration parameters, edit the `definition/gcl.yaml` file. The `gcl.yaml` file is written in the Gateway Configuration Language (GCL). However, you do not need prior GCL knowledge to use this tutorial. The configuration parameters you define in the `gcl.yaml` appear as variables in the `src/generated/config.rs` file after you run the `make build-asset-file` command. You set any user input you need for implementing the Rust source code in the `gcl.yaml` file. Configuration parameters appear in the API Manager UI when applying a policy to Flex Gateway running in Connected Mode. When applying the policy to Flex Gateway running in Local Mode, it is your responsibility to distribute a configuration `yaml` file for your policy. The default `gcl.yaml` file has the following content: ```yaml apiVersion: gateway.mulesoft.com.v1alpha1 kind: Extension metadata: labels: title: my-custom-policy category: Custom spec: extends: - name: extension-definition properties: stringProperty: type: string ``` The `gcl.yaml` file contains two sections: - `metadata`: Defines information about the policy - `properties`: Defines the policy’s configuration parameters To define a schema definition: 1. [Define Metadata](#define-metadata) 2. [Define Parameters](#define-parameters) 3. [Use Custom Parameters in Rust Source Code](#use-custom-parameters-in-rust-source-code) ## Define Metadata Add labels in the metadata section to enrich the data shown in the UI when applying the policy. To define the metadata, edit the `metadata` in the `gcl.yaml` file. The supported labels are: - `title`: The policy name that appears in the UI. - `description`: A brief explanation of the policy’s behavior. - `category`: The category the of the policy. The possible categories are `security`, `compliance`, `transformation`, `quality of service`, and `troubleshooting`. For example: ```yaml metadata: labels: title: JSON Threat Protection description: Protects against malicious JSON in API requests. category: Security ``` `labels` are suggested but not required. ## Define Outbound Policies By default, PDK creates policies as inbound policies. To create an outbound policy, edit the `labels` section in the `gcl.yaml` file. Add the `metadata/capabilities/injectionPoint: outbound` label, for example: ```yaml metadata: labels: title: My Outbound Policy description: An outbound security policy category: Security metadata/capabilities/injectionPoint: outbound ``` ## Define Parameters To add parameters, edit the `spec.properties` section in the `gcl.yaml` file. For example: ```yaml properties: username: type: string password: type: string ``` After defining your properties, you can: - [Define Required Properties and Default Values](#define-required-properties-and-default-values) - [Define Supported Types](#define-supported-types) ### Define Required Properties and Default Values You can define each property listed in the `gcl.yaml` file as `required` and set a `default` value for the property. To define properties as required, list them in the `spec.required` object. For example, the following policy requires a `password` but not a `username`: ```yaml properties: username: type: string password: type: string required: - password ``` In the above configuration example, applying a policy without a password results in a failed configuration. The following example defines a default value for each property: ```yaml properties: username: type: string default: user1 password: type: string default: 12345678 required: - password ``` If you do not set a value for a required property when applying a policy, the property uses the default value. For non-required properties, the API Manager UI suggests the configured default value for properties. If you do not specify the value for non-required properties, the property is not configured. In the following configuration table, if the policy was applied in API Manager, `user2` would appear as a suggested value for `username` but is not configured if the value is omitted:

Policy Configuration

Effective Configuration

Configuration Status

{}

{"password": "12345678"}

Success

{"username": "user2"}

{"password": "12345678",
"username": "user2"}

Success

{"password": "password"}

{"password": "password"}

Success

{"password": "password",
"username": "user2"}

{"password": "password",
"username": "user2"}

Success

### Define Sensitive Data Protect sensitive data, such as passwords or certificates, by adding the `security:sensitive` characteristic: ```yaml properties: key: type: string default: "YourKey" "@context": { "@characteristics": [ "security:sensitive" ] } ``` When applying the policy, the input value to the sensitive parameter is not visible to the user: ![The character inputs to the key parameter appear as black dots.](/mulesoft/current/en-us/pdk/1.4/_images/sensitive-data.png) Toggling **Show** reveals any new data currently being entered. However, you cannot reveal previously stored data. For example, if you configure the example **Key** parameter and apply the policy, you cannot view the parameter if you edit the policy’s configuration in the future. ### Define Conditional Parameters Render policy configuration parameters dynamically by establishing conditions to make fields visible. In the following code example, the `encryptionKey` parameter appears if the user selects `true` for the `encryptBody` parameter: ```yaml properties: encryptBody: type: boolean default: false encryptionKey: type: string "@rendering": "@visibleOn": - property: encryptBody value: true ``` In the following code example, the `encryptionKey` parameter is initially visible and disappears if the user selects `false` for the for the `encryptBody` parameter: ```yaml properties: encryptBody: type: boolean default: true encryptionKey: type: string "@rendering": "@visibleOn": - property: encryptBody value: true ``` Conditional parameters have the following restrictions: - You can only define a single condition per parameter. - Only `string`, `boolean`, or `integer` parameters are supported as the condition parameter. - The conditionally rendered parameter cannot be an `object` or `enum`. - Required properties that are conditionally rendered must have a default value defined. In the above examples, if `encryptionKey` is required, it requires a default value. - Only root-level parameters support conditional rendering. Inner properties of arrays or objects do not support conditional rendering. ### Define Enumerated Parameters Limit user’s input values by defining parameters with the `enum` property, for example: ```yaml properties: signingMethod: type: string enum: - rsa - hmac ``` In the API Manager UI, `enum` parameters render as radio buttons for three or fewer enumerated values and as a dropdown field for more. For Flex Gateway running in Local Mode, the user must configure the parameter as one of the enumerated values or the policy configuration fails. Enumerated parameters don’t support the `@visibleOn` tag. To learn more about how to render variables dynamically, see [Define Conditional Parameters](#define-conditional-parameters). ### Define Supported Types Define a supported data type for each policy parameter to ensure the policy receives the correct data. The supported types are: String The string type specifies that the data is text. ```yaml properties: password: type: string ``` The `string` type also supports enables you to configure a `format` type. The supported formatting types are: - `dataweave`: Specifies the input parameter is a DataWeave variable and notifies Flex Gateway to transform the input. For more information about DataWeave expressions, see [Define DataWeave Expressions](#dataweave-expressions). - `service`: Specifies the input parameter is a URI and automatically creates a Flex Gateway service to enable HTTP calls from the policy. - `ipRange`: Specifies the expected text is a range of IPs and provides additional validation on the input. - `uri`: Specifies the expected text is a URI and provides additional validation on the input. Only use `uri` when the URI is not a service making HTTP calls from the policy. The following yaml snippet demonstrates all string formats: ```yaml properties: externalService: type: string format: service default: "https://auth-service:9000/login" token: type: string format: dataweave default: "#[splitBy(attributes.headers['Authorization'], ' ')[1]]" blockedIps: type: string format: ipRange default: "192.168.3.1/30" loginUrl: type: string format: uri default: "https://anypoint.mulesoft.com/login" ``` Number The `number` type specifies data as a floating point value. For example: ```yaml properties: squareRoot: type: number default: 1.414213562 seconds: type: number default: 10 ``` Integer The `integer` type specifies data as an integer value. For example: ```yaml properties: maxHeaders: type: integer default: 10 ``` Boolean The `boolean` type specifies data as a boolean value. Supported values are `true` or `false`. For example: ```yaml properties: skipValidation: type: boolean default: false requireCredentials: type: boolean default: true ``` Array The `array` type specifies the data as a list of ordered elements. For the `array` type, you must also specify `items.type` to specify the data type of the items in the array. For example: ```yaml properties: scopes: type: array items: type: string default: ["READ", "WRITE"] ``` Object The `object` type specifies the data as a list of ordered elements with multiple properties. For the `object` type, you must also specify `properties.type` for each element in the object. For example: ```yaml properties: user: type: object properties: id: type: string name: type: string required: - id - name default: { "id": "1", "name": "John Doe" } ``` ### Define DataWeave Expressions The `dataweave` format for `string` type parameters specifies the input parameter as a DataWeave expression. The `dataweave` variable supports the following expression bindings: ```yaml : type: string format: dataweave bindings: payload: mimeType: text attributes: true authentication: false vars: [] ``` - `payload`: The body of the incoming request. Define the `mimeType` as either `text`, `json`, or `xml` to set how to read the payload. By default, `mimeType` is set to `text`. If the `content-type` header is bound to the evaluator, then the payload is interpreted according to the value of the `content-type` header. To restrict the use of the `payload` variable, exclude the payload variable as shown in this example: ```yaml bindings: attributes: true authentication: false vars: [] ``` - `attributes`: Attributes, such as headers, of the incoming request. Set `attributes` to `true` to enable the policy to read the attributes of the incoming request. By default, `attributes` is set to `true`. - `authentication`: Authentication information of the incoming request. Set `authentication` to `true` to enable the policy to read authentication details of the incoming request. By default, `authentication` is set to `false`. - `vars`: Specifies the names of the variables that are available for the policy to use. By default, `vars` is empty. When the policy is applied, if the user inputs a variable that is not defined in the schema, the policy evaluates the variable as `null`. For more information about the supported expression bindings, see [Predefined Variables](https://docs.mulesoft.com/dataweave/latest/dataweave-variables-context). If the user’s expression contains bindings that are not defined in the policy’s schema when applying the policy, the policy configuration fails. For example, if the user expression is `[authentication.principal]` and `authentication` is not set to `true`, an error similar to the following occurs: test-local-flex-1 | \[flex-gateway-envoy\]\[error\] wasm log main: \[policy: ingress-http-jwt-auth-v1-0-impl-1.default\]\[api: ingress-http.default.svc\] Launcher problem: Failed to parse configuration '{"dw":"P\[\[\\".\\", \\"0-24\\", \[\\":ref\\", \\"0-14\\", \\"authentication\\"\], \[\\":str\\", \\"15-24\\", \\"principal\\"\]\], \\"#\[authentication.principal\]\\"\]"}'. Cause: Error compiling expression: Unknown symbol \`authentication\` at line 1 column 141 When evaluating the DataWeave expression in your policy, you must provide the script to resolve the expression. To learn how to implement DataWeave expressions in your Rust source code, see [Implement DataWeave Expressions](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features#use-dataweave-expressions). For more information about DataWeave support for Flex Gateway, see [DataWeave Support in Omni Gateway Policies](https://docs.mulesoft.com/gateway/latest/policies-dataweave-support). ## Use Custom Parameters in Rust Source Code After you modify the `gcl.yaml` file, run one of the following commands to propagate the changes to the `src/generated/config.rs` rust file and the JSON schema for the API Manager UI: - `make build-asset-files` only propagates the changes to `src/generated/config.rs`. ```cmd make build-asset-files ``` - `make build` propagates the changes to `src/generated/config.rs` and generates the policy’s target files. Do not run `make build` if you do not want to override your policy’s target file: ```cmd make build ``` For more information about compiling your policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.4/policies-pdk-compile-policies). Properties defined in the `gcl.yaml` files are mapped to the Rust data types in the `config.rs` Rust file as follows:
gcl.yamlconfig.rs

string

String

uri string

String

ipRange string

String

dataweave string

pdk::script::Script

number

f64

integer

i64

boolean

bool

array

vec containing the specified item type

object

struct containing the specified property types

> [!IMPORTANT] If a parameter in `gcl.yaml` is not defined as ‘required’, the parameter’s > counterpart in the `config.rs` is wrapped in an ‘Option’ object. > > Validate that the parameter is present before unwrapping. Unwrapping a parameter that is not > present may cause a `panic!`. > > Use one of the following validation examples to ensure the parameter is present: > > - `if let Some(val) = myValue` > > - `if myValue.is_some() {myValue.unwrap()}` For example, the following `gcl.yaml` files produces the following `struct` in `config.rs`: 1. `gcl.yaml`: ```yaml properties: tokenExtractor: type: string format: dataweave default: "#[dw::core::Strings::substringAfter(attributes.headers['Authorization'], 'Bearer ')]" reject_missing_tokens: type: boolean max_chars: type: number required: - tokenExtractor ``` 2. `config.rs`: ```rust pub struct Config { #[serde(alias = "max_chars")] pub max_chars: Option, #[serde(alias = "reject_missing_tokens")] pub reject_missing_tokens: Option, #[serde(alias = "tokenExtractor")] pub token_extractor: pdk::script::Script, } ``` For example, you can access the values in `struct Config` with the following `.operators` in the `entrypoint` function: ```rust #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration,) -> Result<(), LaunchError> { let config: Config = serde_json::from_slice(&configuration)?; match config.reject_missing_tokens { ``` ## See Also - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.4/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Defining a Policy Schema Definition > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Similar to the policies listed in the [Inbound Policies Directory](https://docs.mulesoft.com/gateway/latest/policies-included-directory), custom policies have configuration parameters. Use the configuration parameters to improve the usability of your custom policy and support a wider range of API configurations. To define custom configuration parameters, edit the `definition/gcl.yaml` file. The `gcl.yaml` file is written in the Gateway Configuration Language (GCL). However, you do not need prior GCL knowledge to use this tutorial. The configuration parameters you define in the `gcl.yaml` appear as variables in the `src/generated/config.rs` file after you run the `make build-asset-file` command. You set any user input you need for implementing the Rust source code in the `gcl.yaml` file. Configuration parameters appear in the API Manager UI when applying a policy to Flex Gateway running in Connected Mode. When applying the policy to Flex Gateway running in Local Mode, it is your responsibility to distribute a configuration `yaml` file for your policy. The default `gcl.yaml` file has the following content: ```yaml apiVersion: gateway.mulesoft.com.v1alpha1 kind: Extension metadata: labels: title: my-custom-policy category: Custom spec: extends: - name: extension-definition properties: stringProperty: type: string ``` The `gcl.yaml` file contains two sections: - `metadata`: Defines information about the policy - `properties`: Defines the policy’s configuration parameters To define a schema definition: 1. [Define Metadata](#define-metadata) 2. [Define Parameters](#define-parameters) 3. [Use Custom Parameters in Rust Source Code](#use-custom-parameters-in-rust-source-code) ## Define Metadata Add labels in the metadata section to enrich the data shown in the UI when applying the policy. To define the metadata, edit the `metadata` in the `gcl.yaml` file. The supported labels are: - `title`: The policy name that appears in the UI. - `description`: A brief explanation of the policy’s behavior. - `category`: The category the of the policy. The possible categories are `security`, `compliance`, `transformation`, `quality of service`, and `troubleshooting`. For example: ```yaml metadata: labels: title: JSON Threat Protection description: Protects against malicious JSON in API requests. category: Security ``` `labels` are suggested but not required. ## Define Outbound Policies By default, PDK creates policies as inbound policies. To create an outbound policy, edit the `labels` section in the `gcl.yaml` file. Add the `metadata/capabilities/injectionPoint: outbound` label, for example: ```yaml metadata: labels: title: My Outbound Policy description: An outbound security policy category: Security metadata/capabilities/injectionPoint: outbound ``` ## Define Parameters To add parameters, edit the `spec.properties` section in the `gcl.yaml` file. For example: ```yaml properties: username: type: string password: type: string ``` After defining your properties, you can: - [Define Required Properties and Default Values](#define-required-properties-and-default-values) - [Define Supported Types](#define-supported-types) ### Define Required Properties and Default Values You can define each property listed in the `gcl.yaml` file as `required` and set a `default` value for the property. To define properties as required, list them in the `spec.required` object. For example, the following policy requires a `password` but not a `username`: ```yaml properties: username: type: string password: type: string required: - password ``` In the above configuration example, applying a policy without a password results in a failed configuration. The following example defines a default value for each property: ```yaml properties: username: type: string default: user1 password: type: string default: 12345678 required: - password ``` If you do not set a value for a required property when applying a policy, the property uses the default value. For non-required properties, the API Manager UI suggests the configured default value for properties. If you do not specify the value for non-required properties, the property is not configured. In the following configuration table, if the policy was applied in API Manager, `user2` would appear as a suggested value for `username` but is not configured if the value is omitted:

Policy Configuration

Effective Configuration

Configuration Status

{}

{"password": "12345678"}

Success

{"username": "user2"}

{"password": "12345678",
"username": "user2"}

Success

{"password": "password"}

{"password": "password"}

Success

{"password": "password",
"username": "user2"}

{"password": "password",
"username": "user2"}

Success

### Define Sensitive Data Protect sensitive data, such as passwords or certificates, by adding the `security:sensitive` characteristic: ```yaml properties: key: type: string default: "YourKey" "@context": { "@characteristics": [ "security:sensitive" ] } ``` When applying the policy, the input value to the sensitive parameter is not visible to the user: ![The character inputs to the key parameter appear as black dots.](/mulesoft/current/en-us/pdk/1.5/_images/sensitive-data.png) Toggling **Show** reveals any new data currently being entered. However, you cannot reveal previously stored data. For example, if you configure the example **Key** parameter and apply the policy, you cannot view the parameter if you edit the policy’s configuration in the future. ### Define Conditional Parameters Render policy configuration parameters dynamically by establishing conditions to make fields visible. In the following code example, the `encryptionKey` parameter appears if the user selects `true` for the `encryptBody` parameter: ```yaml properties: encryptBody: type: boolean default: false encryptionKey: type: string "@rendering": "@visibleOn": - property: encryptBody value: true ``` In the following code example, the `encryptionKey` parameter is initially visible and disappears if the user selects `false` for the for the `encryptBody` parameter: ```yaml properties: encryptBody: type: boolean default: true encryptionKey: type: string "@rendering": "@visibleOn": - property: encryptBody value: true ``` Conditional parameters have the following restrictions: - You can only define a single condition per parameter. - Only `string`, `boolean`, or `integer` parameters are supported as the condition parameter. - The conditionally rendered parameter cannot be an `object` or `enum`. - Required properties that are conditionally rendered must have a default value defined. In the above examples, if `encryptionKey` is required, it requires a default value. - Only root-level parameters support conditional rendering. Inner properties of arrays or objects do not support conditional rendering. ### Define Enumerated Parameters Limit user’s input values by defining parameters with the `enum` property, for example: ```yaml properties: signingMethod: type: string enum: - rsa - hmac ``` In the API Manager UI, `enum` parameters render as radio buttons for three or fewer enumerated values and as a dropdown field for more. For Flex Gateway running in Local Mode, the user must configure the parameter as one of the enumerated values or the policy configuration fails. Enumerated parameters don’t support the `@visibleOn` tag. To learn more about how to render variables dynamically, see [Define Conditional Parameters](#define-conditional-parameters). ### Define Supported Types Define a supported data type for each policy parameter to ensure the policy receives the correct data. The supported types are: String The string type specifies that the data is text. ```yaml properties: password: type: string ``` The `string` type also supports enables you to configure a `format` type. The supported formatting types are: - `dataweave`: Specifies the input parameter is a DataWeave variable and notifies Flex Gateway to transform the input. For more information about DataWeave expressions, see [Define DataWeave Expressions](#dataweave-expressions). - `service`: Specifies the input parameter is a URI and automatically creates a Flex Gateway service to enable HTTP calls from the policy. - `ipRange`: Specifies the expected text is a range of IPs and provides additional validation on the input. - `uri`: Specifies the expected text is a URI and provides additional validation on the input. Only use `uri` when the URI is not a service making HTTP calls from the policy. The following yaml snippet demonstrates all string formats: ```yaml properties: externalService: type: string format: service default: "https://auth-service:9000/login" token: type: string format: dataweave default: "#[splitBy(attributes.headers['Authorization'], ' ')[1]]" blockedIps: type: string format: ipRange default: "192.168.3.1/30" loginUrl: type: string format: uri default: "https://anypoint.mulesoft.com/login" ``` Number The `number` type specifies data as a floating point value. For example: ```yaml properties: squareRoot: type: number default: 1.414213562 seconds: type: number default: 10 ``` Integer The `integer` type specifies data as an integer value. For example: ```yaml properties: maxHeaders: type: integer default: 10 ``` Boolean The `boolean` type specifies data as a boolean value. Supported values are `true` or `false`. For example: ```yaml properties: skipValidation: type: boolean default: false requireCredentials: type: boolean default: true ``` Array The `array` type specifies the data as a list of ordered elements. For the `array` type, you must also specify `items.type` to specify the data type of the items in the array. For example: ```yaml properties: scopes: type: array items: type: string default: ["READ", "WRITE"] ``` Object The `object` type specifies the data as a list of ordered elements with multiple properties. For the `object` type, you must also specify `properties.type` for each element in the object. For example: ```yaml properties: user: type: object properties: id: type: string name: type: string required: - id - name default: { "id": "1", "name": "John Doe" } ``` ### Define DataWeave Expressions The `dataweave` format for `string` type parameters specifies the input parameter as a DataWeave expression. The `dataweave` variable supports the following expression bindings: ```yaml : type: string format: dataweave bindings: payload: mimeType: text attributes: true authentication: false vars: [] ``` - `payload`: The body of the incoming request. Define the `mimeType` as either `text`, `json`, or `xml` to set how to read the payload. By default, `mimeType` is set to `text`. If the `content-type` header is bound to the evaluator, then the payload is interpreted according to the value of the `content-type` header. To restrict the use of the `payload` variable, exclude the payload variable as shown in this example: ```yaml bindings: attributes: true authentication: false vars: [] ``` - `attributes`: Attributes, such as headers, of the incoming request. Set `attributes` to `true` to enable the policy to read the attributes of the incoming request. By default, `attributes` is set to `true`. - `authentication`: Authentication information of the incoming request. Set `authentication` to `true` to enable the policy to read authentication details of the incoming request. By default, `authentication` is set to `false`. - `vars`: Specifies the names of the variables that are available for the policy to use. By default, `vars` is empty. When the policy is applied, if the user inputs a variable that is not defined in the schema, the policy evaluates the variable as `null`. For more information about the supported expression bindings, see [Predefined Variables](https://docs.mulesoft.com/dataweave/latest/dataweave-variables-context). If the user’s expression contains bindings that are not defined in the policy’s schema when applying the policy, the policy configuration fails. For example, if the user expression is `[authentication.principal]` and `authentication` is not set to `true`, an error similar to the following occurs: test-local-flex-1 | \[flex-gateway-envoy\]\[error\] wasm log main: \[policy: ingress-http-jwt-auth-v1-0-impl-1.default\]\[api: ingress-http.default.svc\] Launcher problem: Failed to parse configuration '{"dw":"P\[\[\\".\\", \\"0-24\\", \[\\":ref\\", \\"0-14\\", \\"authentication\\"\], \[\\":str\\", \\"15-24\\", \\"principal\\"\]\], \\"#\[authentication.principal\]\\"\]"}'. Cause: Error compiling expression: Unknown symbol \`authentication\` at line 1 column 141 When evaluating the DataWeave expression in your policy, you must provide the script to resolve the expression. To learn how to implement DataWeave expressions in your Rust source code, see [Implement DataWeave Expressions](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features#use-dataweave-expressions). For more information about DataWeave support for Flex Gateway, see [DataWeave Support in Omni Gateway Policies](https://docs.mulesoft.com/gateway/latest/policies-dataweave-support). ## Use Custom Parameters in Rust Source Code After you modify the `gcl.yaml` file, run one of the following commands to propagate the changes to the `src/generated/config.rs` rust file and the JSON schema for the API Manager UI: - `make build-asset-files` only propagates the changes to `src/generated/config.rs`. ```cmd make build-asset-files ``` - `make build` propagates the changes to `src/generated/config.rs` and generates the policy’s target files. Do not run `make build` if you do not want to override your policy’s target file: ```cmd make build ``` For more information about compiling your policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.5/policies-pdk-compile-policies). Properties defined in the `gcl.yaml` files are mapped to the Rust data types in the `config.rs` Rust file as follows:
gcl.yamlconfig.rs

string

String

uri string

String

ipRange string

String

dataweave string

pdk::script::Script

number

f64

integer

i64

boolean

bool

array

vec containing the specified item type

object

struct containing the specified property types

> [!IMPORTANT] If a parameter in `gcl.yaml` is not defined as ‘required’, the parameter’s > counterpart in the `config.rs` is wrapped in an ‘Option’ object. > > Validate that the parameter is present before unwrapping. Unwrapping a parameter that is not > present may cause a `panic!`. > > Use one of the following validation examples to ensure the parameter is present: > > - `if let Some(val) = myValue` > > - `if myValue.is_some() {myValue.unwrap()}` For example, the following `gcl.yaml` files produces the following `struct` in `config.rs`: 1. `gcl.yaml`: ```yaml properties: tokenExtractor: type: string format: dataweave default: "#[dw::core::Strings::substringAfter(attributes.headers['Authorization'], 'Bearer ')]" reject_missing_tokens: type: boolean max_chars: type: number required: - tokenExtractor ``` 2. `config.rs`: ```rust pub struct Config { #[serde(alias = "max_chars")] pub max_chars: Option, #[serde(alias = "reject_missing_tokens")] pub reject_missing_tokens: Option, #[serde(alias = "tokenExtractor")] pub token_extractor: pdk::script::Script, } ``` For example, you can access the values in `struct Config` with the following `.operators` in the `entrypoint` function: ```rust #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration,) -> Result<(), LaunchError> { let config: Config = serde_json::from_slice(&configuration)?; match config.reject_missing_tokens { ``` ## See Also - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.5/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Defining a Policy Schema Definition > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Similar to the policies listed in the [Inbound Policies Directory](https://docs.mulesoft.com/gateway/latest/policies-included-directory), custom policies have configuration parameters. Use the configuration parameters to improve the usability of your custom policy and support a wider range of API configurations. To define custom configuration parameters, edit the `definition/gcl.yaml` file. The `gcl.yaml` file is written in the Gateway Configuration Language (GCL). However, you do not need prior GCL knowledge to use this tutorial. The configuration parameters you define in the `gcl.yaml` appear as variables in the `src/generated/config.rs` file after you run the `make build-asset-file` command. You set any user input you need for implementing the Rust source code in the `gcl.yaml` file. Configuration parameters appear in the API Manager UI when applying a policy to Flex Gateway running in Connected Mode. When applying the policy to Flex Gateway running in Local Mode, it is your responsibility to distribute a configuration `yaml` file for your policy. The default `gcl.yaml` file has the following content: ```yaml apiVersion: gateway.mulesoft.com.v1alpha1 kind: Extension metadata: labels: title: my-custom-policy category: Custom spec: extends: - name: extension-definition properties: stringProperty: type: string ``` The `gcl.yaml` file contains two sections: - `metadata`: Defines information about the policy - `properties`: Defines the policy’s configuration parameters To define a schema definition: 1. [Define Metadata](#define-metadata) 2. [Define Parameters](#define-parameters) 3. [Use Custom Parameters in Rust Source Code](#use-custom-parameters-in-rust-source-code) ## Define Metadata Add labels in the metadata section to enrich the data shown in the UI when applying the policy. To define the metadata, edit the `metadata` in the `gcl.yaml` file. The supported labels are: - `title`: The policy name that appears in the UI. - `description`: A brief explanation of the policy’s behavior. - `category`: The category the of the policy. The possible categories are `security`, `compliance`, `transformation`, `quality of service`, and `troubleshooting`. For example: ```yaml metadata: labels: title: JSON Threat Protection description: Protects against malicious JSON in API requests. category: Security ``` `labels` are suggested but not required. ## Define Outbound Policies By default, PDK creates policies as inbound policies. To create an outbound policy, edit the `labels` section in the `gcl.yaml` file. Add the `metadata/capabilities/injectionPoint: outbound` label, for example: ```yaml metadata: labels: title: My Outbound Policy description: An outbound security policy category: Security metadata/capabilities/injectionPoint: outbound ``` ## Define Parameters To add parameters, edit the `spec.properties` section in the `gcl.yaml` file. For example: ```yaml properties: username: type: string password: type: string ``` After defining your properties, you can: - [Define Required Properties and Default Values](#define-required-properties-and-default-values) - [Define Supported Types](#define-supported-types) ### Define Required Properties and Default Values You can define each property listed in the `gcl.yaml` file as `required` and set a `default` value for the property. To define properties as required, list them in the `spec.required` object. For example, the following policy requires a `password` but not a `username`: ```yaml properties: username: type: string password: type: string required: - password ``` In the above configuration example, applying a policy without a password results in a failed configuration. The following example defines a default value for each property: ```yaml properties: username: type: string default: user1 password: type: string default: 12345678 required: - password ``` If you do not set a value for a required property when applying a policy, the property uses the default value. For non-required properties, the API Manager UI suggests the configured default value for properties. If you do not specify the value for non-required properties, the property is not configured. In the following configuration table, if the policy was applied in API Manager, `user2` would appear as a suggested value for `username` but is not configured if the value is omitted:

Policy Configuration

Effective Configuration

Configuration Status

{}

{"password": "12345678"}

Success

{"username": "user2"}

{"password": "12345678",
"username": "user2"}

Success

{"password": "password"}

{"password": "password"}

Success

{"password": "password",
"username": "user2"}

{"password": "password",
"username": "user2"}

Success

### Define Sensitive Data Protect sensitive data, such as passwords or certificates, by adding the `security:sensitive` characteristic: ```yaml properties: key: type: string default: "YourKey" "@context": { "@characteristics": [ "security:sensitive" ] } ``` When applying the policy, the input value to the sensitive parameter is not visible to the user: ![The character inputs to the key parameter appear as black dots.](/mulesoft/current/en-us/pdk/1.6/_images/sensitive-data.png) Toggling **Show** reveals any new data currently being entered. However, you cannot reveal previously stored data. For example, if you configure the example **Key** parameter and apply the policy, you cannot view the parameter if you edit the policy’s configuration in the future. ### Define Conditional Parameters Render policy configuration parameters dynamically by establishing conditions to make fields visible. In the following code example, the `encryptionKey` parameter appears if the user selects `true` for the `encryptBody` parameter: ```yaml properties: encryptBody: type: boolean default: false encryptionKey: type: string "@rendering": "@visibleOn": - property: encryptBody value: true ``` In the following code example, the `encryptionKey` parameter is initially visible and disappears if the user selects `false` for the for the `encryptBody` parameter: ```yaml properties: encryptBody: type: boolean default: true encryptionKey: type: string "@rendering": "@visibleOn": - property: encryptBody value: true ``` Conditional parameters have the following restrictions: - You can only define a single condition per parameter. - Only `string`, `boolean`, or `integer` parameters are supported as the condition parameter. - The conditionally rendered parameter cannot be an `object` or `enum`. - Required properties that are conditionally rendered must have a default value defined. In the above examples, if `encryptionKey` is required, it requires a default value. - Only root-level parameters support conditional rendering. Inner properties of arrays or objects do not support conditional rendering. ### Define Enumerated Parameters Limit user’s input values by defining parameters with the `enum` property, for example: ```yaml properties: signingMethod: type: string enum: - rsa - hmac ``` In the API Manager UI, `enum` parameters render as radio buttons for three or fewer enumerated values and as a dropdown field for more. For Flex Gateway running in Local Mode, the user must configure the parameter as one of the enumerated values or the policy configuration fails. Enumerated parameters don’t support the `@visibleOn` tag. To learn more about how to render variables dynamically, see [Define Conditional Parameters](#define-conditional-parameters). ### Define Supported Types Define a supported data type for each policy parameter to ensure the policy receives the correct data. The supported types are: String The string type specifies that the data is text. ```yaml properties: password: type: string ``` The `string` type also supports enables you to configure a `format` type. The supported formatting types are: - `dataweave`: Specifies the input parameter is a DataWeave variable and notifies Flex Gateway to transform the input. For more information about DataWeave expressions, see [Define DataWeave Expressions](#dataweave-expressions). - `service`: Specifies the input parameter is a URI and automatically creates a Flex Gateway service to enable HTTP calls from the policy. - `ipRange`: Specifies the expected text is a range of IPs and provides additional validation on the input. - `uri`: Specifies the expected text is a URI and provides additional validation on the input. Only use `uri` when the URI is not a service making HTTP calls from the policy. The following yaml snippet demonstrates all string formats: ```yaml properties: externalService: type: string format: service default: "https://auth-service:9000/login" token: type: string format: dataweave default: "#[splitBy(attributes.headers['Authorization'], ' ')[1]]" blockedIps: type: string format: ipRange default: "192.168.3.1/30" loginUrl: type: string format: uri default: "https://anypoint.mulesoft.com/login" ``` Number The `number` type specifies data as a floating point value. For example: ```yaml properties: squareRoot: type: number default: 1.414213562 seconds: type: number default: 10 ``` Integer The `integer` type specifies data as an integer value. For example: ```yaml properties: maxHeaders: type: integer default: 10 ``` Boolean The `boolean` type specifies data as a boolean value. Supported values are `true` or `false`. For example: ```yaml properties: skipValidation: type: boolean default: false requireCredentials: type: boolean default: true ``` Array The `array` type specifies the data as a list of ordered elements. For the `array` type, you must also specify `items.type` to specify the data type of the items in the array. For example: ```yaml properties: scopes: type: array items: type: string default: ["READ", "WRITE"] ``` Object The `object` type specifies the data as a list of ordered elements with multiple properties. For the `object` type, you must also specify `properties.type` for each element in the object. For example: ```yaml properties: user: type: object properties: id: type: string name: type: string required: - id - name default: { "id": "1", "name": "John Doe" } ``` ### Define DataWeave Expressions The `dataweave` format for `string` type parameters specifies the input parameter as a DataWeave expression. The `dataweave` variable supports the following expression bindings: ```yaml : type: string format: dataweave bindings: payload: mimeType: text attributes: true authentication: false vars: [] ``` - `payload`: The body of the incoming request. Define the `mimeType` as either `text`, `json`, or `xml` to set how to read the payload. By default, `mimeType` is set to `text`. If the `content-type` header is bound to the evaluator, then the payload is interpreted according to the value of the `content-type` header. To restrict the use of the `payload` variable, exclude the payload variable as shown in this example: ```yaml bindings: attributes: true authentication: false vars: [] ``` - `attributes`: Attributes, such as headers, of the incoming request. Set `attributes` to `true` to enable the policy to read the attributes of the incoming request. By default, `attributes` is set to `true`. - `authentication`: Authentication information of the incoming request. Set `authentication` to `true` to enable the policy to read authentication details of the incoming request. By default, `authentication` is set to `false`. - `vars`: Specifies the names of the variables that are available for the policy to use. By default, `vars` is empty. When the policy is applied, if the user inputs a variable that is not defined in the schema, the policy evaluates the variable as `null`. For more information about the supported expression bindings, see [Predefined Variables](https://docs.mulesoft.com/dataweave/latest/dataweave-variables-context). If the user’s expression contains bindings that are not defined in the policy’s schema when applying the policy, the policy configuration fails. For example, if the user expression is `[authentication.principal]` and `authentication` is not set to `true`, an error similar to the following occurs: test-local-flex-1 | \[flex-gateway-envoy\]\[error\] wasm log main: \[policy: ingress-http-jwt-auth-v1-0-impl-1.default\]\[api: ingress-http.default.svc\] Launcher problem: Failed to parse configuration '{"dw":"P\[\[\\".\\", \\"0-24\\", \[\\":ref\\", \\"0-14\\", \\"authentication\\"\], \[\\":str\\", \\"15-24\\", \\"principal\\"\]\], \\"#\[authentication.principal\]\\"\]"}'. Cause: Error compiling expression: Unknown symbol \`authentication\` at line 1 column 141 When evaluating the DataWeave expression in your policy, you must provide the script to resolve the expression. To learn how to implement DataWeave expressions in your Rust source code, see [Implement DataWeave Expressions](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features#use-dataweave-expressions). For more information about DataWeave support for Flex Gateway, see [DataWeave Support in Omni Gateway Policies](https://docs.mulesoft.com/gateway/latest/policies-dataweave-support). ## Use Custom Parameters in Rust Source Code After you modify the `gcl.yaml` file, run one of the following commands to propagate the changes to the `src/generated/config.rs` rust file and the JSON schema for the API Manager UI: - `make build-asset-files` only propagates the changes to `src/generated/config.rs`. ```cmd make build-asset-files ``` - `make build` propagates the changes to `src/generated/config.rs` and generates the policy’s target files. Do not run `make build` if you do not want to override your policy’s target file: ```cmd make build ``` For more information about compiling your policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.6/policies-pdk-compile-policies). Properties defined in the `gcl.yaml` files are mapped to the Rust data types in the `config.rs` Rust file as follows:
gcl.yamlconfig.rs

string

String

uri string

String

ipRange string

String

dataweave string

pdk::script::Script

number

f64

integer

i64

boolean

bool

array

vec containing the specified item type

object

struct containing the specified property types

> [!IMPORTANT] If a parameter in `gcl.yaml` is not defined as ‘required’, the parameter’s > counterpart in the `config.rs` is wrapped in an ‘Option’ object. > > Validate that the parameter is present before unwrapping. Unwrapping a parameter that is not > present may cause a `panic!`. > > Use one of the following validation examples to ensure the parameter is present: > > - `if let Some(val) = myValue` > > - `if myValue.is_some() {myValue.unwrap()}` For example, the following `gcl.yaml` files produces the following `struct` in `config.rs`: 1. `gcl.yaml`: ```yaml properties: tokenExtractor: type: string format: dataweave default: "#[dw::core::Strings::substringAfter(attributes.headers['Authorization'], 'Bearer ')]" reject_missing_tokens: type: boolean max_chars: type: number required: - tokenExtractor ``` 2. `config.rs`: ```rust pub struct Config { #[serde(alias = "max_chars")] pub max_chars: Option, #[serde(alias = "reject_missing_tokens")] pub reject_missing_tokens: Option, #[serde(alias = "tokenExtractor")] pub token_extractor: pdk::script::Script, } ``` For example, you can access the values in `struct Config` with the following `.operators` in the `entrypoint` function: ```rust #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration,) -> Result<(), LaunchError> { let config: Config = serde_json::from_slice(&configuration)?; match config.reject_missing_tokens { ``` ## See Also - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.6/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Defining a Policy Schema Definition > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Similar to the policies listed in the [Inbound Policies Directory](https://docs.mulesoft.com/gateway/latest/policies-included-directory), custom policies have configuration parameters. Use the configuration parameters to improve the usability of your custom policy and support a wider range of API configurations. To define custom configuration parameters, edit the `definition/gcl.yaml` file. The `gcl.yaml` file is written in the Gateway Configuration Language (GCL). However, you do not need prior GCL knowledge to use this tutorial. The configuration parameters you define in the `gcl.yaml` appear as variables in the `src/generated/config.rs` file after you run the `make build-asset-file` command. You set any user input you need for implementing the Rust source code in the `gcl.yaml` file. Configuration parameters appear in the API Manager UI when applying a policy to Flex Gateway running in Connected Mode. When applying the policy to Flex Gateway running in Local Mode, it is your responsibility to distribute a configuration `yaml` file for your policy. The default `gcl.yaml` file has the following content: ```yaml apiVersion: gateway.mulesoft.com.v1alpha1 kind: Extension metadata: labels: title: my-custom-policy category: Custom spec: extends: - name: extension-definition properties: stringProperty: type: string ``` The `gcl.yaml` file contains two sections: - `metadata`: Defines information about the policy - `properties`: Defines the policy’s configuration parameters To define a schema definition: 1. [Define Metadata](#define-metadata) 2. [Define Parameters](#define-parameters) 3. [Use Custom Parameters in Rust Source Code](#use-custom-parameters-in-rust-source-code) ## Define Metadata Add labels in the metadata section to enrich the data shown in the UI when applying the policy. To define the metadata, edit the `metadata` in the `gcl.yaml` file. The supported labels are: - `title`: The policy name that appears in the UI. - `description`: A brief explanation of the policy’s behavior. - `category`: The category the of the policy. The possible categories are `security`, `compliance`, `transformation`, `quality of service`, and `troubleshooting`. For example: ```yaml metadata: labels: title: JSON Threat Protection description: Protects against malicious JSON in API requests. category: Security ``` `labels` are suggested but not required. ## Define Outbound Policies By default, PDK creates policies as inbound policies. To create an outbound policy, edit the `labels` section in the `gcl.yaml` file. Add the `metadata/capabilities/injectionPoint: outbound` label, for example: ```yaml metadata: labels: title: My Outbound Policy description: An outbound security policy category: Security metadata/capabilities/injectionPoint: outbound ``` ## Define Parameters To add parameters, edit the `spec.properties` section in the `gcl.yaml` file. For example: ```yaml properties: username: type: string password: type: string ``` After defining your properties, you can: - [Define Required Properties and Default Values](#define-required-properties-and-default-values) - [Define Supported Types](#define-supported-types) ### Define Required Properties and Default Values You can define each property listed in the `gcl.yaml` file as `required` and set a `default` value for the property. To define properties as required, list them in the `spec.required` object. For example, the following policy requires a `password` but not a `username`: ```yaml properties: username: type: string password: type: string required: - password ``` In the above configuration example, applying a policy without a password results in a failed configuration. The following example defines a default value for each property: ```yaml properties: username: type: string default: user1 password: type: string default: 12345678 required: - password ``` If you do not set a value for a required property when applying a policy, the property uses the default value. For non-required properties, the API Manager UI suggests the configured default value for properties. If you do not specify the value for non-required properties, the property is not configured. In the following configuration table, if the policy was applied in API Manager, `user2` would appear as a suggested value for `username` but is not configured if the value is omitted:

Policy Configuration

Effective Configuration

Configuration Status

{}

{"password": "12345678"}

Success

{"username": "user2"}

{"password": "12345678",
"username": "user2"}

Success

{"password": "password"}

{"password": "password"}

Success

{"password": "password",
"username": "user2"}

{"password": "password",
"username": "user2"}

Success

### Define Sensitive Data Protect sensitive data, such as passwords or certificates, by adding the `security:sensitive` characteristic: ```yaml properties: key: type: string default: "YourKey" "@context": { "@characteristics": [ "security:sensitive" ] } ``` When applying the policy, the input value to the sensitive parameter is not visible to the user: ![The character inputs to the key parameter appear as black dots.](/mulesoft/current/en-us/pdk/1.7/_images/sensitive-data.png) Toggling **Show** reveals any new data currently being entered. However, you cannot reveal previously stored data. For example, if you configure the example **Key** parameter and apply the policy, you cannot view the parameter if you edit the policy’s configuration in the future. ### Define Conditional Parameters Render policy configuration parameters dynamically by establishing conditions to make fields visible. In the following code example, the `encryptionKey` parameter appears if the user selects `true` for the `encryptBody` parameter: ```yaml properties: encryptBody: type: boolean default: false encryptionKey: type: string "@rendering": "@visibleOn": - property: encryptBody value: true ``` In the following code example, the `encryptionKey` parameter is initially visible and disappears if the user selects `false` for the for the `encryptBody` parameter: ```yaml properties: encryptBody: type: boolean default: true encryptionKey: type: string "@rendering": "@visibleOn": - property: encryptBody value: true ``` Conditional parameters have the following restrictions: - You can only define a single condition per parameter. - Only `string`, `boolean`, or `integer` parameters are supported as the condition parameter. - The conditionally rendered parameter cannot be an `object` or `enum`. - Required properties that are conditionally rendered must have a default value defined. In the above examples, if `encryptionKey` is required, it requires a default value. - Only root-level parameters support conditional rendering. Inner properties of arrays or objects do not support conditional rendering. ### Define Enumerated Parameters Limit user’s input values by defining parameters with the `enum` property, for example: ```yaml properties: signingMethod: type: string enum: - rsa - hmac ``` In the API Manager UI, `enum` parameters render as radio buttons for three or fewer enumerated values and as a dropdown field for more. For Flex Gateway running in Local Mode, the user must configure the parameter as one of the enumerated values or the policy configuration fails. Enumerated parameters don’t support the `@visibleOn` tag. To learn more about how to render variables dynamically, see [Define Conditional Parameters](#define-conditional-parameters). ### Define Supported Types Define a supported data type for each policy parameter to ensure the policy receives the correct data. The supported types are: String The string type specifies that the data is text. ```yaml properties: password: type: string ``` The `string` type also supports enables you to configure a `format` type. The supported formatting types are: - `dataweave`: Specifies the input parameter is a DataWeave variable and notifies Flex Gateway to transform the input. For more information about DataWeave expressions, see [Define DataWeave Expressions](#dataweave-expressions). - `service`: Specifies the input parameter is a URI and automatically creates a Flex Gateway service to enable HTTP calls from the policy. - `ipRange`: Specifies the expected text is a range of IPs and provides additional validation on the input. - `uri`: Specifies the expected text is a URI and provides additional validation on the input. Only use `uri` when the URI is not a service making HTTP calls from the policy. The following yaml snippet demonstrates all string formats: ```yaml properties: externalService: type: string format: service default: "https://auth-service:9000/login" token: type: string format: dataweave default: "#[splitBy(attributes.headers['Authorization'], ' ')[1]]" blockedIps: type: string format: ipRange default: "192.168.3.1/30" loginUrl: type: string format: uri default: "https://anypoint.mulesoft.com/login" ``` Number The `number` type specifies data as a floating point value. For example: ```yaml properties: squareRoot: type: number default: 1.414213562 seconds: type: number default: 10 ``` Integer The `integer` type specifies data as an integer value. For example: ```yaml properties: maxHeaders: type: integer default: 10 ``` Boolean The `boolean` type specifies data as a boolean value. Supported values are `true` or `false`. For example: ```yaml properties: skipValidation: type: boolean default: false requireCredentials: type: boolean default: true ``` Array The `array` type specifies the data as a list of ordered elements. For the `array` type, you must also specify `items.type` to specify the data type of the items in the array. For example: ```yaml properties: scopes: type: array items: type: string default: ["READ", "WRITE"] ``` Object The `object` type specifies the data as a list of ordered elements with multiple properties. For the `object` type, you must also specify `properties.type` for each element in the object. For example: ```yaml properties: user: type: object properties: id: type: string name: type: string required: - id - name default: { "id": "1", "name": "John Doe" } ``` ### Define DataWeave Expressions The `dataweave` format for `string` type parameters specifies the input parameter as a DataWeave expression. The `dataweave` variable supports the following expression bindings: ```yaml : type: string format: dataweave bindings: payload: mimeType: text attributes: true authentication: false vars: [] ``` - `payload`: The body of the incoming request. Define the `mimeType` as either `text`, `json`, or `xml` to set how to read the payload. By default, `mimeType` is set to `text`. If the `content-type` header is bound to the evaluator, then the payload is interpreted according to the value of the `content-type` header. To restrict the use of the `payload` variable, exclude the payload variable as shown in this example: ```yaml bindings: attributes: true authentication: false vars: [] ``` - `attributes`: Attributes, such as headers, of the incoming request. Set `attributes` to `true` to enable the policy to read the attributes of the incoming request. By default, `attributes` is set to `true`. - `authentication`: Authentication information of the incoming request. Set `authentication` to `true` to enable the policy to read authentication details of the incoming request. By default, `authentication` is set to `false`. - `vars`: Specifies the names of the variables that are available for the policy to use. By default, `vars` is empty. When the policy is applied, if the user inputs a variable that is not defined in the schema, the policy evaluates the variable as `null`. For more information about the supported expression bindings, see [Predefined Variables](https://docs.mulesoft.com/dataweave/latest/dataweave-variables-context). If the user’s expression contains bindings that are not defined in the policy’s schema when applying the policy, the policy configuration fails. For example, if the user expression is `[authentication.principal]` and `authentication` is not set to `true`, an error similar to the following occurs: test-local-flex-1 | \[flex-gateway-envoy\]\[error\] wasm log main: \[policy: ingress-http-jwt-auth-v1-0-impl-1.default\]\[api: ingress-http.default.svc\] Launcher problem: Failed to parse configuration '{"dw":"P\[\[\\".\\", \\"0-24\\", \[\\":ref\\", \\"0-14\\", \\"authentication\\"\], \[\\":str\\", \\"15-24\\", \\"principal\\"\]\], \\"#\[authentication.principal\]\\"\]"}'. Cause: Error compiling expression: Unknown symbol \`authentication\` at line 1 column 141 When evaluating the DataWeave expression in your policy, you must provide the script to resolve the expression. To learn how to implement DataWeave expressions in your Rust source code, see [Implement DataWeave Expressions](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features#use-dataweave-expressions). For more information about DataWeave support for Flex Gateway, see [DataWeave Support in Omni Gateway Policies](https://docs.mulesoft.com/gateway/latest/policies-dataweave-support). ## Use Custom Parameters in Rust Source Code After you modify the `gcl.yaml` file, run one of the following commands to propagate the changes to the `src/generated/config.rs` rust file and the JSON schema for the API Manager UI: - `make build-asset-files` only propagates the changes to `src/generated/config.rs`. ```cmd make build-asset-files ``` - `make build` propagates the changes to `src/generated/config.rs` and generates the policy’s target files. Do not run `make build` if you do not want to override your policy’s target file: ```cmd make build ``` For more information about compiling your policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-compile-policies). Properties defined in the `gcl.yaml` files are mapped to the Rust data types in the `config.rs` Rust file as follows:
gcl.yamlconfig.rs

string

String

uri string

String

ipRange string

String

dataweave string

pdk::script::Script

number

f64

integer

i64

boolean

bool

array

vec containing the specified item type

object

struct containing the specified property types

> [!IMPORTANT] If a parameter in `gcl.yaml` is not defined as ‘required’, the parameter’s > counterpart in the `config.rs` is wrapped in an ‘Option’ object. > > Validate that the parameter is present before unwrapping. Unwrapping a parameter that is not > present may cause a `panic!`. > > Use one of the following validation examples to ensure the parameter is present: > > - `if let Some(val) = myValue` > > - `if myValue.is_some() {myValue.unwrap()}` For example, the following `gcl.yaml` files produces the following `struct` in `config.rs`: 1. `gcl.yaml`: ```yaml properties: tokenExtractor: type: string format: dataweave default: "#[dw::core::Strings::substringAfter(attributes.headers['Authorization'], 'Bearer ')]" reject_missing_tokens: type: boolean max_chars: type: number required: - tokenExtractor ``` 2. `config.rs`: ```rust pub struct Config { #[serde(alias = "max_chars")] pub max_chars: Option, #[serde(alias = "reject_missing_tokens")] pub reject_missing_tokens: Option, #[serde(alias = "tokenExtractor")] pub token_extractor: pdk::script::Script, } ``` For example, you can access the values in `struct Config` with the following `.operators` in the `entrypoint` function: ```rust #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration,) -> Result<(), LaunchError> { let config: Config = serde_json::from_slice(&configuration)?; match config.reject_missing_tokens { ``` ## See Also - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.7/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Defining a Policy Schema Definition > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Similar to the policies listed in the [Inbound Policies Directory](https://docs.mulesoft.com/gateway/latest/policies-included-directory), custom policies have configuration parameters. Use the configuration parameters to improve the usability of your custom policy and support a wider range of API configurations. To define custom configuration parameters, edit the `definition/gcl.yaml` file. The `gcl.yaml` file is written in the Gateway Configuration Language (GCL). However, you do not need prior GCL knowledge to use this tutorial. The configuration parameters you define in the `gcl.yaml` appear as variables in the `src/generated/config.rs` file after you run the `make build-asset-file` command. You set any user input you need for implementing the Rust source code in the `gcl.yaml` file. Configuration parameters appear in the API Manager UI when applying a policy to Omni Gateway running in Connected Mode. When applying the policy to Omni Gateway running in Local Mode, it is your responsibility to distribute a configuration `yaml` file for your policy. The default `gcl.yaml` file has the following content: ```yaml apiVersion: gateway.mulesoft.com.v1alpha1 kind: Extension metadata: labels: title: my-custom-policy category: Custom spec: extends: - name: extension-definition properties: stringProperty: type: string ``` The `gcl.yaml` file contains two sections: - `metadata`: Defines information about the policy - `properties`: Defines the policy’s configuration parameters To define a schema definition: 1. [Define Metadata](#define-metadata) 2. [Define Parameters](#define-parameters) 3. [Use Custom Parameters in Rust Source Code](#use-custom-parameters-in-rust-source-code) ## Define Metadata Add labels in the metadata section to enrich the data shown in the UI when applying the policy. To define the metadata, edit the `metadata` in the `gcl.yaml` file. The supported labels are: - `title`: The policy name that appears in the UI. - `description`: A brief explanation of the policy’s behavior. - `category`: The category the of the policy. The possible categories are `security`, `compliance`, `transformation`, `quality of service`, and `troubleshooting`. For example: ```yaml metadata: labels: title: JSON Threat Protection description: Protects against malicious JSON in API requests. category: Security ``` `labels` are suggested but not required. ## Define Outbound Policies By default, PDK creates policies as inbound policies. To create an outbound policy, edit the `labels` section in the `gcl.yaml` file. Add the `metadata/capabilities/injectionPoint: outbound` label, for example: ```yaml metadata: labels: title: My Outbound Policy description: An outbound security policy category: Security metadata/capabilities/injectionPoint: outbound ``` ## Define Parameters To add parameters, edit the `spec.properties` section in the `gcl.yaml` file. For example: ```yaml properties: username: type: string password: type: string ``` After defining your properties, you can: - [Define Required Properties and Default Values](#define-required-properties-and-default-values) - [Define Supported Types](#define-supported-types) ### Define Required Properties and Default Values You can define each property listed in the `gcl.yaml` file as `required` and set a `default` value for the property. To define properties as required, list them in the `spec.required` object. For example, the following policy requires a `password` but not a `username`: ```yaml properties: username: type: string password: type: string required: - password ``` In the above configuration example, applying a policy without a password results in a failed configuration. The following example defines a default value for each property: ```yaml properties: username: type: string default: user1 password: type: string default: 12345678 required: - password ``` If you do not set a value for a required property when applying a policy, the property uses the default value. For non-required properties, the API Manager UI suggests the configured default value for properties. If you do not specify the value for non-required properties, the property is not configured. In the following configuration table, if the policy was applied in API Manager, `user2` would appear as a suggested value for `username` but is not configured if the value is omitted:

Policy Configuration

Effective Configuration

Configuration Status

{}

{"password": "12345678"}

Success

{"username": "user2"}

{"password": "12345678",
"username": "user2"}

Success

{"password": "password"}

{"password": "password"}

Success

{"password": "password",
"username": "user2"}

{"password": "password",
"username": "user2"}

Success

### Define Sensitive Data Protect sensitive data, such as passwords or certificates, by adding the `security:sensitive` characteristic: ```yaml properties: key: type: string default: "YourKey" "@context": { "@characteristics": [ "security:sensitive" ] } ``` When applying the policy, the input value to the sensitive parameter is not visible to the user: ![The character inputs to the key parameter appear as black dots.](/mulesoft/current/en-us/pdk/1.8/_images/sensitive-data.png) Toggling **Show** reveals any new data currently being entered. However, you cannot reveal previously stored data. For example, if you configure the example **Key** parameter and apply the policy, you cannot view the parameter if you edit the policy’s configuration in the future. ### Define Conditional Parameters Render policy configuration parameters dynamically by establishing conditions to make fields visible. In the following code example, the `encryptionKey` parameter appears if the user selects `true` for the `encryptBody` parameter: ```yaml properties: encryptBody: type: boolean default: false encryptionKey: type: string "@rendering": "@visibleOn": - property: encryptBody value: true ``` In the following code example, the `encryptionKey` parameter is initially visible and disappears if the user selects `false` for the for the `encryptBody` parameter: ```yaml properties: encryptBody: type: boolean default: true encryptionKey: type: string "@rendering": "@visibleOn": - property: encryptBody value: true ``` Conditional parameters have the following restrictions: - You can only define a single condition per parameter. - Only `string`, `boolean`, or `integer` parameters are supported as the condition parameter. - The conditionally rendered parameter cannot be an `object` or `enum`. - Required properties that are conditionally rendered must have a default value defined. In the above examples, if `encryptionKey` is required, it requires a default value. - Only root-level parameters support conditional rendering. Inner properties of arrays or objects do not support conditional rendering. ### Define Enumerated Parameters Limit user’s input values by defining parameters with the `enum` property, for example: ```yaml properties: signingMethod: type: string enum: - rsa - hmac ``` In the API Manager UI, `enum` parameters render as radio buttons for three or fewer enumerated values and as a dropdown field for more. For Omni Gateway running in Local Mode, the user must configure the parameter as one of the enumerated values or the policy configuration fails. Enumerated parameters don’t support the `@visibleOn` tag. To learn more about how to render variables dynamically, see [Define Conditional Parameters](#define-conditional-parameters). ### Define Supported Types Define a supported data type for each policy parameter to ensure the policy receives the correct data. The supported types are: String The string type specifies that the data is text. ```yaml properties: password: type: string ``` The `string` type also supports enables you to configure a `format` type. The supported formatting types are: - `dataweave`: Specifies the input parameter is a DataWeave variable and notifies Omni Gateway to transform the input. For more information about DataWeave expressions, see [Define DataWeave Expressions](#dataweave-expressions). - `service`: Specifies the input parameter is a URI and automatically creates an Omni Gateway service to enable HTTP calls from the policy. - `ipRange`: Specifies the expected text is a range of IPs and provides additional validation on the input. - `uri`: Specifies the expected text is a URI and provides additional validation on the input. Only use `uri` when the URI is not a service making HTTP calls from the policy. The following yaml snippet demonstrates all string formats: ```yaml properties: externalService: type: string format: service default: "https://auth-service:9000/login" token: type: string format: dataweave default: "#[splitBy(attributes.headers['Authorization'], ' ')[1]]" blockedIps: type: string format: ipRange default: "192.168.3.1/30" loginUrl: type: string format: uri default: "https://anypoint.mulesoft.com/login" ``` Number The `number` type specifies data as a floating point value. For example: ```yaml properties: squareRoot: type: number default: 1.414213562 seconds: type: number default: 10 ``` Integer The `integer` type specifies data as an integer value. For example: ```yaml properties: maxHeaders: type: integer default: 10 ``` Boolean The `boolean` type specifies data as a boolean value. Supported values are `true` or `false`. For example: ```yaml properties: skipValidation: type: boolean default: false requireCredentials: type: boolean default: true ``` Array The `array` type specifies the data as a list of ordered elements. For the `array` type, you must also specify `items.type` to specify the data type of the items in the array. For example: ```yaml properties: scopes: type: array items: type: string default: ["READ", "WRITE"] ``` Object The `object` type specifies the data as a list of ordered elements with multiple properties. For the `object` type, you must also specify `properties.type` for each element in the object. For example: ```yaml properties: user: type: object properties: id: type: string name: type: string required: - id - name default: { "id": "1", "name": "John Doe" } ``` ### Define DataWeave Expressions The `dataweave` format for `string` type parameters specifies the input parameter as a DataWeave expression. The `dataweave` variable supports the following expression bindings: ```yaml : type: string format: dataweave bindings: payload: mimeType: text attributes: true authentication: false vars: [] ``` - `payload`: The body of the incoming request. Define the `mimeType` as either `text`, `json`, or `xml` to set how to read the payload. By default, `mimeType` is set to `text`. If the `content-type` header is bound to the evaluator, then the payload is interpreted according to the value of the `content-type` header. To restrict the use of the `payload` variable, exclude the payload variable as shown in this example: ```yaml bindings: attributes: true authentication: false vars: [] ``` - `attributes`: Attributes, such as headers, of the incoming request. Set `attributes` to `true` to enable the policy to read the attributes of the incoming request. By default, `attributes` is set to `true`. - `authentication`: Authentication information of the incoming request. Set `authentication` to `true` to enable the policy to read authentication details of the incoming request. By default, `authentication` is set to `false`. - `vars`: Specifies the names of the variables that are available for the policy to use. By default, `vars` is empty. When the policy is applied, if the user inputs a variable that is not defined in the schema, the policy evaluates the variable as `null`. For more information about the supported expression bindings, see [Predefined Variables](https://docs.mulesoft.com/dataweave/latest/dataweave-variables-context). If the user’s expression contains bindings that are not defined in the policy’s schema when applying the policy, the policy configuration fails. For example, if the user expression is `[authentication.principal]` and `authentication` is not set to `true`, an error similar to the following occurs: test-local-flex-1 | \[flex-gateway-envoy\]\[error\] wasm log main: \[policy: ingress-http-jwt-auth-v1-0-impl-1.default\]\[api: ingress-http.default.svc\] Launcher problem: Failed to parse configuration '{"dw":"P\[\[\\".\\", \\"0-24\\", \[\\":ref\\", \\"0-14\\", \\"authentication\\"\], \[\\":str\\", \\"15-24\\", \\"principal\\"\]\], \\"#\[authentication.principal\]\\"\]"}'. Cause: Error compiling expression: Unknown symbol \`authentication\` at line 1 column 141 When evaluating the DataWeave expression in your policy, you must provide the script to resolve the expression. To learn how to implement DataWeave expressions in your Rust source code, see [Implement DataWeave Expressions](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features#use-dataweave-expressions). For more information about DataWeave support for Omni Gateway, see [DataWeave Support in Omni Gateway Policies](https://docs.mulesoft.com/gateway/latest/policies-dataweave-support). ## Use Custom Parameters in Rust Source Code After you modify the `gcl.yaml` file, run one of the following commands to propagate the changes to the `src/generated/config.rs` rust file and the JSON schema for the API Manager UI: - `make build-asset-files` only propagates the changes to `src/generated/config.rs`. ```cmd make build-asset-files ``` - `make build` propagates the changes to `src/generated/config.rs` and generates the policy’s target files. Do not run `make build` if you do not want to override your policy’s target file: ```cmd make build ``` For more information about compiling your policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-compile-policies). Properties defined in the `gcl.yaml` files are mapped to the Rust data types in the `config.rs` Rust file as follows:
gcl.yamlconfig.rs

string

String

uri string

String

ipRange string

String

dataweave string

pdk::script::Script

number

f64

integer

i64

boolean

bool

array

vec containing the specified item type

object

struct containing the specified property types

> [!IMPORTANT] If a parameter in `gcl.yaml` is not defined as ‘required’, the parameter’s > counterpart in the `config.rs` is wrapped in an ‘Option’ object. > > Validate that the parameter is present before unwrapping. Unwrapping a parameter that is not > present may cause a `panic!`. > > Use one of the following validation examples to ensure the parameter is present: > > - `if let Some(val) = myValue` > > - `if myValue.is_some() {myValue.unwrap()}` For example, the following `gcl.yaml` files produces the following `struct` in `config.rs`: 1. `gcl.yaml`: ```yaml properties: tokenExtractor: type: string format: dataweave default: "#[dw::core::Strings::substringAfter(attributes.headers['Authorization'], 'Bearer ')]" reject_missing_tokens: type: boolean max_chars: type: number required: - tokenExtractor ``` 2. `config.rs`: ```rust pub struct Config { #[serde(alias = "max_chars")] pub max_chars: Option, #[serde(alias = "reject_missing_tokens")] pub reject_missing_tokens: Option, #[serde(alias = "tokenExtractor")] pub token_extractor: pdk::script::Script, } ``` For example, you can access the values in `struct Config` with the following `.operators` in the `entrypoint` function: ```rust #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration,) -> Result<(), LaunchError> { let config: Config = serde_json::from_slice(&configuration)?; match config.reject_missing_tokens { ``` ## See Also - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.8/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Defining a Policy Schema Definition > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Similar to the policies listed in the [Inbound Policies Directory](https://docs.mulesoft.com/gateway/latest/policies-included-directory), custom policies have configuration parameters. Use the configuration parameters to improve the usability of your custom policy and support a wider range of API configurations. To define custom configuration parameters, edit the `definition/gcl.yaml` file. The `gcl.yaml` file is written in the Gateway Configuration Language (GCL). However, you do not need prior GCL knowledge to use this tutorial. The configuration parameters you define in the `gcl.yaml` appear as variables in the `src/generated/config.rs` file after you run the `make build-asset-file` command. You set any user input you need for implementing the Rust source code in the `gcl.yaml` file. Configuration parameters appear in the API Manager UI when applying a policy to Omni Gateway running in Connected Mode. When applying the policy to Omni Gateway running in Local Mode, it is your responsibility to distribute a configuration `yaml` file for your policy. The default `gcl.yaml` file has the following content: ```yaml apiVersion: gateway.mulesoft.com.v1alpha1 kind: Extension metadata: labels: title: my-custom-policy category: Custom spec: extends: - name: extension-definition properties: stringProperty: type: string ``` The `gcl.yaml` file contains two sections: - `metadata`: Defines information about the policy - `properties`: Defines the policy’s configuration parameters To define a schema definition: 1. [Define Metadata](#define-metadata) 2. [Define Parameters](#define-parameters) 3. [Use Custom Parameters in Rust Source Code](#use-custom-parameters-in-rust-source-code) ## Define Metadata Add labels in the metadata section to enrich the data shown in the UI when applying the policy. To define the metadata, edit the `metadata` in the `gcl.yaml` file. The supported labels are: - `title`: The policy name that appears in the UI. - `description`: A brief explanation of the policy’s behavior. - `category`: The category the of the policy. The possible categories are `security`, `compliance`, `transformation`, `quality of service`, and `troubleshooting`. For example: ```yaml metadata: labels: title: JSON Threat Protection description: Protects against malicious JSON in API requests. category: Security ``` `labels` are suggested but not required. ## Define Outbound Policies By default, PDK creates policies as inbound policies. To create an outbound policy, edit the `labels` section in the `gcl.yaml` file. Add the `metadata/capabilities/injectionPoint: outbound` label, for example: ```yaml metadata: labels: title: My Outbound Policy description: An outbound security policy category: Security metadata/capabilities/injectionPoint: outbound ``` ## Define Parameters To add parameters, edit the `spec.properties` section in the `gcl.yaml` file. For example: ```yaml properties: username: type: string password: type: string ``` After defining your properties, you can: - [Define Required Properties and Default Values](#define-required-properties-and-default-values) - [Define Supported Types](#define-supported-types) ### Define Required Properties and Default Values You can define each property listed in the `gcl.yaml` file as `required` and set a `default` value for the property. To define properties as required, list them in the `spec.required` object. For example, the following policy requires a `password` but not a `username`: ```yaml properties: username: type: string password: type: string required: - password ``` In the above configuration example, applying a policy without a password results in a failed configuration. The following example defines a default value for each property: ```yaml properties: username: type: string default: user1 password: type: string default: 12345678 required: - password ``` If you do not set a value for a required property when applying a policy, the property uses the default value. For non-required properties, the API Manager UI suggests the configured default value for properties. If you do not specify the value for non-required properties, the property is not configured. In the following configuration table, if the policy was applied in API Manager, `user2` would appear as a suggested value for `username` but is not configured if the value is omitted:

Policy Configuration

Effective Configuration

Configuration Status

{}

{"password": "12345678"}

Success

{"username": "user2"}

{"password": "12345678",
"username": "user2"}

Success

{"password": "password"}

{"password": "password"}

Success

{"password": "password",
"username": "user2"}

{"password": "password",
"username": "user2"}

Success

### Define Sensitive Data Protect sensitive data, such as passwords or certificates, by adding the `security:sensitive` characteristic: ```yaml properties: key: type: string default: "YourKey" "@context": { "@characteristics": [ "security:sensitive" ] } ``` When applying the policy, the input value to the sensitive parameter is not visible to the user: ![The character inputs to the key parameter appear as black dots.](/mulesoft/current/en-us/pdk/1.9/_images/sensitive-data.png) Toggling **Show** reveals any new data currently being entered. However, you cannot reveal previously stored data. For example, if you configure the example **Key** parameter and apply the policy, you cannot view the parameter if you edit the policy’s configuration in the future. ### Define Conditional Parameters Render policy configuration parameters dynamically by establishing conditions to make fields visible. In the following code example, the `encryptionKey` parameter appears if the user selects `true` for the `encryptBody` parameter: ```yaml properties: encryptBody: type: boolean default: false encryptionKey: type: string "@rendering": "@visibleOn": - property: encryptBody value: true ``` In the following code example, the `encryptionKey` parameter is initially visible and disappears if the user selects `false` for the for the `encryptBody` parameter: ```yaml properties: encryptBody: type: boolean default: true encryptionKey: type: string "@rendering": "@visibleOn": - property: encryptBody value: true ``` Conditional parameters have the following restrictions: - You can only define a single condition per parameter. - Only `string`, `boolean`, or `integer` parameters are supported as the condition parameter. - The conditionally rendered parameter cannot be an `object` or `enum`. - Required properties that are conditionally rendered must have a default value defined. In the above examples, if `encryptionKey` is required, it requires a default value. - Only root-level parameters support conditional rendering. Inner properties of arrays or objects do not support conditional rendering. ### Define Enumerated Parameters Limit user’s input values by defining parameters with the `enum` property, for example: ```yaml properties: signingMethod: type: string enum: - rsa - hmac ``` In the API Manager UI, `enum` parameters render as radio buttons for three or fewer enumerated values and as a dropdown field for more. For Omni Gateway running in Local Mode, the user must configure the parameter as one of the enumerated values or the policy configuration fails. Enumerated parameters don’t support the `@visibleOn` tag. To learn more about how to render variables dynamically, see [Define Conditional Parameters](#define-conditional-parameters). ### Define Supported Types Define a supported data type for each policy parameter to ensure the policy receives the correct data. The supported types are: String The string type specifies that the data is text. ```yaml properties: password: type: string ``` The `string` type also supports enables you to configure a `format` type. The supported formatting types are: - `dataweave`: Specifies the input parameter is a DataWeave variable and notifies Omni Gateway to transform the input. For more information about DataWeave expressions, see [Define DataWeave Expressions](#dataweave-expressions). - `service`: Specifies the input parameter is a URI and automatically creates an Omni Gateway service to enable HTTP calls from the policy. - `ipRange`: Specifies the expected text is a range of IPs and provides additional validation on the input. - `uri`: Specifies the expected text is a URI and provides additional validation on the input. Only use `uri` when the URI is not a service making HTTP calls from the policy. The following yaml snippet demonstrates all string formats: ```yaml properties: externalService: type: string format: service default: "https://auth-service:9000/login" token: type: string format: dataweave default: "#[splitBy(attributes.headers['Authorization'], ' ')[1]]" blockedIps: type: string format: ipRange default: "192.168.3.1/30" loginUrl: type: string format: uri default: "https://anypoint.mulesoft.com/login" ``` Number The `number` type specifies data as a floating point value. For example: ```yaml properties: squareRoot: type: number default: 1.414213562 seconds: type: number default: 10 ``` Integer The `integer` type specifies data as an integer value. For example: ```yaml properties: maxHeaders: type: integer default: 10 ``` Boolean The `boolean` type specifies data as a boolean value. Supported values are `true` or `false`. For example: ```yaml properties: skipValidation: type: boolean default: false requireCredentials: type: boolean default: true ``` Array The `array` type specifies the data as a list of ordered elements. For the `array` type, you must also specify `items.type` to specify the data type of the items in the array. For example: ```yaml properties: scopes: type: array items: type: string default: ["READ", "WRITE"] ``` Object The `object` type specifies the data as a list of ordered elements with multiple properties. For the `object` type, you must also specify `properties.type` for each element in the object. For example: ```yaml properties: user: type: object properties: id: type: string name: type: string required: - id - name default: { "id": "1", "name": "John Doe" } ``` ### Define DataWeave Expressions The `dataweave` format for `string` type parameters specifies the input parameter as a DataWeave expression. The `dataweave` variable supports the following expression bindings: ```yaml : type: string format: dataweave bindings: payload: mimeType: text attributes: true authentication: false vars: [] ``` - `payload`: The body of the incoming request. Define the `mimeType` as either `text`, `json`, or `xml` to set how to read the payload. By default, `mimeType` is set to `text`. If the `content-type` header is bound to the evaluator, then the payload is interpreted according to the value of the `content-type` header. To restrict the use of the `payload` variable, exclude the payload variable as shown in this example: ```yaml bindings: attributes: true authentication: false vars: [] ``` - `attributes`: Attributes, such as headers, of the incoming request. Set `attributes` to `true` to enable the policy to read the attributes of the incoming request. By default, `attributes` is set to `true`. - `authentication`: Authentication information of the incoming request. Set `authentication` to `true` to enable the policy to read authentication details of the incoming request. By default, `authentication` is set to `false`. - `vars`: Specifies the names of the variables that are available for the policy to use. By default, `vars` is empty. When the policy is applied, if the user inputs a variable that is not defined in the schema, the policy evaluates the variable as `null`. For more information about the supported expression bindings, see [Predefined Variables](https://docs.mulesoft.com/dataweave/latest/dataweave-variables-context). If the user’s expression contains bindings that are not defined in the policy’s schema when applying the policy, the policy configuration fails. For example, if the user expression is `[authentication.principal]` and `authentication` is not set to `true`, an error similar to the following occurs: test-local-flex-1 | \[flex-gateway-envoy\]\[error\] wasm log main: \[policy: ingress-http-jwt-auth-v1-0-impl-1.default\]\[api: ingress-http.default.svc\] Launcher problem: Failed to parse configuration '{"dw":"P\[\[\\".\\", \\"0-24\\", \[\\":ref\\", \\"0-14\\", \\"authentication\\"\], \[\\":str\\", \\"15-24\\", \\"principal\\"\]\], \\"#\[authentication.principal\]\\"\]"}'. Cause: Error compiling expression: Unknown symbol \`authentication\` at line 1 column 141 When evaluating the DataWeave expression in your policy, you must provide the script to resolve the expression. To learn how to implement DataWeave expressions in your Rust source code, see [Implement DataWeave Expressions](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features#use-dataweave-expressions). For more information about DataWeave support for Omni Gateway, see [DataWeave Support in Omni Gateway Policies](https://docs.mulesoft.com/gateway/latest/policies-dataweave-support). ## Use Custom Parameters in Rust Source Code After you modify the `gcl.yaml` file, run one of the following commands to propagate the changes to the `src/generated/config.rs` rust file and the JSON schema for the API Manager UI: - `make build-asset-files` only propagates the changes to `src/generated/config.rs`. ```cmd make build-asset-files ``` - `make build` propagates the changes to `src/generated/config.rs` and generates the policy’s target files. Do not run `make build` if you do not want to override your policy’s target file: ```cmd make build ``` For more information about compiling your policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-compile-policies). Properties defined in the `gcl.yaml` files are mapped to the Rust data types in the `config.rs` Rust file as follows:
gcl.yamlconfig.rs

string

String

uri string

String

ipRange string

String

dataweave string

pdk::script::Script

number

f64

integer

i64

boolean

bool

array

vec containing the specified item type

object

struct containing the specified property types

> [!IMPORTANT] If a parameter in `gcl.yaml` is not defined as ‘required’, the parameter’s > counterpart in the `config.rs` is wrapped in an ‘Option’ object. > > Validate that the parameter is present before unwrapping. Unwrapping a parameter that is not > present may cause a `panic!`. > > Use one of the following validation examples to ensure the parameter is present: > > - `if let Some(val) = myValue` > > - `if myValue.is_some() {myValue.unwrap()}` For example, the following `gcl.yaml` files produces the following `struct` in `config.rs`: 1. `gcl.yaml`: ```yaml properties: tokenExtractor: type: string format: dataweave default: "#[dw::core::Strings::substringAfter(attributes.headers['Authorization'], 'Bearer ')]" reject_missing_tokens: type: boolean max_chars: type: number required: - tokenExtractor ``` 2. `config.rs`: ```rust pub struct Config { #[serde(alias = "max_chars")] pub max_chars: Option, #[serde(alias = "reject_missing_tokens")] pub reject_missing_tokens: Option, #[serde(alias = "tokenExtractor")] pub token_extractor: pdk::script::Script, } ``` For example, you can access the values in `struct Config` with the following `.operators` in the `entrypoint` function: ```rust #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration,) -> Result<(), LaunchError> { let config: Config = serde_json::from_slice(&configuration)?; match config.reject_missing_tokens { ``` ## See Also - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.9/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Defining a Policy Schema Definition > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Similar to the policies listed in the [Inbound Policies Directory](https://docs.mulesoft.com/gateway/latest/policies-included-directory), custom policies have configuration parameters. Use the configuration parameters to improve the usability of your custom policy and support a wider range of API configurations. To define custom configuration parameters, edit the `definition/gcl.yaml` file. The `gcl.yaml` file is written in the Gateway Configuration Language (GCL). However, you do not need prior GCL knowledge to use this tutorial. The configuration parameters you define in the `gcl.yaml` appear as variables in the `src/generated/config.rs` file after you run the `make build-asset-file` command. You set any user input you need for implementing the Rust source code in the `gcl.yaml` file. Configuration parameters appear in the API Manager UI when applying a policy to Omni Gateway running in Connected Mode. When applying the policy to Omni Gateway running in Local Mode, it is your responsibility to distribute a configuration `yaml` file for your policy. The default `gcl.yaml` file has the following content: ```yaml apiVersion: gateway.mulesoft.com.v1alpha1 kind: Extension metadata: labels: title: my-custom-policy category: Custom spec: extends: - name: extension-definition properties: stringProperty: type: string ``` The `gcl.yaml` file contains two sections: - `metadata`: Defines information about the policy - `properties`: Defines the policy’s configuration parameters To define a schema definition: 1. [Define Metadata](#define-metadata) 2. [Define Parameters](#define-parameters) 3. [Use Custom Parameters in Rust Source Code](#use-custom-parameters-in-rust-source-code) ## Define Metadata Add labels in the metadata section to enrich the data shown in the UI when applying the policy. To define the metadata, edit the `metadata` in the `gcl.yaml` file. The supported labels are: - `title`: The policy name that appears in the UI. - `description`: A brief explanation of the policy’s behavior. - `category`: The category the of the policy. The possible categories are `security`, `compliance`, `transformation`, `quality of service`, and `troubleshooting`. For example: ```yaml metadata: labels: title: JSON Threat Protection description: Protects against malicious JSON in API requests. category: Security ``` `labels` are suggested but not required. ## Define Outbound Policies By default, PDK creates policies as inbound policies. To create an outbound policy, edit the `labels` section in the `gcl.yaml` file. Add the `metadata/capabilities/injectionPoint: outbound` label, for example: ```yaml metadata: labels: title: My Outbound Policy description: An outbound security policy category: Security metadata/capabilities/injectionPoint: outbound ``` ## Define Parameters To add parameters, edit the `spec.properties` section in the `gcl.yaml` file. For example: ```yaml properties: username: type: string password: type: string ``` After defining your properties, you can: - [Define Required Properties and Default Values](#define-required-properties-and-default-values) - [Define Supported Types](#define-supported-types) ### Define Required Properties and Default Values You can define each property listed in the `gcl.yaml` file as `required` and set a `default` value for the property. To define properties as required, list them in the `spec.required` object. For example, the following policy requires a `password` but not a `username`: ```yaml properties: username: type: string password: type: string required: - password ``` In the above configuration example, applying a policy without a password results in a failed configuration. The following example defines a default value for each property: ```yaml properties: username: type: string default: user1 password: type: string default: 12345678 required: - password ``` If you do not set a value for a required property when applying a policy, the property uses the default value. For non-required properties, the API Manager UI suggests the configured default value for properties. If you do not specify the value for non-required properties, the property is not configured. In the following configuration table, if the policy was applied in API Manager, `user2` would appear as a suggested value for `username` but is not configured if the value is omitted:

Policy Configuration

Effective Configuration

Configuration Status

{}

{"password": "12345678"}

Success

{"username": "user2"}

{"password": "12345678",
"username": "user2"}

Success

{"password": "password"}

{"password": "password"}

Success

{"password": "password",
"username": "user2"}

{"password": "password",
"username": "user2"}

Success

### Define Sensitive Data Protect sensitive data, such as passwords or certificates, by adding the `security:sensitive` characteristic: ```yaml properties: key: type: string default: "YourKey" "@context": { "@characteristics": [ "security:sensitive" ] } ``` When applying the policy, the input value to the sensitive parameter is not visible to the user: ![The character inputs to the key parameter appear as black dots.](/mulesoft/current/en-us/pdk/latest/_images/sensitive-data.png) Toggling **Show** reveals any new data currently being entered. However, you cannot reveal previously stored data. For example, if you configure the example **Key** parameter and apply the policy, you cannot view the parameter if you edit the policy’s configuration in the future. ### Define Conditional Parameters Render policy configuration parameters dynamically by establishing conditions to make fields visible. In the following code example, the `encryptionKey` parameter appears if the user selects `true` for the `encryptBody` parameter: ```yaml properties: encryptBody: type: boolean default: false encryptionKey: type: string "@rendering": "@visibleOn": - property: encryptBody value: true ``` In the following code example, the `encryptionKey` parameter is initially visible and disappears if the user selects `false` for the for the `encryptBody` parameter: ```yaml properties: encryptBody: type: boolean default: true encryptionKey: type: string "@rendering": "@visibleOn": - property: encryptBody value: true ``` Conditional parameters have the following restrictions: - You can only define a single condition per parameter. - Only `string`, `boolean`, or `integer` parameters are supported as the condition parameter. - The conditionally rendered parameter cannot be an `object` or `enum`. - Required properties that are conditionally rendered must have a default value defined. In the above examples, if `encryptionKey` is required, it requires a default value. - Only root-level parameters support conditional rendering. Inner properties of arrays or objects do not support conditional rendering. ### Define Enumerated Parameters Limit user’s input values by defining parameters with the `enum` property, for example: ```yaml properties: signingMethod: type: string enum: - rsa - hmac ``` In the API Manager UI, `enum` parameters render as radio buttons for three or fewer enumerated values and as a dropdown field for more. For Omni Gateway running in Local Mode, the user must configure the parameter as one of the enumerated values or the policy configuration fails. Enumerated parameters don’t support the `@visibleOn` tag. To learn more about how to render variables dynamically, see [Define Conditional Parameters](#define-conditional-parameters). ### Define Supported Types Define a supported data type for each policy parameter to ensure the policy receives the correct data. The supported types are: String The string type specifies that the data is text. ```yaml properties: password: type: string ``` The `string` type also supports enables you to configure a `format` type. The supported formatting types are: - `dataweave`: Specifies the input parameter is a DataWeave variable and notifies Omni Gateway to transform the input. For more information about DataWeave expressions, see [Define DataWeave Expressions](#dataweave-expressions). - `service`: Specifies the input parameter is a URI and automatically creates an Omni Gateway service to enable HTTP calls from the policy. - `ipRange`: Specifies the expected text is a range of IPs and provides additional validation on the input. - `uri`: Specifies the expected text is a URI and provides additional validation on the input. Only use `uri` when the URI is not a service making HTTP calls from the policy. The following yaml snippet demonstrates all string formats: ```yaml properties: externalService: type: string format: service default: "https://auth-service:9000/login" token: type: string format: dataweave default: "#[splitBy(attributes.headers['Authorization'], ' ')[1]]" blockedIps: type: string format: ipRange default: "192.168.3.1/30" loginUrl: type: string format: uri default: "https://anypoint.mulesoft.com/login" ``` Number The `number` type specifies data as a floating point value. For example: ```yaml properties: squareRoot: type: number default: 1.414213562 seconds: type: number default: 10 ``` Integer The `integer` type specifies data as an integer value. For example: ```yaml properties: maxHeaders: type: integer default: 10 ``` Boolean The `boolean` type specifies data as a boolean value. Supported values are `true` or `false`. For example: ```yaml properties: skipValidation: type: boolean default: false requireCredentials: type: boolean default: true ``` Array The `array` type specifies the data as a list of ordered elements. For the `array` type, you must also specify `items.type` to specify the data type of the items in the array. For example: ```yaml properties: scopes: type: array items: type: string default: ["READ", "WRITE"] ``` Object The `object` type specifies the data as a list of ordered elements with multiple properties. For the `object` type, you must also specify `properties.type` for each element in the object. For example: ```yaml properties: user: type: object properties: id: type: string name: type: string required: - id - name default: { "id": "1", "name": "John Doe" } ``` ### Define DataWeave Expressions The `dataweave` format for `string` type parameters specifies the input parameter as a DataWeave expression. The `dataweave` variable supports the following expression bindings: ```yaml : type: string format: dataweave bindings: payload: mimeType: text attributes: true authentication: false vars: [] ``` - `payload`: The body of the incoming request. Define the `mimeType` as either `text`, `json`, or `xml` to set how to read the payload. By default, `mimeType` is set to `text`. If the `content-type` header is bound to the evaluator, then the payload is interpreted according to the value of the `content-type` header. To restrict the use of the `payload` variable, exclude the payload variable as shown in this example: ```yaml bindings: attributes: true authentication: false vars: [] ``` - `attributes`: Attributes, such as headers, of the incoming request. Set `attributes` to `true` to enable the policy to read the attributes of the incoming request. By default, `attributes` is set to `true`. - `authentication`: Authentication information of the incoming request. Set `authentication` to `true` to enable the policy to read authentication details of the incoming request. By default, `authentication` is set to `false`. - `vars`: Specifies the names of the variables that are available for the policy to use. By default, `vars` is empty. When the policy is applied, if the user inputs a variable that is not defined in the schema, the policy evaluates the variable as `null`. For more information about the supported expression bindings, see [Predefined Variables](https://docs.mulesoft.com/dataweave/latest/dataweave-variables-context). If the user’s expression contains bindings that are not defined in the policy’s schema when applying the policy, the policy configuration fails. For example, if the user expression is `[authentication.principal]` and `authentication` is not set to `true`, an error similar to the following occurs: test-local-flex-1 | \[flex-gateway-envoy\]\[error\] wasm log main: \[policy: ingress-http-jwt-auth-v1-0-impl-1.default\]\[api: ingress-http.default.svc\] Launcher problem: Failed to parse configuration '{"dw":"P\[\[\\".\\", \\"0-24\\", \[\\":ref\\", \\"0-14\\", \\"authentication\\"\], \[\\":str\\", \\"15-24\\", \\"principal\\"\]\], \\"#\[authentication.principal\]\\"\]"}'. Cause: Error compiling expression: Unknown symbol \`authentication\` at line 1 column 141 When evaluating the DataWeave expression in your policy, you must provide the script to resolve the expression. To learn how to implement DataWeave expressions in your Rust source code, see [Implement DataWeave Expressions](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features#use-dataweave-expressions). For more information about DataWeave support for Omni Gateway, see [DataWeave Support in Omni Gateway Policies](https://docs.mulesoft.com/gateway/latest/policies-dataweave-support). ## Use Custom Parameters in Rust Source Code After you modify the `gcl.yaml` file, run one of the following commands to propagate the changes to the `src/generated/config.rs` rust file and the JSON schema for the API Manager UI: - `make build-asset-files` only propagates the changes to `src/generated/config.rs`. ```cmd make build-asset-files ``` - `make build` propagates the changes to `src/generated/config.rs` and generates the policy’s target files. Do not run `make build` if you do not want to override your policy’s target file: ```cmd make build ``` For more information about compiling your policy, see [Compiling Custom Policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-compile-policies). Properties defined in the `gcl.yaml` files are mapped to the Rust data types in the `config.rs` Rust file as follows:
gcl.yamlconfig.rs

string

String

uri string

String

ipRange string

String

dataweave string

pdk::script::Script

number

f64

integer

i64

boolean

bool

array

vec containing the specified item type

object

struct containing the specified property types

> [!IMPORTANT] If a parameter in `gcl.yaml` is not defined as ‘required’, the parameter’s > counterpart in the `config.rs` is wrapped in an ‘Option’ object. > > Validate that the parameter is present before unwrapping. Unwrapping a parameter that is not > present may cause a `panic!`. > > Use one of the following validation examples to ensure the parameter is present: > > - `if let Some(val) = myValue` > > - `if myValue.is_some() {myValue.unwrap()}` For example, the following `gcl.yaml` files produces the following `struct` in `config.rs`: 1. `gcl.yaml`: ```yaml properties: tokenExtractor: type: string format: dataweave default: "#[dw::core::Strings::substringAfter(attributes.headers['Authorization'], 'Bearer ')]" reject_missing_tokens: type: boolean max_chars: type: number required: - tokenExtractor ``` 2. `config.rs`: ```rust pub struct Config { #[serde(alias = "max_chars")] pub max_chars: Option, #[serde(alias = "reject_missing_tokens")] pub reject_missing_tokens: Option, #[serde(alias = "tokenExtractor")] pub token_extractor: pdk::script::Script, } ``` For example, you can access the values in `struct Config` with the following `.operators` in the `entrypoint` function: ```rust #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration,) -> Result<(), LaunchError> { let config: Config = serde_json::from_slice(&configuration)?; match config.reject_missing_tokens { ``` ## See Also - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/latest/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Developing Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt After installing the [Prerequisites](https://docs.mulesoft.com/pdk/1.2/policies-pdk-prerequisites), you can develop custom policies by using Flex Gateway Policy Development Kit (PDK). The custom policy lifecycle consists of all the steps of developing a custom policy that occur in PDK. The following steps do not include steps that occur outside of PDK, such as [applying a policy](https://docs.mulesoft.com/pdk/1.2/policies-pdk-apply-policies), which is the same for all Flex Gateway policies. After you [create a new project](https://docs.mulesoft.com/pdk/1.2/policies-pdk-create-project), you might iteratively complete some steps. For example, while writing the policy’s source code, you might need to return to [add additional parameters](https://docs.mulesoft.com/pdk/1.2/policies-pdk-create-schema-definition), or you might need to recompile the policy after debugging the source code. To create a custom policy with PDK, follow these steps: 1. [Create a new project](https://docs.mulesoft.com/pdk/1.2/policies-pdk-create-project). 2. [Define a schema definition](https://docs.mulesoft.com/pdk/1.2/policies-pdk-create-schema-definition). Modify the `definition/gcl.yaml` file to define metadata and configuration parameters for your custom policy. 3. [Configure custom policy features in Rust](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features). Use the rust code examples to implement your custom logic in the `src/lib.rs` file. 4. [Compile your custom policy](https://docs.mulesoft.com/pdk/1.2/policies-pdk-compile-policies). Compiling your policy creates the `WebAssembly` binary file and configuration files necessary to upload your policy to Exchange and deploy it to a Flex Gateway. 5. [Debug Your Policy with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.2/policies-pdk-debug-local). Use the playground provided with PDK to debug the functionality of your custom policy locally. 6. [Write Integration Tests](https://docs.mulesoft.com/pdk/1.2/policies-pdk-integration-tests). Write intergration tests to ensure your custom policy is compatible with your other services and to ensure that each new policy version does not introduce regression errors. 7. [Publish your policy on Exchange](https://docs.mulesoft.com/pdk/1.2/policies-pdk-publish-policies#publish). Publish your policy on Exchange to distribute a beta version of your policy for testing with your Flex Gateway configuration. To deploy a policy to Flex Gateway, see step 9. 8. [Release your policy on Exchange](https://docs.mulesoft.com/pdk/1.2/policies-pdk-publish-policies#release). Release your policy on Exchange to distribute a production-ready policy. 9. Deploy your custom policy to a production environment by [applying it to an API instance](https://docs.mulesoft.com/pdk/1.2/policies-pdk-apply-policies) deployed on Flex Gateway. 10. Configure a new version of this API instance by returning to step 2. --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Developing Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt After installing the [Prerequisites](https://docs.mulesoft.com/pdk/1.3/policies-pdk-prerequisites), you can develop custom policies by using Flex Gateway Policy Development Kit (PDK). The custom policy lifecycle consists of all the steps of developing a custom policy that occur in PDK. The following steps do not include steps that occur outside of PDK, such as [applying a policy](https://docs.mulesoft.com/pdk/1.3/policies-pdk-apply-policies), which is the same for all Flex Gateway policies. After you [create a new project](https://docs.mulesoft.com/pdk/1.3/policies-pdk-create-project), you might iteratively complete some steps. For example, while writing the policy’s source code, you might need to return to [add additional parameters](https://docs.mulesoft.com/pdk/1.3/policies-pdk-create-schema-definition), or you might need to recompile the policy after debugging the source code. To create a custom policy with PDK, follow these steps: 1. [Create a new project](https://docs.mulesoft.com/pdk/1.3/policies-pdk-create-project). 2. [Define a schema definition](https://docs.mulesoft.com/pdk/1.3/policies-pdk-create-schema-definition). Modify the `definition/gcl.yaml` file to define metadata and configuration parameters for your custom policy. 3. [Configure custom policy features in Rust](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features). Use the rust code examples to implement your custom logic in the `src/lib.rs` file. 4. [Compile your custom policy](https://docs.mulesoft.com/pdk/1.3/policies-pdk-compile-policies). Compiling your policy creates the `WebAssembly` binary file and configuration files necessary to upload your policy to Exchange and deploy it to a Flex Gateway. 5. [Debug Your Policy with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.3/policies-pdk-debug-local). Use the playground provided with PDK to debug the functionality of your custom policy locally. 6. [Write Integration Tests](https://docs.mulesoft.com/pdk/1.3/policies-pdk-integration-tests). Write intergration tests to ensure your custom policy is compatible with your other services and to ensure that each new policy version does not introduce regression errors. 7. [Publish your policy on Exchange](https://docs.mulesoft.com/pdk/1.3/policies-pdk-publish-policies#publish). Publish your policy on Exchange to distribute a beta version of your policy for testing with your Flex Gateway configuration. To deploy a policy to Flex Gateway, see step 9. 8. [Release your policy on Exchange](https://docs.mulesoft.com/pdk/1.3/policies-pdk-publish-policies#release). Release your policy on Exchange to distribute a production-ready policy. 9. Deploy your custom policy to a production environment by [applying it to an API instance](https://docs.mulesoft.com/pdk/1.3/policies-pdk-apply-policies) deployed on Flex Gateway. 10. Configure a new version of this API instance by returning to step 2. --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Developing Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt After installing the [Prerequisites](https://docs.mulesoft.com/pdk/1.4/policies-pdk-prerequisites), you can develop custom policies by using Flex Gateway Policy Development Kit (PDK). The custom policy lifecycle consists of all the steps of developing a custom policy that occur in PDK. The following steps do not include steps that occur outside of PDK, such as [applying a policy](https://docs.mulesoft.com/pdk/1.4/policies-pdk-apply-policies), which is the same for all Flex Gateway policies. After you [create a new project](https://docs.mulesoft.com/pdk/1.4/policies-pdk-create-project), you might iteratively complete some steps. For example, while writing the policy’s source code, you might need to return to [add additional parameters](https://docs.mulesoft.com/pdk/1.4/policies-pdk-create-schema-definition), or you might need to recompile the policy after debugging the source code. To create a custom policy with PDK, follow these steps: 1. [Create a new project](https://docs.mulesoft.com/pdk/1.4/policies-pdk-create-project). 2. [Define a schema definition](https://docs.mulesoft.com/pdk/1.4/policies-pdk-create-schema-definition). Modify the `definition/gcl.yaml` file to define metadata and configuration parameters for your custom policy. 3. [Configure custom policy features in Rust](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features). Use the rust code examples to implement your custom logic in the `src/lib.rs` file. 4. [Compile your custom policy](https://docs.mulesoft.com/pdk/1.4/policies-pdk-compile-policies). Compiling your policy creates the `WebAssembly` binary file and configuration files necessary to upload your policy to Exchange and deploy it to a Flex Gateway. 5. [Debug Your Policy with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.4/policies-pdk-debug-local). Use the playground provided with PDK to debug the functionality of your custom policy locally. 6. [Write Integration Tests](https://docs.mulesoft.com/pdk/1.4/policies-pdk-integration-tests). Write intergration tests to ensure your custom policy is compatible with your other services and to ensure that each new policy version does not introduce regression errors. 7. [Publish your policy on Exchange](https://docs.mulesoft.com/pdk/1.4/policies-pdk-publish-policies#publish). Publish your policy on Exchange to distribute a beta version of your policy for testing with your Flex Gateway configuration. To deploy a policy to Flex Gateway, see step 9. 8. [Release your policy on Exchange](https://docs.mulesoft.com/pdk/1.4/policies-pdk-publish-policies#release). Release your policy on Exchange to distribute a production-ready policy. 9. Deploy your custom policy to a production environment by [applying it to an API instance](https://docs.mulesoft.com/pdk/1.4/policies-pdk-apply-policies) deployed on Flex Gateway. 10. Configure a new version of this API instance by returning to step 2. --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Developing Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt After installing the [Prerequisites](https://docs.mulesoft.com/pdk/1.5/policies-pdk-prerequisites), you can develop custom policies by using Flex Gateway Policy Development Kit (PDK). The custom policy lifecycle consists of all the steps of developing a custom policy that occur in PDK. The following steps do not include steps that occur outside of PDK, such as [applying a policy](https://docs.mulesoft.com/pdk/1.5/policies-pdk-apply-policies), which is the same for all Flex Gateway policies. After you [create a new project](https://docs.mulesoft.com/pdk/1.5/policies-pdk-create-project), you might iteratively complete some steps. For example, while writing the policy’s source code, you might need to return to [add additional parameters](https://docs.mulesoft.com/pdk/1.5/policies-pdk-create-schema-definition), or you might need to recompile the policy after debugging the source code. To create a custom policy with PDK, follow these steps: 1. [Create a new project](https://docs.mulesoft.com/pdk/1.5/policies-pdk-create-project). 2. [Define a schema definition](https://docs.mulesoft.com/pdk/1.5/policies-pdk-create-schema-definition). Modify the `definition/gcl.yaml` file to define metadata and configuration parameters for your custom policy. 3. [Configure custom policy features in Rust](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features). Use the rust code examples to implement your custom logic in the `src/lib.rs` file. 4. [Compile your custom policy](https://docs.mulesoft.com/pdk/1.5/policies-pdk-compile-policies). Compiling your policy creates the `WebAssembly` binary file and configuration files necessary to upload your policy to Exchange and deploy it to a Flex Gateway. 5. [Debug Your Policy with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.5/policies-pdk-debug-local). Use the playground provided with PDK to debug the functionality of your custom policy locally. 6. [Write Integration Tests](https://docs.mulesoft.com/pdk/1.5/policies-pdk-integration-tests). Write intergration tests to ensure your custom policy is compatible with your other services and to ensure that each new policy version does not introduce regression errors. 7. [Publish your policy on Exchange](https://docs.mulesoft.com/pdk/1.5/policies-pdk-publish-policies#publish). Publish your policy on Exchange to distribute a beta version of your policy for testing with your Flex Gateway configuration. To deploy a policy to Flex Gateway, see step 9. 8. [Release your policy on Exchange](https://docs.mulesoft.com/pdk/1.5/policies-pdk-publish-policies#release). Release your policy on Exchange to distribute a production-ready policy. 9. Deploy your custom policy to a production environment by [applying it to an API instance](https://docs.mulesoft.com/pdk/1.5/policies-pdk-apply-policies) deployed on Flex Gateway. 10. Configure a new version of this API instance by returning to step 2. --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Developing Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt After installing the [Prerequisites](https://docs.mulesoft.com/pdk/1.6/policies-pdk-prerequisites), you can develop custom policies by using Flex Gateway Policy Development Kit (PDK). The custom policy lifecycle consists of all the steps of developing a custom policy that occur in PDK. The following steps do not include steps that occur outside of PDK, such as [applying a policy](https://docs.mulesoft.com/pdk/1.6/policies-pdk-apply-policies), which is the same for all Flex Gateway policies. After you [create a new project](https://docs.mulesoft.com/pdk/1.6/policies-pdk-create-project), you might iteratively complete some steps. For example, while writing the policy’s source code, you might need to return to [add additional parameters](https://docs.mulesoft.com/pdk/1.6/policies-pdk-create-schema-definition), or you might need to recompile the policy after debugging the source code. To create a custom policy with PDK, follow these steps: 1. [Create a new project](https://docs.mulesoft.com/pdk/1.6/policies-pdk-create-project). 2. [Define a schema definition](https://docs.mulesoft.com/pdk/1.6/policies-pdk-create-schema-definition). Modify the `definition/gcl.yaml` file to define metadata and configuration parameters for your custom policy. 3. [Configure custom policy features in Rust](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features). Use the rust code examples to implement your custom logic in the `src/lib.rs` file. 4. [Compile your custom policy](https://docs.mulesoft.com/pdk/1.6/policies-pdk-compile-policies). Compiling your policy creates the `WebAssembly` binary file and configuration files necessary to upload your policy to Exchange and deploy it to a Flex Gateway. 5. [Debug Your Policy with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.6/policies-pdk-debug-local). Use the playground provided with PDK to debug the functionality of your custom policy locally. 6. [Write Integration Tests](https://docs.mulesoft.com/pdk/1.6/policies-pdk-integration-tests). Write intergration tests to ensure your custom policy is compatible with your other services and to ensure that each new policy version does not introduce regression errors. 7. [Publish your policy on Exchange](https://docs.mulesoft.com/pdk/1.6/policies-pdk-publish-policies#publish). Publish your policy on Exchange to distribute a beta version of your policy for testing with your Flex Gateway configuration. To deploy a policy to Flex Gateway, see step 9. 8. [Release your policy on Exchange](https://docs.mulesoft.com/pdk/1.6/policies-pdk-publish-policies#release). Release your policy on Exchange to distribute a production-ready policy. 9. Deploy your custom policy to a production environment by [applying it to an API instance](https://docs.mulesoft.com/pdk/1.6/policies-pdk-apply-policies) deployed on Flex Gateway. 10. Configure a new version of this API instance by returning to step 2. --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Developing Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt After installing the [Prerequisites](https://docs.mulesoft.com/pdk/1.7/policies-pdk-prerequisites), you can develop custom policies by using Flex Gateway Policy Development Kit (PDK). The custom policy lifecycle consists of all the steps of developing a custom policy that occur in PDK. The following steps do not include steps that occur outside of PDK, such as [applying a policy](https://docs.mulesoft.com/pdk/1.7/policies-pdk-apply-policies), which is the same for all Flex Gateway policies. After you [create a new project](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-project), you might iteratively complete some steps. For example, while writing the policy’s source code, you might need to return to [add additional parameters](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-schema-definition), or you might need to recompile the policy after debugging the source code. To create a custom policy with PDK, follow these steps: 1. [Create a new project](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-project-overview). 2. [Define a schema definition](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-schema-definition). Modify the `definition/gcl.yaml` file to define metadata and configuration parameters for your custom policy. 3. [Configure custom policy features in Rust](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features). Use the rust code examples to implement your custom logic in the `src/lib.rs` file. 4. [Compile your custom policy](https://docs.mulesoft.com/pdk/1.7/policies-pdk-compile-policies). Compiling your policy creates the `WebAssembly` binary file and configuration files necessary to upload your policy to Exchange and deploy it to a Flex Gateway. 5. [Debug Your Policy with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.7/policies-pdk-debug-local). Use the playground provided with PDK to debug the functionality of your custom policy locally. 6. [Write Integration Tests](https://docs.mulesoft.com/pdk/1.7/policies-pdk-integration-tests). Write intergration tests to ensure your custom policy is compatible with your other services and to ensure that each new policy version does not introduce regression errors. 7. [Publish your policy on Exchange](https://docs.mulesoft.com/pdk/1.7/policies-pdk-publish-policies-overview). Publish your policy on Exchange to distribute a development version of your policy for testing with your Flex Gateway configuration and to release production-ready policies. To deploy a policy to Flex Gateway, see step eight. 8. Deploy your custom policy to a production environment by [applying it to an API instance](https://docs.mulesoft.com/pdk/1.7/policies-pdk-apply-policies) deployed on Flex Gateway. 9. Configure a new version of this API instance by returning to step two. --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Developing Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt After installing the [Prerequisites](https://docs.mulesoft.com/pdk/1.8/policies-pdk-prerequisites), you can develop custom policies by using Omni Gateway Policy Development Kit (PDK). The custom policy lifecycle consists of all the steps of developing a custom policy that occur in PDK. The following steps do not include steps that occur outside of PDK, such as [applying a policy](https://docs.mulesoft.com/pdk/1.8/policies-pdk-apply-policies), which is the same for all Omni Gateway policies. After you [create a new project](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-project), you might iteratively complete some steps. For example, while writing the policy’s source code, you might need to return to [add additional parameters](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-schema-definition), or you might need to recompile the policy after debugging the source code. To create a custom policy with PDK, follow these steps: 1. [Create a new project](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-project-overview). 2. [Define a schema definition](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-schema-definition). Modify the `definition/gcl.yaml` file to define metadata and configuration parameters for your custom policy. 3. [Configure custom policy features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features). Use the rust code examples to implement your custom logic in the `src/lib.rs` file. 4. [Compile your custom policy](https://docs.mulesoft.com/pdk/1.8/policies-pdk-compile-policies). Compiling your policy creates the `WebAssembly` binary file and configuration files necessary to upload your policy to Exchange and deploy it to an Omni Gateway. 5. [Test and debug your policy](https://docs.mulesoft.com/pdk/1.8/policies-pdk-test-debug-overview). Use [pdk-unit](https://docs.mulesoft.com/pdk/1.8/policies-pdk-unit) for fast unit tests, [the PDK debugging playground](https://docs.mulesoft.com/pdk/1.8/policies-pdk-debug-local) for interactive checks with Omni Gateway in Local Mode in Docker, and [integration tests](https://docs.mulesoft.com/pdk/1.8/policies-pdk-integration-tests) to guard against regressions with your services and gateway configuration. 6. [Publish your policy on Exchange](https://docs.mulesoft.com/pdk/1.8/policies-pdk-publish-policies-overview). Publish your policy on Exchange to distribute a development version of your policy for testing with your Omni Gateway configuration and to release production-ready policies. To deploy a policy to Omni Gateway, see step seven. 7. Deploy your custom policy to a production environment by [applying it to an API instance](https://docs.mulesoft.com/pdk/1.8/policies-pdk-apply-policies) deployed on Omni Gateway. 8. Configure a new version of this API instance by returning to step two. --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Developing Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt After installing the [Prerequisites](https://docs.mulesoft.com/pdk/1.9/policies-pdk-prerequisites), you can develop custom policies by using Omni Gateway Policy Development Kit (PDK). The custom policy lifecycle consists of all the steps of developing a custom policy that occur in PDK. The following steps do not include steps that occur outside of PDK, such as [applying a policy](https://docs.mulesoft.com/pdk/1.9/policies-pdk-apply-policies), which is the same for all Omni Gateway policies. After you [create a new project](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-project), you might iteratively complete some steps. For example, while writing the policy’s source code, you might need to return to [add additional parameters](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-schema-definition), or you might need to recompile the policy after debugging the source code. To create a custom policy with PDK, follow these steps: 1. [Create a new project](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-project-overview). 2. [Define a schema definition](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-schema-definition). Modify the `definition/gcl.yaml` file to define metadata and configuration parameters for your custom policy. 3. [Configure custom policy features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features). Use the rust code examples to implement your custom logic in the `src/lib.rs` file. 4. [Compile your custom policy](https://docs.mulesoft.com/pdk/1.9/policies-pdk-compile-policies). Compiling your policy creates the `WebAssembly` binary file and configuration files necessary to upload your policy to Exchange and deploy it to an Omni Gateway. 5. [Test and debug your policy](https://docs.mulesoft.com/pdk/1.9/policies-pdk-test-debug-overview). Use [pdk-unit](https://docs.mulesoft.com/pdk/1.9/policies-pdk-unit) for fast unit tests, [the PDK debugging playground](https://docs.mulesoft.com/pdk/1.9/policies-pdk-debug-local) for interactive checks with Omni Gateway in Local Mode in Docker, and [integration tests](https://docs.mulesoft.com/pdk/1.9/policies-pdk-integration-tests) to guard against regressions with your services and gateway configuration. 6. [Publish your policy on Exchange](https://docs.mulesoft.com/pdk/1.9/policies-pdk-publish-policies-overview). Publish your policy on Exchange to distribute a development version of your policy for testing with your Omni Gateway configuration and to release production-ready policies. To deploy a policy to Omni Gateway, see step seven. 7. Deploy your custom policy to a production environment by [applying it to an API instance](https://docs.mulesoft.com/pdk/1.9/policies-pdk-apply-policies) deployed on Omni Gateway. 8. Configure a new version of this API instance by returning to step two. --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Developing Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt After installing the [Prerequisites](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites), you can develop custom policies by using Omni Gateway Policy Development Kit (PDK). The custom policy lifecycle consists of all the steps of developing a custom policy that occur in PDK. The following steps do not include steps that occur outside of PDK, such as [applying a policy](https://docs.mulesoft.com/pdk/latest/policies-pdk-apply-policies), which is the same for all Omni Gateway policies. After you [create a new project](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-project), you might iteratively complete some steps. For example, while writing the policy’s source code, you might need to return to [add additional parameters](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-schema-definition), or you might need to recompile the policy after debugging the source code. To create a custom policy with PDK, follow these steps: 1. [Create a new project](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-project-overview). 2. [Define a schema definition](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-schema-definition). Modify the `definition/gcl.yaml` file to define metadata and configuration parameters for your custom policy. 3. [Configure custom policy features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features). Use the rust code examples to implement your custom logic in the `src/lib.rs` file. 4. [Compile your custom policy](https://docs.mulesoft.com/pdk/latest/policies-pdk-compile-policies). Compiling your policy creates the `WebAssembly` binary file and configuration files necessary to upload your policy to Exchange and deploy it to an Omni Gateway. 5. [Test and debug your policy](https://docs.mulesoft.com/pdk/latest/policies-pdk-test-debug-overview). Use [pdk-unit](https://docs.mulesoft.com/pdk/latest/policies-pdk-unit) for fast unit tests, [the PDK debugging playground](https://docs.mulesoft.com/pdk/latest/policies-pdk-debug-local) for interactive checks with Omni Gateway in Local Mode in Docker, and [integration tests](https://docs.mulesoft.com/pdk/latest/policies-pdk-integration-tests) to guard against regressions with your services and gateway configuration. 6. [Publish your policy on Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies-overview). Publish your policy on Exchange to distribute a development version of your policy for testing with your Omni Gateway configuration and to release production-ready policies. To deploy a policy to Omni Gateway, see step seven. 7. Deploy your custom policy to a production environment by [applying it to an API instance](https://docs.mulesoft.com/pdk/latest/policies-pdk-apply-policies) deployed on Omni Gateway. 8. Configure a new version of this API instance by returning to step two. --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Filter IP Addresses > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the Flex Gateway Policy Development Kit (PDK) IP Filter to filter requests based on IP addresses. Create allowlists or blocklists using IPv4/IPv6 addresses and CIDR ranges to evaluate incoming requests IPs. Import `IpFilter` from the `pdk` crate, then create an IP filter to either allow or block specific IPs: ```Rust use pdk::ip_filter::IpFilter; // Create an allowlist filter (only specified IPs are permitted) let ip_filter = IpFilter::allow(&["192.168.1.0/24", "10.0.0.1"])?; // Create a blocklist filter (specified IPs are denied) let ip_filter = IpFilter::block(&["192.168.1.0/24", "10.0.0.1"])?; ``` The `IpFilter` accepts an array of strings and supports: - Both IPv4 and IPv6 addresses. - Individual IPs, for example: `10.0.0.1`. - Classless Inter-Domain Routing (CIDR) notation for IP ranges. For example: `192.168.1.0/24`, `10.0.0.0/8`. After creating the filter, use the `is_allowed` method to check if an IP is permitted: ```Rust // Check if an IP is allowed if ip_filter.is_allowed("192.168.1.100") { // IP is permitted, continue processing Flow::Continue(()) } else { // IP is blocked, return forbidden response Flow::Break(Response::new(403).with_body("Forbidden")) } ``` ## IP Filter Configuration Examples PDK provides the [IP Filter Example policy](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.6.0/ip-filter) to demonstrate how to implement IP-based access control in Rust code. Within the example policy, see these code sections for additional configuration details: - [Configure an IP filter](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/ip-filter/src/lib.rs#L41-L65) - [Extract client IP from request headers](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/ip-filter/src/lib.rs#L18-L22) - [Validate if an IP is permitted](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/ip-filter/src/lib.rs#L24-L34) ## See Also - [Custom Policy Examples](https://docs.mulesoft.com/pdk/1.7/policies-pdk-policy-templates) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Filter IP Addresses > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the Omni Gateway Policy Development Kit (PDK) IP Filter to filter requests based on IP addresses. Create allowlists or blocklists using IPv4/IPv6 addresses and CIDR ranges to evaluate incoming requests IPs. Import `IpFilter` from the `pdk` crate, then create an IP filter to either allow or block specific IPs: ```Rust use pdk::ip_filter::IpFilter; // Create an allowlist filter (only specified IPs are permitted) let ip_filter = IpFilter::allow(&["192.168.1.0/24", "10.0.0.1"])?; // Create a blocklist filter (specified IPs are denied) let ip_filter = IpFilter::block(&["192.168.1.0/24", "10.0.0.1"])?; ``` The `IpFilter` accepts an array of strings and supports: - Both IPv4 and IPv6 addresses. - Individual IPs, for example: `10.0.0.1`. - Classless Inter-Domain Routing (CIDR) notation for IP ranges. For example: `192.168.1.0/24`, `10.0.0.0/8`. After creating the filter, use the `is_allowed` method to check if an IP is permitted: ```Rust // Check if an IP is allowed if ip_filter.is_allowed("192.168.1.100") { // IP is permitted, continue processing Flow::Continue(()) } else { // IP is blocked, return forbidden response Flow::Break(Response::new(403).with_body("Forbidden")) } ``` ## IP Filter Configuration Examples PDK provides the [IP Filter Example policy](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.8.0/ip-filter) to demonstrate how to implement IP-based access control in Rust code. Within the example policy, see these code sections for additional configuration details: - [Configure an IP filter](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/ip-filter/src/lib.rs#L41-L65) - [Extract client IP from request headers](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/ip-filter/src/lib.rs#L18-L22) - [Validate if an IP is permitted](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/ip-filter/src/lib.rs#L24-L34) ## See Also - [Custom Policy Examples](https://docs.mulesoft.com/pdk/1.8/policies-pdk-policy-templates) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Filter IP Addresses > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the Omni Gateway Policy Development Kit (PDK) IP Filter to filter requests based on IP addresses. Create allowlists or blocklists using IPv4/IPv6 addresses and CIDR ranges to evaluate incoming requests IPs. Import `IpFilter` from the `pdk` crate, then create an IP filter to either allow or block specific IPs: ```Rust use pdk::ip_filter::IpFilter; // Create an allowlist filter (only specified IPs are permitted) let ip_filter = IpFilter::allow(&["192.168.1.0/24", "10.0.0.1"])?; // Create a blocklist filter (specified IPs are denied) let ip_filter = IpFilter::block(&["192.168.1.0/24", "10.0.0.1"])?; ``` The `IpFilter` accepts an array of strings and supports: - Both IPv4 and IPv6 addresses. - Individual IPs, for example: `10.0.0.1`. - Classless Inter-Domain Routing (CIDR) notation for IP ranges. For example: `192.168.1.0/24`, `10.0.0.0/8`. After creating the filter, use the `is_allowed` method to check if an IP is permitted: ```Rust // Check if an IP is allowed if ip_filter.is_allowed("192.168.1.100") { // IP is permitted, continue processing Flow::Continue(()) } else { // IP is blocked, return forbidden response Flow::Break(Response::new(403).with_body("Forbidden")) } ``` ## IP Filter Configuration Examples PDK provides the [IP Filter Example policy](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.9.0/ip-filter) to demonstrate how to implement IP-based access control in Rust code. Within the example policy, see these code sections for additional configuration details: - [Configure an IP filter](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/ip-filter/src/lib.rs#L41-L65) - [Extract client IP from request headers](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/ip-filter/src/lib.rs#L18-L22) - [Validate if an IP is permitted](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/ip-filter/src/lib.rs#L24-L34) ## See Also - [Custom Policy Examples](https://docs.mulesoft.com/pdk/1.9/policies-pdk-policy-templates) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Filter IP Addresses > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the Omni Gateway Policy Development Kit (PDK) IP Filter to filter requests based on IP addresses. Create allowlists or blocklists using IPv4/IPv6 addresses and CIDR ranges to evaluate incoming requests IPs. Import `IpFilter` from the `pdk` crate, then create an IP filter to either allow or block specific IPs: ```Rust use pdk::ip_filter::IpFilter; // Create an allowlist filter (only specified IPs are permitted) let ip_filter = IpFilter::allow(&["192.168.1.0/24", "10.0.0.1"])?; // Create a blocklist filter (specified IPs are denied) let ip_filter = IpFilter::block(&["192.168.1.0/24", "10.0.0.1"])?; ``` The `IpFilter` accepts an array of strings and supports: - Both IPv4 and IPv6 addresses. - Individual IPs, for example: `10.0.0.1`. - Classless Inter-Domain Routing (CIDR) notation for IP ranges. For example: `192.168.1.0/24`, `10.0.0.0/8`. After creating the filter, use the `is_allowed` method to check if an IP is permitted: ```Rust // Check if an IP is allowed if ip_filter.is_allowed("192.168.1.100") { // IP is permitted, continue processing Flow::Continue(()) } else { // IP is blocked, return forbidden response Flow::Break(Response::new(403).with_body("Forbidden")) } ``` ## IP Filter Configuration Examples PDK provides the [IP Filter Example policy](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.10.0/ip-filter) to demonstrate how to implement IP-based access control in Rust code. Within the example policy, see these code sections for additional configuration details: - [Configure an IP filter](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/ip-filter/src/lib.rs#L41-L65) - [Extract client IP from request headers](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/ip-filter/src/lib.rs#L18-L22) - [Validate if an IP is permitted](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/ip-filter/src/lib.rs#L24-L34) ## See Also - [Custom Policy Examples](https://docs.mulesoft.com/pdk/latest/policies-pdk-policy-templates) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Flex Gateway Policy Development Kit (PDK) Overview > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Policies enforce regulations to help manage security, control traffic, and improve API adoption. Flex Gateway provides many [included policies](https://docs.mulesoft.com/gateway/latest/policies-included-directory), but they might not cover all your specific business needs. Flex Gateway Policy Development Kit (PDK) is a software development kit that enables you to develop custom policies with ease. PDK provides instructions to guide you through the policy development lifecycle, from implementing your Rust source code to releasing your policy on Exchange. Like included policies, you can apply custom policies to Flex Gateway running in Connected Mode by using API Manager or to Flex Gateway running in Local Mode by using YAML configuration files. PDK also provides [example policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-policy-templates) to help you get started with policy development. Watch the PDK Product Spotlight video to see a quick overview of PDK. ![](https://play.vidyard.com/ibt7HZ8SByp9VCn88dNPx7.jpg) ## See Also - [Review the architecture](https://docs.mulesoft.com/pdk/1.2/policies-pdk-architecture) - [Review the prerequisites](https://docs.mulesoft.com/pdk/1.2/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Flex Gateway Policy Development Kit (PDK) Overview > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Policies enforce regulations to help manage security, control traffic, and improve API adoption. Flex Gateway provides many [included policies](https://docs.mulesoft.com/gateway/latest/policies-included-directory), but they might not cover all your specific business needs. Flex Gateway Policy Development Kit (PDK) is a software development kit that enables you to develop custom policies with ease. PDK provides instructions to guide you through the policy development lifecycle, from implementing your Rust source code to releasing your policy on Exchange. Like included policies, you can apply custom policies to Flex Gateway running in Connected Mode by using API Manager or to Flex Gateway running in Local Mode by using YAML configuration files. PDK also provides [example policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-policy-templates) to help you get started with policy development. Watch the PDK Product Spotlight video to see a quick overview of PDK. ![](https://play.vidyard.com/ibt7HZ8SByp9VCn88dNPx7.jpg) ## See Also - [Review the architecture](https://docs.mulesoft.com/pdk/1.3/policies-pdk-architecture) - [Review the prerequisites](https://docs.mulesoft.com/pdk/1.3/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Flex Gateway Policy Development Kit (PDK) Overview > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Policies enforce regulations to help manage security, control traffic, and improve API adoption. Flex Gateway provides many [included policies](https://docs.mulesoft.com/gateway/latest/policies-included-directory), but they might not cover all your specific business needs. Flex Gateway Policy Development Kit (PDK) is a software development kit that enables you to develop custom policies with ease. PDK provides instructions to guide you through the policy development lifecycle, from implementing your Rust source code to releasing your policy on Exchange. Like included policies, you can apply custom policies to Flex Gateway running in Connected Mode by using API Manager or to Flex Gateway running in Local Mode by using YAML configuration files. PDK provides [example policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-policy-templates) to help you get started with policy development and the [MuleSoft MCP Server Policy Management Tools](https://docs.mulesoft.com/mulesoft-mcp-server/reference-mcp-tools#policy-management) to help manage the custom policy lifecycle. Watch the PDK Product Spotlight video to see a quick overview of PDK. ![](https://play.vidyard.com/ibt7HZ8SByp9VCn88dNPx7.jpg) ## See Also - [Review the architecture](https://docs.mulesoft.com/pdk/1.4/policies-pdk-architecture) - [Review the prerequisites](https://docs.mulesoft.com/pdk/1.4/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Flex Gateway Policy Development Kit (PDK) Overview > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Policies enforce regulations to help manage security, control traffic, and improve API adoption. Flex Gateway provides many [included policies](https://docs.mulesoft.com/gateway/latest/policies-included-directory), but they might not cover all your specific business needs. Flex Gateway Policy Development Kit (PDK) is a software development kit that enables you to develop custom policies with ease. PDK provides instructions to guide you through the policy development lifecycle, from implementing your Rust source code to releasing your policy on Exchange. Like included policies, you can apply custom policies to Flex Gateway running in Connected Mode by using API Manager or to Flex Gateway running in Local Mode by using YAML configuration files. PDK provides [example policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-policy-templates) to help you get started with policy development and the [MuleSoft MCP Server Policy Management Tools](https://docs.mulesoft.com/mulesoft-mcp-server/reference-mcp-tools#policy-management) to help manage the custom policy lifecycle. Watch the PDK Product Spotlight video to see a quick overview of PDK. ![](https://play.vidyard.com/ibt7HZ8SByp9VCn88dNPx7.jpg) ## See Also - [Review the architecture](https://docs.mulesoft.com/pdk/1.5/policies-pdk-architecture) - [Review the prerequisites](https://docs.mulesoft.com/pdk/1.5/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Flex Gateway Policy Development Kit (PDK) Overview > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Policies enforce regulations to help manage security, control traffic, and improve API adoption. Flex Gateway provides many [included policies](https://docs.mulesoft.com/gateway/latest/policies-included-directory), but they might not cover all your specific business needs. Flex Gateway Policy Development Kit (PDK) is a software development kit that enables you to develop custom policies with ease. PDK provides instructions to guide you through the policy development lifecycle, from implementing your Rust source code to releasing your policy on Exchange. Like included policies, you can apply custom policies to Flex Gateway running in Connected Mode by using API Manager or to Flex Gateway running in Local Mode by using YAML configuration files. PDK provides [example policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-policy-templates) to help you get started with policy development and the [MuleSoft MCP Server Policy Management Tools](https://docs.mulesoft.com/mulesoft-mcp-server/reference-mcp-tools#policy-management) to help manage the custom policy lifecycle. Watch the PDK Product Spotlight video to see a quick overview of PDK. ![](https://play.vidyard.com/ibt7HZ8SByp9VCn88dNPx7.jpg) ## See Also - [Review the architecture](https://docs.mulesoft.com/pdk/1.6/policies-pdk-architecture) - [Review the prerequisites](https://docs.mulesoft.com/pdk/1.6/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Flex Gateway Policy Development Kit (PDK) Overview > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Policies enforce regulations to help manage security, control traffic, and improve API adoption. Flex Gateway provides many [included policies](https://docs.mulesoft.com/gateway/latest/policies-included-directory), but they might not cover all your specific business needs. Flex Gateway Policy Development Kit (PDK) is a software development kit that enables you to develop custom policies with ease. PDK provides instructions to guide you through the policy development lifecycle, from implementing your Rust source code to releasing your policy on Exchange. Like included policies, you can apply custom policies to Flex Gateway running in Connected Mode by using API Manager or to Flex Gateway running in Local Mode by using YAML configuration files. PDK provides [example policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-policy-templates) to help you get started with policy development and the [MuleSoft MCP Server Policy Management Tools](https://docs.mulesoft.com/mulesoft-mcp-server/reference-mcp-tools#policy-management) to help manage the custom policy lifecycle. Watch the PDK Product Spotlight video to see a quick overview of PDK. ![](https://play.vidyard.com/ibt7HZ8SByp9VCn88dNPx7.jpg) ## See Also - [Review the architecture](https://docs.mulesoft.com/pdk/1.7/policies-pdk-architecture) - [Review the prerequisites](https://docs.mulesoft.com/pdk/1.7/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Implementing Your Custom Policy Features in Rust > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The following pages provide Rust code examples that complete various policy tasks. Implement the Rust code for your policy in the `src/lib.rs` file. The code examples assume you have some prior knowledge of the Rust Programming Language. For more information about programming in Rust, see: - [The Rust Programming Language Documentation](https://doc.rust-lang.org/book/) - [Rust Cookbook](https://rust-lang-nursery.github.io/rust-cookbook/intro.html) ## Before You Begin - [Create a New Project](https://docs.mulesoft.com/pdk/1.2/policies-pdk-create-project) - [Define a Schema Definition](https://docs.mulesoft.com/pdk/1.2/policies-pdk-create-schema-definition) > [!NOTE] You may need to add or redefine configuration parameters while implementing your policy. - Review [Policy Template](#policy-template), [Wrapped Functions](#wrapped-functions), and [Flow Cancellation](#flow-cancellation) to learn about the policy’s source code structure before adding [additional policy capabilities](#provided-rust-source-code). ## Policy Template Flex Gateway Policy Development Kit (PDK) provides the initial `src/lib.rs` file in the policy project as a template to begin implementing your policy: ```Rust // Copyright 2024 Salesforce, Inc. All rights reserved. mod generated; use anyhow::{anyhow, Result}; use pdk::hl::*; use pdk::logger; use crate::generated::config::Config; // This filter shows how to log a specific request header. // You can extend the function and use the configurations exposed in config.rs file async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let token = headers_state.handler().header("Token").unwrap_or_default(); // Log the header value logger::info!("Header value: {token}"); } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_request(|rs| request_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` The policy performs some simple logging. For each incoming request, the policy logs the header `token` at the `info` log level. The following elements configure the policy: - `use pdk::api::hl::*;`: Imports all the components of PDK into the `lib.rs` source code. - `#[entrypoint]` function: Executes when the policy is applied and calls the `request_filter` function. Variables defined inside this function are avaliable while the policy is applied. The `#[entrypoint]` function receives the following parameters: - `Launcher`: Sets the filter functions. - `Configuration`: Provides the configuration parameters defined in [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.2/policies-pdk-create-schema-definition). - `request_filter`: Executes once per every request sent to the API instance to which the policy is applied. This function implements the filtering performed by the example policy. Variables defined inside this function are available for the duration of the request. The `request_filter` is an example of a wrapped function. The `#[entrypoint]` function executes wrapped functions: ```Rust let filter = on_request(|rs| request_filter(rs, &config)); launcher.launch(filter).await?; ``` ## Wrapped Functions The `on_response` or `on_request` wrapper defines when the filter function executes. You can define custom functions other than the provided `requests_filter` and `response_filter` in the `#[entrypoint]` function. The `requests_filter` and `response_filter` are only examples. Instead of filtering an incoming request as shown in the previous example, you can process the outgoing response by using the `on_response` wrapper: ```Rust async fn response_filter(response_state: ResponseState, _config: &Config) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_response(|rs| response_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` > [!NOTE] The `request_filter` function is now the `response_filter` function. To filter both requests and responses, use both wrappers: ```Rust async fn request_filter(request_state: RequestState,_config: &Config) { ... } async fn response_filter(response_state: ResponseState,_config: &Config) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_request(|rs| request_filter(rs, &config)) .on_response(|rs| response_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` ## Flow Cancellation Custom policies run on a single-threaded environment. However, every set of wrapped functions (a `on_request` and a `on_response` `async` function) run as a concurrent task, meaning that a single policy instance handles multiple requests concurrently. To support this behavior, every `.await` is a potential task interruption point. When an `.await` is invoked, the underlying async runtime can set the current task to sleep for a moment, and awake another task that has not finished. The async runtime can cancel a task and never run code that comes after the last `.await` invocation. `on_request` and `on_response` functions assume that `.await` invocations are potential cancellation points. The most common situation, as shown in the following code example, for task cancellation is when a request function waiting for a body and an upstream policy returns an early response: ```Rust // Request function for upstream policy async fn upstream_request(state: RequestState) -> Response { Response::new(404) } // Request function for downstream policy async fn downstream_request(state: RequestState) { // Request function will be cancelled after this .await point. let body_state = state.into_body_state().await; // Code here will never be executed } ``` ## Discover PDK features with Provided Rust Source Code PDK provides code examples for the following policy features. Review [Policy Template](#policy-template) and [Wrapped Functions](#wrapped-functions) before adding the additional policy capabilities: - [Configuring Policy Logging](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-logging) - [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-headers) - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-inject-parameters) - [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-http-request) - [Using CORS Library Functions](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-cors) - [Using JWT Library Functions](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-jwt) - [Using DataWeave Expressions](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-dataweave) - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-share-data) - [Using Third-Party Libraries](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-libraries) - [Sharing Data Between Workers and Configuring Caching](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-caching) - [Accessing Policy Metadata](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-metadata) - [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-streamproperties) - [Accessing Request Authentication Information](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-authentication) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-timer) - [Stopping Request Execution](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-stop) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Implementing Your Custom Policy Features in Rust > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The following pages provide Rust code examples that complete various policy tasks. Implement the Rust code for your policy in the `src/lib.rs` file. The code examples assume you have some prior knowledge of the Rust Programming Language. For more information about programming in Rust, see: - [The Rust Programming Language Documentation](https://doc.rust-lang.org/book/) - [Rust Cookbook](https://rust-lang-nursery.github.io/rust-cookbook/intro.html) ## Before You Begin - [Create a New Project](https://docs.mulesoft.com/pdk/1.3/policies-pdk-create-project) - [Define a Schema Definition](https://docs.mulesoft.com/pdk/1.3/policies-pdk-create-schema-definition) > [!NOTE] You may need to add or redefine configuration parameters while implementing your policy. - Review [Policy Template](#policy-template), [Wrapped Functions](#wrapped-functions), and [Flow Cancellation](#flow-cancellation) to learn about the policy’s source code structure before adding [additional policy capabilities](#provided-rust-source-code). ## Policy Template Flex Gateway Policy Development Kit (PDK) provides the initial `src/lib.rs` file in the policy project as a template to begin implementing your policy: ```Rust // Copyright 2024 Salesforce, Inc. All rights reserved. mod generated; use anyhow::{anyhow, Result}; use pdk::hl::*; use pdk::logger; use crate::generated::config::Config; // This filter shows how to log a specific request header. // You can extend the function and use the configurations exposed in config.rs file async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let token = headers_state.handler().header("Token").unwrap_or_default(); // Log the header value logger::info!("Header value: {token}"); } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_request(|rs| request_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` The policy performs some simple logging. For each incoming request, the policy logs the header `token` at the `info` log level. The following elements configure the policy: - `use pdk::api::hl::*;`: Imports all the components of PDK into the `lib.rs` source code. - `#[entrypoint]` function: Executes when the policy is applied and calls the `request_filter` function. Variables defined inside this function are avaliable while the policy is applied. The `#[entrypoint]` function receives the following parameters: - `Launcher`: Sets the filter functions. - `Configuration`: Provides the configuration parameters defined in [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.3/policies-pdk-create-schema-definition). - `request_filter`: Executes once per every request sent to the API instance to which the policy is applied. This function implements the filtering performed by the example policy. Variables defined inside this function are available for the duration of the request. The `request_filter` is an example of a wrapped function. The `#[entrypoint]` function executes wrapped functions: ```Rust let filter = on_request(|rs| request_filter(rs, &config)); launcher.launch(filter).await?; ``` ## Wrapped Functions The `on_response` or `on_request` wrapper defines when the filter function executes. You can define custom functions other than the provided `requests_filter` and `response_filter` in the `#[entrypoint]` function. The `requests_filter` and `response_filter` are only examples. Instead of filtering an incoming request as shown in the previous example, you can process the outgoing response by using the `on_response` wrapper: ```Rust async fn response_filter(response_state: ResponseState, _config: &Config) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_response(|rs| response_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` > [!NOTE] The `request_filter` function is now the `response_filter` function. To filter both requests and responses, use both wrappers: ```Rust async fn request_filter(request_state: RequestState,_config: &Config) { ... } async fn response_filter(response_state: ResponseState,_config: &Config) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_request(|rs| request_filter(rs, &config)) .on_response(|rs| response_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` ## Flow Cancellation Custom policies run on a single-threaded environment. However, every set of wrapped functions (a `on_request` and a `on_response` `async` function) run as a concurrent task, meaning that a single policy instance handles multiple requests concurrently. To support this behavior, every `.await` is a potential task interruption point. When an `.await` is invoked, the underlying async runtime can set the current task to sleep for a moment, and awake another task that has not finished. The async runtime can cancel a task and never run code that comes after the last `.await` invocation. `on_request` and `on_response` functions assume that `.await` invocations are potential cancellation points. The most common situation, as shown in the following code example, for task cancellation is when a request function waiting for a body and an upstream policy returns an early response: ```Rust // Request function for upstream policy async fn upstream_request(state: RequestState) -> Response { Response::new(404) } // Request function for downstream policy async fn downstream_request(state: RequestState) { // Request function will be cancelled after this .await point. let body_state = state.into_body_state().await; // Code here will never be executed } ``` ## Discover PDK features with Provided Rust Source Code PDK provides code examples for the following policy features. Review [Policy Template](#policy-template) and [Wrapped Functions](#wrapped-functions) before adding the additional policy capabilities: - [Configuring Policy Logging](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-logging) - [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-headers) - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-inject-parameters) - [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-http-request) - [Using Contracts Validation Library Functions](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-contracts) - [Using CORS Library Functions](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-cors) - [Using JWT Library Functions](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-jwt) - [Using DataWeave Expressions](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-dataweave) - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-share-data) - [Using Third-Party Libraries](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-libraries) - [Sharing Data Between Workers and Configuring Caching](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-caching) - [Accessing Policy Metadata](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-metadata) - [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-streamproperties) - [Accessing Request Authentication Information](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-authentication) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-timer) - [Stopping Request Execution](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-stop) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Implementing Your Custom Policy Features in Rust > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The following pages provide Rust code examples that complete various policy tasks. Implement the Rust code for your policy in the `src/lib.rs` file. The code examples assume you have some prior knowledge of the Rust Programming Language. For more information about programming in Rust, see: - [The Rust Programming Language Documentation](https://doc.rust-lang.org/book/) - [Rust Cookbook](https://rust-lang-nursery.github.io/rust-cookbook/intro.html) ## Before You Begin - [Create a New Project](https://docs.mulesoft.com/pdk/1.4/policies-pdk-create-project) - [Define a Schema Definition](https://docs.mulesoft.com/pdk/1.4/policies-pdk-create-schema-definition) > [!NOTE] You may need to add or redefine configuration parameters while implementing your policy. - Review [Policy Template](#policy-template), [Wrapped Functions](#wrapped-functions), and [Flow Cancellation](#flow-cancellation) to learn about the policy’s source code structure before adding [additional policy capabilities](#provided-rust-source-code). ## Policy Template Flex Gateway Policy Development Kit (PDK) provides the initial `src/lib.rs` file in the policy project as a template to begin implementing your policy: ```Rust // Copyright 2024 Salesforce, Inc. All rights reserved. mod generated; use anyhow::{anyhow, Result}; use pdk::hl::*; use pdk::logger; use crate::generated::config::Config; // This filter shows how to log a specific request header. // You can extend the function and use the configurations exposed in config.rs file async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let token = headers_state.handler().header("Token").unwrap_or_default(); // Log the header value logger::info!("Header value: {token}"); } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_request(|rs| request_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` The policy performs some simple logging. For each incoming request, the policy logs the header `token` at the `info` log level. The following elements configure the policy: - `use pdk::api::hl::*;`: Imports all the components of PDK into the `lib.rs` source code. - `#[entrypoint]` function: Executes when the policy is applied and calls the `request_filter` function. Variables defined inside this function are avaliable while the policy is applied. The `#[entrypoint]` function receives the following parameters: - `Launcher`: Sets the filter functions. - `Configuration`: Provides the configuration parameters defined in [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.4/policies-pdk-create-schema-definition). - `request_filter`: Executes once per every request sent to the API instance to which the policy is applied. This function implements the filtering performed by the example policy. Variables defined inside this function are available for the duration of the request. The `request_filter` is an example of a wrapped function. The `#[entrypoint]` function executes wrapped functions: ```Rust let filter = on_request(|rs| request_filter(rs, &config)); launcher.launch(filter).await?; ``` ## Wrapped Functions The `on_response` or `on_request` wrapper defines when the filter function executes. You can define custom functions other than the provided `requests_filter` and `response_filter` in the `#[entrypoint]` function. The `requests_filter` and `response_filter` are only examples. Instead of filtering an incoming request as shown in the previous example, you can process the outgoing response by using the `on_response` wrapper: ```Rust async fn response_filter(response_state: ResponseState, _config: &Config) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_response(|rs| response_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` > [!NOTE] The `request_filter` function is now the `response_filter` function. To filter both requests and responses, use both wrappers: ```Rust async fn request_filter(request_state: RequestState,_config: &Config) { ... } async fn response_filter(response_state: ResponseState,_config: &Config) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_request(|rs| request_filter(rs, &config)) .on_response(|rs| response_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` ## Flow Cancellation Custom policies run on a single-threaded environment. However, every set of wrapped functions (a `on_request` and a `on_response` `async` function) run as a concurrent task, meaning that a single policy instance handles multiple requests concurrently. To support this behavior, every `.await` is a potential task interruption point. When an `.await` is invoked, the underlying async runtime can set the current task to sleep for a moment, and awake another task that has not finished. The async runtime can cancel a task and never run code that comes after the last `.await` invocation. `on_request` and `on_response` functions assume that `.await` invocations are potential cancellation points. The most common situation, as shown in the following code example, for task cancellation is when a request function waiting for a body and an upstream policy returns an early response: ```Rust // Request function for upstream policy async fn upstream_request(state: RequestState) -> Response { Response::new(404) } // Request function for downstream policy async fn downstream_request(state: RequestState) { // Request function will be cancelled after this .await point. let body_state = state.into_body_state().await; // Code here will never be executed } ``` ## Discover PDK features with Provided Rust Source Code PDK provides code examples for the following policy features. Review [Policy Template](#policy-template) and [Wrapped Functions](#wrapped-functions) before adding the additional policy capabilities: - [Configuring Policy Logging](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-logging) - [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-headers) - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-inject-parameters) - [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-http-request) - [Using Contracts Validation Library Functions](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-contracts) - [Using CORS Library Functions](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-cors) - [Using JWT Library Functions](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-jwt) - [Using DataWeave Expressions](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-dataweave) - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-share-data) - [Using Third-Party Libraries](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-libraries) - [Sharing Data Between Workers and Configuring Caching](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-caching) - [Accessing Policy Metadata](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-metadata) - [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-streamproperties) - [Accessing Request Authentication Information](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-authentication) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-timer) - [Reporting Policy Violations](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-violations) - [Stopping Request Execution](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-stop) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Implementing Your Custom Policy Features in Rust > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The following pages provide Rust code examples that complete various policy tasks. Implement the Rust code for your policy in the `src/lib.rs` file. The code examples assume you have some prior knowledge of the Rust Programming Language. For more information about programming in Rust, see: - [The Rust Programming Language Documentation](https://doc.rust-lang.org/book/) - [Rust Cookbook](https://rust-lang-nursery.github.io/rust-cookbook/intro.html) ## Before You Begin - [Create a New Project](https://docs.mulesoft.com/pdk/1.5/policies-pdk-create-project) - [Define a Schema Definition](https://docs.mulesoft.com/pdk/1.5/policies-pdk-create-schema-definition) > [!NOTE] You may need to add or redefine configuration parameters while implementing your policy. - Review [Policy Template](#policy-template), [Wrapped Functions](#wrapped-functions), and [Flow Cancellation](#flow-cancellation) to learn about the policy’s source code structure before adding [additional policy capabilities](#provided-rust-source-code). ## Policy Template Flex Gateway Policy Development Kit (PDK) provides the initial `src/lib.rs` file in the policy project as a template to begin implementing your policy: ```Rust // Copyright 2024 Salesforce, Inc. All rights reserved. mod generated; use anyhow::{anyhow, Result}; use pdk::hl::*; use pdk::logger; use crate::generated::config::Config; // This filter shows how to log a specific request header. // You can extend the function and use the configurations exposed in config.rs file async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let token = headers_state.handler().header("Token").unwrap_or_default(); // Log the header value logger::info!("Header value: {token}"); } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_request(|rs| request_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` The policy performs some simple logging. For each incoming request, the policy logs the header `token` at the `info` log level. The following elements configure the policy: - `use pdk::api::hl::*;`: Imports all the components of PDK into the `lib.rs` source code. - `#[entrypoint]` function: Executes when the policy is applied and calls the `request_filter` function. Variables defined inside this function are avaliable while the policy is applied. The `#[entrypoint]` function receives the following parameters: - `Launcher`: Sets the filter functions. - `Configuration`: Provides the configuration parameters defined in [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.5/policies-pdk-create-schema-definition). - `request_filter`: Executes once per every request sent to the API instance to which the policy is applied. This function implements the filtering performed by the example policy. Variables defined inside this function are available for the duration of the request. The `request_filter` is an example of a wrapped function. The `#[entrypoint]` function executes wrapped functions: ```Rust let filter = on_request(|rs| request_filter(rs, &config)); launcher.launch(filter).await?; ``` ## Wrapped Functions The `on_response` or `on_request` wrapper defines when the filter function executes. You can define custom functions other than the provided `requests_filter` and `response_filter` in the `#[entrypoint]` function. The `requests_filter` and `response_filter` are only examples. Instead of filtering an incoming request as shown in the previous example, you can process the outgoing response by using the `on_response` wrapper: ```Rust async fn response_filter(response_state: ResponseState, _config: &Config) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_response(|rs| response_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` > [!NOTE] The `request_filter` function is now the `response_filter` function. To filter both requests and responses, use both wrappers: ```Rust async fn request_filter(request_state: RequestState,_config: &Config) { ... } async fn response_filter(response_state: ResponseState,_config: &Config) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_request(|rs| request_filter(rs, &config)) .on_response(|rs| response_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` ## Flow Cancellation Custom policies run on a single-threaded environment. However, every set of wrapped functions (a `on_request` and a `on_response` `async` function) run as a concurrent task, meaning that a single policy instance handles multiple requests concurrently. To support this behavior, every `.await` is a potential task interruption point. When an `.await` is invoked, the underlying async runtime can set the current task to sleep for a moment, and awake another task that has not finished. The async runtime can cancel a task and never run code that comes after the last `.await` invocation. `on_request` and `on_response` functions assume that `.await` invocations are potential cancellation points. The most common situation, as shown in the following code example, for task cancellation is when a request function waiting for a body and an upstream policy returns an early response: ```Rust // Request function for upstream policy async fn upstream_request(state: RequestState) -> Response { Response::new(404) } // Request function for downstream policy async fn downstream_request(state: RequestState) { // Request function will be cancelled after this .await point. let body_state = state.into_body_state().await; // Code here will never be executed } ``` ## Discover PDK features with Provided Rust Source Code PDK provides code examples for the following policy features. Review [Policy Template](#policy-template) and [Wrapped Functions](#wrapped-functions) before adding the additional policy capabilities: - [Configuring Policy Logging](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-logging) - [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-headers) - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-inject-parameters) - [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-http-request) - [Using Contracts Validation Library Functions](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-contracts) - [Using CORS Library Functions](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-cors) - [Using JWT Library Functions](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-jwt) - [Using DataWeave Expressions](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-dataweave) - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-share-data) - [Configuring Data Storage](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-data-storage) - [Using Third-Party Libraries](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-libraries) - [Sharing Data Between Workers and Configuring Caching](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-caching) - [Accessing Policy Metadata](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-metadata) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-rate-limiting) - [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-streamproperties) - [Accessing Request Authentication Information](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-authentication) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-timer) - [Reporting Policy Violations](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-violations) - [Stopping Request Execution](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-stop) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Implementing Your Custom Policy Features in Rust > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The following pages provide Rust code examples that complete various policy tasks. Implement the Rust code for your policy in the `src/lib.rs` file. The code examples assume you have some prior knowledge of the Rust Programming Language. For more information about programming in Rust, see: - [The Rust Programming Language Documentation](https://doc.rust-lang.org/book/) - [Rust Cookbook](https://rust-lang-nursery.github.io/rust-cookbook/intro.html) ## Before You Begin - [Create a New Project](https://docs.mulesoft.com/pdk/1.6/policies-pdk-create-project) - [Define a Schema Definition](https://docs.mulesoft.com/pdk/1.6/policies-pdk-create-schema-definition) > [!NOTE] You may need to add or redefine configuration parameters while implementing your policy. - Review [Policy Template](#policy-template), [Wrapped Functions](#wrapped-functions), and [Flow Cancellation](#flow-cancellation) to learn about the policy’s source code structure before adding [additional policy capabilities](#provided-rust-source-code). ## Policy Template Flex Gateway Policy Development Kit (PDK) provides the initial `src/lib.rs` file in the policy project as a template to begin implementing your policy: ```Rust // Copyright 2024 Salesforce, Inc. All rights reserved. mod generated; use anyhow::{anyhow, Result}; use pdk::hl::*; use pdk::logger; use crate::generated::config::Config; // This filter shows how to log a specific request header. // You can extend the function and use the configurations exposed in config.rs file async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let token = headers_state.handler().header("Token").unwrap_or_default(); // Log the header value logger::info!("Header value: {token}"); } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_request(|rs| request_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` The policy performs some simple logging. For each incoming request, the policy logs the header `token` at the `info` log level. The following elements configure the policy: - `use pdk::api::hl::*;`: Imports all the components of PDK into the `lib.rs` source code. - `#[entrypoint]` function: Executes when the policy is applied and calls the `request_filter` function. Variables defined inside this function are avaliable while the policy is applied. The `#[entrypoint]` function receives the following parameters: - `Launcher`: Sets the filter functions. - `Configuration`: Provides the configuration parameters defined in [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.6/policies-pdk-create-schema-definition). - `request_filter`: Executes once per every request sent to the API instance to which the policy is applied. This function implements the filtering performed by the example policy. Variables defined inside this function are available for the duration of the request. The `request_filter` is an example of a wrapped function. The `#[entrypoint]` function executes wrapped functions: ```Rust let filter = on_request(|rs| request_filter(rs, &config)); launcher.launch(filter).await?; ``` ## Wrapped Functions The `on_response` or `on_request` wrapper defines when the filter function executes. You can define custom functions other than the provided `requests_filter` and `response_filter` in the `#[entrypoint]` function. The `requests_filter` and `response_filter` are only examples. Instead of filtering an incoming request as shown in the previous example, you can process the outgoing response by using the `on_response` wrapper: ```Rust async fn response_filter(response_state: ResponseState, _config: &Config) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_response(|rs| response_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` > [!NOTE] The `request_filter` function is now the `response_filter` function. To filter both requests and responses, use both wrappers: ```Rust async fn request_filter(request_state: RequestState,_config: &Config) { ... } async fn response_filter(response_state: ResponseState,_config: &Config) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_request(|rs| request_filter(rs, &config)) .on_response(|rs| response_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` ## Flow Cancellation Custom policies run on a single-threaded environment. However, every set of wrapped functions (a `on_request` and a `on_response` `async` function) run as a concurrent task, meaning that a single policy instance handles multiple requests concurrently. To support this behavior, every `.await` is a potential task interruption point. When an `.await` is invoked, the underlying async runtime can set the current task to sleep for a moment, and awake another task that has not finished. The async runtime can cancel a task and never run code that comes after the last `.await` invocation. `on_request` and `on_response` functions assume that `.await` invocations are potential cancellation points. The most common situation, as shown in the following code example, for task cancellation is when a request function waiting for a body and an upstream policy returns an early response: ```Rust // Request function for upstream policy async fn upstream_request(state: RequestState) -> Response { Response::new(404) } // Request function for downstream policy async fn downstream_request(state: RequestState) { // Request function will be cancelled after this .await point. let body_state = state.into_body_state().await; // Code here will never be executed } ``` ## Discover PDK features with Provided Rust Source Code PDK provides code examples for the following policy features. Review [Policy Template](#policy-template) and [Wrapped Functions](#wrapped-functions) before adding the additional policy capabilities: - [Configuring Policy Logging](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-logging) - [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-headers) - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-inject-parameters) - [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-http-request) - [Using Contracts Validation Library Functions](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-contracts) - [Using CORS Library Functions](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-cors) - [Using JWT Library Functions](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-jwt) - [Using DataWeave Expressions](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-dataweave) - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-share-data) - [Configuring Data Storage](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-data-storage) - [Using Third-Party Libraries](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-libraries) - [Sharing Data Between Workers and Configuring Caching](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-caching) - [Accessing Policy Metadata](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-metadata) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-rate-limiting) - [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-streamproperties) - [Accessing Request Authentication Information](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-authentication) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-timer) - [Reporting Policy Violations](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-violations) - [Stopping Request Execution](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-stop) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Implementing Your Custom Policy Features in Rust > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The following pages provide Rust code examples that complete various policy tasks. Implement the Rust code for your policy in the `src/lib.rs` file. The code examples assume you have some prior knowledge of the Rust Programming Language. For more information about programming in Rust, see: - [The Rust Programming Language Documentation](https://doc.rust-lang.org/book/) - [Rust Cookbook](https://rust-lang-nursery.github.io/rust-cookbook/intro.html) ## Before You Begin - [Create a New Project](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-project) - [Define a Schema Definition](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-schema-definition) > [!NOTE] You may need to add or redefine configuration parameters while implementing your policy. - Review [Policy Template](#policy-template), [Wrapped Functions](#wrapped-functions), and [Flow Cancellation](#flow-cancellation) to learn about the policy’s source code structure before adding [additional policy capabilities](#provided-rust-source-code). ## Policy Template Flex Gateway Policy Development Kit (PDK) provides the initial `src/lib.rs` file in the policy project as a template to begin implementing your policy: ```Rust // Copyright 2024 Salesforce, Inc. All rights reserved. mod generated; use anyhow::{anyhow, Result}; use pdk::hl::*; use pdk::logger; use crate::generated::config::Config; // This filter shows how to log a specific request header. // You can extend the function and use the configurations exposed in config.rs file async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let token = headers_state.handler().header("Token").unwrap_or_default(); // Log the header value logger::info!("Header value: {token}"); } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_request(|rs| request_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` The policy performs some simple logging. For each incoming request, the policy logs the header `token` at the `info` log level. The following elements configure the policy: - `use pdk::api::hl::*;`: Imports all the components of PDK into the `lib.rs` source code. - `#[entrypoint]` function: Executes when the policy is applied and calls the `request_filter` function. Variables defined inside this function are avaliable while the policy is applied. The `#[entrypoint]` function receives the following parameters: - `Launcher`: Sets the filter functions. - `Configuration`: Provides the configuration parameters defined in [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-schema-definition). - `request_filter`: Executes once per every request sent to the API instance to which the policy is applied. This function implements the filtering performed by the example policy. Variables defined inside this function are available for the duration of the request. The `request_filter` is an example of a wrapped function. The `#[entrypoint]` function executes wrapped functions: ```Rust let filter = on_request(|rs| request_filter(rs, &config)); launcher.launch(filter).await?; ``` ## Wrapped Functions The `on_response` or `on_request` wrapper defines when the filter function executes. You can define custom functions other than the provided `requests_filter` and `response_filter` in the `#[entrypoint]` function. The `requests_filter` and `response_filter` are only examples. Instead of filtering an incoming request as shown in the previous example, you can process the outgoing response by using the `on_response` wrapper: ```Rust async fn response_filter(response_state: ResponseState, _config: &Config) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_response(|rs| response_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` > [!NOTE] The `request_filter` function is now the `response_filter` function. To filter both requests and responses, use both wrappers: ```Rust async fn request_filter(request_state: RequestState,_config: &Config) { ... } async fn response_filter(response_state: ResponseState,_config: &Config) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_request(|rs| request_filter(rs, &config)) .on_response(|rs| response_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` ## Flow Cancellation Custom policies run on a single-threaded environment. However, every set of wrapped functions (a `on_request` and a `on_response` `async` function) run as a concurrent task, meaning that a single policy instance handles multiple requests concurrently. To support this behavior, every `.await` is a potential task interruption point. When an `.await` is invoked, the underlying async runtime can set the current task to sleep for a moment, and awake another task that has not finished. The async runtime can cancel a task and never run code that comes after the last `.await` invocation. `on_request` and `on_response` functions assume that `.await` invocations are potential cancellation points. The most common situation, as shown in the following code example, for task cancellation is when a request function waiting for a body and an upstream policy returns an early response: ```Rust // Request function for upstream policy async fn upstream_request(state: RequestState) -> Response { Response::new(404) } // Request function for downstream policy async fn downstream_request(state: RequestState) { // Request function will be cancelled after this .await point. let body_state = state.into_body_state().await; // Code here will never be executed } ``` ## Discover PDK features with Provided Rust Source Code PDK provides code examples for the following policy features. Review [Policy Template](#policy-template) and [Wrapped Functions](#wrapped-functions) before adding the additional policy capabilities: - [Configuring Policy Logging](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-logging) - [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-headers) - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-inject-parameters) - [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-http-request) - [Using Contracts Validation Library Functions](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-contracts) - [Using CORS Library Functions](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-cors) - [Using JWT Library Functions](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-jwt) - [Using OAuth 2.0 Token Introspection Library Functions](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-token-introspection) - [Using DataWeave Expressions](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-dataweave) - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-share-data) - [Configuring Data Storage](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-data-storage) - [Using Third-Party Libraries](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-libraries) - [Sharing Data Between Workers and Configuring Caching](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-caching) - [Accessing Policy Metadata](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-metadata) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-rate-limiting) - [Filter IP Addresses](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-ip-filter) - [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-streamproperties) - [Accessing Request Authentication Information](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-authentication) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-timer) - [Reporting Policy Violations](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-violations) - [Stopping Request and Response Execution](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-stop) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Implementing Your Custom Policy Features in Rust > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The following pages provide Rust code examples that complete various policy tasks. Implement the Rust code for your policy in the `src/lib.rs` file. The code examples assume you have some prior knowledge of the Rust Programming Language. For more information about programming in Rust, see: - [The Rust Programming Language Documentation](https://doc.rust-lang.org/book/) - [Rust Cookbook](https://rust-lang-nursery.github.io/rust-cookbook/intro.html) ## Before You Begin - [Create a New Project](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-project) - [Define a Schema Definition](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-schema-definition) > [!NOTE] You may need to add or redefine configuration parameters while implementing your policy. - Review [Policy Template](#policy-template), [Wrapped Functions](#wrapped-functions), and [Flow Cancellation](#flow-cancellation) to learn about the policy’s source code structure before adding [additional policy capabilities](#provided-rust-source-code). ## Policy Template Omni Gateway Policy Development Kit (PDK) provides the initial `src/lib.rs` file in the policy project as a template to begin implementing your policy: ```Rust // Copyright 2024 Salesforce, Inc. All rights reserved. mod generated; use anyhow::{anyhow, Result}; use pdk::hl::*; use pdk::logger; use crate::generated::config::Config; // This filter shows how to log a specific request header. // You can extend the function and use the configurations exposed in config.rs file async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let token = headers_state.handler().header("Token").unwrap_or_default(); // Log the header value logger::info!("Header value: {token}"); } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_request(|rs| request_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` The policy performs some simple logging. For each incoming request, the policy logs the header `token` at the `info` log level. The following elements configure the policy: - `use pdk::api::hl::*;`: Imports all the components of PDK into the `lib.rs` source code. - `#[entrypoint]` function: Executes when the policy is applied and calls the `request_filter` function. Variables defined inside this function are avaliable while the policy is applied. The `#[entrypoint]` function receives the following parameters: - `Launcher`: Sets the filter functions. - `Configuration`: Provides the configuration parameters defined in [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-schema-definition). - `request_filter`: Executes once per every request sent to the API instance to which the policy is applied. This function implements the filtering performed by the example policy. Variables defined inside this function are available for the duration of the request. The `request_filter` is an example of a wrapped function. The `#[entrypoint]` function executes wrapped functions: ```Rust let filter = on_request(|rs| request_filter(rs, &config)); launcher.launch(filter).await?; ``` ## Wrapped Functions The `on_response` or `on_request` wrapper defines when the filter function executes. You can define custom functions other than the provided `requests_filter` and `response_filter` in the `#[entrypoint]` function. The `requests_filter` and `response_filter` are only examples. Instead of filtering an incoming request as shown in the previous example, you can process the outgoing response by using the `on_response` wrapper: ```Rust async fn response_filter(response_state: ResponseState, _config: &Config) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_response(|rs| response_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` > [!NOTE] The `request_filter` function is now the `response_filter` function. To filter both requests and responses, use both wrappers: ```Rust async fn request_filter(request_state: RequestState,_config: &Config) { ... } async fn response_filter(response_state: ResponseState,_config: &Config) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_request(|rs| request_filter(rs, &config)) .on_response(|rs| response_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` ## Flow Cancellation Custom policies run on a single-threaded environment. However, every set of wrapped functions (a `on_request` and a `on_response` `async` function) run as a concurrent task, meaning that a single policy instance handles multiple requests concurrently. To support this behavior, every `.await` is a potential task interruption point. When an `.await` is invoked, the underlying async runtime can set the current task to sleep for a moment, and awake another task that has not finished. The async runtime can cancel a task and never run code that comes after the last `.await` invocation. `on_request` and `on_response` functions assume that `.await` invocations are potential cancellation points. The most common situation, as shown in the following code example, for task cancellation is when a request function waiting for a body and an upstream policy returns an early response: ```Rust // Request function for upstream policy async fn upstream_request(state: RequestState) -> Response { Response::new(404) } // Request function for downstream policy async fn downstream_request(state: RequestState) { // Request function will be cancelled after this .await point. let body_state = state.into_body_state().await; // Code here will never be executed } ``` ## Discover PDK features with Provided Rust Source Code PDK provides code examples for the following policy features. Review [Policy Template](#policy-template) and [Wrapped Functions](#wrapped-functions) before adding the additional policy capabilities: - [Configuring Policy Logging](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-logging) - [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-headers) - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-inject-parameters) - [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-http-request) - [Using Contracts Validation Library Functions](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-contracts) - [Using CORS Library Functions](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-cors) - [Using JWT Library Functions](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-jwt) - [Using XML Validator Library Functions](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-xml-validator) - [Using JSON Validator Library Functions](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-json-validator) - [Using OAuth 2.0 Token Introspection Library Functions](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-token-introspection) - [Using DataWeave Expressions](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-dataweave) - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-share-data) - [Configuring Data Storage](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-data-storage) - [Using Third-Party Libraries](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-libraries) - [Sharing Data Between Workers and Configuring Caching](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-caching) - [Accessing Policy Metadata](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-metadata) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-rate-limiting) - [Using Spike Control Library Functions](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-spike-control) - [Filter IP Addresses](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-ip-filter) - [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-streamproperties) - [Accessing Request Authentication Information](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-authentication) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-timer) - [Reporting Policy Violations](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-violations) - [Stopping Request and Response Execution](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-stop) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Implementing Your Custom Policy Features in Rust > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The following pages provide Rust code examples that complete various policy tasks. Implement the Rust code for your policy in the `src/lib.rs` file. The code examples assume you have some prior knowledge of the Rust Programming Language. For more information about programming in Rust, see: - [The Rust Programming Language Documentation](https://doc.rust-lang.org/book/) - [Rust Cookbook](https://rust-lang-nursery.github.io/rust-cookbook/intro.html) ## Before You Begin - [Create a New Project](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-project) - [Define a Schema Definition](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-schema-definition) > [!NOTE] You may need to add or redefine configuration parameters while implementing your policy. - Review [Policy Template](#policy-template), [Wrapped Functions](#wrapped-functions), and [Flow Cancellation](#flow-cancellation) to learn about the policy’s source code structure before adding [additional policy capabilities](#provided-rust-source-code). ## Policy Template Omni Gateway Policy Development Kit (PDK) provides the initial `src/lib.rs` file in the policy project as a template to begin implementing your policy: ```Rust // Copyright 2024 Salesforce, Inc. All rights reserved. mod generated; use anyhow::{anyhow, Result}; use pdk::hl::*; use pdk::logger; use crate::generated::config::Config; // This filter shows how to log a specific request header. // You can extend the function and use the configurations exposed in config.rs file async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let token = headers_state.handler().header("Token").unwrap_or_default(); // Log the header value logger::info!("Header value: {token}"); } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_request(|rs| request_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` The policy performs some simple logging. For each incoming request, the policy logs the header `token` at the `info` log level. The following elements configure the policy: - `use pdk::api::hl::*;`: Imports all the components of PDK into the `lib.rs` source code. - `#[entrypoint]` function: Executes when the policy is applied and calls the `request_filter` function. Variables defined inside this function are avaliable while the policy is applied. The `#[entrypoint]` function receives the following parameters: - `Launcher`: Sets the filter functions. - `Configuration`: Provides the configuration parameters defined in [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-schema-definition). - `request_filter`: Executes once per every request sent to the API instance to which the policy is applied. This function implements the filtering performed by the example policy. Variables defined inside this function are available for the duration of the request. The `request_filter` is an example of a wrapped function. The `#[entrypoint]` function executes wrapped functions: ```Rust let filter = on_request(|rs| request_filter(rs, &config)); launcher.launch(filter).await?; ``` ## Wrapped Functions The `on_response` or `on_request` wrapper defines when the filter function executes. You can define custom functions other than the provided `requests_filter` and `response_filter` in the `#[entrypoint]` function. The `requests_filter` and `response_filter` are only examples. Instead of filtering an incoming request as shown in the previous example, you can process the outgoing response by using the `on_response` wrapper: ```Rust async fn response_filter(response_state: ResponseState, _config: &Config) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_response(|rs| response_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` > [!NOTE] The `request_filter` function is now the `response_filter` function. To filter both requests and responses, use both wrappers: ```Rust async fn request_filter(request_state: RequestState,_config: &Config) { ... } async fn response_filter(response_state: ResponseState,_config: &Config) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_request(|rs| request_filter(rs, &config)) .on_response(|rs| response_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` ## Flow Cancellation Custom policies run on a single-threaded environment. However, every set of wrapped functions (a `on_request` and a `on_response` `async` function) run as a concurrent task, meaning that a single policy instance handles multiple requests concurrently. To support this behavior, every `.await` is a potential task interruption point. When an `.await` is invoked, the underlying async runtime can set the current task to sleep for a moment, and awake another task that has not finished. The async runtime can cancel a task and never run code that comes after the last `.await` invocation. `on_request` and `on_response` functions assume that `.await` invocations are potential cancellation points. The most common situation, as shown in the following code example, for task cancellation is when a request function waiting for a body and an upstream policy returns an early response: ```Rust // Request function for upstream policy async fn upstream_request(state: RequestState) -> Response { Response::new(404) } // Request function for downstream policy async fn downstream_request(state: RequestState) { // Request function will be cancelled after this .await point. let body_state = state.into_body_state().await; // Code here will never be executed } ``` ## Discover PDK features with Provided Rust Source Code PDK provides code examples for the following policy features. Review [Policy Template](#policy-template) and [Wrapped Functions](#wrapped-functions) before adding the additional policy capabilities: - [Configuring Policy Logging](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-logging) - [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-headers) - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-inject-parameters) - [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-http-request) - [Using Contracts Validation Library Functions](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-contracts) - [Using CORS Library Functions](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-cors) - [Using JWT Library Functions](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-jwt) - [Using XML Validator Library Functions](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-xml-validator) - [Using JSON Validator Library Functions](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-json-validator) - [Using OAuth 2.0 Token Introspection Library Functions](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-token-introspection) - [Using DataWeave Expressions](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-dataweave) - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-share-data) - [Configuring Data Storage](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-data-storage) - [Using Third-Party Libraries](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-libraries) - [Sharing Data Between Workers and Configuring Caching](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-caching) - [Accessing Policy Metadata](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-metadata) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-rate-limiting) - [Using Spike Control Library Functions](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-spike-control) - [Filter IP Addresses](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-ip-filter) - [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-streamproperties) - [Accessing Request Authentication Information](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-authentication) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-timer) - [Reporting Policy Violations](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-violations) - [Support WebSocket APIs](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-websocket) - [Stopping Request and Response Execution](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-stop) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Implementing Your Custom Policy Features in Rust > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The following pages provide Rust code examples that complete various policy tasks. Implement the Rust code for your policy in the `src/lib.rs` file. The code examples assume you have some prior knowledge of the Rust Programming Language. For more information about programming in Rust, see: - [The Rust Programming Language Documentation](https://doc.rust-lang.org/book/) - [Rust Cookbook](https://rust-lang-nursery.github.io/rust-cookbook/intro.html) ## Before You Begin - [Create a New Project](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-project) - [Define a Schema Definition](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-schema-definition) > [!NOTE] You may need to add or redefine configuration parameters while implementing your policy. - Review [Policy Template](#policy-template), [Wrapped Functions](#wrapped-functions), and [Flow Cancellation](#flow-cancellation) to learn about the policy’s source code structure before adding [additional policy capabilities](#provided-rust-source-code). ## Policy Template Omni Gateway Policy Development Kit (PDK) provides the initial `src/lib.rs` file in the policy project as a template to begin implementing your policy: ```Rust // Copyright 2024 Salesforce, Inc. All rights reserved. mod generated; use anyhow::{anyhow, Result}; use pdk::hl::*; use pdk::logger; use crate::generated::config::Config; // This filter shows how to log a specific request header. // You can extend the function and use the configurations exposed in config.rs file async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let token = headers_state.handler().header("Token").unwrap_or_default(); // Log the header value logger::info!("Header value: {token}"); } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_request(|rs| request_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` The policy performs some simple logging. For each incoming request, the policy logs the header `token` at the `info` log level. The following elements configure the policy: - `use pdk::api::hl::*;`: Imports all the components of PDK into the `lib.rs` source code. - `#[entrypoint]` function: Executes when the policy is applied and calls the `request_filter` function. Variables defined inside this function are avaliable while the policy is applied. The `#[entrypoint]` function receives the following parameters: - `Launcher`: Sets the filter functions. - `Configuration`: Provides the configuration parameters defined in [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-schema-definition). - `request_filter`: Executes once per every request sent to the API instance to which the policy is applied. This function implements the filtering performed by the example policy. Variables defined inside this function are available for the duration of the request. The `request_filter` is an example of a wrapped function. The `#[entrypoint]` function executes wrapped functions: ```Rust let filter = on_request(|rs| request_filter(rs, &config)); launcher.launch(filter).await?; ``` ## Wrapped Functions The `on_response` or `on_request` wrapper defines when the filter function executes. You can define custom functions other than the provided `requests_filter` and `response_filter` in the `#[entrypoint]` function. The `requests_filter` and `response_filter` are only examples. Instead of filtering an incoming request as shown in the previous example, you can process the outgoing response by using the `on_response` wrapper: ```Rust async fn response_filter(response_state: ResponseState, _config: &Config) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_response(|rs| response_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` > [!NOTE] The `request_filter` function is now the `response_filter` function. To filter both requests and responses, use both wrappers: ```Rust async fn request_filter(request_state: RequestState,_config: &Config) { ... } async fn response_filter(response_state: ResponseState,_config: &Config) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).map_err(|err| { anyhow!( "Failed to parse configuration '{}'. Cause: {}", String::from_utf8_lossy(&bytes), err ) })?; let filter = on_request(|rs| request_filter(rs, &config)) .on_response(|rs| response_filter(rs, &config)); launcher.launch(filter).await?; Ok(()) } ``` ## Flow Cancellation Custom policies run on a single-threaded environment. However, every set of wrapped functions (a `on_request` and a `on_response` `async` function) run as a concurrent task, meaning that a single policy instance handles multiple requests concurrently. To support this behavior, every `.await` is a potential task interruption point. When an `.await` is invoked, the underlying async runtime can set the current task to sleep for a moment, and awake another task that has not finished. The async runtime can cancel a task and never run code that comes after the last `.await` invocation. `on_request` and `on_response` functions assume that `.await` invocations are potential cancellation points. The most common situation, as shown in the following code example, for task cancellation is when a request function waiting for a body and an upstream policy returns an early response: ```Rust // Request function for upstream policy async fn upstream_request(state: RequestState) -> Response { Response::new(404) } // Request function for downstream policy async fn downstream_request(state: RequestState) { // Request function will be cancelled after this .await point. let body_state = state.into_body_state().await; // Code here will never be executed } ``` ## Discover PDK features with Provided Rust Source Code PDK provides code examples for the following policy features. Review [Policy Template](#policy-template) and [Wrapped Functions](#wrapped-functions) before adding the additional policy capabilities: - [Configuring Policy Logging](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-logging) - [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-headers) - [Injecting Parameters](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-inject-parameters) - [Performing an HTTP Call](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-http-request) - [Using Contracts Validation Library Functions](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-contracts) - [Using CORS Library Functions](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-cors) - [Using JWT Library Functions](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-jwt) - [Using XML Validator Library Functions](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-xml-validator) - [Using JSON Validator Library Functions](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-json-validator) - [Using OAuth 2.0 Token Introspection Library Functions](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-token-introspection) - [Using DataWeave Expressions](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-dataweave) - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-share-data) - [Configuring Data Storage](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-data-storage) - [Using Third-Party Libraries](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-libraries) - [Sharing Data Between Workers and Configuring Caching](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-caching) - [Accessing Policy Metadata](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-metadata) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-rate-limiting) - [Using Spike Control Library Functions](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-spike-control) - [Filter IP Addresses](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-ip-filter) - [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-streamproperties) - [Accessing Request Authentication Information](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-authentication) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-timer) - [Reporting Policy Violations](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-violations) - [Support WebSocket APIs](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-websocket) - [Stopping Request and Response Execution](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-stop) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Injecting Parameters > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides the following parameters that you can inject into the `#[entrypoint]` configuration function: - `Configuration`: Provides the policy’s configuration parameters. For information about how to define configuration parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.2/policies-pdk-create-schema-definition). - `Metadata`: Provides metadata about the policy, the Flex Gateway instance, the API instance, and the Anypoint Organization. For more information about the metadata provided, see [Accessing Policy Metadata](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-metadata). - `HttpClient`: Enables the policy to make HTTP calls. For more information about how to make HTTP calls from the policy, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-http-request). - `CacheBuilder`: Provides the caching features of the policy. For more information about caching, see [Sharing Data Between Workers and Configuring Caching](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-caching). - `StreamProperties`: Provides a structure to share properties with other policies that process the same request. For more information about sharing information between policies, see [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-streamproperties). You can also directly inject the `HttpClient` and `StreamProperties` parameter into the `on_request` or `on_response` wrapped functions. For example, if you need to perform an HTTP call inside the `on_request` function, inject `HTTPClient` directly into that function. For best practice, inject the parameters only where they must be used. However, if the parameters require initialization steps that need to be executed only one time when the policy is applied, it is best to inject the parameters into the `#[entrypoint]` to complete the configuration steps to increase the performance of the wrapped functions. ## Inject Parameters into the on\_request and on\_response Wrapped Functions The wrapped functions accept the following parameters: - `HttpClient`: Enables the policy to make HTTP calls. For more information about how to make HTTP calls from the policy, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-http-request). - `StreamProperties`: Provides a structure to share properties with other policies that process the same request. For more information about sharing information between policies, see [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-streamproperties). - `RequestState`: Provides access to the different stages of request filtering to operate over the incoming requests headers and body. `RequestState` is only available in `on_request` functions. To read and write to the headers and body in the\`RequestState\`, see [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-headers). - `ResponseState`: Provides access to the different stages of request filtering to operate over the upstream responses headers and body. `ResponseState` is only available in `on_response` functions. To read and write to the headers and body in the `ResponseState`, see [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-headers). - `RequestData`: Share data between the `on_request` and\`on\_response\` functions. `RequestData` is only available in `on_response` functions. To learn more about `RequestData`, see [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-share-data). - `Authentication`: Provides access to read authentication data or share it with other policies. To learn more about `Authentication`, see [Accessing Request Authentication Information](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-authentication). If your wrapped functions only receive these parameters, the lambda is not required in the wrapper. For example, if the signature of the function is: ```Rust async fn request_filter(state: RequestState) -> RequestData; async fn response_filter(state: ResponseState, path: RequestData); ``` The following example demonstrates defining the lambda of a function definition: ```Rust let filter = on_request(|request_state| request_filter(request_state)) .on_response(|response_state, request_data| response_filter(response_state, request_data)); ``` Instead of defining the lambda, you can use the following function definition: ```Rust let filter = on_request(request_filter) .on_response(response_filter); ``` If your wrapped functions require other parameters, such as the configuration parameters defined in the `#[entrypoint]` function, inject the parameters into the wrapped functions. To pass the parameters, define the lambda and send a variable reference, for example: ```Rust async fn request_filter(state: RequestState, conf: &Config, tuple: &(u32, u32)) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config = serde_json::from_slice(&bytes)?; let tuple: (u32, u32) = (10, 10); let filter = on_request(|request_state| request_filter(request_state, &config, &tuple)); launcher .launch(filter) .await?; Ok(()) } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Injecting Parameters > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides the following parameters that you can inject into the `#[entrypoint]` configuration function: - `Configuration`: Provides the policy’s configuration parameters. For information about how to define configuration parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.3/policies-pdk-create-schema-definition). - `Metadata`: Provides metadata about the policy, the Flex Gateway instance, the API instance, and the Anypoint Organization. For more information about the metadata provided, see [Accessing Policy Metadata](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-metadata). - `HttpClient`: Enables the policy to make HTTP calls. For more information about how to make HTTP calls from the policy, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-http-request). - `CacheBuilder`: Provides the caching features of the policy. For more information about caching, see [Sharing Data Between Workers and Configuring Caching](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-caching). - `StreamProperties`: Provides a structure to share properties with other policies that process the same request. For more information about sharing information between policies, see [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-streamproperties). You can also directly inject the `HttpClient` and `StreamProperties` parameter into the `on_request` or `on_response` wrapped functions. For example, if you need to perform an HTTP call inside the `on_request` function, inject `HTTPClient` directly into that function. For best practice, inject the parameters only where they must be used. However, if the parameters require initialization steps that need to be executed only one time when the policy is applied, it is best to inject the parameters into the `#[entrypoint]` to complete the configuration steps to increase the performance of the wrapped functions. ## Inject Parameters into the on\_request and on\_response Wrapped Functions The wrapped functions accept the following parameters: - `HttpClient`: Enables the policy to make HTTP calls. For more information about how to make HTTP calls from the policy, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-http-request). - `StreamProperties`: Provides a structure to share properties with other policies that process the same request. For more information about sharing information between policies, see [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-streamproperties). - `RequestState`: Provides access to the different stages of request filtering to operate over the incoming requests headers and body. `RequestState` is only available in `on_request` functions. To read and write to the headers and body in the\`RequestState\`, see [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-headers). - `ResponseState`: Provides access to the different stages of request filtering to operate over the upstream responses headers and body. `ResponseState` is only available in `on_response` functions. To read and write to the headers and body in the `ResponseState`, see [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-headers). - `RequestData`: Share data between the `on_request` and\`on\_response\` functions. `RequestData` is only available in `on_response` functions. To learn more about `RequestData`, see [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-share-data). - `Authentication`: Provides access to read authentication data or share it with other policies. To learn more about `Authentication`, see [Accessing Request Authentication Information](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-authentication). If your wrapped functions only receive these parameters, the lambda is not required in the wrapper. For example, if the signature of the function is: ```Rust async fn request_filter(state: RequestState) -> RequestData; async fn response_filter(state: ResponseState, path: RequestData); ``` The following example demonstrates defining the lambda of a function definition: ```Rust let filter = on_request(|request_state| request_filter(request_state)) .on_response(|response_state, request_data| response_filter(response_state, request_data)); ``` Instead of defining the lambda, you can use the following function definition: ```Rust let filter = on_request(request_filter) .on_response(response_filter); ``` If your wrapped functions require other parameters, such as the configuration parameters defined in the `#[entrypoint]` function, inject the parameters into the wrapped functions. To pass the parameters, define the lambda and send a variable reference, for example: ```Rust async fn request_filter(state: RequestState, conf: &Config, tuple: &(u32, u32)) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config = serde_json::from_slice(&bytes)?; let tuple: (u32, u32) = (10, 10); let filter = on_request(|request_state| request_filter(request_state, &config, &tuple)); launcher .launch(filter) .await?; Ok(()) } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Injecting Parameters > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides the following parameters that you can inject into the `#[entrypoint]` configuration function: - `Configuration`: Provides the policy’s configuration parameters. For information about how to define configuration parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.4/policies-pdk-create-schema-definition). - `Metadata`: Provides metadata about the policy, the Flex Gateway instance, the API instance, and the Anypoint Organization. For more information about the metadata provided, see [Accessing Policy Metadata](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-metadata). - `HttpClient`: Enables the policy to make HTTP calls. For more information about how to make HTTP calls from the policy, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-http-request). - `CacheBuilder`: Provides the caching features of the policy. For more information about caching, see [Sharing Data Between Workers and Configuring Caching](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-caching). - `StreamProperties`: Provides a structure to share properties with other policies that process the same request. For more information about sharing information between policies, see [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-streamproperties). - `` PolicyViolations` ``: Provides a mechanism to report policy violations for your monitoring dashboards. For more information about policy violations, see [Reporting Policy Violations](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-violations). You can also directly inject the `HttpClient` and `StreamProperties` parameter into the `on_request` or `on_response` wrapped functions. For example, if you need to perform an HTTP call inside the `on_request` function, inject `HTTPClient` directly into that function. For best practice, inject the parameters only where they must be used. However, if the parameters require initialization steps that need to be executed only one time when the policy is applied, it is best to inject the parameters into the `#[entrypoint]` to complete the configuration steps to increase the performance of the wrapped functions. ## Inject Parameters into the on\_request and on\_response Wrapped Functions The wrapped functions accept the following parameters: - `HttpClient`: Enables the policy to make HTTP calls. For more information about how to make HTTP calls from the policy, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-http-request). - `StreamProperties`: Provides a structure to share properties with other policies that process the same request. For more information about sharing information between policies, see [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-streamproperties). - `RequestState`: Provides access to the different stages of request filtering to operate over the incoming requests headers and body. `RequestState` is only available in `on_request` functions. To read and write to the headers and body in the\`RequestState\`, see [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-headers). - `ResponseState`: Provides access to the different stages of request filtering to operate over the upstream responses headers and body. `ResponseState` is only available in `on_response` functions. To read and write to the headers and body in the `ResponseState`, see [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-headers). - `RequestData`: Share data between the `on_request` and\`on\_response\` functions. `RequestData` is only available in `on_response` functions. To learn more about `RequestData`, see [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-share-data). - `Authentication`: Provides access to read authentication data or share it with other policies. To learn more about `Authentication`, see [Accessing Request Authentication Information](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-authentication). If your wrapped functions only receive these parameters, the lambda is not required in the wrapper. For example, if the signature of the function is: ```Rust async fn request_filter(state: RequestState) -> RequestData; async fn response_filter(state: ResponseState, path: RequestData); ``` The following example demonstrates defining the lambda of a function definition: ```Rust let filter = on_request(|request_state| request_filter(request_state)) .on_response(|response_state, request_data| response_filter(response_state, request_data)); ``` Instead of defining the lambda, you can use the following function definition: ```Rust let filter = on_request(request_filter) .on_response(response_filter); ``` If your wrapped functions require other parameters, such as the configuration parameters defined in the `#[entrypoint]` function, inject the parameters into the wrapped functions. To pass the parameters, define the lambda and send a variable reference, for example: ```Rust async fn request_filter(state: RequestState, conf: &Config, tuple: &(u32, u32)) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config = serde_json::from_slice(&bytes)?; let tuple: (u32, u32) = (10, 10); let filter = on_request(|request_state| request_filter(request_state, &config, &tuple)); launcher .launch(filter) .await?; Ok(()) } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Injecting Parameters > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides the following parameters that you can inject into the `#[entrypoint]` configuration function: - `Configuration`: Provides the policy’s configuration parameters. For information about how to define configuration parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.5/policies-pdk-create-schema-definition). - `Metadata`: Provides metadata about the policy, the Flex Gateway instance, the API instance, and the Anypoint Organization. For more information about the metadata provided, see [Accessing Policy Metadata](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-metadata). - `HttpClient`: Enables the policy to make HTTP calls. For more information about how to make HTTP calls from the policy, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-http-request). - `CacheBuilder`: Provides the caching features of the policy. For more information about caching, see [Sharing Data Between Workers and Configuring Caching](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-caching). - `StreamProperties`: Provides a structure to share properties with other policies that process the same request. For more information about sharing information between policies, see [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-streamproperties). - `` PolicyViolations` ``: Provides a mechanism to report policy violations for your monitoring dashboards. For more information about policy violations, see [Reporting Policy Violations](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-violations). - `RateLimitBuilder`: Provides rate limiting functionality to control request rates. For more information about rate limiting, see [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-rate-limiting). You can also directly inject the `HttpClient` and `StreamProperties` parameter into the `on_request` or `on_response` wrapped functions. For example, if you need to perform an HTTP call inside the `on_request` function, inject `HTTPClient` directly into that function. For best practice, inject the parameters only where they must be used. However, if the parameters require initialization steps that need to be executed only one time when the policy is applied, it is best to inject the parameters into the `#[entrypoint]` to complete the configuration steps to increase the performance of the wrapped functions. ## Inject Parameters into the on\_request and on\_response Wrapped Functions The wrapped functions accept the following parameters: - `HttpClient`: Enables the policy to make HTTP calls. For more information about how to make HTTP calls from the policy, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-http-request). - `StreamProperties`: Provides a structure to share properties with other policies that process the same request. For more information about sharing information between policies, see [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-streamproperties). - `RequestState`: Provides access to the different stages of request filtering to operate over the incoming requests headers and body. `RequestState` is only available in `on_request` functions. To read and write to the headers and body in the\`RequestState\`, see [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-headers). - `ResponseState`: Provides access to the different stages of request filtering to operate over the upstream responses headers and body. `ResponseState` is only available in `on_response` functions. To read and write to the headers and body in the `ResponseState`, see [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-headers). - `RequestData`: Share data between the `on_request` and\`on\_response\` functions. `RequestData` is only available in `on_response` functions. To learn more about `RequestData`, see [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-share-data). - `Authentication`: Provides access to read authentication data or share it with other policies. To learn more about `Authentication`, see [Accessing Request Authentication Information](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-authentication). If your wrapped functions only receive these parameters, the lambda is not required in the wrapper. For example, if the signature of the function is: ```Rust async fn request_filter(state: RequestState) -> RequestData; async fn response_filter(state: ResponseState, path: RequestData); ``` The following example demonstrates defining the lambda of a function definition: ```Rust let filter = on_request(|request_state| request_filter(request_state)) .on_response(|response_state, request_data| response_filter(response_state, request_data)); ``` Instead of defining the lambda, you can use the following function definition: ```Rust let filter = on_request(request_filter) .on_response(response_filter); ``` If your wrapped functions require other parameters, such as the configuration parameters defined in the `#[entrypoint]` function, inject the parameters into the wrapped functions. To pass the parameters, define the lambda and send a variable reference, for example: ```Rust async fn request_filter(state: RequestState, conf: &Config, tuple: &(u32, u32)) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config = serde_json::from_slice(&bytes)?; let tuple: (u32, u32) = (10, 10); let filter = on_request(|request_state| request_filter(request_state, &config, &tuple)); launcher .launch(filter) .await?; Ok(()) } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Injecting Parameters > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides the following parameters that you can inject into the `#[entrypoint]` configuration function: - `Configuration`: Provides the policy’s configuration parameters. For information about how to define configuration parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.6/policies-pdk-create-schema-definition). - `Metadata`: Provides metadata about the policy, the Flex Gateway instance, the API instance, and the Anypoint Organization. For more information about the metadata provided, see [Accessing Policy Metadata](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-metadata). - `HttpClient`: Enables the policy to make HTTP calls. For more information about how to make HTTP calls from the policy, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-http-request). - `CacheBuilder`: Provides the caching features of the policy. For more information about caching, see [Sharing Data Between Workers and Configuring Caching](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-caching). - `StreamProperties`: Provides a structure to share properties with other policies that process the same request. For more information about sharing information between policies, see [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-streamproperties). - `` PolicyViolations` ``: Provides a mechanism to report policy violations for your monitoring dashboards. For more information about policy violations, see [Reporting Policy Violations](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-violations). - `RateLimitBuilder`: Provides rate limiting functionality to control request rates. For more information about rate limiting, see [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-rate-limiting). You can also directly inject the `HttpClient` and `StreamProperties` parameter into the `on_request` or `on_response` wrapped functions. For example, if you need to perform an HTTP call inside the `on_request` function, inject `HTTPClient` directly into that function. For best practice, inject the parameters only where they must be used. However, if the parameters require initialization steps that need to be executed only one time when the policy is applied, it is best to inject the parameters into the `#[entrypoint]` to complete the configuration steps to increase the performance of the wrapped functions. ## Inject Parameters into the on\_request and on\_response Wrapped Functions The wrapped functions accept the following parameters: - `HttpClient`: Enables the policy to make HTTP calls. For more information about how to make HTTP calls from the policy, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-http-request). - `StreamProperties`: Provides a structure to share properties with other policies that process the same request. For more information about sharing information between policies, see [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-streamproperties). - `RequestState`: Provides access to the different stages of request filtering to operate over the incoming requests headers and body. `RequestState` is only available in `on_request` functions. To read and write to the headers and body in the\`RequestState\`, see [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-headers). - `ResponseState`: Provides access to the different stages of request filtering to operate over the upstream responses headers and body. `ResponseState` is only available in `on_response` functions. To read and write to the headers and body in the `ResponseState`, see [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-headers). - `RequestData`: Share data between the `on_request` and\`on\_response\` functions. `RequestData` is only available in `on_response` functions. To learn more about `RequestData`, see [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-share-data). - `Authentication`: Provides access to read authentication data or share it with other policies. To learn more about `Authentication`, see [Accessing Request Authentication Information](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-authentication). If your wrapped functions only receive these parameters, the lambda is not required in the wrapper. For example, if the signature of the function is: ```Rust async fn request_filter(state: RequestState) -> RequestData; async fn response_filter(state: ResponseState, path: RequestData); ``` The following example demonstrates defining the lambda of a function definition: ```Rust let filter = on_request(|request_state| request_filter(request_state)) .on_response(|response_state, request_data| response_filter(response_state, request_data)); ``` Instead of defining the lambda, you can use the following function definition: ```Rust let filter = on_request(request_filter) .on_response(response_filter); ``` If your wrapped functions require other parameters, such as the configuration parameters defined in the `#[entrypoint]` function, inject the parameters into the wrapped functions. To pass the parameters, define the lambda and send a variable reference, for example: ```Rust async fn request_filter(state: RequestState, conf: &Config, tuple: &(u32, u32)) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config = serde_json::from_slice(&bytes)?; let tuple: (u32, u32) = (10, 10); let filter = on_request(|request_state| request_filter(request_state, &config, &tuple)); launcher .launch(filter) .await?; Ok(()) } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Injecting Parameters > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides the following parameters that you can inject into the `#[entrypoint]` configuration function: - `Configuration`: Provides the policy’s configuration parameters. For information about how to define configuration parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-schema-definition). - `Metadata`: Provides metadata about the policy, the Flex Gateway instance, the API instance, and the Anypoint Organization. For more information about the metadata provided, see [Accessing Policy Metadata](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-metadata). - `HttpClient`: Enables the policy to make HTTP calls. For more information about how to make HTTP calls from the policy, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-http-request). - `CacheBuilder`: Provides the caching features of the policy. For more information about caching, see [Sharing Data Between Workers and Configuring Caching](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-caching). - `StreamProperties`: Provides a structure to share properties with other policies that process the same request. For more information about sharing information between policies, see [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-streamproperties). - `` PolicyViolations` ``: Provides a mechanism to report policy violations for your monitoring dashboards. For more information about policy violations, see [Reporting Policy Violations](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-violations). - `RateLimitBuilder`: Provides rate limiting functionality to control request rates. For more information about rate limiting, see [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-rate-limiting). You can also directly inject the `HttpClient` and `StreamProperties` parameter into the `on_request` or `on_response` wrapped functions. For example, if you need to perform an HTTP call inside the `on_request` function, inject `HTTPClient` directly into that function. For best practice, inject the parameters only where they must be used. However, if the parameters require initialization steps that need to be executed only one time when the policy is applied, it is best to inject the parameters into the `#[entrypoint]` to complete the configuration steps to increase the performance of the wrapped functions. ## Inject Parameters into the on\_request and on\_response Wrapped Functions The wrapped functions accept the following parameters: - `HttpClient`: Enables the policy to make HTTP calls. For more information about how to make HTTP calls from the policy, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-http-request). - `StreamProperties`: Provides a structure to share properties with other policies that process the same request. For more information about sharing information between policies, see [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-streamproperties). - `RequestState`: Provides access to the different stages of request filtering to operate over the incoming requests headers and body. `RequestState` is only available in `on_request` functions. To read and write to the headers and body in the\`RequestState\`, see [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-headers). - `ResponseState`: Provides access to the different stages of request filtering to operate over the upstream responses headers and body. `ResponseState` is only available in `on_response` functions. To read and write to the headers and body in the `ResponseState`, see [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-headers). - `RequestData`: Share data between the `on_request` and\`on\_response\` functions. `RequestData` is only available in `on_response` functions. To learn more about `RequestData`, see [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-share-data). - `Authentication`: Provides access to read authentication data or share it with other policies. To learn more about `Authentication`, see [Accessing Request Authentication Information](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-authentication). If your wrapped functions only receive these parameters, the lambda is not required in the wrapper. For example, if the signature of the function is: ```Rust async fn request_filter(state: RequestState) -> RequestData; async fn response_filter(state: ResponseState, path: RequestData); ``` The following example demonstrates defining the lambda of a function definition: ```Rust let filter = on_request(|request_state| request_filter(request_state)) .on_response(|response_state, request_data| response_filter(response_state, request_data)); ``` Instead of defining the lambda, you can use the following function definition: ```Rust let filter = on_request(request_filter) .on_response(response_filter); ``` If your wrapped functions require other parameters, such as the configuration parameters defined in the `#[entrypoint]` function, inject the parameters into the wrapped functions. To pass the parameters, define the lambda and send a variable reference, for example: ```Rust async fn request_filter(state: RequestState, conf: &Config, tuple: &(u32, u32)) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config = serde_json::from_slice(&bytes)?; let tuple: (u32, u32) = (10, 10); let filter = on_request(|request_state| request_filter(request_state, &config, &tuple)); launcher .launch(filter) .await?; Ok(()) } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Injecting Parameters > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) provides the following parameters that you can inject into the `#[entrypoint]` configuration function: - `Configuration`: Provides the policy’s configuration parameters. For information about how to define configuration parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-schema-definition). - `Metadata`: Provides metadata about the policy, the Omni Gateway instance, the API instance, and the Anypoint Organization. For more information about the metadata provided, see [Accessing Policy Metadata](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-metadata). - `HttpClient`: Enables the policy to make HTTP calls. For more information about how to make HTTP calls from the policy, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-http-request). - `CacheBuilder`: Provides the caching features of the policy. For more information about caching, see [Sharing Data Between Workers and Configuring Caching](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-caching). - `StreamProperties`: Provides a structure to share properties with other policies that process the same request. For more information about sharing information between policies, see [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-streamproperties). - `` PolicyViolations` ``: Provides a mechanism to report policy violations for your monitoring dashboards. For more information about policy violations, see [Reporting Policy Violations](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-violations). - `RateLimitBuilder`: Provides rate limiting functionality to control request rates. For more information about rate limiting, see [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-rate-limiting). You can also directly inject the `HttpClient` and `StreamProperties` parameter into the `on_request` or `on_response` wrapped functions. For example, if you need to perform an HTTP call inside the `on_request` function, inject `HTTPClient` directly into that function. For best practice, inject the parameters only where they must be used. However, if the parameters require initialization steps that need to be executed only one time when the policy is applied, it is best to inject the parameters into the `#[entrypoint]` to complete the configuration steps to increase the performance of the wrapped functions. ## Inject Parameters into the on\_request and on\_response Wrapped Functions The wrapped functions accept the following parameters: - `HttpClient`: Enables the policy to make HTTP calls. For more information about how to make HTTP calls from the policy, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-http-request). - `StreamProperties`: Provides a structure to share properties with other policies that process the same request. For more information about sharing information between policies, see [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-streamproperties). - `RequestState`: Provides access to the different stages of request filtering to operate over the incoming requests headers and body. `RequestState` is only available in `on_request` functions. To read and write to the headers and body in the\`RequestState\`, see [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-headers). - `ResponseState`: Provides access to the different stages of request filtering to operate over the upstream responses headers and body. `ResponseState` is only available in `on_response` functions. To read and write to the headers and body in the `ResponseState`, see [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-headers). - `RequestData`: Share data between the `on_request` and\`on\_response\` functions. `RequestData` is only available in `on_response` functions. To learn more about `RequestData`, see [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-share-data). - `Authentication`: Provides access to read authentication data or share it with other policies. To learn more about `Authentication`, see [Accessing Request Authentication Information](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-authentication). If your wrapped functions only receive these parameters, the lambda is not required in the wrapper. For example, if the signature of the function is: ```Rust async fn request_filter(state: RequestState) -> RequestData; async fn response_filter(state: ResponseState, path: RequestData); ``` The following example demonstrates defining the lambda of a function definition: ```Rust let filter = on_request(|request_state| request_filter(request_state)) .on_response(|response_state, request_data| response_filter(response_state, request_data)); ``` Instead of defining the lambda, you can use the following function definition: ```Rust let filter = on_request(request_filter) .on_response(response_filter); ``` If your wrapped functions require other parameters, such as the configuration parameters defined in the `#[entrypoint]` function, inject the parameters into the wrapped functions. To pass the parameters, define the lambda and send a variable reference, for example: ```Rust async fn request_filter(state: RequestState, conf: &Config, tuple: &(u32, u32)) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config = serde_json::from_slice(&bytes)?; let tuple: (u32, u32) = (10, 10); let filter = on_request(|request_state| request_filter(request_state, &config, &tuple)); launcher .launch(filter) .await?; Ok(()) } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Injecting Parameters > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) provides the following parameters that you can inject into the `#[entrypoint]` configuration function: - `Configuration`: Provides the policy’s configuration parameters. For information about how to define configuration parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-schema-definition). - `Metadata`: Provides metadata about the policy, the Omni Gateway instance, the API instance, and the Anypoint Organization. For more information about the metadata provided, see [Accessing Policy Metadata](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-metadata). - `HttpClient`: Enables the policy to make HTTP calls. For more information about how to make HTTP calls from the policy, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-http-request). - `CacheBuilder`: Provides the caching features of the policy. For more information about caching, see [Sharing Data Between Workers and Configuring Caching](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-caching). - `StreamProperties`: Provides a structure to share properties with other policies that process the same request. For more information about sharing information between policies, see [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-streamproperties). - `` PolicyViolations` ``: Provides a mechanism to report policy violations for your monitoring dashboards. For more information about policy violations, see [Reporting Policy Violations](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-violations). - `RateLimitBuilder`: Provides rate limiting functionality to control request rates. For more information about rate limiting, see [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-rate-limiting). You can also directly inject the `HttpClient` and `StreamProperties` parameter into the `on_request` or `on_response` wrapped functions. For example, if you need to perform an HTTP call inside the `on_request` function, inject `HTTPClient` directly into that function. For best practice, inject the parameters only where they must be used. However, if the parameters require initialization steps that need to be executed only one time when the policy is applied, it is best to inject the parameters into the `#[entrypoint]` to complete the configuration steps to increase the performance of the wrapped functions. ## Inject Parameters into the on\_request and on\_response Wrapped Functions The wrapped functions accept the following parameters: - `HttpClient`: Enables the policy to make HTTP calls. For more information about how to make HTTP calls from the policy, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-http-request). - `StreamProperties`: Provides a structure to share properties with other policies that process the same request. For more information about sharing information between policies, see [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-streamproperties). - `RequestState`: Provides access to the different stages of request filtering to operate over the incoming requests headers and body. `RequestState` is only available in `on_request` functions. To read and write to the headers and body in the\`RequestState\`, see [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-headers). - `ResponseState`: Provides access to the different stages of request filtering to operate over the upstream responses headers and body. `ResponseState` is only available in `on_response` functions. To read and write to the headers and body in the `ResponseState`, see [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-headers). - `RequestData`: Share data between the `on_request` and\`on\_response\` functions. `RequestData` is only available in `on_response` functions. To learn more about `RequestData`, see [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-share-data). - `Authentication`: Provides access to read authentication data or share it with other policies. To learn more about `Authentication`, see [Accessing Request Authentication Information](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-authentication). If your wrapped functions only receive these parameters, the lambda is not required in the wrapper. For example, if the signature of the function is: ```Rust async fn request_filter(state: RequestState) -> RequestData; async fn response_filter(state: ResponseState, path: RequestData); ``` The following example demonstrates defining the lambda of a function definition: ```Rust let filter = on_request(|request_state| request_filter(request_state)) .on_response(|response_state, request_data| response_filter(response_state, request_data)); ``` Instead of defining the lambda, you can use the following function definition: ```Rust let filter = on_request(request_filter) .on_response(response_filter); ``` If your wrapped functions require other parameters, such as the configuration parameters defined in the `#[entrypoint]` function, inject the parameters into the wrapped functions. To pass the parameters, define the lambda and send a variable reference, for example: ```Rust async fn request_filter(state: RequestState, conf: &Config, tuple: &(u32, u32)) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config = serde_json::from_slice(&bytes)?; let tuple: (u32, u32) = (10, 10); let filter = on_request(|request_state| request_filter(request_state, &config, &tuple)); launcher .launch(filter) .await?; Ok(()) } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Injecting Parameters > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) provides the following parameters that you can inject into the `#[entrypoint]` configuration function: - `Configuration`: Provides the policy’s configuration parameters. For information about how to define configuration parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-schema-definition). - `Metadata`: Provides metadata about the policy, the Omni Gateway instance, the API instance, and the Anypoint Organization. For more information about the metadata provided, see [Accessing Policy Metadata](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-metadata). - `HttpClient`: Enables the policy to make HTTP calls. For more information about how to make HTTP calls from the policy, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-http-request). - `CacheBuilder`: Provides the caching features of the policy. For more information about caching, see [Sharing Data Between Workers and Configuring Caching](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-caching). - `StreamProperties`: Provides a structure to share properties with other policies that process the same request. For more information about sharing information between policies, see [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-streamproperties). - `` PolicyViolations` ``: Provides a mechanism to report policy violations for your monitoring dashboards. For more information about policy violations, see [Reporting Policy Violations](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-violations). - `RateLimitBuilder`: Provides rate limiting functionality to control request rates. For more information about rate limiting, see [Rate Limiting Requests](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-rate-limiting). You can also directly inject the `HttpClient` and `StreamProperties` parameter into the `on_request` or `on_response` wrapped functions. For example, if you need to perform an HTTP call inside the `on_request` function, inject `HTTPClient` directly into that function. For best practice, inject the parameters only where they must be used. However, if the parameters require initialization steps that need to be executed only one time when the policy is applied, it is best to inject the parameters into the `#[entrypoint]` to complete the configuration steps to increase the performance of the wrapped functions. ## Inject Parameters into the on\_request and on\_response Wrapped Functions The wrapped functions accept the following parameters: - `HttpClient`: Enables the policy to make HTTP calls. For more information about how to make HTTP calls from the policy, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-http-request). - `StreamProperties`: Provides a structure to share properties with other policies that process the same request. For more information about sharing information between policies, see [Sharing Data Between Policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-streamproperties). - `RequestState`: Provides access to the different stages of request filtering to operate over the incoming requests headers and body. `RequestState` is only available in `on_request` functions. To read and write to the headers and body in the\`RequestState\`, see [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-headers). - `ResponseState`: Provides access to the different stages of request filtering to operate over the upstream responses headers and body. `ResponseState` is only available in `on_response` functions. To read and write to the headers and body in the `ResponseState`, see [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-headers). - `RequestData`: Share data between the `on_request` and\`on\_response\` functions. `RequestData` is only available in `on_response` functions. To learn more about `RequestData`, see [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-share-data). - `Authentication`: Provides access to read authentication data or share it with other policies. To learn more about `Authentication`, see [Accessing Request Authentication Information](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-authentication). If your wrapped functions only receive these parameters, the lambda is not required in the wrapper. For example, if the signature of the function is: ```Rust async fn request_filter(state: RequestState) -> RequestData; async fn response_filter(state: ResponseState, path: RequestData); ``` The following example demonstrates defining the lambda of a function definition: ```Rust let filter = on_request(|request_state| request_filter(request_state)) .on_response(|response_state, request_data| response_filter(response_state, request_data)); ``` Instead of defining the lambda, you can use the following function definition: ```Rust let filter = on_request(request_filter) .on_response(response_filter); ``` If your wrapped functions require other parameters, such as the configuration parameters defined in the `#[entrypoint]` function, inject the parameters into the wrapped functions. To pass the parameters, define the lambda and send a variable reference, for example: ```Rust async fn request_filter(state: RequestState, conf: &Config, tuple: &(u32, u32)) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config = serde_json::from_slice(&bytes)?; let tuple: (u32, u32) = (10, 10); let filter = on_request(|request_state| request_filter(request_state, &config, &tuple)); launcher .launch(filter) .await?; Ok(()) } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Omni Gateway Policy Development Kit (PDK) Overview > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Policies enforce regulations to help manage security, control traffic, and improve API adoption. Omni Gateway provides many [included policies](https://docs.mulesoft.com/gateway/latest/policies-included-directory), but they might not cover all your specific business needs. Omni Gateway (formerly Flex Gateway) Policy Development Kit (PDK) is a software development kit that enables you to develop custom policies with ease. PDK provides instructions to guide you through the policy development lifecycle, from implementing your Rust source code to releasing your policy on Exchange. Like included policies, you can apply custom policies to Omni Gateway running in Connected Mode by using API Manager or to Omni Gateway running in Local Mode by using YAML configuration files. PDK provides [example policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-policy-templates) to help you get started with policy development and the [MuleSoft MCP Server Policy Management Tools](https://docs.mulesoft.com/mulesoft-mcp-server/reference-mcp-tools#policy-management) to help manage the custom policy lifecycle. Watch the PDK Product Spotlight video to see a quick overview of PDK. ![](https://play.vidyard.com/ibt7HZ8SByp9VCn88dNPx7.jpg) ## See Also - [Review the architecture](https://docs.mulesoft.com/pdk/1.8/policies-pdk-architecture) - [Review the prerequisites](https://docs.mulesoft.com/pdk/1.8/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Omni Gateway Policy Development Kit (PDK) Overview > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Policies enforce regulations to help manage security, control traffic, and improve API adoption. Omni Gateway provides many [included policies](https://docs.mulesoft.com/gateway/latest/policies-included-directory), but they might not cover all your specific business needs. Omni Gateway (formerly Flex Gateway) Policy Development Kit (PDK) is a software development kit that enables you to develop custom policies with ease. PDK provides instructions to guide you through the policy development lifecycle, from implementing your Rust source code to releasing your policy on Exchange. Like included policies, you can apply custom policies to Omni Gateway running in Connected Mode by using API Manager or to Omni Gateway running in Local Mode by using YAML configuration files. PDK provides [example policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-policy-templates) to help you get started with policy development and the [MuleSoft MCP Server Policy Management Tools](https://docs.mulesoft.com/mulesoft-mcp-server/reference-mcp-tools#policy-management) to help manage the custom policy lifecycle. Watch the PDK Product Spotlight video to see a quick overview of PDK. ![](https://play.vidyard.com/ibt7HZ8SByp9VCn88dNPx7.jpg) ## See Also - [Review the architecture](https://docs.mulesoft.com/pdk/1.9/policies-pdk-architecture) - [Review the prerequisites](https://docs.mulesoft.com/pdk/1.9/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Omni Gateway Policy Development Kit (PDK) Overview > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Policies enforce regulations to help manage security, control traffic, and improve API adoption. Omni Gateway provides many [included policies](https://docs.mulesoft.com/gateway/latest/policies-included-directory), but they might not cover all your specific business needs. Omni Gateway (formerly Flex Gateway) Policy Development Kit (PDK) is a software development kit that enables you to develop custom policies with ease. PDK provides instructions to guide you through the policy development lifecycle, from implementing your Rust source code to releasing your policy on Exchange. Like included policies, you can apply custom policies to Omni Gateway running in Connected Mode by using API Manager or to Omni Gateway running in Local Mode by using YAML configuration files. PDK provides [example policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-policy-templates) to help you get started with policy development and the [MuleSoft MCP Server Policy Management Tools](https://docs.mulesoft.com/mulesoft-mcp-server/reference-mcp-tools#policy-management) to help manage the custom policy lifecycle. Watch the PDK Product Spotlight video to see a quick overview of PDK. ![](https://play.vidyard.com/ibt7HZ8SByp9VCn88dNPx7.jpg) ## See Also - [Review the architecture](https://docs.mulesoft.com/pdk/latest/policies-pdk-architecture) - [Review the prerequisites](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Omni Gateway Policy Development Kit (PDK) Release Notes > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) is a software development kit that enables you to develop Omni Gateway custom policies with ease. PDK provides instructions to guide you through the policy development lifecycle, from implementing your Rust source code to releasing your policy on Exchange. Like included policies, you can apply custom policies to Omni Gateway running in Connected Mode by using API Manager or to Omni Gateway running in Local Mode by using YAML configuration files. The following release notes are provided for PDK: - [Omni Gateway Policy Development Kit (PDK) Release Notes](https://docs.mulesoft.com/release-notes/pdk/pdk-release-notes) ## See Also - [Omni Gateway Policy Development Kit (PDK) Overview](https://docs.mulesoft.com/pdk/latest/policies-pdk-overview) - [Omni Gateway Overview](https://docs.mulesoft.com/gateway/latest/) - [Known Issues](https://help.salesforce.com/s/issues) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Omni Gateway Policy Development Kit (PDK) Release Notes > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) is a software development kit that enables you to develop Omni Gateway custom policies with ease. PDK provides instructions to guide you through the policy development lifecycle, from implementing your Rust source code to releasing your policy on Exchange. Like included policies, you can apply custom policies to Omni Gateway running in Connected Mode by using API Manager or to Omni Gateway running in Local Mode by using YAML configuration files. The following release notes are provided for PDK: - [Omni Gateway Policy Development Kit (PDK) Release Notes](https://docs.mulesoft.com/release-notes/pdk/pdk-release-notes) ## See Also - [Omni Gateway Policy Development Kit (PDK) Overview](https://docs.mulesoft.com/pdk/latest/policies-pdk-overview) - [Omni Gateway Overview](https://docs.mulesoft.com/gateway/latest/) - [Known Issues](https://help.salesforce.com/s/issues) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Omni Gateway Policy Development Kit (PDK) Release Notes > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) is a software development kit that enables you to develop Omni Gateway custom policies with ease. PDK provides instructions to guide you through the policy development lifecycle, from implementing your Rust source code to releasing your policy on Exchange. Like included policies, you can apply custom policies to Omni Gateway running in Connected Mode by using API Manager or to Omni Gateway running in Local Mode by using YAML configuration files. The following release notes are provided for PDK: - [Omni Gateway Policy Development Kit (PDK) Release Notes](https://docs.mulesoft.com/release-notes/pdk/pdk-release-notes) ## See Also - [Omni Gateway Policy Development Kit (PDK) Overview](https://docs.mulesoft.com/pdk/latest/policies-pdk-overview) - [Omni Gateway Overview](https://docs.mulesoft.com/gateway/latest/) - [Known Issues](https://help.salesforce.com/s/issues) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Omni Gateway Policy Development Kit (PDK) Release Notes > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) is a software development kit that enables you to develop Omni Gateway custom policies with ease. PDK provides instructions to guide you through the policy development lifecycle, from implementing your Rust source code to releasing your policy on Exchange. Like included policies, you can apply custom policies to Omni Gateway running in Connected Mode by using API Manager or to Omni Gateway running in Local Mode by using YAML configuration files. The following release notes are provided for PDK: - [Omni Gateway Policy Development Kit (PDK) Release Notes](https://docs.mulesoft.com/release-notes/pdk/pdk-release-notes) ## See Also - [Omni Gateway Policy Development Kit (PDK) Overview](https://docs.mulesoft.com/pdk/latest/policies-pdk-overview) - [Omni Gateway Overview](https://docs.mulesoft.com/gateway/latest/) - [Known Issues](https://help.salesforce.com/s/issues) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Omni Gateway Policy Development Kit (PDK) Release Notes > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) is a software development kit that enables you to develop Omni Gateway custom policies with ease. PDK provides instructions to guide you through the policy development lifecycle, from implementing your Rust source code to releasing your policy on Exchange. Like included policies, you can apply custom policies to Omni Gateway running in Connected Mode by using API Manager or to Omni Gateway running in Local Mode by using YAML configuration files. The following release notes are provided for PDK: - [Omni Gateway Policy Development Kit (PDK) Release Notes](https://docs.mulesoft.com/release-notes/pdk/pdk-release-notes) ## See Also - [Omni Gateway Policy Development Kit (PDK) Overview](https://docs.mulesoft.com/pdk/latest/policies-pdk-overview) - [Omni Gateway Overview](https://docs.mulesoft.com/gateway/latest/) - [Known Issues](https://help.salesforce.com/s/issues) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Omni Gateway Policy Development Kit (PDK) Release Notes > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) is a software development kit that enables you to develop Omni Gateway custom policies with ease. PDK provides instructions to guide you through the policy development lifecycle, from implementing your Rust source code to releasing your policy on Exchange. Like included policies, you can apply custom policies to Omni Gateway running in Connected Mode by using API Manager or to Omni Gateway running in Local Mode by using YAML configuration files. The following release notes are provided for PDK: - [Omni Gateway Policy Development Kit (PDK) Release Notes](https://docs.mulesoft.com/release-notes/pdk/pdk-release-notes) ## See Also - [Omni Gateway Policy Development Kit (PDK) Overview](https://docs.mulesoft.com/pdk/latest/policies-pdk-overview) - [Omni Gateway Overview](https://docs.mulesoft.com/gateway/latest/) - [Known Issues](https://help.salesforce.com/s/issues) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Omni Gateway Policy Development Kit (PDK) Release Notes > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) is a software development kit that enables you to develop Omni Gateway custom policies with ease. PDK provides instructions to guide you through the policy development lifecycle, from implementing your Rust source code to releasing your policy on Exchange. Like included policies, you can apply custom policies to Omni Gateway running in Connected Mode by using API Manager or to Omni Gateway running in Local Mode by using YAML configuration files. The following release notes are provided for PDK: - [Omni Gateway Policy Development Kit (PDK) Release Notes](https://docs.mulesoft.com/release-notes/pdk/pdk-release-notes) ## See Also - [Omni Gateway Policy Development Kit (PDK) Overview](https://docs.mulesoft.com/pdk/latest/policies-pdk-overview) - [Omni Gateway Overview](https://docs.mulesoft.com/gateway/latest/) - [Known Issues](https://help.salesforce.com/s/issues) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Omni Gateway Policy Development Kit (PDK) Release Notes > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) is a software development kit that enables you to develop Omni Gateway custom policies with ease. PDK provides instructions to guide you through the policy development lifecycle, from implementing your Rust source code to releasing your policy on Exchange. Like included policies, you can apply custom policies to Omni Gateway running in Connected Mode by using API Manager or to Omni Gateway running in Local Mode by using YAML configuration files. The following release notes are provided for PDK: - [Omni Gateway Policy Development Kit (PDK) Release Notes](https://docs.mulesoft.com/release-notes/pdk/pdk-release-notes) ## See Also - [Omni Gateway Policy Development Kit (PDK) Overview](https://docs.mulesoft.com/pdk/latest/policies-pdk-overview) - [Omni Gateway Overview](https://docs.mulesoft.com/gateway/latest/) - [Known Issues](https://help.salesforce.com/s/issues) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Omni Gateway Policy Development Kit (PDK) Release Notes > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) is a software development kit that enables you to develop Omni Gateway custom policies with ease. PDK provides instructions to guide you through the policy development lifecycle, from implementing your Rust source code to releasing your policy on Exchange. Like included policies, you can apply custom policies to Omni Gateway running in Connected Mode by using API Manager or to Omni Gateway running in Local Mode by using YAML configuration files. The following release notes are provided for PDK: - [Omni Gateway Policy Development Kit (PDK) Release Notes](https://docs.mulesoft.com/release-notes/pdk/pdk-release-notes) ## See Also - [Omni Gateway Policy Development Kit (PDK) Overview](https://docs.mulesoft.com/pdk/latest/policies-pdk-overview) - [Omni Gateway Overview](https://docs.mulesoft.com/gateway/latest/) - [Known Issues](https://help.salesforce.com/s/issues) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # PDK Troubleshooting > For the full documentation index, see: https://docs.mulesoft.com/llms.txt When using Flex Gateway Policy Development Kit (PDK), you might encounter issues with PDK itself. See the following sections to help you resolve these issues: - [Cargo-Generate Error on a Mac Device](#cargo-generate) - [Anypoint CLI Credentials Error](#cli-credential) - [Group ID Error When Creating the Policy Project](#group-id-error) - [401 Authorization Error When Running Make Setup](#authorization-error) To debug issues with your custom policy, see: - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.2/policies-pdk-debug-local) - [Debugging Deployed Custom Policies](https://docs.mulesoft.com/pdk/1.2/policies-pdk-debug-deployed-policies) ## Cargo-Generate Error on a Mac Device When compiling Rust on a Mac Device for the first time, the following error might occur: ```ssh $ cargo install cargo-generate error: linking with `cc` failed: exit status: 1 [...] ``` To troubleshoot this error: 1. Ensure Xcode is installed, then compile again. To install Xcode, execute the following command: ```ssh xcode-select --install ``` 2. If Xcode is installed and PDK still does not compile, create or edit the `~/.cargo/config.toml` file by adding the following: ```toml [target.x86_64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] [target.aarch64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] ``` ## Anypoint CLI Credentials Error Anypoint CLI requires multi-factor authentication (MFA) with a Connected App. Using any PDK command without Connected App credentials results in an error similar to the following: ```ssh Error: Failed to launch the browser process! undefined [...]:ERROR:ozone_platform_x11.cc(239)] Missing X server or $DISPLAY [21921:21921:1103/113335.217708:ERROR:env.cc(255)] The platform failed to initialize. Exiting. TROUBLESHOOTING: https://pptr.dev/troubleshooting ``` To configure Anypoint CLI with MFA authentication using a Connected App, refer to [Authentication to the Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/auth). ## Group ID Error When Creating the Policy Project Anypoint CLI uses the `ANYPOINT_ORG` environment variable. This variable can use either the organization name or the organization ID as the value. If the variable is set to the organization name, the [policy creation command](https://docs.mulesoft.com/pdk/1.2/policies-pdk-create-project) fails to infer the group ID of the organization. Use the organization ID for the value of `ANYPOINT_ORG`. However, if you cannot change the variable, use one of the following methods to provide the group ID: - If you run the create command and receive the following prompt: ```ssh Please provide a valid group-id (the id of the organization that will own the asset): ``` Enter your group ID, then press Enter. - Use the `--group-id` flag when creating the PDK project, for example: ```ssh anypoint-cli-v4 pdk policy-project create -n --group-id ``` ## 401 Authorization Error When Running Make Setup When executing \`make setup', the following error might occur: ```ssh $ make setup Login token for `anypoint` saved [...] Caused by: failed to get successful HTTP response from `https://anypoint.mulesoft.com/crates[...]/download` [...], got 401 body: make: *** [install-cargo-anypoint] Error 101 ``` This error occurs when your version of Rust is not v1.74.0 or later. To solve this error, refer to [Rust Requirements for Using PDK](https://docs.mulesoft.com/pdk/1.2/policies-pdk-prerequisites#rust-requirements) to ensure your Rust software meets the required version. ## See Also - [Policy Development Kit Architecture Overview](https://docs.mulesoft.com/pdk/1.2/policies-pdk-architecture) - [Reviewing PDK Prerequisites](https://docs.mulesoft.com/pdk/1.2/policies-pdk-prerequisites) - [Known Issues](https://help.salesforce.com/s/issues) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # PDK Troubleshooting > For the full documentation index, see: https://docs.mulesoft.com/llms.txt When using Flex Gateway Policy Development Kit (PDK), you might encounter issues with PDK itself. See the following sections to help you resolve these issues: - [Cargo-Generate Error on a Mac Device](#cargo-generate) - [Anypoint CLI Credentials Error](#cli-credential) - [Group ID Error When Creating the Policy Project](#group-id-error) - [401 Authorization Error When Running Make Setup](#authorization-error) To debug issues with your custom policy, see: - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.3/policies-pdk-debug-local) - [Debugging Deployed Custom Policies](https://docs.mulesoft.com/pdk/1.3/policies-pdk-debug-deployed-policies) ## Cargo-Generate Error on a Mac Device When compiling Rust on a Mac Device for the first time, the following error might occur: ```ssh $ cargo install cargo-generate error: linking with `cc` failed: exit status: 1 [...] ``` To troubleshoot this error: 1. Ensure Xcode is installed, then compile again. To install Xcode, execute the following command: ```ssh xcode-select --install ``` 2. If Xcode is installed and PDK still does not compile, create or edit the `~/.cargo/config.toml` file by adding the following: ```toml [target.x86_64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] [target.aarch64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] ``` ## Anypoint CLI Credentials Error Anypoint CLI requires multi-factor authentication (MFA) with a Connected App. Using any PDK command without Connected App credentials results in an error similar to the following: ```ssh Error: Failed to launch the browser process! undefined [...]:ERROR:ozone_platform_x11.cc(239)] Missing X server or $DISPLAY [21921:21921:1103/113335.217708:ERROR:env.cc(255)] The platform failed to initialize. Exiting. TROUBLESHOOTING: https://pptr.dev/troubleshooting ``` To configure Anypoint CLI with MFA authentication using a Connected App, refer to [Authentication to the Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/auth). ## Group ID Error When Creating the Policy Project Anypoint CLI uses the `ANYPOINT_ORG` environment variable. This variable can use either the organization name or the organization ID as the value. If the variable is set to the organization name, the [policy creation command](https://docs.mulesoft.com/pdk/1.3/policies-pdk-create-project) fails to infer the group ID of the organization. Use the organization ID for the value of `ANYPOINT_ORG`. However, if you cannot change the variable, use one of the following methods to provide the group ID: - If you run the create command and receive the following prompt: ```ssh Please provide a valid group-id (the id of the organization that will own the asset): ``` Enter your group ID, then press Enter. - Use the `--group-id` flag when creating the PDK project, for example: ```ssh anypoint-cli-v4 pdk policy-project create -n --group-id ``` ## 401 Authorization Error When Running Make Setup When executing \`make setup', the following error might occur: ```ssh $ make setup Login token for `anypoint` saved [...] Caused by: failed to get successful HTTP response from `https://anypoint.mulesoft.com/crates[...]/download` [...], got 401 body: make: *** [install-cargo-anypoint] Error 101 ``` This error occurs when your version of Rust is not v1.74.0 or later. To solve this error, refer to [Rust Requirements for Using PDK](https://docs.mulesoft.com/pdk/1.3/policies-pdk-prerequisites#rust-requirements) to ensure your Rust software meets the required version. ## See Also - [Policy Development Kit Architecture Overview](https://docs.mulesoft.com/pdk/1.3/policies-pdk-architecture) - [Prerequisites for Flex Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.3/policies-pdk-prerequisites) - [Known Issues](https://help.salesforce.com/s/issues) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # PDK Troubleshooting > For the full documentation index, see: https://docs.mulesoft.com/llms.txt When using Flex Gateway Policy Development Kit (PDK), you might encounter issues with PDK itself. See the following sections to help you resolve these issues: - [Cargo-Generate Error on a Mac Device](#cargo-generate) - [Anypoint CLI Credentials Error](#cli-credential) - [Group ID Error When Creating the Policy Project](#group-id-error) - [401 Authorization Error When Running Make Setup](#authorization-error) To debug issues with your custom policy, see: - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.4/policies-pdk-debug-local) - [Debugging Deployed Custom Policies](https://docs.mulesoft.com/pdk/1.4/policies-pdk-debug-deployed-policies) ## Cargo-Generate Error on a Mac Device When compiling Rust on a Mac Device for the first time, the following error might occur: ```ssh $ cargo install cargo-generate error: linking with `cc` failed: exit status: 1 [...] ``` To troubleshoot this error: 1. Ensure Xcode is installed, then compile again. To install Xcode, execute the following command: ```ssh xcode-select --install ``` 2. If Xcode is installed and PDK still does not compile, create or edit the `~/.cargo/config.toml` file by adding the following: ```toml [target.x86_64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] [target.aarch64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] ``` ## Anypoint CLI Credentials Error Anypoint CLI requires multi-factor authentication (MFA) with a Connected App. Using any PDK command without Connected App credentials results in an error similar to the following: ```ssh Error: Failed to launch the browser process! undefined [...]:ERROR:ozone_platform_x11.cc(239)] Missing X server or $DISPLAY [21921:21921:1103/113335.217708:ERROR:env.cc(255)] The platform failed to initialize. Exiting. TROUBLESHOOTING: https://pptr.dev/troubleshooting ``` To configure Anypoint CLI with MFA authentication using a Connected App, refer to [Authentication to the Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/auth). ## Group ID Error When Creating the Policy Project Anypoint CLI uses the `ANYPOINT_ORG` environment variable. This variable can use either the organization name or the organization ID as the value. If the variable is set to the organization name, the [policy creation command](https://docs.mulesoft.com/pdk/1.4/policies-pdk-create-project) fails to infer the group ID of the organization. Use the organization ID for the value of `ANYPOINT_ORG`. However, if you cannot change the variable, use one of the following methods to provide the group ID: - If you run the create command and receive the following prompt: ```ssh Please provide a valid group-id (the id of the organization that will own the asset): ``` Enter your group ID, then press Enter. - Use the `--group-id` flag when creating the PDK project, for example: ```ssh anypoint-cli-v4 pdk policy-project create -n --group-id ``` ## 401 Authorization Error When Running Make Setup When executing \`make setup', the following error might occur: ```ssh $ make setup Login token for `anypoint` saved [...] Caused by: failed to get successful HTTP response from `https://anypoint.mulesoft.com/crates[...]/download` [...], got 401 body: make: *** [install-cargo-anypoint] Error 101 ``` This error occurs when your version of Rust is not v1.87.0 or later. To solve this error, refer to [Rust Requirements for Using PDK](https://docs.mulesoft.com/pdk/1.4/policies-pdk-prerequisites#rust-requirements) to ensure your Rust software meets the required version. ## See Also - [Policy Development Kit Architecture Overview](https://docs.mulesoft.com/pdk/1.4/policies-pdk-architecture) - [Prerequisites for Flex Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.4/policies-pdk-prerequisites) - [Known Issues](https://help.salesforce.com/s/issues) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # PDK Troubleshooting > For the full documentation index, see: https://docs.mulesoft.com/llms.txt When using Flex Gateway Policy Development Kit (PDK), you might encounter issues with PDK itself. See the following sections to help you resolve these issues: - [Cargo-Generate Error on a Mac Device](#cargo-generate) - [Anypoint CLI Credentials Error](#cli-credential) - [Group ID Error When Creating the Policy Project](#group-id-error) - [401 Authorization Error When Running Make Setup](#authorization-error) To debug issues with your custom policy, see: - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.5/policies-pdk-debug-local) - [Debugging Deployed Custom Policies](https://docs.mulesoft.com/pdk/1.5/policies-pdk-debug-deployed-policies) ## Cargo-Generate Error on a Mac Device When compiling Rust on a Mac Device for the first time, the following error might occur: ```ssh $ cargo install cargo-generate error: linking with `cc` failed: exit status: 1 [...] ``` To troubleshoot this error: 1. Ensure Xcode is installed, then compile again. To install Xcode, execute the following command: ```ssh xcode-select --install ``` 2. If Xcode is installed and PDK still does not compile, create or edit the `~/.cargo/config.toml` file by adding the following: ```toml [target.x86_64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] [target.aarch64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] ``` ## Anypoint CLI Credentials Error Anypoint CLI requires multi-factor authentication (MFA) with a Connected App. Using any PDK command without Connected App credentials results in an error similar to the following: ```ssh Error: Failed to launch the browser process! undefined [...]:ERROR:ozone_platform_x11.cc(239)] Missing X server or $DISPLAY [21921:21921:1103/113335.217708:ERROR:env.cc(255)] The platform failed to initialize. Exiting. TROUBLESHOOTING: https://pptr.dev/troubleshooting ``` To configure Anypoint CLI with MFA authentication using a Connected App, refer to [Authentication to the Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/auth). ## Group ID Error When Creating the Policy Project Anypoint CLI uses the `ANYPOINT_ORG` environment variable. This variable can use either the organization name or the organization ID as the value. If the variable is set to the organization name, the [policy creation command](https://docs.mulesoft.com/pdk/1.5/policies-pdk-create-project) fails to infer the group ID of the organization. Use the organization ID for the value of `ANYPOINT_ORG`. However, if you cannot change the variable, use one of the following methods to provide the group ID: - If you run the create command and receive the following prompt: ```ssh Please provide a valid group-id (the id of the organization that will own the asset): ``` Enter your group ID, then press Enter. - Use the `--group-id` flag when creating the PDK project, for example: ```ssh anypoint-cli-v4 pdk policy-project create -n --group-id ``` ## 401 Authorization Error When Running Make Setup When executing \`make setup', the following error might occur: ```ssh $ make setup Login token for `anypoint` saved [...] Caused by: failed to get successful HTTP response from `https://anypoint.mulesoft.com/crates[...]/download` [...], got 401 body: make: *** [install-cargo-anypoint] Error 101 ``` This error occurs when your version of Rust is not v1.87.0 or later. To solve this error, refer to [Rust Requirements for Using PDK](https://docs.mulesoft.com/pdk/1.5/policies-pdk-prerequisites#rust-requirements) to ensure your Rust software meets the required version. ## See Also - [Policy Development Kit Architecture Overview](https://docs.mulesoft.com/pdk/1.5/policies-pdk-architecture) - [Prerequisites for Flex Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.5/policies-pdk-prerequisites) - [Known Issues](https://help.salesforce.com/s/issues) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # PDK Troubleshooting > For the full documentation index, see: https://docs.mulesoft.com/llms.txt When using Flex Gateway Policy Development Kit (PDK), you might encounter issues with PDK itself. See the following sections to help you resolve these issues: - [Cargo-Generate Error on a Mac Device](#cargo-generate) - [Anypoint CLI Credentials Error](#cli-credential) - [Group ID Error When Creating the Policy Project](#group-id-error) - [401 Authorization Error When Running Make Setup](#authorization-error) To debug issues with your custom policy, see: - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.6/policies-pdk-debug-local) - [Debugging Deployed Custom Policies](https://docs.mulesoft.com/pdk/1.6/policies-pdk-debug-deployed-policies) ## Cargo-Generate Error on a Mac Device When compiling Rust on a Mac Device for the first time, the following error might occur: ```ssh $ cargo install cargo-generate error: linking with `cc` failed: exit status: 1 [...] ``` To troubleshoot this error: 1. Ensure Xcode is installed, then compile again. To install Xcode, execute the following command: ```ssh xcode-select --install ``` 2. If Xcode is installed and PDK still does not compile, create or edit the `~/.cargo/config.toml` file by adding the following: ```toml [target.x86_64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] [target.aarch64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] ``` ## Anypoint CLI Credentials Error Anypoint CLI requires multi-factor authentication (MFA) with a Connected App. Using any PDK command without Connected App credentials results in an error similar to the following: ```ssh Error: Failed to launch the browser process! undefined [...]:ERROR:ozone_platform_x11.cc(239)] Missing X server or $DISPLAY [21921:21921:1103/113335.217708:ERROR:env.cc(255)] The platform failed to initialize. Exiting. TROUBLESHOOTING: https://pptr.dev/troubleshooting ``` To configure Anypoint CLI with MFA authentication using a Connected App, refer to [Authentication to the Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/auth). ## Group ID Error When Creating the Policy Project Anypoint CLI uses the `ANYPOINT_ORG` environment variable. This variable can use either the organization name or the organization ID as the value. If the variable is set to the organization name, the [policy creation command](https://docs.mulesoft.com/pdk/1.6/policies-pdk-create-project) fails to infer the group ID of the organization. Use the organization ID for the value of `ANYPOINT_ORG`. However, if you cannot change the variable, use one of the following methods to provide the group ID: - If you run the create command and receive the following prompt: ```ssh Please provide a valid group-id (the id of the organization that will own the asset): ``` Enter your group ID, then press Enter. - Use the `--group-id` flag when creating the PDK project, for example: ```ssh anypoint-cli-v4 pdk policy-project create -n --group-id ``` ## 401 Authorization Error When Running Make Setup When executing \`make setup', the following error might occur: ```ssh $ make setup Login token for `anypoint` saved [...] Caused by: failed to get successful HTTP response from `https://anypoint.mulesoft.com/crates[...]/download` [...], got 401 body: make: *** [install-cargo-anypoint] Error 101 ``` This error occurs when your version of Rust is not v1.88.0 or later. To solve this error, refer to [Rust Requirements for Using PDK](https://docs.mulesoft.com/pdk/1.6/policies-pdk-prerequisites#rust-requirements) to ensure your Rust software meets the required version. ## See Also - [Policy Development Kit Architecture Overview](https://docs.mulesoft.com/pdk/1.6/policies-pdk-architecture) - [Prerequisites for Flex Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.6/policies-pdk-prerequisites) - [Known Issues](https://help.salesforce.com/s/issues) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # PDK Troubleshooting > For the full documentation index, see: https://docs.mulesoft.com/llms.txt When using Flex Gateway Policy Development Kit (PDK), you might encounter issues with PDK itself. See the following sections to help you resolve these issues: - [Cargo-Generate Error on a Mac Device](#cargo-generate) - [Anypoint CLI Credentials Error](#cli-credential) - [Group ID Error When Creating the Policy Project](#group-id-error) - [401 Authorization Error When Running Make Setup](#authorization-error) - [Error: No such file or directory When Running Make Build (Split Model Policy)](#implementation-build-no-file) - [Error Looking for the Specified Asset When Running Make Build-Asset-Files (Split Model Policy)](#build-asset-files-asset-not-found) To debug issues with your custom policy, see: - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.7/policies-pdk-debug-local) - [Debugging Deployed Custom Policies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-debug-deployed-policies) ## Cargo-Generate Error on a Mac Device When compiling Rust on a Mac Device for the first time, the following error might occur: ```ssh $ cargo install cargo-generate error: linking with `cc` failed: exit status: 1 [...] ``` To troubleshoot this error: 1. Ensure Xcode is installed, then compile again. To install Xcode, execute the following command: ```ssh xcode-select --install ``` 2. If Xcode is installed and PDK still does not compile, create or edit the `~/.cargo/config.toml` file by adding the following: ```toml [target.x86_64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] [target.aarch64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] ``` ## Anypoint CLI Credentials Error Anypoint CLI requires multi-factor authentication (MFA) with a Connected App. Using any PDK command without Connected App credentials results in an error similar to the following: ```ssh Error: Failed to launch the browser process! undefined [...]:ERROR:ozone_platform_x11.cc(239)] Missing X server or $DISPLAY [21921:21921:1103/113335.217708:ERROR:env.cc(255)] The platform failed to initialize. Exiting. TROUBLESHOOTING: https://pptr.dev/troubleshooting ``` To configure Anypoint CLI with MFA authentication using a Connected App, refer to [Authentication to the Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/auth). ## Group ID Error When Creating the Policy Project Anypoint CLI uses the `ANYPOINT_ORG` environment variable. This variable can use either the organization name or the organization ID as the value. If the variable is set to the organization name, the [policy creation command](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-project) fails to infer the group ID of the organization. Use the organization ID for the value of `ANYPOINT_ORG`. However, if you cannot change the variable, use one of the following methods to provide the group ID: - If you run the create command and receive the following prompt: ```ssh Please provide a valid group-id (the id of the organization that will own the asset): ``` Enter your group ID, then press Enter. - Use the `--group-id` flag when creating the PDK project, for example: ```ssh anypoint-cli-v4 pdk policy-project create -n --group-id ``` ## 401 Authorization Error When Running Make Setup When executing \`make setup', the following error might occur: ```ssh $ make setup Login token for `anypoint` saved [...] Caused by: failed to get successful HTTP response from `https://anypoint.mulesoft.com/crates[...]/download` [...], got 401 body: make: *** [install-cargo-anypoint] Error 101 ``` This error occurs when your version of Rust is not v1.88.0 or later. To solve this error, refer to [Rust Requirements for Using PDK](https://docs.mulesoft.com/pdk/1.7/policies-pdk-prerequisites#rust-requirements) to ensure your Rust software meets the required version. ## Error: No such file or directory When Running Make Build (Split Model Policy) When running `make build` from the implementation project, this error sometimes occurs: ```ssh Error: No such file or directory (os error 2) make: *** [build] Error 1 ``` Make sure that you’ve executed `make setup` and `make release-local` and that you’ve published the definition asset version before building the implementation. ## Error Looking for the Specified Asset When Running Make Build-Asset-Files (Split Model Policy) When running `make build-asset-files` from the implementation project, this error sometimes occurs: ```ssh Fetching policy: {definition_asset_id}:{definition_asset_version}... ! Error: There was a problem looking for the specified asset. make: *** [build-asset-files] Error 2 ``` Make sure that you’ve executed `make setup` and `make release-local` and that you’ve published the definition asset version before building the implementation. ## See Also - [Policy Development Kit Architecture Overview](https://docs.mulesoft.com/pdk/1.7/policies-pdk-architecture) - [Prerequisites for Flex Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.7/policies-pdk-prerequisites) - [Known Issues](https://help.salesforce.com/s/issues) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # PDK Troubleshooting > For the full documentation index, see: https://docs.mulesoft.com/llms.txt When using Omni Gateway Policy Development Kit (PDK), you might encounter issues with PDK itself. See the following sections to help you resolve these issues: - [Cargo-Generate Error on a Mac Device](#cargo-generate) - [Anypoint CLI Credentials Error](#cli-credential) - [Group ID Error When Creating the Policy Project](#group-id-error) - [401 Authorization Error When Running Make Setup](#authorization-error) - [Error: No such file or directory When Running Make Build (Split Model Policy)](#implementation-build-no-file) - [Error Looking for the Specified Asset When Running Make Build-Asset-Files (Split Model Policy)](#build-asset-files-asset-not-found) To debug issues with your custom policy, see: - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.8/policies-pdk-debug-local) - [Debugging Deployed Custom Policies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-debug-deployed-policies) ## Cargo-Generate Error on a Mac Device When compiling Rust on a Mac Device for the first time, the following error might occur: ```ssh $ cargo install cargo-generate error: linking with `cc` failed: exit status: 1 [...] ``` To troubleshoot this error: 1. Ensure Xcode is installed, then compile again. To install Xcode, execute the following command: ```ssh xcode-select --install ``` 2. If Xcode is installed and PDK still does not compile, create or edit the `~/.cargo/config.toml` file by adding the following: ```toml [target.x86_64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] [target.aarch64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] ``` ## Anypoint CLI Credentials Error Anypoint CLI requires multi-factor authentication (MFA) with a Connected App. Using any PDK command without Connected App credentials results in an error similar to the following: ```ssh Error: Failed to launch the browser process! undefined [...]:ERROR:ozone_platform_x11.cc(239)] Missing X server or $DISPLAY [21921:21921:1103/113335.217708:ERROR:env.cc(255)] The platform failed to initialize. Exiting. TROUBLESHOOTING: https://pptr.dev/troubleshooting ``` To configure Anypoint CLI with MFA authentication using a Connected App, refer to [Authentication to the Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/auth). ## Group ID Error When Creating the Policy Project Anypoint CLI uses the `ANYPOINT_ORG` environment variable. This variable can use either the organization name or the organization ID as the value. If the variable is set to the organization name, the [policy creation command](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-project) fails to infer the group ID of the organization. Use the organization ID for the value of `ANYPOINT_ORG`. However, if you cannot change the variable, use one of the following methods to provide the group ID: - If you run the create command and receive the following prompt: ```ssh Please provide a valid group-id (the id of the organization that will own the asset): ``` Enter your group ID, then press Enter. - Use the `--group-id` flag when creating the PDK project, for example: ```ssh anypoint-cli-v4 pdk policy-project create -n --group-id ``` ## 401 Authorization Error When Running Make Setup When executing \`make setup', the following error might occur: ```ssh $ make setup Login token for `anypoint` saved [...] Caused by: failed to get successful HTTP response from `https://anypoint.mulesoft.com/crates[...]/download` [...], got 401 body: make: *** [install-cargo-anypoint] Error 101 ``` This error occurs when your version of Rust is not v1.88.0 or later. To solve this error, refer to [Rust Requirements for Using PDK](https://docs.mulesoft.com/pdk/1.8/policies-pdk-prerequisites#rust-requirements) to ensure your Rust software meets the required version. ## Error: No such file or directory When Running Make Build (Split Model Policy) When running `make build` from the implementation project, this error sometimes occurs: ```ssh Error: No such file or directory (os error 2) make: *** [build] Error 1 ``` Make sure that you’ve executed `make setup` and `make release-local` and that you’ve published the definition asset version before building the implementation. ## Error Looking for the Specified Asset When Running Make Build-Asset-Files (Split Model Policy) When running `make build-asset-files` from the implementation project, this error sometimes occurs: ```ssh Fetching policy: {definition_asset_id}:{definition_asset_version}... ! Error: There was a problem looking for the specified asset. make: *** [build-asset-files] Error 2 ``` Make sure that you’ve executed `make setup` and `make release-local` and that you’ve published the definition asset version before building the implementation. ## See Also - [Policy Development Kit Architecture Overview](https://docs.mulesoft.com/pdk/1.8/policies-pdk-architecture) - [Prerequisites for Omni Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.8/policies-pdk-prerequisites) - [Known Issues](https://help.salesforce.com/s/issues) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # PDK Troubleshooting > For the full documentation index, see: https://docs.mulesoft.com/llms.txt When using Omni Gateway Policy Development Kit (PDK), you might encounter issues with PDK itself. See the following sections to help you resolve these issues: - [Cargo-Generate Error on a Mac Device](#cargo-generate) - [Anypoint CLI Credentials Error](#cli-credential) - [Group ID Error When Creating the Policy Project](#group-id-error) - [401 Authorization Error When Running Make Setup](#authorization-error) - [Error: No such file or directory When Running Make Build (Split Model Policy)](#implementation-build-no-file) - [Error Looking for the Specified Asset When Running Make Build-Asset-Files (Split Model Policy)](#build-asset-files-asset-not-found) To debug issues with your custom policy, see: - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.9/policies-pdk-debug-local) - [Debugging Deployed Custom Policies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-debug-deployed-policies) ## Cargo-Generate Error on a Mac Device When compiling Rust on a Mac Device for the first time, the following error might occur: ```ssh $ cargo install cargo-generate error: linking with `cc` failed: exit status: 1 [...] ``` To troubleshoot this error: 1. Ensure Xcode is installed, then compile again. To install Xcode, execute the following command: ```ssh xcode-select --install ``` 2. If Xcode is installed and PDK still does not compile, create or edit the `~/.cargo/config.toml` file by adding the following: ```toml [target.x86_64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] [target.aarch64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] ``` ## Anypoint CLI Credentials Error Anypoint CLI requires multi-factor authentication (MFA) with a Connected App. Using any PDK command without Connected App credentials results in an error similar to the following: ```ssh Error: Failed to launch the browser process! undefined [...]:ERROR:ozone_platform_x11.cc(239)] Missing X server or $DISPLAY [21921:21921:1103/113335.217708:ERROR:env.cc(255)] The platform failed to initialize. Exiting. TROUBLESHOOTING: https://pptr.dev/troubleshooting ``` To configure Anypoint CLI with MFA authentication using a Connected App, refer to [Authentication to the Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/auth). ## Group ID Error When Creating the Policy Project Anypoint CLI uses the `ANYPOINT_ORG` environment variable. This variable can use either the organization name or the organization ID as the value. If the variable is set to the organization name, the [policy creation command](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-project) fails to infer the group ID of the organization. Use the organization ID for the value of `ANYPOINT_ORG`. However, if you cannot change the variable, use one of the following methods to provide the group ID: - If you run the create command and receive the following prompt: ```ssh Please provide a valid group-id (the id of the organization that will own the asset): ``` Enter your group ID, then press Enter. - Use the `--group-id` flag when creating the PDK project, for example: ```ssh anypoint-cli-v4 pdk policy-project create -n --group-id ``` ## 401 Authorization Error When Running Make Setup When executing \`make setup', the following error might occur: ```ssh $ make setup Login token for `anypoint` saved [...] Caused by: failed to get successful HTTP response from `https://anypoint.mulesoft.com/crates[...]/download` [...], got 401 body: make: *** [install-cargo-anypoint] Error 101 ``` This error occurs when your version of Rust is not v1.88.0 or later. To solve this error, refer to [Rust Requirements for Using PDK](https://docs.mulesoft.com/pdk/1.9/policies-pdk-prerequisites#rust-requirements) to ensure your Rust software meets the required version. ## Error: No such file or directory When Running Make Build (Split Model Policy) When running `make build` from the implementation project, this error sometimes occurs: ```ssh Error: No such file or directory (os error 2) make: *** [build] Error 1 ``` Make sure that you’ve executed `make setup` and `make release-local` and that you’ve published the definition asset version before building the implementation. ## Error Looking for the Specified Asset When Running Make Build-Asset-Files (Split Model Policy) When running `make build-asset-files` from the implementation project, this error sometimes occurs: ```ssh Fetching policy: {definition_asset_id}:{definition_asset_version}... ! Error: There was a problem looking for the specified asset. make: *** [build-asset-files] Error 2 ``` Make sure that you’ve executed `make setup` and `make release-local` and that you’ve published the definition asset version before building the implementation. ## See Also - [Policy Development Kit Architecture Overview](https://docs.mulesoft.com/pdk/1.9/policies-pdk-architecture) - [Prerequisites for Omni Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.9/policies-pdk-prerequisites) - [Known Issues](https://help.salesforce.com/s/issues) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # PDK Troubleshooting > For the full documentation index, see: https://docs.mulesoft.com/llms.txt When using Omni Gateway Policy Development Kit (PDK), you might encounter issues with PDK itself. See the following sections to help you resolve these issues: - [Cargo-Generate Error on a Mac Device](#cargo-generate) - [Anypoint CLI Credentials Error](#cli-credential) - [Group ID Error When Creating the Policy Project](#group-id-error) - [401 Authorization Error When Running Make Setup](#authorization-error) - [Error: No such file or directory When Running Make Build (Split Model Policy)](#implementation-build-no-file) - [Error Looking for the Specified Asset When Running Make Build-Asset-Files (Split Model Policy)](#build-asset-files-asset-not-found) To debug issues with your custom policy, see: - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/latest/policies-pdk-debug-local) - [Debugging Deployed Custom Policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-debug-deployed-policies) ## Cargo-Generate Error on a Mac Device When compiling Rust on a Mac Device for the first time, the following error might occur: ```ssh $ cargo install cargo-generate error: linking with `cc` failed: exit status: 1 [...] ``` To troubleshoot this error: 1. Ensure Xcode is installed, then compile again. To install Xcode, execute the following command: ```ssh xcode-select --install ``` 2. If Xcode is installed and PDK still does not compile, create or edit the `~/.cargo/config.toml` file by adding the following: ```toml [target.x86_64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] [target.aarch64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] ``` ## Anypoint CLI Credentials Error Anypoint CLI requires multi-factor authentication (MFA) with a Connected App. Using any PDK command without Connected App credentials results in an error similar to the following: ```ssh Error: Failed to launch the browser process! undefined [...]:ERROR:ozone_platform_x11.cc(239)] Missing X server or $DISPLAY [21921:21921:1103/113335.217708:ERROR:env.cc(255)] The platform failed to initialize. Exiting. TROUBLESHOOTING: https://pptr.dev/troubleshooting ``` To configure Anypoint CLI with MFA authentication using a Connected App, refer to [Authentication to the Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/auth). ## Group ID Error When Creating the Policy Project Anypoint CLI uses the `ANYPOINT_ORG` environment variable. This variable can use either the organization name or the organization ID as the value. If the variable is set to the organization name, the [policy creation command](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-project) fails to infer the group ID of the organization. Use the organization ID for the value of `ANYPOINT_ORG`. However, if you cannot change the variable, use one of the following methods to provide the group ID: - If you run the create command and receive the following prompt: ```ssh Please provide a valid group-id (the id of the organization that will own the asset): ``` Enter your group ID, then press Enter. - Use the `--group-id` flag when creating the PDK project, for example: ```ssh anypoint-cli-v4 pdk policy-project create -n --group-id ``` ## 401 Authorization Error When Running Make Setup When executing \`make setup', the following error might occur: ```ssh $ make setup Login token for `anypoint` saved [...] Caused by: failed to get successful HTTP response from `https://anypoint.mulesoft.com/crates[...]/download` [...], got 401 body: make: *** [install-cargo-anypoint] Error 101 ``` This error occurs when your version of Rust is not v1.88.0 or later. To solve this error, refer to [Rust Requirements for Using PDK](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites#rust-requirements) to ensure your Rust software meets the required version. ## Error: No such file or directory When Running Make Build (Split Model Policy) When running `make build` from the implementation project, this error sometimes occurs: ```ssh Error: No such file or directory (os error 2) make: *** [build] Error 1 ``` Make sure that you’ve executed `make setup` and `make release-local` and that you’ve published the definition asset version before building the implementation. ## Error Looking for the Specified Asset When Running Make Build-Asset-Files (Split Model Policy) When running `make build-asset-files` from the implementation project, this error sometimes occurs: ```ssh Fetching policy: {definition_asset_id}:{definition_asset_version}... ! Error: There was a problem looking for the specified asset. make: *** [build-asset-files] Error 2 ``` Make sure that you’ve executed `make setup` and `make release-local` and that you’ve published the definition asset version before building the implementation. ## See Also - [Policy Development Kit Architecture Overview](https://docs.mulesoft.com/pdk/latest/policies-pdk-architecture) - [Prerequisites for Omni Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites) - [Known Issues](https://help.salesforce.com/s/issues) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Performing an HTTP Call > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that makes HTTP calls, see > [Simple OAuth 2.0 Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/simple-oauth-2-validation/README.md). To interact with external services, a policy can use HTTP calls. You can only make HTTP calls from the request filter or the response filter. ## Define the HTTP Service Define your service as a parameter in your schema definition to make HTTP requests. To learn more about defining parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.2/policies-pdk-create-schema-definition) The following code snippet provides an example schema definition for an external service: ```yaml properties: externalService: type: string format: service endpointPath: type: string ``` In the policy’s Rust source code, you can access the defined external service in the `Config` struct. To perform requests, call the HTTP client in your policy, for example: ```rust let response = client .request(&config.external_service) .path(&config.endpoint_path) .headers(vec![("Content-Type", "application/json")]) .body(r#"{"key": "value"}"#.as_bytes()) .put().await?; ``` ## Inject the HTTP Client Parameters to Enable Requests To perform an HTTP call, either inject the `HTTPClient` into the `[entrypoint]` function or the wrapper functions: - To enable requests in the request and response filters, inject the client parameter into the `#[entrypoint]` function: ```Rust #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration, client: HttpClient) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).unwrap(); // Both request and the response handlers will use the client let filter = on_request(|request_state| request_filter(request_state, &config, &client)) .on_response(|response_state, request_data| { response_filter(response_state, request_data, &config, &client) }); launcher.launch(filter).await?; Ok(()) } ``` - To enable requests only in the request or the response, inject the client parameters either in the `on_request` or `on_response` wrapper functions: ```Rust // Handler with the logic for incoming requests ​​async fn request_filter(state: RequestState, conf: &Config, client: HttpClient) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).unwrap(); // For incoming request events, using the on_request wrapper, inject the client and pass it to the request_filter handler launcher .launch(on_request(|request, client| { request_filter(request, &config, client) })) .await?; Ok(()) } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Performing an HTTP Call > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that makes HTTP calls, see > [Simple OAuth 2.0 Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/simple-oauth-2-validation/README.md). To interact with external services, a policy can use HTTP calls. You can only make HTTP calls from the request filter or the response filter. ## Define the HTTP Service Define your service as a parameter in your schema definition to make HTTP requests. To learn more about defining parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.3/policies-pdk-create-schema-definition) The following code snippet provides an example schema definition for an external service: ```yaml properties: externalService: type: string format: service endpointPath: type: string ``` In the policy’s Rust source code, you can access the defined external service in the `Config` struct. To perform requests, call the HTTP client in your policy, for example: ```rust let response = client .request(&config.external_service) .path(&config.endpoint_path) .headers(vec![("Content-Type", "application/json")]) .body(r#"{"key": "value"}"#.as_bytes()) .put().await?; ``` ## Inject the HTTP Client Parameters to Enable Requests To perform an HTTP call, either inject the `HTTPClient` into the `[entrypoint]` function or the wrapper functions: - To enable requests in the request and response filters, inject the client parameter into the `#[entrypoint]` function: ```Rust #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration, client: HttpClient) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).unwrap(); // Both request and the response handlers will use the client let filter = on_request(|request_state| request_filter(request_state, &config, &client)) .on_response(|response_state, request_data| { response_filter(response_state, request_data, &config, &client) }); launcher.launch(filter).await?; Ok(()) } ``` - To enable requests only in the request or the response, inject the client parameters either in the `on_request` or `on_response` wrapper functions: ```Rust // Handler with the logic for incoming requests ​​async fn request_filter(state: RequestState, conf: &Config, client: HttpClient) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).unwrap(); // For incoming request events, using the on_request wrapper, inject the client and pass it to the request_filter handler launcher .launch(on_request(|request, client| { request_filter(request, &config, client) })) .await?; Ok(()) } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Performing an HTTP Call > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that makes HTTP calls, see > [Simple OAuth 2.0 Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/simple-oauth-2-validation/README.md). To interact with external services, a policy can use HTTP calls. You can only make HTTP calls from the request filter or the response filter. ## Define the HTTP Service Define your service as a parameter in your schema definition to make HTTP requests. To learn more about defining parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.4/policies-pdk-create-schema-definition) The following code snippet provides an example schema definition for an external service: ```yaml properties: externalService: type: string format: service endpointPath: type: string ``` In the policy’s Rust source code, you can access the defined external service in the `Config` struct. To perform requests, call the HTTP client in your policy, for example: ```rust let response = client .request(&config.external_service) .path(&config.endpoint_path) .headers(vec![("Content-Type", "application/json")]) .body(r#"{"key": "value"}"#.as_bytes()) .put().await?; ``` ## Inject the HTTP Client Parameters to Enable Requests To perform an HTTP call, either inject the `HTTPClient` into the `[entrypoint]` function or the wrapper functions: - To enable requests in the request and response filters, inject the client parameter into the `#[entrypoint]` function: ```Rust #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration, client: HttpClient) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).unwrap(); // Both request and the response handlers will use the client let filter = on_request(|request_state| request_filter(request_state, &config, &client)) .on_response(|response_state, request_data| { response_filter(response_state, request_data, &config, &client) }); launcher.launch(filter).await?; Ok(()) } ``` - To enable requests only in the request or the response, inject the client parameters either in the `on_request` or `on_response` wrapper functions: ```Rust // Handler with the logic for incoming requests ​​async fn request_filter(state: RequestState, conf: &Config, client: HttpClient) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).unwrap(); // For incoming request events, using the on_request wrapper, inject the client and pass it to the request_filter handler launcher .launch(on_request(|request, client| { request_filter(request, &config, client) })) .await?; Ok(()) } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Performing an HTTP Call > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that makes HTTP calls, see > [Simple OAuth 2.0 Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/simple-oauth-2-validation/README.md). To interact with external services, a policy can use HTTP calls. You can only make HTTP calls from the request filter or the response filter. ## Define the HTTP Service Define your service as a parameter in your schema definition to make HTTP requests. To learn more about defining parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.5/policies-pdk-create-schema-definition) The following code snippet provides an example schema definition for an external service: ```yaml properties: externalService: type: string format: service endpointPath: type: string ``` In the policy’s Rust source code, you can access the defined external service in the `Config` struct. To perform requests, call the HTTP client in your policy, for example: ```rust let response = client .request(&config.external_service) .path(&config.endpoint_path) .headers(vec![("Content-Type", "application/json")]) .body(r#"{"key": "value"}"#.as_bytes()) .put().await?; ``` ## Inject the HTTP Client Parameters to Enable Requests To perform an HTTP call, either inject the `HTTPClient` into the `[entrypoint]` function or the wrapper functions: - To enable requests in the request and response filters, inject the client parameter into the `#[entrypoint]` function: ```Rust #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration, client: HttpClient) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).unwrap(); // Both request and the response handlers will use the client let filter = on_request(|request_state| request_filter(request_state, &config, &client)) .on_response(|response_state, request_data| { response_filter(response_state, request_data, &config, &client) }); launcher.launch(filter).await?; Ok(()) } ``` - To enable requests only in the request or the response, inject the client parameters either in the `on_request` or `on_response` wrapper functions: ```Rust // Handler with the logic for incoming requests ​​async fn request_filter(state: RequestState, conf: &Config, client: HttpClient) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).unwrap(); // For incoming request events, using the on_request wrapper, inject the client and pass it to the request_filter handler launcher .launch(on_request(|request, client| { request_filter(request, &config, client) })) .await?; Ok(()) } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Performing an HTTP Call > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that makes HTTP calls, see > [Simple OAuth 2.0 Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/simple-oauth-2-validation/README.md). To interact with external services, a policy can use HTTP calls. You can only make HTTP calls from the request filter or the response filter. ## Define the HTTP Service Define your service as a parameter in your schema definition to make HTTP requests. To learn more about defining parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.6/policies-pdk-create-schema-definition) The following code snippet provides an example schema definition for an external service: ```yaml properties: externalService: type: string format: service endpointPath: type: string ``` In the policy’s Rust source code, you can access the defined external service in the `Config` struct. To perform requests, call the HTTP client in your policy, for example: ```rust let response = client .request(&config.external_service) .path(&config.endpoint_path) .headers(vec![("Content-Type", "application/json")]) .body(r#"{"key": "value"}"#.as_bytes()) .put().await?; ``` ## Inject the HTTP Client Parameters to Enable Requests To perform an HTTP call, either inject the `HTTPClient` into the `[entrypoint]` function or the wrapper functions: - To enable requests in the request and response filters, inject the client parameter into the `#[entrypoint]` function: ```Rust #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration, client: HttpClient) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).unwrap(); // Both request and the response handlers will use the client let filter = on_request(|request_state| request_filter(request_state, &config, &client)) .on_response(|response_state, request_data| { response_filter(response_state, request_data, &config, &client) }); launcher.launch(filter).await?; Ok(()) } ``` - To enable requests only in the request or the response, inject the client parameters either in the `on_request` or `on_response` wrapper functions: ```Rust // Handler with the logic for incoming requests ​​async fn request_filter(state: RequestState, conf: &Config, client: HttpClient) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).unwrap(); // For incoming request events, using the on_request wrapper, inject the client and pass it to the request_filter handler launcher .launch(on_request(|request, client| { request_filter(request, &config, client) })) .await?; Ok(()) } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Performing an HTTP Call > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that makes HTTP calls, see > [Simple OAuth 2.0 Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/simple-oauth-2-validation/README.md). To interact with external services, a policy can use HTTP calls. You can only make HTTP calls from the request filter or the response filter. ## Define the HTTP Service Define your service as a parameter in your schema definition to make HTTP requests. To learn more about defining parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-schema-definition) The following code snippet provides an example schema definition for an external service: ```yaml properties: externalService: type: string format: service endpointPath: type: string ``` In the policy’s Rust source code, you can access the defined external service in the `Config` struct. To perform requests, call the HTTP client in your policy, for example: ```rust let response = client .request(&config.external_service) .path(&config.endpoint_path) .headers(vec![("Content-Type", "application/json")]) .body(r#"{"key": "value"}"#.as_bytes()) .put().await?; ``` ## Inject the HTTP Client Parameters to Enable Requests To perform an HTTP call, either inject the `HTTPClient` into the `[entrypoint]` function or the wrapper functions: - To enable requests in the request and response filters, inject the client parameter into the `#[entrypoint]` function: ```Rust #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration, client: HttpClient) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).unwrap(); // Both request and the response handlers will use the client let filter = on_request(|request_state| request_filter(request_state, &config, &client)) .on_response(|response_state, request_data| { response_filter(response_state, request_data, &config, &client) }); launcher.launch(filter).await?; Ok(()) } ``` - To enable requests only in the request or the response, inject the client parameters either in the `on_request` or `on_response` wrapper functions: ```Rust // Handler with the logic for incoming requests ​​async fn request_filter(state: RequestState, conf: &Config, client: HttpClient) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).unwrap(); // For incoming request events, using the on_request wrapper, inject the client and pass it to the request_filter handler launcher .launch(on_request(|request, client| { request_filter(request, &config, client) })) .await?; Ok(()) } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Performing an HTTP Call > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that makes HTTP calls, see > [Simple OAuth 2.0 Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/simple-oauth-2-validation/README.md). To interact with external services, a policy can use HTTP calls. You can only make HTTP calls from the request filter or the response filter. ## Define the HTTP Service Define your service as a parameter in your schema definition to make HTTP requests. To learn more about defining parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-schema-definition) The following code snippet provides an example schema definition for an external service: ```yaml properties: externalService: type: string format: service endpointPath: type: string ``` In the policy’s Rust source code, you can access the defined external service in the `Config` struct. To perform requests, call the HTTP client in your policy, for example: ```rust let response = client .request(&config.external_service) .path(&config.endpoint_path) .headers(vec![("Content-Type", "application/json")]) .body(r#"{"key": "value"}"#.as_bytes()) .put().await?; ``` ## Inject the HTTP Client Parameters to Enable Requests To perform an HTTP call, either inject the `HTTPClient` into the `[entrypoint]` function or the wrapper functions: - To enable requests in the request and response filters, inject the client parameter into the `#[entrypoint]` function: ```Rust #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration, client: HttpClient) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).unwrap(); // Both request and the response handlers will use the client let filter = on_request(|request_state| request_filter(request_state, &config, &client)) .on_response(|response_state, request_data| { response_filter(response_state, request_data, &config, &client) }); launcher.launch(filter).await?; Ok(()) } ``` - To enable requests only in the request or the response, inject the client parameters either in the `on_request` or `on_response` wrapper functions: ```Rust // Handler with the logic for incoming requests ​​async fn request_filter(state: RequestState, conf: &Config, client: HttpClient) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).unwrap(); // For incoming request events, using the on_request wrapper, inject the client and pass it to the request_filter handler launcher .launch(on_request(|request, client| { request_filter(request, &config, client) })) .await?; Ok(()) } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Performing an HTTP Call > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that makes HTTP calls, see > [Simple OAuth 2.0 Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/simple-oauth-2-validation/README.md). To interact with external services, a policy can use HTTP calls. You can only make HTTP calls from the request filter or the response filter. ## Define the HTTP Service Define your service as a parameter in your schema definition to make HTTP requests. To learn more about defining parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-schema-definition) The following code snippet provides an example schema definition for an external service: ```yaml properties: externalService: type: string format: service endpointPath: type: string ``` In the policy’s Rust source code, you can access the defined external service in the `Config` struct. To perform requests, call the HTTP client in your policy, for example: ```rust let response = client .request(&config.external_service) .path(&config.endpoint_path) .headers(vec![("Content-Type", "application/json")]) .body(r#"{"key": "value"}"#.as_bytes()) .put().await?; ``` ## Inject the HTTP Client Parameters to Enable Requests To perform an HTTP call, either inject the `HTTPClient` into the `[entrypoint]` function or the wrapper functions: - To enable requests in the request and response filters, inject the client parameter into the `#[entrypoint]` function: ```Rust #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration, client: HttpClient) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).unwrap(); // Both request and the response handlers will use the client let filter = on_request(|request_state| request_filter(request_state, &config, &client)) .on_response(|response_state, request_data| { response_filter(response_state, request_data, &config, &client) }); launcher.launch(filter).await?; Ok(()) } ``` - To enable requests only in the request or the response, inject the client parameters either in the `on_request` or `on_response` wrapper functions: ```Rust // Handler with the logic for incoming requests ​​async fn request_filter(state: RequestState, conf: &Config, client: HttpClient) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).unwrap(); // For incoming request events, using the on_request wrapper, inject the client and pass it to the request_filter handler launcher .launch(on_request(|request, client| { request_filter(request, &config, client) })) .await?; Ok(()) } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Performing an HTTP Call > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that makes HTTP calls, see > [Simple OAuth 2.0 Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/simple-oauth-2-validation/README.md). To interact with external services, a policy can use HTTP calls. You can only make HTTP calls from the request filter or the response filter. ## Define the HTTP Service Define your service as a parameter in your schema definition to make HTTP requests. To learn more about defining parameters, see [Defining a Policy Schema Definition](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-schema-definition) The following code snippet provides an example schema definition for an external service: ```yaml properties: externalService: type: string format: service endpointPath: type: string ``` In the policy’s Rust source code, you can access the defined external service in the `Config` struct. To perform requests, call the HTTP client in your policy, for example: ```rust let response = client .request(&config.external_service) .path(&config.endpoint_path) .headers(vec![("Content-Type", "application/json")]) .body(r#"{"key": "value"}"#.as_bytes()) .put().await?; ``` ## Inject the HTTP Client Parameters to Enable Requests To perform an HTTP call, either inject the `HTTPClient` into the `[entrypoint]` function or the wrapper functions: - To enable requests in the request and response filters, inject the client parameter into the `#[entrypoint]` function: ```Rust #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration, client: HttpClient) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).unwrap(); // Both request and the response handlers will use the client let filter = on_request(|request_state| request_filter(request_state, &config, &client)) .on_response(|response_state, request_data| { response_filter(response_state, request_data, &config, &client) }); launcher.launch(filter).await?; Ok(()) } ``` - To enable requests only in the request or the response, inject the client parameters either in the `on_request` or `on_response` wrapper functions: ```Rust // Handler with the logic for incoming requests ​​async fn request_filter(state: RequestState, conf: &Config, client: HttpClient) { ... } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes).unwrap(); // For incoming request events, using the on_request wrapper, inject the client and pass it to the request_filter handler launcher .launch(on_request(|request, client| { request_filter(request, &config, client) })) .await?; Ok(()) } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Policy Development Kit Architecture Overview > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) consists of: - [Anypoint CLI PDK Plugin](#anypoint-cli-pdk-plugin): Generates and distributes the policy to Exchange - [Policy Template](#policy-template): Scaffolds new custom policies - [SDK Building Tools](#sdk-building-tools): Simplifies the development process ## Anypoint CLI PDK Plugin The Anypoint CLI PDK plugin creates the PDK project and uploads policy assets to Exchange (for Connected Mode only). After creating the project, PDK provides a simplified set of commands in a `Makefile` to complete all following development steps. ## Policy Template PDK generates some simple scaffolding when creating the policy. All generated files contain the required information to properly compile the policy. For more information about the included files, see [Project Structure](https://docs.mulesoft.com/pdk/1.2/policies-pdk-create-project#project-structure). ## SDK Building Tools Flex Gateway is built on Envoy which requires developed policies to be compatible with the event-driven [proxy-wasm](https://github.com/proxy-wasm/spec) architecture. \`proxy-wasm’s event-driven architecture requires users to manage the different events that handle a single request. This causes the following drawbacks that make developing and maintaining event-driven code costly: - High complexity of the code due to the coupling of business logic with the entry points - Inability to modularize common logic which creates monolithic code - Verbose non-linear control flow that creates difficult function callbacks and error propagation PDK provides building tools that abstract the developer from the event-oriented coding approach by using reactor and executor patterns. PDK provides the developer a way to code each incoming request in a linear method that results in: - Fewer compile and runtime errors from using methods in the incorrect context - Reduced learning curve - Improved debugging by minimizing call stacks - Reduced code duplication - Improved parameter injection - Reduced use of dynamic memory that decreases indeterminism and the need for custom memory management ## See Also - [Reviewing PDK Prerequisites](https://docs.mulesoft.com/pdk/1.2/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Policy Development Kit Architecture Overview > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) consists of: - [Anypoint CLI PDK Plugin](#anypoint-cli-pdk-plugin): Generates and distributes the policy to Exchange - [Policy Template](#policy-template): Scaffolds new custom policies - [SDK Building Tools](#sdk-building-tools): Simplifies the development process ## Anypoint CLI PDK Plugin The Anypoint CLI PDK plugin creates the PDK project and uploads policy assets to Exchange (for Connected Mode only). After creating the project, PDK provides a simplified set of commands in a `Makefile` to complete all following development steps. ## Policy Template PDK generates some simple scaffolding when creating the policy. All generated files contain the required information to properly compile the policy. For more information about the included files, see [Project Structure](https://docs.mulesoft.com/pdk/1.3/policies-pdk-create-project#project-structure). ## SDK Building Tools Flex Gateway is built on Envoy which requires developed policies to be compatible with the event-driven [proxy-wasm](https://github.com/proxy-wasm/spec) architecture. \`proxy-wasm’s event-driven architecture requires users to manage the different events that handle a single request. This causes the following drawbacks that make developing and maintaining event-driven code costly: - High complexity of the code due to the coupling of business logic with the entry points - Inability to modularize common logic which creates monolithic code - Verbose non-linear control flow that creates difficult function callbacks and error propagation PDK provides building tools that abstract the developer from the event-oriented coding approach by using reactor and executor patterns. PDK provides the developer a way to code each incoming request in a linear method that results in: - Fewer compile and runtime errors from using methods in the incorrect context - Reduced learning curve - Improved debugging by minimizing call stacks - Reduced code duplication - Improved parameter injection - Reduced use of dynamic memory that decreases indeterminism and the need for custom memory management ## See Also - [Prerequisites for Flex Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.3/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Policy Development Kit Architecture Overview > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) consists of: - [Anypoint CLI PDK Plugin](#anypoint-cli-pdk-plugin): Generates and distributes the policy to Exchange - [Policy Template](#policy-template): Scaffolds new custom policies - [SDK Building Tools](#sdk-building-tools): Simplifies the development process ## Anypoint CLI PDK Plugin The Anypoint CLI PDK plugin creates the PDK project and uploads policy assets to Exchange (for Connected Mode only). After creating the project, PDK provides a simplified set of commands in a `Makefile` to complete all following development steps. ## Policy Template PDK generates some simple scaffolding when creating the policy. All generated files contain the required information to properly compile the policy. For more information about the included files, see [Project Structure](https://docs.mulesoft.com/pdk/1.4/policies-pdk-create-project#project-structure). ## SDK Building Tools Flex Gateway is built on Envoy which requires developed policies to be compatible with the event-driven [proxy-wasm](https://github.com/proxy-wasm/spec) architecture. \`proxy-wasm’s event-driven architecture requires users to manage the different events that handle a single request. This causes the following drawbacks that make developing and maintaining event-driven code costly: - High complexity of the code due to the coupling of business logic with the entry points - Inability to modularize common logic which creates monolithic code - Verbose non-linear control flow that creates difficult function callbacks and error propagation PDK provides building tools that abstract the developer from the event-oriented coding approach by using reactor and executor patterns. PDK provides the developer a way to code each incoming request in a linear method that results in: - Fewer compile and runtime errors from using methods in the incorrect context - Reduced learning curve - Improved debugging by minimizing call stacks - Reduced code duplication - Improved parameter injection - Reduced use of dynamic memory that decreases indeterminism and the need for custom memory management ## MCP Policy Management The Mulesoft MCP Server provides `manage_flex_gateway_policy_project` and `get_flex_gateway_policy_example` tools to manage the custom policy lifecycle. To learn more, see [MuleSoft MCP Server Policy Management Tools](https://docs.mulesoft.com/mulesoft-mcp-server/reference-mcp-tools#policy-management). ## See Also - [Prerequisites for Flex Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.4/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Policy Development Kit Architecture Overview > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) consists of: - [Anypoint CLI PDK Plugin](#anypoint-cli-pdk-plugin): Generates and distributes the policy to Exchange - [Policy Template](#policy-template): Scaffolds new custom policies - [SDK Building Tools](#sdk-building-tools): Simplifies the development process ## Anypoint CLI PDK Plugin The Anypoint CLI PDK plugin creates the PDK project and uploads policy assets to Exchange (for Connected Mode only). After creating the project, PDK provides a simplified set of commands in a `Makefile` to complete all following development steps. ## Policy Template PDK generates some simple scaffolding when creating the policy. All generated files contain the required information to properly compile the policy. For more information about the included files, see [Project Structure](https://docs.mulesoft.com/pdk/1.5/policies-pdk-create-project#project-structure). ## SDK Building Tools Flex Gateway is built on Envoy which requires developed policies to be compatible with the event-driven [proxy-wasm](https://github.com/proxy-wasm/spec) architecture. \`proxy-wasm’s event-driven architecture requires users to manage the different events that handle a single request. This causes the following drawbacks that make developing and maintaining event-driven code costly: - High complexity of the code due to the coupling of business logic with the entry points - Inability to modularize common logic which creates monolithic code - Verbose non-linear control flow that creates difficult function callbacks and error propagation PDK provides building tools that abstract the developer from the event-oriented coding approach by using reactor and executor patterns. PDK provides the developer a way to code each incoming request in a linear method that results in: - Fewer compile and runtime errors from using methods in the incorrect context - Reduced learning curve - Improved debugging by minimizing call stacks - Reduced code duplication - Improved parameter injection - Reduced use of dynamic memory that decreases indeterminism and the need for custom memory management ## MCP Policy Management The Mulesoft MCP Server provides `manage_flex_gateway_policy_project` and `get_flex_gateway_policy_example` tools to manage the custom policy lifecycle. To learn more, see [MuleSoft MCP Server Policy Management Tools](https://docs.mulesoft.com/mulesoft-mcp-server/reference-mcp-tools#policy-management). ## See Also - [Prerequisites for Flex Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.5/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Policy Development Kit Architecture Overview > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) consists of: - [Anypoint CLI PDK Plugin](#anypoint-cli-pdk-plugin): Generates and distributes the policy to Exchange - [Policy Template](#policy-template): Scaffolds new custom policies - [SDK Building Tools](#sdk-building-tools): Simplifies the development process ## Anypoint CLI PDK Plugin The Anypoint CLI PDK plugin creates the PDK project and uploads policy assets to Exchange (for Connected Mode only). After creating the project, PDK provides a simplified set of commands in a `Makefile` to complete all following development steps. ## Policy Template PDK generates some simple scaffolding when creating the policy. All generated files contain the required information to properly compile the policy. For more information about the included files, see [Project Structure](https://docs.mulesoft.com/pdk/1.6/policies-pdk-create-project#project-structure). ## SDK Building Tools Flex Gateway is built on Envoy which requires developed policies to be compatible with the event-driven [proxy-wasm](https://github.com/proxy-wasm/spec) architecture. \`proxy-wasm’s event-driven architecture requires users to manage the different events that handle a single request. This causes the following drawbacks that make developing and maintaining event-driven code costly: - High complexity of the code due to the coupling of business logic with the entry points - Inability to modularize common logic which creates monolithic code - Verbose non-linear control flow that creates difficult function callbacks and error propagation PDK provides building tools that abstract the developer from the event-oriented coding approach by using reactor and executor patterns. PDK provides the developer a way to code each incoming request in a linear method that results in: - Fewer compile and runtime errors from using methods in the incorrect context - Reduced learning curve - Improved debugging by minimizing call stacks - Reduced code duplication - Improved parameter injection - Reduced use of dynamic memory that decreases indeterminism and the need for custom memory management ## MCP Policy Management The Mulesoft MCP Server provides `manage_flex_gateway_policy_project` and `get_flex_gateway_policy_example` tools to manage the custom policy lifecycle. To learn more, see [MuleSoft MCP Server Policy Management Tools](https://docs.mulesoft.com/mulesoft-mcp-server/reference-mcp-tools#policy-management). ## See Also - [Prerequisites for Flex Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.6/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Policy Development Kit Architecture Overview > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) consists of: - [Anypoint CLI PDK Plugin](#anypoint-cli-pdk-plugin): Generates and distributes the policy to Exchange - [Policy Template](#policy-template): Scaffolds new custom policies - [SDK Building Tools](#sdk-building-tools): Simplifies the development process ## Anypoint CLI PDK Plugin The Anypoint CLI PDK plugin creates the PDK project and uploads policy assets to Exchange (for Connected Mode only). After creating the project, PDK provides a simplified set of commands in a `Makefile` to complete all following development steps. ## Policy Template PDK generates some simple scaffolding when creating the policy. All generated files contain the required information to properly compile the policy. For more information about the included files, see [Project Structure](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-project#project-structure). ## SDK Building Tools Flex Gateway is built on Envoy which requires developed policies to be compatible with the event-driven [proxy-wasm](https://github.com/proxy-wasm/spec) architecture. \`proxy-wasm’s event-driven architecture requires users to manage the different events that handle a single request. This causes the following drawbacks that make developing and maintaining event-driven code costly: - High complexity of the code due to the coupling of business logic with the entry points - Inability to modularize common logic which creates monolithic code - Verbose non-linear control flow that creates difficult function callbacks and error propagation PDK provides building tools that abstract the developer from the event-oriented coding approach by using reactor and executor patterns. PDK provides the developer a way to code each incoming request in a linear method that results in: - Fewer compile and runtime errors from using methods in the incorrect context - Reduced learning curve - Improved debugging by minimizing call stacks - Reduced code duplication - Improved parameter injection - Reduced use of dynamic memory that decreases indeterminism and the need for custom memory management ## MCP Policy Management The Mulesoft MCP Server provides `manage_flex_gateway_policy_project` and `get_flex_gateway_policy_example` tools to manage the custom policy lifecycle. To learn more, see [MuleSoft MCP Server Policy Management Tools](https://docs.mulesoft.com/mulesoft-mcp-server/reference-mcp-tools#policy-management). ## See Also - [Prerequisites for Flex Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.7/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Policy Development Kit Architecture Overview > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) consists of: - [Anypoint CLI PDK Plugin](#anypoint-cli-pdk-plugin): Generates and distributes the policy to Exchange - [Policy Template](#policy-template): Scaffolds new custom policies - [SDK Building Tools](#sdk-building-tools): Simplifies the development process ## Anypoint CLI PDK Plugin The Anypoint CLI PDK plugin creates the PDK project and uploads policy assets to Exchange (for Connected Mode only). After creating the project, PDK provides a simplified set of commands in a `Makefile` to complete all following development steps. ## Policy Template PDK generates some simple scaffolding when creating the policy. All generated files contain the required information to properly compile the policy. For more information about the included files, see [Project Structure](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-project#project-structure). ## SDK Building Tools Omni Gateway is built on Envoy which requires developed policies to be compatible with the event-driven [proxy-wasm](https://github.com/proxy-wasm/spec) architecture. \`proxy-wasm’s event-driven architecture requires users to manage the different events that handle a single request. This causes the following drawbacks that make developing and maintaining event-driven code costly: - High complexity of the code due to the coupling of business logic with the entry points - Inability to modularize common logic which creates monolithic code - Verbose non-linear control flow that creates difficult function callbacks and error propagation PDK provides building tools that abstract the developer from the event-oriented coding approach by using reactor and executor patterns. PDK provides the developer a way to code each incoming request in a linear method that results in: - Fewer compile and runtime errors from using methods in the incorrect context - Reduced learning curve - Improved debugging by minimizing call stacks - Reduced code duplication - Improved parameter injection - Reduced use of dynamic memory that decreases indeterminism and the need for custom memory management ## MCP Policy Management The Mulesoft MCP Server provides `manage_flex_gateway_policy_project` and `get_flex_gateway_policy_example` tools to manage the custom policy lifecycle. To learn more, see [MuleSoft MCP Server Policy Management Tools](https://docs.mulesoft.com/mulesoft-mcp-server/reference-mcp-tools#policy-management). ## See Also - [Prerequisites for Omni Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.8/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Policy Development Kit Architecture Overview > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) consists of: - [Anypoint CLI PDK Plugin](#anypoint-cli-pdk-plugin): Generates and distributes the policy to Exchange - [Policy Template](#policy-template): Scaffolds new custom policies - [SDK Building Tools](#sdk-building-tools): Simplifies the development process ## Anypoint CLI PDK Plugin The Anypoint CLI PDK plugin creates the PDK project and uploads policy assets to Exchange (for Connected Mode only). After creating the project, PDK provides a simplified set of commands in a `Makefile` to complete all following development steps. ## Policy Template PDK generates some simple scaffolding when creating the policy. All generated files contain the required information to properly compile the policy. For more information about the included files, see [Project Structure](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-project#project-structure). ## SDK Building Tools Omni Gateway is built on Envoy which requires developed policies to be compatible with the event-driven [proxy-wasm](https://github.com/proxy-wasm/spec) architecture. \`proxy-wasm’s event-driven architecture requires users to manage the different events that handle a single request. This causes the following drawbacks that make developing and maintaining event-driven code costly: - High complexity of the code due to the coupling of business logic with the entry points - Inability to modularize common logic which creates monolithic code - Verbose non-linear control flow that creates difficult function callbacks and error propagation PDK provides building tools that abstract the developer from the event-oriented coding approach by using reactor and executor patterns. PDK provides the developer a way to code each incoming request in a linear method that results in: - Fewer compile and runtime errors from using methods in the incorrect context - Reduced learning curve - Improved debugging by minimizing call stacks - Reduced code duplication - Improved parameter injection - Reduced use of dynamic memory that decreases indeterminism and the need for custom memory management ## MCP Policy Management The Mulesoft MCP Server provides `manage_flex_gateway_policy_project` and `get_flex_gateway_policy_example` tools to manage the custom policy lifecycle. To learn more, see [MuleSoft MCP Server Policy Management Tools](https://docs.mulesoft.com/mulesoft-mcp-server/reference-mcp-tools#policy-management). ## See Also - [Prerequisites for Omni Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.9/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Policy Development Kit Architecture Overview > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) consists of: - [Anypoint CLI PDK Plugin](#anypoint-cli-pdk-plugin): Generates and distributes the policy to Exchange - [Policy Template](#policy-template): Scaffolds new custom policies - [SDK Building Tools](#sdk-building-tools): Simplifies the development process ## Anypoint CLI PDK Plugin The Anypoint CLI PDK plugin creates the PDK project and uploads policy assets to Exchange (for Connected Mode only). After creating the project, PDK provides a simplified set of commands in a `Makefile` to complete all following development steps. ## Policy Template PDK generates some simple scaffolding when creating the policy. All generated files contain the required information to properly compile the policy. For more information about the included files, see [Project Structure](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-project#project-structure). ## SDK Building Tools Omni Gateway is built on Envoy which requires developed policies to be compatible with the event-driven [proxy-wasm](https://github.com/proxy-wasm/spec) architecture. \`proxy-wasm’s event-driven architecture requires users to manage the different events that handle a single request. This causes the following drawbacks that make developing and maintaining event-driven code costly: - High complexity of the code due to the coupling of business logic with the entry points - Inability to modularize common logic which creates monolithic code - Verbose non-linear control flow that creates difficult function callbacks and error propagation PDK provides building tools that abstract the developer from the event-oriented coding approach by using reactor and executor patterns. PDK provides the developer a way to code each incoming request in a linear method that results in: - Fewer compile and runtime errors from using methods in the incorrect context - Reduced learning curve - Improved debugging by minimizing call stacks - Reduced code duplication - Improved parameter injection - Reduced use of dynamic memory that decreases indeterminism and the need for custom memory management ## MCP Policy Management The Mulesoft MCP Server provides `manage_flex_gateway_policy_project` and `get_flex_gateway_policy_example` tools to manage the custom policy lifecycle. To learn more, see [MuleSoft MCP Server Policy Management Tools](https://docs.mulesoft.com/mulesoft-mcp-server/reference-mcp-tools#policy-management). ## See Also - [Prerequisites for Omni Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Prerequisites for Flex Gateway Policy Development Kit (PDK) > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Before you begin using Flex Gateway Policy Development Kit (PDK), review these prerequisites. ## Flex Gateway PDK tutorials assume that you have [downloaded Flex Gateway](https://docs.mulesoft.com/gateway/latest/install) and have some prior knowledge of the product. Policies created with PDK might be compatible with Omni Gateway versions that aren’t compatible with PDK’s integration testing framework. The Omni Gateway version used for testing doesn’t affect the functionality of the policy when deployed to a different Omni Gateway version. See the following table to ensure your Omni Gateway’s compatibility:
ComponentMinimum Omni Gateway VersionMaximum Omni Gateway Version

Policies

1.6.1

Latest

Testing Framework

1.6.1

Latest

## Rust Requirements for Using PDK 1. Git To download and install, see [Installing Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git). 2. Rust programming language version v1.74.0 to v1.83.0: 1. To install or update Rust, run the following curl command: ```ssh curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` > [!NOTE] If you do not have curl installed, see > [Install curl](https://curl.se/download.html). 2. Due to the `wasm32-wasi` compilation target used by the PDK being deprecated in Rust v1.84.0, downgrade Rust to the last compatible version: ```ssh rustup default 1.83.0 ``` 3. Rust WebAssembly System Interface (WASI) Crate To install or update Rust WASI, run the following command: ```ssh rustup target add wasm32-wasi ``` 4. Cargo Generate To install or update Cargo Generate, run the following command: ```ssh cargo install --locked cargo-generate@0.22.0 ``` ## Supported Operating Systems - macOS - Ubuntu To use Ubuntu, execute the following commands to install the required packages after installing the [Rust Requirements for Using PDK](#rust-requirements): ```ssh sudo apt install -y build-essential sudo apt install -y pkg-config sudo apt install -y libssl-dev ``` - Windows > [!IMPORTANT] PDK supports Windows to develop and test you custom policy. However, Flex Gateway > does not support Windows in production environments. To execute the `make` commands included in PDK, install: 1. [PowerShell on Windows](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.3) 2. Make, with either: - [Make for Windows](https://gnuwin32.sourceforge.net/packages/make.htm) - Chocolatey: ```ssh choco install make ``` ## Anypoint CLI To configure the Anypoint CLI for PDK: 1. [Install Anypoint CLI 4.x v1.4.4 or later](https://docs.mulesoft.com/anypoint-cli/latest/install). > [!NOTE] To find your Anypoint CLI 4.x version, see > [Verify the Core Package Version](https://docs.mulesoft.com/anypoint-cli/latest/install#verify-installation). 2. [Authenticate to the Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/auth) using a [Connected App](https://docs.mulesoft.com/access-management/connected-apps-overview). Authenticate with a Connected App by providing the app’s client ID and client secret. > [!NOTE] In addition to the `View Organization` and `View Environment` scopes required to > authenticate to Anypoint Platform, to complete > [Uploading Custom Policies to Exchange](https://docs.mulesoft.com/pdk/1.3/policies-pdk-publish-policies), the Connected App must > have the `Exchange Contributor` scope applied. 3. Run the following command to install or update the Anypoint CLI PDK Plugin: ```ssh anypoint-cli-v4 plugins:install anypoint-cli-pdk-plugin ``` ## Docker Docker is required to use the [local debugging environment](https://docs.mulesoft.com/pdk/1.3/policies-pdk-debug-local) and the [integration testing framework](https://docs.mulesoft.com/pdk/1.3/policies-pdk-integration-tests) provided with PDK. You can still build and publish policies without docker. To install Docker, see [Install Docker](https://docs.docker.com/get-started/get-docker/). > [!IMPORTANT] You can run Flex Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Flex Gateway does not support Windows in production environments. ## Visual Studio (Suggested IDE) You can use PDK in any IDE or text editor, such as [Microsoft Visual Studio](https://code.visualstudio.com/) with the [Rust in Visual Studio Code Plugin](https://code.visualstudio.com/docs/languages/rust) installed. ## See Also - [Upgrading PDK](https://docs.mulesoft.com/pdk/1.3/policies-pdk-upgrade-pdk) - [Policy Development Kit Architecture Overview](https://docs.mulesoft.com/pdk/1.3/policies-pdk-architecture) - [Developing Custom Policies](https://docs.mulesoft.com/pdk/1.3/policies-pdk-develop-custom-policies) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Prerequisites for Flex Gateway Policy Development Kit (PDK) > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Before you begin using Flex Gateway Policy Development Kit (PDK), review these prerequisites. ## Flex Gateway PDK tutorials assume that you have [downloaded Flex Gateway](https://docs.mulesoft.com/gateway/latest/install) and have some prior knowledge of the product. Policies created with PDK might be compatible with Omni Gateway versions that aren’t compatible with PDK’s integration testing framework. The Omni Gateway version used for testing doesn’t affect the functionality of the policy when deployed to a different Omni Gateway version. See the following table to ensure your Omni Gateway’s compatibility:
ComponentMinimum Omni Gateway VersionMaximum Omni Gateway Version

Policies

1.6.1

Latest

Testing Framework

1.6.1

Latest

## Rust Requirements for Using PDK 1. Git To download and install, see [Installing Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git). 2. Rust programming language version v1.87.0 or later To install or update Rust, run the following curl command: ```ssh curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` > [!NOTE] If you do not have curl installed, see [Install curl](https://curl.se/download.html). 3. Rust WebAssembly System Interface (WASI) Crate To install or update Rust WASI, run the following command: ```ssh rustup target add wasm32-wasip1 ``` 4. Cargo Generate To install or update Cargo Generate, run the following command: ```ssh cargo install --locked cargo-generate@0.22.0 ``` ## Supported Operating Systems - macOS - Ubuntu To use Ubuntu, execute the following commands to install the required packages after installing the [Rust Requirements for Using PDK](#rust-requirements): ```ssh sudo apt install -y build-essential sudo apt install -y pkg-config sudo apt install -y libssl-dev ``` - Windows > [!IMPORTANT] PDK supports Windows to develop and test you custom policy. However, Flex Gateway > does not support Windows in production environments. To execute the `make` commands included in PDK, install: 1. [PowerShell on Windows](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.3) 2. Make, with either: - [Make for Windows](https://gnuwin32.sourceforge.net/packages/make.htm) - Chocolatey: ```ssh choco install make ``` ## Anypoint CLI To configure the Anypoint CLI for PDK: 1. [Install Anypoint CLI 4.x v1.4.4 or later](https://docs.mulesoft.com/anypoint-cli/latest/install). > [!NOTE] To find your Anypoint CLI 4.x version, see > [Verify the Core Package Version](https://docs.mulesoft.com/anypoint-cli/latest/install#verify-installation). 2. [Authenticate to the Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/auth) using a [Connected App](https://docs.mulesoft.com/access-management/connected-apps-overview). Authenticate with a Connected App by providing the app’s client ID and client secret. > [!NOTE] In addition to the `View Organization` and `View Environment` scopes required to > authenticate to Anypoint Platform, to complete > [Uploading Custom Policies to Exchange](https://docs.mulesoft.com/pdk/1.4/policies-pdk-publish-policies), the Connected App must > have the `Exchange Contributor` scope applied. 3. Run the following command to install or update the Anypoint CLI PDK Plugin: ```ssh anypoint-cli-v4 plugins:install anypoint-cli-pdk-plugin ``` ## Docker Docker is required to use the [local debugging environment](https://docs.mulesoft.com/pdk/1.4/policies-pdk-debug-local) and the [integration testing framework](https://docs.mulesoft.com/pdk/1.4/policies-pdk-integration-tests) provided with PDK. You can still build and publish policies without docker. To install Docker, see [Install Docker](https://docs.docker.com/get-started/get-docker/). > [!IMPORTANT] You can run Flex Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Flex Gateway does not support Windows in production environments. ## Visual Studio (Suggested IDE) You can use PDK in any IDE or text editor, such as [Microsoft Visual Studio](https://code.visualstudio.com/) with the [Rust in Visual Studio Code Plugin](https://code.visualstudio.com/docs/languages/rust) installed. ## See Also - [Upgrading PDK](https://docs.mulesoft.com/pdk/1.4/policies-pdk-upgrade-pdk) - [Policy Development Kit Architecture Overview](https://docs.mulesoft.com/pdk/1.4/policies-pdk-architecture) - [Developing Custom Policies](https://docs.mulesoft.com/pdk/1.4/policies-pdk-develop-custom-policies) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Prerequisites for Flex Gateway Policy Development Kit (PDK) > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Before you begin using Flex Gateway Policy Development Kit (PDK), review these prerequisites. ## Flex Gateway PDK tutorials assume that you have [downloaded Flex Gateway](https://docs.mulesoft.com/gateway/latest/install) and have some prior knowledge of the product. Policies created with PDK might be compatible with Omni Gateway versions that aren’t compatible with PDK’s integration testing framework. The Omni Gateway version used for testing doesn’t affect the functionality of the policy when deployed to a different Omni Gateway version. See the following table to ensure your Omni Gateway’s compatibility:
ComponentMinimum Omni Gateway VersionMaximum Omni Gateway Version

Policies

1.6.1

Latest

Testing Framework

1.6.1

Latest

## Rust Requirements for Using PDK 1. Git To download and install, see [Installing Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git). 2. Rust programming language version v1.87.0 or later To install or update Rust, run the following curl command: ```ssh curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` > [!NOTE] If you do not have curl installed, see [Install curl](https://curl.se/download.html). 3. Rust WebAssembly System Interface (WASI) Crate To install or update Rust WASI, run the following command: ```ssh rustup target add wasm32-wasip1 ``` 4. Cargo Generate To install or update Cargo Generate, run the following command: ```ssh cargo install --locked cargo-generate@0.22.0 ``` ## Supported Operating Systems - macOS - Ubuntu To use Ubuntu, execute the following commands to install the required packages after installing the [Rust Requirements for Using PDK](#rust-requirements): ```ssh sudo apt install -y build-essential sudo apt install -y pkg-config sudo apt install -y libssl-dev ``` - Windows > [!IMPORTANT] PDK supports Windows to develop and test you custom policy. However, Flex Gateway > does not support Windows in production environments. To execute the `make` commands included in PDK, install: 1. [PowerShell on Windows](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.3) 2. Make, with either: - [Make for Windows](https://gnuwin32.sourceforge.net/packages/make.htm) - Chocolatey: ```ssh choco install make ``` ## Anypoint CLI To configure the Anypoint CLI for PDK: 1. [Install Anypoint CLI 4.x v1.4.4 or later](https://docs.mulesoft.com/anypoint-cli/latest/install). > [!NOTE] To find your Anypoint CLI 4.x version, see > [Verify the Core Package Version](https://docs.mulesoft.com/anypoint-cli/latest/install#verify-installation). 2. [Authenticate to the Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/auth) using a [Connected App](https://docs.mulesoft.com/access-management/connected-apps-overview). Authenticate with a Connected App by providing the app’s client ID and client secret. > [!NOTE] In addition to the `View Organization` and `View Environment` scopes required to > authenticate to Anypoint Platform, to complete > [Uploading Custom Policies to Exchange](https://docs.mulesoft.com/pdk/1.5/policies-pdk-publish-policies), the Connected App must > have the `Exchange Contributor` scope applied. 3. Run the following command to install or update the Anypoint CLI PDK Plugin: ```ssh anypoint-cli-v4 plugins:install anypoint-cli-pdk-plugin ``` ## Docker Docker is required to use the [local debugging environment](https://docs.mulesoft.com/pdk/1.5/policies-pdk-debug-local) and the [integration testing framework](https://docs.mulesoft.com/pdk/1.5/policies-pdk-integration-tests) provided with PDK. You can still build and publish policies without docker. To install Docker, see [Install Docker](https://docs.docker.com/get-started/get-docker/). > [!IMPORTANT] You can run Flex Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Flex Gateway does not support Windows in production environments. ## Visual Studio (Suggested IDE) You can use PDK in any IDE or text editor, such as [Microsoft Visual Studio](https://code.visualstudio.com/) with the [Rust in Visual Studio Code Plugin](https://code.visualstudio.com/docs/languages/rust) installed. ## See Also - [Upgrading PDK](https://docs.mulesoft.com/pdk/1.5/policies-pdk-upgrade-pdk) - [Policy Development Kit Architecture Overview](https://docs.mulesoft.com/pdk/1.5/policies-pdk-architecture) - [Developing Custom Policies](https://docs.mulesoft.com/pdk/1.5/policies-pdk-develop-custom-policies) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Prerequisites for Flex Gateway Policy Development Kit (PDK) > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Before you begin using Flex Gateway Policy Development Kit (PDK), review these prerequisites. ## Flex Gateway PDK tutorials assume that you have [downloaded Flex Gateway](https://docs.mulesoft.com/gateway/latest/install) and have some prior knowledge of the product. Policies created with PDK might be compatible with Omni Gateway versions that aren’t compatible with PDK’s integration testing framework. The Omni Gateway version used for testing doesn’t affect the functionality of the policy when deployed to a different Omni Gateway version. See the following table to ensure your Omni Gateway’s compatibility:
ComponentMinimum Omni Gateway VersionMaximum Omni Gateway Version

Policies

1.6.1

Latest

Testing Framework

1.6.1

Latest

## Rust Requirements for Using PDK 1. Git To download and install, see [Installing Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git). 2. Rust programming language version v1.88.0 or later To install or update Rust, run the following curl command: ```ssh curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` > [!NOTE] If you do not have curl installed, see [Install curl](https://curl.se/download.html). 3. Rust WebAssembly System Interface (WASI) Crate To install or update Rust WASI, run the following command: ```ssh rustup target add wasm32-wasip1 ``` 4. Cargo Generate To install or update Cargo Generate, run the following command: ```ssh cargo install --locked cargo-generate@0.22.0 ``` ## Supported Operating Systems - macOS - Ubuntu To use Ubuntu, execute the following commands to install the required packages after installing the [Rust Requirements for Using PDK](#rust-requirements): ```ssh sudo apt install -y build-essential sudo apt install -y pkg-config sudo apt install -y libssl-dev ``` - Windows > [!IMPORTANT] PDK supports Windows to develop and test you custom policy. However, Flex Gateway > does not support Windows in production environments. To execute the `make` commands included in PDK, install: 1. [PowerShell on Windows](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.3) 2. Make, with either: - [Make for Windows](https://gnuwin32.sourceforge.net/packages/make.htm) - Chocolatey: ```ssh choco install make ``` ## Anypoint CLI To configure the Anypoint CLI for PDK: 1. [Install Anypoint CLI 4.x v1.4.4 or later](https://docs.mulesoft.com/anypoint-cli/latest/install). > [!NOTE] To find your Anypoint CLI 4.x version, see > [Verify the Core Package Version](https://docs.mulesoft.com/anypoint-cli/latest/install#verify-installation). 2. [Authenticate to the Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/auth) using a [Connected App](https://docs.mulesoft.com/access-management/connected-apps-overview). Authenticate with a Connected App by providing the app’s client ID and client secret. > [!NOTE] In addition to the `View Organization` and `View Environment` scopes required to > authenticate to Anypoint Platform, to complete > [Uploading Custom Policies to Exchange](https://docs.mulesoft.com/pdk/1.6/policies-pdk-publish-policies), the Connected App must > have the `Exchange Contributor` scope applied. 3. Run the following command to install or update the Anypoint CLI PDK Plugin: ```ssh anypoint-cli-v4 plugins:install anypoint-cli-pdk-plugin ``` ## Docker Docker is required to use the [local debugging environment](https://docs.mulesoft.com/pdk/1.6/policies-pdk-debug-local) and the [integration testing framework](https://docs.mulesoft.com/pdk/1.6/policies-pdk-integration-tests) provided with PDK. You can still build and publish policies without docker. To install Docker, see [Install Docker](https://docs.docker.com/get-started/get-docker/). > [!IMPORTANT] You can run Flex Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Flex Gateway does not support Windows in production environments. ## Visual Studio (Suggested IDE) You can use PDK in any IDE or text editor, such as [Microsoft Visual Studio](https://code.visualstudio.com/) with the [Rust in Visual Studio Code Plugin](https://code.visualstudio.com/docs/languages/rust) installed. ## See Also - [Upgrading PDK](https://docs.mulesoft.com/pdk/1.6/policies-pdk-upgrade-pdk) - [Policy Development Kit Architecture Overview](https://docs.mulesoft.com/pdk/1.6/policies-pdk-architecture) - [Developing Custom Policies](https://docs.mulesoft.com/pdk/1.6/policies-pdk-develop-custom-policies) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Prerequisites for Flex Gateway Policy Development Kit (PDK) > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Before you begin using Flex Gateway Policy Development Kit (PDK), review these prerequisites. ## Flex Gateway PDK tutorials assume that you have [downloaded Flex Gateway](https://docs.mulesoft.com/gateway/latest/install) and have some prior knowledge of the product. ## Rust Requirements for Using PDK 1. Git To download and install, see [Installing Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git). 2. Rust programming language version v1.88.0 or later To install or update Rust, run the following curl command: ```ssh curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` > [!NOTE] If you do not have curl installed, see [Install curl](https://curl.se/download.html). 3. Rust WebAssembly System Interface (WASI) Crate To install or update Rust WASI, run the following command: ```ssh rustup target add wasm32-wasip1 ``` 4. Cargo Generate To install or update Cargo Generate, run the following command: ```ssh cargo install --locked cargo-generate@0.22.0 ``` ## Supported Operating Systems - macOS - Ubuntu To use Ubuntu, execute the following commands to install the required packages after installing the [Rust Requirements for Using PDK](#rust-requirements): ```ssh sudo apt install -y build-essential sudo apt install -y pkg-config sudo apt install -y libssl-dev ``` - Windows > [!IMPORTANT] PDK supports Windows to develop and test you custom policy. However, Flex Gateway > does not support Windows in production environments. To execute the `make` commands included in PDK, install: 1. [PowerShell on Windows](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.3) 2. Make, with either: - [Make for Windows](https://gnuwin32.sourceforge.net/packages/make.htm) - Chocolatey: ```ssh choco install make ``` ## Anypoint CLI To configure the Anypoint CLI for PDK: 1. [Install Anypoint CLI 4.x v1.4.4 or later](https://docs.mulesoft.com/anypoint-cli/latest/install). > [!NOTE] To find your Anypoint CLI 4.x version, see > [Verify the Core Package Version](https://docs.mulesoft.com/anypoint-cli/latest/install#verify-installation). 2. [Authenticate to the Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/auth) using a [Connected App](https://docs.mulesoft.com/access-management/connected-apps-overview). Authenticate with a Connected App by providing the app’s client ID and client secret. > [!NOTE] In addition to the `View Organization` and `View Environment` scopes required to > authenticate to Anypoint Platform, to complete > [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.7/policies-pdk-publish-policies), the Connected > App must have the `Exchange Contributor` scope applied. 3. Run the following command to install or update the Anypoint CLI PDK Plugin: ```ssh anypoint-cli-v4 plugins:install anypoint-pdk-plugin ``` ## Docker Docker is required to use the [local debugging environment](https://docs.mulesoft.com/pdk/1.7/policies-pdk-debug-local) and the [integration testing framework](https://docs.mulesoft.com/pdk/1.7/policies-pdk-integration-tests) provided with PDK. You can still build and publish policies without docker. To install Docker, see [Install Docker](https://docs.docker.com/get-docker/). > [!IMPORTANT] You can run Flex Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Flex Gateway does not support Windows in production environments. ## Visual Studio (Suggested IDE) You can use PDK in any IDE or text editor, such as [Microsoft Visual Studio](https://code.visualstudio.com/) with the [Rust in Visual Studio Code Plugin](https://code.visualstudio.com/docs/languages/rust) installed. ## See Also - [Upgrading PDK](https://docs.mulesoft.com/pdk/1.7/policies-pdk-upgrade-pdk) - [Policy Development Kit Architecture Overview](https://docs.mulesoft.com/pdk/1.7/policies-pdk-architecture) - [Developing Custom Policies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-develop-custom-policies) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Prerequisites for Omni Gateway Policy Development Kit (PDK) > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Before you begin using Omni Gateway Policy Development Kit (PDK), review these prerequisites. ## Omni Gateway PDK tutorials assume that you have [downloaded Omni Gateway](https://docs.mulesoft.com/gateway/latest/install) and have some prior knowledge of the product. ## Rust Requirements for Using PDK 1. Git To download and install, see [Installing Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git). 2. Rust programming language version v1.88.0 or later To install or update Rust, run the following curl command: ```ssh curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` > [!NOTE] If you do not have curl installed, see [Install curl](https://curl.se/download.html). 3. Rust WebAssembly System Interface (WASI) Crate To install or update Rust WASI, run the following command: ```ssh rustup target add wasm32-wasip1 ``` 4. Cargo Generate To install or update Cargo Generate, run the following command: ```ssh cargo install --locked cargo-generate@0.22.0 ``` ## Supported Operating Systems - macOS - Ubuntu To use Ubuntu, execute the following commands to install the required packages after installing the [Rust Requirements for Using PDK](#rust-requirements): ```ssh sudo apt install -y build-essential sudo apt install -y pkg-config sudo apt install -y libssl-dev ``` - Windows > [!IMPORTANT] PDK supports Windows to develop and test you custom policy. However, Omni Gateway > does not support Windows in production environments. To execute the `make` commands included in PDK, install: 1. [PowerShell on Windows](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.3) 2. Make, with either: - [Make for Windows](https://gnuwin32.sourceforge.net/packages/make.htm) - Chocolatey: ```ssh choco install make ``` ## Anypoint CLI To configure the Anypoint CLI for PDK: 1. [Install Anypoint CLI 4.x v1.4.4 or later](https://docs.mulesoft.com/anypoint-cli/latest/install). > [!NOTE] To find your Anypoint CLI 4.x version, see > [Verify the Core Package Version](https://docs.mulesoft.com/anypoint-cli/latest/install#verify-installation). 2. [Authenticate to the Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/auth) using a [Connected App](https://docs.mulesoft.com/access-management/connected-apps-overview). Authenticate with a Connected App by providing the app’s client ID and client secret. > [!NOTE] In addition to the `View Organization` and `View Environment` scopes required to > authenticate to Anypoint Platform, to complete > [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.8/policies-pdk-publish-policies), the Connected > App must have the `Exchange Contributor` scope applied. 3. Run the following command to install or update the Anypoint CLI PDK Plugin: ```ssh anypoint-cli-v4 plugins:install anypoint-pdk-plugin ``` ## Docker Docker is required to use the [local debugging environment](https://docs.mulesoft.com/pdk/1.8/policies-pdk-debug-local) and the [integration testing framework](https://docs.mulesoft.com/pdk/1.8/policies-pdk-integration-tests) provided with PDK. You can still build and publish policies without docker. To install Docker, see [Install Docker](https://docs.docker.com/get-docker/). > [!IMPORTANT] You can run Omni Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Omni Gateway does not support Windows in production environments. ## Visual Studio (Suggested IDE) You can use PDK in any IDE or text editor, such as [Microsoft Visual Studio](https://code.visualstudio.com/) with the [Rust in Visual Studio Code Plugin](https://code.visualstudio.com/docs/languages/rust) installed. ## See Also - [Upgrading PDK](https://docs.mulesoft.com/pdk/1.8/policies-pdk-upgrade-pdk) - [Policy Development Kit Architecture Overview](https://docs.mulesoft.com/pdk/1.8/policies-pdk-architecture) - [Developing Custom Policies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-develop-custom-policies) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Prerequisites for Omni Gateway Policy Development Kit (PDK) > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Before you begin using Omni Gateway Policy Development Kit (PDK), review these prerequisites. ## Omni Gateway PDK tutorials assume that you have [downloaded Omni Gateway](https://docs.mulesoft.com/gateway/latest/install) and have some prior knowledge of the product. ## Rust Requirements for Using PDK 1. Git To download and install, see [Installing Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git). 2. Rust programming language version v1.88.0 or later To install or update Rust, run the following curl command: ```ssh curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` > [!NOTE] If you do not have curl installed, see [Install curl](https://curl.se/download.html). 3. Rust WebAssembly System Interface (WASI) Crate To install or update Rust WASI, run the following command: ```ssh rustup target add wasm32-wasip1 ``` 4. Cargo Generate To install or update Cargo Generate, run the following command: ```ssh cargo install --locked cargo-generate@0.22.0 ``` ## Supported Operating Systems - macOS - Ubuntu To use Ubuntu, execute the following commands to install the required packages after installing the [Rust Requirements for Using PDK](#rust-requirements): ```ssh sudo apt install -y build-essential sudo apt install -y pkg-config sudo apt install -y libssl-dev ``` - Windows > [!IMPORTANT] PDK supports Windows to develop and test you custom policy. However, Omni Gateway > does not support Windows in production environments. To execute the `make` commands included in PDK, install: 1. [PowerShell on Windows](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.3) 2. Make, with either: - [Make for Windows](https://gnuwin32.sourceforge.net/packages/make.htm) - Chocolatey: ```ssh choco install make ``` ## Anypoint CLI To configure the Anypoint CLI for PDK: 1. [Install Anypoint CLI 4.x v1.4.4 or later](https://docs.mulesoft.com/anypoint-cli/latest/install). > [!NOTE] To find your Anypoint CLI 4.x version, see > [Verify the Core Package Version](https://docs.mulesoft.com/anypoint-cli/latest/install#verify-installation). 2. [Authenticate to the Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/auth) using a [Connected App](https://docs.mulesoft.com/access-management/connected-apps-overview). Authenticate with a Connected App by providing the app’s client ID and client secret. > [!NOTE] In addition to the `View Organization` and `View Environment` scopes required to > authenticate to Anypoint Platform, to complete > [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/1.9/policies-pdk-publish-policies), the Connected > App must have the `Exchange Contributor` scope applied. 3. Run the following command to install or update the Anypoint CLI PDK Plugin: ```ssh anypoint-cli-v4 plugins:install anypoint-pdk-plugin ``` ## Docker Docker is required to use the [local debugging environment](https://docs.mulesoft.com/pdk/1.9/policies-pdk-debug-local) and the [integration testing framework](https://docs.mulesoft.com/pdk/1.9/policies-pdk-integration-tests) provided with PDK. You can still build and publish policies without docker. To install Docker, see [Install Docker](https://docs.docker.com/get-docker/). > [!IMPORTANT] You can run Omni Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Omni Gateway does not support Windows in production environments. ## Visual Studio (Suggested IDE) You can use PDK in any IDE or text editor, such as [Microsoft Visual Studio](https://code.visualstudio.com/) with the [Rust in Visual Studio Code Plugin](https://code.visualstudio.com/docs/languages/rust) installed. ## See Also - [Upgrading PDK](https://docs.mulesoft.com/pdk/1.9/policies-pdk-upgrade-pdk) - [Policy Development Kit Architecture Overview](https://docs.mulesoft.com/pdk/1.9/policies-pdk-architecture) - [Developing Custom Policies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-develop-custom-policies) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Prerequisites for Omni Gateway Policy Development Kit (PDK) > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Before you begin using Omni Gateway Policy Development Kit (PDK), review these prerequisites. ## Omni Gateway PDK tutorials assume that you have [downloaded Omni Gateway](https://docs.mulesoft.com/gateway/latest/install) and have some prior knowledge of the product. ## Rust Requirements for Using PDK 1. Git To download and install, see [Installing Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git). 2. Rust programming language version v1.88.0 or later To install or update Rust, run the following curl command: ```ssh curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` > [!NOTE] If you do not have curl installed, see [Install curl](https://curl.se/download.html). 3. Rust WebAssembly System Interface (WASI) Crate To install or update Rust WASI, run the following command: ```ssh rustup target add wasm32-wasip1 ``` 4. Cargo Generate To install or update Cargo Generate, run the following command: ```ssh cargo install --locked cargo-generate@0.22.0 ``` ## Supported Operating Systems - macOS - Ubuntu To use Ubuntu, execute the following commands to install the required packages after installing the [Rust Requirements for Using PDK](#rust-requirements): ```ssh sudo apt install -y build-essential sudo apt install -y pkg-config sudo apt install -y libssl-dev ``` - Windows > [!IMPORTANT] PDK supports Windows to develop and test you custom policy. However, Omni Gateway > does not support Windows in production environments. To execute the `make` commands included in PDK, install: 1. [PowerShell on Windows](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.3) 2. Make, with either: - [Make for Windows](https://gnuwin32.sourceforge.net/packages/make.htm) - Chocolatey: ```ssh choco install make ``` ## Anypoint CLI To configure the Anypoint CLI for PDK: 1. [Install Anypoint CLI 4.x v1.4.4 or later](https://docs.mulesoft.com/anypoint-cli/latest/install). > [!NOTE] To find your Anypoint CLI 4.x version, see > [Verify the Core Package Version](https://docs.mulesoft.com/anypoint-cli/latest/install#verify-installation). 2. [Authenticate to the Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/auth) using a [Connected App](https://docs.mulesoft.com/access-management/connected-apps-overview). Authenticate with a Connected App by providing the app’s client ID and client secret. > [!NOTE] In addition to the `View Organization` and `View Environment` scopes required to > authenticate to Anypoint Platform, to complete > [Publishing Unified-Model Policies to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies), the Connected > App must have the `Exchange Contributor` scope applied. 3. Run the following command to install or update the Anypoint CLI PDK Plugin: ```ssh anypoint-cli-v4 plugins:install anypoint-pdk-plugin ``` ## Docker Docker is required to use the [local debugging environment](https://docs.mulesoft.com/pdk/latest/policies-pdk-debug-local) and the [integration testing framework](https://docs.mulesoft.com/pdk/latest/policies-pdk-integration-tests) provided with PDK. You can still build and publish policies without docker. To install Docker, see [Install Docker](https://docs.docker.com/get-docker/). > [!IMPORTANT] You can run Omni Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Omni Gateway does not support Windows in production environments. ## Visual Studio (Suggested IDE) You can use PDK in any IDE or text editor, such as [Microsoft Visual Studio](https://code.visualstudio.com/) with the [Rust in Visual Studio Code Plugin](https://code.visualstudio.com/docs/languages/rust) installed. ## See Also - [Upgrading PDK](https://docs.mulesoft.com/pdk/latest/policies-pdk-upgrade-pdk) - [Policy Development Kit Architecture Overview](https://docs.mulesoft.com/pdk/latest/policies-pdk-architecture) - [Developing Custom Policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-develop-custom-policies) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Publishing Custom Policies to Exchange > For the full documentation index, see: https://docs.mulesoft.com/llms.txt During the custom policy development cycle, you can upload your policy to Anypoint Exchange to create and manage policy assets, control versions, and distribute policies to other users or gateways. For more information about Exchange, see [Anypoint Exchange Overview](https://docs.mulesoft.com/exchange/). The steps and commands differ depending on whether your policy is a unified-model or split-model project. Choose the guide that matches your project: - [Uploading a Unified-Model Policy to Exchange](https://docs.mulesoft.com/pdk/1.7/policies-pdk-publish-policies) - [Uploading a Split-Model Policy to Exchange](https://docs.mulesoft.com/pdk/1.7/policies-pdk-publish-policies-split) After you upload your policy to Exchange, see [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-apply-policies) to apply the policy to your APIs. ## See Also - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.7/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Publishing Custom Policies to Exchange > For the full documentation index, see: https://docs.mulesoft.com/llms.txt During the custom policy development cycle, you can upload your policy to Anypoint Exchange to create and manage policy assets, control versions, and distribute policies to other users or gateways. For more information about Exchange, see [Anypoint Exchange Overview](https://docs.mulesoft.com/exchange/). The steps and commands differ depending on whether your policy is a unified-model or split-model project. Choose the guide that matches your project: - [Uploading a Unified-Model Policy to Exchange](https://docs.mulesoft.com/pdk/1.8/policies-pdk-publish-policies) - [Uploading a Split-Model Policy to Exchange](https://docs.mulesoft.com/pdk/1.8/policies-pdk-publish-policies-split) After you upload your policy to Exchange, see [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-apply-policies) to apply the policy to your APIs. ## See Also - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.8/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Publishing Custom Policies to Exchange > For the full documentation index, see: https://docs.mulesoft.com/llms.txt During the custom policy development cycle, you can upload your policy to Anypoint Exchange to create and manage policy assets, control versions, and distribute policies to other users or gateways. For more information about Exchange, see [Anypoint Exchange Overview](https://docs.mulesoft.com/exchange/). The steps and commands differ depending on whether your policy is a unified-model or split-model project. Choose the guide that matches your project: - [Uploading a Unified-Model Policy to Exchange](https://docs.mulesoft.com/pdk/1.9/policies-pdk-publish-policies) - [Uploading a Split-Model Policy to Exchange](https://docs.mulesoft.com/pdk/1.9/policies-pdk-publish-policies-split) After you upload your policy to Exchange, see [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-apply-policies) to apply the policy to your APIs. ## See Also - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.9/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Publishing Custom Policies to Exchange > For the full documentation index, see: https://docs.mulesoft.com/llms.txt During the custom policy development cycle, you can upload your policy to Anypoint Exchange to create and manage policy assets, control versions, and distribute policies to other users or gateways. For more information about Exchange, see [Anypoint Exchange Overview](https://docs.mulesoft.com/exchange/). The steps and commands differ depending on whether your policy is a unified-model or split-model project. Choose the guide that matches your project: - [Uploading a Unified-Model Policy to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies) - [Uploading a Split-Model Policy to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies-split) After you upload your policy to Exchange, see [Applying Custom Policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-apply-policies) to apply the policy to your APIs. ## See Also - [Applying Custom Policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/latest/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Publishing Split-Model Policies to Exchange > For the full documentation index, see: https://docs.mulesoft.com/llms.txt During the custom split-model policy development cycle, you can upload the definition and implementation of your policy to Exchange to create a new Exchange assets to manage the asset versions and to distribute it to other users. For more information about Exchange, see [Anypoint Exchange Overview](https://docs.mulesoft.com/exchange/). For custom policies running in Local Mode, it is not required to publish your policy to Exchange. However, Exchange is a useful version control tool. It is your responsibility to distribute custom policies for Local Mode use. When uploading your policy to Exchange, you can choose to either: - [Publish a Custom Policy](#publish-a-new-split-model-policy) Publish a policy if the policy version is still in development. This enables you to test and edit the policy version. To learn about development assets, see [Publish a Custom Policy](https://docs.mulesoft.com/pdk/1.7/policies-pdk-publish-policies#publish). - Release a Custom Policy Release the policy to create a definitive version of the policy. After releasing the policy, you must create a new policy version to edit the policy. To learn about production assets, see [Release a Custom Policy](https://docs.mulesoft.com/pdk/1.7/policies-pdk-publish-policies#release). Every time you publish or release a definition and implementation asset, you create a new `stable` version of that asset in Exchange. For more information about `stable` state assets, see [Stable State Assets](https://docs.mulesoft.com/exchange/lifecycle#stablet-state). After you upload your definition and implementation assets to Exchange, see [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-apply-policies). ## Before You Begin - Ensure that the Connected App you used to authenticate to the [Anypoint Platform CLI](https://docs.mulesoft.com/pdk/1.7/policies-pdk-prerequisites#cli) has the `Exchange Contributor` scope applied. - [Compile your Policy](https://docs.mulesoft.com/pdk/1.7/policies-pdk-compile-policies). ## Publish a New Split-Model Policy 1. [Create a definition project](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-project-split#create-a-new-policy-definition-project): 1. Make changes on the `gcl.yaml` 2. Execute `make publish` in the definition project to publish the development definition asset to Exchange. 2. [Create an implementation project](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-project-split#create-a-new-policy-implementation-project): 1. Update the `definition_asset_id` version field in the `cargo.toml` file to `1.0.0-DEV`. 2. Execute `make build-asset-files` in the implementation project. 3. Code your policy logic and test locally. 4. Execute `make publish` to release the development implementation asset to Exchange for testing in lower environments. 5. Validate the policy works as expected. Complete steps C and D until testing is complete. 3. After validating the policy works as expected, release the both assets to Exchange: 1. In the definition project, execute `make release` to release the definition asset to Exchange. 2. In the implementation project, update the `definition_asset_id` version field in the `cargo.toml` file to `1.0.0`. 3. Execute `make release` to release the implementation asset to Exchange. ## Publish a Patch Version Update (Implementation Update) After you have [Published a new split-model policy](#publish-a-new-split-model-policy), you can update the implementation asset for bug fixes or performance updates: 1. Develop the new policy implementation: 1. In the implementation project, update the patch number of version in the `cargo.toml` file. For example: `1.0.1`. 2. Add the `-DEV` suffix to the `definition_asset_id` version field in the `cargo.toml`. For example: `1.0.0-DEV`. 3. Execute `make build-asset-files` in the implementation project. 4. Code your policy logic and test locally. 5. Execute `make publish` to release the development implementation asset to Exchange for testing in lower environments. 6. Validate the policy works as expected. Complete steps D and E until testing is complete. 2. After validating the policy works as expected, release the implementation asset to Exchange: 1. In the implementation project, remove the `-DEV` suffix from the `definition_asset_id` version field in the `cargo.toml` file. For example: `1.0.0-DEV` to `1.0.0`. 2. Execute `make release` to release the implementation asset to Exchange. ## Publish a Minor or Major Version Update (Definition and Implementation Update) After you have [Published a new split-model policy](#publish-a-new-split-model-policy), you can update the definition and implementation assets for updates that require new parameters: 1. Update the definition asset: 1. Update the version in the `exchange.json` file of your definition project to `1.1.0`. 2. Make changes to the `gcl.yaml` file. 3. `make publish` on the definition project to publish the development definition asset to Exchange. 2. Update the implementation asset: 1. In the implementation project, update the minor or major number of version in the `cargo.toml` file. For example: `1.0.0` to `1.1.0`. 2. Update and add the `-DEV` suffix to the `definition_asset_id` version field in the `cargo.toml`. For example: `1.0.0-DEV` to `1.1.0-DEV`. 3. Execute `make build-asset-files` in the implementation project. 4. Code your policy logic and test locally. 5. Execute `make publish` to release the development implementation asset to Exchange for testing in lower environments. 6. Validate the policy works as expected. Complete steps D and E until testing is complete. 3. After validating the policy works as expected, release both assets to Exchange: 1. In the implementation project, remove the `-DEV` suffix from the `definition_asset_id` version field in the `cargo.toml` file. For example: `1.1.0-DEV` to `1.1.0`. 2. Execute `make release` to release the implementation asset to Exchange. ## Develop Split Model Policies Locally Without Publishing to Exchange 1. Develop the policy definition: 1. Ensure the version in the `exchange.json` file is the correct version. For example: `1.0.0` for your first version. 2. Make changes to the `gcl.yaml` file. 3. Execute `make release-local` in the definition project. 2. Develop the policy implementation: 1. Add the `-DEV` suffix to the `definition_asset_id` version field in the `cargo.toml` and ensure it matches the definition asset version used in step one. 2. Execute `make build-asset-files` in the implementation project. 3. Code your policy logic and test locally. 4. Validate the policy works as expected. Complete steps C until testing is complete. 3. If you wish to distribute the policy locally as a production asset: 1. Remove the `-DEV` suffix from the `definition_asset_id` version field in the `cargo.toml` file. For example: `1.0.0-DEV` to `1.0.0`. 2. Execute `make build` to compile the implementation asset. 3. Distribute the policy assets as desired. ## See Also - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.7/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Publishing Split-Model Policies to Exchange > For the full documentation index, see: https://docs.mulesoft.com/llms.txt During the custom split-model policy development cycle, you can upload the definition and implementation of your policy to Exchange to create a new Exchange assets to manage the asset versions and to distribute it to other users. For more information about Exchange, see [Anypoint Exchange Overview](https://docs.mulesoft.com/exchange/). For custom policies running in Local Mode, it is not required to publish your policy to Exchange. However, Exchange is a useful version control tool. It is your responsibility to distribute custom policies for Local Mode use. When uploading your policy to Exchange, you can choose to either: - [Publish a Custom Policy](#publish-a-new-split-model-policy) Publish a policy if the policy version is still in development. This enables you to test and edit the policy version. To learn about development assets, see [Publish a Custom Policy](https://docs.mulesoft.com/pdk/1.8/policies-pdk-publish-policies#publish). - Release a Custom Policy Release the policy to create a definitive version of the policy. After releasing the policy, you must create a new policy version to edit the policy. To learn about production assets, see [Release a Custom Policy](https://docs.mulesoft.com/pdk/1.8/policies-pdk-publish-policies#release). Every time you publish or release a definition and implementation asset, you create a new `stable` version of that asset in Exchange. For more information about `stable` state assets, see [Stable State Assets](https://docs.mulesoft.com/exchange/lifecycle#stablet-state). After you upload your definition and implementation assets to Exchange, see [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-apply-policies). ## Before You Begin - Ensure that the Connected App you used to authenticate to the [Anypoint Platform CLI](https://docs.mulesoft.com/pdk/1.8/policies-pdk-prerequisites#cli) has the `Exchange Contributor` scope applied. - [Compile your Policy](https://docs.mulesoft.com/pdk/1.8/policies-pdk-compile-policies). ## Publish a New Split-Model Policy 1. [Create a definition project](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-project-split#create-a-new-policy-definition-project): 1. Make changes on the `gcl.yaml` 2. Execute `make publish` in the definition project to publish the development definition asset to Exchange. 2. [Create an implementation project](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-project-split#create-a-new-policy-implementation-project): 1. Update the `definition_asset_id` version field in the `cargo.toml` file to `1.0.0-DEV`. 2. Execute `make build-asset-files` in the implementation project. 3. Code your policy logic and test locally. 4. Execute `make publish` to release the development implementation asset to Exchange for testing in lower environments. 5. Validate the policy works as expected. Complete steps C and D until testing is complete. 3. After validating the policy works as expected, release the both assets to Exchange: 1. In the definition project, execute `make release` to release the definition asset to Exchange. 2. In the implementation project, update the `definition_asset_id` version field in the `cargo.toml` file to `1.0.0`. 3. Execute `make release` to release the implementation asset to Exchange. ## Publish a Patch Version Update (Implementation Update) After you have [Published a new split-model policy](#publish-a-new-split-model-policy), you can update the implementation asset for bug fixes or performance updates: 1. Develop the new policy implementation: 1. In the implementation project, update the patch number of version in the `cargo.toml` file. For example: `1.0.1`. 2. Add the `-DEV` suffix to the `definition_asset_id` version field in the `cargo.toml`. For example: `1.0.0-DEV`. 3. Execute `make build-asset-files` in the implementation project. 4. Code your policy logic and test locally. 5. Execute `make publish` to release the development implementation asset to Exchange for testing in lower environments. 6. Validate the policy works as expected. Complete steps D and E until testing is complete. 2. After validating the policy works as expected, release the implementation asset to Exchange: 1. In the implementation project, remove the `-DEV` suffix from the `definition_asset_id` version field in the `cargo.toml` file. For example: `1.0.0-DEV` to `1.0.0`. 2. Execute `make release` to release the implementation asset to Exchange. ## Publish a Minor or Major Version Update (Definition and Implementation Update) After you have [Published a new split-model policy](#publish-a-new-split-model-policy), you can update the definition and implementation assets for updates that require new parameters: 1. Update the definition asset: 1. Update the version in the `exchange.json` file of your definition project to `1.1.0`. 2. Make changes to the `gcl.yaml` file. 3. `make publish` on the definition project to publish the development definition asset to Exchange. 2. Update the implementation asset: 1. In the implementation project, update the minor or major number of version in the `cargo.toml` file. For example: `1.0.0` to `1.1.0`. 2. Update and add the `-DEV` suffix to the `definition_asset_id` version field in the `cargo.toml`. For example: `1.0.0-DEV` to `1.1.0-DEV`. 3. Execute `make build-asset-files` in the implementation project. 4. Code your policy logic and test locally. 5. Execute `make publish` to release the development implementation asset to Exchange for testing in lower environments. 6. Validate the policy works as expected. Complete steps D and E until testing is complete. 3. After validating the policy works as expected, release both assets to Exchange: 1. In the implementation project, remove the `-DEV` suffix from the `definition_asset_id` version field in the `cargo.toml` file. For example: `1.1.0-DEV` to `1.1.0`. 2. Execute `make release` to release the implementation asset to Exchange. ## Develop Split Model Policies Locally Without Publishing to Exchange 1. Develop the policy definition: 1. Ensure the version in the `exchange.json` file is the correct version. For example: `1.0.0` for your first version. 2. Make changes to the `gcl.yaml` file. 3. Execute `make release-local` in the definition project. 2. Develop the policy implementation: 1. Add the `-DEV` suffix to the `definition_asset_id` version field in the `cargo.toml` and ensure it matches the definition asset version used in step one. 2. Execute `make build-asset-files` in the implementation project. 3. Code your policy logic and test locally. 4. Validate the policy works as expected. Complete steps C until testing is complete. 3. If you wish to distribute the policy locally as a production asset: 1. Remove the `-DEV` suffix from the `definition_asset_id` version field in the `cargo.toml` file. For example: `1.0.0-DEV` to `1.0.0`. 2. Execute `make build` to compile the implementation asset. 3. Distribute the policy assets as desired. ## See Also - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.8/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Publishing Split-Model Policies to Exchange > For the full documentation index, see: https://docs.mulesoft.com/llms.txt During the custom split-model policy development cycle, you can upload the definition and implementation of your policy to Exchange to create a new Exchange assets to manage the asset versions and to distribute it to other users. For more information about Exchange, see [Anypoint Exchange Overview](https://docs.mulesoft.com/exchange/). For custom policies running in Local Mode, it is not required to publish your policy to Exchange. However, Exchange is a useful version control tool. It is your responsibility to distribute custom policies for Local Mode use. When uploading your policy to Exchange, you can choose to either: - [Publish a Custom Policy](#publish-a-new-split-model-policy) Publish a policy if the policy version is still in development. This enables you to test and edit the policy version. To learn about development assets, see [Publish a Custom Policy](https://docs.mulesoft.com/pdk/1.9/policies-pdk-publish-policies#publish). - Release a Custom Policy Release the policy to create a definitive version of the policy. After releasing the policy, you must create a new policy version to edit the policy. To learn about production assets, see [Release a Custom Policy](https://docs.mulesoft.com/pdk/1.9/policies-pdk-publish-policies#release). Every time you publish or release a definition and implementation asset, you create a new `stable` version of that asset in Exchange. For more information about `stable` state assets, see [Stable State Assets](https://docs.mulesoft.com/exchange/lifecycle#stablet-state). After you upload your definition and implementation assets to Exchange, see [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-apply-policies). ## Before You Begin - Ensure that the Connected App you used to authenticate to the [Anypoint Platform CLI](https://docs.mulesoft.com/pdk/1.9/policies-pdk-prerequisites#cli) has the `Exchange Contributor` scope applied. - [Compile your Policy](https://docs.mulesoft.com/pdk/1.9/policies-pdk-compile-policies). ## Publish a New Split-Model Policy 1. [Create a definition project](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-project-split#create-a-new-policy-definition-project): 1. Make changes on the `gcl.yaml` 2. Execute `make publish` in the definition project to publish the development definition asset to Exchange. 2. [Create an implementation project](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-project-split#create-a-new-policy-implementation-project): 1. Update the `definition_asset_id` version field in the `cargo.toml` file to `1.0.0-DEV`. 2. Execute `make build-asset-files` in the implementation project. 3. Code your policy logic and test locally. 4. Execute `make publish` to release the development implementation asset to Exchange for testing in lower environments. 5. Validate the policy works as expected. Complete steps C and D until testing is complete. 3. After validating the policy works as expected, release the both assets to Exchange: 1. In the definition project, execute `make release` to release the definition asset to Exchange. 2. In the implementation project, update the `definition_asset_id` version field in the `cargo.toml` file to `1.0.0`. 3. Execute `make release` to release the implementation asset to Exchange. ## Publish a Patch Version Update (Implementation Update) After you have [Published a new split-model policy](#publish-a-new-split-model-policy), you can update the implementation asset for bug fixes or performance updates: 1. Develop the new policy implementation: 1. In the implementation project, update the patch number of version in the `cargo.toml` file. For example: `1.0.1`. 2. Add the `-DEV` suffix to the `definition_asset_id` version field in the `cargo.toml`. For example: `1.0.0-DEV`. 3. Execute `make build-asset-files` in the implementation project. 4. Code your policy logic and test locally. 5. Execute `make publish` to release the development implementation asset to Exchange for testing in lower environments. 6. Validate the policy works as expected. Complete steps D and E until testing is complete. 2. After validating the policy works as expected, release the implementation asset to Exchange: 1. In the implementation project, remove the `-DEV` suffix from the `definition_asset_id` version field in the `cargo.toml` file. For example: `1.0.0-DEV` to `1.0.0`. 2. Execute `make release` to release the implementation asset to Exchange. ## Publish a Minor or Major Version Update (Definition and Implementation Update) After you have [Published a new split-model policy](#publish-a-new-split-model-policy), you can update the definition and implementation assets for updates that require new parameters: 1. Update the definition asset: 1. Update the version in the `exchange.json` file of your definition project to `1.1.0`. 2. Make changes to the `gcl.yaml` file. 3. `make publish` on the definition project to publish the development definition asset to Exchange. 2. Update the implementation asset: 1. In the implementation project, update the minor or major number of version in the `cargo.toml` file. For example: `1.0.0` to `1.1.0`. 2. Update and add the `-DEV` suffix to the `definition_asset_id` version field in the `cargo.toml`. For example: `1.0.0-DEV` to `1.1.0-DEV`. 3. Execute `make build-asset-files` in the implementation project. 4. Code your policy logic and test locally. 5. Execute `make publish` to release the development implementation asset to Exchange for testing in lower environments. 6. Validate the policy works as expected. Complete steps D and E until testing is complete. 3. After validating the policy works as expected, release both assets to Exchange: 1. In the implementation project, remove the `-DEV` suffix from the `definition_asset_id` version field in the `cargo.toml` file. For example: `1.1.0-DEV` to `1.1.0`. 2. Execute `make release` to release the implementation asset to Exchange. ## Develop Split Model Policies Locally Without Publishing to Exchange 1. Develop the policy definition: 1. Ensure the version in the `exchange.json` file is the correct version. For example: `1.0.0` for your first version. 2. Make changes to the `gcl.yaml` file. 3. Execute `make release-local` in the definition project. 2. Develop the policy implementation: 1. Add the `-DEV` suffix to the `definition_asset_id` version field in the `cargo.toml` and ensure it matches the definition asset version used in step one. 2. Execute `make build-asset-files` in the implementation project. 3. Code your policy logic and test locally. 4. Validate the policy works as expected. Complete steps C until testing is complete. 3. If you wish to distribute the policy locally as a production asset: 1. Remove the `-DEV` suffix from the `definition_asset_id` version field in the `cargo.toml` file. For example: `1.0.0-DEV` to `1.0.0`. 2. Execute `make build` to compile the implementation asset. 3. Distribute the policy assets as desired. ## See Also - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.9/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Publishing Split-Model Policies to Exchange > For the full documentation index, see: https://docs.mulesoft.com/llms.txt During the custom split-model policy development cycle, you can upload the definition and implementation of your policy to Exchange to create a new Exchange assets to manage the asset versions and to distribute it to other users. For more information about Exchange, see [Anypoint Exchange Overview](https://docs.mulesoft.com/exchange/). For custom policies running in Local Mode, it is not required to publish your policy to Exchange. However, Exchange is a useful version control tool. It is your responsibility to distribute custom policies for Local Mode use. When uploading your policy to Exchange, you can choose to either: - [Publish a Custom Policy](#publish-a-new-split-model-policy) Publish a policy if the policy version is still in development. This enables you to test and edit the policy version. To learn about development assets, see [Publish a Custom Policy](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies#publish). - Release a Custom Policy Release the policy to create a definitive version of the policy. After releasing the policy, you must create a new policy version to edit the policy. To learn about production assets, see [Release a Custom Policy](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies#release). Every time you publish or release a definition and implementation asset, you create a new `stable` version of that asset in Exchange. For more information about `stable` state assets, see [Stable State Assets](https://docs.mulesoft.com/exchange/lifecycle#stablet-state). After you upload your definition and implementation assets to Exchange, see [Applying Custom Policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-apply-policies). ## Before You Begin - Ensure that the Connected App you used to authenticate to the [Anypoint Platform CLI](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites#cli) has the `Exchange Contributor` scope applied. - [Compile your Policy](https://docs.mulesoft.com/pdk/latest/policies-pdk-compile-policies). ## Publish a New Split-Model Policy 1. [Create a definition project](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-project-split#create-a-new-policy-definition-project): 1. Make changes on the `gcl.yaml` 2. Execute `make publish` in the definition project to publish the development definition asset to Exchange. 2. [Create an implementation project](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-project-split#create-a-new-policy-implementation-project): 1. Update the `definition_asset_id` version field in the `cargo.toml` file to `1.0.0-DEV`. 2. Execute `make build-asset-files` in the implementation project. 3. Code your policy logic and test locally. 4. Execute `make publish` to release the development implementation asset to Exchange for testing in lower environments. 5. Validate the policy works as expected. Complete steps C and D until testing is complete. 3. After validating the policy works as expected, release the both assets to Exchange: 1. In the definition project, execute `make release` to release the definition asset to Exchange. 2. In the implementation project, update the `definition_asset_id` version field in the `cargo.toml` file to `1.0.0`. 3. Execute `make release` to release the implementation asset to Exchange. ## Publish a Patch Version Update (Implementation Update) After you have [Published a new split-model policy](#publish-a-new-split-model-policy), you can update the implementation asset for bug fixes or performance updates: 1. Develop the new policy implementation: 1. In the implementation project, update the patch number of version in the `cargo.toml` file. For example: `1.0.1`. 2. Add the `-DEV` suffix to the `definition_asset_id` version field in the `cargo.toml`. For example: `1.0.0-DEV`. 3. Execute `make build-asset-files` in the implementation project. 4. Code your policy logic and test locally. 5. Execute `make publish` to release the development implementation asset to Exchange for testing in lower environments. 6. Validate the policy works as expected. Complete steps D and E until testing is complete. 2. After validating the policy works as expected, release the implementation asset to Exchange: 1. In the implementation project, remove the `-DEV` suffix from the `definition_asset_id` version field in the `cargo.toml` file. For example: `1.0.0-DEV` to `1.0.0`. 2. Execute `make release` to release the implementation asset to Exchange. ## Publish a Minor or Major Version Update (Definition and Implementation Update) After you have [Published a new split-model policy](#publish-a-new-split-model-policy), you can update the definition and implementation assets for updates that require new parameters: 1. Update the definition asset: 1. Update the version in the `exchange.json` file of your definition project to `1.1.0`. 2. Make changes to the `gcl.yaml` file. 3. `make publish` on the definition project to publish the development definition asset to Exchange. 2. Update the implementation asset: 1. In the implementation project, update the minor or major number of version in the `cargo.toml` file. For example: `1.0.0` to `1.1.0`. 2. Update and add the `-DEV` suffix to the `definition_asset_id` version field in the `cargo.toml`. For example: `1.0.0-DEV` to `1.1.0-DEV`. 3. Execute `make build-asset-files` in the implementation project. 4. Code your policy logic and test locally. 5. Execute `make publish` to release the development implementation asset to Exchange for testing in lower environments. 6. Validate the policy works as expected. Complete steps D and E until testing is complete. 3. After validating the policy works as expected, release both assets to Exchange: 1. In the implementation project, remove the `-DEV` suffix from the `definition_asset_id` version field in the `cargo.toml` file. For example: `1.1.0-DEV` to `1.1.0`. 2. Execute `make release` to release the implementation asset to Exchange. ## Develop Split Model Policies Locally Without Publishing to Exchange 1. Develop the policy definition: 1. Ensure the version in the `exchange.json` file is the correct version. For example: `1.0.0` for your first version. 2. Make changes to the `gcl.yaml` file. 3. Execute `make release-local` in the definition project. 2. Develop the policy implementation: 1. Add the `-DEV` suffix to the `definition_asset_id` version field in the `cargo.toml` and ensure it matches the definition asset version used in step one. 2. Execute `make build-asset-files` in the implementation project. 3. Code your policy logic and test locally. 4. Validate the policy works as expected. Complete steps C until testing is complete. 3. If you wish to distribute the policy locally as a production asset: 1. Remove the `-DEV` suffix from the `definition_asset_id` version field in the `cargo.toml` file. For example: `1.0.0-DEV` to `1.0.0`. 2. Execute `make build` to compile the implementation asset. 3. Distribute the policy assets as desired. ## See Also - [Applying Custom Policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/latest/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Publishing Unified-Model Policies to Exchange > For the full documentation index, see: https://docs.mulesoft.com/llms.txt During the custom policy development cycle, you can upload your policy to Exchange to create a new Exchange asset to manage the policy’s version and to distribute it to other users. For more information about Exchange, see [Anypoint Exchange Overview](https://docs.mulesoft.com/exchange/). For custom policies running in Local Mode, it is not required to publish your policy to Exchange. However, Exchange is a useful version control tool. It is your responsibility to distribute custom policies for Local Mode use. When uploading your policy to Exchange, you can choose to either: - [Publish a Custom Policy](#publish) Publish a policy if the policy version is still in development. This enables you to test and edit the policy version. - [Release a Custom Policy](#release) Release the policy to create a definitive version of the policy. After releasing the policy, you must create a new policy version to edit the policy. Every time you publish or release a policy, you create a new `stable` asset in Exchange. For more information about `stable` state assets, see [Stable State Assets](https://docs.mulesoft.com/exchange/lifecycle#stablet-state). After you upload your policy to Exchange, see [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-apply-policies). ## Before You Begin - Ensure that the Connected App you used to authenticate to the [Anypoint Platform CLI](https://docs.mulesoft.com/pdk/1.7/policies-pdk-prerequisites#cli) has the `Exchange Contributor` scope applied. - [Compile your Policy](https://docs.mulesoft.com/pdk/1.7/policies-pdk-compile-policies). ## Publish a Custom Policy To publish a custom policy, run the `make publish` command from the policy’s root folder: ```ssh make publish ``` After publishing the asset, a new asset labeled `DEV` appears in Exchange: ![Policy appears in Exchange labeled DEV.](/mulesoft/current/en-us/pdk/1.7/_images/pdk-dev-asset.png) The asset’s group ID, asset ID, and asset version (GAV) appear, similar to the following: - **groupID**: `` - **assetID**: `my-custom-policy-dev` When publishing a policy, `-dev` appears appended to the **assetID**. - **version**: `1.0.0-20230618115723` When publishing a policy, a timestamp appears appended to the **version**. Rerunning the publish command creates a new version of the policy asset with an updated timestamp. Previously published policy versions are still available. ## Release a Custom Policy To release a custom policy, run the `make release` command from the policy’s root folder: ```ssh make release ``` Released policies are not labeled `DEV`. The asset’s GAV appears similar to the following: - **groupID**: `` - **assetID**: `my-custom-policy` Released policies do not have `-dev` appended to their **assetID**. - **version**: `1.0.0` Released policies do not have a timestamp appended to their **assetID**. After releasing the asset, rerunning the `make release` command results in a conflict error. To begin working on the next version of your policy, update the version number in the `Cargo.toml` file. For example, if the latest version is `1.0.0`, update the `Cargo.toml` file as follows to begin working on a minor release: ```toml name = "my-custom-policy" version = "1.1.0" ``` ## See Also - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.7/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.7/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Publishing Unified-Model Policies to Exchange > For the full documentation index, see: https://docs.mulesoft.com/llms.txt During the custom policy development cycle, you can upload your policy to Exchange to create a new Exchange asset to manage the policy’s version and to distribute it to other users. For more information about Exchange, see [Anypoint Exchange Overview](https://docs.mulesoft.com/exchange/). For custom policies running in Local Mode, it is not required to publish your policy to Exchange. However, Exchange is a useful version control tool. It is your responsibility to distribute custom policies for Local Mode use. When uploading your policy to Exchange, you can choose to either: - [Publish a Custom Policy](#publish) Publish a policy if the policy version is still in development. This enables you to test and edit the policy version. - [Release a Custom Policy](#release) Release the policy to create a definitive version of the policy. After releasing the policy, you must create a new policy version to edit the policy. Every time you publish or release a policy, you create a new `stable` asset in Exchange. For more information about `stable` state assets, see [Stable State Assets](https://docs.mulesoft.com/exchange/lifecycle#stablet-state). After you upload your policy to Exchange, see [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-apply-policies). ## Before You Begin - Ensure that the Connected App you used to authenticate to the [Anypoint Platform CLI](https://docs.mulesoft.com/pdk/1.8/policies-pdk-prerequisites#cli) has the `Exchange Contributor` scope applied. - [Compile your Policy](https://docs.mulesoft.com/pdk/1.8/policies-pdk-compile-policies). ## Publish a Custom Policy To publish a custom policy, run the `make publish` command from the policy’s root folder: ```ssh make publish ``` After publishing the asset, a new asset labeled `DEV` appears in Exchange: ![Policy appears in Exchange labeled DEV.](/mulesoft/current/en-us/pdk/1.8/_images/pdk-dev-asset.png) The asset’s group ID, asset ID, and asset version (GAV) appear, similar to the following: - **groupID**: `` - **assetID**: `my-custom-policy-dev` When publishing a policy, `-dev` appears appended to the **assetID**. - **version**: `1.0.0-20230618115723` When publishing a policy, a timestamp appears appended to the **version**. Rerunning the publish command creates a new version of the policy asset with an updated timestamp. Previously published policy versions are still available. ## Release a Custom Policy To release a custom policy, run the `make release` command from the policy’s root folder: ```ssh make release ``` Released policies are not labeled `DEV`. The asset’s GAV appears similar to the following: - **groupID**: `` - **assetID**: `my-custom-policy` Released policies do not have `-dev` appended to their **assetID**. - **version**: `1.0.0` Released policies do not have a timestamp appended to their **assetID**. After releasing the asset, rerunning the `make release` command results in a conflict error. To begin working on the next version of your policy, update the version number in the `Cargo.toml` file. For example, if the latest version is `1.0.0`, update the `Cargo.toml` file as follows to begin working on a minor release: ```toml name = "my-custom-policy" version = "1.1.0" ``` ## See Also - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.8/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Publishing Unified-Model Policies to Exchange > For the full documentation index, see: https://docs.mulesoft.com/llms.txt During the custom policy development cycle, you can upload your policy to Exchange to create a new Exchange asset to manage the policy’s version and to distribute it to other users. For more information about Exchange, see [Anypoint Exchange Overview](https://docs.mulesoft.com/exchange/). For custom policies running in Local Mode, it is not required to publish your policy to Exchange. However, Exchange is a useful version control tool. It is your responsibility to distribute custom policies for Local Mode use. When uploading your policy to Exchange, you can choose to either: - [Publish a Custom Policy](#publish) Publish a policy if the policy version is still in development. This enables you to test and edit the policy version. - [Release a Custom Policy](#release) Release the policy to create a definitive version of the policy. After releasing the policy, you must create a new policy version to edit the policy. Every time you publish or release a policy, you create a new `stable` asset in Exchange. For more information about `stable` state assets, see [Stable State Assets](https://docs.mulesoft.com/exchange/lifecycle#stablet-state). After you upload your policy to Exchange, see [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-apply-policies). ## Before You Begin - Ensure that the Connected App you used to authenticate to the [Anypoint Platform CLI](https://docs.mulesoft.com/pdk/1.9/policies-pdk-prerequisites#cli) has the `Exchange Contributor` scope applied. - [Compile your Policy](https://docs.mulesoft.com/pdk/1.9/policies-pdk-compile-policies). ## Publish a Custom Policy To publish a custom policy, run the `make publish` command from the policy’s root folder: ```ssh make publish ``` After publishing the asset, a new asset labeled `DEV` appears in Exchange: ![Policy appears in Exchange labeled DEV.](/mulesoft/current/en-us/pdk/1.9/_images/pdk-dev-asset.png) The asset’s group ID, asset ID, and asset version (GAV) appear, similar to the following: - **groupID**: `` - **assetID**: `my-custom-policy-dev` When publishing a policy, `-dev` appears appended to the **assetID**. - **version**: `1.0.0-20230618115723` When publishing a policy, a timestamp appears appended to the **version**. Rerunning the publish command creates a new version of the policy asset with an updated timestamp. Previously published policy versions are still available. ## Release a Custom Policy To release a custom policy, run the `make release` command from the policy’s root folder: ```ssh make release ``` Released policies are not labeled `DEV`. The asset’s GAV appears similar to the following: - **groupID**: `` - **assetID**: `my-custom-policy` Released policies do not have `-dev` appended to their **assetID**. - **version**: `1.0.0` Released policies do not have a timestamp appended to their **assetID**. After releasing the asset, rerunning the `make release` command results in a conflict error. To begin working on the next version of your policy, update the version number in the `Cargo.toml` file. For example, if the latest version is `1.0.0`, update the `Cargo.toml` file as follows to begin working on a minor release: ```toml name = "my-custom-policy" version = "1.1.0" ``` ## See Also - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.9/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Publishing Unified-Model Policies to Exchange > For the full documentation index, see: https://docs.mulesoft.com/llms.txt During the custom policy development cycle, you can upload your policy to Exchange to create a new Exchange asset to manage the policy’s version and to distribute it to other users. For more information about Exchange, see [Anypoint Exchange Overview](https://docs.mulesoft.com/exchange/). For custom policies running in Local Mode, it is not required to publish your policy to Exchange. However, Exchange is a useful version control tool. It is your responsibility to distribute custom policies for Local Mode use. When uploading your policy to Exchange, you can choose to either: - [Publish a Custom Policy](#publish) Publish a policy if the policy version is still in development. This enables you to test and edit the policy version. - [Release a Custom Policy](#release) Release the policy to create a definitive version of the policy. After releasing the policy, you must create a new policy version to edit the policy. Every time you publish or release a policy, you create a new `stable` asset in Exchange. For more information about `stable` state assets, see [Stable State Assets](https://docs.mulesoft.com/exchange/lifecycle#stablet-state). After you upload your policy to Exchange, see [Applying Custom Policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-apply-policies). ## Before You Begin - Ensure that the Connected App you used to authenticate to the [Anypoint Platform CLI](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites#cli) has the `Exchange Contributor` scope applied. - [Compile your Policy](https://docs.mulesoft.com/pdk/latest/policies-pdk-compile-policies). ## Publish a Custom Policy To publish a custom policy, run the `make publish` command from the policy’s root folder: ```ssh make publish ``` After publishing the asset, a new asset labeled `DEV` appears in Exchange: ![Policy appears in Exchange labeled DEV.](/mulesoft/current/en-us/pdk/latest/_images/pdk-dev-asset.png) The asset’s group ID, asset ID, and asset version (GAV) appear, similar to the following: - **groupID**: `` - **assetID**: `my-custom-policy-dev` When publishing a policy, `-dev` appears appended to the **assetID**. - **version**: `1.0.0-20230618115723` When publishing a policy, a timestamp appears appended to the **version**. Rerunning the publish command creates a new version of the policy asset with an updated timestamp. Previously published policy versions are still available. ## Skip Republishing an Unchanged Definition Running `make publish` or `make release` uploads a new policy definition and policy implementation to Exchange. If the policy definition is unchanged from the published version, PDK skips republishing the definition and reuses the existing one. The publication step reports this message if the definition is skipped: ```text Definition unchanged from published version x.y.z. Skipping definition publish and reusing it. ``` > [!NOTE] This feature is only applicable to policies created with PDK 1.10.0 or later, not policies > created with an earlier version that were updated. When the definition is reused, you only need to update the policy implementation. See [Upgrade a Policy Implementation](https://docs.mulesoft.com/gateway/latest/gateway-secure-conn#upgrade-policy-implementation). To always publish a new definition, set the `SKIP_UNCHANGED_DEFINITION` flag to `false` in the Makefile: ```makefile SKIP_UNCHANGED_DEFINITION ?= false ``` ## Release a Custom Policy To release a custom policy, run the `make release` command from the policy’s root folder: ```ssh make release ``` Released policies are not labeled `DEV`. The asset’s GAV appears similar to the following: - **groupID**: `` - **assetID**: `my-custom-policy` Released policies do not have `-dev` appended to their **assetID**. - **version**: `1.0.0` Released policies do not have a timestamp appended to their **assetID**. After releasing the asset, rerunning the `make release` command results in a conflict error. To begin working on the next version of your policy, update the version number in the `Cargo.toml` file. For example, if the latest version is `1.0.0`, update the `Cargo.toml` file as follows to begin working on a minor release: ```toml name = "my-custom-policy" version = "1.1.0" ``` ## See Also - [Applying Custom Policies](https://docs.mulesoft.com/pdk/latest/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/latest/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Rate Limiting Requests > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides rate limiting functionality to control request rates. Custom policies support both single Flex Replica and multi-replica deployments. For multi-replica deployments, you must configure shared storage. To configure shared storage, see: - [Configuring Redis Shared Storage for Omni Gateway in Connected Mode](https://docs.mulesoft.com/gateway/latest/conn-shared-storage-config) - [Configuring Redis Shared Storage for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-shared-storage-config) ## Inject the `RateLimitBuilder` To enable rate limiting functionality, you must inject the `RateLimitBuilder` in your custom policy’s entrypoint and configure it for either local (single-replica) or clustered (multi-replica) mode: ```Rust // buckets example configuration let buckets = vec![ ("api", vec![Tier { requests: 100, period_in_millis: 60000 }]), // 100 requests per minute ("user", vec![Tier { requests: 10, period_in_millis: 30000 }]), // 10 requests per 30 seconds ]; // timer example let timer = clock.period(Duration::from_millis(100)); // 100ms intervals for rate limit sync // for local mode (single-instance) let builder = rate_limit_builder .new(builder_id); let rate_limiter = builder.buckets(buckets).build()?; // for clustered mode with shared storage (multi-instance) let builder = rate_limit_builder .new(builder_id) .clustered(Rc::new(timer)) .shared(); let rate_limiter = builder.buckets(buckets).build()?; ``` The `RateLimitBuilder` struct provides the following methods to configure the rate limits: - `builder_id`: a string identifier for the rate limiter instance (required) - `buckets`: rate limit tiers configuration with requests and time windows (optional - defaults to api instance configuration if unspecified) - `timer`: a periodic timer for rate limit sync (required for clustered mode) - `clustered`: Enables the rate limiter to use distributed storage backends. Without it, the rate limiter uses in-memory storage. - `shared`: Enables the rate limiter to share state across different policy instances. ## Check Requests Against Rate Limits After creating the rate limiter instance, use the `is_allowed` method to check if requests are allowed with support for multiple independent rate limit configurations: ```Rust // Check if request is allowed for a specific group and client key match rate_limiter.is_allowed(group, &client_key, request_amount).await { Ok(RateLimitResult::Allowed(_)) => Flow::Continue(()), Ok(RateLimitResult::TooManyRequests(_)) => Flow::Break(Response::new(429)), Err(e) => Flow::Break(Response::new(503)), } ``` ## Rate Limiting Configuration Examples PDK provides the [Multi-Instance Rate Limiting Example policy](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.5.0/multi-instance-rate-limiting) to demonstrate how to configure rate limiting in Rust code. Within the example policy, see these functions for further configuration details: - [`entrypoint` function](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/multi-instance-rate-limiting/src/lib.rs) for how to configure the `RateLimitBuilder`. - [`request_filter` function](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/multi-instance-rate-limiting/src/lib.rs) for how the policy applies rate limits to incoming requests. ## Redis Shared Storage Configuration Example For an example of how to configure Redis shared storage for testing, see the example [`playground/config/shared-storage-redis.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/multi-instance-rate-limiting/playground/config/shared-storage-redis.yaml) and [`playground/docker-compose.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/multi-instance-rate-limiting/playground/docker-compose.yaml) files. ## See Also - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-timer) - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-share-data) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Rate Limiting Requests > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides rate limiting functionality to control request rates. Custom policies support both single Flex Replica and multi-replica deployments. For multi-replica deployments, you must configure shared storage. To configure shared storage, see: - [Configuring Redis Shared Storage for Omni Gateway in Connected Mode](https://docs.mulesoft.com/gateway/latest/conn-shared-storage-config) - [Configuring Redis Shared Storage for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-shared-storage-config) ## Inject the `RateLimitBuilder` To enable rate limiting functionality, you must inject the `RateLimitBuilder` in your custom policy’s entrypoint and configure it for either local (single-replica) or clustered (multi-replica) mode: ```Rust // buckets example configuration let buckets = vec![ ("api", vec![Tier { requests: 100, period_in_millis: 60000 }]), // 100 requests per minute ("user", vec![Tier { requests: 10, period_in_millis: 30000 }]), // 10 requests per 30 seconds ]; // timer example let timer = clock.period(Duration::from_millis(100)); // 100ms intervals for rate limit sync // for local mode (single-instance) let builder = rate_limit_builder .new(builder_id); let rate_limiter = builder.buckets(buckets).build()?; // for clustered mode with shared storage (multi-instance) let builder = rate_limit_builder .new(builder_id) .clustered(Rc::new(timer)) .shared(); let rate_limiter = builder.buckets(buckets).build()?; ``` The `RateLimitBuilder` struct provides the following methods to configure the rate limits: - `builder_id`: a string identifier for the rate limiter instance (required) - `buckets`: rate limit tiers configuration with requests and time windows (optional - defaults to api instance configuration if unspecified) - `timer`: a periodic timer for rate limit sync (required for clustered mode) - `clustered`: Enables the rate limiter to use distributed storage backends. Without it, the rate limiter uses in-memory storage. - `shared`: Enables the rate limiter to share state across different policy instances. ## Check Requests Against Rate Limits After creating the rate limiter instance, use the `is_allowed` method to check if requests are allowed with support for multiple independent rate limit configurations: ```Rust // Check if request is allowed for a specific group and client key match rate_limiter.is_allowed(group, &client_key, request_amount).await { Ok(RateLimitResult::Allowed(_)) => Flow::Continue(()), Ok(RateLimitResult::TooManyRequests(_)) => Flow::Break(Response::new(429)), Err(e) => Flow::Break(Response::new(503)), } ``` ## Rate Limiting Configuration Examples PDK provides the [Multi-Instance Rate Limiting Example policy](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.6.0/multi-instance-rate-limiting) to demonstrate how to configure rate limiting in Rust code. Within the example policy, see these functions for further configuration details: - [`entrypoint` function](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/multi-instance-rate-limiting/src/lib.rs) for how to configure the `RateLimitBuilder`. - [`request_filter` function](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/multi-instance-rate-limiting/src/lib.rs) for how the policy applies rate limits to incoming requests. ## Redis Shared Storage Configuration Example For an example of how to configure Redis shared storage for testing, see the example [`playground/config/shared-storage-redis.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/multi-instance-rate-limiting/playground/config/shared-storage-redis.yaml) and [`playground/docker-compose.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/multi-instance-rate-limiting/playground/docker-compose.yaml) files. ## See Also - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-timer) - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-share-data) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Rate Limiting Requests > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides rate limiting functionality to control request rates. Custom policies support both single Flex Replica and multi-replica deployments. For multi-replica deployments, you must configure shared storage. To configure shared storage, see: - [Configuring Redis Shared Storage for Omni Gateway in Connected Mode](https://docs.mulesoft.com/gateway/latest/conn-shared-storage-config) - [Configuring Redis Shared Storage for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-shared-storage-config) ## Inject the `RateLimitBuilder` To enable rate limiting functionality, you must inject the `RateLimitBuilder` in your custom policy’s entrypoint and configure it for either local (single-replica) or clustered (multi-replica) mode: ```Rust // buckets example configuration let buckets = vec![ ("api", vec![Tier { requests: 100, period_in_millis: 60000 }]), // 100 requests per minute ("user", vec![Tier { requests: 10, period_in_millis: 30000 }]), // 10 requests per 30 seconds ]; // timer example let timer = clock.period(Duration::from_millis(100)); // 100ms intervals for rate limit sync // for local mode (single-instance) let builder = rate_limit_builder .new(builder_id); let rate_limiter = builder.buckets(buckets).build()?; // for clustered mode with shared storage (multi-instance) let builder = rate_limit_builder .new(builder_id) .clustered(Rc::new(timer)) .shared(); let rate_limiter = builder.buckets(buckets).build()?; ``` The `RateLimitBuilder` struct provides the following methods to configure the rate limits: - `builder_id`: a string identifier for the rate limiter instance (required) - `buckets`: rate limit tiers configuration with requests and time windows (optional - defaults to api instance configuration if unspecified) - `timer`: a periodic timer for rate limit sync (required for clustered mode) - `clustered`: Enables the rate limiter to use distributed storage backends. Without it, the rate limiter uses in-memory storage. - `shared`: Enables the rate limiter to share state across different policy instances. ## Check Requests Against Rate Limits After creating the rate limiter instance, use the `is_allowed` method to check if requests are allowed with support for multiple independent rate limit configurations: ```Rust // Check if request is allowed for a specific group and client key match rate_limiter.is_allowed(group, &client_key, request_amount).await { Ok(RateLimitResult::Allowed(_)) => Flow::Continue(()), Ok(RateLimitResult::TooManyRequests(_)) => Flow::Break(Response::new(429)), Err(e) => Flow::Break(Response::new(503)), } ``` ## Rate Limiting Configuration Examples PDK provides the [Multi-Instance Rate Limiting Example policy](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.6.0/multi-instance-rate-limiting) to demonstrate how to configure rate limiting in Rust code. Within the example policy, see these functions for further configuration details: - [`entrypoint` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.6.0/multi-instance-rate-limiting/src/lib.rs#L118) for how to configure the `RateLimitBuilder`. - [`request_filter` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.6.0/multi-instance-rate-limiting/src/lib.rs#L54) for how the policy applies rate limits to incoming requests. ## Redis Shared Storage Configuration Example For an example of how to configure Redis shared storage for testing, see the example [`playground/config/shared-storage-redis.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/multi-instance-rate-limiting/playground/config/shared-storage-redis.yaml) and [`playground/docker-compose.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/multi-instance-rate-limiting/playground/docker-compose.yaml) files. ## See Also - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-timer) - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-share-data) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Rate Limiting Requests > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) provides rate limiting functionality to control request rates. Custom policies support both single Omni Replica and multi-replica deployments. For multi-replica deployments, you must configure shared storage. To configure shared storage, see: - [Configuring Redis Shared Storage for Omni Gateway in Connected Mode](https://docs.mulesoft.com/gateway/latest/conn-shared-storage-config) - [Configuring Redis Shared Storage for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-shared-storage-config) ## Inject the `RateLimitBuilder` To enable rate limiting functionality, you must inject the `RateLimitBuilder` in your custom policy’s entrypoint and configure it for either local (single-replica) or clustered (multi-replica) mode: ```Rust // buckets example configuration let buckets = vec![ ("api", vec![Tier { requests: 100, period_in_millis: 60000 }]), // 100 requests per minute ("user", vec![Tier { requests: 10, period_in_millis: 30000 }]), // 10 requests per 30 seconds ]; // timer example let timer = clock.period(Duration::from_millis(100)); // 100ms intervals for rate limit sync // for local mode (single-instance) let builder = rate_limit_builder .new(builder_id); let rate_limiter = builder.buckets(buckets).build()?; // for clustered mode with shared storage (multi-instance) let builder = rate_limit_builder .new(builder_id) .clustered(Rc::new(timer)) .shared(); let rate_limiter = builder.buckets(buckets).build()?; ``` The `RateLimitBuilder` struct provides the following methods to configure the rate limits: - `builder_id`: a string identifier for the rate limiter instance (required) - `buckets`: rate limit tiers configuration with requests and time windows (optional - defaults to api instance configuration if unspecified) - `timer`: a periodic timer for rate limit sync (required for clustered mode) - `clustered`: Enables the rate limiter to use distributed storage backends. Without it, the rate limiter uses in-memory storage. - `shared`: Enables the rate limiter to share state across different policy instances. ## Check Requests Against Rate Limits After creating the rate limiter instance, use the `is_allowed` method to check if requests are allowed with support for multiple independent rate limit configurations: ```Rust // Check if request is allowed for a specific group and client key match rate_limiter.is_allowed(group, &client_key, request_amount).await { Ok(RateLimitResult::Allowed(_)) => Flow::Continue(()), Ok(RateLimitResult::TooManyRequests(_)) => Flow::Break(Response::new(429)), Err(e) => Flow::Break(Response::new(503)), } ``` ## Rate Limiting Configuration Examples PDK provides the [Multi-Instance Rate Limiting Example policy](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.8.0/multi-instance-rate-limiting) to demonstrate how to configure rate limiting in Rust code. Within the example policy, see these functions for further configuration details: - [`entrypoint` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.8.0/multi-instance-rate-limiting/src/lib.rs#L118) for how to configure the `RateLimitBuilder`. - [`request_filter` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.8.0/multi-instance-rate-limiting/src/lib.rs#L54) for how the policy applies rate limits to incoming requests. ## Redis Shared Storage Configuration Example For an example of how to configure Redis shared storage for testing, see the example [`playground/config/shared-storage-redis.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/multi-instance-rate-limiting/playground/config/shared-storage-redis.yaml) and [`playground/docker-compose.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/multi-instance-rate-limiting/playground/docker-compose.yaml) files. ## See Also - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-timer) - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-share-data) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Rate Limiting Requests > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) provides rate limiting functionality to control request rates. Custom policies support both single Omni Replica and multi-replica deployments. For multi-replica deployments, you must configure shared storage. To configure shared storage, see: - [Configuring Redis Shared Storage for Omni Gateway in Connected Mode](https://docs.mulesoft.com/gateway/latest/conn-shared-storage-config) - [Configuring Redis Shared Storage for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-shared-storage-config) ## Inject the `RateLimitBuilder` To enable rate limiting functionality, you must inject the `RateLimitBuilder` in your custom policy’s entrypoint and configure it for either local (single-replica) or clustered (multi-replica) mode: ```Rust // buckets example configuration let buckets = vec![ ("api", vec![Tier { requests: 100, period_in_millis: 60000 }]), // 100 requests per minute ("user", vec![Tier { requests: 10, period_in_millis: 30000 }]), // 10 requests per 30 seconds ]; // timer example let timer = clock.period(Duration::from_millis(100)); // 100ms intervals for rate limit sync // for local mode (single-instance) let builder = rate_limit_builder .new(builder_id); let rate_limiter = builder.buckets(buckets).build()?; // for clustered mode with shared storage (multi-instance) let builder = rate_limit_builder .new(builder_id) .clustered(Rc::new(timer)) .shared(); let rate_limiter = builder.buckets(buckets).build()?; ``` The `RateLimitBuilder` struct provides the following methods to configure the rate limits: - `builder_id`: a string identifier for the rate limiter instance (required) - `buckets`: rate limit tiers configuration with requests and time windows (optional - defaults to api instance configuration if unspecified) - `timer`: a periodic timer for rate limit sync (required for clustered mode) - `clustered`: Enables the rate limiter to use distributed storage backends. Without it, the rate limiter uses in-memory storage. - `shared`: Enables the rate limiter to share state across different policy instances. ## Check Requests Against Rate Limits After creating the rate limiter instance, use the `is_allowed` method to check if requests are allowed with support for multiple independent rate limit configurations: ```Rust // Check if request is allowed for a specific group and client key match rate_limiter.is_allowed(group, &client_key, request_amount).await { Ok(RateLimitResult::Allowed(_)) => Flow::Continue(()), Ok(RateLimitResult::TooManyRequests(_)) => Flow::Break(Response::new(429)), Err(e) => Flow::Break(Response::new(503)), } ``` ## Rate Limiting Configuration Examples PDK provides the [Multi-Instance Rate Limiting Example policy](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.9.0/multi-instance-rate-limiting) to demonstrate how to configure rate limiting in Rust code. Within the example policy, see these functions for further configuration details: - [`entrypoint` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.9.0/multi-instance-rate-limiting/src/lib.rs#L118) for how to configure the `RateLimitBuilder`. - [`request_filter` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.9.0/multi-instance-rate-limiting/src/lib.rs#L54) for how the policy applies rate limits to incoming requests. ## Redis Shared Storage Configuration Example For an example of how to configure Redis shared storage for testing, see the example [`playground/config/shared-storage-redis.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/multi-instance-rate-limiting/playground/config/shared-storage-redis.yaml) and [`playground/docker-compose.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/multi-instance-rate-limiting/playground/docker-compose.yaml) files. ## See Also - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-timer) - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-share-data) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Rate Limiting Requests > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) provides rate limiting functionality to control request rates. Custom policies support both single Omni Replica and multi-replica deployments. For multi-replica deployments, you must configure shared storage. To configure shared storage, see: - [Configuring Redis Shared Storage for Omni Gateway in Connected Mode](https://docs.mulesoft.com/gateway/latest/conn-shared-storage-config) - [Configuring Redis Shared Storage for Omni Gateway in Local Mode](https://docs.mulesoft.com/gateway/latest/local-shared-storage-config) ## Inject the `RateLimitBuilder` To enable rate limiting functionality, you must inject the `RateLimitBuilder` in your custom policy’s entrypoint and configure it for either local (single-replica) or clustered (multi-replica) mode: ```Rust // buckets example configuration let buckets = vec![ ("api", vec![Tier { requests: 100, period_in_millis: 60000 }]), // 100 requests per minute ("user", vec![Tier { requests: 10, period_in_millis: 30000 }]), // 10 requests per 30 seconds ]; // timer example let timer = clock.period(Duration::from_millis(100)); // 100ms intervals for rate limit sync // for local mode (single-instance) let builder = rate_limit_builder .new(builder_id); let rate_limiter = builder.buckets(buckets).build()?; // for clustered mode with shared storage (multi-instance) let builder = rate_limit_builder .new(builder_id) .clustered(Rc::new(timer)) .shared(); let rate_limiter = builder.buckets(buckets).build()?; ``` The `RateLimitBuilder` struct provides the following methods to configure the rate limits: - `builder_id`: a string identifier for the rate limiter instance (required) - `buckets`: rate limit tiers configuration with requests and time windows (optional - defaults to api instance configuration if unspecified) - `timer`: a periodic timer for rate limit sync (required for clustered mode) - `clustered`: Enables the rate limiter to use distributed storage backends. Without it, the rate limiter uses in-memory storage. - `shared`: Enables the rate limiter to share state across different policy instances. ## Check Requests Against Rate Limits After creating the rate limiter instance, use the `is_allowed` method to check if requests are allowed with support for multiple independent rate limit configurations: ```Rust // Check if request is allowed for a specific group and client key match rate_limiter.is_allowed(group, &client_key, request_amount).await { Ok(RateLimitResult::Allowed(_)) => Flow::Continue(()), Ok(RateLimitResult::TooManyRequests(_)) => Flow::Break(Response::new(429)), Err(e) => Flow::Break(Response::new(503)), } ``` ## Rate Limiting Configuration Examples PDK provides the [Multi-Instance Rate Limiting Example policy](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.10.0/multi-instance-rate-limiting) to demonstrate how to configure rate limiting in Rust code. Within the example policy, see these functions for further configuration details: - [`entrypoint` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.10.0/multi-instance-rate-limiting/src/lib.rs#L118) for how to configure the `RateLimitBuilder`. - [`request_filter` function](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.10.0/multi-instance-rate-limiting/src/lib.rs#L54) for how the policy applies rate limits to incoming requests. ## Redis Shared Storage Configuration Example For an example of how to configure Redis shared storage for testing, see the example [`playground/config/shared-storage-redis.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/multi-instance-rate-limiting/playground/config/shared-storage-redis.yaml) and [`playground/docker-compose.yaml`](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/multi-instance-rate-limiting/playground/docker-compose.yaml) files. ## See Also - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-timer) - [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-share-data) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Reading and Writing Request Headers and Bodies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt With Flex Gateway Policy Development Kit (PDK), you can read and write to request and response headers and bodies. ## Event Flow When filtering requests and responses, Proxy Wasm splits handling the headers and body into two main events that must happen in a specific order. Before the policy can handle the body, the header event has to fully propagate through all policies. For example, the event flow for an API with two policies applied is: 1. Policy 1 handles the request header event. 2. Policy 2 handles the request header event. 3. The backend service receives the request headers. 4. Policy 1 handles the request body event. 5. Policy 2 handles the request body event. 6. The backend receives the request body. 7. The backend sends the response. 8. Policy 2 handles the response header event. 9. Policy 1 handles the response header event. 10. The client receives the response headers. 11. Policy 2 handles the response body event. 12. Policy 1 handles the response body event. 13. The client receives the response body. This order creates the following limitations: - Policies can’t modify headers after reading the body. - All policies must fully process the header event before reading the body. Saving data of the body on one policy and then modifying the headers using that body data in a different policy isn’t possible. - When all policies process the header event, it reaches the backend service. To ensure no data from a rejected request reaches the backend service, you must reject the headers based on only the request headers. When rejecting requests based on their body, most servers and clients can detect interrupted requests and discard the headers of the request. In the policy source code, reading the body separates the header and body event. For example, if the declaration `let body_state = headers_state.into_body_state().await;` is used to read the body, everything prior to the declaration occurs in the header event, and everything after occurs in the body event. ## Read and Write Request Headers To access the headers in both the request and the response, transform the `RequestState` or `ResponseState` to a header state by calling the method `into_headers_state()` and awaiting it. After calling the method, access and manipulate the headers by calling the functions of the `HeadersHandler` trait. ```Rust pub trait HeadersHandler { fn headers(&self) -> Vec<(String, String)>; fn header(&self, name: &str) -> Option; fn add_header(&self, name: &str, value: &str); fn set_header(&self, name: &str, value: &str); fn set_headers(&self, headers: Vec<(&str, &str)>); fn remove_header(&self, name: &str); } ``` You can access headers in `on_request` or `on_response` wrapped functions by implementing the following code: ```Rust async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let headers_handler = headers_state.handler(); let old_value = headers_handler.header("request-header").unwrap_or_default(); let new_value = "--replaced--"; logger::info!("Old request header value: {old_value}, New value: {new_value}"); headers_handler.set_header("request-header", new_value); } async fn response_filter(response_state: ResponseState, _config: &Config) { let headers_state = response_state.into_headers_state().await; let headers_handler = headers_state.handler(); let old_headers = headers_handler.header("request-header").unwrap_or_default(); let new_headers = vec![("response-header1", "--replaced--"), ("response-header2", "--replaced--")]; logger::info!("Old request header value: {old_headers:?}, New value: {new_headers:?}"); headers_handler.set_headers(new_headers); } ``` Envoy handles the method, scheme, path, authority, and status codes as headers. PDK provides the following methods to access and modify the request’s `:method`, `:scheme`, `:path`, `:authority`, and `:status` Envoy headers: ```Rust async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let method = headers_state.method(); let scheme = headers_state.scheme(); let authority = headers_state.authority(); let path = headers_state.path(); ... } async fn response_filter(response_state: ResponseState, _config: &Config) { let headers_state = response_state.into_headers_state().await; let status = headers_state.status_code(); } ``` ## Read and Write Request Bodies > [!NOTE] Reading and writing bodies is limited to payloads of size 1MB or smaller. To access the body in both the request and the response, transform the `RequestState` or `ResponseState` to a body state by calling the method `into_body_state()` and awaiting it: ```Rust let body_state = request_state.into_body_state().await; ``` > [!NOTE] The previous `.await` introduces a cancellation point. During a request, a > [Flow Cancellation](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features#flow-cancellation) might cause the `.await` to > never resume. If the original state was already transformed into a header state, transform the state into a body state by calling the same function, for example: ```Rust let headers_state = request_state.into_headers_state().await; let body_state = headers_state.into_body_state().await; ``` After calling `into_body_state()`, access and manipulate the headers by calling the functions of the `BodyHandler` trait. ```Rust pub trait BodyHandler { fn body(&self) -> Vec; fn set_body(&self, body: &[u8]) -> Result<(), BodyError>; } ``` Because Envoy uses the same buffer to share data from the headers and the body, the policy cannot access the headers and the body at the same time. If the policy must read both: 1. Read the headers and save the necessary values in a variable. 2. Read the body. You can read the headers and then the body in both the response and request. However, you cannot modify headers after reading the body. Complete all header modification before reading the body, for example: ```Rust async fn request_filter(request_state: RequestState) { let headers_state = request_state.into_headers_state().await; let headers_handler = headers_state.handler(); let agent = headers_handler.header("User-Agent").unwrap_or_else(|| "Undefined".to_string()); // Removing old content length header before manipulating body headers_handler.remove_header("content-length"); let body_state = headers_state.into_body_state().await; let body_handler = body_state.handler(); let body = body_handler.body(); logger::info!("User: {agent} sent: {}", String::from_utf8_lossy(body.as_slice())); let new_body = "new body".as_bytes(); match body_handler.set_body(&new_body) { Ok(_) => logger::info!("Body updated"), Err(e) => logger::info!("Unable to set body. Reason: {e:?}), } } ``` > [!NOTE] This code removes the `content-length` header. This is required to modify the body. `BodyHandler::set_body()` method returns a `Result<(), BodyError>` object. Body updating might fail due to: - `BodyError::BodyNotSent`: The current HTTP Flow doesn’t have a body (for example, `GET` request). - `BodyError::ExceededBodySize`: The new body exceeds the maximum body buffer size supported by Envoy. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Reading and Writing Request Headers and Bodies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt With Flex Gateway Policy Development Kit (PDK), you can read and write to request and response headers and bodies. ## Event Flow When filtering requests and responses, Proxy Wasm splits handling the headers and body into two main events that must happen in a specific order. Before the policy can handle the body, the header event has to fully propagate through all policies. For example, the event flow for an API with two policies applied is: 1. Policy 1 handles the request header event. 2. Policy 2 handles the request header event. 3. The backend service receives the request headers. 4. Policy 1 handles the request body event. 5. Policy 2 handles the request body event. 6. The backend receives the request body. 7. The backend sends the response. 8. Policy 2 handles the response header event. 9. Policy 1 handles the response header event. 10. The client receives the response headers. 11. Policy 2 handles the response body event. 12. Policy 1 handles the response body event. 13. The client receives the response body. This order creates the following limitations: - Policies can’t modify headers after reading the body. - All policies must fully process the header event before reading the body. Saving data of the body on one policy and then modifying the headers using that body data in a different policy isn’t possible. - When all policies process the header event, it reaches the backend service. To ensure no data from a rejected request reaches the backend service, you must reject the headers based on only the request headers. When rejecting requests based on their body, most servers and clients can detect interrupted requests and discard the headers of the request. In the policy source code, reading the body separates the header and body event. For example, if the declaration `let body_state = headers_state.into_body_state().await;` is used to read the body, everything prior to the declaration occurs in the header event, and everything after occurs in the body event. ## Read and Write Request Headers To access the headers in both the request and the response, transform the `RequestState` or `ResponseState` to a header state by calling the method `into_headers_state()` and awaiting it. After calling the method, access and manipulate the headers by calling the functions of the `HeadersHandler` trait. ```Rust pub trait HeadersHandler { fn headers(&self) -> Vec<(String, String)>; fn header(&self, name: &str) -> Option; fn add_header(&self, name: &str, value: &str); fn set_header(&self, name: &str, value: &str); fn set_headers(&self, headers: Vec<(&str, &str)>); fn remove_header(&self, name: &str); } ``` You can access headers in `on_request` or `on_response` wrapped functions by implementing the following code: ```Rust async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let headers_handler = headers_state.handler(); let old_value = headers_handler.header("request-header").unwrap_or_default(); let new_value = "--replaced--"; logger::info!("Old request header value: {old_value}, New value: {new_value}"); headers_handler.set_header("request-header", new_value); } async fn response_filter(response_state: ResponseState, _config: &Config) { let headers_state = response_state.into_headers_state().await; let headers_handler = headers_state.handler(); let old_headers = headers_handler.header("request-header").unwrap_or_default(); let new_value = vec![("response-header1", "--replaced--"), ("response-header2", "--replaced--")]; logger::info!("Old request header value: {old_headers:?}, New value: {new_value:?}"); headers_handler.set_headers(new_value); } ``` Envoy handles the method, scheme, path, authority, and status codes as headers. PDK provides the following methods to access and modify the request’s `:method`, `:scheme`, `:path`, `:authority`, and `:status` Envoy headers: ```Rust async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let method = headers_state.method(); let scheme = headers_state.scheme(); let authority = headers_state.authority(); let path = headers_state.path(); ... } async fn response_filter(response_state: ResponseState, _config: &Config) { let headers_state = response_state.into_headers_state().await; let status = headers_state.status_code(); } ``` ## Read and Write Request Bodies > [!NOTE] Reading and writing bodies is limited to payloads of size 1MB or smaller. To access the body in both the request and the response, transform the `RequestState` or `ResponseState` to a body state by calling the method `into_body_state()` and awaiting it: ```Rust let body_state = request_state.into_body_state().await; ``` > [!NOTE] The previous `.await` introduces a cancellation point. During a request, a > [Flow Cancellation](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features#flow-cancellation) might cause the `.await` to > never resume. If the original state was already transformed into a header state, transform the state into a body state by calling the same function, for example: ```Rust let headers_state = request_state.into_headers_state().await; let body_state = headers_state.into_body_state().await; ``` After calling `into_body_state()`, access and manipulate the headers by calling the functions of the `BodyHandler` trait. ```Rust pub trait BodyHandler { fn body(&self) -> Vec; fn set_body(&self, body: &[u8]) -> Result<(), BodyError>; } ``` Because Envoy uses the same buffer to share data from the headers and the body, the policy cannot access the headers and the body at the same time. If the policy must read both: 1. Read the headers and save the necessary values in a variable. 2. Read the body. You can read the headers and then the body in both the response and request. However, you cannot modify headers after reading the body. Complete all header modification before reading the body, for example: ```Rust async fn request_filter(request_state: RequestState) { let headers_state = request_state.into_headers_state().await; let headers_handler = headers_state.handler(); let agent = headers_handler.header("User-Agent").unwrap_or_else(|| "Undefined".to_string()); // Removing old content length header before manipulating body headers_handler.remove_header("content-length"); let body_state = headers_state.into_body_state().await; let body_handler = body_state.handler(); let body = body_handler.body(); logger::info!("User: {agent} sent: {}", String::from_utf8_lossy(body.as_slice())); let new_body = "new body".as_bytes(); match body_handler.set_body(&new_body) { Ok(_) => logger::info!("Body updated"), Err(e) => logger::info!("Unable to set body. Reason: {e:?}), } } ``` > [!NOTE] This code removes the `content-length` header. This is required to modify the body. `BodyHandler::set_body()` method returns a `Result<(), BodyError>` object. Body updating might fail due to: - `BodyError::BodyNotSent`: The current HTTP Flow doesn’t have a body (for example, `GET` request). - `BodyError::ExceededBodySize`: The new body exceeds the maximum body buffer size supported by Envoy. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Reading and Writing Request Headers and Bodies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt With Flex Gateway Policy Development Kit (PDK), you can read and write to request and response headers and bodies and read from a streamed body. ## Event Flow When filtering requests and responses, Proxy Wasm splits handling the headers and body into two main events that must happen in a specific order. Before the policy can handle the body, the header event has to fully propagate through all policies. For example, the event flow for an API with two policies applied is: 1. Policy 1 handles the request header event. 2. Policy 2 handles the request header event. 3. The backend service receives the request headers. 4. Policy 1 handles the request body event. 5. Policy 2 handles the request body event. 6. The backend receives the request body. 7. The backend sends the response. 8. Policy 2 handles the response header event. 9. Policy 1 handles the response header event. 10. The client receives the response headers. 11. Policy 2 handles the response body event. 12. Policy 1 handles the response body event. 13. The client receives the response body. This order creates the following limitations: - Policies can’t modify headers after reading the body. - All policies must fully process the header event before reading the body. Saving data of the body on one policy and then modifying the headers using that body data in a different policy isn’t possible. - When all policies process the header event, it reaches the backend service. To ensure no data from a rejected request reaches the backend service, you must reject the headers based on only the request headers. When rejecting requests based on their body, most servers and clients can detect interrupted requests and discard the headers of the request. In the policy source code, reading the body separates the header and body event. For example, if the declaration `let body_state = headers_state.into_body_state().await;` is used to read the body, everything prior to the declaration occurs in the header event, and everything after occurs in the body event. ## Read and Write Request Headers To access the headers in both the request and the response, transform the `RequestState` or `ResponseState` to a header state by calling the method `into_headers_state()` and awaiting it. After calling the method, access and manipulate the headers by calling the functions of the `HeadersHandler` trait. ```Rust pub trait HeadersHandler { fn headers(&self) -> Vec<(String, String)>; fn header(&self, name: &str) -> Option; fn add_header(&self, name: &str, value: &str); fn set_header(&self, name: &str, value: &str); fn set_headers(&self, headers: Vec<(&str, &str)>); fn remove_header(&self, name: &str); } ``` You can access headers in `on_request` or `on_response` wrapped functions by implementing the following code: ```Rust async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let headers_handler = headers_state.handler(); let old_value = headers_handler.header("request-header").unwrap_or_default(); let new_value = "--replaced--"; logger::info!("Old request header value: {old_value}, New value: {new_value}"); headers_handler.set_header("request-header", new_value); } async fn response_filter(response_state: ResponseState, _config: &Config) { let headers_state = response_state.into_headers_state().await; let headers_handler = headers_state.handler(); let old_headers = headers_handler.header("request-header").unwrap_or_default(); let new_value = vec![("response-header1", "--replaced--"), ("response-header2", "--replaced--")]; logger::info!("Old request header value: {old_headers:?}, New value: {new_value:?}"); headers_handler.set_headers(new_value); } ``` Envoy handles the method, scheme, path, authority, and status codes as headers. PDK provides the following methods to access and modify the request’s `:method`, `:scheme`, `:path`, `:authority`, and `:status` Envoy headers: ```Rust async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let method = headers_state.method(); let scheme = headers_state.scheme(); let authority = headers_state.authority(); let path = headers_state.path(); ... } async fn response_filter(response_state: ResponseState, _config: &Config) { let headers_state = response_state.into_headers_state().await; let status = headers_state.status_code(); } ``` ## Read and Write Request Bodies > [!NOTE] Reading and writing bodies is limited to payloads of size 1MB or smaller. For larger > payloads, see [Streaming Bodies](#streaming-bodies). To access the body in both the request and the response, transform the `RequestState` or `ResponseState` to a body state by calling the method `into_body_state()` and awaiting it: ```Rust let body_state = request_state.into_body_state().await; ``` > [!NOTE] The previous `.await` introduces a cancellation point. During a request, a > [Flow Cancellation](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features#flow-cancellation) might cause the `.await` to > never resume. If the original state was already transformed into a header state, transform the state into a body state by calling the same function, for example: ```Rust let headers_state = request_state.into_headers_state().await; let body_state = headers_state.into_body_state().await; ``` After calling `into_body_state()`, access and manipulate the headers by calling the functions of the `BodyHandler` trait. ```Rust pub trait BodyHandler { fn body(&self) -> Vec; fn set_body(&self, body: &[u8]) -> Result<(), BodyError>; } ``` Because Envoy uses the same buffer to share data from the headers and the body, the policy cannot access the headers and the body at the same time. If the policy must read both: 1. Read the headers and save the necessary values in a variable. 2. Read the body. You can read the headers and then the body in both the response and request. However, you cannot modify headers after reading the body. Complete all header modification before reading the body, for example: ```Rust async fn request_filter(request_state: RequestState) { let headers_state = request_state.into_headers_state().await; let headers_handler = headers_state.handler(); let agent = headers_handler.header("User-Agent").unwrap_or_else(|| "Undefined".to_string()); // Removing old content length header before manipulating body headers_handler.remove_header("content-length"); let body_state = headers_state.into_body_state().await; let body_handler = body_state.handler(); let body = body_handler.body(); logger::info!("User: {agent} sent: {}", String::from_utf8_lossy(body.as_slice())); let new_body = "new body".as_bytes(); match body_handler.set_body(&new_body) { Ok(_) => logger::info!("Body updated"), Err(e) => logger::info!("Unable to set body. Reason: {e:?}), } } ``` > [!NOTE] This code removes the `content-length` header. This is required to modify the body. `BodyHandler::set_body()` method returns a `Result<(), BodyError>` object. Body updating might fail due to: - `BodyError::BodyNotSent`: The current HTTP Flow doesn’t have a body (for example, `GET` request). - `BodyError::ExceededBodySize`: The new body exceeds the maximum body buffer size supported by Envoy. ## Streaming Bodies > [!NOTE] To view an example policy that uses the streaming body state, see > [Stream Payload Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/stream-payload/README.md). To handle request or response bodies larger than 1MB, use the streaming body state. The streaming body state enables the body to be processed as chunks as data arrives. When using the streaming body state, you cannot write to the body. Using the stream body state doesn’t affect reading and writing headers To use the streaming body state, convert the `RequestState` or `ResponseState` into a body stream state by calling the `into_body_stream_state()` method and awaiting it: ```Rust let body_stream_state = request_state.into_body_stream_state().await; ``` After conversion, access the incoming chunks through the `stream()` method: ```Rust let mut stream = body_stream_state.stream(); while let Some(chunk) = stream.next().await { // Process each chunk as it arrives let chunk_bytes = chunk.into_bytes(); // ... process chunk_bytes ... } ``` > [!NOTE] For an example of chunk processing, see > [Stream Payload Policy Chunks](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/stream-payload/src/lib.rs#L30). If you need the complete body before processing the payload, use the `collect()` method to collect all chunks: ```Rust let collect = stream.collect().await; ``` > [!NOTE] For an example of how to collect and process full payloads, see > [Stream Payload Policy Collect](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/stream-payload/src/lib.rs#L54). ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Reading and Writing Request Headers and Bodies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt With Flex Gateway Policy Development Kit (PDK), you can read and write to request and response headers and bodies and read from a streamed body. ## Event Flow When filtering requests and responses, Proxy Wasm splits handling the headers and body into two main events that must happen in a specific order. Before the policy can handle the body, the header event has to fully propagate through all policies. For example, the event flow for an API with two policies applied is: 1. Policy 1 handles the request header event. 2. Policy 2 handles the request header event. 3. The backend service receives the request headers. 4. Policy 1 handles the request body event. 5. Policy 2 handles the request body event. 6. The backend receives the request body. 7. The backend sends the response. 8. Policy 2 handles the response header event. 9. Policy 1 handles the response header event. 10. The client receives the response headers. 11. Policy 2 handles the response body event. 12. Policy 1 handles the response body event. 13. The client receives the response body. This order creates the following limitations: - Policies can’t modify headers after reading the body. - All policies must fully process the header event before reading the body. Saving data of the body on one policy and then modifying the headers using that body data in a different policy isn’t possible. - When all policies process the header event, it reaches the backend service. To ensure no data from a rejected request reaches the backend service, you must reject the headers based on only the request headers. When rejecting requests based on their body, most servers and clients can detect interrupted requests and discard the headers of the request. In the policy source code, reading the body separates the header and body event. For example, if the declaration `let body_state = headers_state.into_body_state().await;` is used to read the body, everything prior to the declaration occurs in the header event, and everything after occurs in the body event. ## Read and Write Request Headers To access the headers in both the request and the response, transform the `RequestState` or `ResponseState` to a header state by calling the method `into_headers_state()` and awaiting it. After calling the method, access and manipulate the headers by calling the functions of the `HeadersHandler` trait. ```Rust pub trait HeadersHandler { fn headers(&self) -> Vec<(String, String)>; fn header(&self, name: &str) -> Option; fn add_header(&self, name: &str, value: &str); fn set_header(&self, name: &str, value: &str); fn set_headers(&self, headers: Vec<(&str, &str)>); fn remove_header(&self, name: &str); } ``` You can access headers in `on_request` or `on_response` wrapped functions by implementing the following code: ```Rust async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let headers_handler = headers_state.handler(); let old_value = headers_handler.header("request-header").unwrap_or_default(); let new_value = "--replaced--"; logger::info!("Old request header value: {old_value}, New value: {new_value}"); headers_handler.set_header("request-header", new_value); } async fn response_filter(response_state: ResponseState, _config: &Config) { let headers_state = response_state.into_headers_state().await; let headers_handler = headers_state.handler(); let old_headers = headers_handler.header("request-header").unwrap_or_default(); let new_value = vec![("response-header1", "--replaced--"), ("response-header2", "--replaced--")]; logger::info!("Old request header value: {old_headers:?}, New value: {new_value:?}"); headers_handler.set_headers(new_value); } ``` Envoy handles the method, scheme, path, authority, and status codes as headers. PDK provides the following methods to access and modify the request’s `:method`, `:scheme`, `:path`, `:authority`, and `:status` Envoy headers: ```Rust async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let method = headers_state.method(); let scheme = headers_state.scheme(); let authority = headers_state.authority(); let path = headers_state.path(); ... } async fn response_filter(response_state: ResponseState, _config: &Config) { let headers_state = response_state.into_headers_state().await; let status = headers_state.status_code(); } ``` ## Read and Write Request Bodies > [!NOTE] Reading and writing bodies is limited to payloads of size 1MB or smaller. For larger > payloads, see [Streaming Bodies](#streaming-bodies). To access the body in both the request and the response, transform the `RequestState` or `ResponseState` to a body state by calling the method `into_body_state()` and awaiting it: ```Rust let body_state = request_state.into_body_state().await; ``` > [!NOTE] The previous `.await` introduces a cancellation point. During a request, a > [Flow Cancellation](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features#flow-cancellation) might cause the `.await` to > never resume. If the original state was already transformed into a header state, transform the state into a body state by calling the same function, for example: ```Rust let headers_state = request_state.into_headers_state().await; let body_state = headers_state.into_body_state().await; ``` After calling `into_body_state()`, access and manipulate the headers by calling the functions of the `BodyHandler` trait. ```Rust pub trait BodyHandler { fn body(&self) -> Vec; fn set_body(&self, body: &[u8]) -> Result<(), BodyError>; } ``` Because Envoy uses the same buffer to share data from the headers and the body, the policy cannot access the headers and the body at the same time. If the policy must read both: 1. Read the headers and save the necessary values in a variable. 2. Read the body. You can read the headers and then the body in both the response and request. However, you cannot modify headers after reading the body. Complete all header modification before reading the body, for example: ```Rust async fn request_filter(request_state: RequestState) { let headers_state = request_state.into_headers_state().await; let headers_handler = headers_state.handler(); let agent = headers_handler.header("User-Agent").unwrap_or_else(|| "Undefined".to_string()); // Removing old content length header before manipulating body headers_handler.remove_header("content-length"); let body_state = headers_state.into_body_state().await; let body_handler = body_state.handler(); let body = body_handler.body(); logger::info!("User: {agent} sent: {}", String::from_utf8_lossy(body.as_slice())); let new_body = "new body".as_bytes(); match body_handler.set_body(&new_body) { Ok(_) => logger::info!("Body updated"), Err(e) => logger::info!("Unable to set body. Reason: {e:?}), } } ``` > [!NOTE] This code removes the `content-length` header. This is required to modify the body. `BodyHandler::set_body()` method returns a `Result<(), BodyError>` object. Body updating might fail due to: - `BodyError::BodyNotSent`: The current HTTP Flow doesn’t have a body (for example, `GET` request). - `BodyError::ExceededBodySize`: The new body exceeds the maximum body buffer size supported by Envoy. ## Streaming Bodies > [!NOTE] To view an example policy that uses the streaming body state, see > [Stream Payload Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/stream-payload/README.md). To handle request or response bodies larger than 1MB, use the streaming body state. The streaming body state enables the body to be processed as chunks as data arrives. When using the streaming body state, you cannot write to the body. Using the stream body state doesn’t affect reading and writing headers To use the streaming body state, convert the `RequestState` or `ResponseState` into a body stream state by calling the `into_body_stream_state()` method and awaiting it: ```Rust let body_stream_state = request_state.into_body_stream_state().await; ``` After conversion, access the incoming chunks through the `stream()` method: ```Rust let mut stream = body_stream_state.stream(); while let Some(chunk) = stream.next().await { // Process each chunk as it arrives let chunk_bytes = chunk.into_bytes(); // ... process chunk_bytes ... } ``` > [!NOTE] For an example of chunk processing, see > [Stream Payload Policy Chunks](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/stream-payload/src/lib.rs#L30). If you need the complete body before processing the payload, use the `collect()` method to collect all chunks: ```Rust let collect = stream.collect().await; ``` > [!NOTE] For an example of how to collect and process full payloads, see > [Stream Payload Policy Collect](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/stream-payload/src/lib.rs#L54). ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Reading and Writing Request Headers and Bodies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt With Flex Gateway Policy Development Kit (PDK), you can read and write to request and response headers and bodies and read from a streamed body. ## Event Flow When filtering requests and responses, Proxy Wasm splits handling the headers and body into two main events that must happen in a specific order. Before the policy can handle the body, the header event has to fully propagate through all policies. For example, the event flow for an API with two policies applied is: 1. Policy 1 handles the request header event. 2. Policy 2 handles the request header event. 3. The backend service receives the request headers. 4. Policy 1 handles the request body event. 5. Policy 2 handles the request body event. 6. The backend receives the request body. 7. The backend sends the response. 8. Policy 2 handles the response header event. 9. Policy 1 handles the response header event. 10. The client receives the response headers. 11. Policy 2 handles the response body event. 12. Policy 1 handles the response body event. 13. The client receives the response body. This order creates the following limitations: - Policies can’t modify headers after reading the body. - All policies must fully process the header event before reading the body. Saving data of the body on one policy and then modifying the headers using that body data in a different policy isn’t possible. - When all policies process the header event, it reaches the backend service. To ensure no data from a rejected request reaches the backend service, you must reject the headers based on only the request headers. When rejecting requests based on their body, most servers and clients can detect interrupted requests and discard the headers of the request. In the policy source code, reading the body separates the header and body event. For example, if the declaration `let body_state = headers_state.into_body_state().await;` is used to read the body, everything prior to the declaration occurs in the header event, and everything after occurs in the body event. ## Read and Write Request Headers To access the headers in both the request and the response, transform the `RequestState` or `ResponseState` to a header state by calling the method `into_headers_state()` and awaiting it. After calling the method, access and manipulate the headers by calling the functions of the `HeadersHandler` trait. ```Rust pub trait HeadersHandler { fn headers(&self) -> Vec<(String, String)>; fn header(&self, name: &str) -> Option; fn add_header(&self, name: &str, value: &str); fn set_header(&self, name: &str, value: &str); fn set_headers(&self, headers: Vec<(&str, &str)>); fn remove_header(&self, name: &str); } ``` You can access headers in `on_request` or `on_response` wrapped functions by implementing the following code: ```Rust async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let headers_handler = headers_state.handler(); let old_value = headers_handler.header("request-header").unwrap_or_default(); let new_value = "--replaced--"; logger::info!("Old request header value: {old_value}, New value: {new_value}"); headers_handler.set_header("request-header", new_value); } async fn response_filter(response_state: ResponseState, _config: &Config) { let headers_state = response_state.into_headers_state().await; let headers_handler = headers_state.handler(); let old_headers = headers_handler.header("request-header").unwrap_or_default(); let new_value = vec![("response-header1", "--replaced--"), ("response-header2", "--replaced--")]; logger::info!("Old request header value: {old_headers:?}, New value: {new_value:?}"); headers_handler.set_headers(new_value); } ``` Envoy handles the method, scheme, path, authority, and status codes as headers. PDK provides the following methods to access and modify the request’s `:method`, `:scheme`, `:path`, `:authority`, and `:status` Envoy headers: ```Rust async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let method = headers_state.method(); let scheme = headers_state.scheme(); let authority = headers_state.authority(); let path = headers_state.path(); ... } async fn response_filter(response_state: ResponseState, _config: &Config) { let headers_state = response_state.into_headers_state().await; let status = headers_state.status_code(); } ``` ## Read and Write Request Bodies > [!NOTE] Reading and writing bodies is limited to payloads of size 1MB or smaller. For larger > payloads, see [Streaming Bodies](#streaming-bodies). To access the body in both the request and the response, transform the `RequestState` or `ResponseState` to a body state by calling the method `into_body_state()` and awaiting it: ```Rust let body_state = request_state.into_body_state().await; ``` > [!NOTE] The previous `.await` introduces a cancellation point. During a request, a > [Flow Cancellation](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features#flow-cancellation) might cause the `.await` to > never resume. If the original state was already transformed into a header state, transform the state into a body state by calling the same function, for example: ```Rust let headers_state = request_state.into_headers_state().await; let body_state = headers_state.into_body_state().await; ``` After calling `into_body_state()`, access and manipulate the headers by calling the functions of the `BodyHandler` trait. ```Rust pub trait BodyHandler { fn body(&self) -> Vec; fn set_body(&self, body: &[u8]) -> Result<(), BodyError>; } ``` Because Envoy uses the same buffer to share data from the headers and the body, the policy cannot access the headers and the body at the same time. If the policy must read both: 1. Read the headers and save the necessary values in a variable. 2. Read the body. You can read the headers and then the body in both the response and request. However, you cannot modify headers after reading the body. Complete all header modification before reading the body, for example: ```Rust async fn request_filter(request_state: RequestState) { let headers_state = request_state.into_headers_state().await; let headers_handler = headers_state.handler(); let agent = headers_handler.header("User-Agent").unwrap_or_else(|| "Undefined".to_string()); // Removing old content length header before manipulating body headers_handler.remove_header("content-length"); let body_state = headers_state.into_body_state().await; let body_handler = body_state.handler(); let body = body_handler.body(); logger::info!("User: {agent} sent: {}", String::from_utf8_lossy(body.as_slice())); let new_body = "new body".as_bytes(); match body_handler.set_body(&new_body) { Ok(_) => logger::info!("Body updated"), Err(e) => logger::info!("Unable to set body. Reason: {e:?}), } } ``` > [!NOTE] This code removes the `content-length` header. This is required to modify the body. `BodyHandler::set_body()` method returns a `Result<(), BodyError>` object. Body updating might fail due to: - `BodyError::BodyNotSent`: The current HTTP Flow doesn’t have a body (for example, `GET` request). - `BodyError::ExceededBodySize`: The new body exceeds the maximum body buffer size supported by Envoy. ## Streaming Bodies > [!NOTE] To view an example policy that uses the streaming body state, see > [Stream Payload Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/stream-payload/README.md). To handle request or response bodies larger than 1MB, use the streaming body state. The streaming body state enables the body to be processed as chunks as data arrives. When using the streaming body state, you cannot write to the body. Using the stream body state doesn’t affect reading and writing headers To use the streaming body state, convert the `RequestState` or `ResponseState` into a body stream state by calling the `into_body_stream_state()` method and awaiting it: ```Rust let body_stream_state = request_state.into_body_stream_state().await; ``` After conversion, access the incoming chunks through the `stream()` method: ```Rust let mut stream = body_stream_state.stream(); while let Some(chunk) = stream.next().await { // Process each chunk as it arrives let chunk_bytes = chunk.into_bytes(); // ... process chunk_bytes ... } ``` > [!NOTE] For an example of chunk processing, see > [Stream Payload Policy Chunks](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/stream-payload/src/lib.rs#L30). If you need the complete body before processing the payload, use the `collect()` method to collect all chunks: ```Rust let collect = stream.collect().await; ``` > [!NOTE] For an example of how to collect and process full payloads, see > [Stream Payload Policy Collect](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/stream-payload/src/lib.rs#L54). ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Reading and Writing Request Headers and Bodies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt With Flex Gateway Policy Development Kit (PDK), you can read and write to request and response headers and bodies and read from a streamed body. ## Event Flow When filtering requests and responses, Proxy Wasm splits handling the headers and body into two main events that must happen in a specific order. Before the policy can handle the body, the header event has to fully propagate through all policies. For example, the event flow for an API with two policies applied is: 1. Policy 1 handles the request header event. 2. Policy 2 handles the request header event. 3. The backend service receives the request headers. 4. Policy 1 handles the request body event. 5. Policy 2 handles the request body event. 6. The backend receives the request body. 7. The backend sends the response. 8. Policy 2 handles the response header event. 9. Policy 1 handles the response header event. 10. The client receives the response headers. 11. Policy 2 handles the response body event. 12. Policy 1 handles the response body event. 13. The client receives the response body. This order creates the following limitations: - Policies can’t modify headers after reading the body. - All policies must fully process the header event before reading the body. Saving data of the body on one policy and then modifying the headers using that body data in a different policy isn’t possible. - When all policies process the header event, it reaches the backend service. To ensure no data from a rejected request reaches the backend service, you must reject the headers based on only the request headers. When rejecting requests based on their body, most servers and clients can detect interrupted requests and discard the headers of the request. In the policy source code, reading the body separates the header and body event. For example, if the declaration `let body_state = headers_state.into_body_state().await;` is used to read the body, everything prior to the declaration occurs in the header event, and everything after occurs in the body event. ## Read and Write Request Headers To access the headers in both the request and the response, transform the `RequestState` or `ResponseState` to a header state by calling the method `into_headers_state()` and awaiting it. After calling the method, access and manipulate the headers by calling the functions of the `HeadersHandler` trait. ```Rust pub trait HeadersHandler { fn headers(&self) -> Vec<(String, String)>; fn header(&self, name: &str) -> Option; fn add_header(&self, name: &str, value: &str); fn set_header(&self, name: &str, value: &str); fn set_headers(&self, headers: Vec<(&str, &str)>); fn remove_header(&self, name: &str); } ``` You can access headers in `on_request` or `on_response` wrapped functions by implementing the following code: ```Rust async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let headers_handler = headers_state.handler(); let old_value = headers_handler.header("request-header").unwrap_or_default(); let new_value = "--replaced--"; logger::info!("Old request header value: {old_value}, New value: {new_value}"); headers_handler.set_header("request-header", new_value); } async fn response_filter(response_state: ResponseState, _config: &Config) { let headers_state = response_state.into_headers_state().await; let headers_handler = headers_state.handler(); let old_headers = headers_handler.header("request-header").unwrap_or_default(); let new_value = vec![("response-header1", "--replaced--"), ("response-header2", "--replaced--")]; logger::info!("Old request header value: {old_headers:?}, New value: {new_value:?}"); headers_handler.set_headers(new_value); } ``` Envoy handles the method, scheme, path, authority, and status codes as headers. PDK provides the following methods to access and modify the request’s `:method`, `:scheme`, `:path`, `:authority`, and `:status` Envoy headers: ```Rust async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let method = headers_state.method(); let scheme = headers_state.scheme(); let authority = headers_state.authority(); let path = headers_state.path(); ... } async fn response_filter(response_state: ResponseState, _config: &Config) { let headers_state = response_state.into_headers_state().await; let status = headers_state.status_code(); } ``` ## Read and Write Request Bodies > [!NOTE] Reading and writing bodies is limited to payloads of size 1MB or smaller. For larger > payloads, see [Streaming Bodies](#streaming-bodies). To access the body in both the request and the response, transform the `RequestState` or `ResponseState` to a body state by calling the method `into_body_state()` and awaiting it: ```Rust let body_state = request_state.into_body_state().await; ``` > [!NOTE] The previous `.await` introduces a cancellation point. During a request, a > [Flow Cancellation](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features#flow-cancellation) might cause the `.await` to > never resume. If the original state was already transformed into a header state, transform the state into a body state by calling the same function, for example: ```Rust let headers_state = request_state.into_headers_state().await; let body_state = headers_state.into_body_state().await; ``` After calling `into_body_state()`, access and manipulate the headers by calling the functions of the `BodyHandler` trait. ```Rust pub trait BodyHandler { fn body(&self) -> Vec; fn set_body(&self, body: &[u8]) -> Result<(), BodyError>; } ``` Because Envoy uses the same buffer to share data from the headers and the body, the policy cannot access the headers and the body at the same time. If the policy must read both: 1. Read the headers and save the necessary values in a variable. 2. Read the body. You can read the headers and then the body in both the response and request. However, you cannot modify headers after reading the body. Complete all header modification before reading the body, for example: ```Rust async fn request_filter(request_state: RequestState) { let headers_state = request_state.into_headers_state().await; let headers_handler = headers_state.handler(); let agent = headers_handler.header("User-Agent").unwrap_or_else(|| "Undefined".to_string()); // Removing old content length header before manipulating body headers_handler.remove_header("content-length"); let body_state = headers_state.into_body_state().await; let body_handler = body_state.handler(); let body = body_handler.body(); logger::info!("User: {agent} sent: {}", String::from_utf8_lossy(body.as_slice())); let new_body = "new body".as_bytes(); match body_handler.set_body(&new_body) { Ok(_) => logger::info!("Body updated"), Err(e) => logger::info!("Unable to set body. Reason: {e:?}), } } ``` > [!NOTE] This code removes the `content-length` header. This is required to modify the body. `BodyHandler::set_body()` method returns a `Result<(), BodyError>` object. Body updating might fail due to: - `BodyError::BodyNotSent`: The current HTTP Flow doesn’t have a body (for example, `GET` request). - `BodyError::ExceededBodySize`: The new body exceeds the maximum body buffer size supported by Envoy. ## Streaming Bodies > [!NOTE] To view an example policy that uses the streaming body state, see > [Stream Payload Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/stream-payload/README.md). To handle request or response bodies larger than 1MB, use the streaming body state. The streaming body state enables the body to be processed as chunks as data arrives. When using the streaming body state, you cannot write to the body. Using the stream body state doesn’t affect reading and writing headers To use the streaming body state, convert the `RequestState` or `ResponseState` into a body stream state by calling the `into_body_stream_state()` method and awaiting it: ```Rust let body_stream_state = request_state.into_body_stream_state().await; ``` After conversion, access the incoming chunks through the `stream()` method: ```Rust let mut stream = body_stream_state.stream(); while let Some(chunk) = stream.next().await { // Process each chunk as it arrives let chunk_bytes = chunk.into_bytes(); // ... process chunk_bytes ... } ``` > [!NOTE] For an example of chunk processing, see > [Stream Payload Policy Chunks](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/stream-payload/src/lib.rs#L30). If you need the complete body before processing the payload, use the `collect()` method to collect all chunks: ```Rust let collect = stream.collect().await; ``` > [!NOTE] For an example of how to collect and process full payloads, see > [Stream Payload Policy Collect](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/stream-payload/src/lib.rs#L54). ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Reading and Writing Request Headers and Bodies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK), provides two seperate ways to read and write headers and bodies. Choose either depending on your use case: - [Reading and Writing Request Headers and Bodies with Separate Event States](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-headers-event): Use the event flow method when you: - Don’t need to read the request body and don’t want to buffer the entire payload. - Need to stream the request payload. - [Reading and Writing Request Headers and Bodies with Stop Iteration](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-headers-stop): Use the stop iteration method when: - Your policy must read and write headers and bodies at the same time. --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Reading and Writing Request Headers and Bodies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK), provides two seperate ways to read and write headers and bodies. Choose either depending on your use case: - [Reading and Writing Request Headers and Bodies with Separate Event States](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-headers-event): Use the event flow method when you: - Don’t need to read the request body and don’t want to buffer the entire payload. - Need to stream the request payload. - [Reading and Writing Request Headers and Bodies with Stop Iteration](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-headers-stop): Use the stop iteration method when: - Your policy must read and write headers and bodies at the same time. --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Reading and Writing Request Headers and Bodies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK), provides two seperate ways to read and write headers and bodies. Choose either depending on your use case: - [Reading and Writing Request Headers and Bodies with Separate Event States](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-headers-event): Use the event flow method when you: - Don’t need to read the request body and don’t want to buffer the entire payload. - Need to stream the request payload. - [Reading and Writing Request Headers and Bodies with Stop Iteration](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-headers-stop): Use the stop iteration method when: - Your policy must read and write headers and bodies at the same time. --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Reading and Writing Request Headers and Bodies with Separate Event States > For the full documentation index, see: https://docs.mulesoft.com/llms.txt With Omni Gateway Policy Development Kit (PDK), you can read and write to request and response headers and bodies and read from a streamed body. ## Event Flow When filtering requests and responses, Proxy Wasm splits handling the headers and body into two main events that must happen in a specific order. Before the policy can handle the body, the header event has to fully propagate through all policies. For example, the event flow for an API with two policies applied is: 1. Policy 1 handles the request header event. 2. Policy 2 handles the request header event. 3. The backend service receives the request headers. 4. Policy 1 handles the request body event. 5. Policy 2 handles the request body event. 6. The backend receives the request body. 7. The backend sends the response. 8. Policy 2 handles the response header event. 9. Policy 1 handles the response header event. 10. The client receives the response headers. 11. Policy 2 handles the response body event. 12. Policy 1 handles the response body event. 13. The client receives the response body. This order creates the following limitations: - Policies can’t modify headers after reading the body. - All policies must fully process the header event before reading the body. Saving data of the body on one policy and then modifying the headers using that body data in a different policy isn’t possible. - When all policies process the header event, it reaches the backend service. To ensure no data from a rejected request reaches the backend service, you must reject the headers based on only the request headers. When rejecting requests based on their body, most servers and clients can detect interrupted requests and discard the headers of the request. In the policy source code, reading the body separates the header and body event. For example, if the declaration `let body_state = headers_state.into_body_state().await;` is used to read the body, everything prior to the declaration occurs in the header event, and everything after occurs in the body event. ## Read and Write Request Headers To access the headers in both the request and the response, transform the `RequestState` or `ResponseState` to a header state by calling the method `into_headers_state()` and awaiting it. After calling the method, access and manipulate the headers by calling the functions of the `HeadersHandler` trait. ```Rust pub trait HeadersHandler { fn headers(&self) -> Vec<(String, String)>; fn header(&self, name: &str) -> Option; fn add_header(&self, name: &str, value: &str); fn set_header(&self, name: &str, value: &str); fn set_headers(&self, headers: Vec<(&str, &str)>); fn remove_header(&self, name: &str); } ``` You can access headers in `on_request` or `on_response` wrapped functions by implementing the following code: ```Rust async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let headers_handler = headers_state.handler(); let old_value = headers_handler.header("request-header").unwrap_or_default(); let new_value = "--replaced--"; logger::info!("Old request header value: {old_value}, New value: {new_value}"); headers_handler.set_header("request-header", new_value); } async fn response_filter(response_state: ResponseState, _config: &Config) { let headers_state = response_state.into_headers_state().await; let headers_handler = headers_state.handler(); let old_headers = headers_handler.header("request-header").unwrap_or_default(); let new_value = vec![("response-header1", "--replaced--"), ("response-header2", "--replaced--")]; logger::info!("Old request header value: {old_headers:?}, New value: {new_value:?}"); headers_handler.set_headers(new_value); } ``` Envoy handles the method, scheme, path, authority, and status codes as headers. PDK provides the following methods to access and modify the request’s `:method`, `:scheme`, `:path`, `:authority`, and `:status` Envoy headers: ```Rust async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let method = headers_state.method(); let scheme = headers_state.scheme(); let authority = headers_state.authority(); let path = headers_state.path(); ... } async fn response_filter(response_state: ResponseState, _config: &Config) { let headers_state = response_state.into_headers_state().await; let status = headers_state.status_code(); } ``` ## Read and Write Request Bodies > [!NOTE] Reading and writing bodies is limited to payloads of size 1MB or smaller. For larger > payloads, see [Streaming Bodies](#streaming-bodies). To access the body in both the request and the response, transform the `RequestState` or `ResponseState` to a body state by calling the method `into_body_state()` and awaiting it: ```Rust let body_state = request_state.into_body_state().await; ``` > [!NOTE] The previous `.await` introduces a cancellation point. During a request, a > [Flow Cancellation](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features#flow-cancellation) might cause the `.await` to > never resume. If the original state was already transformed into a header state, transform the state into a body state by calling the same function, for example: ```Rust let headers_state = request_state.into_headers_state().await; let body_state = headers_state.into_body_state().await; ``` After calling `into_body_state()`, access and manipulate the headers by calling the functions of the `BodyHandler` trait. ```Rust pub trait BodyHandler { fn body(&self) -> Vec; fn set_body(&self, body: &[u8]) -> Result<(), BodyError>; } ``` Because Envoy uses the same buffer to share data from the headers and the body, the policy cannot access the headers and the body at the same time. If the policy must read both: 1. Read the headers and save the necessary values in a variable. 2. Read the body. You can read the headers and then the body in both the response and request. However, you cannot modify headers after reading the body. Complete all header modification before reading the body, for example: ```Rust async fn request_filter(request_state: RequestState) { let headers_state = request_state.into_headers_state().await; let headers_handler = headers_state.handler(); let agent = headers_handler.header("User-Agent").unwrap_or_else(|| "Undefined".to_string()); // Removing old content length header before manipulating body headers_handler.remove_header("content-length"); let body_state = headers_state.into_body_state().await; let body_handler = body_state.handler(); let body = body_handler.body(); logger::info!("User: {agent} sent: {}", String::from_utf8_lossy(body.as_slice())); let new_body = "new body".as_bytes(); match body_handler.set_body(&new_body) { Ok(_) => logger::info!("Body updated"), Err(e) => logger::info!("Unable to set body. Reason: {e:?}), } } ``` > [!NOTE] This code removes the `content-length` header. This is required to modify the body. `BodyHandler::set_body()` method returns a `Result<(), BodyError>` object. Body updating might fail due to: - `BodyError::BodyNotSent`: The current HTTP Flow doesn’t have a body (for example, `GET` request). - `BodyError::ExceededBodySize`: The new body exceeds the maximum body buffer size supported by Envoy. ## Streaming Bodies > [!NOTE] To view an example policy that uses the streaming body state, see > [Stream Payload Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/stream-payload/README.md). To handle request or response bodies larger than 1MB, use the streaming body state. The streaming body state enables the body to be processed as chunks as data arrives. When using the streaming body state, you cannot write to the body. Using the stream body state doesn’t affect reading and writing headers To use the streaming body state, convert the `RequestState` or `ResponseState` into a body stream state by calling the `into_body_stream_state()` method and awaiting it: ```Rust let body_stream_state = request_state.into_body_stream_state().await; ``` After conversion, access the incoming chunks through the `stream()` method: ```Rust let mut stream = body_stream_state.stream(); while let Some(chunk) = stream.next().await { // Process each chunk as it arrives let chunk_bytes = chunk.into_bytes(); // ... process chunk_bytes ... } ``` > [!NOTE] For an example of chunk processing, see > [Stream Payload Policy Chunks](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/stream-payload/src/lib.rs#L30). If you need the complete body before processing the payload, use the `collect()` method to collect all chunks: ```Rust let collect = stream.collect().await; ``` > [!NOTE] For an example of how to collect and process full payloads, see > [Stream Payload Policy Collect](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/stream-payload/src/lib.rs#L54). ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Reading and Writing Request Headers and Bodies with Separate Event States > For the full documentation index, see: https://docs.mulesoft.com/llms.txt With Omni Gateway Policy Development Kit (PDK), you can read and write to request and response headers and bodies and read from a streamed body. ## Event Flow When filtering requests and responses, Proxy Wasm splits handling the headers and body into two main events that must happen in a specific order. Before the policy can handle the body, the header event has to fully propagate through all policies. For example, the event flow for an API with two policies applied is: 1. Policy 1 handles the request header event. 2. Policy 2 handles the request header event. 3. The backend service receives the request headers. 4. Policy 1 handles the request body event. 5. Policy 2 handles the request body event. 6. The backend receives the request body. 7. The backend sends the response. 8. Policy 2 handles the response header event. 9. Policy 1 handles the response header event. 10. The client receives the response headers. 11. Policy 2 handles the response body event. 12. Policy 1 handles the response body event. 13. The client receives the response body. This order creates the following limitations: - Policies can’t modify headers after reading the body. - All policies must fully process the header event before reading the body. Saving data of the body on one policy and then modifying the headers using that body data in a different policy isn’t possible. - When all policies process the header event, it reaches the backend service. To ensure no data from a rejected request reaches the backend service, you must reject the headers based on only the request headers. When rejecting requests based on their body, most servers and clients can detect interrupted requests and discard the headers of the request. In the policy source code, reading the body separates the header and body event. For example, if the declaration `let body_state = headers_state.into_body_state().await;` is used to read the body, everything prior to the declaration occurs in the header event, and everything after occurs in the body event. ## Read and Write Request Headers To access the headers in both the request and the response, transform the `RequestState` or `ResponseState` to a header state by calling the method `into_headers_state()` and awaiting it. After calling the method, access and manipulate the headers by calling the functions of the `HeadersHandler` trait. ```Rust pub trait HeadersHandler { fn headers(&self) -> Vec<(String, String)>; fn header(&self, name: &str) -> Option; fn add_header(&self, name: &str, value: &str); fn set_header(&self, name: &str, value: &str); fn set_headers(&self, headers: Vec<(&str, &str)>); fn remove_header(&self, name: &str); } ``` You can access headers in `on_request` or `on_response` wrapped functions by implementing the following code: ```Rust async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let headers_handler = headers_state.handler(); let old_value = headers_handler.header("request-header").unwrap_or_default(); let new_value = "--replaced--"; logger::info!("Old request header value: {old_value}, New value: {new_value}"); headers_handler.set_header("request-header", new_value); } async fn response_filter(response_state: ResponseState, _config: &Config) { let headers_state = response_state.into_headers_state().await; let headers_handler = headers_state.handler(); let old_headers = headers_handler.header("request-header").unwrap_or_default(); let new_value = vec![("response-header1", "--replaced--"), ("response-header2", "--replaced--")]; logger::info!("Old request header value: {old_headers:?}, New value: {new_value:?}"); headers_handler.set_headers(new_value); } ``` Envoy handles the method, scheme, path, authority, and status codes as headers. PDK provides the following methods to access and modify the request’s `:method`, `:scheme`, `:path`, `:authority`, and `:status` Envoy headers: ```Rust async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let method = headers_state.method(); let scheme = headers_state.scheme(); let authority = headers_state.authority(); let path = headers_state.path(); ... } async fn response_filter(response_state: ResponseState, _config: &Config) { let headers_state = response_state.into_headers_state().await; let status = headers_state.status_code(); } ``` ## Read and Write Request Bodies > [!NOTE] Reading and writing bodies is limited to payloads of size 1MB or smaller. For larger > payloads, see [Streaming Bodies](#streaming-bodies). To access the body in both the request and the response, transform the `RequestState` or `ResponseState` to a body state by calling the method `into_body_state()` and awaiting it: ```Rust let body_state = request_state.into_body_state().await; ``` > [!NOTE] The previous `.await` introduces a cancellation point. During a request, a > [Flow Cancellation](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features#flow-cancellation) might cause the `.await` to > never resume. If the original state was already transformed into a header state, transform the state into a body state by calling the same function, for example: ```Rust let headers_state = request_state.into_headers_state().await; let body_state = headers_state.into_body_state().await; ``` After calling `into_body_state()`, access and manipulate the headers by calling the functions of the `BodyHandler` trait. ```Rust pub trait BodyHandler { fn body(&self) -> Vec; fn set_body(&self, body: &[u8]) -> Result<(), BodyError>; } ``` Because Envoy uses the same buffer to share data from the headers and the body, the policy cannot access the headers and the body at the same time. If the policy must read both: 1. Read the headers and save the necessary values in a variable. 2. Read the body. You can read the headers and then the body in both the response and request. However, you cannot modify headers after reading the body. Complete all header modification before reading the body, for example: ```Rust async fn request_filter(request_state: RequestState) { let headers_state = request_state.into_headers_state().await; let headers_handler = headers_state.handler(); let agent = headers_handler.header("User-Agent").unwrap_or_else(|| "Undefined".to_string()); // Removing old content length header before manipulating body headers_handler.remove_header("content-length"); let body_state = headers_state.into_body_state().await; let body_handler = body_state.handler(); let body = body_handler.body(); logger::info!("User: {agent} sent: {}", String::from_utf8_lossy(body.as_slice())); let new_body = "new body".as_bytes(); match body_handler.set_body(&new_body) { Ok(_) => logger::info!("Body updated"), Err(e) => logger::info!("Unable to set body. Reason: {e:?}), } } ``` > [!NOTE] This code removes the `content-length` header. This is required to modify the body. `BodyHandler::set_body()` method returns a `Result<(), BodyError>` object. Body updating might fail due to: - `BodyError::BodyNotSent`: The current HTTP Flow doesn’t have a body (for example, `GET` request). - `BodyError::ExceededBodySize`: The new body exceeds the maximum body buffer size supported by Envoy. ## Streaming Bodies > [!NOTE] To view an example policy that uses the streaming body state, see > [Stream Payload Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/stream-payload/README.md). To handle request or response bodies larger than 1MB, use the streaming body state. The streaming body state enables the body to be processed as chunks as data arrives. When using the streaming body state, you cannot write to the body. Using the stream body state doesn’t affect reading and writing headers To use the streaming body state, convert the `RequestState` or `ResponseState` into a body stream state by calling the `into_body_stream_state()` method and awaiting it: ```Rust let body_stream_state = request_state.into_body_stream_state().await; ``` After conversion, access the incoming chunks through the `stream()` method: ```Rust let mut stream = body_stream_state.stream(); while let Some(chunk) = stream.next().await { // Process each chunk as it arrives let chunk_bytes = chunk.into_bytes(); // ... process chunk_bytes ... } ``` > [!NOTE] For an example of chunk processing, see > [Stream Payload Policy Chunks](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/stream-payload/src/lib.rs#L30). If you need the complete body before processing the payload, use the `collect()` method to collect all chunks: ```Rust let collect = stream.collect().await; ``` > [!NOTE] For an example of how to collect and process full payloads, see > [Stream Payload Policy Collect](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/stream-payload/src/lib.rs#L54). ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Reading and Writing Request Headers and Bodies with Separate Event States > For the full documentation index, see: https://docs.mulesoft.com/llms.txt With Omni Gateway Policy Development Kit (PDK), you can read and write to request and response headers and bodies and read from a streamed body. ## Event Flow When filtering requests and responses, Proxy Wasm splits handling the headers and body into two main events that must happen in a specific order. Before the policy can handle the body, the header event has to fully propagate through all policies. For example, the event flow for an API with two policies applied is: 1. Policy 1 handles the request header event. 2. Policy 2 handles the request header event. 3. The backend service receives the request headers. 4. Policy 1 handles the request body event. 5. Policy 2 handles the request body event. 6. The backend receives the request body. 7. The backend sends the response. 8. Policy 2 handles the response header event. 9. Policy 1 handles the response header event. 10. The client receives the response headers. 11. Policy 2 handles the response body event. 12. Policy 1 handles the response body event. 13. The client receives the response body. This order creates the following limitations: - Policies can’t modify headers after reading the body. - All policies must fully process the header event before reading the body. Saving data of the body on one policy and then modifying the headers using that body data in a different policy isn’t possible. - When all policies process the header event, it reaches the backend service. To ensure no data from a rejected request reaches the backend service, you must reject the headers based on only the request headers. When rejecting requests based on their body, most servers and clients can detect interrupted requests and discard the headers of the request. In the policy source code, reading the body separates the header and body event. For example, if the declaration `let body_state = headers_state.into_body_state().await;` is used to read the body, everything prior to the declaration occurs in the header event, and everything after occurs in the body event. ## Read and Write Request Headers To access the headers in both the request and the response, transform the `RequestState` or `ResponseState` to a header state by calling the method `into_headers_state()` and awaiting it. After calling the method, access and manipulate the headers by calling the functions of the `HeadersHandler` trait. ```Rust pub trait HeadersHandler { fn headers(&self) -> Vec<(String, String)>; fn header(&self, name: &str) -> Option; fn add_header(&self, name: &str, value: &str); fn set_header(&self, name: &str, value: &str); fn set_headers(&self, headers: Vec<(&str, &str)>); fn remove_header(&self, name: &str); } ``` You can access headers in `on_request` or `on_response` wrapped functions by implementing the following code: ```Rust async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let headers_handler = headers_state.handler(); let old_value = headers_handler.header("request-header").unwrap_or_default(); let new_value = "--replaced--"; logger::info!("Old request header value: {old_value}, New value: {new_value}"); headers_handler.set_header("request-header", new_value); } async fn response_filter(response_state: ResponseState, _config: &Config) { let headers_state = response_state.into_headers_state().await; let headers_handler = headers_state.handler(); let old_headers = headers_handler.header("request-header").unwrap_or_default(); let new_value = vec![("response-header1", "--replaced--"), ("response-header2", "--replaced--")]; logger::info!("Old request header value: {old_headers:?}, New value: {new_value:?}"); headers_handler.set_headers(new_value); } ``` Envoy handles the method, scheme, path, authority, and status codes as headers. PDK provides the following methods to access and modify the request’s `:method`, `:scheme`, `:path`, `:authority`, and `:status` Envoy headers: ```Rust async fn request_filter(request_state: RequestState, _config: &Config) { let headers_state = request_state.into_headers_state().await; let method = headers_state.method(); let scheme = headers_state.scheme(); let authority = headers_state.authority(); let path = headers_state.path(); ... } async fn response_filter(response_state: ResponseState, _config: &Config) { let headers_state = response_state.into_headers_state().await; let status = headers_state.status_code(); } ``` ## Read and Write Request Bodies > [!NOTE] Reading and writing bodies is limited to payloads of size 1MB or smaller. For larger > payloads, see [Streaming Bodies](#streaming-bodies). To access the body in both the request and the response, transform the `RequestState` or `ResponseState` to a body state by calling the method `into_body_state()` and awaiting it: ```Rust let body_state = request_state.into_body_state().await; ``` > [!NOTE] The previous `.await` introduces a cancellation point. During a request, a > [Flow Cancellation](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features#flow-cancellation) might cause the `.await` to > never resume. If the original state was already transformed into a header state, transform the state into a body state by calling the same function, for example: ```Rust let headers_state = request_state.into_headers_state().await; let body_state = headers_state.into_body_state().await; ``` After calling `into_body_state()`, access and manipulate the headers by calling the functions of the `BodyHandler` trait. ```Rust pub trait BodyHandler { fn body(&self) -> Vec; fn set_body(&self, body: &[u8]) -> Result<(), BodyError>; } ``` Because Envoy uses the same buffer to share data from the headers and the body, the policy cannot access the headers and the body at the same time. If the policy must read both: 1. Read the headers and save the necessary values in a variable. 2. Read the body. You can read the headers and then the body in both the response and request. However, you cannot modify headers after reading the body. Complete all header modification before reading the body, for example: ```Rust async fn request_filter(request_state: RequestState) { let headers_state = request_state.into_headers_state().await; let headers_handler = headers_state.handler(); let agent = headers_handler.header("User-Agent").unwrap_or_else(|| "Undefined".to_string()); // Removing old content length header before manipulating body headers_handler.remove_header("content-length"); let body_state = headers_state.into_body_state().await; let body_handler = body_state.handler(); let body = body_handler.body(); logger::info!("User: {agent} sent: {}", String::from_utf8_lossy(body.as_slice())); let new_body = "new body".as_bytes(); match body_handler.set_body(&new_body) { Ok(_) => logger::info!("Body updated"), Err(e) => logger::info!("Unable to set body. Reason: {e:?}), } } ``` > [!NOTE] This code removes the `content-length` header. This is required to modify the body. `BodyHandler::set_body()` method returns a `Result<(), BodyError>` object. Body updating might fail due to: - `BodyError::BodyNotSent`: The current HTTP Flow doesn’t have a body (for example, `GET` request). - `BodyError::ExceededBodySize`: The new body exceeds the maximum body buffer size supported by Envoy. ## Streaming Bodies > [!NOTE] To view an example policy that uses the streaming body state, see > [Stream Payload Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/stream-payload/README.md). To handle request or response bodies larger than 1MB, use the streaming body state. The streaming body state enables the body to be processed as chunks as data arrives. When using the streaming body state, you cannot write to the body. Using the stream body state doesn’t affect reading and writing headers To use the streaming body state, convert the `RequestState` or `ResponseState` into a body stream state by calling the `into_body_stream_state()` method and awaiting it: ```Rust let body_stream_state = request_state.into_body_stream_state().await; ``` After conversion, access the incoming chunks through the `stream()` method: ```Rust let mut stream = body_stream_state.stream(); while let Some(chunk) = stream.next().await { // Process each chunk as it arrives let chunk_bytes = chunk.into_bytes(); // ... process chunk_bytes ... } ``` > [!NOTE] For an example of chunk processing, see > [Stream Payload Policy Chunks](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/stream-payload/src/lib.rs#L30). If you need the complete body before processing the payload, use the `collect()` method to collect all chunks: ```Rust let collect = stream.collect().await; ``` > [!NOTE] For an example of how to collect and process full payloads, see > [Stream Payload Policy Collect](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/stream-payload/src/lib.rs#L54). ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Reading and Writing Request Headers and Bodies with Stop Iteration > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the Omni Gateway Policy Development Kit (PDK) `enable_stop_iteration` feature to simultaneously read and modify headers and body content. PDK Policies using stop iteration only supports payload bodies of up to 1MB. > [!NOTE] Only Omni Gateway version 1.12.0 or later support stop interation. ## Enable Stop Iteration in your Cargo.toml To enable this feature, add `enable_stop_iteration` to your `Cargo.toml` file dependencies: ```toml [dependencies] pdk = { version = "1.8.0", features = ["enable_stop_iteration"] } ``` ## Read and Write Request Headers After enabling the feature, use `into_headers_body_state()` to transition from the initial request or response state to the combined headers-body state: ```Rust use pdk::hl::*; async fn request_filter(request_state: RequestState) -> Flow<()> { // Transition to headers-body state let state = request_state.into_headers_body_state().await; // Access both headers and body through the unified handler state.handler().set_header("x-custom-header", "value"); if state.contains_body() { let _ = state.handler().set_body("modified body".as_bytes()); } Flow::Continue(()) } ``` The `into_headers_body_state()` method returns a `RequestHeadersBodyState` for request flows or `ResponseHeadersBodyState` for response flows. Both states provide a unified `handler()` that implements both `HeadersHandler` and `BodyHandler` traits: ```Rust pub trait Handler { fn headers(&self) -> Vec<(String, String)>; fn header(&self, name: &str) -> Option; fn add_header(&self, name: &str, value: &str); fn set_header(&self, name: &str, value: &str); fn set_headers(&self, headers: Vec<(&str, &str)>); fn remove_header(&self, name: &str); fn body(&self) -> Vec; fn set_body(&self, body: &[u8]) -> Result<(), BodyError>; fr contains_body(&self) -> Bool; } ``` ## Handle Requests Without Body When a request or response doesn’t contain a body, the headers-body state handler gracefully handles the absence: ```Rust async fn request_filter(request_state: RequestState) -> Flow<()> { let state = request_state.into_headers_body_state().await; // Check if body exists if state.contains_body() { let body = state.handler().body(); // Process body } // Attempting to set body on a request without body returns an error if let Err(BodyError::BodyNotSent) = state.handler().set_body("data".as_bytes()) { // Handle case where body cannot be set (e.g., GET request) state.handler().set_header("x-data", "data"); } Flow::Continue(()) } ``` ## Stop Iteration Configuration Examples PDK provides the [Stop Iteration Example policy](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.8.0/stop-iteration) to demonstrate how to use the headers-body unified state in Rust code. Within the example policy, see these code sections for additional configuration details: - [Transition to headers-body state and modify both headers and body in request filter](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.8.0/stop-iteration/src/lib.rs#L10-L40) - [Use headers-body state in response filters](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.8.0/stop-iteration/src/lib.rs#L42-L61) - [Handle body modification with error handling](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.8.0/stop-iteration/src/lib.rs#L25-L37) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Reading and Writing Request Headers and Bodies with Stop Iteration > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the Omni Gateway Policy Development Kit (PDK) `enable_stop_iteration` feature to simultaneously read and modify headers and body content. Use stop iteration to process the body before the headers are sent. Stop iteration doesn’t support streaming. Without stop iteration, a policy forwards the headers before the body. To learn more about the non-stop iteration event flow, see [Event Flow](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-headers-event#event-flow). Stop iteration is supported for Omni Gateway v1.11.4 and later. > [!NOTE] If the buffered body exceeds the `FLEX_DOWNSTREAM_CONNECTION_BUFFER_LIMIT_BYTES`, the > request is terminated with a `500` error code. ## Body Buffering and Size Limitations When a PDK policy transitions to the headers-body state with into\_headers\_body\_state(), Flex Gateway buffers the entire body for both the request and the response before your policy runs. The policy doesn’t receive the headers-body state until the full body has been buffered. The maximum body size that stop iteration can buffer is set by the `FLEX_DOWNSTREAM_CONNECTION_BUFFER_LIMIT_BYTES` environment variable (default 1MB). To configure the value, see [Configure Omni Gateway Environment Variables in Connected Mode](https://docs.mulesoft.com/gateway/latest/conn-env-variables) or [Configure Omni Gateway Environment Variables in Local Mode](https://docs.mulesoft.com/gateway/latest/local-env-variables). If a body exceeds `FLEX_DOWNSTREAM_CONNECTION_BUFFER_LIMIT_BYTES`, Envoy aborts the request before any policy code runs. Size the limit to your largest expected payload. ## Enable Stop Iteration in your Cargo.toml To enable this feature, add `enable_stop_iteration` to your `Cargo.toml` file dependencies: ```toml [dependencies] pdk = { version = "1.8.0", features = ["enable_stop_iteration"] } ``` ## Read and Write Request Headers After enabling the feature, use `into_headers_body_state()` to transition from the initial request or response state to the combined headers-body state: ```Rust use pdk::hl::*; async fn request_filter(request_state: RequestState) -> Flow<()> { // Transition to headers-body state let state = request_state.into_headers_body_state().await; // Access both headers and body through the unified handler state.handler().set_header("x-custom-header", "value"); if state.contains_body() { let _ = state.handler().set_body("modified body".as_bytes()); } Flow::Continue(()) } ``` The `into_headers_body_state()` method returns a `RequestHeadersBodyState` for request flows or `ResponseHeadersBodyState` for response flows. Both states provide a unified `handler()` that implements both `HeadersHandler` and `BodyHandler` traits: ```Rust pub trait Handler { fn headers(&self) -> Vec<(String, String)>; fn header(&self, name: &str) -> Option; fn add_header(&self, name: &str, value: &str); fn set_header(&self, name: &str, value: &str); fn set_headers(&self, headers: Vec<(&str, &str)>); fn remove_header(&self, name: &str); fn body(&self) -> Vec; fn set_body(&self, body: &[u8]) -> Result<(), BodyError>; fr contains_body(&self) -> Bool; } ``` ## Handle Requests Without Body When a request or response doesn’t contain a body, the headers-body state handler gracefully handles the absence: ```Rust async fn request_filter(request_state: RequestState) -> Flow<()> { let state = request_state.into_headers_body_state().await; // Check if body exists if state.contains_body() { let body = state.handler().body(); // Process body } // Attempting to set body on a request without body returns an error if let Err(BodyError::BodyNotSent) = state.handler().set_body("data".as_bytes()) { // Handle case where body cannot be set (e.g., GET request) state.handler().set_header("x-data", "data"); } Flow::Continue(()) } ``` ## Stop Iteration Configuration Examples PDK provides the [Stop Iteration Example policy](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.9.0/stop-iteration) to demonstrate how to use the headers-body unified state in Rust code. Within the example policy, see these code sections for additional configuration details: - [Transition to headers-body state and modify both headers and body in request filter](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.9.0/stop-iteration/src/lib.rs#L10-L40) - [Use headers-body state in response filters](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.9.0/stop-iteration/src/lib.rs#L42-L61) - [Handle body modification with error handling](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.9.0/stop-iteration/src/lib.rs#L25-L37) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Reading and Writing Request Headers and Bodies with Stop Iteration > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the Omni Gateway Policy Development Kit (PDK) `enable_stop_iteration` feature to simultaneously read and modify headers and body content. Use stop iteration to process the body before the headers are sent. Stop iteration doesn’t support streaming. Without stop iteration, a policy forwards the headers before the body. To learn more about the non-stop iteration event flow, see [Event Flow](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-headers-event#event-flow). Stop iteration is supported for Omni Gateway v1.11.4 and later. > [!NOTE] If the buffered body exceeds the `FLEX_DOWNSTREAM_CONNECTION_BUFFER_LIMIT_BYTES`, the > request is terminated with a `500` error code. ## Body Buffering and Size Limitations When a PDK policy transitions to the headers-body state with into\_headers\_body\_state(), Flex Gateway buffers the entire body for both the request and the response before your policy runs. The policy doesn’t receive the headers-body state until the full body has been buffered. The maximum body size that stop iteration can buffer is set by the `FLEX_DOWNSTREAM_CONNECTION_BUFFER_LIMIT_BYTES` environment variable (default 1MB). To configure the value, see [Configure Omni Gateway Environment Variables in Connected Mode](https://docs.mulesoft.com/gateway/latest/conn-env-variables) or [Configure Omni Gateway Environment Variables in Local Mode](https://docs.mulesoft.com/gateway/latest/local-env-variables). If a body exceeds `FLEX_DOWNSTREAM_CONNECTION_BUFFER_LIMIT_BYTES`, Envoy aborts the request before any policy code runs. Size the limit to your largest expected payload. ## Enable Stop Iteration in your Cargo.toml To enable this feature, add `enable_stop_iteration` to your `Cargo.toml` file dependencies: ```toml [dependencies] pdk = { version = "1.8.0", features = ["enable_stop_iteration"] } ``` ## Read and Write Request Headers After enabling the feature, use `into_headers_body_state()` to transition from the initial request or response state to the combined headers-body state: ```Rust use pdk::hl::*; async fn request_filter(request_state: RequestState) -> Flow<()> { // Transition to headers-body state let state = request_state.into_headers_body_state().await; // Access both headers and body through the unified handler state.handler().set_header("x-custom-header", "value"); if state.contains_body() { let _ = state.handler().set_body("modified body".as_bytes()); } Flow::Continue(()) } ``` The `into_headers_body_state()` method returns a `RequestHeadersBodyState` for request flows or `ResponseHeadersBodyState` for response flows. Both states provide a unified `handler()` that implements both `HeadersHandler` and `BodyHandler` traits: ```Rust pub trait Handler { fn headers(&self) -> Vec<(String, String)>; fn header(&self, name: &str) -> Option; fn add_header(&self, name: &str, value: &str); fn set_header(&self, name: &str, value: &str); fn set_headers(&self, headers: Vec<(&str, &str)>); fn remove_header(&self, name: &str); fn body(&self) -> Vec; fn set_body(&self, body: &[u8]) -> Result<(), BodyError>; fr contains_body(&self) -> Bool; } ``` ## Handle Requests Without Body When a request or response doesn’t contain a body, the headers-body state handler gracefully handles the absence: ```Rust async fn request_filter(request_state: RequestState) -> Flow<()> { let state = request_state.into_headers_body_state().await; // Check if body exists if state.contains_body() { let body = state.handler().body(); // Process body } // Attempting to set body on a request without body returns an error if let Err(BodyError::BodyNotSent) = state.handler().set_body("data".as_bytes()) { // Handle case where body cannot be set (e.g., GET request) state.handler().set_header("x-data", "data"); } Flow::Continue(()) } ``` ## Stop Iteration Configuration Examples PDK provides the [Stop Iteration Example policy](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.10.0/stop-iteration) to demonstrate how to use the headers-body unified state in Rust code. Within the example policy, see these code sections for additional configuration details: - [Transition to headers-body state and modify both headers and body in request filter](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.10.0/stop-iteration/src/lib.rs#L10-L40) - [Use headers-body state in response filters](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.10.0/stop-iteration/src/lib.rs#L42-L61) - [Handle body modification with error handling](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.10.0/stop-iteration/src/lib.rs#L25-L37) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Reporting Policy Violations > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] For an example of reporting policy violations, see > [Stream Payload Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/stream-payload/README.md). PDK provides functions to report a policy violation. Reported policy violations appear in Anypoint Monitoring. Only one policy violation can be active for a request at a time. When a new violation occurs, it overides any existing violation. If multiple policies generate violations for a single request, only one violation appears in Anypoint Monitoring. Reporting a policy violation doesn’t reject the request. To reject requests, see [Stopping Request Execution](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-stop). To view the current policy violation or generate a new policy violation, use these PDK functions: ```Rust /// Returns the existing policy violation of the current request. Returns None if no violation exists. pub fn policy_violation(&self) -> Option; /// Generates a new policy violation for the current request. If a violation was previously generated, the previous violation is overridden. pub fn generate_policy_violation(&self); /// Generates a new policy violation with the client application details for the current request. This overwrites any previous policy violations. pub fn generate_policy_violation_for_client_app, K: Into>( &self, client_name: T, client_id: K, ); ``` To retrieve information about the current policy violation, use these PDK functions: ```Rust /// The name of the policy that generated the violation pub fn get_policy_name(&self) -> &str; /// Client name associated with the violation, only available if a previous policy reported the client ID pub fn get_client_name(&self) -> Option<&str>; /// Client ID associated with the violation, only available if a previous policy reported the client ID pub fn get_client_id(&self) -> Option<&str>; ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Reporting Policy Violations > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] For an example of reporting policy violations, see > [Stream Payload Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/stream-payload/README.md). PDK provides functions to report a policy violation. Reported policy violations appear in Anypoint Monitoring. Only one policy violation can be active for a request at a time. When a new violation occurs, it overides any existing violation. If multiple policies generate violations for a single request, only one violation appears in Anypoint Monitoring. Reporting a policy violation doesn’t reject the request. To reject requests, see [Stopping Request Execution](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-stop). To view the current policy violation or generate a new policy violation, use these PDK functions: ```Rust /// Returns the existing policy violation of the current request. Returns None if no violation exists. pub fn policy_violation(&self) -> Option; /// Generates a new policy violation for the current request. If a violation was previously generated, the previous violation is overridden. pub fn generate_policy_violation(&self); /// Generates a new policy violation with the client application details for the current request. This overwrites any previous policy violations. pub fn generate_policy_violation_for_client_app, K: Into>( &self, client_name: T, client_id: K, ); ``` To retrieve information about the current policy violation, use these PDK functions: ```Rust /// The name of the policy that generated the violation pub fn get_policy_name(&self) -> &str; /// Client name associated with the violation, only available if a previous policy reported the client ID pub fn get_client_name(&self) -> Option<&str>; /// Client ID associated with the violation, only available if a previous policy reported the client ID pub fn get_client_id(&self) -> Option<&str>; ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Reporting Policy Violations > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] For an example of reporting policy violations, see > [Stream Payload Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/stream-payload/README.md). PDK provides functions to report a policy violation. Reported policy violations appear in Anypoint Monitoring. Only one policy violation can be active for a request at a time. When a new violation occurs, it overides any existing violation. If multiple policies generate violations for a single request, only one violation appears in Anypoint Monitoring. Reporting a policy violation doesn’t reject the request. To reject requests, see [Stopping Request Execution](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-stop). To view the current policy violation or generate a new policy violation, use these PDK functions: ```Rust /// Returns the existing policy violation of the current request. Returns None if no violation exists. pub fn policy_violation(&self) -> Option; /// Generates a new policy violation for the current request. If a violation was previously generated, the previous violation is overridden. pub fn generate_policy_violation(&self); /// Generates a new policy violation with the client application details for the current request. This overwrites any previous policy violations. pub fn generate_policy_violation_for_client_app, K: Into>( &self, client_name: T, client_id: K, ); ``` To retrieve information about the current policy violation, use these PDK functions: ```Rust /// The name of the policy that generated the violation pub fn get_policy_name(&self) -> &str; /// Client name associated with the violation, only available if a previous policy reported the client ID pub fn get_client_name(&self) -> Option<&str>; /// Client ID associated with the violation, only available if a previous policy reported the client ID pub fn get_client_id(&self) -> Option<&str>; ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Reporting Policy Violations > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] For an example of reporting policy violations, see > [Stream Payload Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/stream-payload/README.md). PDK provides functions to report a policy violation. Reported policy violations appear in Anypoint Monitoring. Only one policy violation can be active for a request at a time. When a new violation occurs, it overides any existing violation. If multiple policies generate violations for a single request, only one violation appears in Anypoint Monitoring. Reporting a policy violation doesn’t reject the request. To reject requests, see [Stopping Request and Response Execution](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-stop). To view the current policy violation or generate a new policy violation, use these PDK functions: ```Rust /// Returns the existing policy violation of the current request. Returns None if no violation exists. pub fn policy_violation(&self) -> Option; /// Generates a new policy violation for the current request. If a violation was previously generated, the previous violation is overridden. pub fn generate_policy_violation(&self); /// Generates a new policy violation with the client application details for the current request. This overwrites any previous policy violations. pub fn generate_policy_violation_for_client_app, K: Into>( &self, client_name: T, client_id: K, ); ``` To retrieve information about the current policy violation, use these PDK functions: ```Rust /// The name of the policy that generated the violation pub fn get_policy_name(&self) -> &str; /// Client name associated with the violation, only available if a previous policy reported the client ID pub fn get_client_name(&self) -> Option<&str>; /// Client ID associated with the violation, only available if a previous policy reported the client ID pub fn get_client_id(&self) -> Option<&str>; ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Reporting Policy Violations > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] For an example of reporting policy violations, see > [Stream Payload Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/stream-payload/README.md). PDK provides functions to report a policy violation. Reported policy violations appear in Anypoint Monitoring. Only one policy violation can be active for a request at a time. When a new violation occurs, it overides any existing violation. If multiple policies generate violations for a single request, only one violation appears in Anypoint Monitoring. Reporting a policy violation doesn’t reject the request. To reject requests, see [Stopping Request and Response Execution](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-stop). To view the current policy violation or generate a new policy violation, use these PDK functions: ```Rust /// Returns the existing policy violation of the current request. Returns None if no violation exists. pub fn policy_violation(&self) -> Option; /// Generates a new policy violation for the current request. If a violation was previously generated, the previous violation is overridden. pub fn generate_policy_violation(&self); /// Generates a new policy violation with the client application details for the current request. This overwrites any previous policy violations. pub fn generate_policy_violation_for_client_app, K: Into>( &self, client_name: T, client_id: K, ); ``` To retrieve information about the current policy violation, use these PDK functions: ```Rust /// The name of the policy that generated the violation pub fn get_policy_name(&self) -> &str; /// Client name associated with the violation, only available if a previous policy reported the client ID pub fn get_client_name(&self) -> Option<&str>; /// Client ID associated with the violation, only available if a previous policy reported the client ID pub fn get_client_id(&self) -> Option<&str>; ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Reporting Policy Violations > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] For an example of reporting policy violations, see > [Stream Payload Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/stream-payload/README.md). PDK provides functions to report a policy violation. Reported policy violations appear in Anypoint Monitoring. Only one policy violation can be active for a request at a time. When a new violation occurs, it overides any existing violation. If multiple policies generate violations for a single request, only one violation appears in Anypoint Monitoring. Reporting a policy violation doesn’t reject the request. To reject requests, see [Stopping Request and Response Execution](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-stop). To view the current policy violation or generate a new policy violation, use these PDK functions: ```Rust /// Returns the existing policy violation of the current request. Returns None if no violation exists. pub fn policy_violation(&self) -> Option; /// Generates a new policy violation for the current request. If a violation was previously generated, the previous violation is overridden. pub fn generate_policy_violation(&self); /// Generates a new policy violation with the client application details for the current request. This overwrites any previous policy violations. pub fn generate_policy_violation_for_client_app, K: Into>( &self, client_name: T, client_id: K, ); ``` To retrieve information about the current policy violation, use these PDK functions: ```Rust /// The name of the policy that generated the violation pub fn get_policy_name(&self) -> &str; /// Client name associated with the violation, only available if a previous policy reported the client ID pub fn get_client_name(&self) -> Option<&str>; /// Client ID associated with the violation, only available if a previous policy reported the client ID pub fn get_client_id(&self) -> Option<&str>; ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Reporting Policy Violations > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] For an example of reporting policy violations, see > [Stream Payload Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/stream-payload/README.md). PDK provides functions to report a policy violation. Reported policy violations appear in Anypoint Monitoring. Only one policy violation can be active for a request at a time. When a new violation occurs, it overides any existing violation. If multiple policies generate violations for a single request, only one violation appears in Anypoint Monitoring. Reporting a policy violation doesn’t reject the request. To reject requests, see [Stopping Request and Response Execution](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-stop). To view the current policy violation or generate a new policy violation, use these PDK functions: ```Rust /// Returns the existing policy violation of the current request. Returns None if no violation exists. pub fn policy_violation(&self) -> Option; /// Generates a new policy violation for the current request. If a violation was previously generated, the previous violation is overridden. pub fn generate_policy_violation(&self); /// Generates a new policy violation with the client application details for the current request. This overwrites any previous policy violations. pub fn generate_policy_violation_for_client_app, K: Into>( &self, client_name: T, client_id: K, ); ``` To retrieve information about the current policy violation, use these PDK functions: ```Rust /// The name of the policy that generated the violation pub fn get_policy_name(&self) -> &str; /// Client name associated with the violation, only available if a previous policy reported the client ID pub fn get_client_name(&self) -> Option<&str>; /// Client ID associated with the violation, only available if a previous policy reported the client ID pub fn get_client_id(&self) -> Option<&str>; ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Reviewing PDK Prerequisites > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To begin using Flex Gateway Policy Development Kit (PDK), ensure you have the following prerequisites installed. ## Flex Gateway PDK tutorials assume that you have [downloaded Flex Gateway](https://docs.mulesoft.com/gateway/latest/) and have some prior knowledge of the product. Policies created with PDK might be compatible with Omni Gateway versions that aren’t compatible with PDK’s integration testing framework. The Omni Gateway version used for testing doesn’t affect the functionality of the policy when deployed to a different Omni Gateway version. See the following table to ensure your Omni Gateway’s compatibility:
ComponentMinimum Omni Gateway VersionMaximum Omni Gateway Version

Policies

1.6.1

Latest

Testing Framework

1.6.1

Latest

## Rust Requirements for Using PDK 1. Git To download and install, see [Installing Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git). 2. Rust programming language version v1.74.0 to v1.83.0: 1. To install or update Rust, run the following curl command: ```ssh curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` > [!NOTE] If you do not have curl installed, see > [Install curl](https://curl.se/download.html). 2. Due to the `wasm32-wasi` compilation target used by the PDK being deprecated in Rust v1.84.0, downgrade Rust to the last compatible version: ```ssh rustup default 1.83.0 ``` 3. Rust WebAssembly System Interface (WASI) Crate To install or update Rust WASI, run the following command: ```ssh rustup target add wasm32-wasi ``` 4. Cargo Generate To install or update Cargo Generate, run the following command: ```ssh cargo install --locked cargo-generate ``` ## Supported Operating Systems - macOS - Ubuntu To use Ubuntu, execute the following commands to install the required packages after installing the [Rust Requirements for Using PDK](#rust-requirements): ```ssh sudo apt install -y build-essential sudo apt install -y pkg-config sudo apt install -y libssl-dev ``` - Windows > [!IMPORTANT] PDK supports Windows to develop and test you custom policy. However, Flex Gateway > does not support Windows in production environments. To execute the `make` commands included in PDK, install: 1. [PowerShell on Windows](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.3) 2. Make, with either: - [Make for Windows](https://gnuwin32.sourceforge.net/packages/make.htm) - Chocolatey: ```ssh choco install make ``` ## Anypoint CLI To configure the Anypoint CLI for PDK: 1. [Install Anypoint CLI 4.x v1.4.4 or later](https://docs.mulesoft.com/anypoint-cli/latest/install). > [!NOTE] To find your Anypoint CLI 4.x version, see > [Verify the Core Package Version](https://docs.mulesoft.com/anypoint-cli/latest/install#verify-installation). 2. [Authenticate to the Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/auth) using a [Connected App](https://docs.mulesoft.com/access-management/connected-apps-overview). Authenticate with a Connected App by providing the app’s client ID and client secret. > [!NOTE] In addition to the `View Organization` and `View Environment` scopes required to > authenticate to Anypoint Platform, to complete > [Uploading Custom Policies to Exchange](https://docs.mulesoft.com/pdk/1.2/policies-pdk-publish-policies), the Connected App must > have the `Exchange Contributor` scope applied. 3. Run the following command to install or update the Anypoint CLI PDK Plugin: ```ssh anypoint-cli-v4 plugins:install anypoint-cli-pdk-plugin ``` ## Docker Docker is required to use the [local debugging environment](https://docs.mulesoft.com/pdk/1.2/policies-pdk-debug-local) and the [integration testing framework](https://docs.mulesoft.com/pdk/1.2/policies-pdk-integration-tests) provided with PDK. You can still build and publish policies without docker. To install Docker, see [Install Docker](https://docs.docker.com/get-started/get-docker/). > [!IMPORTANT] You can run Flex Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Flex Gateway does not support Windows in production environments. ## Visual Studio (Suggested IDE) You can use PDK in any IDE or text editor, such as [Microsoft Visual Studio](https://code.visualstudio.com/) with the [Rust in Visual Studio Code Plugin](https://code.visualstudio.com/docs/languages/rust) installed. ## See Also - [Upgrading PDK](https://docs.mulesoft.com/pdk/1.2/policies-pdk-upgrade-pdk) - [Policy Development Kit Architecture Overview](https://docs.mulesoft.com/pdk/1.2/policies-pdk-architecture) - [Developing Custom Policies](https://docs.mulesoft.com/pdk/1.2/policies-pdk-develop-custom-policies) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Sharing Data Between Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The `StreamProperties` injectable provides an interface to: - Consume properties set by other policies that are processing the same request. - Broadcast properties so that the other policies can consume them. To share data, `StreamProperties` implements the `PropertyAccessor` trait: ```Rust pub trait PropertyAccessor { fn read_property(&self, path: &[&str]) -> Option; fn set_property(&self, path: &[&str], value: Option<&[u8]>); } ``` The following example shows a simple filter that reads a property from the stream and then writes another parameter to it: ```Rust async fn request_filter(stream: StreamProperties) -> Flow<()> { let incoming = String::from_utf8(stream.read_property(&["incoming_property"]).unwrap_or_default()).unwrap_or_default(); logger::info!("Recieved incoming prop {}", incoming); let outgoing = "outgoing".as_bytes(); stream.set_property(&["outgoing_property"], Some(outgoing)); Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher) -> Result<()> { let filter = on_request(|stream| request_filter(stream)); launcher.launch(filter).await?; Ok(()) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Sharing Data Between Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The `StreamProperties` injectable provides an interface to: - Consume properties set by other policies that are processing the same request. - Broadcast properties so that the other policies can consume them. To share data, `StreamProperties` implements the `PropertyAccessor` trait: ```Rust pub trait PropertyAccessor { fn read_property(&self, path: &[&str]) -> Option; fn set_property(&self, path: &[&str], value: Option<&[u8]>); } ``` The following example shows a simple filter that reads a property from the stream and then writes another parameter to it: ```Rust async fn request_filter(stream: StreamProperties) -> Flow<()> { let incoming = String::from_utf8(stream.read_property(&["incoming_property"]).unwrap_or_default()).unwrap_or_default(); logger::info!("Recieved incoming prop {}", incoming); let outgoing = "outgoing".as_bytes(); stream.set_property(&["outgoing_property"], Some(outgoing)); Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher) -> Result<()> { let filter = on_request(|stream| request_filter(stream)); launcher.launch(filter).await?; Ok(()) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Sharing Data Between Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The `StreamProperties` injectable provides an interface to: - Consume properties set by other policies that are processing the same request. - Broadcast properties so that the other policies can consume them. To share data, `StreamProperties` implements the `PropertyAccessor` trait: ```Rust pub trait PropertyAccessor { fn read_property(&self, path: &[&str]) -> Option; fn set_property(&self, path: &[&str], value: Option<&[u8]>); } ``` The following example shows a simple filter that reads a property from the stream and then writes another parameter to it: ```Rust async fn request_filter(stream: StreamProperties) -> Flow<()> { let incoming = String::from_utf8(stream.read_property(&["incoming_property"]).unwrap_or_default()).unwrap_or_default(); logger::info!("Recieved incoming prop {}", incoming); let outgoing = "outgoing".as_bytes(); stream.set_property(&["outgoing_property"], Some(outgoing)); Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher) -> Result<()> { let filter = on_request(|stream| request_filter(stream)); launcher.launch(filter).await?; Ok(()) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Sharing Data Between Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The `StreamProperties` injectable provides an interface to: - Consume properties set by other policies that are processing the same request. - Broadcast properties so that the other policies can consume them. To share data, `StreamProperties` implements the `PropertyAccessor` trait: ```Rust pub trait PropertyAccessor { fn read_property(&self, path: &[&str]) -> Option; fn set_property(&self, path: &[&str], value: Option<&[u8]>); } ``` The following example shows a simple filter that reads a property from the stream and then writes another parameter to it: ```Rust async fn request_filter(stream: StreamProperties) -> Flow<()> { let incoming = String::from_utf8(stream.read_property(&["incoming_property"]).unwrap_or_default()).unwrap_or_default(); logger::info!("Recieved incoming prop {}", incoming); let outgoing = "outgoing".as_bytes(); stream.set_property(&["outgoing_property"], Some(outgoing)); Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher) -> Result<()> { let filter = on_request(|stream| request_filter(stream)); launcher.launch(filter).await?; Ok(()) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Sharing Data Between Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The `StreamProperties` injectable provides an interface to: - Consume properties set by other policies that are processing the same request. - Broadcast properties so that the other policies can consume them. To share data, `StreamProperties` implements the `PropertyAccessor` trait: ```Rust pub trait PropertyAccessor { fn read_property(&self, path: &[&str]) -> Option; fn set_property(&self, path: &[&str], value: Option<&[u8]>); } ``` The following example shows a simple filter that reads a property from the stream and then writes another parameter to it: ```Rust async fn request_filter(stream: StreamProperties) -> Flow<()> { let incoming = String::from_utf8(stream.read_property(&["incoming_property"]).unwrap_or_default()).unwrap_or_default(); logger::info!("Recieved incoming prop {}", incoming); let outgoing = "outgoing".as_bytes(); stream.set_property(&["outgoing_property"], Some(outgoing)); Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher) -> Result<()> { let filter = on_request(|stream| request_filter(stream)); launcher.launch(filter).await?; Ok(()) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Sharing Data Between Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The `StreamProperties` injectable provides an interface to: - Consume properties set by other policies that are processing the same request. - Broadcast properties so that the other policies can consume them. To share data, `StreamProperties` implements the `PropertyAccessor` trait: ```Rust pub trait PropertyAccessor { fn read_property(&self, path: &[&str]) -> Option; fn set_property(&self, path: &[&str], value: Option<&[u8]>); } ``` The following example shows a simple filter that reads a property from the stream and then writes another parameter to it: ```Rust async fn request_filter(stream: StreamProperties) -> Flow<()> { let incoming = String::from_utf8(stream.read_property(&["incoming_property"]).unwrap_or_default()).unwrap_or_default(); logger::info!("Recieved incoming prop {}", incoming); let outgoing = "outgoing".as_bytes(); stream.set_property(&["outgoing_property"], Some(outgoing)); Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher) -> Result<()> { let filter = on_request(|stream| request_filter(stream)); launcher.launch(filter).await?; Ok(()) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Sharing Data Between Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The `StreamProperties` injectable provides an interface to: - Consume properties set by other policies that are processing the same request. - Broadcast properties so that the other policies can consume them. To share data, `StreamProperties` implements the `PropertyAccessor` trait: ```Rust pub trait PropertyAccessor { fn read_property(&self, path: &[&str]) -> Option; fn set_property(&self, path: &[&str], value: Option<&[u8]>); } ``` The following example shows a simple filter that reads a property from the stream and then writes another parameter to it: ```Rust async fn request_filter(stream: StreamProperties) -> Flow<()> { let incoming = String::from_utf8(stream.read_property(&["incoming_property"]).unwrap_or_default()).unwrap_or_default(); logger::info!("Recieved incoming prop {}", incoming); let outgoing = "outgoing".as_bytes(); stream.set_property(&["outgoing_property"], Some(outgoing)); Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher) -> Result<()> { let filter = on_request(|stream| request_filter(stream)); launcher.launch(filter).await?; Ok(()) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Sharing Data Between Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The `StreamProperties` injectable provides an interface to: - Consume properties set by other policies that are processing the same request. - Broadcast properties so that the other policies can consume them. To share data, `StreamProperties` implements the `PropertyAccessor` trait: ```Rust pub trait PropertyAccessor { fn read_property(&self, path: &[&str]) -> Option; fn set_property(&self, path: &[&str], value: Option<&[u8]>); } ``` The following example shows a simple filter that reads a property from the stream and then writes another parameter to it: ```Rust async fn request_filter(stream: StreamProperties) -> Flow<()> { let incoming = String::from_utf8(stream.read_property(&["incoming_property"]).unwrap_or_default()).unwrap_or_default(); logger::info!("Recieved incoming prop {}", incoming); let outgoing = "outgoing".as_bytes(); stream.set_property(&["outgoing_property"], Some(outgoing)); Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher) -> Result<()> { let filter = on_request(|stream| request_filter(stream)); launcher.launch(filter).await?; Ok(()) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Sharing Data Between Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt The `StreamProperties` injectable provides an interface to: - Consume properties set by other policies that are processing the same request. - Broadcast properties so that the other policies can consume them. To share data, `StreamProperties` implements the `PropertyAccessor` trait: ```Rust pub trait PropertyAccessor { fn read_property(&self, path: &[&str]) -> Option; fn set_property(&self, path: &[&str], value: Option<&[u8]>); } ``` The following example shows a simple filter that reads a property from the stream and then writes another parameter to it: ```Rust async fn request_filter(stream: StreamProperties) -> Flow<()> { let incoming = String::from_utf8(stream.read_property(&["incoming_property"]).unwrap_or_default()).unwrap_or_default(); logger::info!("Recieved incoming prop {}", incoming); let outgoing = "outgoing".as_bytes(); stream.set_property(&["outgoing_property"], Some(outgoing)); Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher) -> Result<()> { let filter = on_request(|stream| request_filter(stream)); launcher.launch(filter).await?; Ok(()) } ``` ## See Also - [Injecting Parameters](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-inject-parameters) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Sharing Data Between Requests and Responses > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides the `RequestData` enum to pass data between the request and the response. To share a status between the request and the response functions, the request function must return a `Flow::Continue` enum variant with a data parameter that you wish to pass to the response function. The response function must receive the `RequestData` parameter that contains the request function’s final status and the data parameter that was passed. The `RequestData` enum has the following possible final status: - `RequestData::Continue(data)`: The request function ended with `Flow::Continue(data)`. - `RequestData::Break` : The request function ended with `Flow::Break`. - `RequestData::Cancel`: The request function was [cancelled](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features#flow-cancellation). If the request function ended with a `Flow::Continue` and was not cancelled by upstream policies, the `RequestData::Continue` variant contains the value sent by the request function. Implement this by adding an `on_response` wrapped function to the `Flow` example used in [Stopping Request Execution](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-stop): ```Rust async fn request_filter(state: RequestState) -> Flow { let state = state.into_headers_state().await; let handler = state.handler(); if handler.header("authorization").is_some() { Flow::Continue(state.path()) } else { Flow::Break( Response::new(401) .with_headers(vec![( "WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string(), )]) .with_body(r#"{ "error": "token was not present"}"#), ) } } async fn response_filter(state: ResponseState, request_data: RequestData) { // Handle only completed requests if let RequestData::Continue(path) = request_data else { return; }; let state = state.into_headers_state().await; logger::info!("Path: {path}, Status: {}", state.status_code()); } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Sharing Data Between Requests and Responses > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides the `RequestData` enum to pass data between the request and the response. To share a status between the request and the response functions, the request function must return a `Flow::Continue` enum variant with a data parameter that you wish to pass to the response function. The response function must receive the `RequestData` parameter that contains the request function’s final status and the data parameter that was passed. The `RequestData` enum has the following possible final status: - `RequestData::Continue(data)`: The request function ended with `Flow::Continue(data)`. - `RequestData::Break` : The request function ended with `Flow::Break`. - `RequestData::Cancel`: The request function was [cancelled](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features#flow-cancellation). If the request function ended with a `Flow::Continue` and was not cancelled by upstream policies, the `RequestData::Continue` variant contains the value sent by the request function. Implement this by adding an `on_response` wrapped function to the `Flow` example used in [Stopping Request Execution](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-stop): ```Rust async fn request_filter(state: RequestState) -> Flow { let state = state.into_headers_state().await; let handler = state.handler(); if handler.header("authorization").is_some() { Flow::Continue(state.path()) } else { Flow::Break( Response::new(401) .with_headers(vec![( "WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string(), )]) .with_body(r#"{ "error": "token was not present"}"#), ) } } async fn response_filter(state: ResponseState, request_data: RequestData) { // Handle only completed requests if let RequestData::Continue(path) = request_data else { return; }; let state = state.into_headers_state().await; logger::info!("Path: {path}, Status: {}", state.status_code()); } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Sharing Data Between Requests and Responses > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides the `RequestData` enum to pass data between the request and the response. To share a status between the request and the response functions, the request function must return a `Flow::Continue` enum variant with a data parameter that you wish to pass to the response function. The response function must receive the `RequestData` parameter that contains the request function’s final status and the data parameter that was passed. The `RequestData` enum has the following possible final status: - `RequestData::Continue(data)`: The request function ended with `Flow::Continue(data)`. - `RequestData::Break` : The request function ended with `Flow::Break`. - `RequestData::Cancel`: The request function was [cancelled](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features#flow-cancellation). If the request function ended with a `Flow::Continue` and was not cancelled by upstream policies, the `RequestData::Continue` variant contains the value sent by the request function. Implement this by adding an `on_response` wrapped function to the `Flow` example used in [Stopping Request Execution](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-stop): ```Rust async fn request_filter(state: RequestState) -> Flow { let state = state.into_headers_state().await; let handler = state.handler(); if handler.header("authorization").is_some() { Flow::Continue(state.path()) } else { Flow::Break( Response::new(401) .with_headers(vec![( "WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string(), )]) .with_body(r#"{ "error": "token was not present"}"#), ) } } async fn response_filter(state: ResponseState, request_data: RequestData) { // Handle only completed requests if let RequestData::Continue(path) = request_data else { return; }; let state = state.into_headers_state().await; logger::info!("Path: {path}, Status: {}", state.status_code()); } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Sharing Data Between Requests and Responses > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides the `RequestData` enum to pass data between the request and the response. To share a status between the request and the response functions, the request function must return a `Flow::Continue` enum variant with a data parameter that you wish to pass to the response function. The response function must receive the `RequestData` parameter that contains the request function’s final status and the data parameter that was passed. The `RequestData` enum has the following possible final status: - `RequestData::Continue(data)`: The request function ended with `Flow::Continue(data)`. - `RequestData::Break` : The request function ended with `Flow::Break`. - `RequestData::Cancel`: The request function was [cancelled](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features#flow-cancellation). If the request function ended with a `Flow::Continue` and was not cancelled by upstream policies, the `RequestData::Continue` variant contains the value sent by the request function. Implement this by adding an `on_response` wrapped function to the `Flow` example used in [Stopping Request Execution](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-stop): ```Rust async fn request_filter(state: RequestState) -> Flow { let state = state.into_headers_state().await; let handler = state.handler(); if handler.header("authorization").is_some() { Flow::Continue(state.path()) } else { Flow::Break( Response::new(401) .with_headers(vec![( "WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string(), )]) .with_body(r#"{ "error": "token was not present"}"#), ) } } async fn response_filter(state: ResponseState, request_data: RequestData) { // Handle only completed requests if let RequestData::Continue(path) = request_data else { return; }; let state = state.into_headers_state().await; logger::info!("Path: {path}, Status: {}", state.status_code()); } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Sharing Data Between Requests and Responses > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides the `RequestData` enum to pass data between the request and the response. To share a status between the request and the response functions, the request function must return a `Flow::Continue` enum variant with a data parameter that you wish to pass to the response function. The response function must receive the `RequestData` parameter that contains the request function’s final status and the data parameter that was passed. The `RequestData` enum has the following possible final status: - `RequestData::Continue(data)`: The request function ended with `Flow::Continue(data)`. - `RequestData::Break` : The request function ended with `Flow::Break`. - `RequestData::Cancel`: The request function was [cancelled](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features#flow-cancellation). If the request function ended with a `Flow::Continue` and was not cancelled by upstream policies, the `RequestData::Continue` variant contains the value sent by the request function. Implement this by adding an `on_response` wrapped function to the `Flow` example used in [Stopping Request Execution](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-stop): ```Rust async fn request_filter(state: RequestState) -> Flow { let state = state.into_headers_state().await; let handler = state.handler(); if handler.header("authorization").is_some() { Flow::Continue(state.path()) } else { Flow::Break( Response::new(401) .with_headers(vec![( "WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string(), )]) .with_body(r#"{ "error": "token was not present"}"#), ) } } async fn response_filter(state: ResponseState, request_data: RequestData) { // Handle only completed requests if let RequestData::Continue(path) = request_data else { return; }; let state = state.into_headers_state().await; logger::info!("Path: {path}, Status: {}", state.status_code()); } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Sharing Data Between Requests and Responses > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides the `RequestData` enum to pass data between the request and the response. To share a status between the request and the response functions, the request function must return a `Flow::Continue` enum variant with a data parameter that you wish to pass to the response function. The response function must receive the `RequestData` parameter that contains the request function’s final status and the data parameter that was passed. The `RequestData` enum has the following possible final status: - `RequestData::Continue(data)`: The request function ended with `Flow::Continue(data)`. - `RequestData::Break` : The request function ended with `Flow::Break`. - `RequestData::Cancel`: The request function was [cancelled](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features#flow-cancellation). If the request function ended with a `Flow::Continue` and was not cancelled by upstream policies, the `RequestData::Continue` variant contains the value sent by the request function. Implement this by adding an `on_response` wrapped function to the `Flow` example used in [Stopping Request and Response Execution](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-stop): ```Rust async fn request_filter(state: RequestState) -> Flow { let state = state.into_headers_state().await; let handler = state.handler(); if handler.header("authorization").is_some() { Flow::Continue(state.path()) } else { Flow::Break( Response::new(401) .with_headers(vec![( "WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string(), )]) .with_body(r#"{ "error": "token was not present"}"#), ) } } async fn response_filter(state: ResponseState, request_data: RequestData) { // Handle only completed requests if let RequestData::Continue(path) = request_data else { return; }; let state = state.into_headers_state().await; logger::info!("Path: {path}, Status: {}", state.status_code()); } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Sharing Data Between Requests and Responses > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) provides the `RequestData` enum to pass data between the request and the response. To share a status between the request and the response functions, the request function must return a `Flow::Continue` enum variant with a data parameter that you wish to pass to the response function. The response function must receive the `RequestData` parameter that contains the request function’s final status and the data parameter that was passed. The `RequestData` enum has the following possible final status: - `RequestData::Continue(data)`: The request function ended with `Flow::Continue(data)`. - `RequestData::Break` : The request function ended with `Flow::Break`. - `RequestData::Cancel`: The request function was [cancelled](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features#flow-cancellation). If the request function ended with a `Flow::Continue` and was not cancelled by upstream policies, the `RequestData::Continue` variant contains the value sent by the request function. Implement this by adding an `on_response` wrapped function to the `Flow` example used in [Stopping Request and Response Execution](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-stop): ```Rust async fn request_filter(state: RequestState) -> Flow { let state = state.into_headers_state().await; let handler = state.handler(); if handler.header("authorization").is_some() { Flow::Continue(state.path()) } else { Flow::Break( Response::new(401) .with_headers(vec![( "WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string(), )]) .with_body(r#"{ "error": "token was not present"}"#), ) } } async fn response_filter(state: ResponseState, request_data: RequestData) { // Handle only completed requests if let RequestData::Continue(path) = request_data else { return; }; let state = state.into_headers_state().await; logger::info!("Path: {path}, Status: {}", state.status_code()); } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Sharing Data Between Requests and Responses > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) provides the `RequestData` enum to pass data between the request and the response. To share a status between the request and the response functions, the request function must return a `Flow::Continue` enum variant with a data parameter that you wish to pass to the response function. The response function must receive the `RequestData` parameter that contains the request function’s final status and the data parameter that was passed. The `RequestData` enum has the following possible final status: - `RequestData::Continue(data)`: The request function ended with `Flow::Continue(data)`. - `RequestData::Break` : The request function ended with `Flow::Break`. - `RequestData::Cancel`: The request function was [cancelled](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features#flow-cancellation). If the request function ended with a `Flow::Continue` and was not cancelled by upstream policies, the `RequestData::Continue` variant contains the value sent by the request function. Implement this by adding an `on_response` wrapped function to the `Flow` example used in [Stopping Request and Response Execution](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-stop): ```Rust async fn request_filter(state: RequestState) -> Flow { let state = state.into_headers_state().await; let handler = state.handler(); if handler.header("authorization").is_some() { Flow::Continue(state.path()) } else { Flow::Break( Response::new(401) .with_headers(vec![( "WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string(), )]) .with_body(r#"{ "error": "token was not present"}"#), ) } } async fn response_filter(state: ResponseState, request_data: RequestData) { // Handle only completed requests if let RequestData::Continue(path) = request_data else { return; }; let state = state.into_headers_state().await; logger::info!("Path: {path}, Status: {}", state.status_code()); } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Sharing Data Between Requests and Responses > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) provides the `RequestData` enum to pass data between the request and the response. To share a status between the request and the response functions, the request function must return a `Flow::Continue` enum variant with a data parameter that you wish to pass to the response function. The response function must receive the `RequestData` parameter that contains the request function’s final status and the data parameter that was passed. The `RequestData` enum has the following possible final status: - `RequestData::Continue(data)`: The request function ended with `Flow::Continue(data)`. - `RequestData::Break` : The request function ended with `Flow::Break`. - `RequestData::Cancel`: The request function was [cancelled](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features#flow-cancellation). If the request function ended with a `Flow::Continue` and was not cancelled by upstream policies, the `RequestData::Continue` variant contains the value sent by the request function. Implement this by adding an `on_response` wrapped function to the `Flow` example used in [Stopping Request and Response Execution](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-stop): ```Rust async fn request_filter(state: RequestState) -> Flow { let state = state.into_headers_state().await; let handler = state.handler(); if handler.header("authorization").is_some() { Flow::Continue(state.path()) } else { Flow::Break( Response::new(401) .with_headers(vec![( "WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string(), )]) .with_body(r#"{ "error": "token was not present"}"#), ) } } async fn response_filter(state: ResponseState, request_data: RequestData) { // Handle only completed requests if let RequestData::Continue(path) = request_data else { return; }; let state = state.into_headers_state().await; logger::info!("Path: {path}, Status: {}", state.status_code()); } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Sharing Data Between Workers and Configuring Caching > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses caching, see > [Data Caching Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/data-caching/README.md). Envoy spawns many workers to increase the policy’s capability of handling requests. A single worker handles all the stages of a specific request, including outgoing connections and the response flow. This enables you to track internal status for a specific request, and to create a sequential execution flow despite the underlying event-driven implementation. Each worker processes a single request at a given time. To share a global state in a specific worker, use a `RefCell` without any risk of concurrent modification. Use the provided `Cache` mechanism to create a shared global state for all workers. After injecting the cache builder, provide an ID for the cache and the maximum number of elements the cache can support. The following example configures a cache that can hold ten elements: ```Rust #[entrypoint] async fn configure( launcher: Launcher, cache_builder: CacheBuilder, ) -> Result<()> { let cache = cache_builder.new(String::from("caching")).max_entries(10); ... ``` The cache has the following interface: ```Rust pub trait Cache { fn save(&self, key: &str, value: Vec) -> Result<(), CacheError>; fn get(&self, key: &str) -> Option>; fn delete(&self, key: &str) -> Option>; fn purge(&self); } ``` > [!IMPORTANT] Because different workers write to the cache concurrently, there is no guarantee that > the value overwritten when saving the cache is the same as when it was retrieved. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Sharing Data Between Workers and Configuring Caching > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses caching, see > [Data Caching Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/data-caching/README.md). Envoy spawns many workers to increase the policy’s capability of handling requests. A single worker handles all the stages of a specific request, including outgoing connections and the response flow. This enables you to track internal status for a specific request, and to create a sequential execution flow despite the underlying event-driven implementation. Each worker processes a single request at a given time. To share a global state in a specific worker, use a `RefCell` without any risk of concurrent modification. Use the provided `Cache` mechanism to create a shared global state for all workers. After injecting the cache builder, provide an ID for the cache and the maximum number of elements the cache can support. The following example configures a cache that can hold ten elements: ```Rust #[entrypoint] async fn configure( launcher: Launcher, cache_builder: CacheBuilder, ) -> Result<()> { let cache = cache_builder.new(String::from("caching")).max_entries(10); ... ``` The cache has the following interface: ```Rust pub trait Cache { fn save(&self, key: &str, value: Vec) -> Result<(), CacheError>; fn get(&self, key: &str) -> Option>; fn delete(&self, key: &str) -> Option>; fn purge(&self); } ``` > [!IMPORTANT] Because different workers write to the cache concurrently, there is no guarantee that > the value overwritten when saving the cache is the same as when it was retrieved. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Sharing Data Between Workers and Configuring Caching > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses caching, see > [Data Caching Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/data-caching/README.md). Envoy spawns many workers to increase the policy’s capability of handling requests. A single worker handles all the stages of a specific request, including outgoing connections and the response flow. This enables you to track internal status for a specific request, and to create a sequential execution flow despite the underlying event-driven implementation. Each worker processes a single request at a given time. To share a global state in a specific worker, use a `RefCell` without any risk of concurrent modification. Use the provided `Cache` mechanism to create a shared global state for all workers. After injecting the cache builder, provide an ID for the cache and the maximum number of elements the cache can support. The following example configures a cache that can hold ten elements: ```Rust #[entrypoint] async fn configure( launcher: Launcher, cache_builder: CacheBuilder, ) -> Result<()> { let cache = cache_builder.new(String::from("caching")).max_entries(10); ... ``` The cache has the following interface: ```Rust pub trait Cache { fn save(&self, key: &str, value: Vec) -> Result<(), CacheError>; fn get(&self, key: &str) -> Option>; fn delete(&self, key: &str) -> Option>; fn purge(&self); } ``` > [!IMPORTANT] Because different workers write to the cache concurrently, there is no guarantee that > the value overwritten when saving the cache is the same as when it was retrieved. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Sharing Data Between Workers and Configuring Caching > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses caching, see > [Data Caching Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/data-caching/README.md). Envoy spawns many workers to increase the policy’s capability of handling requests. A single worker handles all the stages of a specific request, including outgoing connections and the response flow. This enables you to track internal status for a specific request, and to create a sequential execution flow despite the underlying event-driven implementation. Each worker processes a single request at a given time. To share a global state in a specific worker, use a `RefCell` without any risk of concurrent modification. Use the provided `Cache` mechanism to create a shared global state for all workers. After injecting the cache builder, provide an ID for the cache and the maximum number of elements the cache can support. The following example configures a cache that can hold ten elements: ```Rust #[entrypoint] async fn configure( launcher: Launcher, cache_builder: CacheBuilder, ) -> Result<()> { let cache = cache_builder.new(String::from("caching")).max_entries(10); ... ``` The cache has the following interface: ```Rust pub trait Cache { fn save(&self, key: &str, value: Vec) -> Result<(), CacheError>; fn get(&self, key: &str) -> Option>; fn delete(&self, key: &str) -> Option>; fn purge(&self); } ``` > [!IMPORTANT] Because different workers write to the cache concurrently, there is no guarantee that > the value overwritten when saving the cache is the same as when it was retrieved. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Sharing Data Between Workers and Configuring Caching > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses caching, see > [Data Caching Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/data-caching/README.md). Envoy spawns many workers to increase the policy’s capability of handling requests. A single worker handles all the stages of a specific request, including outgoing connections and the response flow. This enables you to track internal status for a specific request, and to create a sequential execution flow despite the underlying event-driven implementation. Each worker processes a single request at a given time. To share a global state in a specific worker, use a `RefCell` without any risk of concurrent modification. Use the provided `Cache` mechanism to create a shared global state for all workers. After injecting the cache builder, provide an ID for the cache and the maximum number of elements the cache can support. The following example configures a cache that can hold ten elements: ```Rust #[entrypoint] async fn configure( launcher: Launcher, cache_builder: CacheBuilder, ) -> Result<()> { let cache = cache_builder.new(String::from("caching")).max_entries(10); ... ``` The cache has the following interface: ```Rust pub trait Cache { fn save(&self, key: &str, value: Vec) -> Result<(), CacheError>; fn get(&self, key: &str) -> Option>; fn delete(&self, key: &str) -> Option>; fn purge(&self); } ``` > [!IMPORTANT] Because different workers write to the cache concurrently, there is no guarantee that > the value overwritten when saving the cache is the same as when it was retrieved. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Sharing Data Between Workers and Configuring Caching > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses caching, see > [Data Caching Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/data-caching/README.md). Envoy spawns many workers to increase the policy’s capability of handling requests. A single worker handles all the stages of a specific request, including outgoing connections and the response flow. This enables you to track internal status for a specific request, and to create a sequential execution flow despite the underlying event-driven implementation. Each worker processes a single request at a given time. To share a global state in a specific worker, use a `RefCell` without any risk of concurrent modification. Use the provided `Cache` mechanism to create a shared global state for all workers. After injecting the cache builder, provide an ID for the cache and the maximum number of elements the cache can support. The following example configures a cache that can hold ten elements: ```Rust #[entrypoint] async fn configure( launcher: Launcher, cache_builder: CacheBuilder, ) -> Result<()> { let cache = cache_builder.new(String::from("caching")).max_entries(10); ... ``` The cache has the following interface: ```Rust pub trait Cache { fn save(&self, key: &str, value: Vec) -> Result<(), CacheError>; fn get(&self, key: &str) -> Option>; fn delete(&self, key: &str) -> Option>; fn purge(&self); } ``` > [!IMPORTANT] Because different workers write to the cache concurrently, there is no guarantee that > the value overwritten when saving the cache is the same as when it was retrieved. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Sharing Data Between Workers and Configuring Caching > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses caching, see > [Data Caching Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/data-caching/README.md). Envoy spawns many workers to increase the policy’s capability of handling requests. A single worker handles all the stages of a specific request, including outgoing connections and the response flow. This enables you to track internal status for a specific request, and to create a sequential execution flow despite the underlying event-driven implementation. Each worker processes a single request at a given time. To share a global state in a specific worker, use a `RefCell` without any risk of concurrent modification. Use the provided `Cache` mechanism to create a shared global state for all workers. After injecting the cache builder, provide an ID for the cache and the maximum number of elements the cache can support. The following example configures a cache that can hold ten elements: ```Rust #[entrypoint] async fn configure( launcher: Launcher, cache_builder: CacheBuilder, ) -> Result<()> { let cache = cache_builder.new(String::from("caching")).max_entries(10); ... ``` The cache has the following interface: ```Rust pub trait Cache { fn save(&self, key: &str, value: Vec) -> Result<(), CacheError>; fn get(&self, key: &str) -> Option>; fn delete(&self, key: &str) -> Option>; fn purge(&self); } ``` > [!IMPORTANT] Because different workers write to the cache concurrently, there is no guarantee that > the value overwritten when saving the cache is the same as when it was retrieved. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Sharing Data Between Workers and Configuring Caching > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses caching, see > [Data Caching Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/data-caching/README.md). Envoy spawns many workers to increase the policy’s capability of handling requests. A single worker handles all the stages of a specific request, including outgoing connections and the response flow. This enables you to track internal status for a specific request, and to create a sequential execution flow despite the underlying event-driven implementation. Each worker processes a single request at a given time. To share a global state in a specific worker, use a `RefCell` without any risk of concurrent modification. Use the provided `Cache` mechanism to create a shared global state for all workers. After injecting the cache builder, provide an ID for the cache and the maximum number of elements the cache can support. The following example configures a cache that can hold ten elements: ```Rust #[entrypoint] async fn configure( launcher: Launcher, cache_builder: CacheBuilder, ) -> Result<()> { let cache = cache_builder.new(String::from("caching")).max_entries(10); ... ``` The cache has the following interface: ```Rust pub trait Cache { fn save(&self, key: &str, value: Vec) -> Result<(), CacheError>; fn get(&self, key: &str) -> Option>; fn delete(&self, key: &str) -> Option>; fn purge(&self); } ``` > [!IMPORTANT] Because different workers write to the cache concurrently, there is no guarantee that > the value overwritten when saving the cache is the same as when it was retrieved. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Sharing Data Between Workers and Configuring Caching > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses caching, see > [Data Caching Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/data-caching/README.md). Envoy spawns many workers to increase the policy’s capability of handling requests. A single worker handles all the stages of a specific request, including outgoing connections and the response flow. This enables you to track internal status for a specific request, and to create a sequential execution flow despite the underlying event-driven implementation. Each worker processes a single request at a given time. To share a global state in a specific worker, use a `RefCell` without any risk of concurrent modification. Use the provided `Cache` mechanism to create a shared global state for all workers. After injecting the cache builder, provide an ID for the cache and the maximum number of elements the cache can support. The following example configures a cache that can hold ten elements: ```Rust #[entrypoint] async fn configure( launcher: Launcher, cache_builder: CacheBuilder, ) -> Result<()> { let cache = cache_builder.new(String::from("caching")).max_entries(10); ... ``` The cache has the following interface: ```Rust pub trait Cache { fn save(&self, key: &str, value: Vec) -> Result<(), CacheError>; fn get(&self, key: &str) -> Option>; fn delete(&self, key: &str) -> Option>; fn purge(&self); } ``` > [!IMPORTANT] Because different workers write to the cache concurrently, there is no guarantee that > the value overwritten when saving the cache is the same as when it was retrieved. ## Configure a Cache Eviction Strategy The cache builder supports selecting between the first-in first-out (FIFO) and Least Recently Used (LRU) eviction strategies. By default, the cache uses the FIFO strategy. To select the LRU strategy, use the `eviction_strategy` method on the cache builder and provide the strategy configuration: ```Rust // The LRU cache shards its state, and eviction happens per-shard, so LRU // ordering is only approximate across shards. This code snippet uses // a single shard for true global LRU ordering deterministically. let single_shard_lru = LruStrategy::default().with_shards(1); let demo_lru = cache_builder .new("lru-cache".to_string()) .eviction_strategy(EvictionStrategy::Lru(single_shard_lru)) .ttl(Duration::from_millis(10000)) .max_entries(2); ``` ## Configure a Cache TTL To configure a time-to-live (TTL) for cache entries, use the cache builder `ttl` to set a global TTL for all cache entries: ```Rust let cache = cache_builder .new("caching".to_string()) .ttl(Duration::from_millis(10000)) .max_entries(10); ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Stopping Request and Response Execution > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) enables you to send early responses during the request and response execution to terminate the execution flow. To intercept and stop a request or response, return a `Response` object from your `on_request` or `on_response` wrapped functions: ```Rust Response::new(401) .with_headers(vec![("WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string())]) .with_body(r#"{ "error": "token was not present"}"#) ``` To return the \`Response\`object, see: - [Stop Request Execution](#stop-request-execution) - [Stop Response Execution](#stop-response-execution) ## Stop Request Execution Block or allow requests to reach the upstream service using a `Flow`. A `Flow` in an `enum` value with two possible values: - `Continue`: Defines an object that is forwarded to the response. - `Break`: Aborts the request and returns the provided response. Create a `Flow` as follows: ```Rust async fn request_filter(request_state: RequestState) -> Flow<()> { let header_state = request_state.into_headers_state().await; let handler = header_state.handler(); if handler.header("authorization").is_some() { Flow::Continue(()) } else { Flow::Break(Response::new(401) .with_headers(vec![("WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string())]) .with_body(r#"{ "error": "token was not present"}"#)) } } ``` > [!IMPORTANT] Due to the streaming nature of `proxy wasm`, it is possible for an early request to > partially reach the upstream service while awaiting the `headers_state.into_body_state` function. > Avoid this is by not awaiting the body. However, this is not possible for all policies. Configure > your upstream to ignore partial requests if the policy must read the body. > > To avoid early responses reaching the client, see > [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-share-data). ## Stop Response Execution To send an early response during the `on_response` phase, return a `Response` object using the `send_response` method of the `ResponseHeadersState`. You can’t send an early response from the body state: ```Rust pub fn send_response(self, response: Response) { ``` The `send_response` method enables you to add a body to responses that don’t already have one. Sending an early response using the `send_response` method terminates the execution flow. You can’t perform any other operation after sending an early response: ```Rust async fn response_filter(state: ResponseState) { let state = state.into_headers_state().await; state.send_response( Response::new(200) .with_headers(vec![("some".to_string(), "200".to_string())]) .with_body("Some"), ); } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Stopping Request and Response Execution > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) enables you to send early responses during the request and response execution to terminate the execution flow. To intercept and stop a request or response, return a `Response` object from your `on_request` or `on_response` wrapped functions: ```Rust Response::new(401) .with_headers(vec![("WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string())]) .with_body(r#"{ "error": "token was not present"}"#) ``` To return the \`Response\`object, see: - [Stop Request Execution](#stop-request-execution) - [Stop Response Execution](#stop-response-execution) ## Stop Request Execution Block or allow requests to reach the upstream service using a `Flow`. A `Flow` in an `enum` value with two possible values: - `Continue`: Defines an object that is forwarded to the response. - `Break`: Aborts the request and returns the provided response. Create a `Flow` as follows: ```Rust async fn request_filter(request_state: RequestState) -> Flow<()> { let header_state = request_state.into_headers_state().await; let handler = header_state.handler(); if handler.header("authorization").is_some() { Flow::Continue(()) } else { Flow::Break(Response::new(401) .with_headers(vec![("WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string())]) .with_body(r#"{ "error": "token was not present"}"#)) } } ``` > [!IMPORTANT] Due to the streaming nature of `proxy wasm`, it is possible for an early request to > partially reach the upstream service while awaiting the `headers_state.into_body_state` function. > Avoid this is by not awaiting the body. However, this is not possible for all policies. Configure > your upstream to ignore partial requests if the policy must read the body. > > To avoid early responses reaching the client, see > [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-share-data). ## Stop Response Execution To send an early response during the `on_response` phase, return a `Response` object using the `send_response` method of the `ResponseHeadersState`. You can’t send an early response from the body state: ```Rust pub fn send_response(self, response: Response) { ``` The `send_response` method enables you to add a body to responses that don’t already have one. Sending an early response using the `send_response` method terminates the execution flow. You can’t perform any other operation after sending an early response: ```Rust async fn response_filter(state: ResponseState) { let state = state.into_headers_state().await; state.send_response( Response::new(200) .with_headers(vec![("some".to_string(), "200".to_string())]) .with_body("Some"), ); } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Stopping Request and Response Execution > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) enables you to send early responses during the request and response execution to terminate the execution flow. To intercept and stop a request or response, return a `Response` object from your `on_request` or `on_response` wrapped functions: ```Rust Response::new(401) .with_headers(vec![("WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string())]) .with_body(r#"{ "error": "token was not present"}"#) ``` To return the \`Response\`object, see: - [Stop Request Execution](#stop-request-execution) - [Stop Response Execution](#stop-response-execution) ## Stop Request Execution Block or allow requests to reach the upstream service using a `Flow`. A `Flow` in an `enum` value with two possible values: - `Continue`: Defines an object that is forwarded to the response. - `Break`: Aborts the request and returns the provided response. Create a `Flow` as follows: ```Rust async fn request_filter(request_state: RequestState) -> Flow<()> { let header_state = request_state.into_headers_state().await; let handler = header_state.handler(); if handler.header("authorization").is_some() { Flow::Continue(()) } else { Flow::Break(Response::new(401) .with_headers(vec![("WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string())]) .with_body(r#"{ "error": "token was not present"}"#)) } } ``` > [!IMPORTANT] Due to the streaming nature of `proxy wasm`, it is possible for an early request to > partially reach the upstream service while awaiting the `headers_state.into_body_state` function. > Avoid this is by not awaiting the body. However, this is not possible for all policies. Configure > your upstream to ignore partial requests if the policy must read the body. > > To avoid early responses reaching the client, see > [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-share-data). ## Stop Response Execution To send an early response during the `on_response` phase, return a `Response` object using the `send_response` method of the `ResponseHeadersState`. You can’t send an early response from the body state: ```Rust pub fn send_response(self, response: Response) { ``` The `send_response` method enables you to add a body to responses that don’t already have one. Sending an early response using the `send_response` method terminates the execution flow. You can’t perform any other operation after sending an early response: ```Rust async fn response_filter(state: ResponseState) { let state = state.into_headers_state().await; state.send_response( Response::new(200) .with_headers(vec![("some".to_string(), "200".to_string())]) .with_body("Some"), ); } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Stopping Request and Response Execution > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) enables you to send early responses during the request and response execution to terminate the execution flow. To intercept and stop a request or response, return a `Response` object from your `on_request` or `on_response` wrapped functions: ```Rust Response::new(401) .with_headers(vec![("WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string())]) .with_body(r#"{ "error": "token was not present"}"#) ``` To return the \`Response\`object, see: - [Stop Request Execution](#stop-request-execution) - [Stop Response Execution](#stop-response-execution) ## Stop Request Execution Block or allow requests to reach the upstream service using a `Flow`. A `Flow` in an `enum` value with two possible values: - `Continue`: Defines an object that is forwarded to the response. - `Break`: Aborts the request and returns the provided response. Create a `Flow` as follows: ```Rust async fn request_filter(request_state: RequestState) -> Flow<()> { let header_state = request_state.into_headers_state().await; let handler = header_state.handler(); if handler.header("authorization").is_some() { Flow::Continue(()) } else { Flow::Break(Response::new(401) .with_headers(vec![("WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string())]) .with_body(r#"{ "error": "token was not present"}"#)) } } ``` > [!IMPORTANT] Due to the streaming nature of `proxy wasm`, it is possible for an early request to > partially reach the upstream service while awaiting the `headers_state.into_body_state` function. > Avoid this is by not awaiting the body. However, this is not possible for all policies. Configure > your upstream to ignore partial requests if the policy must read the body. > > To avoid early responses reaching the client, see > [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-share-data). ## Stop Response Execution To send an early response during the `on_response` phase, return a `Response` object using the `send_response` method of the `ResponseHeadersState`. You can’t send an early response from the body state: ```Rust pub fn send_response(self, response: Response) { ``` The `send_response` method enables you to add a body to responses that don’t already have one. Sending an early response using the `send_response` method terminates the execution flow. You can’t perform any other operation after sending an early response: ```Rust async fn response_filter(state: ResponseState) { let state = state.into_headers_state().await; state.send_response( Response::new(200) .with_headers(vec![("some".to_string(), "200".to_string())]) .with_body("Some"), ); } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Stopping Request Execution > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To intercept and stop a request, return a `Response` object from your `on_request` wrapped functions: ```Rust Response::new(401) .with_headers(vec![("WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string())]) .with_body(r#"{ "error": "token was not present"}"#) ``` You can block or allow requests to reach the upstream service using a `Flow`. A `Flow` in an `enum` value with two possible values: - `Continue`: Defines an object that is forwarded to the response. - `Break`: Aborts the request and returns the provided response. Create a `Flow` as follows: ```Rust async fn request_filter(request_state: RequestState) -> Flow<()> { let header_state = request_state.into_headers_state().await; let handler = header_state.handler(); if handler.header("authorization").is_some() { Flow::Continue(()) } else { Flow::Break(Response::new(401) .with_headers(vec![("WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string())]) .with_body(r#"{ "error": "token was not present"}"#)) } } ``` > [!IMPORTANT] Due to the streaming nature of `proxy wasm`, it is possible for an early request to > partially reach the upstream service while awaiting the `headers_state.into_body_state` function. > Avoid this is by not awaiting the body. However, this is not possible for all policies. Configure > your upstream to ignore partial requests if the policy must read the body. > > To avoid early responses reaching the client, see > [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-share-data). ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Stopping Request Execution > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To intercept and stop a request, return a `Response` object from your `on_request` wrapped functions: ```Rust Response::new(401) .with_headers(vec![("WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string())]) .with_body(r#"{ "error": "token was not present"}"#) ``` You can block or allow requests to reach the upstream service using a `Flow`. A `Flow` in an `enum` value with two possible values: - `Continue`: Defines an object that is forwarded to the response. - `Break`: Aborts the request and returns the provided response. Create a `Flow` as follows: ```Rust async fn request_filter(request_state: RequestState) -> Flow<()> { let header_state = request_state.into_headers_state().await; let handler = header_state.handler(); if handler.header("authorization").is_some() { Flow::Continue(()) } else { Flow::Break(Response::new(401) .with_headers(vec![("WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string())]) .with_body(r#"{ "error": "token was not present"}"#)) } } ``` > [!IMPORTANT] Due to the streaming nature of `proxy wasm`, it is possible for an early request to > partially reach the upstream service while awaiting the `headers_state.into_body_state` function. > Avoid this is by not awaiting the body. However, this is not possible for all policies. Configure > your upstream to ignore partial requests if the policy must read the body. > > To avoid early responses reaching the client, see > [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-share-data). ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Stopping Request Execution > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To intercept and stop a request, return a `Response` object from your `on_request` wrapped functions: ```Rust Response::new(401) .with_headers(vec![("WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string())]) .with_body(r#"{ "error": "token was not present"}"#) ``` You can block or allow requests to reach the upstream service using a `Flow`. A `Flow` in an `enum` value with two possible values: - `Continue`: Defines an object that is forwarded to the response. - `Break`: Aborts the request and returns the provided response. Create a `Flow` as follows: ```Rust async fn request_filter(request_state: RequestState) -> Flow<()> { let header_state = request_state.into_headers_state().await; let handler = header_state.handler(); if handler.header("authorization").is_some() { Flow::Continue(()) } else { Flow::Break(Response::new(401) .with_headers(vec![("WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string())]) .with_body(r#"{ "error": "token was not present"}"#)) } } ``` > [!IMPORTANT] Due to the streaming nature of `proxy wasm`, it is possible for an early request to > partially reach the upstream service while awaiting the `headers_state.into_body_state` function. > Avoid this is by not awaiting the body. However, this is not possible for all policies. Configure > your upstream to ignore partial requests if the policy must read the body. > > To avoid early responses reaching the client, see > [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-share-data). ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Stopping Request Execution > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To intercept and stop a request, return a `Response` object from your `on_request` wrapped functions: ```Rust Response::new(401) .with_headers(vec![("WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string())]) .with_body(r#"{ "error": "token was not present"}"#) ``` You can block or allow requests to reach the upstream service using a `Flow`. A `Flow` in an `enum` value with two possible values: - `Continue`: Defines an object that is forwarded to the response. - `Break`: Aborts the request and returns the provided response. Create a `Flow` as follows: ```Rust async fn request_filter(request_state: RequestState) -> Flow<()> { let header_state = request_state.into_headers_state().await; let handler = header_state.handler(); if handler.header("authorization").is_some() { Flow::Continue(()) } else { Flow::Break(Response::new(401) .with_headers(vec![("WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string())]) .with_body(r#"{ "error": "token was not present"}"#)) } } ``` > [!IMPORTANT] Due to the streaming nature of `proxy wasm`, it is possible for an early request to > partially reach the upstream service while awaiting the `headers_state.into_body_state` function. > Avoid this is by not awaiting the body. However, this is not possible for all policies. Configure > your upstream to ignore partial requests if the policy must read the body. > > To avoid early responses reaching the client, see > [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-share-data). ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Stopping Request Execution > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To intercept and stop a request, return a `Response` object from your `on_request` wrapped functions: ```Rust Response::new(401) .with_headers(vec![("WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string())]) .with_body(r#"{ "error": "token was not present"}"#) ``` You can block or allow requests to reach the upstream service using a `Flow`. A `Flow` in an `enum` value with two possible values: - `Continue`: Defines an object that is forwarded to the response. - `Break`: Aborts the request and returns the provided response. Create a `Flow` as follows: ```Rust async fn request_filter(request_state: RequestState) -> Flow<()> { let header_state = request_state.into_headers_state().await; let handler = header_state.handler(); if handler.header("authorization").is_some() { Flow::Continue(()) } else { Flow::Break(Response::new(401) .with_headers(vec![("WWW-Authenticate".to_string(), "Bearer realm=\"oauth2\"".to_string())]) .with_body(r#"{ "error": "token was not present"}"#)) } } ``` > [!IMPORTANT] Due to the streaming nature of `proxy wasm`, it is possible for an early request to > partially reach the upstream service while awaiting the `headers_state.into_body_state` function. > Avoid this is by not awaiting the body. However, this is not possible for all policies. Configure > your upstream to ignore partial requests if the policy must read the body. > > To avoid early responses reaching the client, see > [Sharing Data Between Requests and Responses](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-share-data). ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Support WebSocket APIs > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)'s > WebSocket library, see > [WebSocket Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/websocket/README.md). Use the Omni Gateway Policy Development Kit (PDK) WebSocket library to implement custom policies that support WebSocket APIs. ## Enable WebSocket Support To enable WebSocket functionality, add the `experimental_websocket` feature at the PDK dependency in your `Cargo.toml` file: ```toml [dependencies] pdk = { version = "1.9.0", features = ["experimental_websocket"]} ``` ## Configure WebSocket Handlers To access WebSocket functionality, use the `FilterBuilder` with `on_upgrade_upstream` and `on_upgrade_downstream` handlers: ```rust use pdk::hl::*; use pdk::websockets::{Decoder, Encoder, Frame, FrameType}; pub async fn configure(launcher: Launcher) -> Result<()> { let handler = FilterBuilder::new() .on_create(|| YourPolicyState {}) .on_request(|_req: RequestState| async move { Flow::Continue(()) }) .on_upgrade_upstream(handle_upstream) .on_upgrade_downstream(handle_downstream) .build(); launcher.launch(handler).await?; Ok(()) } ``` ## Supported Frame Types The PDK supports these WebSocket frame types: - `FrameType::Text`: Text data frames - `FrameType::Binary`: Binary data frames - `FrameType::Close`: Connection close frames - `FrameType::Ping`: Ping frames - `FrameType::Pong`: Pong frames To maintain the WebSocket protocol integrity, pass control frames (Close, Ping, Pong) through without modification. ## Maintain Frame Boundaries Make sure your policy processes complete WebSocket messages regardless of how they arrive from the network. WebSocket frames might be fragmented across multiple chunks. PDK ensures your policy processes complete WebSocket messages regardless of how they arrive by: 1. Accumulating bytes using `state.accumulate().await` when complete frames aren’t available. 2. Tracking remainder bytes between iterations. 3. Parsing complete frames only when sufficient data is available. ## Process Client to Server Frames Process client to server frames in the upstream handler using `UpstreamState`. The handler must manage frame boundaries by accumulating partial frames: ```rust async fn handle_upstream(mut state: UpstreamState) -> Result<(), BoxError> { let mut remainder_bytes = Vec::new(); loop { let current_bytes = state.bytes(); let mut bytes = remainder_bytes.clone(); bytes.extend_from_slice(¤t_bytes); let (frames, remainder) = Decoder::parse(bytes); // Wait for complete frames before processing if frames.is_empty() { state = state.accumulate().await; } else { remainder_bytes = remainder; // Inspect and modify frames let modified: Vec = frames .into_iter() .map(|frame| match frame.frame_type() { FrameType::Text => { let text = String::from_utf8_lossy(frame.data()); Frame::text(format!("Modified: {}", text), frame.fin()) } _ => frame, // Control frames pass through }) .collect(); let encoded = Encoder::default().encode_client(modified); state.set_body(&encoded); state = state.next().await; } } } ``` ## Process Server to Client Frames Process server to client frames in the downstream handler using `DownstreamState`: ```rust async fn handle_downstream(mut state: DownstreamState) -> Result<(), BoxError> { let mut remainder_bytes = Vec::new(); loop { let current_bytes = state.bytes(); let mut bytes = remainder_bytes.clone(); bytes.extend_from_slice(¤t_bytes); let (frames, remainder) = Decoder::parse(bytes); // Wait for complete frames before processing if frames.is_empty() { state = state.accumulate().await; } else { remainder_bytes = remainder; // Process frames let modified: Vec = frames .into_iter() .map(|frame| match frame.frame_type() { FrameType::Text => { let text = String::from_utf8_lossy(frame.data()); Frame::text(format!("Echo: {}", text), frame.fin()) } _ => frame, // Control frames pass through }) .collect(); let encoded = Encoder::default().encode_server(modified); state.set_body(&encoded); state = state.next().await; } } } ``` ## See Also - [PDK WebSocket Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.9.0/websocket) - [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-headers-event) - [PDK Architecture](https://docs.mulesoft.com/pdk/1.9/policies-pdk-architecture) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Support WebSocket APIs > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)'s > WebSocket library, see > [WebSocket Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/websocket/README.md). Use the Omni Gateway Policy Development Kit (PDK) WebSocket library to implement custom policies that support WebSocket APIs. ## Enable WebSocket Support To enable WebSocket functionality, add the `experimental_websocket` feature at the PDK dependency in your `Cargo.toml` file: ```toml [dependencies] pdk = { version = "1.10.0", features = ["experimental_websocket"]} ``` ## Configure WebSocket Handlers To access WebSocket functionality, use the `FilterBuilder` with `on_upgrade_upstream` and `on_upgrade_downstream` handlers: ```rust use pdk::hl::*; use pdk::websockets::{Decoder, Encoder, Frame, FrameType}; pub async fn configure(launcher: Launcher) -> Result<()> { let handler = FilterBuilder::new() .on_create(|| YourPolicyState {}) .on_request(|_req: RequestState| async move { Flow::Continue(()) }) .on_upgrade_upstream(handle_upstream) .on_upgrade_downstream(handle_downstream) .build(); launcher.launch(handler).await?; Ok(()) } ``` ## Supported Frame Types The PDK supports these WebSocket frame types: - `FrameType::Text`: Text data frames - `FrameType::Binary`: Binary data frames - `FrameType::Close`: Connection close frames - `FrameType::Ping`: Ping frames - `FrameType::Pong`: Pong frames To maintain the WebSocket protocol integrity, pass control frames (Close, Ping, Pong) through without modification. ## Maintain Frame Boundaries Make sure your policy processes complete WebSocket messages regardless of how they arrive from the network. WebSocket frames might be fragmented across multiple chunks. PDK ensures your policy processes complete WebSocket messages regardless of how they arrive by: 1. Accumulating bytes using `state.accumulate().await` when complete frames aren’t available. 2. Tracking remainder bytes between iterations. 3. Parsing complete frames only when sufficient data is available. ## Process Client to Server Frames Process client to server frames in the upstream handler using `UpstreamState`. The handler must manage frame boundaries by accumulating partial frames: ```rust async fn handle_upstream(mut state: UpstreamState) -> Result<(), BoxError> { let mut remainder_bytes = Vec::new(); loop { let current_bytes = state.bytes(); let mut bytes = remainder_bytes.clone(); bytes.extend_from_slice(¤t_bytes); let (frames, remainder) = Decoder::parse(bytes); // Wait for complete frames before processing if frames.is_empty() { state = state.accumulate().await; } else { remainder_bytes = remainder; // Inspect and modify frames let modified: Vec = frames .into_iter() .map(|frame| match frame.frame_type() { FrameType::Text => { let text = String::from_utf8_lossy(frame.data()); Frame::text(format!("Modified: {}", text), frame.fin()) } _ => frame, // Control frames pass through }) .collect(); let encoded = Encoder::default().encode_client(modified); state.set_body(&encoded); state = state.next().await; } } } ``` ## Process Server to Client Frames Process server to client frames in the downstream handler using `DownstreamState`: ```rust async fn handle_downstream(mut state: DownstreamState) -> Result<(), BoxError> { let mut remainder_bytes = Vec::new(); loop { let current_bytes = state.bytes(); let mut bytes = remainder_bytes.clone(); bytes.extend_from_slice(¤t_bytes); let (frames, remainder) = Decoder::parse(bytes); // Wait for complete frames before processing if frames.is_empty() { state = state.accumulate().await; } else { remainder_bytes = remainder; // Process frames let modified: Vec = frames .into_iter() .map(|frame| match frame.frame_type() { FrameType::Text => { let text = String::from_utf8_lossy(frame.data()); Frame::text(format!("Echo: {}", text), frame.fin()) } _ => frame, // Control frames pass through }) .collect(); let encoded = Encoder::default().encode_server(modified); state.set_body(&encoded); state = state.next().await; } } } ``` ## See Also - [PDK WebSocket Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/tree/1.10.0/websocket) - [Reading and Writing Request Headers and Bodies](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-headers-event) - [PDK Architecture](https://docs.mulesoft.com/pdk/latest/policies-pdk-architecture) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Testing and Debugging Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the Policy Development Kit (PDK) testing options to validate behavior, catch regressions, and debug before you [publish your policy to Exchange](https://docs.mulesoft.com/pdk/1.8/policies-pdk-publish-policies-overview): - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.8/policies-pdk-debug-local) — Use the preconfigured API instance in your project’s `playground` directory to exercise and debug the policy interactively. - [Writing Unit Tests](https://docs.mulesoft.com/pdk/1.8/policies-pdk-unit): Run fast, deterministic Rust unit tests that exercise the full request and response lifecycle without configuring Envoy, WebAssembly, or external services. - [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.8/policies-pdk-integration-tests): Run automated tests on a local mode Omni Gateway to verify your policy with real gateway behavior and surrounding configuration. --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Testing and Debugging Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the Policy Development Kit (PDK) testing options to validate behavior, catch regressions, and debug before you [publish your policy to Exchange](https://docs.mulesoft.com/pdk/1.9/policies-pdk-publish-policies-overview): - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.9/policies-pdk-debug-local) — Use the preconfigured API instance in your project’s `playground` directory to exercise and debug the policy interactively. - [Writing Unit Tests](https://docs.mulesoft.com/pdk/1.9/policies-pdk-unit): Run fast, deterministic Rust unit tests that exercise the full request and response lifecycle without configuring Envoy, WebAssembly, or external services. - [Writing Integration Tests](https://docs.mulesoft.com/pdk/1.9/policies-pdk-integration-tests): Run automated tests on a local mode Omni Gateway to verify your policy with real gateway behavior and surrounding configuration. --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Testing and Debugging Custom Policies > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the Policy Development Kit (PDK) testing options to validate behavior, catch regressions, and debug before you [publish your policy to Exchange](https://docs.mulesoft.com/pdk/latest/policies-pdk-publish-policies-overview): - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/latest/policies-pdk-debug-local) — Use the preconfigured API instance in your project’s `playground` directory to exercise and debug the policy interactively. - [Writing Unit Tests](https://docs.mulesoft.com/pdk/latest/policies-pdk-unit): Run fast, deterministic Rust unit tests that exercise the full request and response lifecycle without configuring Envoy, WebAssembly, or external services. - [Writing Integration Tests](https://docs.mulesoft.com/pdk/latest/policies-pdk-integration-tests): Run automated tests on a local mode Omni Gateway to verify your policy with real gateway behavior and surrounding configuration. --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Upgrading PDK > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To update a custom policy project, you must update each of these separately versioned Flex Gateway Policy Development Kit (PDK) components: - Anypoint CLI PDK plugin - PDK Rust libraries - Anypoint Cargo plugin When you upgrade your Anypoint CLI PDK plugin, you must manually upgrade the PDK Rust libraries and Anypoint Cargo plugin to be compatible with the new plugin version. All the PDK custom policies on your device use the same Anypoint CLI PDK plugin. When you create a new custom policy project, the PDK Rust libraries and Anypoint Cargo plugin versions are the same as the Anypoint CLI PDK plugin used to create the project and are independent from other policy projects. To upgrade a custom policy project created with an earlier version of the Anypoint CLI PDK plugin: 1. [Upgrade the Anypoint CLI PDK Plugin](#anypoint-cli-pdk-plugin) 2. [Upgrade the PDK Rust Libraries](#pdk-rust-libraries) 3. [Upgrade the Anypoint Cargo Plugin](#anypoint-cargo-plugin) ## Upgrade the Anypoint CLI PDK Plugin When editing a custom policy created with an earlier plugin version, ensure your [PDK Rust libraries](#pdk-rust-libraries) and [Anypoint Cargo plugin](#anypoint-cargo-plugin) match your Anypoint CLI PDK plugin version. To upgrade your Anypoint CLI PDK plugin to the latest version, execute the following command: ```ssh anypoint-cli-v4 plugins:install anypoint-cli-pdk-plugin ``` To verify your current plugin version, execute the following command: ```ssh anypoint-cli-v4 plugins ``` For example, the following PDK plugin version is `1.1.0`: ```ssh anypoint-cli-pdk-plugin 1.1.0 ├─ anypoint-cli-command 1.5.2 │ └─ @oclif/plugin-help 5.1.12 └─ @oclif/plugin-version 1.0.4 ``` ## Upgrade the PDK Rust Libraries The PDK Rust library is the Rust code library used by a specific custom policy. Different custom policies might use different PDK library versions. To upgrade the PDK Rust code libraries, modify the `pdk` `dependency` and `pdk-test` `dev-dependency` versions in the `cargo.toml` file of the custom policy. The `pdk` and `pdk-test` versions must match and your Anypoint CLI PDK plugin must support the specified version. In the following example, both dependency versions are `1.0.0`. Modify it to your required version: ```toml [dependencies] pdk = { version = "1.0.0", registry = "anypoint" } [dev-dependencies] pdk-test = { version = "1.0.0", registry = "anypoint" } ``` ## Upgrade the Anypoint Cargo Plugin The Anypoint Cargo plugin extends the functionality of Cargo for use with the PDK Rust Libraries. To upgrade your Anypoint Cargo plugin: 1. Open the `Makefile` of your custom policy. 2. Find the `install-cargo-anypoint` target, for example: install-cargo-anypoint: cargo install cargo-anypoint@1.0.0 --registry anypoint --config .cargo/config.toml 3. Change the version after the `@` character to the required version. 4. Save the `Makefile`. 5. Execute the `make setup` command: ```ssh make setup ``` > [!NOTE] Executing the `make setup` command for a certain policy installs that policy’s > Anypoint Cargo plugin version. 6. Execute the following command to verify the correct version is installed: ```ssh cargo anypoint --version ``` ## See Also - [Reviewing PDK Prerequisites](https://docs.mulesoft.com/pdk/1.2/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Upgrading PDK > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To update a custom policy project, you must update each of these separately versioned Flex Gateway Policy Development Kit (PDK) components: - Anypoint CLI PDK plugin - PDK Rust libraries - Anypoint Cargo plugin When you upgrade your Anypoint CLI PDK plugin, you must manually upgrade the PDK Rust libraries and Anypoint Cargo plugin to be compatible with the new plugin version. All the PDK custom policies on your device use the same Anypoint CLI PDK plugin. When you create a new custom policy project, the PDK Rust libraries and Anypoint Cargo plugin versions are the same as the Anypoint CLI PDK plugin used to create the project and are independent from other policy projects. To upgrade a custom policy project created with an earlier version of the Anypoint CLI PDK plugin: 1. [Upgrade the Anypoint CLI PDK Plugin](#anypoint-cli-pdk-plugin) 2. [Upgrade the PDK Rust Libraries](#pdk-rust-libraries) 3. [Upgrade the Anypoint Cargo Plugin](#anypoint-cargo-plugin) ## Upgrade the Anypoint CLI PDK Plugin When editing a custom policy created with an earlier plugin version, ensure your [PDK Rust libraries](#pdk-rust-libraries) and [Anypoint Cargo plugin](#anypoint-cargo-plugin) match your Anypoint CLI PDK plugin version. To upgrade your Anypoint CLI PDK plugin to the latest version, execute the following command: ```ssh anypoint-cli-v4 plugins:install anypoint-cli-pdk-plugin ``` To verify your current plugin version, execute the following command: ```ssh anypoint-cli-v4 plugins ``` For example, the following PDK plugin version is `1.1.0`: ```ssh anypoint-cli-pdk-plugin 1.1.0 ├─ anypoint-cli-command 1.5.2 │ └─ @oclif/plugin-help 5.1.12 └─ @oclif/plugin-version 1.0.4 ``` ## Upgrade the PDK Rust Libraries The PDK Rust library is the Rust code library used by a specific custom policy. Different custom policies might use different PDK library versions. To upgrade the PDK Rust code libraries, modify the `pdk` `dependency` and `pdk-test` `dev-dependency` versions in the `cargo.toml` file of the custom policy. The `pdk` and `pdk-test` versions must match and your Anypoint CLI PDK plugin must support the specified version. In the following example, both dependency versions are `1.0.0`. Modify it to your required version: ```toml [dependencies] pdk = { version = "1.0.0", registry = "anypoint" } [dev-dependencies] pdk-test = { version = "1.0.0", registry = "anypoint" } ``` ## Upgrade the Anypoint Cargo Plugin The Anypoint Cargo plugin extends the functionality of Cargo for use with the PDK Rust Libraries. To upgrade your Anypoint Cargo plugin: 1. Open the `Makefile` of your custom policy. 2. Find the `install-cargo-anypoint` target, for example: install-cargo-anypoint: cargo install cargo-anypoint@1.0.0 --registry anypoint --config .cargo/config.toml 3. Change the version after the `@` character to the required version. 4. Save the `Makefile`. 5. Execute the `make setup` command: ```ssh make setup ``` > [!NOTE] Executing the `make setup` command for a certain policy installs that policy’s > Anypoint Cargo plugin version. 6. Execute the following command to verify the correct version is installed: ```ssh cargo anypoint --version ``` ## See Also - [Prerequisites for Flex Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.3/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Upgrading PDK > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To update a custom policy project, you must update each of these separately versioned Flex Gateway Policy Development Kit (PDK) components: - Anypoint CLI PDK plugin - PDK Rust libraries - Anypoint Cargo plugin - Policy Rust Version - WASI Crate When you upgrade your Anypoint CLI PDK plugin, you must manually upgrade the PDK Rust libraries and Anypoint Cargo plugin to be compatible with the new plugin version. All the PDK custom policies on your device use the same Anypoint CLI PDK plugin. When you create a new custom policy project, the PDK Rust libraries and Anypoint Cargo plugin versions are the same as the Anypoint CLI PDK plugin used to create the project and are independent from other policy projects. To upgrade a custom policy project created with an earlier version of the Anypoint CLI PDK plugin: 1. [Upgrade the Anypoint CLI PDK Plugin](#anypoint-cli-pdk-plugin) 2. [Upgrade the PDK Rust Libraries](#pdk-rust-libraries) 3. [Upgrade the Anypoint Cargo Plugin](#anypoint-cargo-plugin) 4. [Upgrade a Policy’s Rust Version](#anypoint-rust-version) 5. [Upgrade a Policy’s WASI Crate](#anypoint-wasi-crate) ## Upgrade the Anypoint CLI PDK Plugin When editing a custom policy created with an earlier plugin version, ensure your [PDK Rust libraries](#pdk-rust-libraries) and [Anypoint Cargo plugin](#anypoint-cargo-plugin) match your Anypoint CLI PDK plugin version. To upgrade your Anypoint CLI PDK plugin to the latest version, execute the following command: ```ssh anypoint-cli-v4 plugins:install anypoint-cli-pdk-plugin ``` To verify your current plugin version, execute the following command: ```ssh anypoint-cli-v4 plugins ``` For example, the following PDK plugin version is `1.4.1`: ```ssh anypoint-cli-pdk-plugin 1.4.1 ├─ anypoint-cli-command 1.5.2 │ └─ @oclif/plugin-help 5.1.12 └─ @oclif/plugin-version 1.0.4 ``` ## Upgrade the PDK Rust Libraries The PDK Rust library is the Rust code library used by a specific custom policy. Different custom policies might use different PDK library versions. To upgrade the PDK Rust code libraries, modify the `pdk` `dependency` and `pdk-test` `dev-dependency` versions in the `cargo.toml` file of the custom policy. The `pdk` and `pdk-test` versions must match and your Anypoint CLI PDK plugin must support the specified version. In the following example, both dependency versions are `1.0.0`. Modify it to your required version: ```toml [dependencies] pdk = { version = "1.0.0", registry = "anypoint" } [dev-dependencies] pdk-test = { version = "1.0.0", registry = "anypoint" } ``` ## Upgrade the Anypoint Cargo Plugin The Anypoint Cargo plugin extends the functionality of Cargo for use with the PDK Rust Libraries. To upgrade your Anypoint Cargo plugin: 1. Open the `Makefile` of your custom policy. 2. Find the `install-cargo-anypoint` target, for example: install-cargo-anypoint: cargo install cargo-anypoint@1.0.0 --registry anypoint --config .cargo/config.toml 3. Change the version after the `@` character to the required version. 4. Save the `Makefile`. 5. Execute the `make setup` command: ```ssh make setup ``` > [!NOTE] Executing the `make setup` command for a certain policy installs that policy’s > Anypoint Cargo plugin version. 6. Execute the following command to verify the correct version is installed: ```ssh cargo anypoint --version ``` ## Upgrade a Policy’s Rust Version To upgrade your Policy’s Rust version: 1. Ensure the Rust version is downloaded on your device. To update Rust, see [Rust Requirements for Using PDK](https://docs.mulesoft.com/pdk/1.4/policies-pdk-prerequisites#rust-requirements). 2. Open the `cargo.toml` of your custom policy. 3. Find your Rust version. For example: rust-version = "1.83.0" 4. Update your Rust version. For example: rust-version = "1.87.0" 5. Save the `cargo.toml` file. ## Upgrade a Policy’s WASI Crate To upgrade your Rust WebAssembly System Interface (WASI) Crate from `wasm32-wasi` to `wasm32-wasip1`: 1. Open the `Makefile` of your custom policy. 2. Find this line: TARGET := wasm32-wasi 3. Replace `wasm32-wasi` with `wasm32-wasip1`: TARGET := wasm32-wasip1 4. Save the `Makefile`. 5. Open the `tests/common/mod.rs` of your custom policy. 6. Find the this line: pub const POLICY\_DIR: &str = concat!(env!("CARGO\_MANIFEST\_DIR"), "/target/wasm32-wasi/release"); 7. Replace `wasm32-wasi` with `wasm32-wasip1`: pub const POLICY\_DIR: &str = concat!(env!("CARGO\_MANIFEST\_DIR"), "/target/wasm32-wasip1/release"); 8. Save the `mod.rs` file. ## See Also - [Prerequisites for Flex Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.4/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Upgrading PDK > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To update a custom policy project, you must update each of these separately versioned Flex Gateway Policy Development Kit (PDK) components: - Anypoint CLI PDK plugin - PDK Rust libraries - Anypoint Cargo plugin - Policy Rust Version - WASI Crate When you upgrade your Anypoint CLI PDK plugin, you must manually upgrade the PDK Rust libraries and Anypoint Cargo plugin to be compatible with the new plugin version. All the PDK custom policies on your device use the same Anypoint CLI PDK plugin. When you create a new custom policy project, the PDK Rust libraries and Anypoint Cargo plugin versions are the same as the Anypoint CLI PDK plugin used to create the project and are independent from other policy projects. To upgrade a custom policy project created with an earlier version of the Anypoint CLI PDK plugin: 1. [Upgrade the Anypoint CLI PDK Plugin](#anypoint-cli-pdk-plugin) 2. [Upgrade the PDK Rust Libraries](#pdk-rust-libraries) 3. [Upgrade the Anypoint Cargo Plugin](#anypoint-cargo-plugin) 4. [Upgrade a Policy’s Rust Version](#anypoint-rust-version) 5. [Upgrade a Policy’s WASI Crate](#anypoint-wasi-crate) ## Upgrade the Anypoint CLI PDK Plugin When editing a custom policy created with an earlier plugin version, ensure your [PDK Rust libraries](#pdk-rust-libraries) and [Anypoint Cargo plugin](#anypoint-cargo-plugin) match your Anypoint CLI PDK plugin version. To upgrade your Anypoint CLI PDK plugin to the latest version, execute the following command: ```ssh anypoint-cli-v4 plugins:install anypoint-cli-pdk-plugin ``` To verify your current plugin version, execute the following command: ```ssh anypoint-cli-v4 plugins ``` For example, the following PDK plugin version is `1.4.1`: ```ssh anypoint-cli-pdk-plugin 1.4.1 ├─ anypoint-cli-command 1.5.2 │ └─ @oclif/plugin-help 5.1.12 └─ @oclif/plugin-version 1.0.4 ``` ## Upgrade the PDK Rust Libraries The PDK Rust library is the Rust code library used by a specific custom policy. Different custom policies might use different PDK library versions. To upgrade the PDK Rust code libraries, modify the `pdk` `dependency` and `pdk-test` `dev-dependency` versions in the `cargo.toml` file of the custom policy. The `pdk` and `pdk-test` versions must match and your Anypoint CLI PDK plugin must support the specified version. In the following example, both dependency versions are `1.0.0`. Modify it to your required version: ```toml [dependencies] pdk = { version = "1.0.0", registry = "anypoint" } [dev-dependencies] pdk-test = { version = "1.0.0", registry = "anypoint" } ``` ## Upgrade the Anypoint Cargo Plugin The Anypoint Cargo plugin extends the functionality of Cargo for use with the PDK Rust Libraries. To upgrade your Anypoint Cargo plugin: 1. Open the `Makefile` of your custom policy. 2. Find the `install-cargo-anypoint` target, for example: install-cargo-anypoint: cargo install cargo-anypoint@1.0.0 --registry anypoint --config .cargo/config.toml 3. Change the version after the `@` character to the required version. 4. Save the `Makefile`. 5. Execute the `make setup` command: ```ssh make setup ``` > [!NOTE] Executing the `make setup` command for a certain policy installs that policy’s > Anypoint Cargo plugin version. 6. Execute the following command to verify the correct version is installed: ```ssh cargo anypoint --version ``` ## Upgrade a Policy’s Rust Version To upgrade your Policy’s Rust version: 1. Ensure the Rust version is downloaded on your device. To update Rust, see [Rust Requirements for Using PDK](https://docs.mulesoft.com/pdk/1.5/policies-pdk-prerequisites#rust-requirements). 2. Open the `cargo.toml` of your custom policy. 3. Find your Rust version. For example: rust-version = "1.83.0" 4. Update your Rust version. For example: rust-version = "1.87.0" 5. Save the `cargo.toml` file. ## Upgrade a Policy’s WASI Crate To upgrade your Rust WebAssembly System Interface (WASI) Crate from `wasm32-wasi` to `wasm32-wasip1`: 1. Open the `Makefile` of your custom policy. 2. Find this line: TARGET := wasm32-wasi 3. Replace `wasm32-wasi` with `wasm32-wasip1`: TARGET := wasm32-wasip1 4. Save the `Makefile`. 5. Open the `tests/common/mod.rs` of your custom policy. 6. Find the this line: pub const POLICY\_DIR: &str = concat!(env!("CARGO\_MANIFEST\_DIR"), "/target/wasm32-wasi/release"); 7. Replace `wasm32-wasi` with `wasm32-wasip1`: pub const POLICY\_DIR: &str = concat!(env!("CARGO\_MANIFEST\_DIR"), "/target/wasm32-wasip1/release"); 8. Save the `mod.rs` file. ## See Also - [Prerequisites for Flex Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.5/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Upgrading PDK > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To update a custom policy project, you must update each of these separately versioned Flex Gateway Policy Development Kit (PDK) components: - Anypoint CLI PDK plugin - PDK Rust libraries - Anypoint Cargo plugin - Policy Rust Version - WASI Crate When you upgrade your Anypoint CLI PDK plugin, you must manually upgrade the PDK Rust libraries and Anypoint Cargo plugin to be compatible with the new plugin version. All the PDK custom policies on your device use the same Anypoint CLI PDK plugin. When you create a new custom policy project, the PDK Rust libraries and Anypoint Cargo plugin versions are the same as the Anypoint CLI PDK plugin used to create the project and are independent from other policy projects. To upgrade a custom policy project created with an earlier version of the Anypoint CLI PDK plugin: 1. [Upgrade the Anypoint CLI PDK Plugin](#anypoint-cli-pdk-plugin) 2. [Upgrade the PDK Rust Libraries](#pdk-rust-libraries) 3. [Upgrade the Anypoint Cargo Plugin](#anypoint-cargo-plugin) 4. [Upgrade a Policy’s Rust Version](#anypoint-rust-version) 5. [Upgrade a Policy’s WASI Crate](#anypoint-wasi-crate) ## Upgrade the Anypoint CLI PDK Plugin When editing a custom policy created with an earlier plugin version, ensure your [PDK Rust libraries](#pdk-rust-libraries) and [Anypoint Cargo plugin](#anypoint-cargo-plugin) match your Anypoint CLI PDK plugin version. To upgrade your Anypoint CLI PDK plugin to the latest version, execute the following command: ```ssh anypoint-cli-v4 plugins:install anypoint-cli-pdk-plugin ``` To verify your current plugin version, execute the following command: ```ssh anypoint-cli-v4 plugins ``` For example, the following PDK plugin version is `1.6.0`: ```ssh anypoint-cli-pdk-plugin 1.6.0 ├─ anypoint-cli-command 1.5.2 │ └─ @oclif/plugin-help 5.1.12 └─ @oclif/plugin-version 1.0.4 ``` ## Upgrade the PDK Rust Libraries The PDK Rust library is the Rust code library used by a specific custom policy. Different custom policies might use different PDK library versions. To upgrade the PDK Rust code libraries, modify the `pdk` `dependency` and `pdk-test` `dev-dependency` versions in the `cargo.toml` file of the custom policy. The `pdk` and `pdk-test` versions must match and your Anypoint CLI PDK plugin must support the specified version. In the following example, both dependency versions are `1.6.0`. Modify it to your required version: ```toml [dependencies] pdk = { version = "1.6.0" } [dev-dependencies] pdk-test = { version = "1.6.0" } ``` ## Upgrade the Anypoint Cargo Plugin The Anypoint Cargo plugin extends the functionality of Cargo for use with the PDK Rust Libraries. To upgrade your Anypoint Cargo plugin: 1. Open the `Makefile` of your custom policy. 2. Find the `install-cargo-anypoint` target, for example: install-cargo-anypoint: cargo install cargo-anypoint@1.6.0 3. Change the version after the `@` character to the required version. 4. Save the `Makefile`. 5. Execute the `make setup` command: ```ssh make setup ``` > [!NOTE] Executing the `make setup` command for a certain policy installs that policy’s > Anypoint Cargo plugin version. 6. Execute the following command to verify the correct version is installed: ```ssh cargo anypoint --version ``` ## Upgrade a Policy’s Rust Version To upgrade your Policy’s Rust version: 1. Ensure the Rust version is downloaded on your device. To update Rust, see [Rust Requirements for Using PDK](https://docs.mulesoft.com/pdk/1.6/policies-pdk-prerequisites#rust-requirements). 2. Open the `cargo.toml` of your custom policy. 3. Find your Rust version. For example: rust-version = "1.87.0" 4. Update your Rust version. For example: rust-version = "1.88.0" 5. Save the `cargo.toml` file. ## Upgrade a Policy’s WASI Crate To upgrade your Rust WebAssembly System Interface (WASI) Crate from `wasm32-wasi` to `wasm32-wasip1`: 1. Open the `Makefile` of your custom policy. 2. Find this line: TARGET := wasm32-wasi 3. Replace `wasm32-wasi` with `wasm32-wasip1`: TARGET := wasm32-wasip1 4. Save the `Makefile`. 5. Open the `tests/common/mod.rs` of your custom policy. 6. Find the this line: pub const POLICY\_DIR: &str = concat!(env!("CARGO\_MANIFEST\_DIR"), "/target/wasm32-wasi/release"); 7. Replace `wasm32-wasi` with `wasm32-wasip1`: pub const POLICY\_DIR: &str = concat!(env!("CARGO\_MANIFEST\_DIR"), "/target/wasm32-wasip1/release"); 8. Save the `mod.rs` file. ## Upgrade Policies with Versions Earlier Than 1.6.0 In PDK 1.6.0, the PDK libraries moved from the Anypoint platform to [crates.io](https://crates.io/crates/pdk). When upgrading from versions earlier than 1.6.0, you must update the dependencies to point to the new location. To upgrade policies with versions earlier than 1.6.0: 1. [Upgrade the Anypoint CLI PDK plugin](#anypoint-cli-pdk-plugin). 2. [Upgrade the PDK Rust libraries](#anypoint-rust-version). 3. Upgrade the PDK Rust libraries: 1. Locate the `dependencies` and `dev-dependencies` in your policy’s `cargo.toml`: ```toml [dependencies] pdk = { version = "1.5.0", registry = "anypoint" } [dev-dependencies] pdk-test = { version = "1.5.0", registry = "anypoint" } ``` 2. Update the version and remove the `registry = "anypoint"`: ```toml [dependencies] pdk = { version = "1.6.0" } [dev-dependencies] pdk-test = { version = "1.6.0" } ``` 3. Save the `cargo.toml` file. 4. Upgrade the Anypoint Cargo Plugin: 1. Open the `Makefile` of your custom policy. 2. Find the `install-cargo-anypoint` target, for example: install-cargo-anypoint: cargo install cargo-anypoint@1.5.0 --registry anypoint --config .cargo/config.toml 3. Update the version and remove the `--registry` and `--config` flags: install-cargo-anypoint: cargo install cargo-anypoint@1.6.0 4. Save the `Makefile` file. 5. Remove the Anypoint Platform registry references from your `setup` command: 1. Open the `Makefile` of your custom policy. 2. Find the `setup` target, for example: .PHONY: setup setup: registry-creds login install-cargo-anypoint ## Setup all required tools to build cargo fetch 3. Remove the Anypoint Platform registry references: .PHONY: setup setup: install-cargo-anypoint ## Setup all required tools to build cargo fetch 4. Delete the `login` and `registry-creds` targets. For example: To find an example of the targets, see the [`login` and `registry-creds` targets in the Certification Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/certs/Makefile#L68-L85). 5. Save the `Makefile` file. 6. Execute `make setup` to install the updated versions. ## See Also - [Prerequisites for Flex Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.6/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Upgrading PDK > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To update a custom policy project, you must update each of these separately versioned Flex Gateway Policy Development Kit (PDK) components: - Anypoint CLI PDK plugin - PDK Rust libraries - Anypoint Cargo plugin - Policy Rust Version - WASI Crate When you upgrade your Anypoint CLI PDK plugin, you must manually upgrade the PDK Rust libraries and Anypoint Cargo plugin to be compatible with the new plugin version. All the PDK custom policies on your device use the same Anypoint CLI PDK plugin. When you create a new custom policy project, the PDK Rust libraries and Anypoint Cargo plugin versions are the same as the Anypoint CLI PDK plugin used to create the project and are independent from other policy projects. To upgrade a custom policy project created with an earlier version of the Anypoint CLI PDK plugin: 1. [Upgrade the Anypoint CLI PDK Plugin](#anypoint-cli-pdk-plugin) 2. [Upgrade the PDK Rust Libraries](#pdk-rust-libraries) 3. [Upgrade the Anypoint Cargo Plugin](#anypoint-cargo-plugin) 4. [Upgrade a Policy’s Rust Version](#anypoint-rust-version) 5. [Upgrade a Policy’s WASI Crate](#anypoint-wasi-crate) ## Upgrade the Anypoint CLI PDK Plugin When editing a custom policy created with an earlier plugin version, ensure your [PDK Rust libraries](#pdk-rust-libraries) and [Anypoint Cargo plugin](#anypoint-cargo-plugin) match your Anypoint CLI PDK plugin version. To upgrade your Anypoint CLI PDK plugin to the latest version, execute the following command: ```ssh anypoint-cli-v4 plugins:install anypoint-pdk-plugin ``` \+ NOTE: In PDK 1.7.0, the name of the Anypoint CLI PDK plugin changes from `anypoint-cli-pdk-plugin` to `anypoint-pdk-plugin`. To install the new plugin, see [Upgrade the Anypoint CLI PDK Plugin for Policies with Versions Earlier Than 1.7.0](#upgrade-anypoint-cli-pdk-plugin-earlier-1.7.0). To verify your current plugin version, execute the following command: ```ssh anypoint-cli-v4 plugins ``` For example, the following PDK plugin version is `1.7.0`: ```ssh anypoint-pdk-plugin 1.7.0 ├─ anypoint-cli-command 1.5.2 │ └─ @oclif/plugin-help 5.1.12 └─ @oclif/plugin-version 1.0.4 ``` ## Upgrade the PDK Rust Libraries The PDK Rust library is the Rust code library used by a specific custom policy. Different custom policies might use different PDK library versions. To upgrade the PDK Rust code libraries, modify the `pdk` `dependency` and `pdk-test` `dev-dependency` versions in the `cargo.toml` file of the custom policy. The `pdk` and `pdk-test` versions must match and your Anypoint CLI PDK plugin must support the specified version. In the following example, both dependency versions are `1.6.0`. Modify it to your required version: ```toml [dependencies] pdk = { version = "1.6.0" } [dev-dependencies] pdk-test = { version = "1.6.0" } ``` ## Upgrade the Anypoint Cargo Plugin The Anypoint Cargo plugin extends the functionality of Cargo for use with the PDK Rust Libraries. To upgrade your Anypoint Cargo plugin: 1. Open the `Makefile` of your custom policy. 2. Find the `install-cargo-anypoint` target, for example: install-cargo-anypoint: cargo install cargo-anypoint@1.6.0 3. Change the version after the `@` character to the required version. 4. Save the `Makefile`. 5. Execute the `make setup` command: ```ssh make setup ``` > [!NOTE] Executing the `make setup` command for a certain policy installs that policy’s > Anypoint Cargo plugin version. 6. Execute the following command to verify the correct version is installed: ```ssh cargo anypoint --version ``` ## Upgrade a Policy’s Rust Version To upgrade your Policy’s Rust version: 1. Ensure the Rust version is downloaded on your device. To update Rust, see [Rust Requirements for Using PDK](https://docs.mulesoft.com/pdk/1.7/policies-pdk-prerequisites#rust-requirements). 2. Open the `cargo.toml` of your custom policy. 3. Find your Rust version. For example: rust-version = "1.87.0" 4. Update your Rust version. For example: rust-version = "1.88.0" 5. Save the `cargo.toml` file. ## Upgrade a Policy’s WASI Crate To upgrade your Rust WebAssembly System Interface (WASI) Crate from `wasm32-wasi` to `wasm32-wasip1`: 1. Open the `Makefile` of your custom policy. 2. Find this line: TARGET := wasm32-wasi 3. Replace `wasm32-wasi` with `wasm32-wasip1`: TARGET := wasm32-wasip1 4. Save the `Makefile`. 5. Open the `tests/common/mod.rs` of your custom policy. 6. Find the this line: pub const POLICY\_DIR: &str = concat!(env!("CARGO\_MANIFEST\_DIR"), "/target/wasm32-wasi/release"); 7. Replace `wasm32-wasi` with `wasm32-wasip1`: pub const POLICY\_DIR: &str = concat!(env!("CARGO\_MANIFEST\_DIR"), "/target/wasm32-wasip1/release"); 8. Save the `mod.rs` file. ## Upgrade Policies with Versions Earlier Than 1.6.0 In PDK 1.6.0, the PDK libraries moved from the Anypoint platform to [crates.io](https://crates.io/crates/pdk). When upgrading from versions earlier than 1.6.0, you must update the dependencies to point to the new location. To upgrade policies with versions earlier than 1.6.0: 1. [Upgrade the Anypoint CLI PDK plugin](#anypoint-cli-pdk-plugin). 2. [Upgrade the PDK Rust libraries](#anypoint-rust-version). 3. Upgrade the PDK Rust libraries: 1. Locate the `dependencies` and `dev-dependencies` in your policy’s `cargo.toml`: ```toml [dependencies] pdk = { version = "1.5.0", registry = "anypoint" } [dev-dependencies] pdk-test = { version = "1.5.0", registry = "anypoint" } ``` 2. Update the version and remove the `registry = "anypoint"`: ```toml [dependencies] pdk = { version = "1.6.0" } [dev-dependencies] pdk-test = { version = "1.6.0" } ``` 3. Save the `cargo.toml` file. 4. Upgrade the Anypoint Cargo Plugin: 1. Open the `Makefile` of your custom policy. 2. Find the `install-cargo-anypoint` target, for example: install-cargo-anypoint: cargo install cargo-anypoint@1.5.0 --registry anypoint --config .cargo/config.toml 3. Update the version and remove the `--registry` and `--config` flags: install-cargo-anypoint: cargo install cargo-anypoint@1.6.0 4. Save the `Makefile` file. 5. Remove the Anypoint Platform registry references from your `setup` command: 1. Open the `Makefile` of your custom policy. 2. Find the `setup` target, for example: .PHONY: setup setup: registry-creds login install-cargo-anypoint ## Setup all required tools to build cargo fetch 3. Remove the Anypoint Platform registry references: .PHONY: setup setup: install-cargo-anypoint ## Setup all required tools to build cargo fetch 4. Delete the `login` and `registry-creds` targets. For example: To find an example of the targets, see the [`login` and `registry-creds` targets in the Certification Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/certs/Makefile#L68-L85). 5. Save the `Makefile` file. 6. Execute `make setup` to install the updated versions. ## Upgrade the Anypoint CLI PDK Plugin for Policies with Versions Earlier Than 1.7.0 In PDK 1.7.0, the name of the Anypoint CLI PDK plugin changes from `anypoint-cli-pdk-plugin` to `anypoint-pdk-plugin`. To upgrade your earlier versions, uninstall the old plugin before installing the new one: 1. Uninstall the old plugin: ```ssh anypoint-cli-v4 plugins:uninstall anypoint-cli-pdk-plugin ``` 2. Install the new plugin: ```ssh anypoint-cli-v4 plugins:install anypoint-pdk-plugin ``` ## See Also - [Prerequisites for Flex Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.7/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Upgrading PDK > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To update a custom policy project, you must update each of these separately versioned Omni Gateway Policy Development Kit (PDK) components: - Anypoint CLI PDK plugin - PDK Rust libraries - Anypoint Cargo plugin - Policy Rust Version - WASI Crate When you upgrade your Anypoint CLI PDK plugin, you must manually upgrade the PDK Rust libraries and Anypoint Cargo plugin to be compatible with the new plugin version. All the PDK custom policies on your device use the same Anypoint CLI PDK plugin. When you create a new custom policy project, the PDK Rust libraries and Anypoint Cargo plugin versions are the same as the Anypoint CLI PDK plugin used to create the project and are independent from other policy projects. To upgrade a custom policy project created with an earlier version of the Anypoint CLI PDK plugin: 1. [Upgrade the Anypoint CLI PDK Plugin](#anypoint-cli-pdk-plugin) 2. [Upgrade the PDK Rust Libraries](#pdk-rust-libraries) 3. [Upgrade the Anypoint Cargo Plugin](#anypoint-cargo-plugin) 4. [Upgrade a Policy’s Rust Version](#anypoint-rust-version) 5. [Upgrade a Policy’s WASI Crate](#anypoint-wasi-crate) ## Upgrade the Anypoint CLI PDK Plugin When editing a custom policy created with an earlier plugin version, ensure your [PDK Rust libraries](#pdk-rust-libraries) and [Anypoint Cargo plugin](#anypoint-cargo-plugin) match your Anypoint CLI PDK plugin version. To upgrade your Anypoint CLI PDK plugin to the latest version, execute the following command: ```ssh anypoint-cli-v4 plugins:install anypoint-pdk-plugin ``` \+ NOTE: In PDK 1.7.0, the name of the Anypoint CLI PDK plugin changes from `anypoint-cli-pdk-plugin` to `anypoint-pdk-plugin`. To install the new plugin, see [Upgrade the Anypoint CLI PDK Plugin for Policies with Versions Earlier Than 1.7.0](#upgrade-anypoint-cli-pdk-plugin-earlier-1.7.0). To verify your current plugin version, execute the following command: ```ssh anypoint-cli-v4 plugins ``` For example, the following PDK plugin version is `1.7.0`: ```ssh anypoint-pdk-plugin 1.7.0 ├─ anypoint-cli-command 1.5.2 │ └─ @oclif/plugin-help 5.1.12 └─ @oclif/plugin-version 1.0.4 ``` ## Upgrade the PDK Rust Libraries The PDK Rust library is the Rust code library used by a specific custom policy. Different custom policies might use different PDK library versions. To upgrade the PDK Rust code libraries, modify the `pdk` `dependency` and `pdk-test` `dev-dependency` versions in the `cargo.toml` file of the custom policy. The `pdk` and `pdk-test` versions must match and your Anypoint CLI PDK plugin must support the specified version. In the following example, both dependency versions are `1.6.0`. Modify it to your required version: ```toml [dependencies] pdk = { version = "1.6.0" } [dev-dependencies] pdk-test = { version = "1.6.0" } ``` ## Upgrade the Anypoint Cargo Plugin The Anypoint Cargo plugin extends the functionality of Cargo for use with the PDK Rust Libraries. To upgrade your Anypoint Cargo plugin: 1. Open the `Makefile` of your custom policy. 2. Find the `install-cargo-anypoint` target, for example: install-cargo-anypoint: cargo install cargo-anypoint@1.6.0 3. Change the version after the `@` character to the required version. 4. Save the `Makefile`. 5. Execute the `make setup` command: ```ssh make setup ``` > [!NOTE] Executing the `make setup` command for a certain policy installs that policy’s > Anypoint Cargo plugin version. 6. Execute the following command to verify the correct version is installed: ```ssh cargo anypoint --version ``` ## Upgrade a Policy’s Rust Version To upgrade your Policy’s Rust version: 1. Ensure the Rust version is downloaded on your device. To update Rust, see [Rust Requirements for Using PDK](https://docs.mulesoft.com/pdk/1.8/policies-pdk-prerequisites#rust-requirements). 2. Open the `cargo.toml` of your custom policy. 3. Find your Rust version. For example: rust-version = "1.87.0" 4. Update your Rust version. For example: rust-version = "1.88.0" 5. Save the `cargo.toml` file. ## Upgrade a Policy’s WASI Crate To upgrade your Rust WebAssembly System Interface (WASI) Crate from `wasm32-wasi` to `wasm32-wasip1`: 1. Open the `Makefile` of your custom policy. 2. Find this line: TARGET := wasm32-wasi 3. Replace `wasm32-wasi` with `wasm32-wasip1`: TARGET := wasm32-wasip1 4. Save the `Makefile`. 5. Open the `tests/common/mod.rs` of your custom policy. 6. Find the this line: pub const POLICY\_DIR: &str = concat!(env!("CARGO\_MANIFEST\_DIR"), "/target/wasm32-wasi/release"); 7. Replace `wasm32-wasi` with `wasm32-wasip1`: pub const POLICY\_DIR: &str = concat!(env!("CARGO\_MANIFEST\_DIR"), "/target/wasm32-wasip1/release"); 8. Save the `mod.rs` file. ## Upgrade the Anypoint CLI PDK Plugin for Policies with Versions Earlier Than 1.8.0 Depending on you configuration, when upgrading to 1.8.0 you might experience these issues: - [Tokio Runtime Feature Compatibility Error](#feature-compatibility-issue-on-tokio) - [Compilation Error When Constructing Metadata-Related Structs](#compilation-error-structs) ### Tokio Runtime Feature Compatibility Error When using a Tokio runtime for testing, sometimes a compilation occurs similar to this error when building for WebAssembly: ```text error: Only features sync,macros,io-util,rt,time are supported on wasm. --> /Users/test-user/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.51.1/src/lib.rs:478:1 | 478 | compile_error!("Only features sync,macros,io-util,rt,time are supported on wasm."); ``` To solve this error, under the `[package]` section of your policy’s `Cargo.toml`, add `resolver = "2"`. This enables your compiler resolve dependencies separately for production code and for test dependencies. ```toml [package] name = "my_policy" version = "1.0.0" rust-version = "1.88.0" edition = "2018" resolver = "2" ``` ### Compilation Error When Constructing Metadata-Related Structs When constructing Metadata-related structs, sometimes an error similar to this one occurs: ```text error[E0639]: cannot create non-exhaustive struct using struct expression --> test-policy/src/lib.rs:90:32 | 90 | flex_metadata: FlexMetadata { | ________________________________^ 91 | | flex_name: "test_flex_name".to_string(), 92 | | flex_version: "1.0.0".to_string(), 93 | | }, | |_________________^ ``` PDK 1.8.0 marks metadata-related structs as `#[non_exhaustive]` so that you can add new metadata fields without breaking changes. When constructing these structs manually in tests, use one of these approaches: - Use the new default constructor and set each field to the value you need. For example: ```rust let mut metadata = FlexMetadata::default(); metadata.flex_name = "test_flex_name".to_string(); metadata.flex_version = "1.0.0".to_string(); ``` - Add the `non_exhaustive!` macro from the [`non-exhaustive`](https://crates.io/crates/non-exhaustive) crate to the `[dev-dependencies]` in your `cargo.toml` files: ```toml [dev-dependencies] non-exhaustive = "0.1.1" ``` This enables you to use the default construct as shown in this example: ```rust use non_exhaustive::non_exhaustive; // ... let metadata = non_exhaustive!(FlexMetadata { flex_name: "test_flex_name".to_string(), flex_version: "1.0.0".to_string(), }); ``` ## Upgrade the Anypoint CLI PDK Plugin for Policies with Versions Earlier Than 1.7.0 In PDK 1.7.0, the name of the Anypoint CLI PDK plugin changes from `anypoint-cli-pdk-plugin` to `anypoint-pdk-plugin`. To upgrade your earlier versions, uninstall the old plugin before installing the new one: 1. Uninstall the old plugin: ```ssh anypoint-cli-v4 plugins:uninstall anypoint-cli-pdk-plugin ``` 2. Install the new plugin: ```ssh anypoint-cli-v4 plugins:install anypoint-pdk-plugin ``` ## Upgrade Policies with Versions Earlier Than 1.6.0 In PDK 1.6.0, the PDK libraries moved from the Anypoint platform to [crates.io](https://crates.io/crates/pdk). When upgrading from versions earlier than 1.6.0, you must update the dependencies to point to the new location. To upgrade policies with versions earlier than 1.6.0: 1. [Upgrade the Anypoint CLI PDK plugin](#anypoint-cli-pdk-plugin). 2. [Upgrade the PDK Rust libraries](#anypoint-rust-version). 3. Upgrade the PDK Rust libraries: 1. Locate the `dependencies` and `dev-dependencies` in your policy’s `cargo.toml`: ```toml [dependencies] pdk = { version = "1.5.0", registry = "anypoint" } [dev-dependencies] pdk-test = { version = "1.5.0", registry = "anypoint" } ``` 2. Update the version and remove the `registry = "anypoint"`: ```toml [dependencies] pdk = { version = "1.6.0" } [dev-dependencies] pdk-test = { version = "1.6.0" } ``` 3. Save the `cargo.toml` file. 4. Upgrade the Anypoint Cargo Plugin: 1. Open the `Makefile` of your custom policy. 2. Find the `install-cargo-anypoint` target, for example: install-cargo-anypoint: cargo install cargo-anypoint@1.5.0 --registry anypoint --config .cargo/config.toml 3. Update the version and remove the `--registry` and `--config` flags: install-cargo-anypoint: cargo install cargo-anypoint@1.6.0 4. Save the `Makefile` file. 5. Remove the Anypoint Platform registry references from your `setup` command: 1. Open the `Makefile` of your custom policy. 2. Find the `setup` target, for example: .PHONY: setup setup: registry-creds login install-cargo-anypoint ## Setup all required tools to build cargo fetch 3. Remove the Anypoint Platform registry references: .PHONY: setup setup: install-cargo-anypoint ## Setup all required tools to build cargo fetch 4. Delete the `login` and `registry-creds` targets. For example: To find an example of the targets, see the [`login` and `registry-creds` targets in the Certification Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/certs/Makefile#L68-L85). 5. Save the `Makefile` file. 6. Execute `make setup` to install the updated versions. ## See Also - [Prerequisites for Omni Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.8/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Upgrading PDK > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To update a custom policy project, you must update each of these separately versioned Omni Gateway Policy Development Kit (PDK) components: - Anypoint CLI PDK plugin - PDK Rust libraries - Anypoint Cargo plugin - Policy Rust Version - WASI Crate When you upgrade your Anypoint CLI PDK plugin, you must manually upgrade the PDK Rust libraries and Anypoint Cargo plugin to be compatible with the new plugin version. All the PDK custom policies on your device use the same Anypoint CLI PDK plugin. When you create a new custom policy project, the PDK Rust libraries and Anypoint Cargo plugin versions are the same as the Anypoint CLI PDK plugin used to create the project and are independent from other policy projects. To upgrade a custom policy project created with an earlier version of the Anypoint CLI PDK plugin: 1. [Upgrade the Anypoint CLI PDK Plugin](#anypoint-cli-pdk-plugin) 2. [Upgrade the PDK Rust Libraries](#pdk-rust-libraries) 3. [Upgrade the Anypoint Cargo Plugin](#anypoint-cargo-plugin) 4. [Upgrade a Policy’s Rust Version](#anypoint-rust-version) 5. [Upgrade a Policy’s WASI Crate](#anypoint-wasi-crate) ## Upgrade the Anypoint CLI PDK Plugin When editing a custom policy created with an earlier plugin version, ensure your [PDK Rust libraries](#pdk-rust-libraries) and [Anypoint Cargo plugin](#anypoint-cargo-plugin) match your Anypoint CLI PDK plugin version. To upgrade your Anypoint CLI PDK plugin to the latest version, execute the following command: ```ssh anypoint-cli-v4 plugins:install anypoint-pdk-plugin ``` \+ NOTE: In PDK 1.7.0, the name of the Anypoint CLI PDK plugin changes from `anypoint-cli-pdk-plugin` to `anypoint-pdk-plugin`. To install the new plugin, see [Upgrade the Anypoint CLI PDK Plugin for Policies with Versions Earlier Than 1.7.0](#upgrade-anypoint-cli-pdk-plugin-earlier-1.7.0). To verify your current plugin version, execute the following command: ```ssh anypoint-cli-v4 plugins ``` For example, the following PDK plugin version is `1.7.0`: ```ssh anypoint-pdk-plugin 1.7.0 ├─ anypoint-cli-command 1.5.2 │ └─ @oclif/plugin-help 5.1.12 └─ @oclif/plugin-version 1.0.4 ``` ## Upgrade the PDK Rust Libraries The PDK Rust library is the Rust code library used by a specific custom policy. Different custom policies might use different PDK library versions. To upgrade the PDK Rust code libraries, modify the `pdk` `dependency` and `pdk-test` `dev-dependency` versions in the `cargo.toml` file of the custom policy. The `pdk` and `pdk-test` versions must match and your Anypoint CLI PDK plugin must support the specified version. In the following example, both dependency versions are `1.6.0`. Modify it to your required version: ```toml [dependencies] pdk = { version = "1.6.0" } [dev-dependencies] pdk-test = { version = "1.6.0" } ``` ## Upgrade the Anypoint Cargo Plugin The Anypoint Cargo plugin extends the functionality of Cargo for use with the PDK Rust Libraries. To upgrade your Anypoint Cargo plugin: 1. Open the `Makefile` of your custom policy. 2. Find the `install-cargo-anypoint` target, for example: install-cargo-anypoint: cargo install cargo-anypoint@1.6.0 3. Change the version after the `@` character to the required version. 4. Save the `Makefile`. 5. Execute the `make setup` command: ```ssh make setup ``` > [!NOTE] Executing the `make setup` command for a certain policy installs that policy’s > Anypoint Cargo plugin version. 6. Execute the following command to verify the correct version is installed: ```ssh cargo anypoint --version ``` ## Upgrade a Policy’s Rust Version To upgrade your Policy’s Rust version: 1. Ensure the Rust version is downloaded on your device. To update Rust, see [Rust Requirements for Using PDK](https://docs.mulesoft.com/pdk/1.9/policies-pdk-prerequisites#rust-requirements). 2. Open the `cargo.toml` of your custom policy. 3. Find your Rust version. For example: rust-version = "1.87.0" 4. Update your Rust version. For example: rust-version = "1.88.0" 5. Save the `cargo.toml` file. ## Upgrade a Policy’s WASI Crate To upgrade your Rust WebAssembly System Interface (WASI) Crate from `wasm32-wasi` to `wasm32-wasip1`: 1. Open the `Makefile` of your custom policy. 2. Find this line: TARGET := wasm32-wasi 3. Replace `wasm32-wasi` with `wasm32-wasip1`: TARGET := wasm32-wasip1 4. Save the `Makefile`. 5. Open the `tests/common/mod.rs` of your custom policy. 6. Find the this line: pub const POLICY\_DIR: &str = concat!(env!("CARGO\_MANIFEST\_DIR"), "/target/wasm32-wasi/release"); 7. Replace `wasm32-wasi` with `wasm32-wasip1`: pub const POLICY\_DIR: &str = concat!(env!("CARGO\_MANIFEST\_DIR"), "/target/wasm32-wasip1/release"); 8. Save the `mod.rs` file. ## Upgrade the Anypoint CLI PDK Plugin for Policies with Versions Earlier Than 1.8.0 Depending on you configuration, when upgrading to 1.8.0 you might experience these issues: - [Tokio Runtime Feature Compatibility Error](#feature-compatibility-issue-on-tokio) - [Compilation Error When Constructing Metadata-Related Structs](#compilation-error-structs) ### Tokio Runtime Feature Compatibility Error When using a Tokio runtime for testing, sometimes a compilation occurs similar to this error when building for WebAssembly: ```text error: Only features sync,macros,io-util,rt,time are supported on wasm. --> /Users/test-user/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.51.1/src/lib.rs:478:1 | 478 | compile_error!("Only features sync,macros,io-util,rt,time are supported on wasm."); ``` To solve this error, under the `[package]` section of your policy’s `Cargo.toml`, add `resolver = "2"`. This enables your compiler resolve dependencies separately for production code and for test dependencies. ```toml [package] name = "my_policy" version = "1.0.0" rust-version = "1.88.0" edition = "2018" resolver = "2" ``` ### Compilation Error When Constructing Metadata-Related Structs When constructing Metadata-related structs, sometimes an error similar to this one occurs: ```text error[E0639]: cannot create non-exhaustive struct using struct expression --> test-policy/src/lib.rs:90:32 | 90 | flex_metadata: FlexMetadata { | ________________________________^ 91 | | flex_name: "test_flex_name".to_string(), 92 | | flex_version: "1.0.0".to_string(), 93 | | }, | |_________________^ ``` PDK 1.8.0 marks metadata-related structs as `#[non_exhaustive]` so that you can add new metadata fields without breaking changes. When constructing these structs manually in tests, use one of these approaches: - Use the new default constructor and set each field to the value you need. For example: ```rust let mut metadata = FlexMetadata::default(); metadata.flex_name = "test_flex_name".to_string(); metadata.flex_version = "1.0.0".to_string(); ``` - Add the `non_exhaustive!` macro from the [`non-exhaustive`](https://crates.io/crates/non-exhaustive) crate to the `[dev-dependencies]` in your `cargo.toml` files: ```toml [dev-dependencies] non-exhaustive = "0.1.1" ``` This enables you to use the default construct as shown in this example: ```rust use non_exhaustive::non_exhaustive; // ... let metadata = non_exhaustive!(FlexMetadata { flex_name: "test_flex_name".to_string(), flex_version: "1.0.0".to_string(), }); ``` ## Upgrade the Anypoint CLI PDK Plugin for Policies with Versions Earlier Than 1.7.0 In PDK 1.7.0, the name of the Anypoint CLI PDK plugin changes from `anypoint-cli-pdk-plugin` to `anypoint-pdk-plugin`. To upgrade your earlier versions, uninstall the old plugin before installing the new one: 1. Uninstall the old plugin: ```ssh anypoint-cli-v4 plugins:uninstall anypoint-cli-pdk-plugin ``` 2. Install the new plugin: ```ssh anypoint-cli-v4 plugins:install anypoint-pdk-plugin ``` ## Upgrade Policies with Versions Earlier Than 1.6.0 In PDK 1.6.0, the PDK libraries moved from the Anypoint platform to [crates.io](https://crates.io/crates/pdk). When upgrading from versions earlier than 1.6.0, you must update the dependencies to point to the new location. To upgrade policies with versions earlier than 1.6.0: 1. [Upgrade the Anypoint CLI PDK plugin](#anypoint-cli-pdk-plugin). 2. [Upgrade the PDK Rust libraries](#anypoint-rust-version). 3. Upgrade the PDK Rust libraries: 1. Locate the `dependencies` and `dev-dependencies` in your policy’s `cargo.toml`: ```toml [dependencies] pdk = { version = "1.5.0", registry = "anypoint" } [dev-dependencies] pdk-test = { version = "1.5.0", registry = "anypoint" } ``` 2. Update the version and remove the `registry = "anypoint"`: ```toml [dependencies] pdk = { version = "1.6.0" } [dev-dependencies] pdk-test = { version = "1.6.0" } ``` 3. Save the `cargo.toml` file. 4. Upgrade the Anypoint Cargo Plugin: 1. Open the `Makefile` of your custom policy. 2. Find the `install-cargo-anypoint` target, for example: install-cargo-anypoint: cargo install cargo-anypoint@1.5.0 --registry anypoint --config .cargo/config.toml 3. Update the version and remove the `--registry` and `--config` flags: install-cargo-anypoint: cargo install cargo-anypoint@1.6.0 4. Save the `Makefile` file. 5. Remove the Anypoint Platform registry references from your `setup` command: 1. Open the `Makefile` of your custom policy. 2. Find the `setup` target, for example: .PHONY: setup setup: registry-creds login install-cargo-anypoint ## Setup all required tools to build cargo fetch 3. Remove the Anypoint Platform registry references: .PHONY: setup setup: install-cargo-anypoint ## Setup all required tools to build cargo fetch 4. Delete the `login` and `registry-creds` targets. For example: To find an example of the targets, see the [`login` and `registry-creds` targets in the Certification Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/certs/Makefile#L68-L85). 5. Save the `Makefile` file. 6. Execute `make setup` to install the updated versions. ## See Also - [Prerequisites for Omni Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/1.9/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Upgrading PDK > For the full documentation index, see: https://docs.mulesoft.com/llms.txt To update a custom policy project, you must update each of these separately versioned Omni Gateway Policy Development Kit (PDK) components: - Anypoint CLI PDK plugin - PDK Rust libraries - Anypoint Cargo plugin - Policy Rust Version - WASI Crate When you upgrade your Anypoint CLI PDK plugin, you must manually upgrade the PDK Rust libraries and Anypoint Cargo plugin to be compatible with the new plugin version. All the PDK custom policies on your device use the same Anypoint CLI PDK plugin. When you create a new custom policy project, the PDK Rust libraries and Anypoint Cargo plugin versions are the same as the Anypoint CLI PDK plugin used to create the project and are independent from other policy projects. To upgrade a custom policy project created with an earlier version of the Anypoint CLI PDK plugin: 1. [Upgrade the Anypoint CLI PDK Plugin](#anypoint-cli-pdk-plugin) 2. [Upgrade the PDK Rust Libraries](#pdk-rust-libraries) 3. [Upgrade the Anypoint Cargo Plugin](#anypoint-cargo-plugin) 4. [Upgrade a Policy’s Rust Version](#anypoint-rust-version) 5. [Upgrade a Policy’s WASI Crate](#anypoint-wasi-crate) ## Upgrade the Anypoint CLI PDK Plugin When editing a custom policy created with an earlier plugin version, ensure your [PDK Rust libraries](#pdk-rust-libraries) and [Anypoint Cargo plugin](#anypoint-cargo-plugin) match your Anypoint CLI PDK plugin version. To upgrade your Anypoint CLI PDK plugin to the latest version, execute the following command: ```ssh anypoint-cli-v4 plugins:install anypoint-pdk-plugin ``` \+ NOTE: In PDK 1.7.0, the name of the Anypoint CLI PDK plugin changes from `anypoint-cli-pdk-plugin` to `anypoint-pdk-plugin`. To install the new plugin, see [Upgrade the Anypoint CLI PDK Plugin for Policies with Versions Earlier Than 1.7.0](#upgrade-anypoint-cli-pdk-plugin-earlier-1.7.0). To verify your current plugin version, execute the following command: ```ssh anypoint-cli-v4 plugins ``` For example, the following PDK plugin version is `1.7.0`: ```ssh anypoint-pdk-plugin 1.7.0 ├─ anypoint-cli-command 1.5.2 │ └─ @oclif/plugin-help 5.1.12 └─ @oclif/plugin-version 1.0.4 ``` ## Upgrade the PDK Rust Libraries The PDK Rust library is the Rust code library used by a specific custom policy. Different custom policies might use different PDK library versions. To upgrade the PDK Rust code libraries, modify the `pdk` `dependency` and `pdk-test` `dev-dependency` versions in the `cargo.toml` file of the custom policy. The `pdk` and `pdk-test` versions must match and your Anypoint CLI PDK plugin must support the specified version. In the following example, both dependency versions are `1.6.0`. Modify it to your required version: ```toml [dependencies] pdk = { version = "1.6.0" } [dev-dependencies] pdk-test = { version = "1.6.0" } ``` ## Upgrade the Anypoint Cargo Plugin The Anypoint Cargo plugin extends the functionality of Cargo for use with the PDK Rust Libraries. To upgrade your Anypoint Cargo plugin: 1. Open the `Makefile` of your custom policy. 2. Find the `install-cargo-anypoint` target, for example: install-cargo-anypoint: cargo install cargo-anypoint@1.6.0 3. Change the version after the `@` character to the required version. 4. Save the `Makefile`. 5. Execute the `make setup` command: ```ssh make setup ``` > [!NOTE] Executing the `make setup` command for a certain policy installs that policy’s > Anypoint Cargo plugin version. 6. Execute the following command to verify the correct version is installed: ```ssh cargo anypoint --version ``` ## Upgrade a Policy’s Rust Version To upgrade your Policy’s Rust version: 1. Ensure the Rust version is downloaded on your device. To update Rust, see [Rust Requirements for Using PDK](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites#rust-requirements). 2. Open the `cargo.toml` of your custom policy. 3. Find your Rust version. For example: rust-version = "1.87.0" 4. Update your Rust version. For example: rust-version = "1.88.0" 5. Save the `cargo.toml` file. ## Upgrade a Policy’s WASI Crate To upgrade your Rust WebAssembly System Interface (WASI) Crate from `wasm32-wasi` to `wasm32-wasip1`: 1. Open the `Makefile` of your custom policy. 2. Find this line: TARGET := wasm32-wasi 3. Replace `wasm32-wasi` with `wasm32-wasip1`: TARGET := wasm32-wasip1 4. Save the `Makefile`. 5. Open the `tests/common/mod.rs` of your custom policy. 6. Find the this line: pub const POLICY\_DIR: &str = concat!(env!("CARGO\_MANIFEST\_DIR"), "/target/wasm32-wasi/release"); 7. Replace `wasm32-wasi` with `wasm32-wasip1`: pub const POLICY\_DIR: &str = concat!(env!("CARGO\_MANIFEST\_DIR"), "/target/wasm32-wasip1/release"); 8. Save the `mod.rs` file. ## Upgrade the Anypoint CLI PDK Plugin for Policies with Versions Earlier Than 1.8.0 Depending on you configuration, when upgrading to 1.8.0 you might experience these issues: - [Tokio Runtime Feature Compatibility Error](#feature-compatibility-issue-on-tokio) - [Compilation Error When Constructing Metadata-Related Structs](#compilation-error-structs) ### Tokio Runtime Feature Compatibility Error When using a Tokio runtime for testing, sometimes a compilation occurs similar to this error when building for WebAssembly: ```text error: Only features sync,macros,io-util,rt,time are supported on wasm. --> /Users/test-user/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.51.1/src/lib.rs:478:1 | 478 | compile_error!("Only features sync,macros,io-util,rt,time are supported on wasm."); ``` To solve this error, under the `[package]` section of your policy’s `Cargo.toml`, add `resolver = "2"`. This enables your compiler resolve dependencies separately for production code and for test dependencies. ```toml [package] name = "my_policy" version = "1.0.0" rust-version = "1.88.0" edition = "2018" resolver = "2" ``` ### Compilation Error When Constructing Metadata-Related Structs When constructing Metadata-related structs, sometimes an error similar to this one occurs: ```text error[E0639]: cannot create non-exhaustive struct using struct expression --> test-policy/src/lib.rs:90:32 | 90 | flex_metadata: FlexMetadata { | ________________________________^ 91 | | flex_name: "test_flex_name".to_string(), 92 | | flex_version: "1.0.0".to_string(), 93 | | }, | |_________________^ ``` PDK 1.8.0 marks metadata-related structs as `#[non_exhaustive]` so that you can add new metadata fields without breaking changes. When constructing these structs manually in tests, use one of these approaches: - Use the new default constructor and set each field to the value you need. For example: ```rust let mut metadata = FlexMetadata::default(); metadata.flex_name = "test_flex_name".to_string(); metadata.flex_version = "1.0.0".to_string(); ``` - Add the `non_exhaustive!` macro from the [`non-exhaustive`](https://crates.io/crates/non-exhaustive) crate to the `[dev-dependencies]` in your `cargo.toml` files: ```toml [dev-dependencies] non-exhaustive = "0.1.1" ``` This enables you to use the default construct as shown in this example: ```rust use non_exhaustive::non_exhaustive; // ... let metadata = non_exhaustive!(FlexMetadata { flex_name: "test_flex_name".to_string(), flex_version: "1.0.0".to_string(), }); ``` ## Upgrade the Anypoint CLI PDK Plugin for Policies with Versions Earlier Than 1.7.0 In PDK 1.7.0, the name of the Anypoint CLI PDK plugin changes from `anypoint-cli-pdk-plugin` to `anypoint-pdk-plugin`. To upgrade your earlier versions, uninstall the old plugin before installing the new one: 1. Uninstall the old plugin: ```ssh anypoint-cli-v4 plugins:uninstall anypoint-cli-pdk-plugin ``` 2. Install the new plugin: ```ssh anypoint-cli-v4 plugins:install anypoint-pdk-plugin ``` ## Upgrade Policies with Versions Earlier Than 1.6.0 In PDK 1.6.0, the PDK libraries moved from the Anypoint platform to [crates.io](https://crates.io/crates/pdk). When upgrading from versions earlier than 1.6.0, you must update the dependencies to point to the new location. To upgrade policies with versions earlier than 1.6.0: 1. [Upgrade the Anypoint CLI PDK plugin](#anypoint-cli-pdk-plugin). 2. [Upgrade the PDK Rust libraries](#anypoint-rust-version). 3. Upgrade the PDK Rust libraries: 1. Locate the `dependencies` and `dev-dependencies` in your policy’s `cargo.toml`: ```toml [dependencies] pdk = { version = "1.5.0", registry = "anypoint" } [dev-dependencies] pdk-test = { version = "1.5.0", registry = "anypoint" } ``` 2. Update the version and remove the `registry = "anypoint"`: ```toml [dependencies] pdk = { version = "1.6.0" } [dev-dependencies] pdk-test = { version = "1.6.0" } ``` 3. Save the `cargo.toml` file. 4. Upgrade the Anypoint Cargo Plugin: 1. Open the `Makefile` of your custom policy. 2. Find the `install-cargo-anypoint` target, for example: install-cargo-anypoint: cargo install cargo-anypoint@1.5.0 --registry anypoint --config .cargo/config.toml 3. Update the version and remove the `--registry` and `--config` flags: install-cargo-anypoint: cargo install cargo-anypoint@1.6.0 4. Save the `Makefile` file. 5. Remove the Anypoint Platform registry references from your `setup` command: 1. Open the `Makefile` of your custom policy. 2. Find the `setup` target, for example: .PHONY: setup setup: registry-creds login install-cargo-anypoint ## Setup all required tools to build cargo fetch 3. Remove the Anypoint Platform registry references: .PHONY: setup setup: install-cargo-anypoint ## Setup all required tools to build cargo fetch 4. Delete the `login` and `registry-creds` targets. For example: To find an example of the targets, see the [`login` and `registry-creds` targets in the Certification Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/certs/Makefile#L68-L85). 5. Save the `Makefile` file. 6. Execute `make setup` to install the updated versions. ## See Also - [Prerequisites for Omni Gateway Policy Development Kit (PDK)](https://docs.mulesoft.com/pdk/latest/policies-pdk-prerequisites) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Uploading Custom Policies to Exchange > For the full documentation index, see: https://docs.mulesoft.com/llms.txt During the custom policy development cycle, you can upload your policy to Exchange to create a new Exchange asset to manage the policy’s version and to distribute it to other users. For more information about Exchange, see [Anypoint Exchange Overview](https://docs.mulesoft.com/exchange/). For custom policies running in Local Mode, it is not required to publish your policy to Exchange. However, Exchange is a useful version control tool. It is your responsibility to distribute custom policies for Local Mode use. When uploading your policy to Exchange, you can choose to either: - [Publish a Custom Policy](#publish) Publish a policy if the policy version is still in development. This enables you to test and edit the policy version. - [Release a Custom Policy](#release) Release the policy to create a definitive version of the policy. After releasing the policy, you must create a new policy version to edit the policy. Every time you publish or release a policy, you create a new `stable` asset in Exchange. For more information about `stable` state assets, see [Stable State Assets](https://docs.mulesoft.com/exchange/lifecycle#stablet-state). After you upload your policy to Exchange, see [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.2/policies-pdk-apply-policies). ## Before You Begin - Ensure that the Connected App you used to authenticate to the [Anypoint Platform CLI](https://docs.mulesoft.com/pdk/1.2/policies-pdk-prerequisites#cli) has the `Exchange Contributor` scope applied. - [Compile your Policy](https://docs.mulesoft.com/pdk/1.2/policies-pdk-compile-policies). ## Publish a Custom Policy To publish a custom policy, run the `make publish` command from the policy’s root folder: ```ssh make publish ``` After publishing the asset, a new asset labeled `DEV` appears in Exchange: ![Policy appears in Exchange labeled DEV.](/mulesoft/current/en-us/pdk/1.2/_images/pdk-dev-asset.png) The asset’s group ID, asset ID, and asset version (GAV) appear, similar to the following: - **groupID**: `` - **assetID**: `my-custom-policy-dev` When publishing a policy, `-dev` appears appended to the **assetID**. - **version**: `1.0.0-20230618115723` When publishing a policy, a timestamp appears appended to the **version**. Rerunning the publish command creates a new version of the policy asset with an updated timestamp. Previously published policy versions are still available. ## Release a Custom Policy To release a custom policy, run the `make release` command from the policy’s root folder: ```ssh make release ``` Released policies are not labeled `DEV`. The asset’s GAV appears similar to the following: - **groupID**: `` - **assetID**: `my-custom-policy` Released policies do not have `-dev` appended to their **assetID**. - **version**: `1.0.0` Released policies do not have a timestamp appended to their **assetID**. After releasing the asset, rerunning the `make release` command results in a conflict error. To begin working on the next version of your policy, update the version number in the `Cargo.toml` file. For example, if the latest version is `1.0.0`, update the `Cargo.toml` file as follows to begin working on a minor release: ```toml name = "my-custom-policy" version = "1.1.0" ``` ## See Also - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.2/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.2/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Uploading Custom Policies to Exchange > For the full documentation index, see: https://docs.mulesoft.com/llms.txt During the custom policy development cycle, you can upload your policy to Exchange to create a new Exchange asset to manage the policy’s version and to distribute it to other users. For more information about Exchange, see [Anypoint Exchange Overview](https://docs.mulesoft.com/exchange/). For custom policies running in Local Mode, it is not required to publish your policy to Exchange. However, Exchange is a useful version control tool. It is your responsibility to distribute custom policies for Local Mode use. When uploading your policy to Exchange, you can choose to either: - [Publish a Custom Policy](#publish) Publish a policy if the policy version is still in development. This enables you to test and edit the policy version. - [Release a Custom Policy](#release) Release the policy to create a definitive version of the policy. After releasing the policy, you must create a new policy version to edit the policy. Every time you publish or release a policy, you create a new `stable` asset in Exchange. For more information about `stable` state assets, see [Stable State Assets](https://docs.mulesoft.com/exchange/lifecycle#stablet-state). After you upload your policy to Exchange, see [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.3/policies-pdk-apply-policies). ## Before You Begin - Ensure that the Connected App you used to authenticate to the [Anypoint Platform CLI](https://docs.mulesoft.com/pdk/1.3/policies-pdk-prerequisites#cli) has the `Exchange Contributor` scope applied. - [Compile your Policy](https://docs.mulesoft.com/pdk/1.3/policies-pdk-compile-policies). ## Publish a Custom Policy To publish a custom policy, run the `make publish` command from the policy’s root folder: ```ssh make publish ``` After publishing the asset, a new asset labeled `DEV` appears in Exchange: ![Policy appears in Exchange labeled DEV.](/mulesoft/current/en-us/pdk/1.3/_images/pdk-dev-asset.png) The asset’s group ID, asset ID, and asset version (GAV) appear, similar to the following: - **groupID**: `` - **assetID**: `my-custom-policy-dev` When publishing a policy, `-dev` appears appended to the **assetID**. - **version**: `1.0.0-20230618115723` When publishing a policy, a timestamp appears appended to the **version**. Rerunning the publish command creates a new version of the policy asset with an updated timestamp. Previously published policy versions are still available. ## Release a Custom Policy To release a custom policy, run the `make release` command from the policy’s root folder: ```ssh make release ``` Released policies are not labeled `DEV`. The asset’s GAV appears similar to the following: - **groupID**: `` - **assetID**: `my-custom-policy` Released policies do not have `-dev` appended to their **assetID**. - **version**: `1.0.0` Released policies do not have a timestamp appended to their **assetID**. After releasing the asset, rerunning the `make release` command results in a conflict error. To begin working on the next version of your policy, update the version number in the `Cargo.toml` file. For example, if the latest version is `1.0.0`, update the `Cargo.toml` file as follows to begin working on a minor release: ```toml name = "my-custom-policy" version = "1.1.0" ``` ## See Also - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.3/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.3/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Uploading Custom Policies to Exchange > For the full documentation index, see: https://docs.mulesoft.com/llms.txt During the custom policy development cycle, you can upload your policy to Exchange to create a new Exchange asset to manage the policy’s version and to distribute it to other users. For more information about Exchange, see [Anypoint Exchange Overview](https://docs.mulesoft.com/exchange/). For custom policies running in Local Mode, it is not required to publish your policy to Exchange. However, Exchange is a useful version control tool. It is your responsibility to distribute custom policies for Local Mode use. When uploading your policy to Exchange, you can choose to either: - [Publish a Custom Policy](#publish) Publish a policy if the policy version is still in development. This enables you to test and edit the policy version. - [Release a Custom Policy](#release) Release the policy to create a definitive version of the policy. After releasing the policy, you must create a new policy version to edit the policy. Every time you publish or release a policy, you create a new `stable` asset in Exchange. For more information about `stable` state assets, see [Stable State Assets](https://docs.mulesoft.com/exchange/lifecycle#stablet-state). After you upload your policy to Exchange, see [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.4/policies-pdk-apply-policies). ## Before You Begin - Ensure that the Connected App you used to authenticate to the [Anypoint Platform CLI](https://docs.mulesoft.com/pdk/1.4/policies-pdk-prerequisites#cli) has the `Exchange Contributor` scope applied. - [Compile your Policy](https://docs.mulesoft.com/pdk/1.4/policies-pdk-compile-policies). ## Publish a Custom Policy To publish a custom policy, run the `make publish` command from the policy’s root folder: ```ssh make publish ``` After publishing the asset, a new asset labeled `DEV` appears in Exchange: ![Policy appears in Exchange labeled DEV.](/mulesoft/current/en-us/pdk/1.4/_images/pdk-dev-asset.png) The asset’s group ID, asset ID, and asset version (GAV) appear, similar to the following: - **groupID**: `` - **assetID**: `my-custom-policy-dev` When publishing a policy, `-dev` appears appended to the **assetID**. - **version**: `1.0.0-20230618115723` When publishing a policy, a timestamp appears appended to the **version**. Rerunning the publish command creates a new version of the policy asset with an updated timestamp. Previously published policy versions are still available. ## Release a Custom Policy To release a custom policy, run the `make release` command from the policy’s root folder: ```ssh make release ``` Released policies are not labeled `DEV`. The asset’s GAV appears similar to the following: - **groupID**: `` - **assetID**: `my-custom-policy` Released policies do not have `-dev` appended to their **assetID**. - **version**: `1.0.0` Released policies do not have a timestamp appended to their **assetID**. After releasing the asset, rerunning the `make release` command results in a conflict error. To begin working on the next version of your policy, update the version number in the `Cargo.toml` file. For example, if the latest version is `1.0.0`, update the `Cargo.toml` file as follows to begin working on a minor release: ```toml name = "my-custom-policy" version = "1.1.0" ``` ## See Also - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.4/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.4/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Uploading Custom Policies to Exchange > For the full documentation index, see: https://docs.mulesoft.com/llms.txt During the custom policy development cycle, you can upload your policy to Exchange to create a new Exchange asset to manage the policy’s version and to distribute it to other users. For more information about Exchange, see [Anypoint Exchange Overview](https://docs.mulesoft.com/exchange/). For custom policies running in Local Mode, it is not required to publish your policy to Exchange. However, Exchange is a useful version control tool. It is your responsibility to distribute custom policies for Local Mode use. When uploading your policy to Exchange, you can choose to either: - [Publish a Custom Policy](#publish) Publish a policy if the policy version is still in development. This enables you to test and edit the policy version. - [Release a Custom Policy](#release) Release the policy to create a definitive version of the policy. After releasing the policy, you must create a new policy version to edit the policy. Every time you publish or release a policy, you create a new `stable` asset in Exchange. For more information about `stable` state assets, see [Stable State Assets](https://docs.mulesoft.com/exchange/lifecycle#stablet-state). After you upload your policy to Exchange, see [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.5/policies-pdk-apply-policies). ## Before You Begin - Ensure that the Connected App you used to authenticate to the [Anypoint Platform CLI](https://docs.mulesoft.com/pdk/1.5/policies-pdk-prerequisites#cli) has the `Exchange Contributor` scope applied. - [Compile your Policy](https://docs.mulesoft.com/pdk/1.5/policies-pdk-compile-policies). ## Publish a Custom Policy To publish a custom policy, run the `make publish` command from the policy’s root folder: ```ssh make publish ``` After publishing the asset, a new asset labeled `DEV` appears in Exchange: ![Policy appears in Exchange labeled DEV.](/mulesoft/current/en-us/pdk/1.5/_images/pdk-dev-asset.png) The asset’s group ID, asset ID, and asset version (GAV) appear, similar to the following: - **groupID**: `` - **assetID**: `my-custom-policy-dev` When publishing a policy, `-dev` appears appended to the **assetID**. - **version**: `1.0.0-20230618115723` When publishing a policy, a timestamp appears appended to the **version**. Rerunning the publish command creates a new version of the policy asset with an updated timestamp. Previously published policy versions are still available. ## Release a Custom Policy To release a custom policy, run the `make release` command from the policy’s root folder: ```ssh make release ``` Released policies are not labeled `DEV`. The asset’s GAV appears similar to the following: - **groupID**: `` - **assetID**: `my-custom-policy` Released policies do not have `-dev` appended to their **assetID**. - **version**: `1.0.0` Released policies do not have a timestamp appended to their **assetID**. After releasing the asset, rerunning the `make release` command results in a conflict error. To begin working on the next version of your policy, update the version number in the `Cargo.toml` file. For example, if the latest version is `1.0.0`, update the `Cargo.toml` file as follows to begin working on a minor release: ```toml name = "my-custom-policy" version = "1.1.0" ``` ## See Also - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.5/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.5/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Uploading Custom Policies to Exchange > For the full documentation index, see: https://docs.mulesoft.com/llms.txt During the custom policy development cycle, you can upload your policy to Exchange to create a new Exchange asset to manage the policy’s version and to distribute it to other users. For more information about Exchange, see [Anypoint Exchange Overview](https://docs.mulesoft.com/exchange/). For custom policies running in Local Mode, it is not required to publish your policy to Exchange. However, Exchange is a useful version control tool. It is your responsibility to distribute custom policies for Local Mode use. When uploading your policy to Exchange, you can choose to either: - [Publish a Custom Policy](#publish) Publish a policy if the policy version is still in development. This enables you to test and edit the policy version. - [Release a Custom Policy](#release) Release the policy to create a definitive version of the policy. After releasing the policy, you must create a new policy version to edit the policy. Every time you publish or release a policy, you create a new `stable` asset in Exchange. For more information about `stable` state assets, see [Stable State Assets](https://docs.mulesoft.com/exchange/lifecycle#stablet-state). After you upload your policy to Exchange, see [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.6/policies-pdk-apply-policies). ## Before You Begin - Ensure that the Connected App you used to authenticate to the [Anypoint Platform CLI](https://docs.mulesoft.com/pdk/1.6/policies-pdk-prerequisites#cli) has the `Exchange Contributor` scope applied. - [Compile your Policy](https://docs.mulesoft.com/pdk/1.6/policies-pdk-compile-policies). ## Publish a Custom Policy To publish a custom policy, run the `make publish` command from the policy’s root folder: ```ssh make publish ``` After publishing the asset, a new asset labeled `DEV` appears in Exchange: ![Policy appears in Exchange labeled DEV.](/mulesoft/current/en-us/pdk/1.6/_images/pdk-dev-asset.png) The asset’s group ID, asset ID, and asset version (GAV) appear, similar to the following: - **groupID**: `` - **assetID**: `my-custom-policy-dev` When publishing a policy, `-dev` appears appended to the **assetID**. - **version**: `1.0.0-20230618115723` When publishing a policy, a timestamp appears appended to the **version**. Rerunning the publish command creates a new version of the policy asset with an updated timestamp. Previously published policy versions are still available. ## Release a Custom Policy To release a custom policy, run the `make release` command from the policy’s root folder: ```ssh make release ``` Released policies are not labeled `DEV`. The asset’s GAV appears similar to the following: - **groupID**: `` - **assetID**: `my-custom-policy` Released policies do not have `-dev` appended to their **assetID**. - **version**: `1.0.0` Released policies do not have a timestamp appended to their **assetID**. After releasing the asset, rerunning the `make release` command results in a conflict error. To begin working on the next version of your policy, update the version number in the `Cargo.toml` file. For example, if the latest version is `1.0.0`, update the `Cargo.toml` file as follows to begin working on a minor release: ```toml name = "my-custom-policy" version = "1.1.0" ``` ## See Also - [Applying Custom Policies](https://docs.mulesoft.com/pdk/1.6/policies-pdk-apply-policies) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.6/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Using Contracts Validation Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt [Contracts](https://docs.mulesoft.com/api-manager/latest/api-contracts-landing-page) between API instances and applications give the application access to the instance based on SLA tiers. Client applications can validate their contracts by providing credentials that consist of the client ID and client secret. The PDK Contracts Validation library provides functions to validate client credentials and implement a custom client ID enforcement policy. Only one contract at a time can exist between an API instance and an application. ## Extract Client Credentials The Contracts Validation library is available from the `pdk::contracts` module. The module provides the `ContractValidator` object to validate client credentials represented by the `ClientId` and `ClientSecret` objects. Validate authentication and authorization credentials with the `ContractValidator::authenticate()` and `ContractValidator::authorize()` methods: ```Rust impl ContractValidator { pub fn authenticate(client_id: &ClientId, client_secret: &ClientSecret) -> Result; pub fn authorize(client_id: &ClientId, client_secret: &ClientSecret) -> Result; } ``` Both methods return a `ClientData` struct that holds the client ID, client name, and SLA ID fields: ```Rust pub struct ClientData { pub client_id: String, pub client_name: String, pub sla_id: Option, } ``` ## Validate Request Authentication and Authorization Headers Authenticate a request by extracting the client credentials from the request and then invoke the `ClientValidation::authenticate()` method. The `pdk::contracts` module provides the `basic_auth_credentials()` helper function to extract Basic Authentication credentials from request headers: ```Rust pub fn basic_auth_credentials(request_headers_state: &RequestHeadersState) -> Result<(ClientId, ClientSecret), BasicAuthError>; ``` This code snippet provides a simple authentication-request filter: ```Rust async fn my_authentication_filter( state: RequestHeadersState, authentication: Authentication, validator: &ContractValidator, ) -> Flow<()> { // Extract credentials let (client_id, client_secret) = match basic_auth_credentials(&state) { Ok(credentials) => credentials, Err(e) => { logger::info!("Invalid credentials: {e}"); // For simplicity, we are using a user-defined `unathorized_response()` // helper function for building responses. return Flow::Break(unauthorized_response("Invalid credentials", 401)); } }; // Validate authentication let validation = validator.authenticate(&client_id, &client_secret); let client_data = match validation { Ok(client_data) => client_data, Err(e) => { logger::info!("Invalid authentication: {e}"); return Flow::Break(unauthorized_response("Invalid authentication", 403)); } }; // Update the current authentication if let Some(mut auth) = authentication.authentication() { auth.client_id = Some(client_data.client_id); auth.client_name = Some(client_data.client_name); authentication.set_authentication(Some(&auth)); } Flow::Continue(()) } ``` This code snippet provides a simple authorization-request filter: ```Rust async fn my_authorization_filter( state: RequestHeadersState, validator: &ContractValidator, ) -> Flow<()> { // Extract client id with a user defined helper `extract_client_id()` function, let client_id = match extract_client_id(&state) { Ok(credentials) => credentials, Err(e) => { logger::info!("Invalid credentials: {e}"); // For simplicity, we are using a user-defined `unathorized_response()` // helper function for building responses. return Flow::Break(unauthorized_response("Invalid credentials", 401)); } }; // Validate authorization let validation = validator.authorize(&client_id); if let Err(e) = validation { logger::info!("Invalid authentication: {e}"); return Flow::Break(unauthorized_response("Invalid authentication", 403)); } Flow::Continue(()) } ``` ## Implement Custom Extraction for Client Credentials Invoke the `ClientId::new()` and `ClientSecret::new()` methods to extract credentials: ```Rust impl ClientId { pub fn new(client_id: String) -> Self; } impl ClientSecret { pub fn new(client_secret: String) -> Self; } ``` After extracting the credentials, initialize a set of the credentials: ```Rust fn initialize_credentials(raw_client_id: String, raw_client_secret) -> (ClientId, ClientSecret) { let client_id = ClientId::new(raw_client_id); let client_secret = ClientSecret::new(raw_client_secret); (client_id, client_secret) } ``` > [!NOTE] For security, the content of `ClientSecret` is deleted after use, and the `Debug` trait > doesn’t reveal the `ClientSecret` content. ## Inject the ContractValidator Object Inject the `ContractValidator` object into the `#[entrypoint]` function and share its reference to the request filter: ```Rust #[entrypoint] async fn configure(launcher: Launcher, validator: ContractValidator) -> Result<(), LaunchError> { let filter = on_request(|state, authentication| my_authentication_filter(state, authentication, &validator)); launcher.launch(filter).await?; OK(()) } ``` ### Poll the Local Contracts Database The `ContractValidator` object maintains a local copy of the contracts database. You must poll the local copy periodically to maintain a valid copy of the contracts. Invoke the `ContractValidator::update_contracts()` method to poll the local copy: ```Rust impl ContractValidator { pub async fn update_contracts(&self) -> Result<(), UpdateError>; } ``` If the `ContractValidator::update_contracts()` method returns an error that specifies a connectivity problem occurred during the contracts database polling, you must implement the retry and error handling heuristics. To do this, invoke `ContractValidator::update_contracts()` in a period specified by the `ContractValidator::UPDATE_PERIOD` constant: ```Rust async fn update_my_contracts(validator: &ContractValidator, clock: Clock) { // Configure a new timer let timer = clock.period(ContractValidator::UPDATE_PERIOD); loop { // Update result handling should be customized by the programmer let update_result = validator.update_contracts().await; // Wait for the next tick if !timer.next_tick().await { // If no more ticks are available, finish the task. return; } } } ``` The contract database initialization period specifies when to poll the contracts database at a higher frequency than update period. The `ContractValidator::INITIALIZATION_PERIOD` specifies the interval required by the initial polling: ```Rust async fn initialize_my_contracts(validator: &ContractValidator, clock: Clock) { // Configure a new timer let timer = clock.period(ContractValidator::UPDATE_PERIOD); loop { // Update result handling should be customized by the programmer let update_result = validator.update_contracts().await; // Wait for the next tick if !timer.next_tick().await { // If no more ticks are available, finish the task. return; } } } ``` This snippet shows a complete contract polling task with initialization and update polling periods: ```Rust async fn update_my_contracts(validator: &ContractValidator, clock: Clock) { let initialization_timer = clock.period(ContractValidator::INITIALIZATION_PERIOD); loop { if validator.update_contracts().await.is_ok() { logger::info!("Contracts storage initialized."); break; } if !initialization_timer.next_tick().await { logger::info!("Tick event suspended."); break; } } let update_timer = initialization_timer .release() .period(ContractValidator::UPDATE_PERIOD); loop { let _ = validator.update_contracts().await; if !update_timer.next_tick().await { logger::info!("Tick event suspended."); break; } logger::info!("Retrying contracts storage initialization."); } } ``` Because the contracts database polling task must run concurrently with the `Launcher::launch()` task, use the `join!()` macro from the [futures](https://crates.io/crates/futures) crate to join both tasks. This snippet implements a complete `#[entrypoint]` function with polling and launching: ```Rust #[entrypoint] async fn configure(launcher: Launcher, clock: Clock,validator: ContractValidator) -> Result<(), LauncherError> { let filter = on_request(|state, authentication| my_authentication_filter(state, authentication, &validator)); let (_, launcher_result) = join! { update_my_contracts(&validator, clock), launcher.launch(filter), }; launcher_result } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-timer) - [Client Applications, Contracts, and Credentials](https://docs.mulesoft.com/api-manager/latest/api-contracts-landing-page) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Using Contracts Validation Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt [Contracts](https://docs.mulesoft.com/api-manager/latest/api-contracts-landing-page) between API instances and applications give the application access to the instance based on SLA tiers. Client applications can validate their contracts by providing credentials that consist of the client ID and client secret. The PDK Contracts Validation library provides functions to validate client credentials and implement a custom client ID enforcement policy. Only one contract at a time can exist between an API instance and an application. ## Extract Client Credentials The Contracts Validation library is available from the `pdk::contracts` module. The module provides the `ContractValidator` object to validate client credentials represented by the `ClientId` and `ClientSecret` objects. Validate authentication and authorization credentials with the `ContractValidator::authenticate()` and `ContractValidator::authorize()` methods: ```Rust impl ContractValidator { pub fn authenticate(client_id: &ClientId, client_secret: &ClientSecret) -> Result; pub fn authorize(client_id: &ClientId, client_secret: &ClientSecret) -> Result; } ``` Both methods return a `ClientData` struct that holds the client ID, client name, and SLA ID fields: ```Rust pub struct ClientData { pub client_id: String, pub client_name: String, pub sla_id: Option, } ``` ## Validate Request Authentication and Authorization Headers Authenticate a request by extracting the client credentials from the request and then invoke the `ClientValidation::authenticate()` method. The `pdk::contracts` module provides the `basic_auth_credentials()` helper function to extract Basic Authentication credentials from request headers: ```Rust pub fn basic_auth_credentials(request_headers_state: &RequestHeadersState) -> Result<(ClientId, ClientSecret), BasicAuthError>; ``` This code snippet provides a simple authentication-request filter: ```Rust async fn my_authentication_filter( state: RequestHeadersState, authentication: Authentication, validator: &ContractValidator, ) -> Flow<()> { // Extract credentials let (client_id, client_secret) = match basic_auth_credentials(&state) { Ok(credentials) => credentials, Err(e) => { logger::info!("Invalid credentials: {e}"); // For simplicity, we are using a user-defined `unathorized_response()` // helper function for building responses. return Flow::Break(unauthorized_response("Invalid credentials", 401)); } }; // Validate authentication let validation = validator.authenticate(&client_id, &client_secret); let client_data = match validation { Ok(client_data) => client_data, Err(e) => { logger::info!("Invalid authentication: {e}"); return Flow::Break(unauthorized_response("Invalid authentication", 403)); } }; // Update the current authentication if let Some(mut auth) = authentication.authentication() { auth.client_id = Some(client_data.client_id); auth.client_name = Some(client_data.client_name); authentication.set_authentication(Some(&auth)); } Flow::Continue(()) } ``` This code snippet provides a simple authorization-request filter: ```Rust async fn my_authorization_filter( state: RequestHeadersState, validator: &ContractValidator, ) -> Flow<()> { // Extract client id with a user defined helper `extract_client_id()` function, let client_id = match extract_client_id(&state) { Ok(credentials) => credentials, Err(e) => { logger::info!("Invalid credentials: {e}"); // For simplicity, we are using a user-defined `unathorized_response()` // helper function for building responses. return Flow::Break(unauthorized_response("Invalid credentials", 401)); } }; // Validate authorization let validation = validator.authorize(&client_id); if let Err(e) = validation { logger::info!("Invalid authentication: {e}"); return Flow::Break(unauthorized_response("Invalid authentication", 403)); } Flow::Continue(()) } ``` ## Implement Custom Extraction for Client Credentials Invoke the `ClientId::new()` and `ClientSecret::new()` methods to extract credentials: ```Rust impl ClientId { pub fn new(client_id: String) -> Self; } impl ClientSecret { pub fn new(client_secret: String) -> Self; } ``` After extracting the credentials, initialize a set of the credentials: ```Rust fn initialize_credentials(raw_client_id: String, raw_client_secret) -> (ClientId, ClientSecret) { let client_id = ClientId::new(raw_client_id); let client_secret = ClientSecret::new(raw_client_secret); (client_id, client_secret) } ``` > [!NOTE] For security, the content of `ClientSecret` is deleted after use, and the `Debug` trait > doesn’t reveal the `ClientSecret` content. ## Inject the ContractValidator Object Inject the `ContractValidator` object into the `#[entrypoint]` function and share its reference to the request filter: ```Rust #[entrypoint] async fn configure(launcher: Launcher, validator: ContractValidator) -> Result<(), LaunchError> { let filter = on_request(|state, authentication| my_authentication_filter(state, authentication, &validator)); launcher.launch(filter).await?; OK(()) } ``` ### Poll the Local Contracts Database The `ContractValidator` object maintains a local copy of the contracts database. You must poll the local copy periodically to maintain a valid copy of the contracts. Invoke the `ContractValidator::update_contracts()` method to poll the local copy: ```Rust impl ContractValidator { pub async fn update_contracts(&self) -> Result<(), UpdateError>; } ``` If the `ContractValidator::update_contracts()` method returns an error that specifies a connectivity problem occurred during the contracts database polling, you must implement the retry and error handling heuristics. To do this, invoke `ContractValidator::update_contracts()` in a period specified by the `ContractValidator::UPDATE_PERIOD` constant: ```Rust async fn update_my_contracts(validator: &ContractValidator, clock: Clock) { // Configure a new timer let timer = clock.period(ContractValidator::UPDATE_PERIOD); loop { // Update result handling should be customized by the programmer let update_result = validator.update_contracts().await; // Wait for the next tick if !timer.next_tick().await { // If no more ticks are available, finish the task. return; } } } ``` The contract database initialization period specifies when to poll the contracts database at a higher frequency than update period. The `ContractValidator::INITIALIZATION_PERIOD` specifies the interval required by the initial polling: ```Rust async fn initialize_my_contracts(validator: &ContractValidator, clock: Clock) { // Configure a new timer let timer = clock.period(ContractValidator::UPDATE_PERIOD); loop { // Update result handling should be customized by the programmer let update_result = validator.update_contracts().await; // Wait for the next tick if !timer.next_tick().await { // If no more ticks are available, finish the task. return; } } } ``` This snippet shows a complete contract polling task with initialization and update polling periods: ```Rust async fn update_my_contracts(validator: &ContractValidator, clock: Clock) { let initialization_timer = clock.period(ContractValidator::INITIALIZATION_PERIOD); loop { if validator.update_contracts().await.is_ok() { logger::info!("Contracts storage initialized."); break; } if !initialization_timer.next_tick().await { logger::info!("Tick event suspended."); break; } } let update_timer = initialization_timer .release() .period(ContractValidator::UPDATE_PERIOD); loop { let _ = validator.update_contracts().await; if !update_timer.next_tick().await { logger::info!("Tick event suspended."); break; } logger::info!("Retrying contracts storage initialization."); } } ``` Because the contracts database polling task must run concurrently with the `Launcher::launch()` task, use the `join!()` macro from the [futures](https://crates.io/crates/futures) crate to join both tasks. This snippet implements a complete `#[entrypoint]` function with polling and launching: ```Rust #[entrypoint] async fn configure(launcher: Launcher, clock: Clock,validator: ContractValidator) -> Result<(), LauncherError> { let filter = on_request(|state, authentication| my_authentication_filter(state, authentication, &validator)); let (_, launcher_result) = join! { update_my_contracts(&validator, clock), launcher.launch(filter), }; launcher_result } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-timer) - [Client Applications, Contracts, and Credentials](https://docs.mulesoft.com/api-manager/latest/api-contracts-landing-page) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Using Contracts Validation Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt [Contracts](https://docs.mulesoft.com/api-manager/latest/api-contracts-landing-page) between API instances and applications give the application access to the instance based on SLA tiers. Client applications can validate their contracts by providing credentials that consist of the client ID and client secret. The PDK Contracts Validation library provides functions to validate client credentials and implement a custom client ID enforcement policy. Only one contract at a time can exist between an API instance and an application. ## Extract Client Credentials The Contracts Validation library is available from the `pdk::contracts` module. The module provides the `ContractValidator` object to validate client credentials represented by the `ClientId` and `ClientSecret` objects. Validate authentication and authorization credentials with the `ContractValidator::authenticate()` and `ContractValidator::authorize()` methods: ```Rust impl ContractValidator { pub fn authenticate(client_id: &ClientId, client_secret: &ClientSecret) -> Result; pub fn authorize(client_id: &ClientId, client_secret: &ClientSecret) -> Result; } ``` Both methods return a `ClientData` struct that holds the client ID, client name, and SLA ID fields: ```Rust pub struct ClientData { pub client_id: String, pub client_name: String, pub sla_id: Option, } ``` ## Validate Request Authentication and Authorization Headers Authenticate a request by extracting the client credentials from the request and then invoke the `ClientValidation::authenticate()` method. The `pdk::contracts` module provides the `basic_auth_credentials()` helper function to extract Basic Authentication credentials from request headers: ```Rust pub fn basic_auth_credentials(request_headers_state: &RequestHeadersState) -> Result<(ClientId, ClientSecret), BasicAuthError>; ``` This code snippet provides a simple authentication-request filter: ```Rust async fn my_authentication_filter( state: RequestHeadersState, authentication: Authentication, validator: &ContractValidator, ) -> Flow<()> { // Extract credentials let (client_id, client_secret) = match basic_auth_credentials(&state) { Ok(credentials) => credentials, Err(e) => { logger::info!("Invalid credentials: {e}"); // For simplicity, we are using a user-defined `unathorized_response()` // helper function for building responses. return Flow::Break(unauthorized_response("Invalid credentials", 401)); } }; // Validate authentication let validation = validator.authenticate(&client_id, &client_secret); let client_data = match validation { Ok(client_data) => client_data, Err(e) => { logger::info!("Invalid authentication: {e}"); return Flow::Break(unauthorized_response("Invalid authentication", 403)); } }; // Update the current authentication if let Some(mut auth) = authentication.authentication() { auth.client_id = Some(client_data.client_id); auth.client_name = Some(client_data.client_name); authentication.set_authentication(Some(&auth)); } Flow::Continue(()) } ``` This code snippet provides a simple authorization-request filter: ```Rust async fn my_authorization_filter( state: RequestHeadersState, validator: &ContractValidator, ) -> Flow<()> { // Extract client id with a user defined helper `extract_client_id()` function, let client_id = match extract_client_id(&state) { Ok(credentials) => credentials, Err(e) => { logger::info!("Invalid credentials: {e}"); // For simplicity, we are using a user-defined `unathorized_response()` // helper function for building responses. return Flow::Break(unauthorized_response("Invalid credentials", 401)); } }; // Validate authorization let validation = validator.authorize(&client_id); if let Err(e) = validation { logger::info!("Invalid authentication: {e}"); return Flow::Break(unauthorized_response("Invalid authentication", 403)); } Flow::Continue(()) } ``` ## Implement Custom Extraction for Client Credentials Invoke the `ClientId::new()` and `ClientSecret::new()` methods to extract credentials: ```Rust impl ClientId { pub fn new(client_id: String) -> Self; } impl ClientSecret { pub fn new(client_secret: String) -> Self; } ``` After extracting the credentials, initialize a set of the credentials: ```Rust fn initialize_credentials(raw_client_id: String, raw_client_secret) -> (ClientId, ClientSecret) { let client_id = ClientId::new(raw_client_id); let client_secret = ClientSecret::new(raw_client_secret); (client_id, client_secret) } ``` > [!NOTE] For security, the content of `ClientSecret` is deleted after use, and the `Debug` trait > doesn’t reveal the `ClientSecret` content. ## Inject the ContractValidator Object Inject the `ContractValidator` object into the `#[entrypoint]` function and share its reference to the request filter: ```Rust #[entrypoint] async fn configure(launcher: Launcher, validator: ContractValidator) -> Result<(), LaunchError> { let filter = on_request(|state, authentication| my_authentication_filter(state, authentication, &validator)); launcher.launch(filter).await?; OK(()) } ``` ### Poll the Local Contracts Database The `ContractValidator` object maintains a local copy of the contracts database. You must poll the local copy periodically to maintain a valid copy of the contracts. Invoke the `ContractValidator::update_contracts()` method to poll the local copy: ```Rust impl ContractValidator { pub async fn update_contracts(&self) -> Result<(), UpdateError>; } ``` If the `ContractValidator::update_contracts()` method returns an error that specifies a connectivity problem occurred during the contracts database polling, you must implement the retry and error handling heuristics. To do this, invoke `ContractValidator::update_contracts()` in a period specified by the `ContractValidator::UPDATE_PERIOD` constant: ```Rust async fn update_my_contracts(validator: &ContractValidator, clock: Clock) { // Configure a new timer let timer = clock.period(ContractValidator::UPDATE_PERIOD); loop { // Update result handling should be customized by the programmer let update_result = validator.update_contracts().await; // Wait for the next tick if !timer.next_tick().await { // If no more ticks are available, finish the task. return; } } } ``` The contract database initialization period specifies when to poll the contracts database at a higher frequency than update period. The `ContractValidator::INITIALIZATION_PERIOD` specifies the interval required by the initial polling: ```Rust async fn initialize_my_contracts(validator: &ContractValidator, clock: Clock) { // Configure a new timer let timer = clock.period(ContractValidator::UPDATE_PERIOD); loop { // Update result handling should be customized by the programmer let update_result = validator.update_contracts().await; // Wait for the next tick if !timer.next_tick().await { // If no more ticks are available, finish the task. return; } } } ``` This snippet shows a complete contract polling task with initialization and update polling periods: ```Rust async fn update_my_contracts(validator: &ContractValidator, clock: Clock) { let initialization_timer = clock.period(ContractValidator::INITIALIZATION_PERIOD); loop { if validator.update_contracts().await.is_ok() { logger::info!("Contracts storage initialized."); break; } if !initialization_timer.next_tick().await { logger::info!("Tick event suspended."); break; } } let update_timer = initialization_timer .release() .period(ContractValidator::UPDATE_PERIOD); loop { let _ = validator.update_contracts().await; if !update_timer.next_tick().await { logger::info!("Tick event suspended."); break; } logger::info!("Retrying contracts storage initialization."); } } ``` Because the contracts database polling task must run concurrently with the `Launcher::launch()` task, use the `join!()` macro from the [futures](https://crates.io/crates/futures) crate to join both tasks. This snippet implements a complete `#[entrypoint]` function with polling and launching: ```Rust #[entrypoint] async fn configure(launcher: Launcher, clock: Clock,validator: ContractValidator) -> Result<(), LauncherError> { let filter = on_request(|state, authentication| my_authentication_filter(state, authentication, &validator)); let (_, launcher_result) = join! { update_my_contracts(&validator, clock), launcher.launch(filter), }; launcher_result } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-timer) - [Client Applications, Contracts, and Credentials](https://docs.mulesoft.com/api-manager/latest/api-contracts-landing-page) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Using Contracts Validation Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt [Contracts](https://docs.mulesoft.com/api-manager/latest/api-contracts-landing-page) between API instances and applications give the application access to the instance based on SLA tiers. Client applications can validate their contracts by providing credentials that consist of the client ID and client secret. The PDK Contracts Validation library provides functions to validate client credentials and implement a custom client ID enforcement policy. Only one contract at a time can exist between an API instance and an application. ## Extract Client Credentials The Contracts Validation library is available from the `pdk::contracts` module. The module provides the `ContractValidator` object to validate client credentials represented by the `ClientId` and `ClientSecret` objects. Validate authentication and authorization credentials with the `ContractValidator::authenticate()` and `ContractValidator::authorize()` methods: ```Rust impl ContractValidator { pub fn authenticate(client_id: &ClientId, client_secret: &ClientSecret) -> Result; pub fn authorize(client_id: &ClientId, client_secret: &ClientSecret) -> Result; } ``` Both methods return a `ClientData` struct that holds the client ID, client name, and SLA ID fields: ```Rust pub struct ClientData { pub client_id: String, pub client_name: String, pub sla_id: Option, } ``` ## Validate Request Authentication and Authorization Headers Authenticate a request by extracting the client credentials from the request and then invoke the `ClientValidation::authenticate()` method. The `pdk::contracts` module provides the `basic_auth_credentials()` helper function to extract Basic Authentication credentials from request headers: ```Rust pub fn basic_auth_credentials(request_headers_state: &RequestHeadersState) -> Result<(ClientId, ClientSecret), BasicAuthError>; ``` This code snippet provides a simple authentication-request filter: ```Rust async fn my_authentication_filter( state: RequestHeadersState, authentication: Authentication, validator: &ContractValidator, ) -> Flow<()> { // Extract credentials let (client_id, client_secret) = match basic_auth_credentials(&state) { Ok(credentials) => credentials, Err(e) => { logger::info!("Invalid credentials: {e}"); // For simplicity, we are using a user-defined `unathorized_response()` // helper function for building responses. return Flow::Break(unauthorized_response("Invalid credentials", 401)); } }; // Validate authentication let validation = validator.authenticate(&client_id, &client_secret); let client_data = match validation { Ok(client_data) => client_data, Err(e) => { logger::info!("Invalid authentication: {e}"); return Flow::Break(unauthorized_response("Invalid authentication", 403)); } }; // Update the current authentication if let Some(mut auth) = authentication.authentication() { auth.client_id = Some(client_data.client_id); auth.client_name = Some(client_data.client_name); authentication.set_authentication(Some(&auth)); } Flow::Continue(()) } ``` This code snippet provides a simple authorization-request filter: ```Rust async fn my_authorization_filter( state: RequestHeadersState, validator: &ContractValidator, ) -> Flow<()> { // Extract client id with a user defined helper `extract_client_id()` function, let client_id = match extract_client_id(&state) { Ok(credentials) => credentials, Err(e) => { logger::info!("Invalid credentials: {e}"); // For simplicity, we are using a user-defined `unathorized_response()` // helper function for building responses. return Flow::Break(unauthorized_response("Invalid credentials", 401)); } }; // Validate authorization let validation = validator.authorize(&client_id); if let Err(e) = validation { logger::info!("Invalid authentication: {e}"); return Flow::Break(unauthorized_response("Invalid authentication", 403)); } Flow::Continue(()) } ``` ## Implement Custom Extraction for Client Credentials Invoke the `ClientId::new()` and `ClientSecret::new()` methods to extract credentials: ```Rust impl ClientId { pub fn new(client_id: String) -> Self; } impl ClientSecret { pub fn new(client_secret: String) -> Self; } ``` After extracting the credentials, initialize a set of the credentials: ```Rust fn initialize_credentials(raw_client_id: String, raw_client_secret) -> (ClientId, ClientSecret) { let client_id = ClientId::new(raw_client_id); let client_secret = ClientSecret::new(raw_client_secret); (client_id, client_secret) } ``` > [!NOTE] For security, the content of `ClientSecret` is deleted after use, and the `Debug` trait > doesn’t reveal the `ClientSecret` content. ## Inject the ContractValidator Object Inject the `ContractValidator` object into the `#[entrypoint]` function and share its reference to the request filter: ```Rust #[entrypoint] async fn configure(launcher: Launcher, validator: ContractValidator) -> Result<(), LaunchError> { let filter = on_request(|state, authentication| my_authentication_filter(state, authentication, &validator)); launcher.launch(filter).await?; OK(()) } ``` ### Poll the Local Contracts Database The `ContractValidator` object maintains a local copy of the contracts database. You must poll the local copy periodically to maintain a valid copy of the contracts. Invoke the `ContractValidator::update_contracts()` method to poll the local copy: ```Rust impl ContractValidator { pub async fn update_contracts(&self) -> Result<(), UpdateError>; } ``` If the `ContractValidator::update_contracts()` method returns an error that specifies a connectivity problem occurred during the contracts database polling, you must implement the retry and error handling heuristics. To do this, invoke `ContractValidator::update_contracts()` in a period specified by the `ContractValidator::UPDATE_PERIOD` constant: ```Rust async fn update_my_contracts(validator: &ContractValidator, clock: Clock) { // Configure a new timer let timer = clock.period(ContractValidator::UPDATE_PERIOD); loop { // Update result handling should be customized by the programmer let update_result = validator.update_contracts().await; // Wait for the next tick if !timer.next_tick().await { // If no more ticks are available, finish the task. return; } } } ``` The contract database initialization period specifies when to poll the contracts database at a higher frequency than update period. The `ContractValidator::INITIALIZATION_PERIOD` specifies the interval required by the initial polling: ```Rust async fn initialize_my_contracts(validator: &ContractValidator, clock: Clock) { // Configure a new timer let timer = clock.period(ContractValidator::UPDATE_PERIOD); loop { // Update result handling should be customized by the programmer let update_result = validator.update_contracts().await; // Wait for the next tick if !timer.next_tick().await { // If no more ticks are available, finish the task. return; } } } ``` This snippet shows a complete contract polling task with initialization and update polling periods: ```Rust async fn update_my_contracts(validator: &ContractValidator, clock: Clock) { let initialization_timer = clock.period(ContractValidator::INITIALIZATION_PERIOD); loop { if validator.update_contracts().await.is_ok() { logger::info!("Contracts storage initialized."); break; } if !initialization_timer.next_tick().await { logger::info!("Tick event suspended."); break; } } let update_timer = initialization_timer .release() .period(ContractValidator::UPDATE_PERIOD); loop { let _ = validator.update_contracts().await; if !update_timer.next_tick().await { logger::info!("Tick event suspended."); break; } logger::info!("Retrying contracts storage initialization."); } } ``` Because the contracts database polling task must run concurrently with the `Launcher::launch()` task, use the `join!()` macro from the [futures](https://crates.io/crates/futures) crate to join both tasks. This snippet implements a complete `#[entrypoint]` function with polling and launching: ```Rust #[entrypoint] async fn configure(launcher: Launcher, clock: Clock,validator: ContractValidator) -> Result<(), LauncherError> { let filter = on_request(|state, authentication| my_authentication_filter(state, authentication, &validator)); let (_, launcher_result) = join! { update_my_contracts(&validator, clock), launcher.launch(filter), }; launcher_result } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-timer) - [Client Applications, Contracts, and Credentials](https://docs.mulesoft.com/api-manager/latest/api-contracts-landing-page) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Using Contracts Validation Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt [Contracts](https://docs.mulesoft.com/api-manager/latest/api-contracts-landing-page) between API instances and applications give the application access to the instance based on SLA tiers. Client applications can validate their contracts by providing credentials that consist of the client ID and client secret. The PDK Contracts Validation library provides functions to validate client credentials and implement a custom client ID enforcement policy. Only one contract at a time can exist between an API instance and an application. ## Extract Client Credentials The Contracts Validation library is available from the `pdk::contracts` module. The module provides the `ContractValidator` object to validate client credentials represented by the `ClientId` and `ClientSecret` objects. Validate authentication and authorization credentials with the `ContractValidator::authenticate()` and `ContractValidator::authorize()` methods: ```Rust impl ContractValidator { pub fn authenticate(client_id: &ClientId, client_secret: &ClientSecret) -> Result; pub fn authorize(client_id: &ClientId, client_secret: &ClientSecret) -> Result; } ``` Both methods return a `ClientData` struct that holds the client ID, client name, and SLA ID fields: ```Rust pub struct ClientData { pub client_id: String, pub client_name: String, pub sla_id: Option, } ``` ## Validate Request Authentication and Authorization Headers Authenticate a request by extracting the client credentials from the request and then invoke the `ClientValidation::authenticate()` method. The `pdk::contracts` module provides the `basic_auth_credentials()` helper function to extract Basic Authentication credentials from request headers: ```Rust pub fn basic_auth_credentials(request_headers_state: &RequestHeadersState) -> Result<(ClientId, ClientSecret), BasicAuthError>; ``` This code snippet provides a simple authentication-request filter: ```Rust async fn my_authentication_filter( state: RequestHeadersState, authentication: Authentication, validator: &ContractValidator, ) -> Flow<()> { // Extract credentials let (client_id, client_secret) = match basic_auth_credentials(&state) { Ok(credentials) => credentials, Err(e) => { logger::info!("Invalid credentials: {e}"); // For simplicity, we are using a user-defined `unathorized_response()` // helper function for building responses. return Flow::Break(unauthorized_response("Invalid credentials", 401)); } }; // Validate authentication let validation = validator.authenticate(&client_id, &client_secret); let client_data = match validation { Ok(client_data) => client_data, Err(e) => { logger::info!("Invalid authentication: {e}"); return Flow::Break(unauthorized_response("Invalid authentication", 403)); } }; // Update the current authentication if let Some(mut auth) = authentication.authentication() { auth.client_id = Some(client_data.client_id); auth.client_name = Some(client_data.client_name); authentication.set_authentication(Some(&auth)); } Flow::Continue(()) } ``` This code snippet provides a simple authorization-request filter: ```Rust async fn my_authorization_filter( state: RequestHeadersState, validator: &ContractValidator, ) -> Flow<()> { // Extract client id with a user defined helper `extract_client_id()` function, let client_id = match extract_client_id(&state) { Ok(credentials) => credentials, Err(e) => { logger::info!("Invalid credentials: {e}"); // For simplicity, we are using a user-defined `unathorized_response()` // helper function for building responses. return Flow::Break(unauthorized_response("Invalid credentials", 401)); } }; // Validate authorization let validation = validator.authorize(&client_id); if let Err(e) = validation { logger::info!("Invalid authentication: {e}"); return Flow::Break(unauthorized_response("Invalid authentication", 403)); } Flow::Continue(()) } ``` ## Implement Custom Extraction for Client Credentials Invoke the `ClientId::new()` and `ClientSecret::new()` methods to extract credentials: ```Rust impl ClientId { pub fn new(client_id: String) -> Self; } impl ClientSecret { pub fn new(client_secret: String) -> Self; } ``` After extracting the credentials, initialize a set of the credentials: ```Rust fn initialize_credentials(raw_client_id: String, raw_client_secret) -> (ClientId, ClientSecret) { let client_id = ClientId::new(raw_client_id); let client_secret = ClientSecret::new(raw_client_secret); (client_id, client_secret) } ``` > [!NOTE] For security, the content of `ClientSecret` is deleted after use, and the `Debug` trait > doesn’t reveal the `ClientSecret` content. ## Inject the ContractValidator Object Inject the `ContractValidator` object into the `#[entrypoint]` function and share its reference to the request filter: ```Rust #[entrypoint] async fn configure(launcher: Launcher, validator: ContractValidator) -> Result<(), LaunchError> { let filter = on_request(|state, authentication| my_authentication_filter(state, authentication, &validator)); launcher.launch(filter).await?; OK(()) } ``` ### Poll the Local Contracts Database The `ContractValidator` object maintains a local copy of the contracts database. You must poll the local copy periodically to maintain a valid copy of the contracts. Invoke the `ContractValidator::update_contracts()` method to poll the local copy: ```Rust impl ContractValidator { pub async fn update_contracts(&self) -> Result<(), UpdateError>; } ``` If the `ContractValidator::update_contracts()` method returns an error that specifies a connectivity problem occurred during the contracts database polling, you must implement the retry and error handling heuristics. To do this, invoke `ContractValidator::update_contracts()` in a period specified by the `ContractValidator::UPDATE_PERIOD` constant: ```Rust async fn update_my_contracts(validator: &ContractValidator, clock: Clock) { // Configure a new timer let timer = clock.period(ContractValidator::UPDATE_PERIOD); loop { // Update result handling should be customized by the programmer let update_result = validator.update_contracts().await; // Wait for the next tick if !timer.next_tick().await { // If no more ticks are available, finish the task. return; } } } ``` The contract database initialization period specifies when to poll the contracts database at a higher frequency than update period. The `ContractValidator::INITIALIZATION_PERIOD` specifies the interval required by the initial polling: ```Rust async fn initialize_my_contracts(validator: &ContractValidator, clock: Clock) { // Configure a new timer let timer = clock.period(ContractValidator::UPDATE_PERIOD); loop { // Update result handling should be customized by the programmer let update_result = validator.update_contracts().await; // Wait for the next tick if !timer.next_tick().await { // If no more ticks are available, finish the task. return; } } } ``` This snippet shows a complete contract polling task with initialization and update polling periods: ```Rust async fn update_my_contracts(validator: &ContractValidator, clock: Clock) { let initialization_timer = clock.period(ContractValidator::INITIALIZATION_PERIOD); loop { if validator.update_contracts().await.is_ok() { logger::info!("Contracts storage initialized."); break; } if !initialization_timer.next_tick().await { logger::info!("Tick event suspended."); break; } } let update_timer = initialization_timer .release() .period(ContractValidator::UPDATE_PERIOD); loop { let _ = validator.update_contracts().await; if !update_timer.next_tick().await { logger::info!("Tick event suspended."); break; } logger::info!("Retrying contracts storage initialization."); } } ``` Because the contracts database polling task must run concurrently with the `Launcher::launch()` task, use the `join!()` macro from the [futures](https://crates.io/crates/futures) crate to join both tasks. This snippet implements a complete `#[entrypoint]` function with polling and launching: ```Rust #[entrypoint] async fn configure(launcher: Launcher, clock: Clock,validator: ContractValidator) -> Result<(), LauncherError> { let filter = on_request(|state, authentication| my_authentication_filter(state, authentication, &validator)); let (_, launcher_result) = join! { update_my_contracts(&validator, clock), launcher.launch(filter), }; launcher_result } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-timer) - [Client Applications, Contracts, and Credentials](https://docs.mulesoft.com/api-manager/latest/api-contracts-landing-page) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Using Contracts Validation Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt [Contracts](https://docs.mulesoft.com/api-manager/latest/api-contracts-landing-page) between API instances and applications give the application access to the instance based on SLA tiers. Client applications can validate their contracts by providing credentials that consist of the client ID and client secret. The PDK Contracts Validation library provides functions to validate client credentials and implement a custom client ID enforcement policy. Only one contract at a time can exist between an API instance and an application. ## Extract Client Credentials The Contracts Validation library is available from the `pdk::contracts` module. The module provides the `ContractValidator` object to validate client credentials represented by the `ClientId` and `ClientSecret` objects. Validate authentication and authorization credentials with the `ContractValidator::authenticate()` and `ContractValidator::authorize()` methods: ```Rust impl ContractValidator { pub fn authenticate(client_id: &ClientId, client_secret: &ClientSecret) -> Result; pub fn authorize(client_id: &ClientId, client_secret: &ClientSecret) -> Result; } ``` Both methods return a `ClientData` struct that holds the client ID, client name, and SLA ID fields: ```Rust pub struct ClientData { pub client_id: String, pub client_name: String, pub sla_id: Option, } ``` ## Validate Request Authentication and Authorization Headers Authenticate a request by extracting the client credentials from the request and then invoke the `ClientValidation::authenticate()` method. The `pdk::contracts` module provides the `basic_auth_credentials()` helper function to extract Basic Authentication credentials from request headers: ```Rust pub fn basic_auth_credentials(request_headers_state: &RequestHeadersState) -> Result<(ClientId, ClientSecret), BasicAuthError>; ``` This code snippet provides a simple authentication-request filter: ```Rust async fn my_authentication_filter( state: RequestHeadersState, authentication: Authentication, validator: &ContractValidator, ) -> Flow<()> { // Extract credentials let (client_id, client_secret) = match basic_auth_credentials(&state) { Ok(credentials) => credentials, Err(e) => { logger::info!("Invalid credentials: {e}"); // For simplicity, we are using a user-defined `unathorized_response()` // helper function for building responses. return Flow::Break(unauthorized_response("Invalid credentials", 401)); } }; // Validate authentication let validation = validator.authenticate(&client_id, &client_secret); let client_data = match validation { Ok(client_data) => client_data, Err(e) => { logger::info!("Invalid authentication: {e}"); return Flow::Break(unauthorized_response("Invalid authentication", 403)); } }; // Update the current authentication if let Some(mut auth) = authentication.authentication() { auth.client_id = Some(client_data.client_id); auth.client_name = Some(client_data.client_name); authentication.set_authentication(Some(&auth)); } Flow::Continue(()) } ``` This code snippet provides a simple authorization-request filter: ```Rust async fn my_authorization_filter( state: RequestHeadersState, validator: &ContractValidator, ) -> Flow<()> { // Extract client id with a user defined helper `extract_client_id()` function, let client_id = match extract_client_id(&state) { Ok(credentials) => credentials, Err(e) => { logger::info!("Invalid credentials: {e}"); // For simplicity, we are using a user-defined `unathorized_response()` // helper function for building responses. return Flow::Break(unauthorized_response("Invalid credentials", 401)); } }; // Validate authorization let validation = validator.authorize(&client_id); if let Err(e) = validation { logger::info!("Invalid authentication: {e}"); return Flow::Break(unauthorized_response("Invalid authentication", 403)); } Flow::Continue(()) } ``` ## Implement Custom Extraction for Client Credentials Invoke the `ClientId::new()` and `ClientSecret::new()` methods to extract credentials: ```Rust impl ClientId { pub fn new(client_id: String) -> Self; } impl ClientSecret { pub fn new(client_secret: String) -> Self; } ``` After extracting the credentials, initialize a set of the credentials: ```Rust fn initialize_credentials(raw_client_id: String, raw_client_secret) -> (ClientId, ClientSecret) { let client_id = ClientId::new(raw_client_id); let client_secret = ClientSecret::new(raw_client_secret); (client_id, client_secret) } ``` > [!NOTE] For security, the content of `ClientSecret` is deleted after use, and the `Debug` trait > doesn’t reveal the `ClientSecret` content. ## Inject the ContractValidator Object Inject the `ContractValidator` object into the `#[entrypoint]` function and share its reference to the request filter: ```Rust #[entrypoint] async fn configure(launcher: Launcher, validator: ContractValidator) -> Result<(), LaunchError> { let filter = on_request(|state, authentication| my_authentication_filter(state, authentication, &validator)); launcher.launch(filter).await?; OK(()) } ``` ### Poll the Local Contracts Database The `ContractValidator` object maintains a local copy of the contracts database. You must poll the local copy periodically to maintain a valid copy of the contracts. Invoke the `ContractValidator::update_contracts()` method to poll the local copy: ```Rust impl ContractValidator { pub async fn update_contracts(&self) -> Result<(), UpdateError>; } ``` If the `ContractValidator::update_contracts()` method returns an error that specifies a connectivity problem occurred during the contracts database polling, you must implement the retry and error handling heuristics. To do this, invoke `ContractValidator::update_contracts()` in a period specified by the `ContractValidator::UPDATE_PERIOD` constant: ```Rust async fn update_my_contracts(validator: &ContractValidator, clock: Clock) { // Configure a new timer let timer = clock.period(ContractValidator::UPDATE_PERIOD); loop { // Update result handling should be customized by the programmer let update_result = validator.update_contracts().await; // Wait for the next tick if !timer.next_tick().await { // If no more ticks are available, finish the task. return; } } } ``` The contract database initialization period specifies when to poll the contracts database at a higher frequency than update period. The `ContractValidator::INITIALIZATION_PERIOD` specifies the interval required by the initial polling: ```Rust async fn initialize_my_contracts(validator: &ContractValidator, clock: Clock) { // Configure a new timer let timer = clock.period(ContractValidator::UPDATE_PERIOD); loop { // Update result handling should be customized by the programmer let update_result = validator.update_contracts().await; // Wait for the next tick if !timer.next_tick().await { // If no more ticks are available, finish the task. return; } } } ``` This snippet shows a complete contract polling task with initialization and update polling periods: ```Rust async fn update_my_contracts(validator: &ContractValidator, clock: Clock) { let initialization_timer = clock.period(ContractValidator::INITIALIZATION_PERIOD); loop { if validator.update_contracts().await.is_ok() { logger::info!("Contracts storage initialized."); break; } if !initialization_timer.next_tick().await { logger::info!("Tick event suspended."); break; } } let update_timer = initialization_timer .release() .period(ContractValidator::UPDATE_PERIOD); loop { let _ = validator.update_contracts().await; if !update_timer.next_tick().await { logger::info!("Tick event suspended."); break; } logger::info!("Retrying contracts storage initialization."); } } ``` Because the contracts database polling task must run concurrently with the `Launcher::launch()` task, use the `join!()` macro from the [futures](https://crates.io/crates/futures) crate to join both tasks. This snippet implements a complete `#[entrypoint]` function with polling and launching: ```Rust #[entrypoint] async fn configure(launcher: Launcher, clock: Clock,validator: ContractValidator) -> Result<(), LauncherError> { let filter = on_request(|state, authentication| my_authentication_filter(state, authentication, &validator)); let (_, launcher_result) = join! { update_my_contracts(&validator, clock), launcher.launch(filter), }; launcher_result } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-timer) - [Client Applications, Contracts, and Credentials](https://docs.mulesoft.com/api-manager/latest/api-contracts-landing-page) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Using Contracts Validation Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt [Contracts](https://docs.mulesoft.com/api-manager/latest/api-contracts-landing-page) between API instances and applications give the application access to the instance based on SLA tiers. Client applications can validate their contracts by providing credentials that consist of the client ID and client secret. The PDK Contracts Validation library provides functions to validate client credentials and implement a custom client ID enforcement policy. Only one contract at a time can exist between an API instance and an application. ## Extract Client Credentials The Contracts Validation library is available from the `pdk::contracts` module. The module provides the `ContractValidator` object to validate client credentials represented by the `ClientId` and `ClientSecret` objects. Validate authentication and authorization credentials with the `ContractValidator::authenticate()` and `ContractValidator::authorize()` methods: ```Rust impl ContractValidator { pub fn authenticate(client_id: &ClientId, client_secret: &ClientSecret) -> Result; pub fn authorize(client_id: &ClientId, client_secret: &ClientSecret) -> Result; } ``` Both methods return a `ClientData` struct that holds the client ID, client name, and SLA ID fields: ```Rust pub struct ClientData { pub client_id: String, pub client_name: String, pub sla_id: Option, } ``` ## Validate Request Authentication and Authorization Headers Authenticate a request by extracting the client credentials from the request and then invoke the `ClientValidation::authenticate()` method. The `pdk::contracts` module provides the `basic_auth_credentials()` helper function to extract Basic Authentication credentials from request headers: ```Rust pub fn basic_auth_credentials(request_headers_state: &RequestHeadersState) -> Result<(ClientId, ClientSecret), BasicAuthError>; ``` This code snippet provides a simple authentication-request filter: ```Rust async fn my_authentication_filter( state: RequestHeadersState, authentication: Authentication, validator: &ContractValidator, ) -> Flow<()> { // Extract credentials let (client_id, client_secret) = match basic_auth_credentials(&state) { Ok(credentials) => credentials, Err(e) => { logger::info!("Invalid credentials: {e}"); // For simplicity, we are using a user-defined `unathorized_response()` // helper function for building responses. return Flow::Break(unauthorized_response("Invalid credentials", 401)); } }; // Validate authentication let validation = validator.authenticate(&client_id, &client_secret); let client_data = match validation { Ok(client_data) => client_data, Err(e) => { logger::info!("Invalid authentication: {e}"); return Flow::Break(unauthorized_response("Invalid authentication", 403)); } }; // Update the current authentication if let Some(mut auth) = authentication.authentication() { auth.client_id = Some(client_data.client_id); auth.client_name = Some(client_data.client_name); authentication.set_authentication(Some(&auth)); } Flow::Continue(()) } ``` This code snippet provides a simple authorization-request filter: ```Rust async fn my_authorization_filter( state: RequestHeadersState, validator: &ContractValidator, ) -> Flow<()> { // Extract client id with a user defined helper `extract_client_id()` function, let client_id = match extract_client_id(&state) { Ok(credentials) => credentials, Err(e) => { logger::info!("Invalid credentials: {e}"); // For simplicity, we are using a user-defined `unathorized_response()` // helper function for building responses. return Flow::Break(unauthorized_response("Invalid credentials", 401)); } }; // Validate authorization let validation = validator.authorize(&client_id); if let Err(e) = validation { logger::info!("Invalid authentication: {e}"); return Flow::Break(unauthorized_response("Invalid authentication", 403)); } Flow::Continue(()) } ``` ## Implement Custom Extraction for Client Credentials Invoke the `ClientId::new()` and `ClientSecret::new()` methods to extract credentials: ```Rust impl ClientId { pub fn new(client_id: String) -> Self; } impl ClientSecret { pub fn new(client_secret: String) -> Self; } ``` After extracting the credentials, initialize a set of the credentials: ```Rust fn initialize_credentials(raw_client_id: String, raw_client_secret) -> (ClientId, ClientSecret) { let client_id = ClientId::new(raw_client_id); let client_secret = ClientSecret::new(raw_client_secret); (client_id, client_secret) } ``` > [!NOTE] For security, the content of `ClientSecret` is deleted after use, and the `Debug` trait > doesn’t reveal the `ClientSecret` content. ## Inject the ContractValidator Object Inject the `ContractValidator` object into the `#[entrypoint]` function and share its reference to the request filter: ```Rust #[entrypoint] async fn configure(launcher: Launcher, validator: ContractValidator) -> Result<(), LaunchError> { let filter = on_request(|state, authentication| my_authentication_filter(state, authentication, &validator)); launcher.launch(filter).await?; OK(()) } ``` ### Poll the Local Contracts Database The `ContractValidator` object maintains a local copy of the contracts database. You must poll the local copy periodically to maintain a valid copy of the contracts. Invoke the `ContractValidator::update_contracts()` method to poll the local copy: ```Rust impl ContractValidator { pub async fn update_contracts(&self) -> Result<(), UpdateError>; } ``` If the `ContractValidator::update_contracts()` method returns an error that specifies a connectivity problem occurred during the contracts database polling, you must implement the retry and error handling heuristics. To do this, invoke `ContractValidator::update_contracts()` in a period specified by the `ContractValidator::UPDATE_PERIOD` constant: ```Rust async fn update_my_contracts(validator: &ContractValidator, clock: Clock) { // Configure a new timer let timer = clock.period(ContractValidator::UPDATE_PERIOD); loop { // Update result handling should be customized by the programmer let update_result = validator.update_contracts().await; // Wait for the next tick if !timer.next_tick().await { // If no more ticks are available, finish the task. return; } } } ``` The contract database initialization period specifies when to poll the contracts database at a higher frequency than update period. The `ContractValidator::INITIALIZATION_PERIOD` specifies the interval required by the initial polling: ```Rust async fn initialize_my_contracts(validator: &ContractValidator, clock: Clock) { // Configure a new timer let timer = clock.period(ContractValidator::UPDATE_PERIOD); loop { // Update result handling should be customized by the programmer let update_result = validator.update_contracts().await; // Wait for the next tick if !timer.next_tick().await { // If no more ticks are available, finish the task. return; } } } ``` This snippet shows a complete contract polling task with initialization and update polling periods: ```Rust async fn update_my_contracts(validator: &ContractValidator, clock: Clock) { let initialization_timer = clock.period(ContractValidator::INITIALIZATION_PERIOD); loop { if validator.update_contracts().await.is_ok() { logger::info!("Contracts storage initialized."); break; } if !initialization_timer.next_tick().await { logger::info!("Tick event suspended."); break; } } let update_timer = initialization_timer .release() .period(ContractValidator::UPDATE_PERIOD); loop { let _ = validator.update_contracts().await; if !update_timer.next_tick().await { logger::info!("Tick event suspended."); break; } logger::info!("Retrying contracts storage initialization."); } } ``` Because the contracts database polling task must run concurrently with the `Launcher::launch()` task, use the `join!()` macro from the [futures](https://crates.io/crates/futures) crate to join both tasks. This snippet implements a complete `#[entrypoint]` function with polling and launching: ```Rust #[entrypoint] async fn configure(launcher: Launcher, clock: Clock,validator: ContractValidator) -> Result<(), LauncherError> { let filter = on_request(|state, authentication| my_authentication_filter(state, authentication, &validator)); let (_, launcher_result) = join! { update_my_contracts(&validator, clock), launcher.launch(filter), }; launcher_result } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-timer) - [Client Applications, Contracts, and Credentials](https://docs.mulesoft.com/api-manager/latest/api-contracts-landing-page) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Using Contracts Validation Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt [Contracts](https://docs.mulesoft.com/api-manager/latest/api-contracts-landing-page) between API instances and applications give the application access to the instance based on SLA tiers. Client applications can validate their contracts by providing credentials that consist of the client ID and client secret. The PDK Contracts Validation library provides functions to validate client credentials and implement a custom client ID enforcement policy. Only one contract at a time can exist between an API instance and an application. ## Extract Client Credentials The Contracts Validation library is available from the `pdk::contracts` module. The module provides the `ContractValidator` object to validate client credentials represented by the `ClientId` and `ClientSecret` objects. Validate authentication and authorization credentials with the `ContractValidator::authenticate()` and `ContractValidator::authorize()` methods: ```Rust impl ContractValidator { pub fn authenticate(client_id: &ClientId, client_secret: &ClientSecret) -> Result; pub fn authorize(client_id: &ClientId, client_secret: &ClientSecret) -> Result; } ``` Both methods return a `ClientData` struct that holds the client ID, client name, and SLA ID fields: ```Rust pub struct ClientData { pub client_id: String, pub client_name: String, pub sla_id: Option, } ``` ## Validate Request Authentication and Authorization Headers Authenticate a request by extracting the client credentials from the request and then invoke the `ClientValidation::authenticate()` method. The `pdk::contracts` module provides the `basic_auth_credentials()` helper function to extract Basic Authentication credentials from request headers: ```Rust pub fn basic_auth_credentials(request_headers_state: &RequestHeadersState) -> Result<(ClientId, ClientSecret), BasicAuthError>; ``` This code snippet provides a simple authentication-request filter: ```Rust async fn my_authentication_filter( state: RequestHeadersState, authentication: Authentication, validator: &ContractValidator, ) -> Flow<()> { // Extract credentials let (client_id, client_secret) = match basic_auth_credentials(&state) { Ok(credentials) => credentials, Err(e) => { logger::info!("Invalid credentials: {e}"); // For simplicity, we are using a user-defined `unathorized_response()` // helper function for building responses. return Flow::Break(unauthorized_response("Invalid credentials", 401)); } }; // Validate authentication let validation = validator.authenticate(&client_id, &client_secret); let client_data = match validation { Ok(client_data) => client_data, Err(e) => { logger::info!("Invalid authentication: {e}"); return Flow::Break(unauthorized_response("Invalid authentication", 403)); } }; // Update the current authentication if let Some(mut auth) = authentication.authentication() { auth.client_id = Some(client_data.client_id); auth.client_name = Some(client_data.client_name); authentication.set_authentication(Some(&auth)); } Flow::Continue(()) } ``` This code snippet provides a simple authorization-request filter: ```Rust async fn my_authorization_filter( state: RequestHeadersState, validator: &ContractValidator, ) -> Flow<()> { // Extract client id with a user defined helper `extract_client_id()` function, let client_id = match extract_client_id(&state) { Ok(credentials) => credentials, Err(e) => { logger::info!("Invalid credentials: {e}"); // For simplicity, we are using a user-defined `unathorized_response()` // helper function for building responses. return Flow::Break(unauthorized_response("Invalid credentials", 401)); } }; // Validate authorization let validation = validator.authorize(&client_id); if let Err(e) = validation { logger::info!("Invalid authentication: {e}"); return Flow::Break(unauthorized_response("Invalid authentication", 403)); } Flow::Continue(()) } ``` ## Implement Custom Extraction for Client Credentials Invoke the `ClientId::new()` and `ClientSecret::new()` methods to extract credentials: ```Rust impl ClientId { pub fn new(client_id: String) -> Self; } impl ClientSecret { pub fn new(client_secret: String) -> Self; } ``` After extracting the credentials, initialize a set of the credentials: ```Rust fn initialize_credentials(raw_client_id: String, raw_client_secret) -> (ClientId, ClientSecret) { let client_id = ClientId::new(raw_client_id); let client_secret = ClientSecret::new(raw_client_secret); (client_id, client_secret) } ``` > [!NOTE] For security, the content of `ClientSecret` is deleted after use, and the `Debug` trait > doesn’t reveal the `ClientSecret` content. ## Inject the ContractValidator Object Inject the `ContractValidator` object into the `#[entrypoint]` function and share its reference to the request filter: ```Rust #[entrypoint] async fn configure(launcher: Launcher, validator: ContractValidator) -> Result<(), LaunchError> { let filter = on_request(|state, authentication| my_authentication_filter(state, authentication, &validator)); launcher.launch(filter).await?; OK(()) } ``` ### Poll the Local Contracts Database The `ContractValidator` object maintains a local copy of the contracts database. You must poll the local copy periodically to maintain a valid copy of the contracts. Invoke the `ContractValidator::update_contracts()` method to poll the local copy: ```Rust impl ContractValidator { pub async fn update_contracts(&self) -> Result<(), UpdateError>; } ``` If the `ContractValidator::update_contracts()` method returns an error that specifies a connectivity problem occurred during the contracts database polling, you must implement the retry and error handling heuristics. To do this, invoke `ContractValidator::update_contracts()` in a period specified by the `ContractValidator::UPDATE_PERIOD` constant: ```Rust async fn update_my_contracts(validator: &ContractValidator, clock: Clock) { // Configure a new timer let timer = clock.period(ContractValidator::UPDATE_PERIOD); loop { // Update result handling should be customized by the programmer let update_result = validator.update_contracts().await; // Wait for the next tick if !timer.next_tick().await { // If no more ticks are available, finish the task. return; } } } ``` The contract database initialization period specifies when to poll the contracts database at a higher frequency than update period. The `ContractValidator::INITIALIZATION_PERIOD` specifies the interval required by the initial polling: ```Rust async fn initialize_my_contracts(validator: &ContractValidator, clock: Clock) { // Configure a new timer let timer = clock.period(ContractValidator::UPDATE_PERIOD); loop { // Update result handling should be customized by the programmer let update_result = validator.update_contracts().await; // Wait for the next tick if !timer.next_tick().await { // If no more ticks are available, finish the task. return; } } } ``` This snippet shows a complete contract polling task with initialization and update polling periods: ```Rust async fn update_my_contracts(validator: &ContractValidator, clock: Clock) { let initialization_timer = clock.period(ContractValidator::INITIALIZATION_PERIOD); loop { if validator.update_contracts().await.is_ok() { logger::info!("Contracts storage initialized."); break; } if !initialization_timer.next_tick().await { logger::info!("Tick event suspended."); break; } } let update_timer = initialization_timer .release() .period(ContractValidator::UPDATE_PERIOD); loop { let _ = validator.update_contracts().await; if !update_timer.next_tick().await { logger::info!("Tick event suspended."); break; } logger::info!("Retrying contracts storage initialization."); } } ``` Because the contracts database polling task must run concurrently with the `Launcher::launch()` task, use the `join!()` macro from the [futures](https://crates.io/crates/futures) crate to join both tasks. This snippet implements a complete `#[entrypoint]` function with polling and launching: ```Rust #[entrypoint] async fn configure(launcher: Launcher, clock: Clock,validator: ContractValidator) -> Result<(), LauncherError> { let filter = on_request(|state, authentication| my_authentication_filter(state, authentication, &validator)); let (_, launcher_result) = join! { update_my_contracts(&validator, clock), launcher.launch(filter), }; launcher_result } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-timer) - [Client Applications, Contracts, and Credentials](https://docs.mulesoft.com/api-manager/latest/api-contracts-landing-page) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Using CORS Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Flex Gateway Policy Development Kit (PDK)'s > Cross-origin resource sharing (CORS) library, see > [CORS Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/cors-validation/README.md). CORS is a mechanism for web applications to access resources defined in another domain. Browsers support CORS by default. The PDK CORS library complies with the [CORS W3C recommendation](https://fetch.spec.whatwg.org/) standards and provides a set of tools to validate incoming requests and protect resources. ## Define a CORS Configuration Instance The CORS library is available from the `pdk::cors` module. The module provides the `cors::Configuration`, `cors::OriginGroup`, and `cors::AllowedMethod` structs and their builders to define how to validate incoming requests. For example, the following code snippet defines a function that hardcodes the `cors::Configuration` instance: ```Rust 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 Struct Configuration Parameters
PropertyRequired or OptionalDefault ValueDescription

origin_groups

Optional

Empty Vec

Vec containing groups of origins configurable with cors::OriginGroup.

public_resource

Optional

false

A boolean indicating if the CORS configuration is applied as a public resource.

support_credentials

Optional

false

A boolean indicating if the CORS configuration supports credentials, such as cookies, authorization headers, and TLS client certificates.

### cors::OriginGroup Struct Configuration Parameters
PropertyRequired or OptionalDefault ValueDescription

plain_origins

Optional

Empty Vec

Vec of origins included in the group. For example, http://www.the-origin-of-time.com.

access_control_max_age

Optional

30

Duration in seconds to cache a preflight response before sending another preflight request.

allowed_methods

Optional

Empty Vec

Vec of allowed HTTP methods configurable with cors::AllowedMethod.

headers

Optional

Empty Vec

Vec of HTTP headers for preflight requests.

exposed_headers

Optional

Empty Vec

Vec of headers that browser JavaScript can access.

### cors::AllowedMethod Struct Configuration Parameters
PropertyRequired or OptionalDescription

method_name

Required

Method name.

is_allowed

Required

A boolean indicating if a method is allowed. Supported values are CONNECT, DELETE, GET, OPTIONS, PATCH, POST, PUT, or TRACE.

## CORS Validation Methods The `cors::Cors` struct contains the `check_headers()` method to validate incoming headers against a provided `cors::Configuration` instance. The `cors::Cors::check_headers()` method returns the `Result` struct. The result is `Err` when the CORS validation fails. If the validation passes, the request is `Ok` and you can evaluate the `cors::Check` struct. ### `cors::Check` Struct Available Methods
MethodTypeDescription

response_type()

cors::ResponseType

Returns an enum containing the type of action needed for the incoming request. For more details about the enum values, see cors::ResponseType Enum Response Values.

headers()

&[(String, String)]

A list of headers to add to the response.

into_headers()

Vec<(String, String)>

Consumes the cors::Check struct and returns the list of headers to add to the response.

### `cors::ResponseType` Enum Response Values
ValueDescription

Preflight

The incoming request is a CORS preflight request, and the policy must respond early.

Main

The incoming request is a CORS main request, and the request must continue to the upstream.

## Write a CORS Validation Policy To write a CORS validation policy: 1. Define an `#[entrypoint]` function that defines the `cors::Configuration` instance. In the following example, `create_cors_configuration()` is the function defined in the [Define a CORS Configuration Instance](#cors-configuration) example: ```rust 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. Define a `request_filter()` function to validate the incoming requests by using the CORS validation methods. The `Flow` returned must contain a `Vec<(String, String)>` to pass the headers returned from `cors::Cors::check_headers()` to the `response_filter()`: ```rust async fn request_filter( request_headers_state: RequestHeadersState, cors_configuration: &cors::Configuration<'_>, ) -> Flow> { // 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. Define a `response_filter()` function that validates the response by using the CORS validation methods. `RequestData` contains the headers returned by `cors::Cors::check_headers()`: ```rust async fn response_filter(state: ResponseHeadersState, data: RequestData>) { // 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); } } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Using CORS Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Flex Gateway Policy Development Kit (PDK)'s > Cross-origin resource sharing (CORS) library, see > [CORS Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/cors-validation/README.md). CORS is a mechanism for web applications to access resources defined in another domain. Browsers support CORS by default. The PDK CORS library complies with the [CORS W3C recommendation](https://fetch.spec.whatwg.org/) standards and provides a set of tools to validate incoming requests and protect resources. ## Define a CORS Configuration Instance The CORS library is available from the `pdk::cors` module. The module provides the `cors::Configuration`, `cors::OriginGroup`, and `cors::AllowedMethod` structs and their builders to define how to validate incoming requests. For example, the following code snippet defines a function that hardcodes the `cors::Configuration` instance: ```Rust 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 Struct Configuration Parameters
PropertyRequired or OptionalDefault ValueDescription

origin_groups

Optional

Empty Vec

Vec containing groups of origins configurable with cors::OriginGroup.

public_resource

Optional

false

A boolean indicating if the CORS configuration is applied as a public resource.

support_credentials

Optional

false

A boolean indicating if the CORS configuration supports credentials, such as cookies, authorization headers, and TLS client certificates.

### cors::OriginGroup Struct Configuration Parameters
PropertyRequired or OptionalDefault ValueDescription

plain_origins

Optional

Empty Vec

Vec of origins included in the group. For example, http://www.the-origin-of-time.com.

access_control_max_age

Optional

30

Duration in seconds to cache a preflight response before sending another preflight request.

allowed_methods

Optional

Empty Vec

Vec of allowed HTTP methods configurable with cors::AllowedMethod.

headers

Optional

Empty Vec

Vec of HTTP headers for preflight requests.

exposed_headers

Optional

Empty Vec

Vec of headers that browser JavaScript can access.

### cors::AllowedMethod Struct Configuration Parameters
PropertyRequired or OptionalDescription

method_name

Required

Method name.

is_allowed

Required

A boolean indicating if a method is allowed. Supported values are CONNECT, DELETE, GET, OPTIONS, PATCH, POST, PUT, or TRACE.

## CORS Validation Methods The `cors::Cors` struct contains the `check_headers()` method to validate incoming headers against a provided `cors::Configuration` instance. The `cors::Cors::check_headers()` method returns the `Result` struct. The result is `Err` when the CORS validation fails. If the validation passes, the request is `Ok` and you can evaluate the `cors::Check` struct. ### `cors::Check` Struct Available Methods
MethodTypeDescription

response_type()

cors::ResponseType

Returns an enum containing the type of action needed for the incoming request. For more details about the enum values, see cors::ResponseType Enum Response Values.

headers()

&[(String, String)]

A list of headers to add to the response.

into_headers()

Vec<(String, String)>

Consumes the cors::Check struct and returns the list of headers to add to the response.

### `cors::ResponseType` Enum Response Values
ValueDescription

Preflight

The incoming request is a CORS preflight request, and the policy must respond early.

Main

The incoming request is a CORS main request, and the request must continue to the upstream.

## Write a CORS Validation Policy To write a CORS validation policy: 1. Define an `#[entrypoint]` function that defines the `cors::Configuration` instance. In the following example, `create_cors_configuration()` is the function defined in the [Define a CORS Configuration Instance](#cors-configuration) example: ```rust 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. Define a `request_filter()` function to validate the incoming requests by using the CORS validation methods. The `Flow` returned must contain a `Vec<(String, String)>` to pass the headers returned from `cors::Cors::check_headers()` to the `response_filter()`: ```rust async fn request_filter( request_headers_state: RequestHeadersState, cors_configuration: &cors::Configuration<'_>, ) -> Flow> { // 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. Define a `response_filter()` function that validates the response by using the CORS validation methods. `RequestData` contains the headers returned by `cors::Cors::check_headers()`: ```rust async fn response_filter(state: ResponseHeadersState, data: RequestData>) { // 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); } } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Using CORS Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Flex Gateway Policy Development Kit (PDK)'s > Cross-origin resource sharing (CORS) library, see > [CORS Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/cors-validation/README.md). CORS is a mechanism for web applications to access resources defined in another domain. Browsers support CORS by default. The PDK CORS library complies with the [CORS W3C recommendation](https://fetch.spec.whatwg.org/) standards and provides a set of tools to validate incoming requests and protect resources. ## Define a CORS Configuration Instance The CORS library is available from the `pdk::cors` module. The module provides the `cors::Configuration`, `cors::OriginGroup`, and `cors::AllowedMethod` structs and their builders to define how to validate incoming requests. For example, the following code snippet defines a function that hardcodes the `cors::Configuration` instance: ```Rust 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 Struct Configuration Parameters
PropertyRequired or OptionalDefault ValueDescription

origin_groups

Optional

Empty Vec

Vec containing groups of origins configurable with cors::OriginGroup.

public_resource

Optional

false

A boolean indicating if the CORS configuration is applied as a public resource.

support_credentials

Optional

false

A boolean indicating if the CORS configuration supports credentials, such as cookies, authorization headers, and TLS client certificates.

### cors::OriginGroup Struct Configuration Parameters
PropertyRequired or OptionalDefault ValueDescription

plain_origins

Optional

Empty Vec

Vec of origins included in the group. For example, http://www.the-origin-of-time.com.

access_control_max_age

Optional

30

Duration in seconds to cache a preflight response before sending another preflight request.

allowed_methods

Optional

Empty Vec

Vec of allowed HTTP methods configurable with cors::AllowedMethod.

headers

Optional

Empty Vec

Vec of HTTP headers for preflight requests.

exposed_headers

Optional

Empty Vec

Vec of headers that browser JavaScript can access.

### cors::AllowedMethod Struct Configuration Parameters
PropertyRequired or OptionalDescription

method_name

Required

Method name.

is_allowed

Required

A boolean indicating if a method is allowed. Supported values are CONNECT, DELETE, GET, OPTIONS, PATCH, POST, PUT, or TRACE.

## CORS Validation Methods The `cors::Cors` struct contains the `check_headers()` method to validate incoming headers against a provided `cors::Configuration` instance. The `cors::Cors::check_headers()` method returns the `Result` struct. The result is `Err` when the CORS validation fails. If the validation passes, the request is `Ok` and you can evaluate the `cors::Check` struct. ### `cors::Check` Struct Available Methods
MethodTypeDescription

response_type()

cors::ResponseType

Returns an enum containing the type of action needed for the incoming request. For more details about the enum values, see cors::ResponseType Enum Response Values.

headers()

&[(String, String)]

A list of headers to add to the response.

into_headers()

Vec<(String, String)>

Consumes the cors::Check struct and returns the list of headers to add to the response.

### `cors::ResponseType` Enum Response Values
ValueDescription

Preflight

The incoming request is a CORS preflight request, and the policy must respond early.

Main

The incoming request is a CORS main request, and the request must continue to the upstream.

## Write a CORS Validation Policy To write a CORS validation policy: 1. Define an `#[entrypoint]` function that defines the `cors::Configuration` instance. In the following example, `create_cors_configuration()` is the function defined in the [Define a CORS Configuration Instance](#cors-configuration) example: ```rust 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. Define a `request_filter()` function to validate the incoming requests by using the CORS validation methods. The `Flow` returned must contain a `Vec<(String, String)>` to pass the headers returned from `cors::Cors::check_headers()` to the `response_filter()`: ```rust async fn request_filter( request_headers_state: RequestHeadersState, cors_configuration: &cors::Configuration<'_>, ) -> Flow> { // 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. Define a `response_filter()` function that validates the response by using the CORS validation methods. `RequestData` contains the headers returned by `cors::Cors::check_headers()`: ```rust async fn response_filter(state: ResponseHeadersState, data: RequestData>) { // 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); } } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Using CORS Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Flex Gateway Policy Development Kit (PDK)'s > Cross-origin resource sharing (CORS) library, see > [CORS Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/cors-validation/README.md). CORS is a mechanism for web applications to access resources defined in another domain. Browsers support CORS by default. The PDK CORS library complies with the [CORS W3C recommendation](https://fetch.spec.whatwg.org/) standards and provides a set of tools to validate incoming requests and protect resources. ## Define a CORS Configuration Instance The CORS library is available from the `pdk::cors` module. The module provides the `cors::Configuration`, `cors::OriginGroup`, and `cors::AllowedMethod` structs and their builders to define how to validate incoming requests. For example, the following code snippet defines a function that hardcodes the `cors::Configuration` instance: ```Rust 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 Struct Configuration Parameters
PropertyRequired or OptionalDefault ValueDescription

origin_groups

Optional

Empty Vec

Vec containing groups of origins configurable with cors::OriginGroup.

public_resource

Optional

false

A boolean indicating if the CORS configuration is applied as a public resource.

support_credentials

Optional

false

A boolean indicating if the CORS configuration supports credentials, such as cookies, authorization headers, and TLS client certificates.

### cors::OriginGroup Struct Configuration Parameters
PropertyRequired or OptionalDefault ValueDescription

plain_origins

Optional

Empty Vec

Vec of origins included in the group. For example, http://www.the-origin-of-time.com.

access_control_max_age

Optional

30

Duration in seconds to cache a preflight response before sending another preflight request.

allowed_methods

Optional

Empty Vec

Vec of allowed HTTP methods configurable with cors::AllowedMethod.

headers

Optional

Empty Vec

Vec of HTTP headers for preflight requests.

exposed_headers

Optional

Empty Vec

Vec of headers that browser JavaScript can access.

### cors::AllowedMethod Struct Configuration Parameters
PropertyRequired or OptionalDescription

method_name

Required

Method name.

is_allowed

Required

A boolean indicating if a method is allowed. Supported values are CONNECT, DELETE, GET, OPTIONS, PATCH, POST, PUT, or TRACE.

## CORS Validation Methods The `cors::Cors` struct contains the `check_headers()` method to validate incoming headers against a provided `cors::Configuration` instance. The `cors::Cors::check_headers()` method returns the `Result` struct. The result is `Err` when the CORS validation fails. If the validation passes, the request is `Ok` and you can evaluate the `cors::Check` struct. ### `cors::Check` Struct Available Methods
MethodTypeDescription

response_type()

cors::ResponseType

Returns an enum containing the type of action needed for the incoming request. For more details about the enum values, see cors::ResponseType Enum Response Values.

headers()

&[(String, String)]

A list of headers to add to the response.

into_headers()

Vec<(String, String)>

Consumes the cors::Check struct and returns the list of headers to add to the response.

### `cors::ResponseType` Enum Response Values
ValueDescription

Preflight

The incoming request is a CORS preflight request, and the policy must respond early.

Main

The incoming request is a CORS main request, and the request must continue to the upstream.

## Write a CORS Validation Policy To write a CORS validation policy: 1. Define an `#[entrypoint]` function that defines the `cors::Configuration` instance. In the following example, `create_cors_configuration()` is the function defined in the [Define a CORS Configuration Instance](#cors-configuration) example: ```rust 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. Define a `request_filter()` function to validate the incoming requests by using the CORS validation methods. The `Flow` returned must contain a `Vec<(String, String)>` to pass the headers returned from `cors::Cors::check_headers()` to the `response_filter()`: ```rust async fn request_filter( request_headers_state: RequestHeadersState, cors_configuration: &cors::Configuration<'_>, ) -> Flow> { // 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. Define a `response_filter()` function that validates the response by using the CORS validation methods. `RequestData` contains the headers returned by `cors::Cors::check_headers()`: ```rust async fn response_filter(state: ResponseHeadersState, data: RequestData>) { // 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); } } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Using CORS Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Flex Gateway Policy Development Kit (PDK)'s > Cross-origin resource sharing (CORS) library, see > [CORS Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/cors-validation/README.md). CORS is a mechanism for web applications to access resources defined in another domain. Browsers support CORS by default. The PDK CORS library complies with the [CORS W3C recommendation](https://fetch.spec.whatwg.org/) standards and provides a set of tools to validate incoming requests and protect resources. ## Define a CORS Configuration Instance The CORS library is available from the `pdk::cors` module. The module provides the `cors::Configuration`, `cors::OriginGroup`, and `cors::AllowedMethod` structs and their builders to define how to validate incoming requests. For example, the following code snippet defines a function that hardcodes the `cors::Configuration` instance: ```Rust 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 Struct Configuration Parameters
PropertyRequired or OptionalDefault ValueDescription

origin_groups

Optional

Empty Vec

Vec containing groups of origins configurable with cors::OriginGroup.

public_resource

Optional

false

A boolean indicating if the CORS configuration is applied as a public resource.

support_credentials

Optional

false

A boolean indicating if the CORS configuration supports credentials, such as cookies, authorization headers, and TLS client certificates.

### cors::OriginGroup Struct Configuration Parameters
PropertyRequired or OptionalDefault ValueDescription

plain_origins

Optional

Empty Vec

Vec of origins included in the group. For example, http://www.the-origin-of-time.com.

access_control_max_age

Optional

30

Duration in seconds to cache a preflight response before sending another preflight request.

allowed_methods

Optional

Empty Vec

Vec of allowed HTTP methods configurable with cors::AllowedMethod.

headers

Optional

Empty Vec

Vec of HTTP headers for preflight requests.

exposed_headers

Optional

Empty Vec

Vec of headers that browser JavaScript can access.

### cors::AllowedMethod Struct Configuration Parameters
PropertyRequired or OptionalDescription

method_name

Required

Method name.

is_allowed

Required

A boolean indicating if a method is allowed. Supported values are CONNECT, DELETE, GET, OPTIONS, PATCH, POST, PUT, or TRACE.

## CORS Validation Methods The `cors::Cors` struct contains the `check_headers()` method to validate incoming headers against a provided `cors::Configuration` instance. The `cors::Cors::check_headers()` method returns the `Result` struct. The result is `Err` when the CORS validation fails. If the validation passes, the request is `Ok` and you can evaluate the `cors::Check` struct. ### `cors::Check` Struct Available Methods
MethodTypeDescription

response_type()

cors::ResponseType

Returns an enum containing the type of action needed for the incoming request. For more details about the enum values, see cors::ResponseType Enum Response Values.

headers()

&[(String, String)]

A list of headers to add to the response.

into_headers()

Vec<(String, String)>

Consumes the cors::Check struct and returns the list of headers to add to the response.

### `cors::ResponseType` Enum Response Values
ValueDescription

Preflight

The incoming request is a CORS preflight request, and the policy must respond early.

Main

The incoming request is a CORS main request, and the request must continue to the upstream.

## Write a CORS Validation Policy To write a CORS validation policy: 1. Define an `#[entrypoint]` function that defines the `cors::Configuration` instance. In the following example, `create_cors_configuration()` is the function defined in the [Define a CORS Configuration Instance](#cors-configuration) example: ```rust 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. Define a `request_filter()` function to validate the incoming requests by using the CORS validation methods. The `Flow` returned must contain a `Vec<(String, String)>` to pass the headers returned from `cors::Cors::check_headers()` to the `response_filter()`: ```rust async fn request_filter( request_headers_state: RequestHeadersState, cors_configuration: &cors::Configuration<'_>, ) -> Flow> { // 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. Define a `response_filter()` function that validates the response by using the CORS validation methods. `RequestData` contains the headers returned by `cors::Cors::check_headers()`: ```rust async fn response_filter(state: ResponseHeadersState, data: RequestData>) { // 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); } } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Using CORS Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Flex Gateway Policy Development Kit (PDK)'s > Cross-origin resource sharing (CORS) library, see > [CORS Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/cors-validation/README.md). CORS is a mechanism for web applications to access resources defined in another domain. Browsers support CORS by default. The PDK CORS library complies with the [CORS W3C recommendation](https://fetch.spec.whatwg.org/) standards and provides a set of tools to validate incoming requests and protect resources. ## Define a CORS Configuration Instance The CORS library is available from the `pdk::cors` module. The module provides the `cors::Configuration`, `cors::OriginGroup`, and `cors::AllowedMethod` structs and their builders to define how to validate incoming requests. For example, the following code snippet defines a function that hardcodes the `cors::Configuration` instance: ```Rust 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 Struct Configuration Parameters
PropertyRequired or OptionalDefault ValueDescription

origin_groups

Optional

Empty Vec

Vec containing groups of origins configurable with cors::OriginGroup.

public_resource

Optional

false

A boolean indicating if the CORS configuration is applied as a public resource.

support_credentials

Optional

false

A boolean indicating if the CORS configuration supports credentials, such as cookies, authorization headers, and TLS client certificates.

### cors::OriginGroup Struct Configuration Parameters
PropertyRequired or OptionalDefault ValueDescription

plain_origins

Optional

Empty Vec

Vec of origins included in the group. For example, http://www.the-origin-of-time.com.

access_control_max_age

Optional

30

Duration in seconds to cache a preflight response before sending another preflight request.

allowed_methods

Optional

Empty Vec

Vec of allowed HTTP methods configurable with cors::AllowedMethod.

headers

Optional

Empty Vec

Vec of HTTP headers for preflight requests.

exposed_headers

Optional

Empty Vec

Vec of headers that browser JavaScript can access.

### cors::AllowedMethod Struct Configuration Parameters
PropertyRequired or OptionalDescription

method_name

Required

Method name.

is_allowed

Required

A boolean indicating if a method is allowed. Supported values are CONNECT, DELETE, GET, OPTIONS, PATCH, POST, PUT, or TRACE.

## CORS Validation Methods The `cors::Cors` struct contains the `check_headers()` method to validate incoming headers against a provided `cors::Configuration` instance. The `cors::Cors::check_headers()` method returns the `Result` struct. The result is `Err` when the CORS validation fails. If the validation passes, the request is `Ok` and you can evaluate the `cors::Check` struct. ### `cors::Check` Struct Available Methods
MethodTypeDescription

response_type()

cors::ResponseType

Returns an enum containing the type of action needed for the incoming request. For more details about the enum values, see cors::ResponseType Enum Response Values.

headers()

&[(String, String)]

A list of headers to add to the response.

into_headers()

Vec<(String, String)>

Consumes the cors::Check struct and returns the list of headers to add to the response.

### `cors::ResponseType` Enum Response Values
ValueDescription

Preflight

The incoming request is a CORS preflight request, and the policy must respond early.

Main

The incoming request is a CORS main request, and the request must continue to the upstream.

## Write a CORS Validation Policy To write a CORS validation policy: 1. Define an `#[entrypoint]` function that defines the `cors::Configuration` instance. In the following example, `create_cors_configuration()` is the function defined in the [Define a CORS Configuration Instance](#cors-configuration) example: ```rust 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. Define a `request_filter()` function to validate the incoming requests by using the CORS validation methods. The `Flow` returned must contain a `Vec<(String, String)>` to pass the headers returned from `cors::Cors::check_headers()` to the `response_filter()`: ```rust async fn request_filter( request_headers_state: RequestHeadersState, cors_configuration: &cors::Configuration<'_>, ) -> Flow> { // 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. Define a `response_filter()` function that validates the response by using the CORS validation methods. `RequestData` contains the headers returned by `cors::Cors::check_headers()`: ```rust async fn response_filter(state: ResponseHeadersState, data: RequestData>) { // 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); } } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Using CORS Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)'s > Cross-origin resource sharing (CORS) library, see > [CORS Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/cors-validation/README.md). CORS is a mechanism for web applications to access resources defined in another domain. Browsers support CORS by default. The PDK CORS library complies with the [CORS W3C recommendation](https://fetch.spec.whatwg.org/) standards and provides a set of tools to validate incoming requests and protect resources. ## Define a CORS Configuration Instance The CORS library is available from the `pdk::cors` module. The module provides the `cors::Configuration`, `cors::OriginGroup`, and `cors::AllowedMethod` structs and their builders to define how to validate incoming requests. For example, the following code snippet defines a function that hardcodes the `cors::Configuration` instance: ```Rust 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 Struct Configuration Parameters
PropertyRequired or OptionalDefault ValueDescription

origin_groups

Optional

Empty Vec

Vec containing groups of origins configurable with cors::OriginGroup.

public_resource

Optional

false

A boolean indicating if the CORS configuration is applied as a public resource.

support_credentials

Optional

false

A boolean indicating if the CORS configuration supports credentials, such as cookies, authorization headers, and TLS client certificates.

### cors::OriginGroup Struct Configuration Parameters
PropertyRequired or OptionalDefault ValueDescription

plain_origins

Optional

Empty Vec

Vec of origins included in the group. For example, http://www.the-origin-of-time.com.

access_control_max_age

Optional

30

Duration in seconds to cache a preflight response before sending another preflight request.

allowed_methods

Optional

Empty Vec

Vec of allowed HTTP methods configurable with cors::AllowedMethod.

headers

Optional

Empty Vec

Vec of HTTP headers for preflight requests.

exposed_headers

Optional

Empty Vec

Vec of headers that browser JavaScript can access.

### cors::AllowedMethod Struct Configuration Parameters
PropertyRequired or OptionalDescription

method_name

Required

Method name.

is_allowed

Required

A boolean indicating if a method is allowed. Supported values are CONNECT, DELETE, GET, OPTIONS, PATCH, POST, PUT, or TRACE.

## CORS Validation Methods The `cors::Cors` struct contains the `check_headers()` method to validate incoming headers against a provided `cors::Configuration` instance. The `cors::Cors::check_headers()` method returns the `Result` struct. The result is `Err` when the CORS validation fails. If the validation passes, the request is `Ok` and you can evaluate the `cors::Check` struct. ### `cors::Check` Struct Available Methods
MethodTypeDescription

response_type()

cors::ResponseType

Returns an enum containing the type of action needed for the incoming request. For more details about the enum values, see cors::ResponseType Enum Response Values.

headers()

&[(String, String)]

A list of headers to add to the response.

into_headers()

Vec<(String, String)>

Consumes the cors::Check struct and returns the list of headers to add to the response.

### `cors::ResponseType` Enum Response Values
ValueDescription

Preflight

The incoming request is a CORS preflight request, and the policy must respond early.

Main

The incoming request is a CORS main request, and the request must continue to the upstream.

## Write a CORS Validation Policy To write a CORS validation policy: 1. Define an `#[entrypoint]` function that defines the `cors::Configuration` instance. In the following example, `create_cors_configuration()` is the function defined in the [Define a CORS Configuration Instance](#cors-configuration) example: ```rust 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. Define a `request_filter()` function to validate the incoming requests by using the CORS validation methods. The `Flow` returned must contain a `Vec<(String, String)>` to pass the headers returned from `cors::Cors::check_headers()` to the `response_filter()`: ```rust async fn request_filter( request_headers_state: RequestHeadersState, cors_configuration: &cors::Configuration<'_>, ) -> Flow> { // 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. Define a `response_filter()` function that validates the response by using the CORS validation methods. `RequestData` contains the headers returned by `cors::Cors::check_headers()`: ```rust async fn response_filter(state: ResponseHeadersState, data: RequestData>) { // 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); } } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Using CORS Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)'s > Cross-origin resource sharing (CORS) library, see > [CORS Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/cors-validation/README.md). CORS is a mechanism for web applications to access resources defined in another domain. Browsers support CORS by default. The PDK CORS library complies with the [CORS W3C recommendation](https://fetch.spec.whatwg.org/) standards and provides a set of tools to validate incoming requests and protect resources. ## Define a CORS Configuration Instance The CORS library is available from the `pdk::cors` module. The module provides the `cors::Configuration`, `cors::OriginGroup`, and `cors::AllowedMethod` structs and their builders to define how to validate incoming requests. For example, the following code snippet defines a function that hardcodes the `cors::Configuration` instance: ```Rust 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 Struct Configuration Parameters
PropertyRequired or OptionalDefault ValueDescription

origin_groups

Optional

Empty Vec

Vec containing groups of origins configurable with cors::OriginGroup.

public_resource

Optional

false

A boolean indicating if the CORS configuration is applied as a public resource.

support_credentials

Optional

false

A boolean indicating if the CORS configuration supports credentials, such as cookies, authorization headers, and TLS client certificates.

### cors::OriginGroup Struct Configuration Parameters
PropertyRequired or OptionalDefault ValueDescription

plain_origins

Optional

Empty Vec

Vec of origins included in the group. For example, http://www.the-origin-of-time.com.

access_control_max_age

Optional

30

Duration in seconds to cache a preflight response before sending another preflight request.

allowed_methods

Optional

Empty Vec

Vec of allowed HTTP methods configurable with cors::AllowedMethod.

headers

Optional

Empty Vec

Vec of HTTP headers for preflight requests.

exposed_headers

Optional

Empty Vec

Vec of headers that browser JavaScript can access.

### cors::AllowedMethod Struct Configuration Parameters
PropertyRequired or OptionalDescription

method_name

Required

Method name.

is_allowed

Required

A boolean indicating if a method is allowed. Supported values are CONNECT, DELETE, GET, OPTIONS, PATCH, POST, PUT, or TRACE.

## CORS Validation Methods The `cors::Cors` struct contains the `check_headers()` method to validate incoming headers against a provided `cors::Configuration` instance. The `cors::Cors::check_headers()` method returns the `Result` struct. The result is `Err` when the CORS validation fails. If the validation passes, the request is `Ok` and you can evaluate the `cors::Check` struct. ### `cors::Check` Struct Available Methods
MethodTypeDescription

response_type()

cors::ResponseType

Returns an enum containing the type of action needed for the incoming request. For more details about the enum values, see cors::ResponseType Enum Response Values.

headers()

&[(String, String)]

A list of headers to add to the response.

into_headers()

Vec<(String, String)>

Consumes the cors::Check struct and returns the list of headers to add to the response.

### `cors::ResponseType` Enum Response Values
ValueDescription

Preflight

The incoming request is a CORS preflight request, and the policy must respond early.

Main

The incoming request is a CORS main request, and the request must continue to the upstream.

## Write a CORS Validation Policy To write a CORS validation policy: 1. Define an `#[entrypoint]` function that defines the `cors::Configuration` instance. In the following example, `create_cors_configuration()` is the function defined in the [Define a CORS Configuration Instance](#cors-configuration) example: ```rust 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. Define a `request_filter()` function to validate the incoming requests by using the CORS validation methods. The `Flow` returned must contain a `Vec<(String, String)>` to pass the headers returned from `cors::Cors::check_headers()` to the `response_filter()`: ```rust async fn request_filter( request_headers_state: RequestHeadersState, cors_configuration: &cors::Configuration<'_>, ) -> Flow> { // 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. Define a `response_filter()` function that validates the response by using the CORS validation methods. `RequestData` contains the headers returned by `cors::Cors::check_headers()`: ```rust async fn response_filter(state: ResponseHeadersState, data: RequestData>) { // 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); } } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Using CORS Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)'s > Cross-origin resource sharing (CORS) library, see > [CORS Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/cors-validation/README.md). CORS is a mechanism for web applications to access resources defined in another domain. Browsers support CORS by default. The PDK CORS library complies with the [CORS W3C recommendation](https://fetch.spec.whatwg.org/) standards and provides a set of tools to validate incoming requests and protect resources. ## Define a CORS Configuration Instance The CORS library is available from the `pdk::cors` module. The module provides the `cors::Configuration`, `cors::OriginGroup`, and `cors::AllowedMethod` structs and their builders to define how to validate incoming requests. For example, the following code snippet defines a function that hardcodes the `cors::Configuration` instance: ```Rust 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 Struct Configuration Parameters
PropertyRequired or OptionalDefault ValueDescription

origin_groups

Optional

Empty Vec

Vec containing groups of origins configurable with cors::OriginGroup.

public_resource

Optional

false

A boolean indicating if the CORS configuration is applied as a public resource.

support_credentials

Optional

false

A boolean indicating if the CORS configuration supports credentials, such as cookies, authorization headers, and TLS client certificates.

### cors::OriginGroup Struct Configuration Parameters
PropertyRequired or OptionalDefault ValueDescription

plain_origins

Optional

Empty Vec

Vec of origins included in the group. For example, http://www.the-origin-of-time.com.

access_control_max_age

Optional

30

Duration in seconds to cache a preflight response before sending another preflight request.

allowed_methods

Optional

Empty Vec

Vec of allowed HTTP methods configurable with cors::AllowedMethod.

headers

Optional

Empty Vec

Vec of HTTP headers for preflight requests.

exposed_headers

Optional

Empty Vec

Vec of headers that browser JavaScript can access.

### cors::AllowedMethod Struct Configuration Parameters
PropertyRequired or OptionalDescription

method_name

Required

Method name.

is_allowed

Required

A boolean indicating if a method is allowed. Supported values are CONNECT, DELETE, GET, OPTIONS, PATCH, POST, PUT, or TRACE.

## CORS Validation Methods The `cors::Cors` struct contains the `check_headers()` method to validate incoming headers against a provided `cors::Configuration` instance. The `cors::Cors::check_headers()` method returns the `Result` struct. The result is `Err` when the CORS validation fails. If the validation passes, the request is `Ok` and you can evaluate the `cors::Check` struct. ### `cors::Check` Struct Available Methods
MethodTypeDescription

response_type()

cors::ResponseType

Returns an enum containing the type of action needed for the incoming request. For more details about the enum values, see cors::ResponseType Enum Response Values.

headers()

&[(String, String)]

A list of headers to add to the response.

into_headers()

Vec<(String, String)>

Consumes the cors::Check struct and returns the list of headers to add to the response.

### `cors::ResponseType` Enum Response Values
ValueDescription

Preflight

The incoming request is a CORS preflight request, and the policy must respond early.

Main

The incoming request is a CORS main request, and the request must continue to the upstream.

## Write a CORS Validation Policy To write a CORS validation policy: 1. Define an `#[entrypoint]` function that defines the `cors::Configuration` instance. In the following example, `create_cors_configuration()` is the function defined in the [Define a CORS Configuration Instance](#cors-configuration) example: ```rust 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. Define a `request_filter()` function to validate the incoming requests by using the CORS validation methods. The `Flow` returned must contain a `Vec<(String, String)>` to pass the headers returned from `cors::Cors::check_headers()` to the `response_filter()`: ```rust async fn request_filter( request_headers_state: RequestHeadersState, cors_configuration: &cors::Configuration<'_>, ) -> Flow> { // 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. Define a `response_filter()` function that validates the response by using the CORS validation methods. `RequestData` contains the headers returned by `cors::Cors::check_headers()`: ```rust async fn response_filter(state: ResponseHeadersState, data: RequestData>) { // 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); } } ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Using DataWeave Expressions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses DataWeave expressions, see > [Query Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/query/README.md). If the input DataWeave expression parameter is valid, the policy parses the expression and transforms it into a `pdk::script::Script` expression. To obtain the result of the script: 1. Create an evaluator. 2. Call the binding function for each parameter defined in the schema definition: - `vars`: Call the `bind_vars` method for each of the policy’s `vars`. After all of `vars` are bound, the evaluator tries to solve the expression. If the expression contains `vars` other than the ones defined in the schema, they resolve to `null`. - `attributes`: Call the `bind_attributes` method with an implementation of the `AttributesBinding` trait. Flex Gateway Policy Development Kit (PDK) provides an implementation of this trait by instantiating a new `HandlerAttributesBinding` for each `RequestHeaderState`, `RequestHeaderState`, and response of an [HTTP call](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-http-request). - `authentication`: Call the `bind_authentication` method with an implementation of the trait `AuthenticationBinding`. PDK provides an implementation of this trait for `AuthenticationData`. To inject authentication information into your policy, see [Inject Authentication Inforamaion](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-inject-parameters#authentication). - `payload`: Call the `bind_payload` method with an implementation of the trait `PayloadBinding`. PDK provides an implementation of this trait for `RequestBodyState`, `ResponseBodyState`, and the response of an [HTTP call](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-http-request). > [!NOTE] Call only the methods for the bindings defined in the schema definition. For > example, if the `attributes` binding is not used, don’t call the `bind_attributes` method. > > To learn more about defining DataWeave expressions, see > [DataWeave Expressions](https://docs.mulesoft.com/pdk/1.2/policies-pdk-create-schema-definition#dataweave-expressions). 3. After you bind all expression variables, obtain the result by calling the `eval` method. ## Evaluate DataWeave Expressions For example, to evaluate the `tokenExtractor` DataWeave expression in the following policy schema definition: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: Extension metadata: labels: title: jwt-auth category: Custom spec: extends: - name: extension-definition namespace: default properties: tokenExtractor: type: string format: dataweave default: "#[vars.myVar]" bindings: payload: mimeType: text attributes: true authentication: true vars: - myVar required: - tokenExtractor ``` Use the following Rust snippet: ```rust // Copyright 2024 Salesforce, Inc. All rights reserved. mod generated; use anyhow::Result; use crate::generated::config::Config; use pdk::authentication::{Authentication, AuthenticationHandler}; use pdk::logger::info; use pdk::hl::*; use pdk::script::{Evaluator, HandlerAttributesBinding, Value}; async fn request_filter( state: RequestState, stream: StreamProperties, auth: Authentication, mut evaluator: Evaluator<'_>, ) { evaluator.bind_vars("myVar", "myVal"); evaluator.bind_authentication(&auth.authentication()); let state = state.into_headers_state().await; evaluator.bind_attributes(&HandlerAttributesBinding::new(state.handler(), &stream)); let state = state.into_body_state().await; evaluator.bind_payload(&state); if let Ok(value) = evaluator.eval() { match value { Value::Null => info!("value was null!"), Value::Bool(val) => info!("value was Bool: {val}"), Value::Number(val) => info!("value was Number: {val}"), Value::String(val) => info!("value was String: {val}"), Value::Array(val) => info!("value was Array: {val:?}"), Value::Object(val) => info!("value was Object: {val:?}"), } } } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes)?; launcher .launch(on_request(|request, stream, auth| { request_filter(request, stream, auth, config.token_extractor.evaluator()) })) .await?; Ok(()) } ``` ## Validate the Expression was Resolved You can resolve some expressions before all values are bound. For example, the expression `#[vars.myVar]` does not require the `attributes`, `payload`, no `authentication` to be resolved. After one of the binding methods is called, you can confirm the expression was completely resolved by calling the method: ```rust evaluator.is_ready() ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Using DataWeave Expressions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses DataWeave expressions, see > [Query Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/query/README.md). If the input DataWeave expression parameter is valid, the policy parses the expression and transforms it into a `pdk::script::Script` expression. To obtain the result of the script: 1. Create an evaluator. 2. Call the binding function for each parameter defined in the schema definition: - `vars`: Call the `bind_vars` method for each of the policy’s `vars`. After all of `vars` are bound, the evaluator tries to solve the expression. If the expression contains `vars` other than the ones defined in the schema, they resolve to `null`. - `attributes`: Call the `bind_attributes` method with an implementation of the `AttributesBinding` trait. Flex Gateway Policy Development Kit (PDK) provides an implementation of this trait by instantiating a new `HandlerAttributesBinding` for each `RequestHeaderState`, `RequestHeaderState`, and response of an [HTTP call](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-http-request). - `authentication`: Call the `bind_authentication` method with an implementation of the trait `AuthenticationBinding`. PDK provides an implementation of this trait for `AuthenticationData`. To inject authentication information into your policy, see [Inject Authentication Inforamaion](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-inject-parameters#authentication). - `payload`: Call the `bind_payload` method with an implementation of the trait `PayloadBinding`. PDK provides an implementation of this trait for `RequestBodyState`, `ResponseBodyState`, and the response of an [HTTP call](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-http-request). > [!NOTE] Call only the methods for the bindings defined in the schema definition. For > example, if the `attributes` binding is not used, don’t call the `bind_attributes` method. > > To learn more about defining DataWeave expressions, see > [DataWeave Expressions](https://docs.mulesoft.com/pdk/1.3/policies-pdk-create-schema-definition#dataweave-expressions). 3. After you bind all expression variables, obtain the result by calling the `eval` method. ## Evaluate DataWeave Expressions For example, to evaluate the `tokenExtractor` DataWeave expression in the following policy schema definition: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: Extension metadata: labels: title: jwt-auth category: Custom spec: extends: - name: extension-definition namespace: default properties: tokenExtractor: type: string format: dataweave default: "#[vars.myVar]" bindings: payload: mimeType: text attributes: true authentication: true vars: - myVar required: - tokenExtractor ``` Use the following Rust snippet: ```rust // Copyright 2024 Salesforce, Inc. All rights reserved. mod generated; use anyhow::Result; use crate::generated::config::Config; use pdk::authentication::{Authentication, AuthenticationHandler}; use pdk::logger::info; use pdk::hl::*; use pdk::script::{Evaluator, HandlerAttributesBinding, Value}; async fn request_filter( state: RequestState, stream: StreamProperties, auth: Authentication, mut evaluator: Evaluator<'_>, ) { evaluator.bind_vars("myVar", "myVal"); evaluator.bind_authentication(&auth.authentication()); let state = state.into_headers_state().await; evaluator.bind_attributes(&HandlerAttributesBinding::new(state.handler(), &stream)); let state = state.into_body_state().await; evaluator.bind_payload(&state); if let Ok(value) = evaluator.eval() { match value { Value::Null => info!("value was null!"), Value::Bool(val) => info!("value was Bool: {val}"), Value::Number(val) => info!("value was Number: {val}"), Value::String(val) => info!("value was String: {val}"), Value::Array(val) => info!("value was Array: {val:?}"), Value::Object(val) => info!("value was Object: {val:?}"), } } } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes)?; launcher .launch(on_request(|request, stream, auth| { request_filter(request, stream, auth, config.token_extractor.evaluator()) })) .await?; Ok(()) } ``` ## Validate the Expression was Resolved You can resolve some expressions before all values are bound. For example, the expression `#[vars.myVar]` does not require the `attributes`, `payload`, no `authentication` to be resolved. After one of the binding methods is called, you can confirm the expression was completely resolved by calling the method: ```rust evaluator.is_ready() ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features) # Using DataWeave Expressions
To view an example policy project that uses DataWeave expressions, see DataWeave Policy Example.
If the input DataWeave expression parameter is valid, the policy parses the expression and transforms it into a `pdk::script::Script` expression. To obtain the result of the script: 1. Create an evaluator. 2. Call the binding function for each parameter defined in the schema definition: - `vars`: Call the `bind_vars` method for each of the policy’s `vars`. After all of `vars` are bound, the evaluator tries to solve the expression. If the expression contains `vars` other than the ones defined in the schema, they resolve to `null`. - `attributes`: Call the `bind_attributes` method with an implementation of the `AttributesBinding` trait. Flex Gateway Policy Development Kit (PDK) provides an implementation of this trait by instantiating a new `HandlerAttributesBinding` for each `RequestHeaderState`, `RequestHeaderState`, and response of an [HTTP call](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-http-request). - `authentication`: Call the `bind_authentication` method with an implementation of the trait `AuthenticationBinding`. PDK provides an implementation of this trait for `AuthenticationData`. To inject authentication information into your policy, see [Inject Authentication Inforamaion](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-inject-parameters#authentication). - `payload`: Call the `bind_payload` method with an implementation of the trait `PayloadBinding`. PDK provides an implementation of this trait for `RequestBodyState`, `ResponseBodyState`, and the response of an [HTTP call](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-http-request).

Call only the methods for the bindings defined in the schema definition. For example, if the attributes binding is not used, don’t call the bind_attributes method.

To learn more about defining DataWeave expressions, see DataWeave Expressions.

3. After you bind all expression variables, obtain the result by calling the `eval` method. ## [](#example-evaluator-code)Evaluate DataWeave Expressions For example, to evaluate the `tokenExtractor` DataWeave expression in the following policy schema definition: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: Extension metadata: labels: title: jwt-auth category: Custom spec: extends: - name: extension-definition namespace: default properties: tokenExtractor: type: string format: dataweave default: "#[vars.myVar]" bindings: payload: mimeType: text attributes: true authentication: true vars: - myVar required: - tokenExtractor ```

Flex Gateway doesn’t support DataWeave expressions with binary type results. To use the dw::Binaries::fromBase64('dXNlcjpwYXNz') function, transform the result to a string. Transform the binary output to a string with the dw::util::Coercions::toString(binary: Binary, encoding: String): String function. For example, [dw::util::Coercions::toString(dw::core::Binaries::fromBase64('dXNlcjpwYXNz'), 'UTF-8')]. If using a different function that transforms the binary by default, such as [splitBy(dw::core::Binaries::fromBase64('dXNlcjpwYXNz'), ':')], you can skip manually transforming the binary.

Use the following Rust snippet: ```rust // Copyright 2024 Salesforce, Inc. All rights reserved. mod generated; use anyhow::Result; use crate::generated::config::Config; use pdk::authentication::{Authentication, AuthenticationHandler}; use pdk::logger::info; use pdk::hl::*; use pdk::script::{Evaluator, HandlerAttributesBinding, Value}; async fn request_filter( state: RequestState, stream: StreamProperties, auth: Authentication, mut evaluator: Evaluator<'_>, ) { evaluator.bind_vars("myVar", "myVal"); evaluator.bind_authentication(&auth.authentication()); let state = state.into_headers_state().await; evaluator.bind_attributes(&HandlerAttributesBinding::new(state.handler(), &stream)); let state = state.into_body_state().await; evaluator.bind_payload(&state); if let Ok(value) = evaluator.eval() { match value { Value::Null => info!("value was null!"), Value::Bool(val) => info!("value was Bool: {val}"), Value::Number(val) => info!("value was Number: {val}"), Value::String(val) => info!("value was String: {val}"), Value::Array(val) => info!("value was Array: {val:?}"), Value::Object(val) => info!("value was Object: {val:?}"), } } } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes)?; launcher .launch(on_request(|request, stream, auth| { request_filter(request, stream, auth, config.token_extractor.evaluator()) })) .await?; Ok(()) } ``` ## [](#validate-the-expression-was-resolved)Validate the Expression was Resolved You can resolve some expressions before all values are bound. For example, the expression `#[vars.myVar]` does not require the `attributes`, `payload`, no `authentication` to be resolved. After one of the binding methods is called, you can confirm the expression was completely resolved by calling the method: ```rust evaluator.is_ready() ``` ## [](#see-also)See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features) # Using DataWeave Expressions
To view an example policy project that uses DataWeave expressions, see DataWeave Policy Example.
If the input DataWeave expression parameter is valid, the policy parses the expression and transforms it into a `pdk::script::Script` expression. To obtain the result of the script: 1. Create an evaluator. 2. Call the binding function for each parameter defined in the schema definition: - `vars`: Call the `bind_vars` method for each of the policy’s `vars`. After all of `vars` are bound, the evaluator tries to solve the expression. If the expression contains `vars` other than the ones defined in the schema, they resolve to `null`. - `attributes`: Call the `bind_attributes` method with an implementation of the `AttributesBinding` trait. Flex Gateway Policy Development Kit (PDK) provides an implementation of this trait by instantiating a new `HandlerAttributesBinding` for each `RequestHeaderState`, `RequestHeaderState`, and response of an [HTTP call](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-http-request). - `authentication`: Call the `bind_authentication` method with an implementation of the trait `AuthenticationBinding`. PDK provides an implementation of this trait for `AuthenticationData`. To inject authentication information into your policy, see [Inject Authentication Inforamaion](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-inject-parameters#authentication). - `payload`: Call the `bind_payload` method with an implementation of the trait `PayloadBinding`. PDK provides an implementation of this trait for `RequestBodyState`, `ResponseBodyState`, and the response of an [HTTP call](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-http-request).

Call only the methods for the bindings defined in the schema definition. For example, if the attributes binding is not used, don’t call the bind_attributes method.

To learn more about defining DataWeave expressions, see DataWeave Expressions.

3. After you bind all expression variables, obtain the result by calling the `eval` method. ## [](#example-evaluator-code)Evaluate DataWeave Expressions For example, to evaluate the `tokenExtractor` DataWeave expression in the following policy schema definition: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: Extension metadata: labels: title: jwt-auth category: Custom spec: extends: - name: extension-definition namespace: default properties: tokenExtractor: type: string format: dataweave default: "#[vars.myVar]" bindings: payload: mimeType: text attributes: true authentication: true vars: - myVar required: - tokenExtractor ```

Flex Gateway doesn’t support DataWeave expressions with binary type results. To use the dw::Binaries::fromBase64('dXNlcjpwYXNz') function, transform the result to a string. Transform the binary output to a string with the dw::util::Coercions::toString(binary: Binary, encoding: String): String function. For example, [dw::util::Coercions::toString(dw::core::Binaries::fromBase64('dXNlcjpwYXNz'), 'UTF-8')]. If using a different function that transforms the binary by default, such as [splitBy(dw::core::Binaries::fromBase64('dXNlcjpwYXNz'), ':')], you can skip manually transforming the binary.

Use the following Rust snippet: ```rust // Copyright 2024 Salesforce, Inc. All rights reserved. mod generated; use anyhow::Result; use crate::generated::config::Config; use pdk::authentication::{Authentication, AuthenticationHandler}; use pdk::logger::info; use pdk::hl::*; use pdk::script::{Evaluator, HandlerAttributesBinding, Value}; async fn request_filter( state: RequestState, stream: StreamProperties, auth: Authentication, mut evaluator: Evaluator<'_>, ) { evaluator.bind_vars("myVar", "myVal"); evaluator.bind_authentication(&auth.authentication()); let state = state.into_headers_state().await; evaluator.bind_attributes(&HandlerAttributesBinding::new(state.handler(), &stream)); let state = state.into_body_state().await; evaluator.bind_payload(&state); if let Ok(value) = evaluator.eval() { match value { Value::Null => info!("value was null!"), Value::Bool(val) => info!("value was Bool: {val}"), Value::Number(val) => info!("value was Number: {val}"), Value::String(val) => info!("value was String: {val}"), Value::Array(val) => info!("value was Array: {val:?}"), Value::Object(val) => info!("value was Object: {val:?}"), } } } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes)?; launcher .launch(on_request(|request, stream, auth| { request_filter(request, stream, auth, config.token_extractor.evaluator()) })) .await?; Ok(()) } ``` ## [](#validate-the-expression-was-resolved)Validate the Expression was Resolved You can resolve some expressions before all values are bound. For example, the expression `#[vars.myVar]` does not require the `attributes`, `payload`, no `authentication` to be resolved. After one of the binding methods is called, you can confirm the expression was completely resolved by calling the method: ```rust evaluator.is_ready() ``` ## [](#see-also)See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features) # Using DataWeave Expressions
To view an example policy project that uses DataWeave expressions, see DataWeave Policy Example.
If the input DataWeave expression parameter is valid, the policy parses the expression and transforms it into a `pdk::script::Script` expression. To obtain the result of the script: 1. Create an evaluator. 2. Call the binding function for each parameter defined in the schema definition: - `vars`: Call the `bind_vars` method for each of the policy’s `vars`. After all of `vars` are bound, the evaluator tries to solve the expression. If the expression contains `vars` other than the ones defined in the schema, they resolve to `null`. - `attributes`: Call the `bind_attributes` method with an implementation of the `AttributesBinding` trait. Flex Gateway Policy Development Kit (PDK) provides an implementation of this trait by instantiating a new `HandlerAttributesBinding` for each `RequestHeaderState`, `RequestHeaderState`, and response of an [HTTP call](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-http-request). - `authentication`: Call the `bind_authentication` method with an implementation of the trait `AuthenticationBinding`. PDK provides an implementation of this trait for `AuthenticationData`. To inject authentication information into your policy, see [Inject Authentication Inforamaion](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-inject-parameters#authentication). - `payload`: Call the `bind_payload` method with an implementation of the trait `PayloadBinding`. PDK provides an implementation of this trait for `RequestBodyState`, `ResponseBodyState`, and the response of an [HTTP call](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-http-request).

Call only the methods for the bindings defined in the schema definition. For example, if the attributes binding is not used, don’t call the bind_attributes method.

To learn more about defining DataWeave expressions, see DataWeave Expressions.

3. After you bind all expression variables, obtain the result by calling the `eval` method. ## [](#example-evaluator-code)Evaluate DataWeave Expressions For example, to evaluate the `tokenExtractor` DataWeave expression in the following policy schema definition: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: Extension metadata: labels: title: jwt-auth category: Custom spec: extends: - name: extension-definition namespace: default properties: tokenExtractor: type: string format: dataweave default: "#[vars.myVar]" bindings: payload: mimeType: text attributes: true authentication: true vars: - myVar required: - tokenExtractor ```

Flex Gateway doesn’t support DataWeave expressions with binary type results. To use the dw::Binaries::fromBase64('dXNlcjpwYXNz') function, transform the result to a string. Transform the binary output to a string with the dw::util::Coercions::toString(binary: Binary, encoding: String): String function. For example, [dw::util::Coercions::toString(dw::core::Binaries::fromBase64('dXNlcjpwYXNz'), 'UTF-8')]. If using a different function that transforms the binary by default, such as [splitBy(dw::core::Binaries::fromBase64('dXNlcjpwYXNz'), ':')], you can skip manually transforming the binary.

Use the following Rust snippet: ```rust // Copyright 2024 Salesforce, Inc. All rights reserved. mod generated; use anyhow::Result; use crate::generated::config::Config; use pdk::authentication::{Authentication, AuthenticationHandler}; use pdk::logger::info; use pdk::hl::*; use pdk::script::{Evaluator, HandlerAttributesBinding, Value}; async fn request_filter( state: RequestState, stream: StreamProperties, auth: Authentication, mut evaluator: Evaluator<'_>, ) { evaluator.bind_vars("myVar", "myVal"); evaluator.bind_authentication(&auth.authentication()); let state = state.into_headers_state().await; evaluator.bind_attributes(&HandlerAttributesBinding::new(state.handler(), &stream)); let state = state.into_body_state().await; evaluator.bind_payload(&state); if let Ok(value) = evaluator.eval() { match value { Value::Null => info!("value was null!"), Value::Bool(val) => info!("value was Bool: {val}"), Value::Number(val) => info!("value was Number: {val}"), Value::String(val) => info!("value was String: {val}"), Value::Array(val) => info!("value was Array: {val:?}"), Value::Object(val) => info!("value was Object: {val:?}"), } } } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes)?; launcher .launch(on_request(|request, stream, auth| { request_filter(request, stream, auth, config.token_extractor.evaluator()) })) .await?; Ok(()) } ``` ## [](#validate-the-expression-was-resolved)Validate the Expression was Resolved You can resolve some expressions before all values are bound. For example, the expression `#[vars.myVar]` does not require the `attributes`, `payload`, no `authentication` to be resolved. After one of the binding methods is called, you can confirm the expression was completely resolved by calling the method: ```rust evaluator.is_ready() ``` ## [](#see-also)See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features) # Using DataWeave Expressions
To view an example policy project that uses DataWeave expressions, see DataWeave Policy Example.
If the input DataWeave expression parameter is valid, the policy parses the expression and transforms it into a `pdk::script::Script` expression. To obtain the result of the script: 1. Create an evaluator. 2. Call the binding function for each parameter defined in the schema definition: - `vars`: Call the `bind_vars` method for each of the policy’s `vars`. After all of `vars` are bound, the evaluator tries to solve the expression. If the expression contains `vars` other than the ones defined in the schema, they resolve to `null`. - `attributes`: Call the `bind_attributes` method with an implementation of the `AttributesBinding` trait. Flex Gateway Policy Development Kit (PDK) provides an implementation of this trait by instantiating a new `HandlerAttributesBinding` for each `RequestHeaderState`, `RequestHeaderState`, and response of an [HTTP call](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-http-request). - `authentication`: Call the `bind_authentication` method with an implementation of the trait `AuthenticationBinding`. PDK provides an implementation of this trait for `AuthenticationData`. To inject authentication information into your policy, see [Inject Authentication Inforamaion](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-inject-parameters#authentication). - `payload`: Call the `bind_payload` method with an implementation of the trait `PayloadBinding`. PDK provides an implementation of this trait for `RequestBodyState`, `ResponseBodyState`, and the response of an [HTTP call](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-http-request).

Call only the methods for the bindings defined in the schema definition. For example, if the attributes binding is not used, don’t call the bind_attributes method.

To learn more about defining DataWeave expressions, see DataWeave Expressions.

3. After you bind all expression variables, obtain the result by calling the `eval` method. ## [](#example-evaluator-code)Evaluate DataWeave Expressions For example, to evaluate the `tokenExtractor` DataWeave expression in the following policy schema definition: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: Extension metadata: labels: title: jwt-auth category: Custom spec: extends: - name: extension-definition namespace: default properties: tokenExtractor: type: string format: dataweave default: "#[vars.myVar]" bindings: payload: mimeType: text attributes: true authentication: true vars: - myVar required: - tokenExtractor ```

Flex Gateway doesn’t support DataWeave expressions with binary type results. To use the dw::Binaries::fromBase64('dXNlcjpwYXNz') function, transform the result to a string. Transform the binary output to a string with the dw::util::Coercions::toString(binary: Binary, encoding: String): String function. For example, [dw::util::Coercions::toString(dw::core::Binaries::fromBase64('dXNlcjpwYXNz'), 'UTF-8')]. If using a different function that transforms the binary by default, such as [splitBy(dw::core::Binaries::fromBase64('dXNlcjpwYXNz'), ':')], you can skip manually transforming the binary.

Use the following Rust snippet: ```rust // Copyright 2024 Salesforce, Inc. All rights reserved. mod generated; use anyhow::Result; use crate::generated::config::Config; use pdk::authentication::{Authentication, AuthenticationHandler}; use pdk::logger::info; use pdk::hl::*; use pdk::script::{Evaluator, HandlerAttributesBinding, Value}; async fn request_filter( state: RequestState, stream: StreamProperties, auth: Authentication, mut evaluator: Evaluator<'_>, ) { evaluator.bind_vars("myVar", "myVal"); evaluator.bind_authentication(&auth.authentication()); let state = state.into_headers_state().await; evaluator.bind_attributes(&HandlerAttributesBinding::new(state.handler(), &stream)); let state = state.into_body_state().await; evaluator.bind_payload(&state); if let Ok(value) = evaluator.eval() { match value { Value::Null => info!("value was null!"), Value::Bool(val) => info!("value was Bool: {val}"), Value::Number(val) => info!("value was Number: {val}"), Value::String(val) => info!("value was String: {val}"), Value::Array(val) => info!("value was Array: {val:?}"), Value::Object(val) => info!("value was Object: {val:?}"), } } } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes)?; launcher .launch(on_request(|request, stream, auth| { request_filter(request, stream, auth, config.token_extractor.evaluator()) })) .await?; Ok(()) } ``` ## [](#validate-the-expression-was-resolved)Validate the Expression was Resolved You can resolve some expressions before all values are bound. For example, the expression `#[vars.myVar]` does not require the `attributes`, `payload`, no `authentication` to be resolved. After one of the binding methods is called, you can confirm the expression was completely resolved by calling the method: ```rust evaluator.is_ready() ``` ## [](#see-also)See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features) # Using DataWeave Expressions
To view an example policy project that uses DataWeave expressions, see DataWeave Policy Example.
If the input DataWeave expression parameter is valid, the policy parses the expression and transforms it into a `pdk::script::Script` expression. To obtain the result of the script: 1. Create an evaluator. 2. Call the binding function for each parameter defined in the schema definition: - `vars`: Call the `bind_vars` method for each of the policy’s `vars`. After all of `vars` are bound, the evaluator tries to solve the expression. If the expression contains `vars` other than the ones defined in the schema, they resolve to `null`. - `attributes`: Call the `bind_attributes` method with an implementation of the `AttributesBinding` trait. Omni Gateway Policy Development Kit (PDK) provides an implementation of this trait by instantiating a new `HandlerAttributesBinding` for each `RequestHeaderState`, `RequestHeaderState`, and response of an [HTTP call](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-http-request). - `authentication`: Call the `bind_authentication` method with an implementation of the trait `AuthenticationBinding`. PDK provides an implementation of this trait for `AuthenticationData`. To inject authentication information into your policy, see [Inject Authentication Inforamaion](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-inject-parameters#authentication). - `payload`: Call the `bind_payload` method with an implementation of the trait `PayloadBinding`. PDK provides an implementation of this trait for `RequestBodyState`, `ResponseBodyState`, and the response of an [HTTP call](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-http-request).

Call only the methods for the bindings defined in the schema definition. For example, if the attributes binding is not used, don’t call the bind_attributes method.

To learn more about defining DataWeave expressions, see DataWeave Expressions.

3. After you bind all expression variables, obtain the result by calling the `eval` method. ## [](#example-evaluator-code)Evaluate DataWeave Expressions For example, to evaluate the `tokenExtractor` DataWeave expression in the following policy schema definition: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: Extension metadata: labels: title: jwt-auth category: Custom spec: extends: - name: extension-definition namespace: default properties: tokenExtractor: type: string format: dataweave default: "#[vars.myVar]" bindings: payload: mimeType: text attributes: true authentication: true vars: - myVar required: - tokenExtractor ```

Omni Gateway doesn’t support DataWeave expressions with binary type results. To use the dw::Binaries::fromBase64('dXNlcjpwYXNz') function, transform the result to a string. Transform the binary output to a string with the dw::util::Coercions::toString(binary: Binary, encoding: String): String function. For example, [dw::util::Coercions::toString(dw::core::Binaries::fromBase64('dXNlcjpwYXNz'), 'UTF-8')]. If using a different function that transforms the binary by default, such as [splitBy(dw::core::Binaries::fromBase64('dXNlcjpwYXNz'), ':')], you can skip manually transforming the binary.

Use the following Rust snippet: ```rust // Copyright 2024 Salesforce, Inc. All rights reserved. mod generated; use anyhow::Result; use crate::generated::config::Config; use pdk::authentication::{Authentication, AuthenticationHandler}; use pdk::logger::info; use pdk::hl::*; use pdk::script::{Evaluator, HandlerAttributesBinding, Value}; async fn request_filter( state: RequestState, stream: StreamProperties, auth: Authentication, mut evaluator: Evaluator<'_>, ) { evaluator.bind_vars("myVar", "myVal"); evaluator.bind_authentication(&auth.authentication()); let state = state.into_headers_state().await; evaluator.bind_attributes(&HandlerAttributesBinding::new(state.handler(), &stream)); let state = state.into_body_state().await; evaluator.bind_payload(&state); if let Ok(value) = evaluator.eval() { match value { Value::Null => info!("value was null!"), Value::Bool(val) => info!("value was Bool: {val}"), Value::Number(val) => info!("value was Number: {val}"), Value::String(val) => info!("value was String: {val}"), Value::Array(val) => info!("value was Array: {val:?}"), Value::Object(val) => info!("value was Object: {val:?}"), } } } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes)?; launcher .launch(on_request(|request, stream, auth| { request_filter(request, stream, auth, config.token_extractor.evaluator()) })) .await?; Ok(()) } ``` ## [](#validate-the-expression-was-resolved)Validate the Expression was Resolved You can resolve some expressions before all values are bound. For example, the expression `#[vars.myVar]` does not require the `attributes`, `payload`, no `authentication` to be resolved. After one of the binding methods is called, you can confirm the expression was completely resolved by calling the method: ```rust evaluator.is_ready() ``` ## [](#see-also)See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features) # Using DataWeave Expressions
To view an example policy project that uses DataWeave expressions, see DataWeave Policy Example.
If the input DataWeave expression parameter is valid, the policy parses the expression and transforms it into a `pdk::script::Script` expression. To obtain the result of the script: 1. Create an evaluator. 2. Call the binding function for each parameter defined in the schema definition: - `vars`: Call the `bind_vars` method for each of the policy’s `vars`. After all of `vars` are bound, the evaluator tries to solve the expression. If the expression contains `vars` other than the ones defined in the schema, they resolve to `null`. - `attributes`: Call the `bind_attributes` method with an implementation of the `AttributesBinding` trait. Omni Gateway Policy Development Kit (PDK) provides an implementation of this trait by instantiating a new `HandlerAttributesBinding` for each `RequestHeaderState`, `RequestHeaderState`, and response of an [HTTP call](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-http-request). - `authentication`: Call the `bind_authentication` method with an implementation of the trait `AuthenticationBinding`. PDK provides an implementation of this trait for `AuthenticationData`. To inject authentication information into your policy, see [Inject Authentication Inforamaion](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-inject-parameters#authentication). - `payload`: Call the `bind_payload` method with an implementation of the trait `PayloadBinding`. PDK provides an implementation of this trait for `RequestBodyState`, `ResponseBodyState`, and the response of an [HTTP call](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-http-request).

Call only the methods for the bindings defined in the schema definition. For example, if the attributes binding is not used, don’t call the bind_attributes method.

To learn more about defining DataWeave expressions, see DataWeave Expressions.

3. After you bind all expression variables, obtain the result by calling the `eval` method. ## [](#example-evaluator-code)Evaluate DataWeave Expressions For example, to evaluate the `tokenExtractor` DataWeave expression in the following policy schema definition: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: Extension metadata: labels: title: jwt-auth category: Custom spec: extends: - name: extension-definition namespace: default properties: tokenExtractor: type: string format: dataweave default: "#[vars.myVar]" bindings: payload: mimeType: text attributes: true authentication: true vars: - myVar required: - tokenExtractor ```

Omni Gateway doesn’t support DataWeave expressions with binary type results. To use the dw::Binaries::fromBase64('dXNlcjpwYXNz') function, transform the result to a string. Transform the binary output to a string with the dw::util::Coercions::toString(binary: Binary, encoding: String): String function. For example, [dw::util::Coercions::toString(dw::core::Binaries::fromBase64('dXNlcjpwYXNz'), 'UTF-8')]. If using a different function that transforms the binary by default, such as [splitBy(dw::core::Binaries::fromBase64('dXNlcjpwYXNz'), ':')], you can skip manually transforming the binary.

Use the following Rust snippet: ```rust // Copyright 2024 Salesforce, Inc. All rights reserved. mod generated; use anyhow::Result; use crate::generated::config::Config; use pdk::authentication::{Authentication, AuthenticationHandler}; use pdk::logger::info; use pdk::hl::*; use pdk::script::{Evaluator, HandlerAttributesBinding, Value}; async fn request_filter( state: RequestState, stream: StreamProperties, auth: Authentication, mut evaluator: Evaluator<'_>, ) { evaluator.bind_vars("myVar", "myVal"); evaluator.bind_authentication(&auth.authentication()); let state = state.into_headers_state().await; evaluator.bind_attributes(&HandlerAttributesBinding::new(state.handler(), &stream)); let state = state.into_body_state().await; evaluator.bind_payload(&state); if let Ok(value) = evaluator.eval() { match value { Value::Null => info!("value was null!"), Value::Bool(val) => info!("value was Bool: {val}"), Value::Number(val) => info!("value was Number: {val}"), Value::String(val) => info!("value was String: {val}"), Value::Array(val) => info!("value was Array: {val:?}"), Value::Object(val) => info!("value was Object: {val:?}"), } } } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes)?; launcher .launch(on_request(|request, stream, auth| { request_filter(request, stream, auth, config.token_extractor.evaluator()) })) .await?; Ok(()) } ``` ## [](#validate-the-expression-was-resolved)Validate the Expression was Resolved You can resolve some expressions before all values are bound. For example, the expression `#[vars.myVar]` does not require the `attributes`, `payload`, no `authentication` to be resolved. After one of the binding methods is called, you can confirm the expression was completely resolved by calling the method: ```rust evaluator.is_ready() ``` ## [](#see-also)See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features) # Using DataWeave Expressions
To view an example policy project that uses DataWeave expressions, see DataWeave Policy Example.
If the input DataWeave expression parameter is valid, the policy parses the expression and transforms it into a `pdk::script::Script` expression. To obtain the result of the script: 1. Create an evaluator. 2. Call the binding function for each parameter defined in the schema definition: - `vars`: Call the `bind_vars` method for each of the policy’s `vars`. After all of `vars` are bound, the evaluator tries to solve the expression. If the expression contains `vars` other than the ones defined in the schema, they resolve to `null`. - `attributes`: Call the `bind_attributes` method with an implementation of the `AttributesBinding` trait. Omni Gateway Policy Development Kit (PDK) provides an implementation of this trait by instantiating a new `HandlerAttributesBinding` for each `RequestHeaderState`, `RequestHeaderState`, and response of an [HTTP call](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-http-request). - `authentication`: Call the `bind_authentication` method with an implementation of the trait `AuthenticationBinding`. PDK provides an implementation of this trait for `AuthenticationData`. To inject authentication information into your policy, see [Inject Authentication Inforamaion](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-inject-parameters#authentication). - `payload`: Call the `bind_payload` method with an implementation of the trait `PayloadBinding`. PDK provides an implementation of this trait for `RequestBodyState`, `ResponseBodyState`, and the response of an [HTTP call](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-http-request).

Call only the methods for the bindings defined in the schema definition. For example, if the attributes binding is not used, don’t call the bind_attributes method.

To learn more about defining DataWeave expressions, see DataWeave Expressions.

3. After you bind all expression variables, obtain the result by calling the `eval` method. ## [](#example-evaluator-code)Evaluate DataWeave Expressions For example, to evaluate the `tokenExtractor` DataWeave expression in the following policy schema definition: ```yaml apiVersion: gateway.mulesoft.com/v1alpha1 kind: Extension metadata: labels: title: jwt-auth category: Custom spec: extends: - name: extension-definition namespace: default properties: tokenExtractor: type: string format: dataweave default: "#[vars.myVar]" bindings: payload: mimeType: text attributes: true authentication: true vars: - myVar required: - tokenExtractor ```

Omni Gateway doesn’t support DataWeave expressions with binary type results. To use the dw::Binaries::fromBase64('dXNlcjpwYXNz') function, transform the result to a string. Transform the binary output to a string with the dw::util::Coercions::toString(binary: Binary, encoding: String): String function. For example, [dw::util::Coercions::toString(dw::core::Binaries::fromBase64('dXNlcjpwYXNz'), 'UTF-8')]. If using a different function that transforms the binary by default, such as [splitBy(dw::core::Binaries::fromBase64('dXNlcjpwYXNz'), ':')], you can skip manually transforming the binary.

Use the following Rust snippet: ```rust // Copyright 2024 Salesforce, Inc. All rights reserved. mod generated; use anyhow::Result; use crate::generated::config::Config; use pdk::authentication::{Authentication, AuthenticationHandler}; use pdk::logger::info; use pdk::hl::*; use pdk::script::{Evaluator, HandlerAttributesBinding, Value}; async fn request_filter( state: RequestState, stream: StreamProperties, auth: Authentication, mut evaluator: Evaluator<'_>, ) { evaluator.bind_vars("myVar", "myVal"); evaluator.bind_authentication(&auth.authentication()); let state = state.into_headers_state().await; evaluator.bind_attributes(&HandlerAttributesBinding::new(state.handler(), &stream)); let state = state.into_body_state().await; evaluator.bind_payload(&state); if let Ok(value) = evaluator.eval() { match value { Value::Null => info!("value was null!"), Value::Bool(val) => info!("value was Bool: {val}"), Value::Number(val) => info!("value was Number: {val}"), Value::String(val) => info!("value was String: {val}"), Value::Array(val) => info!("value was Array: {val:?}"), Value::Object(val) => info!("value was Object: {val:?}"), } } } #[entrypoint] async fn configure(launcher: Launcher, Configuration(bytes): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&bytes)?; launcher .launch(on_request(|request, stream, auth| { request_filter(request, stream, auth, config.token_extractor.evaluator()) })) .await?; Ok(()) } ``` ## [](#validate-the-expression-was-resolved)Validate the Expression was Resolved You can resolve some expressions before all values are bound. For example, the expression `#[vars.myVar]` does not require the `attributes`, `payload`, no `authentication` to be resolved. After one of the binding methods is called, you can confirm the expression was completely resolved by calling the method: ```rust evaluator.is_ready() ``` ## [](#see-also)See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Using JSON Validator Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)'s > JSON Validator library, see > [JSON Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/json-validation/README.md). JSON APIs can receive payloads with deep nesting, oversized arrays or objects, or long strings and keys. Attackers use those patterns to stress parsers and memory. With `validate_chunk`, you feed the payload incrementally while the PDK JSON Validator library enforces configurable limits. Use the library to build custom policies. These limits match the constraint types in [JSON Threat Protection Policy](https://docs.mulesoft.com/gateway/latest/policies-included-json-threat-protection) for Omni Gateway. Use the library when your custom policy must perform these tasks. - Accept JSON request or response bodies and reject malformed or oversized payloads before the gateway fully buffers them. - Apply limits that match your API’s threat model, such as maximum nesting depth, array length, object entry count, or string and key size. - Validate JSON with [streaming body state](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-headers#streaming-bodies). Call `validate_chunk` for each chunk, or buffer the full stream in memory first, then call `validate_chunk` once with `end_of_stream` set to `true`. Import the types you need from the `json_validator` module of the PDK crate. ```Rust use pdk::json_validator::{JsonValidatorBuilder, ValidationError, ValidationResult}; ``` ## Build a JSON Validator Create a validator with `JsonValidatorBuilder::new()`, chain the configuration methods for the limits you need, and call `build()`. Builder methods match the constraint types in [JSON Threat Protection Policy](https://docs.mulesoft.com/gateway/latest/policies-included-json-threat-protection). Policy UI parameter names differ slightly, but the intent matches.
MethodDescription

with_max_depth

Maximum nesting depth of JSON containers, objects, and arrays combined.

with_max_array_length

Maximum number of elements in a single array.

with_max_object_entries

Maximum number of entries in a single object.

with_max_key_length

Maximum length of an object entry name, as UTF-8 byte length.

with_max_string_length

Maximum length of a string value, as UTF-8 byte length.

If you omit a `with_*` method, that limit isn’t applied, so there’s no restriction on that field. Call only the methods for limits you want enforced. For type details and any extra options, see the PDK Rust API documentation for your release. ## Validate JSON Body Chunks Call `validate_chunk` for each slice of the body you read from the client. The second argument is `end_of_stream`. Set it to `true` only on the final chunk so the parser knows the document is complete. `validate_chunk` returns one of these outcomes: - `Ok(ValidationResult::Incomplete)`, the JSON is valid so far, and you need more chunks before validation can finish. - `Ok(ValidationResult::Complete)`, the JSON is complete and valid. - `Err(ValidationError::…​)`, the payload is malformed or violates a configured limit. See the PDK Rust API documentation for every variant, such as `UnableToProcessPayload`. This example reads every chunk from the body stream into a single buffer, then validates the buffer in one call with `end_of_stream` set to `true`. For very large bodies, call `validate_chunk` once per chunk instead, and set `end_of_stream` to `true` only on the last chunk so you don’t hold the full payload in memory. ```Rust use anyhow::Result; use futures::StreamExt; use pdk::hl::*; use pdk::json_validator::{JsonValidatorBuilder, ValidationError, ValidationResult}; async fn request_filter(state: RequestState) -> Flow<()> { let headers_state = state.into_headers_state().await; if !headers_state.contains_body() { return Flow::Continue(()); } let body_stream_state = headers_state.into_body_stream_state().await; let mut validator = JsonValidatorBuilder::new() .with_max_depth(10) .with_max_array_length(1000) .with_max_object_entries(1000) .with_max_key_length(256) .with_max_string_length(10000) .build(); let mut stream = body_stream_state.stream(); let mut buf = Vec::new(); while let Some(chunk) = stream.next().await { buf.extend_from_slice(&chunk.into_bytes()); } match validator.validate_chunk(&buf, true) { Ok(ValidationResult::Incomplete) => { Flow::Break(Response::new(400).with_body("Incomplete JSON payload")) } Ok(ValidationResult::Complete) => Flow::Continue(()), Err(ValidationError::UnableToProcessPayload) => { Flow::Break(Response::new(400).with_body("Invalid or disallowed JSON payload")) } Err(_) => Flow::Break(Response::new(400).with_body("Invalid or disallowed JSON payload")), } } #[entrypoint] async fn configure(launcher: Launcher, Configuration(_configuration): Configuration) -> Result<()> { launcher .launch(on_request(|request| request_filter(request))) .await?; Ok(()) } ``` On success, the example continues the request so upstream processing runs. On failure, the policy returns `400 Bad Request`. Change the status code and body to match your API’s contract. When `end_of_stream` is `true` and the validator returns `ValidationResult::Incomplete`, the client didn’t send a complete JSON value. Treat that outcome as an error for your API. ## Initialize the Validator from Policy Configuration If you supply limits through your policy schema in GCL, parse the configuration and build the `JsonValidatorBuilder` in the `#[entrypoint]` function. If the configuration is invalid or incompatible, you see a failure when you apply the policy, before traffic reaches the API. Pass the validator into your request filter. When you need shared ownership across closures, wrap the validator in `std::rc::Rc` or `std::sync::Arc`, depending on your policy layout. Map your generated `config::Config` fields to the builder methods in [Build a JSON Validator](#build-json-validator). Use the types the PDK API expects for your release. ## Interpret Validation Errors If `validate_chunk` returns `Err`, reject the payload. The JSON might be malformed or violate a configured limit. If you need operational detail, log the error at the debug or warn level. If you can’t expose parser details, return a generic message to clients. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features) - [Streaming Bodies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-headers#streaming-bodies) - [JSON Threat Protection Policy](https://docs.mulesoft.com/gateway/latest/policies-included-json-threat-protection) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Using JSON Validator Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)'s > JSON Validator library, see > [JSON Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/json-validation/README.md). JSON APIs can receive payloads with deep nesting, oversized arrays or objects, or long strings and keys. Attackers use those patterns to stress parsers and memory. With `validate_chunk`, you feed the payload incrementally while the PDK JSON Validator library enforces configurable limits. Use the library to build custom policies. These limits match the constraint types in [JSON Threat Protection Policy](https://docs.mulesoft.com/gateway/latest/policies-included-json-threat-protection) for Omni Gateway. Use the library when your custom policy must perform these tasks. - Accept JSON request or response bodies and reject malformed or oversized payloads before the gateway fully buffers them. - Apply limits that match your API’s threat model, such as maximum nesting depth, array length, object entry count, or string and key size. - Validate JSON with [streaming body state](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-headers#streaming-bodies). Call `validate_chunk` for each chunk, or buffer the full stream in memory first, then call `validate_chunk` once with `end_of_stream` set to `true`. Import the types you need from the `json_validator` module of the PDK crate. ```Rust use pdk::json_validator::{JsonValidatorBuilder, ValidationError, ValidationResult}; ``` ## Build a JSON Validator Create a validator with `JsonValidatorBuilder::new()`, chain the configuration methods for the limits you need, and call `build()`. Builder methods match the constraint types in [JSON Threat Protection Policy](https://docs.mulesoft.com/gateway/latest/policies-included-json-threat-protection). Policy UI parameter names differ slightly, but the intent matches.
MethodDescription

with_max_depth

Maximum nesting depth of JSON containers, objects, and arrays combined.

with_max_array_length

Maximum number of elements in a single array.

with_max_object_entries

Maximum number of entries in a single object.

with_max_key_length

Maximum length of an object entry name, as UTF-8 byte length.

with_max_string_length

Maximum length of a string value, as UTF-8 byte length.

If you omit a `with_*` method, that limit isn’t applied, so there’s no restriction on that field. Call only the methods for limits you want enforced. For type details and any extra options, see the PDK Rust API documentation for your release. ## Validate JSON Body Chunks Call `validate_chunk` for each slice of the body you read from the client. The second argument is `end_of_stream`. Set it to `true` only on the final chunk so the parser knows the document is complete. `validate_chunk` returns one of these outcomes: - `Ok(ValidationResult::Incomplete)`, the JSON is valid so far, and you need more chunks before validation can finish. - `Ok(ValidationResult::Complete)`, the JSON is complete and valid. - `Err(ValidationError::…​)`, the payload is malformed or violates a configured limit. See the PDK Rust API documentation for every variant, such as `UnableToProcessPayload`. This example reads every chunk from the body stream into a single buffer, then validates the buffer in one call with `end_of_stream` set to `true`. For very large bodies, call `validate_chunk` once per chunk instead, and set `end_of_stream` to `true` only on the last chunk so you don’t hold the full payload in memory. ```Rust use anyhow::Result; use futures::StreamExt; use pdk::hl::*; use pdk::json_validator::{JsonValidatorBuilder, ValidationError, ValidationResult}; async fn request_filter(state: RequestState) -> Flow<()> { let headers_state = state.into_headers_state().await; if !headers_state.contains_body() { return Flow::Continue(()); } let body_stream_state = headers_state.into_body_stream_state().await; let mut validator = JsonValidatorBuilder::new() .with_max_depth(10) .with_max_array_length(1000) .with_max_object_entries(1000) .with_max_key_length(256) .with_max_string_length(10000) .build(); let mut stream = body_stream_state.stream(); let mut buf = Vec::new(); while let Some(chunk) = stream.next().await { buf.extend_from_slice(&chunk.into_bytes()); } match validator.validate_chunk(&buf, true) { Ok(ValidationResult::Incomplete) => { Flow::Break(Response::new(400).with_body("Incomplete JSON payload")) } Ok(ValidationResult::Complete) => Flow::Continue(()), Err(ValidationError::UnableToProcessPayload) => { Flow::Break(Response::new(400).with_body("Invalid or disallowed JSON payload")) } Err(_) => Flow::Break(Response::new(400).with_body("Invalid or disallowed JSON payload")), } } #[entrypoint] async fn configure(launcher: Launcher, Configuration(_configuration): Configuration) -> Result<()> { launcher .launch(on_request(|request| request_filter(request))) .await?; Ok(()) } ``` On success, the example continues the request so upstream processing runs. On failure, the policy returns `400 Bad Request`. Change the status code and body to match your API’s contract. When `end_of_stream` is `true` and the validator returns `ValidationResult::Incomplete`, the client didn’t send a complete JSON value. Treat that outcome as an error for your API. ## Initialize the Validator from Policy Configuration If you supply limits through your policy schema in GCL, parse the configuration and build the `JsonValidatorBuilder` in the `#[entrypoint]` function. If the configuration is invalid or incompatible, you see a failure when you apply the policy, before traffic reaches the API. Pass the validator into your request filter. When you need shared ownership across closures, wrap the validator in `std::rc::Rc` or `std::sync::Arc`, depending on your policy layout. Map your generated `config::Config` fields to the builder methods in [Build a JSON Validator](#build-json-validator). Use the types the PDK API expects for your release. ## Interpret Validation Errors If `validate_chunk` returns `Err`, reject the payload. The JSON might be malformed or violate a configured limit. If you need operational detail, log the error at the debug or warn level. If you can’t expose parser details, return a generic message to clients. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features) - [Streaming Bodies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-headers#streaming-bodies) - [JSON Threat Protection Policy](https://docs.mulesoft.com/gateway/latest/policies-included-json-threat-protection) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Using JSON Validator Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)'s > JSON Validator library, see > [JSON Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/json-validation/README.md). JSON APIs can receive payloads with deep nesting, oversized arrays or objects, or long strings and keys. Attackers use those patterns to stress parsers and memory. With `validate_chunk`, you feed the payload incrementally while the PDK JSON Validator library enforces configurable limits. Use the library to build custom policies. These limits match the constraint types in [JSON Threat Protection Policy](https://docs.mulesoft.com/gateway/latest/policies-included-json-threat-protection) for Omni Gateway. Use the library when your custom policy must perform these tasks. - Accept JSON request or response bodies and reject malformed or oversized payloads before the gateway fully buffers them. - Apply limits that match your API’s threat model, such as maximum nesting depth, array length, object entry count, or string and key size. - Validate JSON with [streaming body state](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-headers#streaming-bodies). Call `validate_chunk` for each chunk, or buffer the full stream in memory first, then call `validate_chunk` once with `end_of_stream` set to `true`. Import the types you need from the `json_validator` module of the PDK crate. ```Rust use pdk::json_validator::{JsonValidatorBuilder, ValidationError, ValidationResult}; ``` ## Build a JSON Validator Create a validator with `JsonValidatorBuilder::new()`, chain the configuration methods for the limits you need, and call `build()`. Builder methods match the constraint types in [JSON Threat Protection Policy](https://docs.mulesoft.com/gateway/latest/policies-included-json-threat-protection). Policy UI parameter names differ slightly, but the intent matches.
MethodDescription

with_max_depth

Maximum nesting depth of JSON containers, objects, and arrays combined.

with_max_array_length

Maximum number of elements in a single array.

with_max_object_entries

Maximum number of entries in a single object.

with_max_key_length

Maximum length of an object entry name, as UTF-8 byte length.

with_max_string_length

Maximum length of a string value, as UTF-8 byte length.

If you omit a `with_*` method, that limit isn’t applied, so there’s no restriction on that field. Call only the methods for limits you want enforced. For type details and any extra options, see the PDK Rust API documentation for your release. ## Validate JSON Body Chunks Call `validate_chunk` for each slice of the body you read from the client. The second argument is `end_of_stream`. Set it to `true` only on the final chunk so the parser knows the document is complete. `validate_chunk` returns one of these outcomes: - `Ok(ValidationResult::Incomplete)`, the JSON is valid so far, and you need more chunks before validation can finish. - `Ok(ValidationResult::Complete)`, the JSON is complete and valid. - `Err(ValidationError::…​)`, the payload is malformed or violates a configured limit. See the PDK Rust API documentation for every variant, such as `UnableToProcessPayload`. This example reads every chunk from the body stream into a single buffer, then validates the buffer in one call with `end_of_stream` set to `true`. For very large bodies, call `validate_chunk` once per chunk instead, and set `end_of_stream` to `true` only on the last chunk so you don’t hold the full payload in memory. ```Rust use anyhow::Result; use futures::StreamExt; use pdk::hl::*; use pdk::json_validator::{JsonValidatorBuilder, ValidationError, ValidationResult}; async fn request_filter(state: RequestState) -> Flow<()> { let headers_state = state.into_headers_state().await; if !headers_state.contains_body() { return Flow::Continue(()); } let body_stream_state = headers_state.into_body_stream_state().await; let mut validator = JsonValidatorBuilder::new() .with_max_depth(10) .with_max_array_length(1000) .with_max_object_entries(1000) .with_max_key_length(256) .with_max_string_length(10000) .build(); let mut stream = body_stream_state.stream(); let mut buf = Vec::new(); while let Some(chunk) = stream.next().await { buf.extend_from_slice(&chunk.into_bytes()); } match validator.validate_chunk(&buf, true) { Ok(ValidationResult::Incomplete) => { Flow::Break(Response::new(400).with_body("Incomplete JSON payload")) } Ok(ValidationResult::Complete) => Flow::Continue(()), Err(ValidationError::UnableToProcessPayload) => { Flow::Break(Response::new(400).with_body("Invalid or disallowed JSON payload")) } Err(_) => Flow::Break(Response::new(400).with_body("Invalid or disallowed JSON payload")), } } #[entrypoint] async fn configure(launcher: Launcher, Configuration(_configuration): Configuration) -> Result<()> { launcher .launch(on_request(|request| request_filter(request))) .await?; Ok(()) } ``` On success, the example continues the request so upstream processing runs. On failure, the policy returns `400 Bad Request`. Change the status code and body to match your API’s contract. When `end_of_stream` is `true` and the validator returns `ValidationResult::Incomplete`, the client didn’t send a complete JSON value. Treat that outcome as an error for your API. ## Initialize the Validator from Policy Configuration If you supply limits through your policy schema in GCL, parse the configuration and build the `JsonValidatorBuilder` in the `#[entrypoint]` function. If the configuration is invalid or incompatible, you see a failure when you apply the policy, before traffic reaches the API. Pass the validator into your request filter. When you need shared ownership across closures, wrap the validator in `std::rc::Rc` or `std::sync::Arc`, depending on your policy layout. Map your generated `config::Config` fields to the builder methods in [Build a JSON Validator](#build-json-validator). Use the types the PDK API expects for your release. ## Interpret Validation Errors If `validate_chunk` returns `Err`, reject the payload. The JSON might be malformed or violate a configured limit. If you need operational detail, log the error at the debug or warn level. If you can’t expose parser details, return a generic message to clients. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features) - [Streaming Bodies](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-headers#streaming-bodies) - [JSON Threat Protection Policy](https://docs.mulesoft.com/gateway/latest/policies-included-json-threat-protection) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Using JWT Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Flex Gateway Policy Development Kit (PDK)'s > JWT library, see > [JWT Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/jwt-validation/README.md). JSON Web Token (JWT) is a URL-secure method of representing claims to be transferred between two parties. The JWT token contains claims encoded in a JSON object as either the payload of a JSON Web Signature (JWS) or as a JSON web encryption (JWE) structure in plain text, which enables the claims to be digitally signed and protected with a message authentication code (MAC). Because the token is signed, you can trust the information and its source. PDK’s JWT library provides a set of tools to validate the JWT signatures and to extract and validate the claims of all incoming requests. ## Extract a JWT Token PDK provides a `TokenProvider` struct that has the `bearer` function to extract JWT tokens that have the format `Bearer ` in the authorization header. The following code demonstrates how to use the `bearer` function: ```Rust // [...] use pdk::jwt::*; // [...] async fn filter( state: RequestState, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; // [...] ``` If you are using a JWT token from a different source or with a different format, you can implement Rust logic to get any other part of the request. Use a DataWeave parameter to configure extraction to create a policy where you can dynamically change the JWT source. ## Validate a JWT Signature The JWT library provides a helper for performing signature validation of the incoming requests authorization tokens. Depending on the algorithm used by the policy, initialize a `SignatureValidator` with the corresponding configuration: ```Rust pub fn new(algorithm: SigningAlgorithm, key_length: SigningKeyLength, key: String) -> Result ``` PDK supports the following signing algorithms and key lengths:

Signing Algorithm

Signing Key Length

RSA

256, 384 and 512

HMAC

256, 384 and 512

ES

256 and 384

The `SigningAlgorithm` enum defines the available signing algorithms: ```Rust pub enum SigningAlgorithm { Rsa, Hmac, Es, } ``` The `SigningKeyLength` enum defines the available signing key lengths: ```Rust pub enum SigningKeyLength { Len256, Len384, Len512, } ``` A `SignatureValidator` instance implements the `SignatureValidation` trait. This `SignatureValidation` trait exposes a `validate` function that accepts tokens as `String` parameters and returns a `Result` that contains the parsed `JWTClaims` or a `JWTError` in the event of an error: ```Rust pub trait SignatureValidation { fn validate(&self, token: String) -> Result; } ``` The following code example shows how to initialize the `SignatureValidator` and validate an incoming token signed with a 256-byte HMAC algorithm: ```Rust use anyhow::Result; use pdk::hl::*; use pdk::jwt::*; // [...] async fn filter( state: RequestState, signature_validator: &SignatureValidator, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; if token.is_err() { return Flow::Break(Response::new(401).with_body("Bearer not found")); } // Validating signature let claims = signature_validator.validate(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } // [...] } #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&configuration)?; let signature_validator = SignatureValidator::new( model::SigningAlgorithm::Hmac, model::SigningKeyLength::Len256, config.secret.clone(), )?; launcher .launch(on_request(|request| { filter(request, &signature_validator) })) .await?; Ok(()) } ``` Because, the `SignatureValidator` confirms that the policy configurations are correct during initialization, initializing the `SignatureValidator` in the `#[entrypoint]` function throws an early error when the policy is applied rather than when the API receives a request. After initialization, the policy passes the `SignatureValidator` to the `on_request` wrapped function to perform `validate` method on incoming requests. ## Access Claims and Propagating to Headers After the [signature validation](#signature-validation) executes, the result contains the parsed JWT claims from the JWT token. In case the signature is invalid or you choose not to validate the signature, PDK provides the `JWTClaimsParser` to parse claims. This structure provides a `parse` method that returns `Result`. ```rust // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } ``` After you run the signature validation or the parsing method, use the following methods exposed by the `JWTClaims` struct to access the JWT claims: ```rust pub fn audience(&self) -> Option, JWTError>> pub fn not_before(&self) -> Option> pub fn expiration(&self) -> Option> pub fn issued_at(&self) -> Option> pub fn issuer(&self) -> Option pub fn jti(&self) -> Option pub fn nonce(&self) -> Option pub fn subject(&self) -> Option pub fn has_claim(&self, name: &str) -> bool pub fn get_claim(&self, name: &str) -> Option where T: ValueRetrieval, pub fn has_header(&self, name: &str) -> bool pub fn get_header(&self, name: &str) -> Option pub fn get_claims(&self) -> pdk_script::Value pub fn get_headers(&self) -> pdk_script::Value ``` The provided methods are designed to return each one of the standard JWT claims. The `get_claim` method can return any standard or custom claim. Because `get_claim` supports different target variable types, the user must specify the output type. `get_claim` supports `String`, `f64`, `Vec`, `chrono::DateTime`, and `serde_json::Value` output types. Because the claim might not exist in the token, you must wrap the type with an `Option`, for example: ```rust let some_custom_claim: Option = claims.get_claim("username"); ``` The following example shows how to parse a JWT token, get a custom claim, and propagate it to the request headers from a wrapped function: ```rust async fn filter( state: RequestState, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; if token.is_err() { return Flow::Break(Response::new(401).with_body("Bearer not found")); } // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } let claims = claims.unwrap(); let username: Option = claims.get_claim("username"); if let Some(custom_claim) = some_custom_claim { headers_state .handler() .set_header("username", custom_claim.as_str()); } Flow::Continue(()) } ``` ## Validate Claims JWT tokens typically contain a set of standard and non-standard claims that you can validate. Use the methods from [Access Claims and Propagating to Headers](#access-claims) to retrieve the claims present in the JWT tokens’s header or payload. Once retrieved, validate the value of the claims. The following code example validates that the JWT token: - Is not expired by validating the `exp` claim. - Has the correct audience value by validating the `aud` claim. - Has the correct custom `role` claim by using a custom validator configured as a DataWeave expression policy parameter. ```Rust use chrono::Utc; use pdk::hl::*; use pdk::jwt::*; use pdk::logger::info; use pdk::script::Evaluator; async fn filter( state: RequestState, mut custom_validator: Evaluator<'_>, ) -> Flow<()> { let headers_state = state.into_headers_state().await; let token = TokenProvider::bearer(headers_state.handler()); if token.is_err() { return Flow::Break(Response::new(400).with_body("Bearer not found")); } // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } let claims = claims.unwrap(); // Validating token expiration if let Some(exp) = claims.expiration() { if exp < Utc::now() { return Flow::Break(Response::new(400).with_body("token expired")); } } else { return Flow::Break(Response::new(400).with_body("token missing exp claim")); } // Validating audience if let Some(aud) = claims.audience() { if !aud_value.iter_mut().any(|a| a == "myAudience") { return Flow::Break(Response::new(400).with_body("token does not have the expected audience")); } } // Custom claim validation custom_validator.bind_vars("claimSet", claims.get_claims()); let result = custom_validator_role_claim.eval(); if !result.ok().and_then(|value| value.as_bool()).unwrap_or_default() { return Flow::Break(Response::new(400).with_body("custom token validations failed.")); } Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&configuration)?; launcher .launch(on_request(|request| { filter(request, config.custom_validator_role.evaluator()) })) .await?; Ok(()) } ``` In the above example, the custom `role` claim is defined by a DataWeave expression configured as an input parameter in the `gcl.yaml` schema definition as follows: ```yaml # [...] spec: extends: - name: extension-definition namespace: default properties: customValidatorRole: type: string format: dataweave default: "#[vars.claimSet.role == 'superRole']" # [...] required: - customValidatorRole ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Using JWT Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Flex Gateway Policy Development Kit (PDK)'s > JWT library, see > [JWT Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/jwt-validation/README.md). JSON Web Token (JWT) is a URL-secure method of representing claims to be transferred between two parties. The JWT token contains claims encoded in a JSON object as either the payload of a JSON Web Signature (JWS) or as a JSON web encryption (JWE) structure in plain text, which enables the claims to be digitally signed and protected with a message authentication code (MAC). Because the token is signed, you can trust the information and its source. PDK’s JWT library provides a set of tools to validate the JWT signatures and to extract and validate the claims of all incoming requests. ## Extract a JWT Token PDK provides a `TokenProvider` struct that has the `bearer` function to extract JWT tokens that have the format `Bearer ` in the authorization header. The following code demonstrates how to use the `bearer` function: ```Rust // [...] use pdk::jwt::*; // [...] async fn filter( state: RequestState, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; // [...] ``` If you are using a JWT token from a different source or with a different format, you can implement Rust logic to get any other part of the request. Use a DataWeave parameter to configure extraction to create a policy where you can dynamically change the JWT source. ## Validate a JWT Signature The JWT library provides a helper for performing signature validation of the incoming requests authorization tokens. Depending on the algorithm used by the policy, initialize a `SignatureValidator` with the corresponding configuration: ```Rust pub fn new(algorithm: SigningAlgorithm, key_length: SigningKeyLength, key: String) -> Result ``` PDK supports the following signing algorithms and key lengths:

Signing Algorithm

Signing Key Length

RSA

256, 384 and 512

HMAC

256, 384 and 512

ES

256 and 384

The `SigningAlgorithm` enum defines the available signing algorithms: ```Rust pub enum SigningAlgorithm { Rsa, Hmac, Es, } ``` The `SigningKeyLength` enum defines the available signing key lengths: ```Rust pub enum SigningKeyLength { Len256, Len384, Len512, } ``` A `SignatureValidator` instance implements the `SignatureValidation` trait. This `SignatureValidation` trait exposes a `validate` function that accepts tokens as `String` parameters and returns a `Result` that contains the parsed `JWTClaims` or a `JWTError` in the event of an error: ```Rust pub trait SignatureValidation { fn validate(&self, token: String) -> Result; } ``` The following code example shows how to initialize the `SignatureValidator` and validate an incoming token signed with a 256-byte HMAC algorithm: ```Rust use anyhow::Result; use pdk::hl::*; use pdk::jwt::*; // [...] async fn filter( state: RequestState, signature_validator: &SignatureValidator, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; if token.is_err() { return Flow::Break(Response::new(401).with_body("Bearer not found")); } // Validating signature let claims = signature_validator.validate(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } // [...] } #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&configuration)?; let signature_validator = SignatureValidator::new( model::SigningAlgorithm::Hmac, model::SigningKeyLength::Len256, config.secret.clone(), )?; launcher .launch(on_request(|request| { filter(request, &signature_validator) })) .await?; Ok(()) } ``` Because, the `SignatureValidator` confirms that the policy configurations are correct during initialization, initializing the `SignatureValidator` in the `#[entrypoint]` function throws an early error when the policy is applied rather than when the API receives a request. After initialization, the policy passes the `SignatureValidator` to the `on_request` wrapped function to perform `validate` method on incoming requests. ## Access Claims and Propagating to Headers After the [signature validation](#signature-validation) executes, the result contains the parsed JWT claims from the JWT token. In case the signature is invalid or you choose not to validate the signature, PDK provides the `JWTClaimsParser` to parse claims. This structure provides a `parse` method that returns `Result`. ```rust // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } ``` After you run the signature validation or the parsing method, use the following methods exposed by the `JWTClaims` struct to access the JWT claims: ```rust pub fn audience(&self) -> Option, JWTError>> pub fn not_before(&self) -> Option> pub fn expiration(&self) -> Option> pub fn issued_at(&self) -> Option> pub fn issuer(&self) -> Option pub fn jti(&self) -> Option pub fn nonce(&self) -> Option pub fn subject(&self) -> Option pub fn has_claim(&self, name: &str) -> bool pub fn get_claim(&self, name: &str) -> Option where T: ValueRetrieval, pub fn has_header(&self, name: &str) -> bool pub fn get_header(&self, name: &str) -> Option pub fn get_claims(&self) -> pdk_script::Value pub fn get_headers(&self) -> pdk_script::Value ``` The provided methods are designed to return each one of the standard JWT claims. The `get_claim` method can return any standard or custom claim. Because `get_claim` supports different target variable types, the user must specify the output type. `get_claim` supports `String`, `f64`, `Vec`, `chrono::DateTime`, and `serde_json::Value` output types. Because the claim might not exist in the token, you must wrap the type with an `Option`, for example: ```rust let some_custom_claim: Option = claims.get_claim("username"); ``` The following example shows how to parse a JWT token, get a custom claim, and propagate it to the request headers from a wrapped function: ```rust async fn filter( state: RequestState, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; if token.is_err() { return Flow::Break(Response::new(401).with_body("Bearer not found")); } // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } let claims = claims.unwrap(); let username: Option = claims.get_claim("username"); if let Some(custom_claim) = some_custom_claim { headers_state .handler() .set_header("username", custom_claim.as_str()); } Flow::Continue(()) } ``` ## Validate Claims JWT tokens typically contain a set of standard and non-standard claims that you can validate. Use the methods from [Access Claims and Propagating to Headers](#access-claims) to retrieve the claims present in the JWT tokens’s header or payload. Once retrieved, validate the value of the claims. The following code example validates that the JWT token: - Is not expired by validating the `exp` claim. - Has the correct audience value by validating the `aud` claim. - Has the correct custom `role` claim by using a custom validator configured as a DataWeave expression policy parameter. ```Rust use chrono::Utc; use pdk::hl::*; use pdk::jwt::*; use pdk::logger::info; use pdk::script::Evaluator; async fn filter( state: RequestState, mut custom_validator: Evaluator<'_>, ) -> Flow<()> { let headers_state = state.into_headers_state().await; let token = TokenProvider::bearer(headers_state.handler()); if token.is_err() { return Flow::Break(Response::new(400).with_body("Bearer not found")); } // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } let claims = claims.unwrap(); // Validating token expiration if let Some(exp) = claims.expiration() { if exp < Utc::now() { return Flow::Break(Response::new(400).with_body("token expired")); } } else { return Flow::Break(Response::new(400).with_body("token missing exp claim")); } // Validating audience if let Some(aud) = claims.audience() { if !aud_value.iter_mut().any(|a| a == "myAudience") { return Flow::Break(Response::new(400).with_body("token does not have the expected audience")); } } // Custom claim validation custom_validator.bind_vars("claimSet", claims.get_claims()); let result = custom_validator_role_claim.eval(); if !result.ok().and_then(|value| value.as_bool()).unwrap_or_default() { return Flow::Break(Response::new(400).with_body("custom token validations failed.")); } Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&configuration)?; launcher .launch(on_request(|request| { filter(request, config.custom_validator_role.evaluator()) })) .await?; Ok(()) } ``` In the above example, the custom `role` claim is defined by a DataWeave expression configured as an input parameter in the `gcl.yaml` schema definition as follows: ```yaml # [...] spec: extends: - name: extension-definition namespace: default properties: customValidatorRole: type: string format: dataweave default: "#[vars.claimSet.role == 'superRole']" # [...] required: - customValidatorRole ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Using JWT Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Flex Gateway Policy Development Kit (PDK)'s > JWT library, see > [JWT Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/jwt-validation/README.md). JSON Web Token (JWT) is a URL-secure method of representing claims to be transferred between two parties. The JWT token contains claims encoded in a JSON object as either the payload of a JSON Web Signature (JWS) or as a JSON web encryption (JWE) structure in plain text, which enables the claims to be digitally signed and protected with a message authentication code (MAC). Because the token is signed, you can trust the information and its source. PDK’s JWT library provides a set of tools to validate the JWT signatures and to extract and validate the claims of all incoming requests. ## Extract a JWT Token PDK provides a `TokenProvider` struct that has the `bearer` function to extract JWT tokens that have the format `Bearer ` in the authorization header. The following code demonstrates how to use the `bearer` function: ```Rust // [...] use pdk::jwt::*; // [...] async fn filter( state: RequestState, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; // [...] ``` If you are using a JWT token from a different source or with a different format, you can implement Rust logic to get any other part of the request. Use a DataWeave parameter to configure extraction to create a policy where you can dynamically change the JWT source. ## Validate a JWT Signature The JWT library provides a helper for performing signature validation of the incoming requests authorization tokens. Depending on the algorithm used by the policy, initialize a `SignatureValidator` with the corresponding configuration: ```Rust pub fn new(algorithm: SigningAlgorithm, key_length: SigningKeyLength, key: String) -> Result ``` PDK supports the following signing algorithms and key lengths:

Signing Algorithm

Signing Key Length

RSA

256, 384 and 512

HMAC

256, 384 and 512

ES

256 and 384

The `SigningAlgorithm` enum defines the available signing algorithms: ```Rust pub enum SigningAlgorithm { Rsa, Hmac, Es, } ``` The `SigningKeyLength` enum defines the available signing key lengths: ```Rust pub enum SigningKeyLength { Len256, Len384, Len512, } ``` A `SignatureValidator` instance implements the `SignatureValidation` trait. This `SignatureValidation` trait exposes a `validate` function that accepts tokens as `String` parameters and returns a `Result` that contains the parsed `JWTClaims` or a `JWTError` in the event of an error: ```Rust pub trait SignatureValidation { fn validate(&self, token: String) -> Result; } ``` The following code example shows how to initialize the `SignatureValidator` and validate an incoming token signed with a 256-byte HMAC algorithm: ```Rust use anyhow::Result; use pdk::hl::*; use pdk::jwt::*; // [...] async fn filter( state: RequestState, signature_validator: &SignatureValidator, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; if token.is_err() { return Flow::Break(Response::new(401).with_body("Bearer not found")); } // Validating signature let claims = signature_validator.validate(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } // [...] } #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&configuration)?; let signature_validator = SignatureValidator::new( model::SigningAlgorithm::Hmac, model::SigningKeyLength::Len256, config.secret.clone(), )?; launcher .launch(on_request(|request| { filter(request, &signature_validator) })) .await?; Ok(()) } ``` Because, the `SignatureValidator` confirms that the policy configurations are correct during initialization, initializing the `SignatureValidator` in the `#[entrypoint]` function throws an early error when the policy is applied rather than when the API receives a request. After initialization, the policy passes the `SignatureValidator` to the `on_request` wrapped function to perform `validate` method on incoming requests. ## Access Claims and Propagating to Headers After the [signature validation](#signature-validation) executes, the result contains the parsed JWT claims from the JWT token. In case the signature is invalid or you choose not to validate the signature, PDK provides the `JWTClaimsParser` to parse claims. This structure provides a `parse` method that returns `Result`. ```rust // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } ``` After you run the signature validation or the parsing method, use the following methods exposed by the `JWTClaims` struct to access the JWT claims: ```rust pub fn audience(&self) -> Option, JWTError>> pub fn not_before(&self) -> Option> pub fn expiration(&self) -> Option> pub fn issued_at(&self) -> Option> pub fn issuer(&self) -> Option pub fn jti(&self) -> Option pub fn nonce(&self) -> Option pub fn subject(&self) -> Option pub fn has_claim(&self, name: &str) -> bool pub fn get_claim(&self, name: &str) -> Option where T: ValueRetrieval, pub fn has_header(&self, name: &str) -> bool pub fn get_header(&self, name: &str) -> Option pub fn get_claims(&self) -> pdk_script::Value pub fn get_headers(&self) -> pdk_script::Value ``` The provided methods are designed to return each one of the standard JWT claims. The `get_claim` method can return any standard or custom claim. Because `get_claim` supports different target variable types, the user must specify the output type. `get_claim` supports `String`, `f64`, `Vec`, `chrono::DateTime`, and `serde_json::Value` output types. Because the claim might not exist in the token, you must wrap the type with an `Option`, for example: ```rust let some_custom_claim: Option = claims.get_claim("username"); ``` The following example shows how to parse a JWT token, get a custom claim, and propagate it to the request headers from a wrapped function: ```rust async fn filter( state: RequestState, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; if token.is_err() { return Flow::Break(Response::new(401).with_body("Bearer not found")); } // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } let claims = claims.unwrap(); let username: Option = claims.get_claim("username"); if let Some(custom_claim) = some_custom_claim { headers_state .handler() .set_header("username", custom_claim.as_str()); } Flow::Continue(()) } ``` ## Validate Claims JWT tokens typically contain a set of standard and non-standard claims that you can validate. Use the methods from [Access Claims and Propagating to Headers](#access-claims) to retrieve the claims present in the JWT tokens’s header or payload. Once retrieved, validate the value of the claims. The following code example validates that the JWT token: - Is not expired by validating the `exp` claim. - Has the correct audience value by validating the `aud` claim. - Has the correct custom `role` claim by using a custom validator configured as a DataWeave expression policy parameter. ```Rust use chrono::Utc; use pdk::hl::*; use pdk::jwt::*; use pdk::logger::info; use pdk::script::Evaluator; async fn filter( state: RequestState, mut custom_validator: Evaluator<'_>, ) -> Flow<()> { let headers_state = state.into_headers_state().await; let token = TokenProvider::bearer(headers_state.handler()); if token.is_err() { return Flow::Break(Response::new(400).with_body("Bearer not found")); } // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } let claims = claims.unwrap(); // Validating token expiration if let Some(exp) = claims.expiration() { if exp < Utc::now() { return Flow::Break(Response::new(400).with_body("token expired")); } } else { return Flow::Break(Response::new(400).with_body("token missing exp claim")); } // Validating audience if let Some(aud) = claims.audience() { if !aud_value.iter_mut().any(|a| a == "myAudience") { return Flow::Break(Response::new(400).with_body("token does not have the expected audience")); } } // Custom claim validation custom_validator.bind_vars("claimSet", claims.get_claims()); let result = custom_validator_role_claim.eval(); if !result.ok().and_then(|value| value.as_bool()).unwrap_or_default() { return Flow::Break(Response::new(400).with_body("custom token validations failed.")); } Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&configuration)?; launcher .launch(on_request(|request| { filter(request, config.custom_validator_role.evaluator()) })) .await?; Ok(()) } ``` In the above example, the custom `role` claim is defined by a DataWeave expression configured as an input parameter in the `gcl.yaml` schema definition as follows: ```yaml # [...] spec: extends: - name: extension-definition namespace: default properties: customValidatorRole: type: string format: dataweave default: "#[vars.claimSet.role == 'superRole']" # [...] required: - customValidatorRole ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Using JWT Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Flex Gateway Policy Development Kit (PDK)'s > JWT library, see > [JWT Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/jwt-validation/README.md). JSON Web Token (JWT) is a URL-secure method of representing claims to be transferred between two parties. The JWT token contains claims encoded in a JSON object as either the payload of a JSON Web Signature (JWS) or as a JSON web encryption (JWE) structure in plain text, which enables the claims to be digitally signed and protected with a message authentication code (MAC). Because the token is signed, you can trust the information and its source. PDK’s JWT library provides a set of tools to validate the JWT signatures and to extract and validate the claims of all incoming requests. ## Extract a JWT Token PDK provides a `TokenProvider` struct that has the `bearer` function to extract JWT tokens that have the format `Bearer ` in the authorization header. The following code demonstrates how to use the `bearer` function: ```Rust // [...] use pdk::jwt::*; // [...] async fn filter( state: RequestState, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; // [...] ``` If you are using a JWT token from a different source or with a different format, you can implement Rust logic to get any other part of the request. Use a DataWeave parameter to configure extraction to create a policy where you can dynamically change the JWT source. ## Validate a JWT Signature The JWT library provides a helper for performing signature validation of the incoming requests authorization tokens. Depending on the algorithm used by the policy, initialize a `SignatureValidator` with the corresponding configuration: ```Rust pub fn new(algorithm: SigningAlgorithm, key_length: SigningKeyLength, key: String) -> Result ``` PDK supports the following signing algorithms and key lengths:

Signing Algorithm

Signing Key Length

RSA

256, 384 and 512

HMAC

256, 384 and 512

ES

256 and 384

The `SigningAlgorithm` enum defines the available signing algorithms: ```Rust pub enum SigningAlgorithm { Rsa, Hmac, Es, } ``` The `SigningKeyLength` enum defines the available signing key lengths: ```Rust pub enum SigningKeyLength { Len256, Len384, Len512, } ``` A `SignatureValidator` instance implements the `SignatureValidation` trait. This `SignatureValidation` trait exposes a `validate` function that accepts tokens as `String` parameters and returns a `Result` that contains the parsed `JWTClaims` or a `JWTError` in the event of an error: ```Rust pub trait SignatureValidation { fn validate(&self, token: String) -> Result; } ``` The following code example shows how to initialize the `SignatureValidator` and validate an incoming token signed with a 256-byte HMAC algorithm: ```Rust use anyhow::Result; use pdk::hl::*; use pdk::jwt::*; // [...] async fn filter( state: RequestState, signature_validator: &SignatureValidator, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; if token.is_err() { return Flow::Break(Response::new(401).with_body("Bearer not found")); } // Validating signature let claims = signature_validator.validate(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } // [...] } #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&configuration)?; let signature_validator = SignatureValidator::new( model::SigningAlgorithm::Hmac, model::SigningKeyLength::Len256, config.secret.clone(), )?; launcher .launch(on_request(|request| { filter(request, &signature_validator) })) .await?; Ok(()) } ``` Because, the `SignatureValidator` confirms that the policy configurations are correct during initialization, initializing the `SignatureValidator` in the `#[entrypoint]` function throws an early error when the policy is applied rather than when the API receives a request. After initialization, the policy passes the `SignatureValidator` to the `on_request` wrapped function to perform `validate` method on incoming requests. ## Access Claims and Propagating to Headers After the [signature validation](#signature-validation) executes, the result contains the parsed JWT claims from the JWT token. In case the signature is invalid or you choose not to validate the signature, PDK provides the `JWTClaimsParser` to parse claims. This structure provides a `parse` method that returns `Result`. ```rust // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } ``` After you run the signature validation or the parsing method, use the following methods exposed by the `JWTClaims` struct to access the JWT claims: ```rust pub fn audience(&self) -> Option, JWTError>> pub fn not_before(&self) -> Option> pub fn expiration(&self) -> Option> pub fn issued_at(&self) -> Option> pub fn issuer(&self) -> Option pub fn jti(&self) -> Option pub fn nonce(&self) -> Option pub fn subject(&self) -> Option pub fn has_claim(&self, name: &str) -> bool pub fn get_claim(&self, name: &str) -> Option where T: ValueRetrieval, pub fn has_header(&self, name: &str) -> bool pub fn get_header(&self, name: &str) -> Option pub fn get_claims(&self) -> pdk_script::Value pub fn get_headers(&self) -> pdk_script::Value ``` The provided methods are designed to return each one of the standard JWT claims. The `get_claim` method can return any standard or custom claim. Because `get_claim` supports different target variable types, the user must specify the output type. `get_claim` supports `String`, `f64`, `Vec`, `chrono::DateTime`, and `serde_json::Value` output types. Because the claim might not exist in the token, you must wrap the type with an `Option`, for example: ```rust let some_custom_claim: Option = claims.get_claim("username"); ``` The following example shows how to parse a JWT token, get a custom claim, and propagate it to the request headers from a wrapped function: ```rust async fn filter( state: RequestState, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; if token.is_err() { return Flow::Break(Response::new(401).with_body("Bearer not found")); } // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } let claims = claims.unwrap(); let username: Option = claims.get_claim("username"); if let Some(custom_claim) = some_custom_claim { headers_state .handler() .set_header("username", custom_claim.as_str()); } Flow::Continue(()) } ``` ## Validate Claims JWT tokens typically contain a set of standard and non-standard claims that you can validate. Use the methods from [Access Claims and Propagating to Headers](#access-claims) to retrieve the claims present in the JWT tokens’s header or payload. Once retrieved, validate the value of the claims. The following code example validates that the JWT token: - Is not expired by validating the `exp` claim. - Has the correct audience value by validating the `aud` claim. - Has the correct custom `role` claim by using a custom validator configured as a DataWeave expression policy parameter. ```Rust use chrono::Utc; use pdk::hl::*; use pdk::jwt::*; use pdk::logger::info; use pdk::script::Evaluator; async fn filter( state: RequestState, mut custom_validator: Evaluator<'_>, ) -> Flow<()> { let headers_state = state.into_headers_state().await; let token = TokenProvider::bearer(headers_state.handler()); if token.is_err() { return Flow::Break(Response::new(400).with_body("Bearer not found")); } // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } let claims = claims.unwrap(); // Validating token expiration if let Some(exp) = claims.expiration() { if exp < Utc::now() { return Flow::Break(Response::new(400).with_body("token expired")); } } else { return Flow::Break(Response::new(400).with_body("token missing exp claim")); } // Validating audience if let Some(aud) = claims.audience() { if !aud_value.iter_mut().any(|a| a == "myAudience") { return Flow::Break(Response::new(400).with_body("token does not have the expected audience")); } } // Custom claim validation custom_validator.bind_vars("claimSet", claims.get_claims()); let result = custom_validator_role_claim.eval(); if !result.ok().and_then(|value| value.as_bool()).unwrap_or_default() { return Flow::Break(Response::new(400).with_body("custom token validations failed.")); } Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&configuration)?; launcher .launch(on_request(|request| { filter(request, config.custom_validator_role.evaluator()) })) .await?; Ok(()) } ``` In the above example, the custom `role` claim is defined by a DataWeave expression configured as an input parameter in the `gcl.yaml` schema definition as follows: ```yaml # [...] spec: extends: - name: extension-definition namespace: default properties: customValidatorRole: type: string format: dataweave default: "#[vars.claimSet.role == 'superRole']" # [...] required: - customValidatorRole ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Using JWT Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Flex Gateway Policy Development Kit (PDK)'s > JWT library, see > [JWT Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/jwt-validation/README.md). JSON Web Token (JWT) is a URL-secure method of representing claims to be transferred between two parties. The JWT token contains claims encoded in a JSON object as either the payload of a JSON Web Signature (JWS) or as a JSON web encryption (JWE) structure in plain text, which enables the claims to be digitally signed and protected with a message authentication code (MAC). Because the token is signed, you can trust the information and its source. PDK’s JWT library provides a set of tools to validate the JWT signatures and to extract and validate the claims of all incoming requests. ## Extract a JWT Token PDK provides a `TokenProvider` struct that has the `bearer` function to extract JWT tokens that have the format `Bearer ` in the authorization header. The following code demonstrates how to use the `bearer` function: ```Rust // [...] use pdk::jwt::*; // [...] async fn filter( state: RequestState, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; // [...] ``` If you are using a JWT token from a different source or with a different format, you can implement Rust logic to get any other part of the request. Use a DataWeave parameter to configure extraction to create a policy where you can dynamically change the JWT source. ## Validate a JWT Signature The JWT library provides a helper for performing signature validation of the incoming requests authorization tokens. Depending on the algorithm used by the policy, initialize a `SignatureValidator` with the corresponding configuration: ```Rust pub fn new(algorithm: SigningAlgorithm, key_length: SigningKeyLength, key: String) -> Result ``` PDK supports the following signing algorithms and key lengths:

Signing Algorithm

Signing Key Length

RSA

256, 384 and 512

HMAC

256, 384 and 512

ES

256 and 384

The `SigningAlgorithm` enum defines the available signing algorithms: ```Rust pub enum SigningAlgorithm { Rsa, Hmac, Es, } ``` The `SigningKeyLength` enum defines the available signing key lengths: ```Rust pub enum SigningKeyLength { Len256, Len384, Len512, } ``` A `SignatureValidator` instance implements the `SignatureValidation` trait. This `SignatureValidation` trait exposes a `validate` function that accepts tokens as `String` parameters and returns a `Result` that contains the parsed `JWTClaims` or a `JWTError` in the event of an error: ```Rust pub trait SignatureValidation { fn validate(&self, token: String) -> Result; } ``` The following code example shows how to initialize the `SignatureValidator` and validate an incoming token signed with a 256-byte HMAC algorithm: ```Rust use anyhow::Result; use pdk::hl::*; use pdk::jwt::*; // [...] async fn filter( state: RequestState, signature_validator: &SignatureValidator, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; if token.is_err() { return Flow::Break(Response::new(401).with_body("Bearer not found")); } // Validating signature let claims = signature_validator.validate(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } // [...] } #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&configuration)?; let signature_validator = SignatureValidator::new( model::SigningAlgorithm::Hmac, model::SigningKeyLength::Len256, config.secret.clone(), )?; launcher .launch(on_request(|request| { filter(request, &signature_validator) })) .await?; Ok(()) } ``` Because, the `SignatureValidator` confirms that the policy configurations are correct during initialization, initializing the `SignatureValidator` in the `#[entrypoint]` function throws an early error when the policy is applied rather than when the API receives a request. After initialization, the policy passes the `SignatureValidator` to the `on_request` wrapped function to perform `validate` method on incoming requests. ## Access Claims and Propagating to Headers After the [signature validation](#signature-validation) executes, the result contains the parsed JWT claims from the JWT token. In case the signature is invalid or you choose not to validate the signature, PDK provides the `JWTClaimsParser` to parse claims. This structure provides a `parse` method that returns `Result`. ```rust // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } ``` After you run the signature validation or the parsing method, use the following methods exposed by the `JWTClaims` struct to access the JWT claims: ```rust pub fn audience(&self) -> Option, JWTError>> pub fn not_before(&self) -> Option> pub fn expiration(&self) -> Option> pub fn issued_at(&self) -> Option> pub fn issuer(&self) -> Option pub fn jti(&self) -> Option pub fn nonce(&self) -> Option pub fn subject(&self) -> Option pub fn has_claim(&self, name: &str) -> bool pub fn get_claim(&self, name: &str) -> Option where T: ValueRetrieval, pub fn has_header(&self, name: &str) -> bool pub fn get_header(&self, name: &str) -> Option pub fn get_claims(&self) -> pdk_script::Value pub fn get_headers(&self) -> pdk_script::Value ``` The provided methods are designed to return each one of the standard JWT claims. The `get_claim` method can return any standard or custom claim. Because `get_claim` supports different target variable types, the user must specify the output type. `get_claim` supports `String`, `f64`, `Vec`, `chrono::DateTime`, and `serde_json::Value` output types. Because the claim might not exist in the token, you must wrap the type with an `Option`, for example: ```rust let some_custom_claim: Option = claims.get_claim("username"); ``` The following example shows how to parse a JWT token, get a custom claim, and propagate it to the request headers from a wrapped function: ```rust async fn filter( state: RequestState, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; if token.is_err() { return Flow::Break(Response::new(401).with_body("Bearer not found")); } // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } let claims = claims.unwrap(); let username: Option = claims.get_claim("username"); if let Some(custom_claim) = some_custom_claim { headers_state .handler() .set_header("username", custom_claim.as_str()); } Flow::Continue(()) } ``` ## Validate Claims JWT tokens typically contain a set of standard and non-standard claims that you can validate. Use the methods from [Access Claims and Propagating to Headers](#access-claims) to retrieve the claims present in the JWT tokens’s header or payload. Once retrieved, validate the value of the claims. The following code example validates that the JWT token: - Is not expired by validating the `exp` claim. - Has the correct audience value by validating the `aud` claim. - Has the correct custom `role` claim by using a custom validator configured as a DataWeave expression policy parameter. ```Rust use chrono::Utc; use pdk::hl::*; use pdk::jwt::*; use pdk::logger::info; use pdk::script::Evaluator; async fn filter( state: RequestState, mut custom_validator: Evaluator<'_>, ) -> Flow<()> { let headers_state = state.into_headers_state().await; let token = TokenProvider::bearer(headers_state.handler()); if token.is_err() { return Flow::Break(Response::new(400).with_body("Bearer not found")); } // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } let claims = claims.unwrap(); // Validating token expiration if let Some(exp) = claims.expiration() { if exp < Utc::now() { return Flow::Break(Response::new(400).with_body("token expired")); } } else { return Flow::Break(Response::new(400).with_body("token missing exp claim")); } // Validating audience if let Some(aud) = claims.audience() { if !aud_value.iter_mut().any(|a| a == "myAudience") { return Flow::Break(Response::new(400).with_body("token does not have the expected audience")); } } // Custom claim validation custom_validator.bind_vars("claimSet", claims.get_claims()); let result = custom_validator_role_claim.eval(); if !result.ok().and_then(|value| value.as_bool()).unwrap_or_default() { return Flow::Break(Response::new(400).with_body("custom token validations failed.")); } Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&configuration)?; launcher .launch(on_request(|request| { filter(request, config.custom_validator_role.evaluator()) })) .await?; Ok(()) } ``` In the above example, the custom `role` claim is defined by a DataWeave expression configured as an input parameter in the `gcl.yaml` schema definition as follows: ```yaml # [...] spec: extends: - name: extension-definition namespace: default properties: customValidatorRole: type: string format: dataweave default: "#[vars.claimSet.role == 'superRole']" # [...] required: - customValidatorRole ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Using JWT Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Flex Gateway Policy Development Kit (PDK)'s > JWT library, see > [JWT Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/jwt-validation/README.md). JSON Web Token (JWT) is a URL-secure method of representing claims to be transferred between two parties. The JWT token contains claims encoded in a JSON object as either the payload of a JSON Web Signature (JWS) or as a JSON web encryption (JWE) structure in plain text, which enables the claims to be digitally signed and protected with a message authentication code (MAC). Because the token is signed, you can trust the information and its source. PDK’s JWT library provides a set of tools to validate the JWT signatures and to extract and validate the claims of all incoming requests. ## Extract a JWT Token PDK provides a `TokenProvider` struct that has the `bearer` function to extract JWT tokens that have the format `Bearer ` in the authorization header. The following code demonstrates how to use the `bearer` function: ```Rust // [...] use pdk::jwt::*; // [...] async fn filter( state: RequestState, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; // [...] ``` If you are using a JWT token from a different source or with a different format, you can implement Rust logic to get any other part of the request. Use a DataWeave parameter to configure extraction to create a policy where you can dynamically change the JWT source. ## Validate a JWT Signature The JWT library provides a helper for performing signature validation of the incoming requests authorization tokens. Depending on the algorithm used by the policy, initialize a `SignatureValidator` with the corresponding configuration: ```Rust pub fn new(algorithm: SigningAlgorithm, key_length: SigningKeyLength, key: String) -> Result ``` PDK supports the following signing algorithms and key lengths:

Signing Algorithm

Signing Key Length

RSA

256, 384 and 512

HMAC

256, 384 and 512

ES

256 and 384

The `SigningAlgorithm` enum defines the available signing algorithms: ```Rust pub enum SigningAlgorithm { Rsa, Hmac, Es, } ``` The `SigningKeyLength` enum defines the available signing key lengths: ```Rust pub enum SigningKeyLength { Len256, Len384, Len512, } ``` A `SignatureValidator` instance implements the `SignatureValidation` trait. This `SignatureValidation` trait exposes a `validate` function that accepts tokens as `String` parameters and returns a `Result` that contains the parsed `JWTClaims` or a `JWTError` in the event of an error: ```Rust pub trait SignatureValidation { fn validate(&self, token: String) -> Result; } ``` The following code example shows how to initialize the `SignatureValidator` and validate an incoming token signed with a 256-byte HMAC algorithm: ```Rust use anyhow::Result; use pdk::hl::*; use pdk::jwt::*; // [...] async fn filter( state: RequestState, signature_validator: &SignatureValidator, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; if token.is_err() { return Flow::Break(Response::new(401).with_body("Bearer not found")); } // Validating signature let claims = signature_validator.validate(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } // [...] } #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&configuration)?; let signature_validator = SignatureValidator::new( model::SigningAlgorithm::Hmac, model::SigningKeyLength::Len256, config.secret.clone(), )?; launcher .launch(on_request(|request| { filter(request, &signature_validator) })) .await?; Ok(()) } ``` Because, the `SignatureValidator` confirms that the policy configurations are correct during initialization, initializing the `SignatureValidator` in the `#[entrypoint]` function throws an early error when the policy is applied rather than when the API receives a request. After initialization, the policy passes the `SignatureValidator` to the `on_request` wrapped function to perform `validate` method on incoming requests. ## Create a JWT Token > [!NOTE] For an example policy that generate JWT tokens, see > [JWT Generation Example Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/jwt-generation/README.md). The JWT library provides a helper for creating JWT tokens. Initialize the `JwtGenerator` with your signing algorithm configuration: ```Rust pub fn new( algorithm: SigningAlgorithm, length: SigningKeyLength, key: &str, ) -> Result ``` PDK supports these signing algorithms, key lengths, and PEM file formats. You must provide the `key` as a PEM file:
Signing AlgorithmSigning Key LengthPEM File Format

RSA

256, 384, and 512

pkcs#8

HMAC

256, 384, and 512

Plain text

ES

256 and 384

pkcs#8

The JWT generator exposes the `jwt` function to create tokens with the given headers and claims added to the JWT token: ```Rust pub fn jwt(&self, claims: JWTClaims) -> Result ``` ## Access Claims and Propagating to Headers After the [signature validation](#signature-validation) executes, the result contains the parsed JWT claims from the JWT token. In case the signature is invalid or you choose not to validate the signature, PDK provides the `JWTClaimsParser` to parse claims. This structure provides a `parse` method that returns `Result`. ```rust // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } ``` After you run the signature validation or the parsing method, use the following methods exposed by the `JWTClaims` struct to access the JWT claims: ```rust pub fn audience(&self) -> Option, JWTError>> pub fn not_before(&self) -> Option> pub fn expiration(&self) -> Option> pub fn issued_at(&self) -> Option> pub fn issuer(&self) -> Option pub fn jti(&self) -> Option pub fn nonce(&self) -> Option pub fn subject(&self) -> Option pub fn has_claim(&self, name: &str) -> bool pub fn get_claim(&self, name: &str) -> Option where T: ValueRetrieval, pub fn has_header(&self, name: &str) -> bool pub fn get_header(&self, name: &str) -> Option pub fn get_claims(&self) -> pdk_script::Value pub fn get_headers(&self) -> pdk_script::Value ``` The provided methods are designed to return each one of the standard JWT claims. The `get_claim` method can return any standard or custom claim. Because `get_claim` supports different target variable types, the user must specify the output type. `get_claim` supports `String`, `f64`, `Vec`, `chrono::DateTime`, and `serde_json::Value` output types. Because the claim might not exist in the token, you must wrap the type with an `Option`, for example: ```rust let some_custom_claim: Option = claims.get_claim("username"); ``` The following example shows how to parse a JWT token, get a custom claim, and propagate it to the request headers from a wrapped function: ```rust async fn filter( state: RequestState, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; if token.is_err() { return Flow::Break(Response::new(401).with_body("Bearer not found")); } // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } let claims = claims.unwrap(); let username: Option = claims.get_claim("username"); if let Some(custom_claim) = some_custom_claim { headers_state .handler() .set_header("username", custom_claim.as_str()); } Flow::Continue(()) } ``` ## Validate Claims JWT tokens typically contain a set of standard and non-standard claims that you can validate. Use the methods from [Access Claims and Propagating to Headers](#access-claims) to retrieve the claims present in the JWT tokens’s header or payload. Once retrieved, validate the value of the claims. The following code example validates that the JWT token: - Is not expired by validating the `exp` claim. - Has the correct audience value by validating the `aud` claim. - Has the correct custom `role` claim by using a custom validator configured as a DataWeave expression policy parameter. ```Rust use chrono::Utc; use pdk::hl::*; use pdk::jwt::*; use pdk::logger::info; use pdk::script::Evaluator; async fn filter( state: RequestState, mut custom_validator: Evaluator<'_>, ) -> Flow<()> { let headers_state = state.into_headers_state().await; let token = TokenProvider::bearer(headers_state.handler()); if token.is_err() { return Flow::Break(Response::new(400).with_body("Bearer not found")); } // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } let claims = claims.unwrap(); // Validating token expiration if let Some(exp) = claims.expiration() { if exp < Utc::now() { return Flow::Break(Response::new(400).with_body("token expired")); } } else { return Flow::Break(Response::new(400).with_body("token missing exp claim")); } // Validating audience if let Some(aud) = claims.audience() { if !aud_value.iter_mut().any(|a| a == "myAudience") { return Flow::Break(Response::new(400).with_body("token does not have the expected audience")); } } // Custom claim validation custom_validator.bind_vars("claimSet", claims.get_claims()); let result = custom_validator_role_claim.eval(); if !result.ok().and_then(|value| value.as_bool()).unwrap_or_default() { return Flow::Break(Response::new(400).with_body("custom token validations failed.")); } Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&configuration)?; launcher .launch(on_request(|request| { filter(request, config.custom_validator_role.evaluator()) })) .await?; Ok(()) } ``` In the above example, the custom `role` claim is defined by a DataWeave expression configured as an input parameter in the `gcl.yaml` schema definition as follows: ```yaml # [...] spec: extends: - name: extension-definition namespace: default properties: customValidatorRole: type: string format: dataweave default: "#[vars.claimSet.role == 'superRole']" # [...] required: - customValidatorRole ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Using JWT Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)'s > JWT library, see > [JWT Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/jwt-validation/README.md). JSON Web Token (JWT) is a URL-secure method of representing claims to be transferred between two parties. The JWT token contains claims encoded in a JSON object as either the payload of a JSON Web Signature (JWS) or as a JSON web encryption (JWE) structure in plain text, which enables the claims to be digitally signed and protected with a message authentication code (MAC). Because the token is signed, you can trust the information and its source. PDK’s JWT library provides a set of tools to validate the JWT signatures and to extract and validate the claims of all incoming requests. ## Extract a JWT Token PDK provides a `TokenProvider` struct that has the `bearer` function to extract JWT tokens that have the format `Bearer ` in the authorization header. The following code demonstrates how to use the `bearer` function: ```Rust // [...] use pdk::jwt::*; // [...] async fn filter( state: RequestState, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; // [...] ``` If you are using a JWT token from a different source or with a different format, you can implement Rust logic to get any other part of the request. Use a DataWeave parameter to configure extraction to create a policy where you can dynamically change the JWT source. ## Validate a JWT Signature The JWT library provides a helper for performing signature validation of the incoming requests authorization tokens. Depending on the algorithm used by the policy, initialize a `SignatureValidator` with the corresponding configuration: ```Rust pub fn new(algorithm: SigningAlgorithm, key_length: SigningKeyLength, key: String) -> Result ``` PDK supports the following signing algorithms and key lengths:

Signing Algorithm

Signing Key Length

RSA

256, 384 and 512

HMAC

256, 384 and 512

ES

256 and 384

The `SigningAlgorithm` enum defines the available signing algorithms: ```Rust pub enum SigningAlgorithm { Rsa, Hmac, Es, } ``` The `SigningKeyLength` enum defines the available signing key lengths: ```Rust pub enum SigningKeyLength { Len256, Len384, Len512, } ``` A `SignatureValidator` instance implements the `SignatureValidation` trait. This `SignatureValidation` trait exposes a `validate` function that accepts tokens as `String` parameters and returns a `Result` that contains the parsed `JWTClaims` or a `JWTError` in the event of an error: ```Rust pub trait SignatureValidation { fn validate(&self, token: String) -> Result; } ``` The following code example shows how to initialize the `SignatureValidator` and validate an incoming token signed with a 256-byte HMAC algorithm: ```Rust use anyhow::Result; use pdk::hl::*; use pdk::jwt::*; // [...] async fn filter( state: RequestState, signature_validator: &SignatureValidator, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; if token.is_err() { return Flow::Break(Response::new(401).with_body("Bearer not found")); } // Validating signature let claims = signature_validator.validate(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } // [...] } #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&configuration)?; let signature_validator = SignatureValidator::new( model::SigningAlgorithm::Hmac, model::SigningKeyLength::Len256, config.secret.clone(), )?; launcher .launch(on_request(|request| { filter(request, &signature_validator) })) .await?; Ok(()) } ``` Because, the `SignatureValidator` confirms that the policy configurations are correct during initialization, initializing the `SignatureValidator` in the `#[entrypoint]` function throws an early error when the policy is applied rather than when the API receives a request. After initialization, the policy passes the `SignatureValidator` to the `on_request` wrapped function to perform `validate` method on incoming requests. ## Create a JWT Token > [!NOTE] For an example policy that generate JWT tokens, see > [JWT Generation Example Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/jwt-generation/README.md). The JWT library provides a helper for creating JWT tokens. Initialize the `JwtGenerator` with your signing algorithm configuration: ```Rust pub fn new( algorithm: SigningAlgorithm, length: SigningKeyLength, key: &str, ) -> Result ``` PDK supports these signing algorithms, key lengths, and PEM file formats. You must provide the `key` as a PEM file:
Signing AlgorithmSigning Key LengthPEM File Format

RSA

256, 384, and 512

pkcs#8

HMAC

256, 384, and 512

Plain text

ES

256 and 384

pkcs#8

The JWT generator exposes the `jwt` function to create tokens with the given headers and claims added to the JWT token: ```Rust pub fn jwt(&self, claims: JWTClaims) -> Result ``` ## Access Claims and Propagating to Headers After the [signature validation](#signature-validation) executes, the result contains the parsed JWT claims from the JWT token. In case the signature is invalid or you choose not to validate the signature, PDK provides the `JWTClaimsParser` to parse claims. This structure provides a `parse` method that returns `Result`. ```rust // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } ``` After you run the signature validation or the parsing method, use the following methods exposed by the `JWTClaims` struct to access the JWT claims: ```rust pub fn audience(&self) -> Option, JWTError>> pub fn not_before(&self) -> Option> pub fn expiration(&self) -> Option> pub fn issued_at(&self) -> Option> pub fn issuer(&self) -> Option pub fn jti(&self) -> Option pub fn nonce(&self) -> Option pub fn subject(&self) -> Option pub fn has_claim(&self, name: &str) -> bool pub fn get_claim(&self, name: &str) -> Option where T: ValueRetrieval, pub fn has_header(&self, name: &str) -> bool pub fn get_header(&self, name: &str) -> Option pub fn get_claims(&self) -> pdk_script::Value pub fn get_headers(&self) -> pdk_script::Value ``` The provided methods are designed to return each one of the standard JWT claims. The `get_claim` method can return any standard or custom claim. Because `get_claim` supports different target variable types, the user must specify the output type. `get_claim` supports `String`, `f64`, `Vec`, `chrono::DateTime`, and `serde_json::Value` output types. Because the claim might not exist in the token, you must wrap the type with an `Option`, for example: ```rust let some_custom_claim: Option = claims.get_claim("username"); ``` The following example shows how to parse a JWT token, get a custom claim, and propagate it to the request headers from a wrapped function: ```rust async fn filter( state: RequestState, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; if token.is_err() { return Flow::Break(Response::new(401).with_body("Bearer not found")); } // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } let claims = claims.unwrap(); let username: Option = claims.get_claim("username"); if let Some(custom_claim) = some_custom_claim { headers_state .handler() .set_header("username", custom_claim.as_str()); } Flow::Continue(()) } ``` ## Validate Claims JWT tokens typically contain a set of standard and non-standard claims that you can validate. Use the methods from [Access Claims and Propagating to Headers](#access-claims) to retrieve the claims present in the JWT tokens’s header or payload. Once retrieved, validate the value of the claims. The following code example validates that the JWT token: - Is not expired by validating the `exp` claim. - Has the correct audience value by validating the `aud` claim. - Has the correct custom `role` claim by using a custom validator configured as a DataWeave expression policy parameter. ```Rust use chrono::Utc; use pdk::hl::*; use pdk::jwt::*; use pdk::logger::info; use pdk::script::Evaluator; async fn filter( state: RequestState, mut custom_validator: Evaluator<'_>, ) -> Flow<()> { let headers_state = state.into_headers_state().await; let token = TokenProvider::bearer(headers_state.handler()); if token.is_err() { return Flow::Break(Response::new(400).with_body("Bearer not found")); } // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } let claims = claims.unwrap(); // Validating token expiration if let Some(exp) = claims.expiration() { if exp < Utc::now() { return Flow::Break(Response::new(400).with_body("token expired")); } } else { return Flow::Break(Response::new(400).with_body("token missing exp claim")); } // Validating audience if let Some(aud) = claims.audience() { if !aud_value.iter_mut().any(|a| a == "myAudience") { return Flow::Break(Response::new(400).with_body("token does not have the expected audience")); } } // Custom claim validation custom_validator.bind_vars("claimSet", claims.get_claims()); let result = custom_validator_role_claim.eval(); if !result.ok().and_then(|value| value.as_bool()).unwrap_or_default() { return Flow::Break(Response::new(400).with_body("custom token validations failed.")); } Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&configuration)?; launcher .launch(on_request(|request| { filter(request, config.custom_validator_role.evaluator()) })) .await?; Ok(()) } ``` In the above example, the custom `role` claim is defined by a DataWeave expression configured as an input parameter in the `gcl.yaml` schema definition as follows: ```yaml # [...] spec: extends: - name: extension-definition namespace: default properties: customValidatorRole: type: string format: dataweave default: "#[vars.claimSet.role == 'superRole']" # [...] required: - customValidatorRole ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Using JWT Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)'s > JWT library, see > [JWT Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/jwt-validation/README.md). JSON Web Token (JWT) is a URL-secure method of representing claims to be transferred between two parties. The JWT token contains claims encoded in a JSON object as either the payload of a JSON Web Signature (JWS) or as a JSON web encryption (JWE) structure in plain text, which enables the claims to be digitally signed and protected with a message authentication code (MAC). Because the token is signed, you can trust the information and its source. PDK’s JWT library provides a set of tools to validate the JWT signatures and to extract and validate the claims of all incoming requests. > [!NOTE] The JWT library is gated behind a Cargo feature and is enabled by default. To disable JWT > features for your policy, see > [Configure PDK Features in Cargo.toml](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-project#configure-pdk-features). ## FIPS-Compliant JWT PDK provides the `jwt-fips` feature for FIPS-compliant JWT support. This feature delegates cryptography to the proxy-wasm host instead of bundling native RustCrypto. Because it’s mutually exclusive with the default `jwt` backend, you must disable `default-features` when using it. To enable FIPS-compliant JWT in your `Cargo.toml`: ```toml # FIPS-compliant JWT only: pdk = { version = "1.9.1", default-features = false, features = ["jwt-fips"] } # FIPS-compliant JWT with XML Validator: pdk = { version = "1.9.1", default-features = false, features = ["jwt-fips", "xml_validator"] } ``` ## Extract a JWT Token PDK provides a `TokenProvider` struct that has the `bearer` function to extract JWT tokens that have the format `Bearer ` in the authorization header. The following code demonstrates how to use the `bearer` function: ```Rust // [...] use pdk::jwt::*; // [...] async fn filter( state: RequestState, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; // [...] ``` If you are using a JWT token from a different source or with a different format, you can implement Rust logic to get any other part of the request. Use a DataWeave parameter to configure extraction to create a policy where you can dynamically change the JWT source. ## Validate a JWT Signature The JWT library provides a helper for performing signature validation of the incoming requests authorization tokens. Depending on the algorithm used by the policy, initialize a `SignatureValidator` with the corresponding configuration: ```Rust pub fn new(algorithm: SigningAlgorithm, key_length: SigningKeyLength, key: String) -> Result ``` PDK supports the following signing algorithms and key lengths:

Signing Algorithm

Signing Key Length

RSA

256, 384 and 512

HMAC

256, 384 and 512

ES

256 and 384

The `SigningAlgorithm` enum defines the available signing algorithms: ```Rust pub enum SigningAlgorithm { Rsa, Hmac, Es, } ``` The `SigningKeyLength` enum defines the available signing key lengths: ```Rust pub enum SigningKeyLength { Len256, Len384, Len512, } ``` A `SignatureValidator` instance implements the `SignatureValidation` trait. This `SignatureValidation` trait exposes a `validate` function that accepts tokens as `String` parameters and returns a `Result` that contains the parsed `JWTClaims` or a `JWTError` in the event of an error: ```Rust pub trait SignatureValidation { fn validate(&self, token: String) -> Result; } ``` The following code example shows how to initialize the `SignatureValidator` and validate an incoming token signed with a 256-byte HMAC algorithm: ```Rust use anyhow::Result; use pdk::hl::*; use pdk::jwt::*; // [...] async fn filter( state: RequestState, signature_validator: &SignatureValidator, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; if token.is_err() { return Flow::Break(Response::new(401).with_body("Bearer not found")); } // Validating signature let claims = signature_validator.validate(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } // [...] } #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&configuration)?; let signature_validator = SignatureValidator::new( model::SigningAlgorithm::Hmac, model::SigningKeyLength::Len256, config.secret.clone(), )?; launcher .launch(on_request(|request| { filter(request, &signature_validator) })) .await?; Ok(()) } ``` Because, the `SignatureValidator` confirms that the policy configurations are correct during initialization, initializing the `SignatureValidator` in the `#[entrypoint]` function throws an early error when the policy is applied rather than when the API receives a request. After initialization, the policy passes the `SignatureValidator` to the `on_request` wrapped function to perform `validate` method on incoming requests. ## Create a JWT Token > [!NOTE] For an example policy that generate JWT tokens, see > [JWT Generation Example Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/jwt-generation/README.md). The JWT library provides a helper for creating JWT tokens. Initialize the `JwtGenerator` with your signing algorithm configuration: ```Rust pub fn new( algorithm: SigningAlgorithm, length: SigningKeyLength, key: &str, ) -> Result ``` PDK supports these signing algorithms, key lengths, and PEM file formats. You must provide the `key` as a PEM file:
Signing AlgorithmSigning Key LengthPEM File Format

RSA

256, 384, and 512

pkcs#8

HMAC

256, 384, and 512

Plain text

ES

256 and 384

pkcs#8

The JWT generator exposes the `jwt` function to create tokens with the given headers and claims added to the JWT token: ```Rust pub fn jwt(&self, claims: JWTClaims) -> Result ``` ## Access Claims and Propagating to Headers After the [signature validation](#signature-validation) executes, the result contains the parsed JWT claims from the JWT token. In case the signature is invalid or you choose not to validate the signature, PDK provides the `JWTClaimsParser` to parse claims. This structure provides a `parse` method that returns `Result`. ```rust // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } ``` After you run the signature validation or the parsing method, use the following methods exposed by the `JWTClaims` struct to access the JWT claims: ```rust pub fn audience(&self) -> Option, JWTError>> pub fn not_before(&self) -> Option> pub fn expiration(&self) -> Option> pub fn issued_at(&self) -> Option> pub fn issuer(&self) -> Option pub fn jti(&self) -> Option pub fn nonce(&self) -> Option pub fn subject(&self) -> Option pub fn has_claim(&self, name: &str) -> bool pub fn get_claim(&self, name: &str) -> Option where T: ValueRetrieval, pub fn has_header(&self, name: &str) -> bool pub fn get_header(&self, name: &str) -> Option pub fn get_claims(&self) -> pdk_script::Value pub fn get_headers(&self) -> pdk_script::Value ``` The provided methods are designed to return each one of the standard JWT claims. The `get_claim` method can return any standard or custom claim. Because `get_claim` supports different target variable types, the user must specify the output type. `get_claim` supports `String`, `f64`, `Vec`, `chrono::DateTime`, and `serde_json::Value` output types. Because the claim might not exist in the token, you must wrap the type with an `Option`, for example: ```rust let some_custom_claim: Option = claims.get_claim("username"); ``` The following example shows how to parse a JWT token, get a custom claim, and propagate it to the request headers from a wrapped function: ```rust async fn filter( state: RequestState, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; if token.is_err() { return Flow::Break(Response::new(401).with_body("Bearer not found")); } // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } let claims = claims.unwrap(); let username: Option = claims.get_claim("username"); if let Some(custom_claim) = some_custom_claim { headers_state .handler() .set_header("username", custom_claim.as_str()); } Flow::Continue(()) } ``` ## Validate Claims JWT tokens typically contain a set of standard and non-standard claims that you can validate. Use the methods from [Access Claims and Propagating to Headers](#access-claims) to retrieve the claims present in the JWT tokens’s header or payload. Once retrieved, validate the value of the claims. The following code example validates that the JWT token: - Is not expired by validating the `exp` claim. - Has the correct audience value by validating the `aud` claim. - Has the correct custom `role` claim by using a custom validator configured as a DataWeave expression policy parameter. ```Rust use chrono::Utc; use pdk::hl::*; use pdk::jwt::*; use pdk::logger::info; use pdk::script::Evaluator; async fn filter( state: RequestState, mut custom_validator: Evaluator<'_>, ) -> Flow<()> { let headers_state = state.into_headers_state().await; let token = TokenProvider::bearer(headers_state.handler()); if token.is_err() { return Flow::Break(Response::new(400).with_body("Bearer not found")); } // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } let claims = claims.unwrap(); // Validating token expiration if let Some(exp) = claims.expiration() { if exp < Utc::now() { return Flow::Break(Response::new(400).with_body("token expired")); } } else { return Flow::Break(Response::new(400).with_body("token missing exp claim")); } // Validating audience if let Some(aud) = claims.audience() { if !aud_value.iter_mut().any(|a| a == "myAudience") { return Flow::Break(Response::new(400).with_body("token does not have the expected audience")); } } // Custom claim validation custom_validator.bind_vars("claimSet", claims.get_claims()); let result = custom_validator_role_claim.eval(); if !result.ok().and_then(|value| value.as_bool()).unwrap_or_default() { return Flow::Break(Response::new(400).with_body("custom token validations failed.")); } Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&configuration)?; launcher .launch(on_request(|request| { filter(request, config.custom_validator_role.evaluator()) })) .await?; Ok(()) } ``` In the above example, the custom `role` claim is defined by a DataWeave expression configured as an input parameter in the `gcl.yaml` schema definition as follows: ```yaml # [...] spec: extends: - name: extension-definition namespace: default properties: customValidatorRole: type: string format: dataweave default: "#[vars.claimSet.role == 'superRole']" # [...] required: - customValidatorRole ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Using JWT Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)'s > JWT library, see > [JWT Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/jwt-validation/README.md). JSON Web Token (JWT) is a URL-secure method of representing claims to be transferred between two parties. The JWT token contains claims encoded in a JSON object as either the payload of a JSON Web Signature (JWS) or as a JSON web encryption (JWE) structure in plain text, which enables the claims to be digitally signed and protected with a message authentication code (MAC). Because the token is signed, you can trust the information and its source. PDK’s JWT library provides a set of tools to validate the JWT signatures and to extract and validate the claims of all incoming requests. > [!NOTE] The JWT library is gated behind a Cargo feature and is enabled by default. To disable JWT > features for your policy, see > [Configure PDK Features in Cargo.toml](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-project#configure-pdk-features). ## FIPS-Compliant JWT PDK provides the `jwt-fips` feature for FIPS-compliant JWT support. This feature delegates cryptography to the proxy-wasm host instead of bundling native RustCrypto. Because it’s mutually exclusive with the default `jwt` backend, you must disable `default-features` when using it. To enable FIPS-compliant JWT in your `Cargo.toml`: ```toml # FIPS-compliant JWT only: pdk = { version = "1.10.0", default-features = false, features = ["jwt-fips"] } # FIPS-compliant JWT with XML Validator: pdk = { version = "1.10.0", default-features = false, features = ["jwt-fips", "xml_validator"] } ``` ## Extract a JWT Token PDK provides a `TokenProvider` struct that has the `bearer` function to extract JWT tokens that have the format `Bearer ` in the authorization header. The following code demonstrates how to use the `bearer` function: ```Rust // [...] use pdk::jwt::*; // [...] async fn filter( state: RequestState, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; // [...] ``` If you are using a JWT token from a different source or with a different format, you can implement Rust logic to get any other part of the request. Use a DataWeave parameter to configure extraction to create a policy where you can dynamically change the JWT source. ## Validate a JWT Signature The JWT library provides a helper for performing signature validation of the incoming requests authorization tokens. Depending on the algorithm used by the policy, initialize a `SignatureValidator` with the corresponding configuration: ```Rust pub fn new(algorithm: SigningAlgorithm, key_length: SigningKeyLength, key: String) -> Result ``` PDK supports the following signing algorithms and key lengths:

Signing Algorithm

Signing Key Length

RSA

256, 384 and 512

HMAC

256, 384 and 512

ES

256 and 384

The `SigningAlgorithm` enum defines the available signing algorithms: ```Rust pub enum SigningAlgorithm { Rsa, Hmac, Es, } ``` The `SigningKeyLength` enum defines the available signing key lengths: ```Rust pub enum SigningKeyLength { Len256, Len384, Len512, } ``` A `SignatureValidator` instance implements the `SignatureValidation` trait. This `SignatureValidation` trait exposes a `validate` function that accepts tokens as `String` parameters and returns a `Result` that contains the parsed `JWTClaims` or a `JWTError` in the event of an error: ```Rust pub trait SignatureValidation { fn validate(&self, token: String) -> Result; } ``` The following code example shows how to initialize the `SignatureValidator` and validate an incoming token signed with a 256-byte HMAC algorithm: ```Rust use anyhow::Result; use pdk::hl::*; use pdk::jwt::*; // [...] async fn filter( state: RequestState, signature_validator: &SignatureValidator, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; if token.is_err() { return Flow::Break(Response::new(401).with_body("Bearer not found")); } // Validating signature let claims = signature_validator.validate(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } // [...] } #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&configuration)?; let signature_validator = SignatureValidator::new( model::SigningAlgorithm::Hmac, model::SigningKeyLength::Len256, config.secret.clone(), )?; launcher .launch(on_request(|request| { filter(request, &signature_validator) })) .await?; Ok(()) } ``` Because, the `SignatureValidator` confirms that the policy configurations are correct during initialization, initializing the `SignatureValidator` in the `#[entrypoint]` function throws an early error when the policy is applied rather than when the API receives a request. After initialization, the policy passes the `SignatureValidator` to the `on_request` wrapped function to perform `validate` method on incoming requests. ## Create a JWT Token > [!NOTE] For an example policy that generate JWT tokens, see > [JWT Generation Example Policy](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/jwt-generation/README.md). The JWT library provides a helper for creating JWT tokens. Initialize the `JwtGenerator` with your signing algorithm configuration: ```Rust pub fn new( algorithm: SigningAlgorithm, length: SigningKeyLength, key: &str, ) -> Result ``` PDK supports these signing algorithms, key lengths, and PEM file formats. You must provide the `key` as a PEM file:
Signing AlgorithmSigning Key LengthPEM File Format

RSA

256, 384, and 512

pkcs#8

HMAC

256, 384, and 512

Plain text

ES

256 and 384

pkcs#8

The JWT generator exposes the `jwt` function to create tokens with the given headers and claims added to the JWT token: ```Rust pub fn jwt(&self, claims: JWTClaims) -> Result ``` ## Access Claims and Propagating to Headers After the [signature validation](#signature-validation) executes, the result contains the parsed JWT claims from the JWT token. In case the signature is invalid or you choose not to validate the signature, PDK provides the `JWTClaimsParser` to parse claims. This structure provides a `parse` method that returns `Result`. ```rust // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } ``` After you run the signature validation or the parsing method, use the following methods exposed by the `JWTClaims` struct to access the JWT claims: ```rust pub fn audience(&self) -> Option, JWTError>> pub fn not_before(&self) -> Option> pub fn expiration(&self) -> Option> pub fn issued_at(&self) -> Option> pub fn issuer(&self) -> Option pub fn jti(&self) -> Option pub fn nonce(&self) -> Option pub fn subject(&self) -> Option pub fn has_claim(&self, name: &str) -> bool pub fn get_claim(&self, name: &str) -> Option where T: ValueRetrieval, pub fn has_header(&self, name: &str) -> bool pub fn get_header(&self, name: &str) -> Option pub fn get_claims(&self) -> pdk_script::Value pub fn get_headers(&self) -> pdk_script::Value ``` The provided methods are designed to return each one of the standard JWT claims. The `get_claim` method can return any standard or custom claim. Because `get_claim` supports different target variable types, the user must specify the output type. `get_claim` supports `String`, `f64`, `Vec`, `chrono::DateTime`, and `serde_json::Value` output types. Because the claim might not exist in the token, you must wrap the type with an `Option`, for example: ```rust let some_custom_claim: Option = claims.get_claim("username"); ``` The following example shows how to parse a JWT token, get a custom claim, and propagate it to the request headers from a wrapped function: ```rust async fn filter( state: RequestState, ) -> Flow<()> { let headers_state = state.into_headers_state().await; // Extract token let token = TokenProvider::bearer(headers_state.handler())?; if token.is_err() { return Flow::Break(Response::new(401).with_body("Bearer not found")); } // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } let claims = claims.unwrap(); let username: Option = claims.get_claim("username"); if let Some(custom_claim) = some_custom_claim { headers_state .handler() .set_header("username", custom_claim.as_str()); } Flow::Continue(()) } ``` ## Validate Claims JWT tokens typically contain a set of standard and non-standard claims that you can validate. Use the methods from [Access Claims and Propagating to Headers](#access-claims) to retrieve the claims present in the JWT tokens’s header or payload. Once retrieved, validate the value of the claims. The following code example validates that the JWT token: - Is not expired by validating the `exp` claim. - Has the correct audience value by validating the `aud` claim. - Has the correct custom `role` claim by using a custom validator configured as a DataWeave expression policy parameter. ```Rust use chrono::Utc; use pdk::hl::*; use pdk::jwt::*; use pdk::logger::info; use pdk::script::Evaluator; async fn filter( state: RequestState, mut custom_validator: Evaluator<'_>, ) -> Flow<()> { let headers_state = state.into_headers_state().await; let token = TokenProvider::bearer(headers_state.handler()); if token.is_err() { return Flow::Break(Response::new(400).with_body("Bearer not found")); } // Being "token" a String that contains a JWT token let parsed_claims = JWTClaimsParser::parse(token.unwrap()); if claims.is_err() { return Flow::Break(Response::new(401).with_body("Invalid token")); } let claims = claims.unwrap(); // Validating token expiration if let Some(exp) = claims.expiration() { if exp < Utc::now() { return Flow::Break(Response::new(400).with_body("token expired")); } } else { return Flow::Break(Response::new(400).with_body("token missing exp claim")); } // Validating audience if let Some(aud) = claims.audience() { if !aud_value.iter_mut().any(|a| a == "myAudience") { return Flow::Break(Response::new(400).with_body("token does not have the expected audience")); } } // Custom claim validation custom_validator.bind_vars("claimSet", claims.get_claims()); let result = custom_validator_role_claim.eval(); if !result.ok().and_then(|value| value.as_bool()).unwrap_or_default() { return Flow::Break(Response::new(400).with_body("custom token validations failed.")); } Flow::Continue(()) } #[entrypoint] async fn configure(launcher: Launcher, Configuration(configuration): Configuration) -> Result<()> { let config: Config = serde_json::from_slice(&configuration)?; launcher .launch(on_request(|request| { filter(request, config.custom_validator_role.evaluator()) })) .await?; Ok(()) } ``` In the above example, the custom `role` claim is defined by a DataWeave expression configured as an input parameter in the `gcl.yaml` schema definition as follows: ```yaml # [...] spec: extends: - name: extension-definition namespace: default properties: customValidatorRole: type: string format: dataweave default: "#[vars.claimSet.role == 'superRole']" # [...] required: - customValidatorRole ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Using OAuth 2.0 Token Introspection Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Flex Gateway Policy Development Kit (PDK)'s > Token Introspection feature, see > [OAuth 2.0 Token Introspection Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/oauth-2-token-introspection/README.md). Use the Flex Gateway Policy Development Kit (PDK) Token Introspection library functions to validate incoming OAuth 2.0 tokens with an upstream introspection service. ## Configure the Token Validator To access OAuth 2.0 Token Introspection functionality, you must import the `token_introspection` module from the PDK crate and inject the `TokenValidatorBuilder` in the [configure](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features#policy-template) function. ```Rust use pdk::token_introspection::{IntrospectionResult, ParsedToken, ScopesValidator, TokenValidator, TokenValidatorBuilder}; #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, validator_builder: TokenValidatorBuilder, ) -> Result<()> { // [...] // Create a token validator let mut validator_instance = validator_builder .new("token-cache") .with_path("/introspect") .with_authorization_value("Basic YWRtaW46YWRtaW4=") .with_expires_in_attribute("exp") .with_max_token_ttl(600) .with_timeout_ms(10000) .with_max_cache_entries(10000) .with_scopes_validator(ScopesValidator::all(scopes_vector)) .with_service(config.my_service) .build(); // [...] } ``` The `TokenValidatorBuilder` provides these methods to configure the token validator. You must call `with_service` before `build`, all other methods are optional:
MethodParameterDefaultDescription

with_path

path (impl Into<String>)

"/"

Sets the introspection endpoint path.

with_authorization_value

value (impl Into<String>)

"" (sends an Auth header with an empty value)

Sets the authorization header value for introspection requests.

with_expires_in_attribute

attr (impl Into<String>)

"exp"

Sets the attribute name for expiration time in the introspection response.

with_max_token_ttl

ttl (i64)

-1 (no cap)

Sets the maximum token TTL in seconds; tokens with a longer TTL are treated as expired. Use -1 for no limit.

with_timeout_ms

timeout (u64)

10000 (10 s)

Sets the timeout for introspection requests in milliseconds.

with_max_cache_entries

max_entries (usize)

1000

Sets the maximum number of entries in the token cache.

with_scopes_validator

validator (ScopesValidator)

—

Sets the scopes validator for token validation (for example, ScopesValidator::all(scopes_vector)).

with_service

service (Service)

Required

Sets the OAuth2 introspection service endpoint. Required to build the validator.

> [!NOTE] The configure function receives the > [configuration parameters](https://docs.mulesoft.com/pdk/1.7/policies-pdk-create-schema-definition) defined in your policy schema. ## Validate a Token Once configured, the validator provides the `validate` function, that expects a token string. The validate function sends a request to the introspection endpoint and returns the `IntrospectionResult`: ```Rust // extract token from header let auth_header = handler.header("Authorization"); let token = auth_header.split_whitespace()[1]; let result = validator .validate(&token) .await .map_err(PolicyError::Introspection)?; ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Using OAuth 2.0 Token Introspection Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)'s > Token Introspection feature, see > [OAuth 2.0 Token Introspection Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/oauth-2-token-introspection/README.md). Use the Omni Gateway Policy Development Kit (PDK) Token Introspection library functions to validate incoming OAuth 2.0 tokens with an upstream introspection service. ## Configure the Token Validator To access OAuth 2.0 Token Introspection functionality, you must import the `token_introspection` module from the PDK crate and inject the `TokenValidatorBuilder` in the [configure](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features#policy-template) function. ```Rust use pdk::token_introspection::{IntrospectionResult, ParsedToken, ScopesValidator, TokenValidator, TokenValidatorBuilder}; #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, validator_builder: TokenValidatorBuilder, ) -> Result<()> { // [...] // Create a token validator let mut validator_instance = validator_builder .new("token-cache") .with_path("/introspect") .with_authorization_value("Basic YWRtaW46YWRtaW4=") // Choose either authorization value or client ID and secret depending on your service authorization. No authorization header is sent if with_authorization_value() isn't defined. .with_client_id("client-id") // Client ID and secret are sent as form params in the body of the request .with_client_secret("client-secret") .with_expires_in_attribute("exp") .with_max_token_ttl(600) .with_timeout_ms(10000) .with_max_cache_entries(10000) .with_scopes_validator(ScopesValidator::all(scopes_vector)) .with_service(config.my_service) .with_protected_resource_metadata(config.auth_server_url) // Choose .with_protected_resource_metadata_with_properties() if additional properties are required .build(); // [...] } ``` The `TokenValidatorBuilder` provides these methods to configure the token validator. You must call `with_service` before `build`, all other methods are optional:
MethodParameterDefaultDescription

with_path

path (impl Into<String>)

"/"

Sets the introspection endpoint path.

with_authorization_value

value (impl Into<String>)

"" (Auth header with an empty value)

Sets the authorization header value for introspection requests.

with_client_id

value (impl Into<String>)

No default

Sets the client ID credential to talk with the introspection service.

with_client_secret

value (impl Into<String>)

No default

Sets the client secret credential to talk with the introspection service.

with_expires_in_attribute

attr (impl Into<String>)

"exp"

Sets the attribute name for expiration time in the introspection response.

with_max_token_ttl

ttl (i64)

-1 (no cap)

Sets the maximum token TTL in seconds; tokens with a longer TTL are treated as expired. Use -1 for no limit.

with_timeout_ms

timeout (u64)

10000 (10 s)

Sets the timeout for introspection requests in milliseconds.

with_max_cache_entries

max_entries (usize)

1000

Sets the maximum number of entries in the token cache.

with_scopes_validator

validator (ScopesValidator)

No default

Sets the scopes validator for token validation (for example, ScopesValidator::all(scopes_vector)).

with_service

service (Service)

No default (required)

Sets the OAuth2 introspection service endpoint. Required to build the validator.

with_protected_resource_metadata

authorization server url (impl Into<String>)

No default

Enables RFC 9728 protected resource discovery with the given authorization server URL. The well-known endpoint path and resource URL are derived automatically from the API base path extracted from PDK metadata when the policy is applied.

with_protected_resource_metadata_with_properties

authorization server url (impl Into<String>), additional properties (Value)

No default

Enables RFC 9728 protected resource discovery with the given authorization server URL and additional metadata properties (such as scopes_supported or bearer_methods_supported). The well-known endpoint path and resource URL are derived automatically from the API base path extracted from PDK metadata when the policy is applied.

> [!NOTE] The configure function receives the > [configuration parameters](https://docs.mulesoft.com/pdk/1.8/policies-pdk-create-schema-definition) defined in your policy schema. ## Validate a Token Once configured, the validator provides the `validate` function, that expects a token string. The validate function sends a request to the introspection endpoint and returns the `IntrospectionResult`: ```Rust // extract token from header let auth_header = handler.header("Authorization"); let token = auth_header.split_whitespace()[1]; let result = validator .validate(&token) .await .map_err(PolicyError::Introspection)?; ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Using OAuth 2.0 Token Introspection Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)'s > Token Introspection feature, see > [OAuth 2.0 Token Introspection Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/oauth-2-token-introspection/README.md). Use the Omni Gateway Policy Development Kit (PDK) Token Introspection library functions to validate incoming OAuth 2.0 tokens with an upstream introspection service. ## Configure the Token Validator To access OAuth 2.0 Token Introspection functionality, you must import the `token_introspection` module from the PDK crate and inject the `TokenValidatorBuilder` in the [configure](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features#policy-template) function. ```Rust use pdk::token_introspection::{IntrospectionResult, ParsedToken, ScopesValidator, TokenValidator, TokenValidatorBuilder}; #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, validator_builder: TokenValidatorBuilder, ) -> Result<()> { // [...] // Create a token validator let mut validator_instance = validator_builder .new("token-cache") .with_path("/introspect") .with_authorization_value("Basic YWRtaW46YWRtaW4=") // Choose either authorization value or client ID and secret depending on your service authorization. No authorization header is sent if with_authorization_value() isn't defined. .with_client_id("client-id") // Client ID and secret are sent as form params in the body of the request .with_client_secret("client-secret") .with_expires_in_attribute("exp") .with_max_token_ttl(600) .with_timeout_ms(10000) .with_max_cache_entries(10000) .with_scopes_validator(ScopesValidator::all(scopes_vector)) .with_service(config.my_service) .with_protected_resource_metadata(config.auth_server_url) // Choose .with_protected_resource_metadata_with_properties() if additional properties are required .build(); // [...] } ``` The `TokenValidatorBuilder` provides these methods to configure the token validator. You must call `with_service` before `build`, all other methods are optional:
MethodParameterDefaultDescription

with_path

path (impl Into<String>)

"/"

Sets the introspection endpoint path.

with_authorization_value

value (impl Into<String>)

"" (Auth header with an empty value)

Sets the authorization header value for introspection requests.

with_client_id

value (impl Into<String>)

No default

Sets the client ID credential to talk with the introspection service.

with_client_secret

value (impl Into<String>)

No default

Sets the client secret credential to talk with the introspection service.

with_expires_in_attribute

attr (impl Into<String>)

"exp"

Sets the attribute name for expiration time in the introspection response.

with_max_token_ttl

ttl (i64)

-1 (no cap)

Sets the maximum token TTL in seconds; tokens with a longer TTL are treated as expired. Use -1 for no limit.

with_timeout_ms

timeout (u64)

10000 (10 s)

Sets the timeout for introspection requests in milliseconds.

with_max_cache_entries

max_entries (usize)

1000

Sets the maximum number of entries in the token cache.

with_scopes_validator

validator (ScopesValidator)

No default

Sets the scopes validator for token validation (for example, ScopesValidator::all(scopes_vector)).

with_service

service (Service)

No default (required)

Sets the OAuth2 introspection service endpoint. Required to build the validator.

with_protected_resource_metadata

authorization server url (impl Into<String>)

No default

Enables RFC 9728 protected resource discovery with the given authorization server URL. The well-known endpoint path and resource URL are derived automatically from the API base path extracted from PDK metadata when the policy is applied.

with_protected_resource_metadata_with_properties

authorization server url (impl Into<String>), additional properties (Value)

No default

Enables RFC 9728 protected resource discovery with the given authorization server URL and additional metadata properties (such as scopes_supported or bearer_methods_supported). The well-known endpoint path and resource URL are derived automatically from the API base path extracted from PDK metadata when the policy is applied.

> [!NOTE] The configure function receives the > [configuration parameters](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-schema-definition) defined in your policy schema. ## Validate a Token Once configured, the validator provides the `validate` function, that expects a token string. The validate function sends a request to the introspection endpoint and returns the `IntrospectionResult`: ```Rust // extract token from header let auth_header = handler.header("Authorization"); let token = auth_header.split_whitespace()[1]; let result = validator .validate(&token) .await .map_err(PolicyError::Introspection)?; ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Using OAuth 2.0 Token Introspection Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)'s > Token Introspection feature, see > [OAuth 2.0 Token Introspection Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/oauth-2-token-introspection/README.md). Use the Omni Gateway Policy Development Kit (PDK) Token Introspection library functions to validate incoming OAuth 2.0 tokens with an upstream introspection service. ## Configure the Token Validator To access OAuth 2.0 Token Introspection functionality, you must import the `token_introspection` module from the PDK crate and inject the `TokenValidatorBuilder` in the [configure](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features#policy-template) function. ```Rust use pdk::token_introspection::{IntrospectionResult, ParsedToken, ScopesValidator, TokenValidator, TokenValidatorBuilder}; #[entrypoint] async fn configure( launcher: Launcher, Configuration(bytes): Configuration, validator_builder: TokenValidatorBuilder, ) -> Result<()> { // [...] // Create a token validator let mut validator_instance = validator_builder .new("token-cache") .with_path("/introspect") .with_authorization_value("Basic YWRtaW46YWRtaW4=") // Choose either authorization value or client ID and secret depending on your service authorization. No authorization header is sent if with_authorization_value() isn't defined. .with_client_id("client-id") // Client ID and secret are sent as form params in the body of the request .with_client_secret("client-secret") .with_expires_in_attribute("exp") .with_max_token_ttl(600) .with_timeout_ms(10000) .with_max_cache_entries(10000) .with_scopes_validator(ScopesValidator::all(scopes_vector)) .with_service(config.my_service) .with_protected_resource_metadata(config.auth_server_url) // Choose .with_protected_resource_metadata_with_properties() if additional properties are required .build(); // [...] } ``` The `TokenValidatorBuilder` provides these methods to configure the token validator. You must call `with_service` before `build`, all other methods are optional:
MethodParameterDefaultDescription

with_path

path (impl Into<String>)

"/"

Sets the introspection endpoint path.

with_authorization_value

value (impl Into<String>)

"" (Auth header with an empty value)

Sets the authorization header value for introspection requests.

with_client_id

value (impl Into<String>)

No default

Sets the client ID credential to talk with the introspection service.

with_client_secret

value (impl Into<String>)

No default

Sets the client secret credential to talk with the introspection service.

with_expires_in_attribute

attr (impl Into<String>)

"exp"

Sets the attribute name for expiration time in the introspection response.

with_max_token_ttl

ttl (i64)

-1 (no cap)

Sets the maximum token TTL in seconds; tokens with a longer TTL are treated as expired. Use -1 for no limit.

with_timeout_ms

timeout (u64)

10000 (10 s)

Sets the timeout for introspection requests in milliseconds.

with_max_cache_entries

max_entries (usize)

1000

Sets the maximum number of entries in the token cache.

with_scopes_validator

validator (ScopesValidator)

No default

Sets the scopes validator for token validation (for example, ScopesValidator::all(scopes_vector)).

with_service

service (Service)

No default (required)

Sets the OAuth2 introspection service endpoint. Required to build the validator.

with_protected_resource_metadata

authorization server url (impl Into<String>)

No default

Enables RFC 9728 protected resource discovery with the given authorization server URL. The well-known endpoint path and resource URL are derived automatically from the API base path extracted from PDK metadata when the policy is applied.

with_protected_resource_metadata_with_properties

authorization server url (impl Into<String>), additional properties (Value)

No default

Enables RFC 9728 protected resource discovery with the given authorization server URL and additional metadata properties (such as scopes_supported or bearer_methods_supported). The well-known endpoint path and resource URL are derived automatically from the API base path extracted from PDK metadata when the policy is applied.

> [!NOTE] The configure function receives the > [configuration parameters](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-schema-definition) defined in your policy schema. ## Validate a Token Once configured, the validator provides the `validate` function, that expects a token string. The validate function sends a request to the introspection endpoint and returns the `IntrospectionResult`: ```Rust // extract token from header let auth_header = handler.header("Authorization"); let token = auth_header.split_whitespace()[1]; let result = validator .validate(&token) .await .map_err(PolicyError::Introspection)?; ``` ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Using Spike Control Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)'s > Spike Control library, see > [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/spike/README.md). To prevent sudden surges from overwhelming upstream services or exhausting shared capacity, spike control regulates how quickly traffic can grow. With the Spike Control library, you drive a handler modeled as a token bucket with a xref:policies-pdk-configure-features-timer.adoc\[Timer\] and a \`Clock\` ticker, then you call \`is\_allowed\` from request or response filters. Use the library for custom policies that need spike arrest, smoothing, or rate style limits like those in Omni Gateway, with Rust logic you control. Use the library when your custom policy must perform these tasks. - Reject or delay traffic when request volume spikes beyond configured tiers. - Share one handler across filters while a periodic ticker refreshes bucket state. - Return `429 Too Many Requests` or another HTTP outcome when `is_allowed` reports overload. ## Inject `SpikeControlBuilder` and Build a Handler Inject `SpikeControlBuilder` and `Clock` in the [`#[entrypoint` configure function\]. Include `Launcher` and your other configuration types. From `Clock`, create a ticker, pass it to the builder, add at least one bucket as `Tier` values with `requests` and `period_in_millis`, and call `build` to get a `SpikeControlHandler` you share with filters inside `std::rc::Rc`. The `Tier` layout matches](policies-pdk-configure-features#policy-template) [rate limiting examples](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-rate-limiting). ```Rust use anyhow::Result; use pdk::hl::*; use std::rc::Rc; use std::time::Duration; use pdk::spike_control::{ SpikeControlBuilder, SpikeControlError, SpikeControlHandler, Tier, }; #[entrypoint] async fn configure( launcher: Launcher, clock: Clock, spike_control: SpikeControlBuilder, ) -> Result<()> { let ticker = Rc::new(clock.period(Duration::from_millis(100))); let handler = Rc::new( spike_control .new("example-spike-control".to_string()) .with_ticker(ticker) .with_bucket( "default".to_string(), vec![Tier { requests: 1, period_in_millis: 1000, }], ) .with_retry(200, 2) .build() .map_err(|e| anyhow::anyhow!("failed to build spike control example: {e}"))?, ); launcher .launch(on_request({ let handler = Rc::clone(&handler); move |state| request_filter(state, handler.as_ref()) })) .await?; Ok(()) } ``` Use the fluent builder on `SpikeControlBuilder` to register a spike control name, ticker, buckets, and optional `with_retry` behavior. See the PDK Rust API documentation for a list of `with_*` methods. The documentation also explains what happens when you omit a call and what the `with_retry` method does. ## Evaluate Traffic with `is_allowed` Pass a reference to `SpikeControlHandler` into your `on_request` or `on_response` filters. For each request, call `is_allowed` with the bucket name, the traffic scope key, the permit count for this call, and the boolean flags your design requires. See the PDK Rust API documentation for full parameter and return value details. ```Rust async fn request_filter(state: RequestState, handler: &SpikeControlHandler) -> Flow<()> { let _ = state.into_headers_state().await; match handler.is_allowed("default", "sample", 1, true).await { Ok(_) => Flow::Continue(()), Err(SpikeControlError::TooManyRequests(_)) => Flow::Break(Response::new(429)), Err(_) => Flow::Break(Response::new(503)), } } ``` Match each `is_allowed` outcome to the HTTP response your API contract requires. The example continues the request when the call succeeds and sends `429 Too Many Requests` when spike control rejects the call for rate reasons. ## Interpret Spike Control Errors `Err(SpikeControlError::TooManyRequests(_))` means traffic exceeded the tier for that bucket and key. Other error variants signal internal faults, such as timer or storage problems. If you need operational detail, log at the debug or warn level. If you can’t expose internal details, return a generic message to clients. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-timer) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Using Spike Control Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)'s > Spike Control library, see > [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/spike/README.md). To prevent sudden surges from overwhelming upstream services or exhausting shared capacity, spike control regulates how quickly traffic can grow. With the Spike Control library, you drive a handler modeled as a token bucket with a xref:policies-pdk-configure-features-timer.adoc\[Timer\] and a \`Clock\` ticker, then you call \`is\_allowed\` from request or response filters. Use the library for custom policies that need spike arrest, smoothing, or rate style limits like those in Omni Gateway, with Rust logic you control. Use the library when your custom policy must perform these tasks. - Reject or delay traffic when request volume spikes beyond configured tiers. - Share one handler across filters while a periodic ticker refreshes bucket state. - Return `429 Too Many Requests` or another HTTP outcome when `is_allowed` reports overload. ## Inject `SpikeControlBuilder` and Build a Handler Inject `SpikeControlBuilder` and `Clock` in the [`#[entrypoint` configure function\]. Include `Launcher` and your other configuration types. From `Clock`, create a ticker, pass it to the builder, add at least one bucket as `Tier` values with `requests` and `period_in_millis`, and call `build` to get a `SpikeControlHandler` you share with filters inside `std::rc::Rc`. The `Tier` layout matches](policies-pdk-configure-features#policy-template) [rate limiting examples](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-rate-limiting). ```Rust use anyhow::Result; use pdk::hl::*; use std::rc::Rc; use std::time::Duration; use pdk::spike_control::{ SpikeControlBuilder, SpikeControlError, SpikeControlHandler, Tier, }; #[entrypoint] async fn configure( launcher: Launcher, clock: Clock, spike_control: SpikeControlBuilder, ) -> Result<()> { let ticker = Rc::new(clock.period(Duration::from_millis(100))); let handler = Rc::new( spike_control .new("example-spike-control".to_string()) .with_ticker(ticker) .with_bucket( "default".to_string(), vec![Tier { requests: 1, period_in_millis: 1000, }], ) .with_retry(200, 2) .build() .map_err(|e| anyhow::anyhow!("failed to build spike control example: {e}"))?, ); launcher .launch(on_request({ let handler = Rc::clone(&handler); move |state| request_filter(state, handler.as_ref()) })) .await?; Ok(()) } ``` Use the fluent builder on `SpikeControlBuilder` to register a spike control name, ticker, buckets, and optional `with_retry` behavior. See the PDK Rust API documentation for a list of `with_*` methods. The documentation also explains what happens when you omit a call and what the `with_retry` method does. ## Evaluate Traffic with `is_allowed` Pass a reference to `SpikeControlHandler` into your `on_request` or `on_response` filters. For each request, call `is_allowed` with the bucket name, the traffic scope key, the permit count for this call, and the boolean flags your design requires. See the PDK Rust API documentation for full parameter and return value details. ```Rust async fn request_filter(state: RequestState, handler: &SpikeControlHandler) -> Flow<()> { let _ = state.into_headers_state().await; match handler.is_allowed("default", "sample", 1, true).await { Ok(_) => Flow::Continue(()), Err(SpikeControlError::TooManyRequests(_)) => Flow::Break(Response::new(429)), Err(_) => Flow::Break(Response::new(503)), } } ``` Match each `is_allowed` outcome to the HTTP response your API contract requires. The example continues the request when the call succeeds and sends `429 Too Many Requests` when spike control rejects the call for rate reasons. ## Interpret Spike Control Errors `Err(SpikeControlError::TooManyRequests(_))` means traffic exceeded the tier for that bucket and key. Other error variants signal internal faults, such as timer or storage problems. If you need operational detail, log at the debug or warn level. If you can’t expose internal details, return a generic message to clients. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-timer) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Using Spike Control Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)'s > Spike Control library, see > [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/spike/README.md). To prevent sudden surges from overwhelming upstream services or exhausting shared capacity, spike control regulates how quickly traffic can grow. With the Spike Control library, you drive a handler modeled as a token bucket with a xref:policies-pdk-configure-features-timer.adoc\[Timer\] and a \`Clock\` ticker, then you call \`is\_allowed\` from request or response filters. Use the library for custom policies that need spike arrest, smoothing, or rate style limits like those in Omni Gateway, with Rust logic you control. Use the library when your custom policy must perform these tasks. - Reject or delay traffic when request volume spikes beyond configured tiers. - Share one handler across filters while a periodic ticker refreshes bucket state. - Return `429 Too Many Requests` or another HTTP outcome when `is_allowed` reports overload. ## Inject `SpikeControlBuilder` and Build a Handler Inject `SpikeControlBuilder` and `Clock` in the [`#[entrypoint` configure function\]. Include `Launcher` and your other configuration types. From `Clock`, create a ticker, pass it to the builder, add at least one bucket as `Tier` values with `requests` and `period_in_millis`, and call `build` to get a `SpikeControlHandler` you share with filters inside `std::rc::Rc`. The `Tier` layout matches](policies-pdk-configure-features#policy-template) [rate limiting examples](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-rate-limiting). ```Rust use anyhow::Result; use pdk::hl::*; use std::rc::Rc; use std::time::Duration; use pdk::spike_control::{ SpikeControlBuilder, SpikeControlError, SpikeControlHandler, Tier, }; #[entrypoint] async fn configure( launcher: Launcher, clock: Clock, spike_control: SpikeControlBuilder, ) -> Result<()> { let ticker = Rc::new(clock.period(Duration::from_millis(100))); let handler = Rc::new( spike_control .new("example-spike-control".to_string()) .with_ticker(ticker) .with_bucket( "default".to_string(), vec![Tier { requests: 1, period_in_millis: 1000, }], ) .with_retry(200, 2) .build() .map_err(|e| anyhow::anyhow!("failed to build spike control example: {e}"))?, ); launcher .launch(on_request({ let handler = Rc::clone(&handler); move |state| request_filter(state, handler.as_ref()) })) .await?; Ok(()) } ``` Use the fluent builder on `SpikeControlBuilder` to register a spike control name, ticker, buckets, and optional `with_retry` behavior. See the PDK Rust API documentation for a list of `with_*` methods. The documentation also explains what happens when you omit a call and what the `with_retry` method does. ## Evaluate Traffic with `is_allowed` Pass a reference to `SpikeControlHandler` into your `on_request` or `on_response` filters. For each request, call `is_allowed` with the bucket name, the traffic scope key, the permit count for this call, and the boolean flags your design requires. See the PDK Rust API documentation for full parameter and return value details. ```Rust async fn request_filter(state: RequestState, handler: &SpikeControlHandler) -> Flow<()> { let _ = state.into_headers_state().await; match handler.is_allowed("default", "sample", 1, true).await { Ok(_) => Flow::Continue(()), Err(SpikeControlError::TooManyRequests(_)) => Flow::Break(Response::new(429)), Err(_) => Flow::Break(Response::new(503)), } } ``` Match each `is_allowed` outcome to the HTTP response your API contract requires. The example continues the request when the call succeeds and sends `429 Too Many Requests` when spike control rejects the call for rate reasons. ## Interpret Spike Control Errors `Err(SpikeControlError::TooManyRequests(_))` means traffic exceeded the tier for that bucket and key. Other error variants signal internal faults, such as timer or storage problems. If you need operational detail, log at the debug or warn level. If you can’t expose internal details, return a generic message to clients. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features) - [Configuring Delayed, Periodic, and Synchronous Functions](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-timer) - [Rate Limiting Requests](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-rate-limiting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Using Third-Party Libraries > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses third-party libraries, see > [Crypto Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/crypto/README.md). Proxy Wasm defines a low level binary application interface (abi), that limits the system calls a library can make. All third-party libraries included in your policy must be compatible with the `wasm32-wasi` Rust compilation target. To define a library such as `serde_urlencoded`, add it to the dependency list in `cargo.toml`: ```toml [dependencies] ... serde_urlencoded = "0.7.0" ``` Defining libraries enables you to use functions in `lib.rs` such as: ```Rust serde_urlencoded::to_string([("token", "myToken")]) ``` Libraries that interact with an external service like a database, or perform a system call like reading a file, are usually not compatible with the `wasm32-wasi` target. If your policy interacts with external services, use the Flex Gateway exposed `HttpClient`. For more information about performing an HTTP call, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features-http-request). It is possible that some libraries compile properly to the `wasm32-wasi` target but don’t work properly when deployed to Flex Gateway. Example errors include: - `Failed to load Wasm module due to a missing import: …​` - `Wasm VM failed to initialize Wasm code` - `Plugin configured to fail closed failed to load` In these cases, contact the owners of the third-party library, or use a different library. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.2/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Using Third-Party Libraries > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses third-party libraries, see > [Crypto Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.2.0/crypto/README.md). Proxy Wasm defines a low level binary application interface (abi), that limits the system calls a library can make. All third-party libraries included in your policy must be compatible with the `wasm32-wasi` Rust compilation target. To define a library such as `serde_urlencoded`, add it to the dependency list in `cargo.toml`: ```toml [dependencies] ... serde_urlencoded = "0.7.0" ``` Defining libraries enables you to use functions in `lib.rs` such as: ```Rust serde_urlencoded::to_string([("token", "myToken")]) ``` Libraries that interact with an external service like a database, or perform a system call like reading a file, are usually not compatible with the `wasm32-wasi` target. If your policy interacts with external services, use the Flex Gateway exposed `HttpClient`. For more information about performing an HTTP call, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features-http-request). It is possible that some libraries compile properly to the `wasm32-wasi` target but don’t work properly when deployed to Flex Gateway. Example errors include: - `Failed to load Wasm module due to a missing import: …​` - `Wasm VM failed to initialize Wasm code` - `Plugin configured to fail closed failed to load` In these cases, contact the owners of the third-party library, or use a different library. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.3/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Using Third-Party Libraries > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses third-party libraries, see > [Crypto Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.4.0/crypto/README.md). Proxy Wasm defines a low level binary application interface (abi), that limits the system calls a library can make. All third-party libraries included in your policy must be compatible with the `wasm32-wasip1` Rust compilation target. To define a library such as `serde_urlencoded`, add it to the dependency list in `cargo.toml`: ```toml [dependencies] ... serde_urlencoded = "0.7.0" ``` Defining libraries enables you to use functions in `lib.rs` such as: ```Rust serde_urlencoded::to_string([("token", "myToken")]) ``` Libraries that interact with an external service like a database, or perform a system call like reading a file, are usually not compatible with the `wasm32-wasip1` target. If your policy interacts with external services, use the Flex Gateway exposed `HttpClient`. For more information about performing an HTTP call, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features-http-request). It is possible that some libraries compile properly to the `wasm32-wasip1` target but don’t work properly when deployed to Flex Gateway. Example errors include: - `Failed to load Wasm module due to a missing import: …​` - `Wasm VM failed to initialize Wasm code` - `Plugin configured to fail closed failed to load` In these cases, contact the owners of the third-party library, or use a different library. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.4/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Using Third-Party Libraries > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses third-party libraries, see > [Crypto Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.5.0/crypto/README.md). Proxy Wasm defines a low level binary application interface (abi), that limits the system calls a library can make. All third-party libraries included in your policy must be compatible with the `wasm32-wasip1` Rust compilation target. To define a library such as `serde_urlencoded`, add it to the dependency list in `cargo.toml`: ```toml [dependencies] ... serde_urlencoded = "0.7.0" ``` Defining libraries enables you to use functions in `lib.rs` such as: ```Rust serde_urlencoded::to_string([("token", "myToken")]) ``` Libraries that interact with an external service like a database, or perform a system call like reading a file, are usually not compatible with the `wasm32-wasip1` target. If your policy interacts with external services, use the Flex Gateway exposed `HttpClient`. For more information about performing an HTTP call, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features-http-request). It is possible that some libraries compile properly to the `wasm32-wasip1` target but don’t work properly when deployed to Flex Gateway. Example errors include: - `Failed to load Wasm module due to a missing import: …​` - `Wasm VM failed to initialize Wasm code` - `Plugin configured to fail closed failed to load` In these cases, contact the owners of the third-party library, or use a different library. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.5/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Using Third-Party Libraries > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses third-party libraries, see > [Crypto Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/crypto/README.md). Proxy Wasm defines a low level binary application interface (abi), that limits the system calls a library can make. All third-party libraries included in your policy must be compatible with the `wasm32-wasip1` Rust compilation target. To define a library such as `serde_urlencoded`, add it to the dependency list in `cargo.toml`: ```toml [dependencies] ... serde_urlencoded = "0.7.0" ``` Defining libraries enables you to use functions in `lib.rs` such as: ```Rust serde_urlencoded::to_string([("token", "myToken")]) ``` Libraries that interact with an external service like a database, or perform a system call like reading a file, are usually not compatible with the `wasm32-wasip1` target. If your policy interacts with external services, use the Flex Gateway exposed `HttpClient`. For more information about performing an HTTP call, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features-http-request). It is possible that some libraries compile properly to the `wasm32-wasip1` target but don’t work properly when deployed to Flex Gateway. Example errors include: - `Failed to load Wasm module due to a missing import: …​` - `Wasm VM failed to initialize Wasm code` - `Plugin configured to fail closed failed to load` In these cases, contact the owners of the third-party library, or use a different library. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.6/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Using Third-Party Libraries > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses third-party libraries, see > [Crypto Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.6.0/crypto/README.md). Proxy Wasm defines a low level binary application interface (abi), that limits the system calls a library can make. All third-party libraries included in your policy must be compatible with the `wasm32-wasip1` Rust compilation target. To define a library such as `serde_urlencoded`, add it to the dependency list in `cargo.toml`: ```toml [dependencies] ... serde_urlencoded = "0.7.0" ``` Defining libraries enables you to use functions in `lib.rs` such as: ```Rust serde_urlencoded::to_string([("token", "myToken")]) ``` Libraries that interact with an external service like a database, or perform a system call like reading a file, are usually not compatible with the `wasm32-wasip1` target. If your policy interacts with external services, use the Flex Gateway exposed `HttpClient`. For more information about performing an HTTP call, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features-http-request). It is possible that some libraries compile properly to the `wasm32-wasip1` target but don’t work properly when deployed to Flex Gateway. Example errors include: - `Failed to load Wasm module due to a missing import: …​` - `Wasm VM failed to initialize Wasm code` - `Plugin configured to fail closed failed to load` In these cases, contact the owners of the third-party library, or use a different library. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Using Third-Party Libraries > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses third-party libraries, see > [Crypto Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/crypto/README.md). Proxy Wasm defines a low level binary application interface (abi), that limits the system calls a library can make. All third-party libraries included in your policy must be compatible with the `wasm32-wasip1` Rust compilation target. To define a library such as `serde_urlencoded`, add it to the dependency list in `cargo.toml`: ```toml [dependencies] ... serde_urlencoded = "0.7.0" ``` Defining libraries enables you to use functions in `lib.rs` such as: ```Rust serde_urlencoded::to_string([("token", "myToken")]) ``` Libraries that interact with an external service like a database, or perform a system call like reading a file, are usually not compatible with the `wasm32-wasip1` target. If your policy interacts with external services, use the Omni Gateway exposed `HttpClient`. For more information about performing an HTTP call, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-http-request). It is possible that some libraries compile properly to the `wasm32-wasip1` target but don’t work properly when deployed to Omni Gateway. Example errors include: - `Failed to load Wasm module due to a missing import: …​` - `Wasm VM failed to initialize Wasm code` - `Plugin configured to fail closed failed to load` In these cases, contact the owners of the third-party library, or use a different library. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Using Third-Party Libraries > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses third-party libraries, see > [Crypto Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/crypto/README.md). Proxy Wasm defines a low level binary application interface (abi), that limits the system calls a library can make. All third-party libraries included in your policy must be compatible with the `wasm32-wasip1` Rust compilation target. To define a library such as `serde_urlencoded`, add it to the dependency list in `cargo.toml`: ```toml [dependencies] ... serde_urlencoded = "0.7.0" ``` Defining libraries enables you to use functions in `lib.rs` such as: ```Rust serde_urlencoded::to_string([("token", "myToken")]) ``` Libraries that interact with an external service like a database, or perform a system call like reading a file, are usually not compatible with the `wasm32-wasip1` target. If your policy interacts with external services, use the Omni Gateway exposed `HttpClient`. For more information about performing an HTTP call, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-http-request). It is possible that some libraries compile properly to the `wasm32-wasip1` target but don’t work properly when deployed to Omni Gateway. Example errors include: - `Failed to load Wasm module due to a missing import: …​` - `Wasm VM failed to initialize Wasm code` - `Plugin configured to fail closed failed to load` In these cases, contact the owners of the third-party library, or use a different library. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Using Third-Party Libraries > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses third-party libraries, see > [Crypto Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/crypto/README.md). Proxy Wasm defines a low level binary application interface (abi), that limits the system calls a library can make. All third-party libraries included in your policy must be compatible with the `wasm32-wasip1` Rust compilation target. To define a library such as `serde_urlencoded`, add it to the dependency list in `cargo.toml`: ```toml [dependencies] ... serde_urlencoded = "0.7.0" ``` Defining libraries enables you to use functions in `lib.rs` such as: ```Rust serde_urlencoded::to_string([("token", "myToken")]) ``` Libraries that interact with an external service like a database, or perform a system call like reading a file, are usually not compatible with the `wasm32-wasip1` target. If your policy interacts with external services, use the Omni Gateway exposed `HttpClient`. For more information about performing an HTTP call, see [Performing an HTTP Call](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-http-request). It is possible that some libraries compile properly to the `wasm32-wasip1` target but don’t work properly when deployed to Omni Gateway. Example errors include: - `Failed to load Wasm module due to a missing import: …​` - `Wasm VM failed to initialize Wasm code` - `Plugin configured to fail closed failed to load` In these cases, contact the owners of the third-party library, or use a different library. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Using XML Validator Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)'s > XML Validator library, see > [XML Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/xml-validation/README.md). Excessive element counts, nesting depth, and attribute sizes in XML payloads can cause parsers to consume excessive memory or CPU. The PDK XML Validator library streams the incoming XML body and enforces configurable limits on its structure and size. Use this library to build custom policies. The library mirrors the limits of the built-in [XML Threat Protection Policy](https://docs.mulesoft.com/gateway/latest/policies-included-xml-threat-protection) for Omni Gateway. Use the library when your custom policy must perform these tasks. - Accept XML request or response bodies and reject malformed or oversized documents before the gateway fully buffers them. - Apply limits that match your API’s threat model, such as maximum element depth, number of children per element, or text node length. - Process large bodies incrementally by using the [streaming body state](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-headers#streaming-bodies). Import the builder from the `xml_validator` module of the PDK crate. ```Rust use pdk::xml_validator::XmlValidatorBuilder; ``` ## Build an XML Validator Create a validator with `XmlValidatorBuilder::new()`, chain the configuration methods for the limits you need, and call `build()`. The builder methods map to the same constraint types as [XML Threat Protection Policy](https://docs.mulesoft.com/gateway/latest/policies-included-xml-threat-protection). Names differ slightly from the policy UI parameters, but the intent matches.
MethodDescription

with_max_depth

Maximum nesting depth of elements in the document.

with_max_attribute_count

Maximum number of attributes on a single element.

with_max_child_count

Maximum number of child nodes of a single element.

with_max_text_length

Maximum length of text node content, as UTF-8 byte length.

with_max_attribute_length

Maximum length of a single attribute value, as UTF-8 byte length.

with_max_comment_length

Maximum length of comment content, as UTF-8 byte length.

If you omit a `with_*` method, that limit isn’t applied, so there’s no restriction on that field. Call only the methods for limits you want enforced. For type details and any extra options, see the PDK Rust API documentation for your release. ## Validate an XML Request Body Stream Validate the raw byte stream of the body. Use the streaming body state so the parser processes data as it arrives. Streaming is required for bodies larger than the buffered body limit, and it matches how the PDK exposes large payloads. For more information, see [Streaming Bodies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-headers#streaming-bodies). The `validate_stream` method consumes the stream, succeeds if the document is well-formed and within your limits, and returns an error if the XML is invalid or breaks a constraint. ```Rust use anyhow::Result; use pdk::hl::*; use pdk::xml_validator::XmlValidatorBuilder; async fn request_filter(state: RequestState) -> Flow<()> { let headers_state = state.into_headers_state().await; if !headers_state.contains_body() { return Flow::Continue(()); } let body_stream_state = headers_state.into_body_stream_state().await; let validator = XmlValidatorBuilder::new() .with_max_depth(10) .with_max_attribute_count(10) .with_max_child_count(50) .with_max_text_length(1024) .with_max_attribute_length(256) .with_max_comment_length(1024) .build(); match validator.validate_stream(body_stream_state.stream()).await { Ok(()) => Flow::Continue(()), Err(_) => Flow::Break(Response::new(400).with_body("Invalid or disallowed XML payload")), } } #[entrypoint] async fn configure(launcher: Launcher, Configuration(_configuration): Configuration) -> Result<()> { launcher .launch(on_request(|request| request_filter(request))) .await?; Ok(()) } ``` On success, the example continues the request to run upstream processing. On failure, the policy returns `400 Bad Request`. Change the status code and body to match your API’s contract. ## Initialize the Validator from Policy Configuration If you supply limits through your policy schema in GCL, parse the configuration and build the XmlValidatorBuilder in the #\[entrypoint\] function. If the configuration is invalid or incompatible, applying the policy fails before traffic reaches the API. Pass the validator into your request filter. For example, if you need shared ownership across closures, wrap the validator in std::rc::Rc or std::sync::Arc, depending on your policy layout. Map your generated config::Config fields to the builder methods in [Build an XML Validator](#build-xml-validator). Use the types the PDK API expects for your release. ## Interpret Validation Errors If `validate_stream` returns `Err`, reject the payload. The XML might be malformed or violate a configured limit. If you need operational detail, log the error at the debug or warn level. If you can’t expose parser details, return a generic client-facing message. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features) - [Streaming Bodies](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-headers#streaming-bodies) - [XML Threat Protection Policy](https://docs.mulesoft.com/gateway/latest/policies-included-xml-threat-protection) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Using XML Validator Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)’s > XML Validator library, see > [XML Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.9.0/xml-validation/README.md). Excessive element counts, nesting depth, and attribute sizes in XML payloads can cause parsers to consume excessive memory or CPU. The PDK XML Validator library streams the incoming XML body and enforces configurable limits on its structure and size. Use this library to build custom policies. The library mirrors the limits of the built-in [XML Threat Protection Policy](https://docs.mulesoft.com/gateway/latest/policies-included-xml-threat-protection) for Omni Gateway. Use the library when your custom policy must perform these tasks. - Accept XML request or response bodies and reject malformed or oversized documents before the gateway fully buffers them. - Apply limits that match your API’s threat model, such as maximum element depth, number of children per element, or text node length. - Process large bodies incrementally by using the [streaming body state](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-headers#streaming-bodies). > [!NOTE] The XML Validator library is gated behind a Cargo feature and is enabled by default. To > disable XML Validator features for your policy, see > [Configure PDK Features in Cargo.toml](https://docs.mulesoft.com/pdk/1.9/policies-pdk-create-project#configure-pdk-features). Import the builder from the `xml_validator` module of the PDK crate. ```Rust use pdk::xml_validator::XmlValidatorBuilder; ``` ## Build an XML Validator Create a validator with `XmlValidatorBuilder::new()`, chain the configuration methods for the limits you need, and call `build()`. The builder methods map to the same constraint types as [XML Threat Protection Policy](https://docs.mulesoft.com/gateway/latest/policies-included-xml-threat-protection). Names differ slightly from the policy UI parameters, but the intent matches.
MethodDescription

with_max_depth

Maximum nesting depth of elements in the document.

with_max_attribute_count

Maximum number of attributes on a single element.

with_max_child_count

Maximum number of child nodes of a single element.

with_max_text_length

Maximum length of text node content, as UTF-8 byte length.

with_max_attribute_length

Maximum length of a single attribute value, as UTF-8 byte length.

with_max_comment_length

Maximum length of comment content, as UTF-8 byte length.

If you omit a `with_*` method, that limit isn’t applied, so there’s no restriction on that field. Call only the methods for limits you want enforced. For type details and any extra options, see the PDK Rust API documentation for your release. ## Validate an XML Request Body Stream Validate the raw byte stream of the body. Use the streaming body state so the parser processes data as it arrives. Streaming is required for bodies larger than the buffered body limit, and it matches how the PDK exposes large payloads. For more information, see [Streaming Bodies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-headers#streaming-bodies). The `validate_stream` method consumes the stream, succeeds if the document is well-formed and within your limits, and returns an error if the XML is invalid or breaks a constraint. ```Rust use anyhow::Result; use pdk::hl::*; use pdk::xml_validator::XmlValidatorBuilder; async fn request_filter(state: RequestState) -> Flow<()> { let headers_state = state.into_headers_state().await; if !headers_state.contains_body() { return Flow::Continue(()); } let body_stream_state = headers_state.into_body_stream_state().await; let validator = XmlValidatorBuilder::new() .with_max_depth(10) .with_max_attribute_count(10) .with_max_child_count(50) .with_max_text_length(1024) .with_max_attribute_length(256) .with_max_comment_length(1024) .build(); match validator.validate_stream(body_stream_state.stream()).await { Ok(()) => Flow::Continue(()), Err(_) => Flow::Break(Response::new(400).with_body("Invalid or disallowed XML payload")), } } #[entrypoint] async fn configure(launcher: Launcher, Configuration(_configuration): Configuration) -> Result<()> { launcher .launch(on_request(|request| request_filter(request))) .await?; Ok(()) } ``` On success, the example continues the request to run upstream processing. On failure, the policy returns `400 Bad Request`. Change the status code and body to match your API’s contract. ## Initialize the Validator from Policy Configuration If you supply limits through your policy schema in GCL, parse the configuration and build the XmlValidatorBuilder in the #\[entrypoint\] function. If the configuration is invalid or incompatible, applying the policy fails before traffic reaches the API. Pass the validator into your request filter. For example, if you need shared ownership across closures, wrap the validator in std::rc::Rc or std::sync::Arc, depending on your policy layout. Map your generated config::Config fields to the builder methods in [Build an XML Validator](#build-xml-validator). Use the types the PDK API expects for your release. ## Interpret Validation Errors If `validate_stream` returns `Err`, reject the payload. The XML might be malformed or violate a configured limit. If you need operational detail, log the error at the debug or warn level. If you can’t expose parser details, return a generic client-facing message. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features) - [Streaming Bodies](https://docs.mulesoft.com/pdk/1.9/policies-pdk-configure-features-headers#streaming-bodies) - [XML Threat Protection Policy](https://docs.mulesoft.com/gateway/latest/policies-included-xml-threat-protection) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Using XML Validator Library Functions > For the full documentation index, see: https://docs.mulesoft.com/llms.txt > [!NOTE] To view an example policy project that uses Omni Gateway Policy Development Kit (PDK)’s > XML Validator library, see > [XML Validation Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.10.0/xml-validation/README.md). Excessive element counts, nesting depth, and attribute sizes in XML payloads can cause parsers to consume excessive memory or CPU. The PDK XML Validator library streams the incoming XML body and enforces configurable limits on its structure and size. Use this library to build custom policies. The library mirrors the limits of the built-in [XML Threat Protection Policy](https://docs.mulesoft.com/gateway/latest/policies-included-xml-threat-protection) for Omni Gateway. Use the library when your custom policy must perform these tasks. - Accept XML request or response bodies and reject malformed or oversized documents before the gateway fully buffers them. - Apply limits that match your API’s threat model, such as maximum element depth, number of children per element, or text node length. - Process large bodies incrementally by using the [streaming body state](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-headers#streaming-bodies). > [!NOTE] The XML Validator library is gated behind a Cargo feature and is enabled by default. To > disable XML Validator features for your policy, see > [Configure PDK Features in Cargo.toml](https://docs.mulesoft.com/pdk/latest/policies-pdk-create-project#configure-pdk-features). Import the builder from the `xml_validator` module of the PDK crate. ```Rust use pdk::xml_validator::XmlValidatorBuilder; ``` ## Build an XML Validator Create a validator with `XmlValidatorBuilder::new()`, chain the configuration methods for the limits you need, and call `build()`. The builder methods map to the same constraint types as [XML Threat Protection Policy](https://docs.mulesoft.com/gateway/latest/policies-included-xml-threat-protection). Names differ slightly from the policy UI parameters, but the intent matches.
MethodDescription

with_max_depth

Maximum nesting depth of elements in the document.

with_max_attribute_count

Maximum number of attributes on a single element.

with_max_child_count

Maximum number of child nodes of a single element.

with_max_text_length

Maximum length of text node content, as UTF-8 byte length.

with_max_attribute_length

Maximum length of a single attribute value, as UTF-8 byte length.

with_max_comment_length

Maximum length of comment content, as UTF-8 byte length.

If you omit a `with_*` method, that limit isn’t applied, so there’s no restriction on that field. Call only the methods for limits you want enforced. For type details and any extra options, see the PDK Rust API documentation for your release. ## Validate an XML Request Body Stream Validate the raw byte stream of the body. Use the streaming body state so the parser processes data as it arrives. Streaming is required for bodies larger than the buffered body limit, and it matches how the PDK exposes large payloads. For more information, see [Streaming Bodies](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-headers#streaming-bodies). The `validate_stream` method consumes the stream, succeeds if the document is well-formed and within your limits, and returns an error if the XML is invalid or breaks a constraint. ```Rust use anyhow::Result; use pdk::hl::*; use pdk::xml_validator::XmlValidatorBuilder; async fn request_filter(state: RequestState) -> Flow<()> { let headers_state = state.into_headers_state().await; if !headers_state.contains_body() { return Flow::Continue(()); } let body_stream_state = headers_state.into_body_stream_state().await; let validator = XmlValidatorBuilder::new() .with_max_depth(10) .with_max_attribute_count(10) .with_max_child_count(50) .with_max_text_length(1024) .with_max_attribute_length(256) .with_max_comment_length(1024) .build(); match validator.validate_stream(body_stream_state.stream()).await { Ok(()) => Flow::Continue(()), Err(_) => Flow::Break(Response::new(400).with_body("Invalid or disallowed XML payload")), } } #[entrypoint] async fn configure(launcher: Launcher, Configuration(_configuration): Configuration) -> Result<()> { launcher .launch(on_request(|request| request_filter(request))) .await?; Ok(()) } ``` On success, the example continues the request to run upstream processing. On failure, the policy returns `400 Bad Request`. Change the status code and body to match your API’s contract. ## Initialize the Validator from Policy Configuration If you supply limits through your policy schema in GCL, parse the configuration and build the XmlValidatorBuilder in the #\[entrypoint\] function. If the configuration is invalid or incompatible, applying the policy fails before traffic reaches the API. Pass the validator into your request filter. For example, if you need shared ownership across closures, wrap the validator in std::rc::Rc or std::sync::Arc, depending on your policy layout. Map your generated config::Config fields to the builder methods in [Build an XML Validator](#build-xml-validator). Use the types the PDK API expects for your release. ## Interpret Validation Errors If `validate_stream` returns `Err`, reject the payload. The XML might be malformed or violate a configured limit. If you need operational detail, log the error at the debug or warn level. If you can’t expose parser details, return a generic client-facing message. ## See Also - [Implementing Your Custom Policy Features in Rust](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features) - [Streaming Bodies](https://docs.mulesoft.com/pdk/latest/policies-pdk-configure-features-headers#streaming-bodies) - [XML Threat Protection Policy](https://docs.mulesoft.com/gateway/latest/policies-included-xml-threat-protection) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.2 --- # Writing Integration Tests > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides an automated testing framework to detect integration regressions in your custom policy. The integration testing framework provided by PDK only supports Flex Gateway running in Local Mode in a Docker container. If you plan to deploy or policy to Flex Gateway running in Connected Mode or to a different platform, you should still first test your policy in PDK by using Flex Gateway running in Local Mode in a Docker container. > [!IMPORTANT] You can run Flex Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Flex Gateway does not support Windows in production environments. To test your policy, complete the following tasks: 1. Review [Before You Begin](#before-you-begin). 2. Review [Integration Tests Directory Structure](#structure). 3. [Register a Flex Gateway Instance in Local Mode](#register). 4. [Configure Your Custom Policy](#configure-your-custom-policy). 5. [Create a Test Function](#create-a-test-function). 6. [Run an Integration Test](#run-integration-test). 7. [Configure Services for Integration Testing](#configure-services-for-integration-testing). 8. [Review Service Logs](#review-service-logs). ## Before You Begin Ensure that you have: - [Installed Docker](https://www.docker.com/) ## Integration Tests Directory Structure By default, the `/tests` directory contains the following files: tests ├── common.rs ├── requests.rs └── common └── logging.yaml └── registration.yaml The `/tests` directory contains the integration tests. By default, the folder contains: - `requests.rs` file: An individual test module and executable. - `commons.rs` file: A test module that contains functionalities, API configurations, and policy configurations that must be included in every integration test module. ## Register a Flex Gateway Instance in Local Mode To begin using the `make test` command to debug your custom policy, register a Flex Gateway in Local Mode. For the `make test` command to work, a Flex Gateway `registration.yaml` file must exist in the `/tests/common` directory. Create this file by running the registration command in the directory, or move a `registration.yaml` file of a previously registered Flex Gateway to the directory. To register Flex Gateway, see: - [Register and Run with a Username and Password in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-up#docker) - [Register and Run with a Connected App in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-app#docker) - [Register and Run with a Token in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-token#docker) > [!IMPORTANT] Run only the registration command. Do not run the Docker start command because the > `make test` command completes this step. Create a different registration file on each device testing the policy. The registration file is ignored for storage in remote repositories and is listed in the `.gitignore` file located at the root of the project directory. ## Configure Your Custom Policy Each test function requires the configuration of the API and policies for that request. To configure the custom policy: 1. Print the policy ID by running the `show-policy-ref-name`: ```ssh make show-policy-ref-name ``` 2. Copy the result. 3. Override `{{project-name}}` in `commons.rs` with your policy ID, for example: ```rust pub const POLICY_NAME: &str = ""; ``` 4. Configure the policy’s configuration parameters. To find your configuration parameters, see the `gcl.yaml` file. ## Create a Test Function Add a new test module by placing a new test function in an existing test module, for example `/tests/requests.rs`. PDK test functions are `async` functions decorated with the `#[pdk_test]` attribute: ```rust use pdk_test::pdk_test; #[pdk_test] async fn say_hello() { } ``` > [!NOTE] Because the body is empty, this test function never fails. Run `make test` to ensure > everything is working fine. ## Run an Integration Test To run the integrations tests modules in the `/tests` folder, execute the `make test` command: ```ssh make test ``` Run this test as you add additional features to your integration test to ensure proper configuration. > [!NOTE] The `make test` command compiles the policy before running the integration tests. ## Configure Services for Integration Testing PDK integration tests contain a composite of services running inside a Docker network. You can register service instances in a `TestComposite` object. Every service has a configuration, hostname, and instance. The `pdk-test` crate contains all the functionality for writing integration tests for custom policies in PDK and is included in the `[dev-dependencies]` section of the `Cargo.toml` file. ### Supported Services PDK’s test library supports the following services:
ServiceDescription

Flex

Flex Gateway service instance.

httpmock

Service binding to the Rust’s httpmock server.

The supported services cover the majority of use cases for integration testing. It is not possible to define different types of service. ### httpmock Service `httpmock` is a mock server that enables you to write request mocks in Rust. Configure an [httpmock](https://crates.io/crates/httpmock) service by using an `HttpMockConfig` value. It is a best practice to return a `Result` from the test function. The [anyhow](https://crates.io/crates/anyhow) Rust crate enables you to return different default error types. To configure an `httpmock` service, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::HttpMockConfig; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HttpMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .port(80) // Port where the service will accept requests .build(); // Register HTTPBin service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .build() .await?; Ok(()) } ``` > [!NOTE] If the Docker engine is properly configured, this test passes. Run `make test` to ensure > proper configuration. ### Get a Service’s Handle Every configured service instance in the composite has a handle for custom interaction. The handle returns the sockets where the service endpoints are available. To find a service’s handle, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::{HttpMock, HttpMockConfig}; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HTTPMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .build(); // Register HTTPMock service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .port(80) // Port where the service accepts requests .build() .await?; // Get the httpmock handle let httpmock: HttpMock = composite.service()?; Ok(()) } ``` > [!NOTE] If the `httpmock` instance is properly configured, this test passes. Run `make test` to > ensure proper configuration. ### HTTP Endpoint Requests To mock endpoints, use the [httpmock When/Then API](https://docs.rs/httpmock/latest/httpmock/#whenthen-api). After mocking the endpoint, use an HTTP client to make endpoint requests. The [reqwest](https://crates.io/crates/reqwest/) crate offers the most comprehensive and flexible Rust HTTP client. To mock endpoints and make requests, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::{HttpMock, HttpMockConfig}; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HttpMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .port(80) // Port where the service will accept requests .build(); // Register HTTPBin service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .build() .await?; // Get the httpmock handle let httpmock: HttpMock = composite.service()?; // Connect the mock server let mock_server = httpmock::MockServer::connect_async(httpmock.socket()).await; // Configure the endpoint mocks mock_server.mock_async(|when, then| { when.path_contains("/hello"); then.status(202).body("World!"); }).await; let base_url = mock_server.base_url(); // Hit the endpoint let response = reqwest::get(format!("{base_url}/hello")).await?; // Assert on response assert_eq!(response.status(), 202); assert_eq!(response.text().await?, "World!"); Ok(()) } ``` > [!NOTE] Run `make test` to ensure proper configuration. ### Configure a Flex Service Instance Configure a `Flex` service by registering an instance of the `FlexConfig` struct in `TestComposite`. To complete the `FlexConfig` instance, you must also define a `ApiConfig` and `PolicyConfig` instance. The `FlexConfig` struct has the following properties:
PropertyContent

version

Flex Gateway version to test.

hostname

Hostname of the Flex service, by default, "local-flex".

config_mounts

A map of local directories where the Flex service finds configuration files. The POLICY_DIR and COMMON_CONFIG_DIR constants are defined in the common.rs module by default. If your test requires further configuration, add a directory with the specific configuration for the test functions.

with_api

The ApiConfiguration of the API deployed to the Flex service instance. Call multiple times to configure multiple APIs.

ports

List of ports where the Flex service listens for requests. If any of your configuration directories included in config_mount directories expose an API, the port must match the ports configured in the spec.address property.

The `ApiConfig` has the following properties:
PropertyContent

name

Name of the API.

upstream

The reference to the upstream service.

path

Path to which the upstream requests are sent.

port

Ports where the API listens for requests.

policies

A List of PolicyConfig instances applied to the API.

The `PolicyConfig` has the following properties:
PropertyContent

name

Policy to apply.

configuration

Parameters for the policy.

The following code example defines a complete `Flex` service: ```rust mod common; use common::*; use pdk_test::{pdk_test, TestComposite}; use pdk_test::port::Port; use pdk_test::services::flex::FlexConfig; // Port where Flex listens for requests const FLEX_PORT: Port = 8081; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure an upstream service for the API let httpmock_config = HttpMockConfig::builder() .port(80) .version("latest") .hostname("backend") .build(); // Configure a policy for the API let policy_config = PolicyConfig::builder() .name(POLICY_NAME) .configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60})) .build(); // Configure the API to deploy to the Flex let api_config = ApiConfig::builder() .name("ingress-http") .upstream(&httpmock_config) .path("/anything/echo/") .port(FLEX_PORT) .policies([policy_config]) .build(); // Configure the Flex service let flex_config = FlexConfig::builder() .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); let composite = TestComposite::builder() .with_service(flex_config) .with_service(httpmock_config) .build() .await?; } ``` > [!NOTE] Run `make test` to ensure proper configuration. ### Flex Service Endpoint Requests `Flex` service exposes endpoints with external base URLs dependent on the port. To access those URLs, the Flex service instance handle provides the `external_url()` method indexed by port, for example: ```rust use pdk_test::{pdk_test, TestComposite, port::Port}; use pdk_test::services::flex::Flex; const FLEX_PORT: Port = 8081; async fn build_composite() -> anyhow::Result { todo!("Configuration stuff comes here") } #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Invoke a helper composite builder function for simplicity let composite = build_composite().await?; // Get the Flex service handle let flex: Flex = composite.service()?; // Get the URL for our configured port let flex_url = flex.external_url(FLEX_PORT).unwrap(); let response = reqwest::get(format!("{flex_url}/hello")).await?; // Make assertions Ok(()) } ``` ### Combine Multiple Services Usually a PDK integration test includes a `Flex` service and at least one backend service. The following code is the default test generated when the custom policy is created: ```rust mod common; use httpmock::MockServer; use pdk_test::{pdk_test, TestComposite}; use pdk_test::port::Port; use pdk_test::services::flex::{FlexConfig, Flex}; use pdk_test::services::httpmock::{HttpMockConfig, HttpMock}; use common::*; // Directory with the configurations for the `hello` test. const HELLO_CONFIG_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/requests/hello"); // Flex port for the internal test network const FLEX_PORT: Port = 8081; // This integration test shows how to build a test to compose a local-flex instance // with a MockServer backend #[pdk_test] async fn hello() -> anyhow::Result<()> { // Configure an HttpMock service let httpmock_config = HttpMockConfig::builder() .port(80) .version("latest") .hostname("backend") .build(); // Configure a policy for the API let policy_config = PolicyConfig::builder() .name(POLICY_NAME) .configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60})) .build(); // Configure the API to deploy to the Flex let api_config = ApiConfig::builder() .name("ingress-http") .upstream(&httpmock_config) .path("/anything/echo/") .port(FLEX_PORT) .policies([policy_config]) .build(); // Configure the Flex service let flex_config = FlexConfig::builder() .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); // Compose the services let composite = TestComposite::builder() .with_service(flex_config) .with_service(httpmock_config) .build() .await?; // Get a handle to the Flex service let flex: Flex = composite.service()?; // Get an external URL to point the Flex service let flex_url = flex.external_url(FLEX_PORT).unwrap(); // Get a handle to the HttpMock service let httpmock: HttpMock = composite.service()?; // Create a MockServer let mock_server = MockServer::connect_async(httpmock.socket()).await; // Mock a /hello request mock_server.mock_async(|when, then| { when.path_contains("/hello"); then.status(202).body("World!"); }).await; // Perform an actual request let response = reqwest::get(format!("{flex_url}/hello")).await?; // Assert on the response assert_eq!(response.status(), 202); Ok(()) } ``` ## Review Service Logs After an integration test fails, you can view the service logs to find errors. To improve the debugging experience, there is a dedicated service log in each test folder at `/target/pdk-test///.log`. For the example, the `say_hello` test has the following service log: ```none ├── Cargo.lock ├── Cargo.toml ├── playground ├── src ├── tests └── target └── pdk-test └── requests └── say_hello └── .log ``` ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.2/policies-pdk-debug-local) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.2/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.3 --- # Writing Integration Tests > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides an automated testing framework to detect integration regressions in your custom policy. The integration testing framework provided by PDK only supports Flex Gateway running in Local Mode in a Docker container. If you plan to deploy or policy to Flex Gateway running in Connected Mode or to a different platform, you should still first test your policy in PDK by using Flex Gateway running in Local Mode in a Docker container. > [!IMPORTANT] You can run Flex Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Flex Gateway does not support Windows in production environments. To test your policy, complete the following tasks: 1. Review [Before You Begin](#before-you-begin). 2. Review [Integration Tests Directory Structure](#structure). 3. [Register a Flex Gateway Instance in Local Mode](#register). 4. [Configure Your Custom Policy](#configure-your-custom-policy). 5. [Create a Test Function](#create-a-test-function). 6. [Run an Integration Test](#run-integration-test). 7. [Configure Services for Integration Testing](#configure-services-for-integration-testing). 8. [Review Service Logs](#review-service-logs). ## Before You Begin Ensure that you have: - [Installed Docker](https://www.docker.com/) ## Integration Tests Directory Structure By default, the `/tests` directory contains the following files: tests ├── requests.rs └── common └── mod.rs └── config └── logging.yaml └── registration.yaml The `/tests` directory contains the integration tests. By default, the folder contains: - `requests.rs` file: An individual test module and executable. - `common/mod.rs` file: A test module that contains functionalities, API configurations, and policy configurations that must be included in every integration test module. ## Register a Flex Gateway Instance in Local Mode To begin using the `make test` command to debug your custom policy, register a Flex Gateway in Local Mode. For the `make test` command to work, a Flex Gateway `registration.yaml` file must exist in the `/tests/config` directory. Create this file by running the registration command in the directory, or move a `registration.yaml` file of a previously registered Flex Gateway to the directory. To register Flex Gateway, see: - [Register and Run with a Username and Password in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-up#docker) - [Register and Run with a Connected App in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-app#docker) - [Register and Run with a Token in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-token#docker) > [!IMPORTANT] Run only the registration command. Do not run the Docker start command because the > `make test` command completes this step. Create a different registration file on each device testing the policy. The registration file is ignored for storage in remote repositories and is listed in the `.gitignore` file located at the root of the project directory. ## Configure Your Custom Policy Each test function requires the configuration of the API and policies for that request. To configure the custom policy: 1. Print the policy ID by running the `show-policy-ref-name`: ```ssh make show-policy-ref-name ``` 2. Copy the result. 3. Override `{{project-name}}` in `common/mod.rs` with your policy ID, for example: ```rust pub const POLICY_NAME: &str = ""; ``` 4. Configure the policy’s configuration parameters. To find your configuration parameters, see the `gcl.yaml` file. ## Create a Test Function Add a new test module by placing a new test function in an existing test module, for example `/tests/requests.rs`. PDK test functions are `async` functions decorated with the `#[pdk_test]` attribute: ```rust use pdk_test::pdk_test; #[pdk_test] async fn say_hello() { } ``` > [!NOTE] Because the body is empty, this test function never fails. Run `make test` to ensure > everything is working fine. ## Run an Integration Test To run the integrations tests modules in the `/tests` folder, execute the `make test` command: ```ssh make test ``` Run this test as you add additional features to your integration test to ensure proper configuration. > [!NOTE] The `make test` command compiles the policy before running the integration tests. ## Configure Services for Integration Testing PDK integration tests contain a composite of services running inside a Docker network. You can register service instances in a `TestComposite` object. Every service has a configuration, hostname, and instance. The `pdk-test` crate contains all the functionality for writing integration tests for custom policies in PDK and is included in the `[dev-dependencies]` section of the `Cargo.toml` file. ### Supported Services PDK’s test library supports the following services:
ServiceDescription

Flex

Flex Gateway service instance.

httpmock

Service binding to the Rust’s httpmock server.

The supported services cover the majority of use cases for integration testing. It is not possible to define different types of service. ### Configure an httpmock Service `httpmock` is a mock server that enables you to write request mocks in Rust. Configure an [httpmock](https://crates.io/crates/httpmock) service by using an `HttpMockConfig` value. It is a best practice to return a `Result` from the test function. The [anyhow](https://crates.io/crates/anyhow) Rust crate enables you to return different default error types. To configure an `httpmock` service, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::HttpMockConfig; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HttpMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .port(80) // Port where the service will accept requests .build(); // Register HTTPBin service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .build() .await?; Ok(()) } ``` > [!NOTE] If the Docker engine is properly configured, this test passes. Run `make test` to ensure > proper configuration. ### Configure an Alternative httpmock Docker Image To use an `httpmock` Docker image from another source, instead of the provided default, the configuration builder provides an `image_name()` method to define it explicitly. To configure an alternative `httpmock` Docker image, update your `HttpMockConfig::builder()` definition as in this example: ```rust // Configure HttpMock service let backend_config = HttpMockConfig::builder() .image_name("myrepo/httpmock") // Custom image name setting .hostname("backend") .port(80) // Port where the service will accept requests .build(); ``` ### Get a Service’s Handle Every configured service instance in the composite has a handle for custom interaction. The handle returns the sockets where the service endpoints are available. To find a service’s handle, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::{HttpMock, HttpMockConfig}; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HTTPMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .build(); // Register HTTPMock service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .port(80) // Port where the service accepts requests .build() .await?; // Get the httpmock handle let httpmock: HttpMock = composite.service()?; Ok(()) } ``` > [!NOTE] If the `httpmock` instance is properly configured, this test passes. Run `make test` to > ensure proper configuration. ### HTTP Endpoint Requests To mock endpoints, use the [httpmock When/Then API](https://docs.rs/httpmock/latest/httpmock/#whenthen-api). After mocking the endpoint, use an HTTP client to make endpoint requests. The [reqwest](https://crates.io/crates/reqwest/) crate offers the most comprehensive and flexible Rust HTTP client. To mock endpoints and make requests, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::{HttpMock, HttpMockConfig}; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HttpMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .port(80) // Port where the service will accept requests .build(); // Register HTTPBin service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .build() .await?; // Get the httpmock handle let httpmock: HttpMock = composite.service()?; // Connect the mock server let mock_server = httpmock::MockServer::connect_async(httpmock.socket()).await; // Configure the endpoint mocks mock_server.mock_async(|when, then| { when.path_contains("/hello"); then.status(202).body("World!"); }).await; let base_url = mock_server.base_url(); // Hit the endpoint let response = reqwest::get(format!("{base_url}/hello")).await?; // Assert on response assert_eq!(response.status(), 202); assert_eq!(response.text().await?, "World!"); Ok(()) } ``` > [!NOTE] Run `make test` to ensure proper configuration. ### Configure a Flex Service Instance Configure a `Flex` service by registering an instance of the `FlexConfig` struct in `TestComposite`. To complete the `FlexConfig` instance, you must also define a `ApiConfig` and `PolicyConfig` instance. The `FlexConfig` struct has the following properties:
PropertyContent

version

Flex Gateway version to test.

image_name

Flex Gateway Docker image name, by default, "mulesoft/flex-gateway".

hostname

Hostname of the Flex service, by default, "local-flex".

config_mounts

A map of local directories where the Flex service finds configuration files. The POLICY_DIR and COMMON_CONFIG_DIR constants are defined in the common/mod.rs module by default. If your test requires further configuration, add a directory with the specific configuration for the test functions.

with_api

The ApiConfiguration of the API deployed to the Flex service instance. Call multiple times to configure multiple APIs.

ports

List of ports where the Flex service listens for requests. If any of your configuration directories included in config_mount directories expose an API, the port must match the ports configured in the spec.address property.

The `ApiConfig` has the following properties:
PropertyContent

name

Name of the API.

upstream

The reference to the upstream service.

path

Path to which the upstream requests are sent.

port

Ports where the API listens for requests.

policies

A List of PolicyConfig instances applied to the API.

The `PolicyConfig` has the following properties:
PropertyContent

name

Policy to apply.

configuration

Parameters for the policy.

The following code example defines a complete `Flex` service: ```rust mod common; use common::*; use pdk_test::{pdk_test, TestComposite}; use pdk_test::port::Port; use pdk_test::services::flex::FlexConfig; // Port where Flex listens for requests const FLEX_PORT: Port = 8081; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure an upstream service for the API let httpmock_config = HttpMockConfig::builder() .port(80) .version("latest") .hostname("backend") .build(); // Configure a policy for the API let policy_config = PolicyConfig::builder() .name(POLICY_NAME) .configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60})) .build(); // Configure the API to deploy to the Flex let api_config = ApiConfig::builder() .name("ingress-http") .upstream(&httpmock_config) .path("/anything/echo/") .port(FLEX_PORT) .policies([policy_config]) .build(); // Configure the Flex service let flex_config = FlexConfig::builder() .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); let composite = TestComposite::builder() .with_service(flex_config) .with_service(httpmock_config) .build() .await?; } ``` ### Configure an Alternative Flex Docker Image To use a `flex` Docker image from another source, instead of the provided default, the configuration builder provides an `image_name()` method to define it explicitly. To configure an alternative Flex Docker image, update your `FlexConfig::builder()` definition as in this example: ```rust // Configure the Flex service let flex_config = FlexConfig::builder() .image_name("myrepo/flex-gateway") // Custom image name setting .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); ``` > [!NOTE] Run `make test` to ensure proper configuration. ### Flex Service Endpoint Requests `Flex` service exposes endpoints with external base URLs dependent on the port. To access those URLs, the Flex service instance handle provides the `external_url()` method indexed by port, for example: ```rust use pdk_test::{pdk_test, TestComposite, port::Port}; use pdk_test::services::flex::Flex; const FLEX_PORT: Port = 8081; async fn build_composite() -> anyhow::Result { todo!("Configuration stuff comes here") } #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Invoke a helper composite builder function for simplicity let composite = build_composite().await?; // Get the Flex service handle let flex: Flex = composite.service()?; // Get the URL for our configured port let flex_url = flex.external_url(FLEX_PORT).unwrap(); let response = reqwest::get(format!("{flex_url}/hello")).await?; // Make assertions Ok(()) } ``` ### Combine Multiple Services Usually a PDK integration test includes a `Flex` service and at least one backend service. The following code is the default test generated when the custom policy is created: ```rust mod common; use httpmock::MockServer; use pdk_test::{pdk_test, TestComposite}; use pdk_test::port::Port; use pdk_test::services::flex::{FlexConfig, Flex}; use pdk_test::services::httpmock::{HttpMockConfig, HttpMock}; use common::*; // Directory with the configurations for the `hello` test. const HELLO_CONFIG_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/requests/hello"); // Flex port for the internal test network const FLEX_PORT: Port = 8081; // This integration test shows how to build a test to compose a local-flex instance // with a MockServer backend #[pdk_test] async fn hello() -> anyhow::Result<()> { // Configure an HttpMock service let httpmock_config = HttpMockConfig::builder() .port(80) .version("latest") .hostname("backend") .build(); // Configure a policy for the API let policy_config = PolicyConfig::builder() .name(POLICY_NAME) .configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60})) .build(); // Configure the API to deploy to the Flex let api_config = ApiConfig::builder() .name("ingress-http") .upstream(&httpmock_config) .path("/anything/echo/") .port(FLEX_PORT) .policies([policy_config]) .build(); // Configure the Flex service let flex_config = FlexConfig::builder() .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); // Compose the services let composite = TestComposite::builder() .with_service(flex_config) .with_service(httpmock_config) .build() .await?; // Get a handle to the Flex service let flex: Flex = composite.service()?; // Get an external URL to point the Flex service let flex_url = flex.external_url(FLEX_PORT).unwrap(); // Get a handle to the HttpMock service let httpmock: HttpMock = composite.service()?; // Create a MockServer let mock_server = MockServer::connect_async(httpmock.socket()).await; // Mock a /hello request mock_server.mock_async(|when, then| { when.path_contains("/hello"); then.status(202).body("World!"); }).await; // Perform an actual request let response = reqwest::get(format!("{flex_url}/hello")).await?; // Assert on the response assert_eq!(response.status(), 202); Ok(()) } ``` ## Review Service Logs After an integration test fails, you can view the service logs to find errors. To improve the debugging experience, there is a dedicated service log in each test folder at `/target/pdk-test///.log`. For the example, the `say_hello` test has the following service log: ```none ├── Cargo.lock ├── Cargo.toml ├── playground ├── src ├── tests └── target └── pdk-test └── requests └── say_hello └── .log ``` ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.3/policies-pdk-debug-local) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.3/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.4 --- # Writing Integration Tests > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides an automated testing framework to detect integration regressions in your custom policy. The integration testing framework provided by PDK only supports Flex Gateway running in Local Mode in a Docker container. If you plan to deploy or policy to Flex Gateway running in Connected Mode or to a different platform, you should still first test your policy in PDK by using Flex Gateway running in Local Mode in a Docker container. > [!IMPORTANT] You can run Flex Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Flex Gateway does not support Windows in production environments. To test your policy, complete the following tasks: 1. Review [Before You Begin](#before-you-begin). 2. Review [Integration Tests Directory Structure](#structure). 3. [Register a Flex Gateway Instance in Local Mode](#register). 4. [Configure Your Custom Policy](#configure-your-custom-policy). 5. [Create a Test Function](#create-a-test-function). 6. [Run an Integration Test](#run-integration-test). 7. [Configure Services for Integration Testing](#configure-services-for-integration-testing). 8. [Review Service Logs](#review-service-logs). ## Before You Begin Ensure that you have: - [Installed Docker](https://www.docker.com/) ## Integration Tests Directory Structure By default, the `/tests` directory contains the following files: tests ├── requests.rs └── common └── mod.rs └── config └── logging.yaml └── registration.yaml The `/tests` directory contains the integration tests. By default, the folder contains: - `requests.rs` file: An individual test module and executable. - `common/mod.rs` file: A test module that contains functionalities, API configurations, and policy configurations that must be included in every integration test module. ## Register a Flex Gateway Instance in Local Mode To begin using the `make test` command to debug your custom policy, register a Flex Gateway in Local Mode. For the `make test` command to work, a Flex Gateway `registration.yaml` file must exist in the `/tests/config` directory. Create this file by running the registration command in the directory, or move a `registration.yaml` file of a previously registered Flex Gateway to the directory. To register Flex Gateway, see: - [Register and Run with a Username and Password in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-up#docker) - [Register and Run with a Connected App in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-app#docker) - [Register and Run with a Token in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-token#docker) > [!IMPORTANT] Run only the registration command. Do not run the Docker start command because the > `make test` command completes this step. Create a different registration file on each device testing the policy. The registration file is ignored for storage in remote repositories and is listed in the `.gitignore` file located at the root of the project directory. ## Configure Your Custom Policy Each test function requires the configuration of the API and policies for that request. To configure the custom policy: 1. Print the policy ID by running the `show-policy-ref-name`: ```ssh make show-policy-ref-name ``` 2. Copy the result. 3. Override `{{project-name}}` in `common/mod.rs` with your policy ID, for example: ```rust pub const POLICY_NAME: &str = ""; ``` 4. Configure the policy’s configuration parameters. To find your configuration parameters, see the `gcl.yaml` file. ## Create a Test Function Add a new test module by placing a new test function in an existing test module, for example `/tests/requests.rs`. PDK test functions are `async` functions decorated with the `#[pdk_test]` attribute: ```rust use pdk_test::pdk_test; #[pdk_test] async fn say_hello() { } ``` > [!NOTE] Because the body is empty, this test function never fails. Run `make test` to ensure > everything is working fine. ## Run an Integration Test To run the integrations tests modules in the `/tests` folder, execute the `make test` command: ```ssh make test ``` Run this test as you add additional features to your integration test to ensure proper configuration. > [!NOTE] The `make test` command compiles the policy before running the integration tests. ## Configure Services for Integration Testing PDK integration tests contain a composite of services running inside a Docker network. You can register service instances in a `TestComposite` object. Every service has a configuration, hostname, and instance. The `pdk-test` crate contains all the functionality for writing integration tests for custom policies in PDK and is included in the `[dev-dependencies]` section of the `Cargo.toml` file. ### Supported Services PDK’s test library supports the following services:
ServiceDescription

Flex

Flex Gateway service instance.

httpmock

Service binding to the Rust’s httpmock server.

The supported services cover the majority of use cases for integration testing. It is not possible to define different types of service. ### Configure an httpmock Service `httpmock` is a mock server that enables you to write request mocks in Rust. Configure an [httpmock](https://crates.io/crates/httpmock) service by using an `HttpMockConfig` value. It is a best practice to return a `Result` from the test function. The [anyhow](https://crates.io/crates/anyhow) Rust crate enables you to return different default error types. To configure an `httpmock` service, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::HttpMockConfig; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HttpMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .port(80) // Port where the service will accept requests .build(); // Register HTTPBin service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .build() .await?; Ok(()) } ``` > [!NOTE] If the Docker engine is properly configured, this test passes. Run `make test` to ensure > proper configuration. ### Configure an Alternative httpmock Docker Image To use an `httpmock` Docker image from another source, instead of the provided default, the configuration builder provides an `image_name()` method to define it explicitly. To configure an alternative `httpmock` Docker image, update your `HttpMockConfig::builder()` definition as in this example: ```rust // Configure HttpMock service let backend_config = HttpMockConfig::builder() .image_name("myrepo/httpmock") // Custom image name setting .hostname("backend") .port(80) // Port where the service will accept requests .build(); ``` ### Get a Service’s Handle Every configured service instance in the composite has a handle for custom interaction. The handle returns the sockets where the service endpoints are available. To find a service’s handle, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::{HttpMock, HttpMockConfig}; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HTTPMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .build(); // Register HTTPMock service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .port(80) // Port where the service accepts requests .build() .await?; // Get the httpmock handle let httpmock: HttpMock = composite.service()?; Ok(()) } ``` > [!NOTE] If the `httpmock` instance is properly configured, this test passes. Run `make test` to > ensure proper configuration. ### HTTP Endpoint Requests To mock endpoints, use the [httpmock When/Then API](https://docs.rs/httpmock/latest/httpmock/#whenthen-api). After mocking the endpoint, use an HTTP client to make endpoint requests. The [reqwest](https://crates.io/crates/reqwest/) crate offers the most comprehensive and flexible Rust HTTP client. To mock endpoints and make requests, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::{HttpMock, HttpMockConfig}; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HttpMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .port(80) // Port where the service will accept requests .build(); // Register HTTPBin service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .build() .await?; // Get the httpmock handle let httpmock: HttpMock = composite.service()?; // Connect the mock server let mock_server = httpmock::MockServer::connect_async(httpmock.socket()).await; // Configure the endpoint mocks mock_server.mock_async(|when, then| { when.path_contains("/hello"); then.status(202).body("World!"); }).await; let base_url = mock_server.base_url(); // Hit the endpoint let response = reqwest::get(format!("{base_url}/hello")).await?; // Assert on response assert_eq!(response.status(), 202); assert_eq!(response.text().await?, "World!"); Ok(()) } ``` > [!NOTE] Run `make test` to ensure proper configuration. ### Configure a Flex Service Instance Configure a `Flex` service by registering an instance of the `FlexConfig` struct in `TestComposite`. To complete the `FlexConfig` instance, you must also define a `ApiConfig` and `PolicyConfig` instance. The `FlexConfig` struct has the following properties:
PropertyContent

version

Flex Gateway version to test.

image_name

Flex Gateway Docker image name, by default, "mulesoft/flex-gateway".

hostname

Hostname of the Flex service, by default, "local-flex".

config_mounts

A map of local directories where the Flex service finds configuration files. The POLICY_DIR and COMMON_CONFIG_DIR constants are defined in the common/mod.rs module by default. If your test requires further configuration, add a directory with the specific configuration for the test functions.

with_api

The ApiConfiguration of the API deployed to the Flex service instance. Call multiple times to configure multiple APIs.

ports

List of ports where the Flex service listens for requests. If any of your configuration directories included in config_mount directories expose an API, the port must match the ports configured in the spec.address property.

The `ApiConfig` has the following properties:
PropertyContent

name

Name of the API.

upstream

The reference to the upstream service.

path

Path to which the upstream requests are sent.

port

Ports where the API listens for requests.

policies

A List of PolicyConfig instances applied to the API.

The `PolicyConfig` has the following properties:
PropertyContent

name

Policy to apply.

configuration

Parameters for the policy.

The following code example defines a complete `Flex` service: ```rust mod common; use common::*; use pdk_test::{pdk_test, TestComposite}; use pdk_test::port::Port; use pdk_test::services::flex::FlexConfig; // Port where Flex listens for requests const FLEX_PORT: Port = 8081; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure an upstream service for the API let httpmock_config = HttpMockConfig::builder() .port(80) .version("latest") .hostname("backend") .build(); // Configure a policy for the API let policy_config = PolicyConfig::builder() .name(POLICY_NAME) .configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60})) .build(); // Configure the API to deploy to the Flex let api_config = ApiConfig::builder() .name("ingress-http") .upstream(&httpmock_config) .path("/anything/echo/") .port(FLEX_PORT) .policies([policy_config]) .build(); // Configure the Flex service let flex_config = FlexConfig::builder() .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); let composite = TestComposite::builder() .with_service(flex_config) .with_service(httpmock_config) .build() .await?; } ``` ### Configure an Alternative Flex Docker Image To use a `flex` Docker image from another source, instead of the provided default, the configuration builder provides an `image_name()` method to define it explicitly. To configure an alternative Flex Docker image, update your `FlexConfig::builder()` definition as in this example: ```rust // Configure the Flex service let flex_config = FlexConfig::builder() .image_name("myrepo/flex-gateway") // Custom image name setting .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); ``` > [!NOTE] Run `make test` to ensure proper configuration. ### Flex Service Endpoint Requests `Flex` service exposes endpoints with external base URLs dependent on the port. To access those URLs, the Flex service instance handle provides the `external_url()` method indexed by port, for example: ```rust use pdk_test::{pdk_test, TestComposite, port::Port}; use pdk_test::services::flex::Flex; const FLEX_PORT: Port = 8081; async fn build_composite() -> anyhow::Result { todo!("Configuration stuff comes here") } #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Invoke a helper composite builder function for simplicity let composite = build_composite().await?; // Get the Flex service handle let flex: Flex = composite.service()?; // Get the URL for our configured port let flex_url = flex.external_url(FLEX_PORT).unwrap(); let response = reqwest::get(format!("{flex_url}/hello")).await?; // Make assertions Ok(()) } ``` ### Combine Multiple Services Usually a PDK integration test includes a `Flex` service and at least one backend service. The following code is the default test generated when the custom policy is created: ```rust mod common; use httpmock::MockServer; use pdk_test::{pdk_test, TestComposite}; use pdk_test::port::Port; use pdk_test::services::flex::{FlexConfig, Flex}; use pdk_test::services::httpmock::{HttpMockConfig, HttpMock}; use common::*; // Directory with the configurations for the `hello` test. const HELLO_CONFIG_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/requests/hello"); // Flex port for the internal test network const FLEX_PORT: Port = 8081; // This integration test shows how to build a test to compose a local-flex instance // with a MockServer backend #[pdk_test] async fn hello() -> anyhow::Result<()> { // Configure an HttpMock service let httpmock_config = HttpMockConfig::builder() .port(80) .version("latest") .hostname("backend") .build(); // Configure a policy for the API let policy_config = PolicyConfig::builder() .name(POLICY_NAME) .configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60})) .build(); // Configure the API to deploy to the Flex let api_config = ApiConfig::builder() .name("ingress-http") .upstream(&httpmock_config) .path("/anything/echo/") .port(FLEX_PORT) .policies([policy_config]) .build(); // Configure the Flex service let flex_config = FlexConfig::builder() .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); // Compose the services let composite = TestComposite::builder() .with_service(flex_config) .with_service(httpmock_config) .build() .await?; // Get a handle to the Flex service let flex: Flex = composite.service()?; // Get an external URL to point the Flex service let flex_url = flex.external_url(FLEX_PORT).unwrap(); // Get a handle to the HttpMock service let httpmock: HttpMock = composite.service()?; // Create a MockServer let mock_server = MockServer::connect_async(httpmock.socket()).await; // Mock a /hello request mock_server.mock_async(|when, then| { when.path_contains("/hello"); then.status(202).body("World!"); }).await; // Perform an actual request let response = reqwest::get(format!("{flex_url}/hello")).await?; // Assert on the response assert_eq!(response.status(), 202); Ok(()) } ``` ## Review Service Logs After an integration test fails, you can view the service logs to find errors. To improve the debugging experience, there is a dedicated service log in each test folder at `/target/pdk-test///.log`. For the example, the `say_hello` test has the following service log: ```none ├── Cargo.lock ├── Cargo.toml ├── playground ├── src ├── tests └── target └── pdk-test └── requests └── say_hello └── .log ``` ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.4/policies-pdk-debug-local) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.4/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.5 --- # Writing Integration Tests > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides an automated testing framework to detect integration regressions in your custom policy. The integration testing framework provided by PDK only supports Flex Gateway running in Local Mode in a Docker container. If you plan to deploy or policy to Flex Gateway running in Connected Mode or to a different platform, you should still first test your policy in PDK by using Flex Gateway running in Local Mode in a Docker container. > [!IMPORTANT] You can run Flex Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Flex Gateway does not support Windows in production environments. To test your policy, complete the following tasks: 1. Review [Before You Begin](#before-you-begin). 2. Review [Integration Tests Directory Structure](#structure). 3. [Register a Flex Gateway Instance in Local Mode](#register). 4. [Configure Your Custom Policy](#configure-your-custom-policy). 5. [Create a Test Function](#create-a-test-function). 6. [Run an Integration Test](#run-integration-test). 7. [Configure Services for Integration Testing](#configure-services-for-integration-testing). 8. [Review Service Logs](#review-service-logs). ## Before You Begin Ensure that you have: - [Installed Docker](https://www.docker.com/) ## Integration Tests Directory Structure By default, the `/tests` directory contains the following files: tests ├── requests.rs └── common └── mod.rs └── config └── logging.yaml └── registration.yaml The `/tests` directory contains the integration tests. By default, the folder contains: - `requests.rs` file: An individual test module and executable. - `common/mod.rs` file: A test module that contains functionalities, API configurations, and policy configurations that must be included in every integration test module. ## Register a Flex Gateway Instance in Local Mode To begin using the `make test` command to debug your custom policy, register a Flex Gateway in Local Mode. For the `make test` command to work, a Flex Gateway `registration.yaml` file must exist in the `/tests/config` directory. Create this file by running the registration command in the directory, or move a `registration.yaml` file of a previously registered Flex Gateway to the directory. To register Flex Gateway, see: - [Register and Run with a Username and Password in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-up#docker) - [Register and Run with a Connected App in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-app#docker) - [Register and Run with a Token in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-token#docker) > [!IMPORTANT] Run only the registration command. Do not run the Docker start command because the > `make test` command completes this step. Create a different registration file on each device testing the policy. The registration file is ignored for storage in remote repositories and is listed in the `.gitignore` file located at the root of the project directory. ## Configure Your Custom Policy Each test function requires the configuration of the API and policies for that request. To configure the custom policy: 1. Print the policy ID by running the `show-policy-ref-name`: ```ssh make show-policy-ref-name ``` 2. Copy the result. 3. Override `{{project-name}}` in `common/mod.rs` with your policy ID, for example: ```rust pub const POLICY_NAME: &str = ""; ``` 4. Configure the policy’s configuration parameters. To find your configuration parameters, see the `gcl.yaml` file. ## Create a Test Function Add a new test module by placing a new test function in an existing test module, for example `/tests/requests.rs`. PDK test functions are `async` functions decorated with the `#[pdk_test]` attribute: ```rust use pdk_test::pdk_test; #[pdk_test] async fn say_hello() { } ``` > [!NOTE] Because the body is empty, this test function never fails. Run `make test` to ensure > everything is working fine. ## Run an Integration Test To run the integrations tests modules in the `/tests` folder, execute the `make test` command: ```ssh make test ``` Run this test as you add additional features to your integration test to ensure proper configuration. > [!NOTE] The `make test` command compiles the policy before running the integration tests. ## Configure Services for Integration Testing PDK integration tests contain a composite of services running inside a Docker network. You can register service instances in a `TestComposite` object. Every service has a configuration, hostname, and instance. The `pdk-test` crate contains all the functionality for writing integration tests for custom policies in PDK and is included in the `[dev-dependencies]` section of the `Cargo.toml` file. ### Supported Services PDK’s test library supports the following services:
ServiceDescription

Flex

Flex Gateway service instance.

httpmock

Service binding to the Rust’s httpmock server.

The supported services cover the majority of use cases for integration testing. It is not possible to define different types of service. ### Configure an httpmock Service `httpmock` is a mock server that enables you to write request mocks in Rust. Configure an [httpmock](https://crates.io/crates/httpmock) service by using an `HttpMockConfig` value. It is a best practice to return a `Result` from the test function. The [anyhow](https://crates.io/crates/anyhow) Rust crate enables you to return different default error types. To configure an `httpmock` service, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::HttpMockConfig; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HttpMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .port(80) // Port where the service will accept requests .build(); // Register HTTPBin service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .build() .await?; Ok(()) } ``` > [!NOTE] If the Docker engine is properly configured, this test passes. Run `make test` to ensure > proper configuration. ### Configure an Alternative httpmock Docker Image To use an `httpmock` Docker image from another source, instead of the provided default, the configuration builder provides an `image_name()` method to define it explicitly. To configure an alternative `httpmock` Docker image, update your `HttpMockConfig::builder()` definition as in this example: ```rust // Configure HttpMock service let backend_config = HttpMockConfig::builder() .image_name("myrepo/httpmock") // Custom image name setting .hostname("backend") .port(80) // Port where the service will accept requests .build(); ``` ### Get a Service’s Handle Every configured service instance in the composite has a handle for custom interaction. The handle returns the sockets where the service endpoints are available. To find a service’s handle, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::{HttpMock, HttpMockConfig}; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HTTPMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .build(); // Register HTTPMock service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .port(80) // Port where the service accepts requests .build() .await?; // Get the httpmock handle let httpmock: HttpMock = composite.service()?; Ok(()) } ``` > [!NOTE] If the `httpmock` instance is properly configured, this test passes. Run `make test` to > ensure proper configuration. ### HTTP Endpoint Requests To mock endpoints, use the [httpmock When/Then API](https://docs.rs/httpmock/latest/httpmock/#whenthen-api). After mocking the endpoint, use an HTTP client to make endpoint requests. The [reqwest](https://crates.io/crates/reqwest/) crate offers the most comprehensive and flexible Rust HTTP client. To mock endpoints and make requests, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::{HttpMock, HttpMockConfig}; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HttpMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .port(80) // Port where the service will accept requests .build(); // Register HTTPBin service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .build() .await?; // Get the httpmock handle let httpmock: HttpMock = composite.service()?; // Connect the mock server let mock_server = httpmock::MockServer::connect_async(httpmock.socket()).await; // Configure the endpoint mocks mock_server.mock_async(|when, then| { when.path_contains("/hello"); then.status(202).body("World!"); }).await; let base_url = mock_server.base_url(); // Hit the endpoint let response = reqwest::get(format!("{base_url}/hello")).await?; // Assert on response assert_eq!(response.status(), 202); assert_eq!(response.text().await?, "World!"); Ok(()) } ``` > [!NOTE] Run `make test` to ensure proper configuration. ### Configure a Flex Service Instance Configure a `Flex` service by registering an instance of the `FlexConfig` struct in `TestComposite`. To complete the `FlexConfig` instance, you must also define a `ApiConfig` and `PolicyConfig` instance. The `FlexConfig` struct has the following properties:
PropertyContent

version

Flex Gateway version to test.

image_name

Flex Gateway Docker image name, by default, "mulesoft/flex-gateway".

hostname

Hostname of the Flex service, by default, "local-flex".

config_mounts

A map of local directories where the Flex service finds configuration files. The POLICY_DIR and COMMON_CONFIG_DIR constants are defined in the common/mod.rs module by default. If your test requires further configuration, add a directory with the specific configuration for the test functions.

with_api

The ApiConfiguration of the API deployed to the Flex service instance. Call multiple times to configure multiple APIs.

ports

List of ports where the Flex service listens for requests. If any of your configuration directories included in config_mount directories expose an API, the port must match the ports configured in the spec.address property.

The `ApiConfig` has the following properties:
PropertyContent

name

Name of the API.

upstream

The reference to the upstream service.

path

Path to which the upstream requests are sent.

port

Ports where the API listens for requests.

policies

A List of PolicyConfig instances applied to the API.

The `PolicyConfig` has the following properties:
PropertyContent

name

Policy to apply.

configuration

Parameters for the policy.

The following code example defines a complete `Flex` service: ```rust mod common; use common::*; use pdk_test::{pdk_test, TestComposite}; use pdk_test::port::Port; use pdk_test::services::flex::FlexConfig; // Port where Flex listens for requests const FLEX_PORT: Port = 8081; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure an upstream service for the API let httpmock_config = HttpMockConfig::builder() .port(80) .version("latest") .hostname("backend") .build(); // Configure a policy for the API let policy_config = PolicyConfig::builder() .name(POLICY_NAME) .configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60})) .build(); // Configure the API to deploy to the Flex let api_config = ApiConfig::builder() .name("ingress-http") .upstream(&httpmock_config) .path("/anything/echo/") .port(FLEX_PORT) .policies([policy_config]) .build(); // Configure the Flex service let flex_config = FlexConfig::builder() .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); let composite = TestComposite::builder() .with_service(flex_config) .with_service(httpmock_config) .build() .await?; } ``` ### Configure an Alternative Flex Docker Image To use a `flex` Docker image from another source, instead of the provided default, the configuration builder provides an `image_name()` method to define it explicitly. To configure an alternative Flex Docker image, update your `FlexConfig::builder()` definition as in this example: ```rust // Configure the Flex service let flex_config = FlexConfig::builder() .image_name("myrepo/flex-gateway") // Custom image name setting .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); ``` > [!NOTE] Run `make test` to ensure proper configuration. ### Flex Service Endpoint Requests `Flex` service exposes endpoints with external base URLs dependent on the port. To access those URLs, the Flex service instance handle provides the `external_url()` method indexed by port, for example: ```rust use pdk_test::{pdk_test, TestComposite, port::Port}; use pdk_test::services::flex::Flex; const FLEX_PORT: Port = 8081; async fn build_composite() -> anyhow::Result { todo!("Configuration stuff comes here") } #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Invoke a helper composite builder function for simplicity let composite = build_composite().await?; // Get the Flex service handle let flex: Flex = composite.service()?; // Get the URL for our configured port let flex_url = flex.external_url(FLEX_PORT).unwrap(); let response = reqwest::get(format!("{flex_url}/hello")).await?; // Make assertions Ok(()) } ``` ### Combine Multiple Services Usually a PDK integration test includes a `Flex` service and at least one backend service. The following code is the default test generated when the custom policy is created: ```rust mod common; use httpmock::MockServer; use pdk_test::{pdk_test, TestComposite}; use pdk_test::port::Port; use pdk_test::services::flex::{FlexConfig, Flex}; use pdk_test::services::httpmock::{HttpMockConfig, HttpMock}; use common::*; // Directory with the configurations for the `hello` test. const HELLO_CONFIG_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/requests/hello"); // Flex port for the internal test network const FLEX_PORT: Port = 8081; // This integration test shows how to build a test to compose a local-flex instance // with a MockServer backend #[pdk_test] async fn hello() -> anyhow::Result<()> { // Configure an HttpMock service let httpmock_config = HttpMockConfig::builder() .port(80) .version("latest") .hostname("backend") .build(); // Configure a policy for the API let policy_config = PolicyConfig::builder() .name(POLICY_NAME) .configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60})) .build(); // Configure the API to deploy to the Flex let api_config = ApiConfig::builder() .name("ingress-http") .upstream(&httpmock_config) .path("/anything/echo/") .port(FLEX_PORT) .policies([policy_config]) .build(); // Configure the Flex service let flex_config = FlexConfig::builder() .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); // Compose the services let composite = TestComposite::builder() .with_service(flex_config) .with_service(httpmock_config) .build() .await?; // Get a handle to the Flex service let flex: Flex = composite.service()?; // Get an external URL to point the Flex service let flex_url = flex.external_url(FLEX_PORT).unwrap(); // Get a handle to the HttpMock service let httpmock: HttpMock = composite.service()?; // Create a MockServer let mock_server = MockServer::connect_async(httpmock.socket()).await; // Mock a /hello request mock_server.mock_async(|when, then| { when.path_contains("/hello"); then.status(202).body("World!"); }).await; // Perform an actual request let response = reqwest::get(format!("{flex_url}/hello")).await?; // Assert on the response assert_eq!(response.status(), 202); Ok(()) } ``` ## Review Service Logs After an integration test fails, you can view the service logs to find errors. To improve the debugging experience, there is a dedicated service log in each test folder at `/target/pdk-test///.log`. For the example, the `say_hello` test has the following service log: ```none ├── Cargo.lock ├── Cargo.toml ├── playground ├── src ├── tests └── target └── pdk-test └── requests └── say_hello └── .log ``` ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.5/policies-pdk-debug-local) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.5/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.6 --- # Writing Integration Tests > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides an automated testing framework to detect integration regressions in your custom policy. The integration testing framework provided by PDK only supports Flex Gateway running in Local Mode in a Docker container. If you plan to deploy or policy to Flex Gateway running in Connected Mode or to a different platform, you should still first test your policy in PDK by using Flex Gateway running in Local Mode in a Docker container. > [!IMPORTANT] You can run Flex Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Flex Gateway does not support Windows in production environments. To test your policy, complete the following tasks: 1. Review [Before You Begin](#before-you-begin). 2. Review [Integration Tests Directory Structure](#structure). 3. [Register a Flex Gateway Instance in Local Mode](#register). 4. [Configure Your Custom Policy](#configure-your-custom-policy). 5. [Create a Test Function](#create-a-test-function). 6. [Run an Integration Test](#run-integration-test). 7. [Configure Services for Integration Testing](#configure-services-for-integration-testing). 8. [Review Service Logs](#review-service-logs). ## Before You Begin Ensure that you have: - [Installed Docker](https://www.docker.com/) ## Integration Tests Directory Structure By default, the `/tests` directory contains the following files: tests ├── requests.rs └── common └── mod.rs └── config └── logging.yaml └── registration.yaml The `/tests` directory contains the integration tests. By default, the folder contains: - `requests.rs` file: An individual test module and executable. - `common/mod.rs` file: A test module that contains functionalities, API configurations, and policy configurations that must be included in every integration test module. ## Register a Flex Gateway Instance in Local Mode To begin using the `make test` command to debug your custom policy, register a Flex Gateway in Local Mode. For the `make test` command to work, a Flex Gateway `registration.yaml` file must exist in the `/tests/config` directory. Create this file by running the registration command in the directory, or move a `registration.yaml` file of a previously registered Flex Gateway to the directory. To register Flex Gateway, see: - [Register and Run with a Username and Password in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-up#docker) - [Register and Run with a Connected App in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-app#docker) - [Register and Run with a Token in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-token#docker) > [!IMPORTANT] Run only the registration command. Do not run the Docker start command because the > `make test` command completes this step. Create a different registration file on each device testing the policy. The registration file is ignored for storage in remote repositories and is listed in the `.gitignore` file located at the root of the project directory. ## Configure Your Custom Policy Each test function requires the configuration of the API and policies for that request. To configure the custom policy: 1. Print the policy ID by running the `show-policy-ref-name`: ```ssh make show-policy-ref-name ``` 2. Copy the result. 3. Override `{{project-name}}` in `common/mod.rs` with your policy ID, for example: ```rust pub const POLICY_NAME: &str = ""; ``` 4. Configure the policy’s configuration parameters. To find your configuration parameters, see the `gcl.yaml` file. ## Create a Test Function Add a new test module by placing a new test function in an existing test module, for example `/tests/requests.rs`. PDK test functions are `async` functions decorated with the `#[pdk_test]` attribute: ```rust use pdk_test::pdk_test; #[pdk_test] async fn say_hello() { } ``` > [!NOTE] Because the body is empty, this test function never fails. Run `make test` to ensure > everything is working fine. ## Run an Integration Test To run the integrations tests modules in the `/tests` folder, execute the `make test` command: ```ssh make test ``` Run this test as you add additional features to your integration test to ensure proper configuration. > [!NOTE] The `make test` command compiles the policy before running the integration tests. ## Configure Services for Integration Testing PDK integration tests contain a composite of services running inside a Docker network. You can register service instances in a `TestComposite` object. Every service has a configuration, hostname, and instance. The `pdk-test` crate contains all the functionality for writing integration tests for custom policies in PDK and is included in the `[dev-dependencies]` section of the `Cargo.toml` file. ### Supported Services PDK’s test library supports the following services:
ServiceDescription

Flex

Flex Gateway service instance.

httpmock

Service binding to the Rust’s httpmock server.

The supported services cover the majority of use cases for integration testing. It is not possible to define different types of service. ### Configure an httpmock Service `httpmock` is a mock server that enables you to write request mocks in Rust. Configure an [httpmock](https://crates.io/crates/httpmock) service by using an `HttpMockConfig` value. It is a best practice to return a `Result` from the test function. The [anyhow](https://crates.io/crates/anyhow) Rust crate enables you to return different default error types. To configure an `httpmock` service, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::HttpMockConfig; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HttpMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .port(80) // Port where the service will accept requests .build(); // Register HTTPBin service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .build() .await?; Ok(()) } ``` > [!NOTE] If the Docker engine is properly configured, this test passes. Run `make test` to ensure > proper configuration. ### Configure an Alternative httpmock Docker Image To use an `httpmock` Docker image from another source, instead of the provided default, the configuration builder provides an `image_name()` method to define it explicitly. To configure an alternative `httpmock` Docker image, update your `HttpMockConfig::builder()` definition as in this example: ```rust // Configure HttpMock service let backend_config = HttpMockConfig::builder() .image_name("myrepo/httpmock") // Custom image name setting .hostname("backend") .port(80) // Port where the service will accept requests .build(); ``` ### Get a Service’s Handle Every configured service instance in the composite has a handle for custom interaction. The handle returns the sockets where the service endpoints are available. To find a service’s handle, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::{HttpMock, HttpMockConfig}; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HTTPMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .build(); // Register HTTPMock service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .port(80) // Port where the service accepts requests .build() .await?; // Get the httpmock handle let httpmock: HttpMock = composite.service()?; Ok(()) } ``` > [!NOTE] If the `httpmock` instance is properly configured, this test passes. Run `make test` to > ensure proper configuration. ### HTTP Endpoint Requests To mock endpoints, use the [httpmock When/Then API](https://docs.rs/httpmock/latest/httpmock/#whenthen-api). After mocking the endpoint, use an HTTP client to make endpoint requests. The [reqwest](https://crates.io/crates/reqwest/) crate offers the most comprehensive and flexible Rust HTTP client. To mock endpoints and make requests, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::{HttpMock, HttpMockConfig}; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HttpMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .port(80) // Port where the service will accept requests .build(); // Register HTTPBin service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .build() .await?; // Get the httpmock handle let httpmock: HttpMock = composite.service()?; // Connect the mock server let mock_server = httpmock::MockServer::connect_async(httpmock.socket()).await; // Configure the endpoint mocks mock_server.mock_async(|when, then| { when.path_contains("/hello"); then.status(202).body("World!"); }).await; let base_url = mock_server.base_url(); // Hit the endpoint let response = reqwest::get(format!("{base_url}/hello")).await?; // Assert on response assert_eq!(response.status(), 202); assert_eq!(response.text().await?, "World!"); Ok(()) } ``` > [!NOTE] Run `make test` to ensure proper configuration. ### Configure a Flex Service Instance Configure a `Flex` service by registering an instance of the `FlexConfig` struct in `TestComposite`. To complete the `FlexConfig` instance, you must also define a `ApiConfig` and `PolicyConfig` instance. The `FlexConfig` struct has the following properties:
PropertyContent

version

Flex Gateway version to test.

image_name

Flex Gateway Docker image name, by default, "mulesoft/flex-gateway".

hostname

Hostname of the Flex service, by default, "local-flex".

config_mounts

A map of local directories where the Flex service finds configuration files. The POLICY_DIR and COMMON_CONFIG_DIR constants are defined in the common/mod.rs module by default. If your test requires further configuration, add a directory with the specific configuration for the test functions.

with_api

The ApiConfiguration of the API deployed to the Flex service instance. Call multiple times to configure multiple APIs.

ports

List of ports where the Flex service listens for requests. If any of your configuration directories included in config_mount directories expose an API, the port must match the ports configured in the spec.address property.

The `ApiConfig` has the following properties:
PropertyContent

name

Name of the API.

upstream

The reference to the upstream service.

path

Path to which the upstream requests are sent.

port

Ports where the API listens for requests.

policies

A List of PolicyConfig instances applied to the API.

The `PolicyConfig` has the following properties:
PropertyContent

name

Policy to apply.

configuration

Parameters for the policy.

The following code example defines a complete `Flex` service: ```rust mod common; use common::*; use pdk_test::{pdk_test, TestComposite}; use pdk_test::port::Port; use pdk_test::services::flex::FlexConfig; // Port where Flex listens for requests const FLEX_PORT: Port = 8081; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure an upstream service for the API let httpmock_config = HttpMockConfig::builder() .port(80) .version("latest") .hostname("backend") .build(); // Configure a policy for the API let policy_config = PolicyConfig::builder() .name(POLICY_NAME) .configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60})) .build(); // Configure the API to deploy to the Flex let api_config = ApiConfig::builder() .name("ingress-http") .upstream(&httpmock_config) .path("/anything/echo/") .port(FLEX_PORT) .policies([policy_config]) .build(); // Configure the Flex service let flex_config = FlexConfig::builder() .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); let composite = TestComposite::builder() .with_service(flex_config) .with_service(httpmock_config) .build() .await?; } ``` ### Configure an Alternative Flex Docker Image To use a `flex` Docker image from another source, instead of the provided default, the configuration builder provides an `image_name()` method to define it explicitly. To configure an alternative Flex Docker image, update your `FlexConfig::builder()` definition as in this example: ```rust // Configure the Flex service let flex_config = FlexConfig::builder() .image_name("myrepo/flex-gateway") // Custom image name setting .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); ``` > [!NOTE] Run `make test` to ensure proper configuration. ### Flex Service Endpoint Requests `Flex` service exposes endpoints with external base URLs dependent on the port. To access those URLs, the Flex service instance handle provides the `external_url()` method indexed by port, for example: ```rust use pdk_test::{pdk_test, TestComposite, port::Port}; use pdk_test::services::flex::Flex; const FLEX_PORT: Port = 8081; async fn build_composite() -> anyhow::Result { todo!("Configuration stuff comes here") } #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Invoke a helper composite builder function for simplicity let composite = build_composite().await?; // Get the Flex service handle let flex: Flex = composite.service()?; // Get the URL for our configured port let flex_url = flex.external_url(FLEX_PORT).unwrap(); let response = reqwest::get(format!("{flex_url}/hello")).await?; // Make assertions Ok(()) } ``` ### Combine Multiple Services Usually a PDK integration test includes a `Flex` service and at least one backend service. The following code is the default test generated when the custom policy is created: ```rust mod common; use httpmock::MockServer; use pdk_test::{pdk_test, TestComposite}; use pdk_test::port::Port; use pdk_test::services::flex::{FlexConfig, Flex}; use pdk_test::services::httpmock::{HttpMockConfig, HttpMock}; use common::*; // Directory with the configurations for the `hello` test. const HELLO_CONFIG_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/requests/hello"); // Flex port for the internal test network const FLEX_PORT: Port = 8081; // This integration test shows how to build a test to compose a local-flex instance // with a MockServer backend #[pdk_test] async fn hello() -> anyhow::Result<()> { // Configure an HttpMock service let httpmock_config = HttpMockConfig::builder() .port(80) .version("latest") .hostname("backend") .build(); // Configure a policy for the API let policy_config = PolicyConfig::builder() .name(POLICY_NAME) .configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60})) .build(); // Configure the API to deploy to the Flex let api_config = ApiConfig::builder() .name("ingress-http") .upstream(&httpmock_config) .path("/anything/echo/") .port(FLEX_PORT) .policies([policy_config]) .build(); // Configure the Flex service let flex_config = FlexConfig::builder() .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); // Compose the services let composite = TestComposite::builder() .with_service(flex_config) .with_service(httpmock_config) .build() .await?; // Get a handle to the Flex service let flex: Flex = composite.service()?; // Get an external URL to point the Flex service let flex_url = flex.external_url(FLEX_PORT).unwrap(); // Get a handle to the HttpMock service let httpmock: HttpMock = composite.service()?; // Create a MockServer let mock_server = MockServer::connect_async(httpmock.socket()).await; // Mock a /hello request mock_server.mock_async(|when, then| { when.path_contains("/hello"); then.status(202).body("World!"); }).await; // Perform an actual request let response = reqwest::get(format!("{flex_url}/hello")).await?; // Assert on the response assert_eq!(response.status(), 202); Ok(()) } ``` ## Review Service Logs After an integration test fails, you can view the service logs to find errors. To improve the debugging experience, there is a dedicated service log in each test folder at `/target/pdk-test///.log`. For the example, the `say_hello` test has the following service log: ```none ├── Cargo.lock ├── Cargo.toml ├── playground ├── src ├── tests └── target └── pdk-test └── requests └── say_hello └── .log ``` ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.6/policies-pdk-debug-local) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.6/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.7 --- # Writing Integration Tests > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Flex Gateway Policy Development Kit (PDK) provides an automated testing framework to detect integration regressions in your custom policy. The integration testing framework provided by PDK only supports Flex Gateway running in Local Mode in a Docker container. If you plan to deploy or policy to Flex Gateway running in Connected Mode or to a different platform, you should still first test your policy in PDK by using Flex Gateway running in Local Mode in a Docker container. > [!IMPORTANT] You can run Flex Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Flex Gateway does not support Windows in production environments. To test your policy, complete the following tasks: 1. Review [Before You Begin](#before-you-begin). 2. Review [Integration Tests Directory Structure](#structure). 3. [Register a Flex Gateway Instance in Local Mode](#register). 4. [Configure Your Custom Policy](#configure-your-custom-policy). 5. [Create a Test Function](#create-a-test-function). 6. [Run an Integration Test](#run-integration-test). 7. [Configure Services for Integration Testing](#configure-services-for-integration-testing). 8. [Review Service Logs](#review-service-logs). ## Before You Begin Ensure that you have: - [Installed Docker](https://www.docker.com/) ## Integration Tests Directory Structure By default, the `/tests` directory contains the following files: tests ├── requests.rs └── common └── mod.rs └── config └── logging.yaml └── registration.yaml The `/tests` directory contains the integration tests. By default, the folder contains: - `requests.rs` file: An individual test module and executable. - `common/mod.rs` file: A test module that contains functionalities, API configurations, and policy configurations that must be included in every integration test module. ## Register a Flex Gateway Instance in Local Mode To begin using the `make test` command to debug your custom policy, register a Flex Gateway in Local Mode. For the `make test` command to work, a Flex Gateway `registration.yaml` file must exist in the `/tests/config` directory. Create this file by running the registration command in the directory, or move a `registration.yaml` file of a previously registered Flex Gateway to the directory. To register Flex Gateway, see: - [Register and Run with a Username and Password in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-up#docker) - [Register and Run with a Connected App in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-app#docker) - [Register and Run with a Token in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-token#docker) > [!IMPORTANT] Run only the registration command. Do not run the Docker start command because the > `make test` command completes this step. Create a different registration file on each device testing the policy. The registration file is ignored for storage in remote repositories and is listed in the `.gitignore` file located at the root of the project directory. ## Configure Your Custom Policy Each test function requires the configuration of the API and policies for that request. To configure the custom policy: 1. Print the policy ID by running the `show-policy-ref-name`: ```ssh make show-policy-ref-name ``` 2. Copy the result. 3. Override `{{project-name}}` in `common/mod.rs` with your policy ID, for example: ```rust pub const POLICY_NAME: &str = ""; ``` 4. Configure the policy’s configuration parameters. To find your configuration parameters, see the `gcl.yaml` file. ## Create a Test Function Add a new test module by placing a new test function in an existing test module, for example `/tests/requests.rs`. PDK test functions are `async` functions decorated with the `#[pdk_test]` attribute: ```rust use pdk_test::pdk_test; #[pdk_test] async fn say_hello() { } ``` > [!NOTE] Because the body is empty, this test function never fails. Run `make test` to ensure > everything is working fine. ## Run an Integration Test To run the integrations tests modules in the `/tests` folder, execute the `make test` command: ```ssh make test ``` Run this test as you add additional features to your integration test to ensure proper configuration. > [!NOTE] The `make test` command compiles the policy before running the integration tests. ## Configure Services for Integration Testing PDK integration tests contain a composite of services running inside a Docker network. You can register service instances in a `TestComposite` object. Every service has a configuration, hostname, and instance. The `pdk-test` crate contains all the functionality for writing integration tests for custom policies in PDK and is included in the `[dev-dependencies]` section of the `Cargo.toml` file. ### Supported Services PDK’s test library supports the following services:
ServiceDescription

Flex

Flex Gateway service instance.

httpmock

Service binding to the Rust’s httpmock server.

The supported services cover the majority of use cases for integration testing. It is not possible to define different types of service. ### Configure an httpmock Service `httpmock` is a mock server that enables you to write request mocks in Rust. Configure an [httpmock](https://crates.io/crates/httpmock) service by using an `HttpMockConfig` value. It is a best practice to return a `Result` from the test function. The [anyhow](https://crates.io/crates/anyhow) Rust crate enables you to return different default error types. To configure an `httpmock` service, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::HttpMockConfig; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HttpMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .port(80) // Port where the service will accept requests .build(); // Register HTTPBin service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .build() .await?; Ok(()) } ``` > [!NOTE] If the Docker engine is properly configured, this test passes. Run `make test` to ensure > proper configuration. ### Configure an Alternative httpmock Docker Image To use an `httpmock` Docker image from another source, instead of the provided default, the configuration builder provides an `image_name()` method to define it explicitly. To configure an alternative `httpmock` Docker image, update your `HttpMockConfig::builder()` definition as in this example: ```rust // Configure HttpMock service let backend_config = HttpMockConfig::builder() .image_name("myrepo/httpmock") // Custom image name setting .hostname("backend") .port(80) // Port where the service will accept requests .build(); ``` ### Get a Service’s Handle Every configured service instance in the composite has a handle for custom interaction. The handle returns the sockets where the service endpoints are available. To find a service’s handle, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::{HttpMock, HttpMockConfig}; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HTTPMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .build(); // Register HTTPMock service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .port(80) // Port where the service accepts requests .build() .await?; // Get the httpmock handle let httpmock: HttpMock = composite.service()?; Ok(()) } ``` > [!NOTE] If the `httpmock` instance is properly configured, this test passes. Run `make test` to > ensure proper configuration. ### HTTP Endpoint Requests To mock endpoints, use the [httpmock When/Then API](https://docs.rs/httpmock/latest/httpmock/#whenthen-api). After mocking the endpoint, use an HTTP client to make endpoint requests. The [reqwest](https://crates.io/crates/reqwest/) crate offers the most comprehensive and flexible Rust HTTP client. To mock endpoints and make requests, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::{HttpMock, HttpMockConfig}; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HttpMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .port(80) // Port where the service will accept requests .build(); // Register HTTPBin service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .build() .await?; // Get the httpmock handle let httpmock: HttpMock = composite.service()?; // Connect the mock server let mock_server = httpmock::MockServer::connect_async(httpmock.socket()).await; // Configure the endpoint mocks mock_server.mock_async(|when, then| { when.path_contains("/hello"); then.status(202).body("World!"); }).await; let base_url = mock_server.base_url(); // Hit the endpoint let response = reqwest::get(format!("{base_url}/hello")).await?; // Assert on response assert_eq!(response.status(), 202); assert_eq!(response.text().await?, "World!"); Ok(()) } ``` > [!NOTE] Run `make test` to ensure proper configuration. ### Configure a Flex Service Instance Configure a `Flex` service by registering an instance of the `FlexConfig` struct in `TestComposite`. To complete the `FlexConfig` instance, you must also define a `ApiConfig` and `PolicyConfig` instance. The `FlexConfig` struct has the following properties:
PropertyContent

version

Flex Gateway version to test.

image_name

Flex Gateway Docker image name, by default, "mulesoft/flex-gateway".

hostname

Hostname of the Flex service, by default, "local-flex".

config_mounts

A map of local directories where the Flex service finds configuration files. The POLICY_DIR and COMMON_CONFIG_DIR constants are defined in the common/mod.rs module by default. If your test requires further configuration, add a directory with the specific configuration for the test functions.

with_api

The ApiConfiguration of the API deployed to the Flex service instance. Call multiple times to configure multiple APIs.

ports

List of ports where the Flex service listens for requests. If any of your configuration directories included in config_mount directories expose an API, the port must match the ports configured in the spec.address property.

The `ApiConfig` has the following properties:
PropertyContent

name

Name of the API.

upstream

The reference to the upstream service.

path

Path to which the upstream requests are sent.

port

Ports where the API listens for requests.

policies

A List of PolicyConfig instances applied to the API.

The `PolicyConfig` has the following properties:
PropertyContent

name

Policy to apply.

configuration

Parameters for the policy.

The following code example defines a complete `Flex` service: ```rust mod common; use common::*; use pdk_test::{pdk_test, TestComposite}; use pdk_test::port::Port; use pdk_test::services::flex::FlexConfig; // Port where Flex listens for requests const FLEX_PORT: Port = 8081; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure an upstream service for the API let httpmock_config = HttpMockConfig::builder() .port(80) .version("latest") .hostname("backend") .build(); // Configure a policy for the API let policy_config = PolicyConfig::builder() .name(POLICY_NAME) .configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60})) .build(); // Configure the API to deploy to the Flex let api_config = ApiConfig::builder() .name("ingress-http") .upstream(&httpmock_config) .path("/anything/echo/") .port(FLEX_PORT) .policies([policy_config]) .build(); // Configure the Flex service let flex_config = FlexConfig::builder() .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); let composite = TestComposite::builder() .with_service(flex_config) .with_service(httpmock_config) .build() .await?; } ``` ### Configure an Alternative Flex Docker Image To use a `flex` Docker image from another source, instead of the provided default, the configuration builder provides an `image_name()` method to define it explicitly. To configure an alternative Flex Docker image, update your `FlexConfig::builder()` definition as in this example: ```rust // Configure the Flex service let flex_config = FlexConfig::builder() .image_name("myrepo/flex-gateway") // Custom image name setting .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); ``` > [!NOTE] Run `make test` to ensure proper configuration. ### Flex Service Endpoint Requests `Flex` service exposes endpoints with external base URLs dependent on the port. To access those URLs, the Flex service instance handle provides the `external_url()` method indexed by port, for example: ```rust use pdk_test::{pdk_test, TestComposite, port::Port}; use pdk_test::services::flex::Flex; const FLEX_PORT: Port = 8081; async fn build_composite() -> anyhow::Result { todo!("Configuration stuff comes here") } #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Invoke a helper composite builder function for simplicity let composite = build_composite().await?; // Get the Flex service handle let flex: Flex = composite.service()?; // Get the URL for our configured port let flex_url = flex.external_url(FLEX_PORT).unwrap(); let response = reqwest::get(format!("{flex_url}/hello")).await?; // Make assertions Ok(()) } ``` ### Combine Multiple Services Usually a PDK integration test includes a `Flex` service and at least one backend service. The following code is the default test generated when the custom policy is created: ```rust mod common; use httpmock::MockServer; use pdk_test::{pdk_test, TestComposite}; use pdk_test::port::Port; use pdk_test::services::flex::{FlexConfig, Flex}; use pdk_test::services::httpmock::{HttpMockConfig, HttpMock}; use common::*; // Directory with the configurations for the `hello` test. const HELLO_CONFIG_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/requests/hello"); // Flex port for the internal test network const FLEX_PORT: Port = 8081; // This integration test shows how to build a test to compose a local-flex instance // with a MockServer backend #[pdk_test] async fn hello() -> anyhow::Result<()> { // Configure an HttpMock service let httpmock_config = HttpMockConfig::builder() .port(80) .version("latest") .hostname("backend") .build(); // Configure a policy for the API let policy_config = PolicyConfig::builder() .name(POLICY_NAME) .configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60})) .build(); // Configure the API to deploy to the Flex let api_config = ApiConfig::builder() .name("ingress-http") .upstream(&httpmock_config) .path("/anything/echo/") .port(FLEX_PORT) .policies([policy_config]) .build(); // Configure the Flex service let flex_config = FlexConfig::builder() .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); // Compose the services let composite = TestComposite::builder() .with_service(flex_config) .with_service(httpmock_config) .build() .await?; // Get a handle to the Flex service let flex: Flex = composite.service()?; // Get an external URL to point the Flex service let flex_url = flex.external_url(FLEX_PORT).unwrap(); // Get a handle to the HttpMock service let httpmock: HttpMock = composite.service()?; // Create a MockServer let mock_server = MockServer::connect_async(httpmock.socket()).await; // Mock a /hello request mock_server.mock_async(|when, then| { when.path_contains("/hello"); then.status(202).body("World!"); }).await; // Perform an actual request let response = reqwest::get(format!("{flex_url}/hello")).await?; // Assert on the response assert_eq!(response.status(), 202); Ok(()) } ``` ## Review Service Logs After an integration test fails, you can view the service logs to find errors. To improve the debugging experience, there is a dedicated service log in each test folder at `/target/pdk-test///.log`. For the example, the `say_hello` test has the following service log: ```none ├── Cargo.lock ├── Cargo.toml ├── playground ├── src ├── tests └── target └── pdk-test └── requests └── say_hello └── .log ``` ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.7/policies-pdk-debug-local) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.7/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Writing Integration Tests > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) provides an automated testing framework to detect integration regressions in your custom policy. The integration testing framework provided by PDK only supports Omni Gateway running in Local Mode in a Docker container. If you plan to deploy or policy to Omni Gateway running in Connected Mode or to a different platform, you should still first test your policy in PDK by using Omni Gateway running in Local Mode in a Docker container. > [!IMPORTANT] You can run Omni Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Omni Gateway does not support Windows in production environments. To test your policy, complete the following tasks: 1. Review [Before You Begin](#before-you-begin). 2. Review [Integration Tests Directory Structure](#structure). 3. [Register an Omni Gateway Instance in Local Mode](#register). 4. [Configure Your Custom Policy](#configure-your-custom-policy). 5. [Create a Test Function](#create-a-test-function). 6. [Run an Integration Test](#run-integration-test). 7. [Configure Services for Integration Testing](#configure-services-for-integration-testing). 8. [Review Service Logs](#review-service-logs). ## Before You Begin Ensure that you have: - [Installed Docker](https://www.docker.com/) ## Integration Tests Directory Structure By default, the `/tests` directory contains the following files: tests ├── requests.rs └── common └── mod.rs └── config └── logging.yaml └── registration.yaml The `/tests` directory contains the integration tests. By default, the folder contains: - `requests.rs` file: An individual test module and executable. - `common/mod.rs` file: A test module that contains functionalities, API configurations, and policy configurations that must be included in every integration test module. ## Register an Omni Gateway Instance in Local Mode To begin using the `make test` command to debug your custom policy, register an Omni Gateway in Local Mode. For the `make test` command to work, an Omni Gateway `registration.yaml` file must exist in the `/tests/config` directory. Create this file by running the registration command in the directory, or move a `registration.yaml` file of a previously registered Omni Gateway to the directory. To register Omni Gateway, see: - [Register and Run with a Username and Password in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-up#docker) - [Register and Run with a Connected App in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-app#docker) - [Register and Run with a Token in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-token#docker) > [!IMPORTANT] Run only the registration command. Do not run the Docker start command because the > `make test` command completes this step. Create a different registration file on each device testing the policy. The registration file is ignored for storage in remote repositories and is listed in the `.gitignore` file located at the root of the project directory. ## Configure Your Custom Policy Each test function requires the configuration of the API and policies for that request. To configure the custom policy: 1. Print the policy ID by running the `show-policy-ref-name`: ```ssh make show-policy-ref-name ``` 2. Copy the result. 3. Override `{{project-name}}` in `common/mod.rs` with your policy ID, for example: ```rust pub const POLICY_NAME: &str = ""; ``` 4. Configure the policy’s configuration parameters. To find your configuration parameters, see the `gcl.yaml` file. ## Create a Test Function Add a new test module by placing a new test function in an existing test module, for example `/tests/requests.rs`. PDK test functions are `async` functions decorated with the `#[pdk_test]` attribute: ```rust use pdk_test::pdk_test; #[pdk_test] async fn say_hello() { } ``` > [!NOTE] Because the body is empty, this test function never fails. Run `make test` to ensure > everything is working fine. ## Run an Integration Test To run the integrations tests modules in the `/tests` folder, execute the `make test` command: ```ssh make test ``` Run this test as you add additional features to your integration test to ensure proper configuration. > [!NOTE] The `make test` command compiles the policy before running the integration tests. ## Configure Services for Integration Testing PDK integration tests contain a composite of services running inside a Docker network. You can register service instances in a `TestComposite` object. Every service has a configuration, hostname, and instance. The `pdk-test` crate contains all the functionality for writing integration tests for custom policies in PDK and is included in the `[dev-dependencies]` section of the `Cargo.toml` file. ### Supported Services PDK’s test library supports the following services:
ServiceDescription

Flex

Omni Gateway service instance.

httpmock

Service binding to the Rust’s httpmock server.

The supported services cover the majority of use cases for integration testing. It is not possible to define different types of service. ### Configure an httpmock Service `httpmock` is a mock server that enables you to write request mocks in Rust. Configure an [httpmock](https://crates.io/crates/httpmock) service by using an `HttpMockConfig` value. It is a best practice to return a `Result` from the test function. The [anyhow](https://crates.io/crates/anyhow) Rust crate enables you to return different default error types. To configure an `httpmock` service, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::HttpMockConfig; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HttpMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .port(80) // Port where the service will accept requests .build(); // Register HTTPBin service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .build() .await?; Ok(()) } ``` > [!NOTE] If the Docker engine is properly configured, this test passes. Run `make test` to ensure > proper configuration. ### Configure an Alternative httpmock Docker Image To use an `httpmock` Docker image from another source, instead of the provided default, the configuration builder provides an `image_name()` method to define it explicitly. To configure an alternative `httpmock` Docker image, update your `HttpMockConfig::builder()` definition as in this example: ```rust // Configure HttpMock service let backend_config = HttpMockConfig::builder() .image_name("myrepo/httpmock") // Custom image name setting .hostname("backend") .port(80) // Port where the service will accept requests .build(); ``` ### Get a Service’s Handle Every configured service instance in the composite has a handle for custom interaction. The handle returns the sockets where the service endpoints are available. To find a service’s handle, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::{HttpMock, HttpMockConfig}; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HTTPMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .build(); // Register HTTPMock service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .port(80) // Port where the service accepts requests .build() .await?; // Get the httpmock handle let httpmock: HttpMock = composite.service()?; Ok(()) } ``` > [!NOTE] If the `httpmock` instance is properly configured, this test passes. Run `make test` to > ensure proper configuration. ### HTTP Endpoint Requests To mock endpoints, use the [httpmock When/Then API](https://docs.rs/httpmock/latest/httpmock/#whenthen-api). After mocking the endpoint, use an HTTP client to make endpoint requests. The [reqwest](https://crates.io/crates/reqwest/) crate offers the most comprehensive and flexible Rust HTTP client. To mock endpoints and make requests, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::{HttpMock, HttpMockConfig}; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HttpMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .port(80) // Port where the service will accept requests .build(); // Register HTTPBin service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .build() .await?; // Get the httpmock handle let httpmock: HttpMock = composite.service()?; // Connect the mock server let mock_server = httpmock::MockServer::connect_async(httpmock.socket()).await; // Configure the endpoint mocks mock_server.mock_async(|when, then| { when.path_contains("/hello"); then.status(202).body("World!"); }).await; let base_url = mock_server.base_url(); // Hit the endpoint let response = reqwest::get(format!("{base_url}/hello")).await?; // Assert on response assert_eq!(response.status(), 202); assert_eq!(response.text().await?, "World!"); Ok(()) } ``` > [!NOTE] Run `make test` to ensure proper configuration. ### Configure an Omni Service Instance Configure a `Flex` service by registering an instance of the `FlexConfig` struct in `TestComposite`. To complete the `FlexConfig` instance, you must also define a `ApiConfig` and `PolicyConfig` instance. The `FlexConfig` struct has the following properties:
PropertyContent

version

Omni Gateway version to test.

image_name

Omni Gateway Docker image name, by default, "mulesoft/flex-gateway".

hostname

Hostname of the Flex service, by default, "local-flex".

config_mounts

A map of local directories where the Flex service finds configuration files. The POLICY_DIR and COMMON_CONFIG_DIR constants are defined in the common/mod.rs module by default. If your test requires further configuration, add a directory with the specific configuration for the test functions.

with_api

The ApiConfiguration of the API deployed to the Flex service instance. Call multiple times to configure multiple APIs.

ports

List of ports where the Flex service listens for requests. If any of your configuration directories included in config_mount directories expose an API, the port must match the ports configured in the spec.address property.

The `ApiConfig` has the following properties:
PropertyContent

name

Name of the API.

upstream

The reference to the upstream service.

path

Path to which the upstream requests are sent.

port

Ports where the API listens for requests.

policies

A List of PolicyConfig instances applied to the API.

The `PolicyConfig` has the following properties:
PropertyContent

name

Policy to apply.

configuration

Parameters for the policy.

The following code example defines a complete `Flex` service: ```rust mod common; use common::*; use pdk_test::{pdk_test, TestComposite}; use pdk_test::port::Port; use pdk_test::services::flex::FlexConfig; // Port where Flex listens for requests const FLEX_PORT: Port = 8081; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure an upstream service for the API let httpmock_config = HttpMockConfig::builder() .port(80) .version("latest") .hostname("backend") .build(); // Configure a policy for the API let policy_config = PolicyConfig::builder() .name(POLICY_NAME) .configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60})) .build(); // Configure the API to deploy to the Flex let api_config = ApiConfig::builder() .name("ingress-http") .upstream(&httpmock_config) .path("/anything/echo/") .port(FLEX_PORT) .policies([policy_config]) .build(); // Configure the Flex service let flex_config = FlexConfig::builder() .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); let composite = TestComposite::builder() .with_service(flex_config) .with_service(httpmock_config) .build() .await?; } ``` ### Configure an Alternative Omni Docker Image To use a `flex` Docker image from another source, instead of the provided default, the configuration builder provides an `image_name()` method to define it explicitly. To configure an alternative Omni Docker image, update your `FlexConfig::builder()` definition as in this example: ```rust // Configure the Flex service let flex_config = FlexConfig::builder() .image_name("myrepo/flex-gateway") // Custom image name setting .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); ``` > [!NOTE] Run `make test` to ensure proper configuration. ### Omni Service Endpoint Requests `Flex` service exposes endpoints with external base URLs dependent on the port. To access those URLs, the Omni service instance handle provides the `external_url()` method indexed by port, for example: ```rust use pdk_test::{pdk_test, TestComposite, port::Port}; use pdk_test::services::flex::Flex; const FLEX_PORT: Port = 8081; async fn build_composite() -> anyhow::Result { todo!("Configuration stuff comes here") } #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Invoke a helper composite builder function for simplicity let composite = build_composite().await?; // Get the Flex service handle let flex: Flex = composite.service()?; // Get the URL for our configured port let flex_url = flex.external_url(FLEX_PORT).unwrap(); let response = reqwest::get(format!("{flex_url}/hello")).await?; // Make assertions Ok(()) } ``` ### Combine Multiple Services Usually a PDK integration test includes a `Flex` service and at least one backend service. The following code is the default test generated when the custom policy is created: ```rust mod common; use httpmock::MockServer; use pdk_test::{pdk_test, TestComposite}; use pdk_test::port::Port; use pdk_test::services::flex::{FlexConfig, Flex}; use pdk_test::services::httpmock::{HttpMockConfig, HttpMock}; use common::*; // Directory with the configurations for the `hello` test. const HELLO_CONFIG_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/requests/hello"); // Flex port for the internal test network const FLEX_PORT: Port = 8081; // This integration test shows how to build a test to compose a local-flex instance // with a MockServer backend #[pdk_test] async fn hello() -> anyhow::Result<()> { // Configure an HttpMock service let httpmock_config = HttpMockConfig::builder() .port(80) .version("latest") .hostname("backend") .build(); // Configure a policy for the API let policy_config = PolicyConfig::builder() .name(POLICY_NAME) .configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60})) .build(); // Configure the API to deploy to the Flex let api_config = ApiConfig::builder() .name("ingress-http") .upstream(&httpmock_config) .path("/anything/echo/") .port(FLEX_PORT) .policies([policy_config]) .build(); // Configure the Flex service let flex_config = FlexConfig::builder() .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); // Compose the services let composite = TestComposite::builder() .with_service(flex_config) .with_service(httpmock_config) .build() .await?; // Get a handle to the Flex service let flex: Flex = composite.service()?; // Get an external URL to point the Flex service let flex_url = flex.external_url(FLEX_PORT).unwrap(); // Get a handle to the HttpMock service let httpmock: HttpMock = composite.service()?; // Create a MockServer let mock_server = MockServer::connect_async(httpmock.socket()).await; // Mock a /hello request mock_server.mock_async(|when, then| { when.path_contains("/hello"); then.status(202).body("World!"); }).await; // Perform an actual request let response = reqwest::get(format!("{flex_url}/hello")).await?; // Assert on the response assert_eq!(response.status(), 202); Ok(()) } ``` ## Review Service Logs After an integration test fails, you can view the service logs to find errors. To improve the debugging experience, there is a dedicated service log in each test folder at `/target/pdk-test///.log`. For the example, the `say_hello` test has the following service log: ```none ├── Cargo.lock ├── Cargo.toml ├── playground ├── src ├── tests └── target └── pdk-test └── requests └── say_hello └── .log ``` ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.8/policies-pdk-debug-local) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.8/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Writing Integration Tests > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) provides an automated testing framework to detect integration regressions in your custom policy. The integration testing framework provided by PDK only supports Omni Gateway running in Local Mode in a Docker container. If you plan to deploy or policy to Omni Gateway running in Connected Mode or to a different platform, you should still first test your policy in PDK by using Omni Gateway running in Local Mode in a Docker container. > [!IMPORTANT] You can run Omni Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Omni Gateway does not support Windows in production environments. To test your policy, complete the following tasks: 1. Review [Before You Begin](#before-you-begin). 2. Review [Integration Tests Directory Structure](#structure). 3. [Register an Omni Gateway Instance in Local Mode](#register). 4. [Configure Your Custom Policy](#configure-your-custom-policy). 5. [Create a Test Function](#create-a-test-function). 6. [Run an Integration Test](#run-integration-test). 7. [Configure Services for Integration Testing](#configure-services-for-integration-testing). 8. [Review Service Logs](#review-service-logs). ## Before You Begin Ensure that you have: - [Installed Docker](https://www.docker.com/) ## Integration Tests Directory Structure By default, the `/tests` directory contains the following files: tests ├── requests.rs └── common └── mod.rs └── config └── logging.yaml └── registration.yaml The `/tests` directory contains the integration tests. By default, the folder contains: - `requests.rs` file: An individual test module and executable. - `common/mod.rs` file: A test module that contains functionalities, API configurations, and policy configurations that must be included in every integration test module. ## Register an Omni Gateway Instance in Local Mode To begin using the `make test` command to debug your custom policy, register an Omni Gateway in Local Mode. For the `make test` command to work, an Omni Gateway `registration.yaml` file must exist in the `/tests/config` directory. Create this file by running the registration command in the directory, or move a `registration.yaml` file of a previously registered Omni Gateway to the directory. To register Omni Gateway, see: - [Register and Run with a Username and Password in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-up#docker) - [Register and Run with a Connected App in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-app#docker) - [Register and Run with a Token in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-token#docker) > [!IMPORTANT] Run only the registration command. Do not run the Docker start command because the > `make test` command completes this step. Create a different registration file on each device testing the policy. The registration file is ignored for storage in remote repositories and is listed in the `.gitignore` file located at the root of the project directory. ## Configure Your Custom Policy Each test function requires the configuration of the API and policies for that request. To configure the custom policy: 1. Print the policy ID by running the `show-policy-ref-name`: ```ssh make show-policy-ref-name ``` 2. Copy the result. 3. Override `{{project-name}}` in `common/mod.rs` with your policy ID, for example: ```rust pub const POLICY_NAME: &str = ""; ``` 4. Configure the policy’s configuration parameters. To find your configuration parameters, see the `gcl.yaml` file. ## Create a Test Function Add a new test module by placing a new test function in an existing test module, for example `/tests/requests.rs`. PDK test functions are `async` functions decorated with the `#[pdk_test]` attribute: ```rust use pdk_test::pdk_test; #[pdk_test] async fn say_hello() { } ``` > [!NOTE] Because the body is empty, this test function never fails. Run `make test` to ensure > everything is working fine. ## Run an Integration Test To run the integrations tests modules in the `/tests` folder, execute the `make test` command: ```ssh make test ``` Run this test as you add additional features to your integration test to ensure proper configuration. > [!NOTE] The `make test` command compiles the policy before running the integration tests. ## Configure Services for Integration Testing PDK integration tests contain a composite of services running inside a Docker network. You can register service instances in a `TestComposite` object. Every service has a configuration, hostname, and instance. The `pdk-test` crate contains all the functionality for writing integration tests for custom policies in PDK and is included in the `[dev-dependencies]` section of the `Cargo.toml` file. ### Supported Services PDK’s test library supports the following services:
ServiceDescription

Flex

Omni Gateway service instance.

httpmock

Service binding to the Rust’s httpmock server.

The supported services cover the majority of use cases for integration testing. It is not possible to define different types of service. ### Configure an httpmock Service `httpmock` is a mock server that enables you to write request mocks in Rust. Configure an [httpmock](https://crates.io/crates/httpmock) service by using an `HttpMockConfig` value. It is a best practice to return a `Result` from the test function. The [anyhow](https://crates.io/crates/anyhow) Rust crate enables you to return different default error types. To configure an `httpmock` service, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::HttpMockConfig; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HttpMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .port(80) // Port where the service will accept requests .build(); // Register HTTPBin service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .build() .await?; Ok(()) } ``` > [!NOTE] If the Docker engine is properly configured, this test passes. Run `make test` to ensure > proper configuration. ### Configure an Alternative httpmock Docker Image To use an `httpmock` Docker image from another source, instead of the provided default, the configuration builder provides an `image_name()` method to define it explicitly. To configure an alternative `httpmock` Docker image, update your `HttpMockConfig::builder()` definition as in this example: ```rust // Configure HttpMock service let backend_config = HttpMockConfig::builder() .image_name("myrepo/httpmock") // Custom image name setting .hostname("backend") .port(80) // Port where the service will accept requests .build(); ``` ### Get a Service’s Handle Every configured service instance in the composite has a handle for custom interaction. The handle returns the sockets where the service endpoints are available. To find a service’s handle, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::{HttpMock, HttpMockConfig}; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HTTPMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .build(); // Register HTTPMock service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .port(80) // Port where the service accepts requests .build() .await?; // Get the httpmock handle let httpmock: HttpMock = composite.service()?; Ok(()) } ``` > [!NOTE] If the `httpmock` instance is properly configured, this test passes. Run `make test` to > ensure proper configuration. ### HTTP Endpoint Requests To mock endpoints, use the [httpmock When/Then API](https://docs.rs/httpmock/latest/httpmock/#whenthen-api). After mocking the endpoint, use an HTTP client to make endpoint requests. The [reqwest](https://crates.io/crates/reqwest/) crate offers the most comprehensive and flexible Rust HTTP client. To mock endpoints and make requests, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::{HttpMock, HttpMockConfig}; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HttpMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .port(80) // Port where the service will accept requests .build(); // Register HTTPBin service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .build() .await?; // Get the httpmock handle let httpmock: HttpMock = composite.service()?; // Connect the mock server let mock_server = httpmock::MockServer::connect_async(httpmock.socket()).await; // Configure the endpoint mocks mock_server.mock_async(|when, then| { when.path_contains("/hello"); then.status(202).body("World!"); }).await; let base_url = mock_server.base_url(); // Hit the endpoint let response = reqwest::get(format!("{base_url}/hello")).await?; // Assert on response assert_eq!(response.status(), 202); assert_eq!(response.text().await?, "World!"); Ok(()) } ``` > [!NOTE] Run `make test` to ensure proper configuration. ### Configure an Omni Service Instance Configure a `Flex` service by registering an instance of the `FlexConfig` struct in `TestComposite`. To complete the `FlexConfig` instance, you must also define a `ApiConfig` and `PolicyConfig` instance. The `FlexConfig` struct has the following properties:
PropertyContent

version

Omni Gateway version to test.

image_name

Omni Gateway Docker image name, by default, "mulesoft/flex-gateway".

hostname

Hostname of the Flex service, by default, "local-flex".

config_mounts

A map of local directories where the Flex service finds configuration files. The POLICY_DIR and COMMON_CONFIG_DIR constants are defined in the common/mod.rs module by default. If your test requires further configuration, add a directory with the specific configuration for the test functions.

with_api

The ApiConfiguration of the API deployed to the Flex service instance. Call multiple times to configure multiple APIs.

ports

List of ports where the Flex service listens for requests. If any of your configuration directories included in config_mount directories expose an API, the port must match the ports configured in the spec.address property.

The `ApiConfig` has the following properties:
PropertyContent

name

Name of the API.

upstream

The reference to the upstream service.

path

Path to which the upstream requests are sent.

port

Ports where the API listens for requests.

policies

A List of PolicyConfig instances applied to the API.

The `PolicyConfig` has the following properties:
PropertyContent

name

Policy to apply.

configuration

Parameters for the policy.

The following code example defines a complete `Flex` service: ```rust mod common; use common::*; use pdk_test::{pdk_test, TestComposite}; use pdk_test::port::Port; use pdk_test::services::flex::FlexConfig; // Port where Flex listens for requests const FLEX_PORT: Port = 8081; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure an upstream service for the API let httpmock_config = HttpMockConfig::builder() .port(80) .version("latest") .hostname("backend") .build(); // Configure a policy for the API let policy_config = PolicyConfig::builder() .name(POLICY_NAME) .configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60})) .build(); // Configure the API to deploy to the Flex let api_config = ApiConfig::builder() .name("ingress-http") .upstream(&httpmock_config) .path("/anything/echo/") .port(FLEX_PORT) .policies([policy_config]) .build(); // Configure the Flex service let flex_config = FlexConfig::builder() .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); let composite = TestComposite::builder() .with_service(flex_config) .with_service(httpmock_config) .build() .await?; } ``` ### Configure an Alternative Omni Docker Image To use a `flex` Docker image from another source, instead of the provided default, the configuration builder provides an `image_name()` method to define it explicitly. To configure an alternative Omni Docker image, update your `FlexConfig::builder()` definition as in this example: ```rust // Configure the Flex service let flex_config = FlexConfig::builder() .image_name("myrepo/flex-gateway") // Custom image name setting .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); ``` > [!NOTE] Run `make test` to ensure proper configuration. ### Omni Service Endpoint Requests `Flex` service exposes endpoints with external base URLs dependent on the port. To access those URLs, the Omni service instance handle provides the `external_url()` method indexed by port, for example: ```rust use pdk_test::{pdk_test, TestComposite, port::Port}; use pdk_test::services::flex::Flex; const FLEX_PORT: Port = 8081; async fn build_composite() -> anyhow::Result { todo!("Configuration stuff comes here") } #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Invoke a helper composite builder function for simplicity let composite = build_composite().await?; // Get the Flex service handle let flex: Flex = composite.service()?; // Get the URL for our configured port let flex_url = flex.external_url(FLEX_PORT).unwrap(); let response = reqwest::get(format!("{flex_url}/hello")).await?; // Make assertions Ok(()) } ``` ### Combine Multiple Services Usually a PDK integration test includes a `Flex` service and at least one backend service. The following code is the default test generated when the custom policy is created: ```rust mod common; use httpmock::MockServer; use pdk_test::{pdk_test, TestComposite}; use pdk_test::port::Port; use pdk_test::services::flex::{FlexConfig, Flex}; use pdk_test::services::httpmock::{HttpMockConfig, HttpMock}; use common::*; // Directory with the configurations for the `hello` test. const HELLO_CONFIG_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/requests/hello"); // Flex port for the internal test network const FLEX_PORT: Port = 8081; // This integration test shows how to build a test to compose a local-flex instance // with a MockServer backend #[pdk_test] async fn hello() -> anyhow::Result<()> { // Configure an HttpMock service let httpmock_config = HttpMockConfig::builder() .port(80) .version("latest") .hostname("backend") .build(); // Configure a policy for the API let policy_config = PolicyConfig::builder() .name(POLICY_NAME) .configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60})) .build(); // Configure the API to deploy to the Flex let api_config = ApiConfig::builder() .name("ingress-http") .upstream(&httpmock_config) .path("/anything/echo/") .port(FLEX_PORT) .policies([policy_config]) .build(); // Configure the Flex service let flex_config = FlexConfig::builder() .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); // Compose the services let composite = TestComposite::builder() .with_service(flex_config) .with_service(httpmock_config) .build() .await?; // Get a handle to the Flex service let flex: Flex = composite.service()?; // Get an external URL to point the Flex service let flex_url = flex.external_url(FLEX_PORT).unwrap(); // Get a handle to the HttpMock service let httpmock: HttpMock = composite.service()?; // Create a MockServer let mock_server = MockServer::connect_async(httpmock.socket()).await; // Mock a /hello request mock_server.mock_async(|when, then| { when.path_contains("/hello"); then.status(202).body("World!"); }).await; // Perform an actual request let response = reqwest::get(format!("{flex_url}/hello")).await?; // Assert on the response assert_eq!(response.status(), 202); Ok(()) } ``` ## Review Service Logs After an integration test fails, you can view the service logs to find errors. To improve the debugging experience, there is a dedicated service log in each test folder at `/target/pdk-test///.log`. For the example, the `say_hello` test has the following service log: ```none ├── Cargo.lock ├── Cargo.toml ├── playground ├── src ├── tests └── target └── pdk-test └── requests └── say_hello └── .log ``` ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/1.9/policies-pdk-debug-local) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/1.9/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Writing Integration Tests > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Omni Gateway Policy Development Kit (PDK) provides an automated testing framework to detect integration regressions in your custom policy. The integration testing framework provided by PDK only supports Omni Gateway running in Local Mode in a Docker container. If you plan to deploy or policy to Omni Gateway running in Connected Mode or to a different platform, you should still first test your policy in PDK by using Omni Gateway running in Local Mode in a Docker container. > [!IMPORTANT] You can run Omni Gateway in Local Mode on Docker in Windows only to develop and test > your policies. However, Omni Gateway does not support Windows in production environments. To test your policy, complete the following tasks: 1. Review [Before You Begin](#before-you-begin). 2. Review [Integration Tests Directory Structure](#structure). 3. [Register an Omni Gateway Instance in Local Mode](#register). 4. [Configure Your Custom Policy](#configure-your-custom-policy). 5. [Create a Test Function](#create-a-test-function). 6. [Run an Integration Test](#run-integration-test). 7. [Configure Services for Integration Testing](#configure-services-for-integration-testing). 8. [Review Service Logs](#review-service-logs). ## Before You Begin Ensure that you have: - [Installed Docker](https://www.docker.com/) ## Integration Tests Directory Structure By default, the `/tests` directory contains the following files: tests ├── requests.rs └── common └── mod.rs └── config └── logging.yaml └── registration.yaml The `/tests` directory contains the integration tests. By default, the folder contains: - `requests.rs` file: An individual test module and executable. - `common/mod.rs` file: A test module that contains functionalities, API configurations, and policy configurations that must be included in every integration test module. ## Register an Omni Gateway Instance in Local Mode To begin using the `make test` command to debug your custom policy, register an Omni Gateway in Local Mode. For the `make test` command to work, an Omni Gateway `registration.yaml` file must exist in the `/tests/config` directory. Create this file by running the registration command in the directory, or move a `registration.yaml` file of a previously registered Omni Gateway to the directory. > [!NOTE] A registration file is generated automatically when you run integration tests if no > `registration.yaml` file is provided. To register Omni Gateway, see: - [Register and Run with a Username and Password in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-up#docker) - [Register and Run with a Connected App in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-app#docker) - [Register and Run with a Token in a Docker Container](https://docs.mulesoft.com/gateway/latest/local-reg-run-token#docker) > [!IMPORTANT] Run only the registration command. Do not run the Docker start command because the > `make test` command completes this step. Create a different registration file on each device testing the policy. The registration file is ignored for storage in remote repositories and is listed in the `.gitignore` file located at the root of the project directory. ## Configure Your Custom Policy Each test function requires the configuration of the API and policies for that request. To configure the custom policy: 1. Print the policy ID by running the `show-policy-ref-name`: ```ssh make show-policy-ref-name ``` 2. Copy the result. 3. Override `{{project-name}}` in `common/mod.rs` with your policy ID, for example: ```rust pub const POLICY_NAME: &str = ""; ``` 4. Configure the policy’s configuration parameters. To find your configuration parameters, see the `gcl.yaml` file. ## Create a Test Function Add a new test module by placing a new test function in an existing test module, for example `/tests/requests.rs`. PDK test functions are `async` functions decorated with the `#[pdk_test]` attribute: ```rust use pdk_test::pdk_test; #[pdk_test] async fn say_hello() { } ``` > [!NOTE] Because the body is empty, this test function never fails. Run `make test` to ensure > everything is working fine. ## Run an Integration Test To run the integrations tests modules in the `/tests` folder, execute the `make test` command: ```ssh make test ``` Run this test as you add additional features to your integration test to ensure proper configuration. > [!NOTE] The `make test` command compiles the policy before running the integration tests. To run a single test, pass the test name to the `TEST` parameter: ```ssh make test TEST= ``` ## Configure Services for Integration Testing PDK integration tests contain a composite of services running inside a Docker network. You can register service instances in a `TestComposite` object. Every service has a configuration, hostname, and instance. The `pdk-test` crate contains all the functionality for writing integration tests for custom policies in PDK and is included in the `[dev-dependencies]` section of the `Cargo.toml` file. ### Supported Services PDK’s test library supports the following services:
ServiceDescription

Flex

Omni Gateway service instance.

httpmock

Service binding to the Rust’s httpmock server.

The supported services cover the majority of use cases for integration testing. It is not possible to define different types of service. ### Configure an httpmock Service `httpmock` is a mock server that enables you to write request mocks in Rust. Configure an [httpmock](https://crates.io/crates/httpmock) service by using an `HttpMockConfig` value. It is a best practice to return a `Result` from the test function. The [anyhow](https://crates.io/crates/anyhow) Rust crate enables you to return different default error types. To configure an `httpmock` service, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::HttpMockConfig; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HttpMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .port(80) // Port where the service will accept requests .build(); // Register HTTPBin service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .build() .await?; Ok(()) } ``` > [!NOTE] If the Docker engine is properly configured, this test passes. Run `make test` to ensure > proper configuration. ### Configure an Alternative httpmock Docker Image To use an `httpmock` Docker image from another source, instead of the provided default, the configuration builder provides an `image_name()` method to define it explicitly. To configure an alternative `httpmock` Docker image, update your `HttpMockConfig::builder()` definition as in this example: ```rust // Configure HttpMock service let backend_config = HttpMockConfig::builder() .image_name("myrepo/httpmock") // Custom image name setting .hostname("backend") .port(80) // Port where the service will accept requests .build(); ``` ### Get a Service’s Handle Every configured service instance in the composite has a handle for custom interaction. The handle returns the sockets where the service endpoints are available. To find a service’s handle, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::{HttpMock, HttpMockConfig}; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HTTPMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .build(); // Register HTTPMock service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .port(80) // Port where the service accepts requests .build() .await?; // Get the httpmock handle let httpmock: HttpMock = composite.service()?; Ok(()) } ``` > [!NOTE] If the `httpmock` instance is properly configured, this test passes. Run `make test` to > ensure proper configuration. ### HTTP Endpoint Requests To mock endpoints, use the [httpmock When/Then API](https://docs.rs/httpmock/latest/httpmock/#whenthen-api). After mocking the endpoint, use an HTTP client to make endpoint requests. The [reqwest](https://crates.io/crates/reqwest/) crate offers the most comprehensive and flexible Rust HTTP client. To mock endpoints and make requests, see the following code example: ```rust use pdk_test::{pdk_test, TestComposite}; use pdk_test::services::httpmock::{HttpMock, HttpMockConfig}; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure HttpMock service let backend_config = HttpMockConfig::builder() .hostname("backend") .port(80) // Port where the service will accept requests .build(); // Register HTTPBin service and start the docker network let composite = TestComposite::builder() .with_service(backend_config) .build() .await?; // Get the httpmock handle let httpmock: HttpMock = composite.service()?; // Connect the mock server let mock_server = httpmock::MockServer::connect_async(httpmock.socket()).await; // Configure the endpoint mocks mock_server.mock_async(|when, then| { when.path_contains("/hello"); then.status(202).body("World!"); }).await; let base_url = mock_server.base_url(); // Hit the endpoint let response = reqwest::get(format!("{base_url}/hello")).await?; // Assert on response assert_eq!(response.status(), 202); assert_eq!(response.text().await?, "World!"); Ok(()) } ``` > [!NOTE] Run `make test` to ensure proper configuration. ### Configure an Omni Service Instance Configure a `Flex` service by registering an instance of the `FlexConfig` struct in `TestComposite`. To complete the `FlexConfig` instance, you must also define a `ApiConfig` and `PolicyConfig` instance. The `FlexConfig` struct has the following properties:
PropertyContent

version

Omni Gateway version to test.

image_name

Omni Gateway Docker image name, by default, "mulesoft/flex-gateway".

hostname

Hostname of the Flex service, by default, "local-flex".

config_mounts

A map of local directories where the Flex service finds configuration files. The POLICY_DIR and COMMON_CONFIG_DIR constants are defined in the common/mod.rs module by default. If your test requires further configuration, add a directory with the specific configuration for the test functions.

with_api

The ApiConfiguration of the API deployed to the Flex service instance. Call multiple times to configure multiple APIs.

ports

List of ports where the Flex service listens for requests. If any of your configuration directories included in config_mount directories expose an API, the port must match the ports configured in the spec.address property.

The `ApiConfig` has the following properties:
PropertyContent

name

Name of the API.

upstream

The reference to the upstream service.

path

Path to which the upstream requests are sent.

port

Ports where the API listens for requests.

policies

A List of PolicyConfig instances applied to the API.

The `PolicyConfig` has the following properties:
PropertyContent

name

Policy to apply.

configuration

Parameters for the policy.

The following code example defines a complete `Flex` service: ```rust mod common; use common::*; use pdk_test::{pdk_test, TestComposite}; use pdk_test::port::Port; use pdk_test::services::flex::FlexConfig; // Port where Flex listens for requests const FLEX_PORT: Port = 8081; #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Configure an upstream service for the API let httpmock_config = HttpMockConfig::builder() .port(80) .version("latest") .hostname("backend") .build(); // Configure a policy for the API let policy_config = PolicyConfig::builder() .name(POLICY_NAME) .configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60})) .build(); // Configure the API to deploy to the Flex let api_config = ApiConfig::builder() .name("ingress-http") .upstream(&httpmock_config) .path("/anything/echo/") .port(FLEX_PORT) .policies([policy_config]) .build(); // Configure the Flex service let flex_config = FlexConfig::builder() .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); let composite = TestComposite::builder() .with_service(flex_config) .with_service(httpmock_config) .build() .await?; } ``` ### Configure an Alternative Omni Docker Image To use a `flex` Docker image from another source, instead of the provided default, the configuration builder provides an `image_name()` method to define it explicitly. To configure an alternative Omni Docker image, update your `FlexConfig::builder()` definition as in this example: ```rust // Configure the Flex service let flex_config = FlexConfig::builder() .image_name("myrepo/flex-gateway") // Custom image name setting .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); ``` > [!NOTE] Run `make test` to ensure proper configuration. ### Omni Service Endpoint Requests `Flex` service exposes endpoints with external base URLs dependent on the port. To access those URLs, the Omni service instance handle provides the `external_url()` method indexed by port, for example: ```rust use pdk_test::{pdk_test, TestComposite, port::Port}; use pdk_test::services::flex::Flex; const FLEX_PORT: Port = 8081; async fn build_composite() -> anyhow::Result { todo!("Configuration stuff comes here") } #[pdk_test] async fn say_hello() -> anyhow::Result<()> { // Invoke a helper composite builder function for simplicity let composite = build_composite().await?; // Get the Flex service handle let flex: Flex = composite.service()?; // Get the URL for our configured port let flex_url = flex.external_url(FLEX_PORT).unwrap(); let response = reqwest::get(format!("{flex_url}/hello")).await?; // Make assertions Ok(()) } ``` ### Combine Multiple Services Usually a PDK integration test includes a `Flex` service and at least one backend service. The following code is the default test generated when the custom policy is created: ```rust mod common; use httpmock::MockServer; use pdk_test::{pdk_test, TestComposite}; use pdk_test::port::Port; use pdk_test::services::flex::{FlexConfig, Flex}; use pdk_test::services::httpmock::{HttpMockConfig, HttpMock}; use common::*; // Directory with the configurations for the `hello` test. const HELLO_CONFIG_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/requests/hello"); // Flex port for the internal test network const FLEX_PORT: Port = 8081; // This integration test shows how to build a test to compose a local-flex instance // with a MockServer backend #[pdk_test] async fn hello() -> anyhow::Result<()> { // Configure an HttpMock service let httpmock_config = HttpMockConfig::builder() .port(80) .version("latest") .hostname("backend") .build(); // Configure a policy for the API let policy_config = PolicyConfig::builder() .name(POLICY_NAME) .configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60})) .build(); // Configure the API to deploy to the Flex let api_config = ApiConfig::builder() .name("ingress-http") .upstream(&httpmock_config) .path("/anything/echo/") .port(FLEX_PORT) .policies([policy_config]) .build(); // Configure the Flex service let flex_config = FlexConfig::builder() .version("1.6.1") .hostname("local-flex") .config_mounts([ (POLICY_DIR, "policy"), (COMMON_CONFIG_DIR, "common") ]) .with_api(api_config) .build(); // Compose the services let composite = TestComposite::builder() .with_service(flex_config) .with_service(httpmock_config) .build() .await?; // Get a handle to the Flex service let flex: Flex = composite.service()?; // Get an external URL to point the Flex service let flex_url = flex.external_url(FLEX_PORT).unwrap(); // Get a handle to the HttpMock service let httpmock: HttpMock = composite.service()?; // Create a MockServer let mock_server = MockServer::connect_async(httpmock.socket()).await; // Mock a /hello request mock_server.mock_async(|when, then| { when.path_contains("/hello"); then.status(202).body("World!"); }).await; // Perform an actual request let response = reqwest::get(format!("{flex_url}/hello")).await?; // Assert on the response assert_eq!(response.status(), 202); Ok(()) } ``` ## Review Service Logs After an integration test fails, you can view the service logs to find errors. To improve the debugging experience, there is a dedicated service log in each test folder at `/target/pdk-test///.log`. For the example, the `say_hello` test has the following service log: ```none ├── Cargo.lock ├── Cargo.toml ├── playground ├── src ├── tests └── target └── pdk-test └── requests └── say_hello └── .log ``` ## See Also - [Debugging Custom Policies with the PDK Debugging Playground](https://docs.mulesoft.com/pdk/latest/policies-pdk-debug-local) - [PDK Troubleshooting](https://docs.mulesoft.com/pdk/latest/policies-pdk-troubleshooting) --- product: Omni Gateway Policy Development Kit (PDK) version: 1.8 --- # Writing Unit Tests > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the `pdk-unit` testing framework for Omni Gateway Policy Development Kit (PDK) custom policies to test the full request and response lifecycle of a policy without a running Envoy proxy, a WebAssembly runtime, or external infrastructure. To see example `pdk-unit` tests, browse the [PDK Custom Policy Examples](https://github.com/mulesoft/pdk-custom-policy-examples) on GitHub. Use `pdk-unit` when you need tests that are: - **Fast feedback**: Tests run as ordinary Rust unit tests completing in milliseconds. - **Deterministic**: No network, no containers, no race conditions. - **Full lifecycle coverage**: Exercises request headers, request body, response headers, and response body phases as the real `proxy-wasm` host does. - **Code coverage**: Policy code runs directly in the Rust environment, so it works with standard coverage tools such as `cargo-tarpaulin`. - **Debugging**: Tests run as native Rust code, so you can attach a debugger or profiler without extra setup. ## Enable pdk-unit Add `pdk-unit` as a dev-dependency in your policy’s `Cargo.toml`: ```toml [dev-dependencies] pdk-unit = { version = "1.8" } ``` ## Basic Request and Response Test To send a test request build a `UnitTest` with the `UnitTestBuilder`, send a `UnitHttpRequest`, and assert on the returned `UnitHttpResponse`. Headers and the body are available through the `UnitHttpMessage` trait: ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpMessage}; #[test] fn test_policy_allows_get() { let mut tester = UnitTestBuilder::default() .with_config(r#"{"allowed_methods": ["GET"]}"#) .with_entrypoint(crate::configure); let response = tester.request( UnitHttpRequest::get().with_path("/api/resource"), ); assert_eq!(response.status_code(), 200); } ``` The `request` method drives the request until execution finishes and returns a `UnitHttpResponse`. If the request doesn’t resolve immediately, the test advances the internal clock and retries until the request completes. ## View Backend Requests Use `TraceBackend` to record requests that reach the upstream. Supply any `Backend` as the response generator: ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpResponse, UnitHttpMessage, TraceBackend, Backend}; use std::rc::Rc; #[test] fn test_policy_adds_header() { let backend = Rc::new(TraceBackend::new(UnitHttpResponse::new(200))); let mut tester = UnitTestBuilder::default() .with_config(r#"{}"#) .with_backend(Rc::clone(&backend)) .with_entrypoint(crate::configure); tester.request(UnitHttpRequest::get().with_path("/api/resource")); let upstream_req = backend.next().unwrap(); assert_eq!(upstream_req.header("x-added-by-policy"), Some("true")); } ``` > [!NOTE] This example always returns `200`. ## Return Custom Upstream Responses Use `UnitHttpResponse` or a different closure that implements the `Backend` to mock upstream responses: ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpResponse, UnitHttpMessage}; #[test] fn test_policy_handles_upstream_error() { let mut tester = UnitTestBuilder::default() .with_config(r#"{}"#) .with_backend(|_req| { UnitHttpResponse::new(503) .with_body(r#"{"error":"unavailable"}"#) }) .with_entrypoint(crate::configure); let response = tester.request( UnitHttpRequest::get().with_path("/api/resource"), ); assert_eq!(response.status_code(), 503); } ``` ## Mock an HTTP Upstream When a policy issues an HTTP call to a specific authority, register a backend for that authority by using `with_http_upstream_from_authority`: ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpResponse, UnitHttpMessage}; #[test] fn test_policy_calls_external_service() { let mut tester = UnitTestBuilder::default() .with_config(r#"{"auth_url": "https://auth.example.com"}"#) .with_http_upstream_from_authority("auth.example.com", |_req| { UnitHttpResponse::new(200) .with_body(r#"{"valid":true}"#) .into() }) .with_entrypoint(crate::configure); let response = tester.request( UnitHttpRequest::get().with_path("/secure"), ); assert_eq!(response.status_code(), 200); } ``` ## Mock a gRPC upstream Use the `protobuf_grpc_backend` macro to derive a `GrpcBackend` implementation from a Rust struct with annotated methods: ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpMessage, protobuf_grpc_backend}; #[derive(Default)] pub struct MockAuthService; #[protobuf_grpc_backend] impl MockAuthService { #[grpc_method(service = "AuthService", method = "Verify")] fn verify(&self, _req: VerifyRequest) -> VerifyResponse { VerifyResponse { authorized: true, ..Default::default() } } } #[test] fn test_grpc_policy() { let mut tester = UnitTestBuilder::default() .with_config(r#"{}"#) .with_grpc_upstream_from_authority("grpc.backend.com", MockAuthService::default()) .with_entrypoint(crate::configure); let response = tester.request( UnitHttpRequest::post().with_path("/api/data"), ); assert_eq!(response.status_code(), 200); } ``` ## Test Client ID Enforcement `add_contract_data` seeds the built-in Anypoint Platform stub with a registered API contract to test policies that validate client credentials. ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpMessage}; #[test] fn test_valid_client_id() { let mut tester = UnitTestBuilder::default() .with_config(r#"{}"#) .with_entrypoint(crate::configure); tester.add_contract_data( "my-client-id", "My App", Some("my-client-secret"), None::, ); tester.sleep(Duration::from_secs(20)); // advance the internal clock to execute the periodic task let response = tester.request( UnitHttpRequest::get() .with_path("/api/resource") .with_header("client_id", "my-client-id") .with_header("client_secret", "my-client-secret"), ); assert_eq!(response.status_code(), 200); } ``` ## Test Time-Based Behavior Unit tests use an internal clock to test timed policy functions. Use the `tick()` and `sleep()` functions to drive policies that use timers or scheduled callbacks. These functions only move the internal testing clock forward and don’t actually take the specified time. Use `Clock::now` or `Timer::now` for time in the policy: ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpMessage}; use std::time::Duration; #[test] fn test_rate_limit_resets_after_window() { let mut tester = UnitTestBuilder::default() .with_config(r#"{"requests_per_minute": 1}"#) .with_entrypoint(crate::configure); let req = || UnitHttpRequest::get().with_path("/api/resource"); let first = tester.request(req()); assert_eq!(first.status_code(), 200); let second = tester.request(req()); assert_eq!(second.status_code(), 429); // Advance time past the rate-limit window tester.sleep(Duration::from_secs(60)); let third = tester.request(req()); assert_eq!(third.status_code(), 200); } ``` > [!NOTE] Using `SystemTime::now` creates non-deterministic tests. ## `UnitTestBuilder` Methods `UnitTestBuilder::default()` is the entry point. All methods return `self` for chaining, except `with_entrypoint` that consumes the builder and returns a `UnitTest`:
MethodSignatureDescription

with_config

with_config(config: impl Into<String>) → Self

Sets the policy configuration as a JSON string.

with_backend

with_backend(backend: impl Backend + 'static) → Self

Sets the default HTTP backend when no named upstream matches the request. Defaults to a TraceBackend returning 200.

with_http_upstream_from_authority

with_http_upstream_from_authority(authority: impl AsRef<str>, backend: impl Backend + 'static) → Self

Registers an HTTP upstream matched by host authority, for example, api.example.com. The authority is converted to the internal upstream service name. Call any metadata() calls that change policy_name or policy_namespace before calling with_http_upstream_from_authority.

with_http_upstream

with_http_upstream(upstream: impl Into<String>, backend: impl Backend + 'static) → Self

Registers an HTTP upstream by its full internal service name. Use with_http_upstream_from_authority unless if you must pass the service name directly.

with_grpc_upstream_from_authority

with_grpc_upstream_from_authority(authority: impl AsRef<str>, backend: impl GrpcBackend + 'static) → Self

Registers a gRPC upstream matched by host authority. The authority is converted to the internal upstream service name.

with_grpc_upstream

with_grpc_upstream(upstream: impl Into<String>, backend: impl GrpcBackend + 'static) → Self

Registers a gRPC upstream by its full internal service name.

with_identity_management

with_identity_management(url: impl Into<String>, backend: impl Backend + 'static) → Self

Configures the identity management service URL and its HTTP backend mock. Use when the policy performs OAuth token introspection or similar identity calls.

metadata

metadata(f: impl FnOnce(&mut Metadata)) → Self

Mutates the Metadata injected into the policy context. Call the metadata method before any with_*_upstream_from_authority method as the upstream methods derive the upstream service name from metadata.

with_entrypoint

with_entrypoint(entrypoint: impl Entrypoint<C, T> + Clone + 'static) → UnitTest

Consumes the builder and creates a UnitTest. Pass crate::configure as the entrypoint. Consumes the builder.

## Core API Reference
Type / functionDescription

UnitTestBuilder

Fluent builder. Configure the policy, metadata, and backends, then call with_entrypoint to produce a UnitTest.

UnitTest

Main orchestrator. Use request for synchronous tests or request_partial plus poll for finer control.

UnitTestRequest

In-flight request handle. poll() returns Poll::Pending or Poll::Ready(response).

UnitHttpRequest

HTTP request built with method helpers (get(), post(), and so on) or custom(). Use with_path, with_header, and with_body to populate it.

UnitHttpResponse

HTTP response from new(status_code). Exposes status_code() and the UnitHttpMessage trait accessors.

UnitHttpMessage

Traits for both UnitHttpRequest and UnitHttpResponse: header(), headers(), body(), property(), authentication(), and violation().

UnitGrpcRequest and UnitGrpcResponse

gRPC wrappers for GrpcBackend implementations.

Backend

Trait for HTTP upstream mocks. Implemented for closures and for structs whose values convert to RequestResponse.

GrpcBackend

Trait for gRPC upstream mocks. Implemented for closures via the protobuf_grpc_backend.

TraceBackend

Wraps any Backend, records each call, and lets you assert on upstream requests with next().

protobuf_grpc_backend

Proc-macro that derives GrpcBackend from annotated impl methods and handles protobuf encode/decode.

StopIterationMode

Controls ordering when resuming paused requests. Enabled with the enable_stop_iteration feature (stable since 1.8).

--- product: Omni Gateway Policy Development Kit (PDK) version: 1.9 --- # Writing Unit Tests > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the `pdk-unit` testing framework for Omni Gateway Policy Development Kit (PDK) custom policies to test the full request and response lifecycle of a policy without a running Envoy proxy, a WebAssembly runtime, or external infrastructure. To see example `pdk-unit` tests, browse the [PDK Custom Policy Examples](https://github.com/mulesoft/pdk-custom-policy-examples) on GitHub. Use `pdk-unit` when you need tests that are: - **Fast feedback**: Tests run as ordinary Rust unit tests completing in milliseconds. - **Deterministic**: No network, no containers, no race conditions. - **Full lifecycle coverage**: Exercises request headers, request body, response headers, and response body phases as the real `proxy-wasm` host does. - **Code coverage**: Policy code runs directly in the Rust environment, so it works with standard coverage tools such as `cargo-tarpaulin`. - **Debugging**: Tests run as native Rust code, so you can attach a debugger or profiler without extra setup. ## Enable pdk-unit Add `pdk-unit` as a dev-dependency in your policy’s `Cargo.toml`: ```toml [dev-dependencies] pdk-unit = { version = "1.9" } ``` ### Enable pdk-unit for Non-PDK Policies PDK-Unit supports testing any policy built with [proxy-wasm-rust-sdk](https://github.com/proxy-wasm/proxy-wasm-rust-sdk). You can write and run unit tests for existing proxy-wasm policies without migrating them to PDK first. Use this functionality to: - Validate behavior before migration: Test your legacy proxy-wasm policies to establish a behavioral baseline. - Identify regressions during migration: Establish tests before migrating your policy to PDK to make sure behavioral differences surface immediately. - Adopt PDK incrementally: Migrate your policies to PDK at your own pace while still performing unit testing. To test non-PDK policies with pdk-unit: 1. Make these edits to the custom policy’s `Cargo.toml` file before compilation: - Replace the `pdk-proxy-wasm-stub` target instead of using `proxy-wasm`. > [!NOTE] Don’t make this edit for `wasm32` architecture. - Add the `pdk_unit` dependency. ```toml [target.'cfg(target_arch = "wasm32")'.dependencies] proxy-wasm = "0.2.5" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] pdk-proxy-wasm-stub = "1.9.0" [dev-dependencies] pdk_unit = { version = "1.9.0", default-features = false, features = ["proxy-wasm-rust-sdk"] } ``` 2. Conditionally import the appropriate crate in your policy code: ```rust #[cfg(target_arch = "wasm32")] use proxy_wasm as pw; #[cfg(not(target_arch = "wasm32"))] use pdk_proxy_wasm_stub as pw; ``` 3. Write your tests as you would for a PDK policy. However, use the `with_context` method instead of the `with_entrypoint` method. The `with_context` method receives a function that creates a root context of the root filter: ```rust let mut tester = UnitTestBuilder::default() .with_backend(TraceBackend::new(UnitHttpResponse::upgrade())) .with_http_upstream("name.namespace.svc", |req: UnitHttpRequest| { UnitHttpResponse::new(200) }) .with_context(|| Box::new(WebSocketRoot)); ``` ## Basic Request and Response Test To send a test request build a `UnitTest` with the `UnitTestBuilder`, send a `UnitHttpRequest`, and assert on the returned `UnitHttpResponse`. Headers and the body are available through the `UnitHttpMessage` trait: ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpMessage}; #[test] fn test_policy_allows_get() { let mut tester = UnitTestBuilder::default() .with_config(r#"{"allowed_methods": ["GET"]}"#) .with_entrypoint(crate::configure); let response = tester.request( UnitHttpRequest::get().with_path("/api/resource"), ); assert_eq!(response.status_code(), 200); } ``` The `request` method drives the request until execution finishes and returns a `UnitHttpResponse`. If the request doesn’t resolve immediately, the test advances the internal clock and retries until the request completes. ## View Backend Requests Use `TraceBackend` to record requests that reach the upstream. Supply any `Backend` as the response generator: ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpResponse, UnitHttpMessage, TraceBackend, Backend}; use std::rc::Rc; #[test] fn test_policy_adds_header() { let backend = Rc::new(TraceBackend::new(UnitHttpResponse::new(200))); let mut tester = UnitTestBuilder::default() .with_config(r#"{}"#) .with_backend(Rc::clone(&backend)) .with_entrypoint(crate::configure); tester.request(UnitHttpRequest::get().with_path("/api/resource")); let upstream_req = backend.next().unwrap(); assert_eq!(upstream_req.header("x-added-by-policy"), Some("true")); } ``` > [!NOTE] This example always returns `200`. ## Return Custom Upstream Responses Use `UnitHttpResponse` or a different closure that implements the `Backend` to mock upstream responses: ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpResponse, UnitHttpMessage}; #[test] fn test_policy_handles_upstream_error() { let mut tester = UnitTestBuilder::default() .with_config(r#"{}"#) .with_backend(|_req| { UnitHttpResponse::new(503) .with_body(r#"{"error":"unavailable"}"#) }) .with_entrypoint(crate::configure); let response = tester.request( UnitHttpRequest::get().with_path("/api/resource"), ); assert_eq!(response.status_code(), 503); } ``` ## Mock an HTTP Upstream When a policy issues an HTTP call to a specific authority, register a backend for that authority by using `with_http_upstream_from_authority`: ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpResponse, UnitHttpMessage}; #[test] fn test_policy_calls_external_service() { let mut tester = UnitTestBuilder::default() .with_config(r#"{"auth_url": "https://auth.example.com"}"#) .with_http_upstream_from_authority("auth.example.com", |_req| { UnitHttpResponse::new(200) .with_body(r#"{"valid":true}"#) .into() }) .with_entrypoint(crate::configure); let response = tester.request( UnitHttpRequest::get().with_path("/secure"), ); assert_eq!(response.status_code(), 200); } ``` ## Mock a gRPC upstream Use the `protobuf_grpc_backend` macro to derive a `GrpcBackend` implementation from a Rust struct with annotated methods: ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpMessage, protobuf_grpc_backend}; #[derive(Default)] pub struct MockAuthService; #[protobuf_grpc_backend] impl MockAuthService { #[grpc_method(service = "AuthService", method = "Verify")] fn verify(&self, _req: VerifyRequest) -> VerifyResponse { VerifyResponse { authorized: true, ..Default::default() } } } #[test] fn test_grpc_policy() { let mut tester = UnitTestBuilder::default() .with_config(r#"{}"#) .with_grpc_upstream_from_authority("grpc.backend.com", MockAuthService::default()) .with_entrypoint(crate::configure); let response = tester.request( UnitHttpRequest::post().with_path("/api/data"), ); assert_eq!(response.status_code(), 200); } ``` ## Test WebSocket Policies To test custom policies that support WebSocket APIs, use the WebSocket testing capabilities in `pdk-unit`. WebSocket tests differ from standard HTTP tests because they establish an upgrade connection and test bidirectional frame exchange. To test a WebSocket policy: 1. Configure the backend as `UnitHttpResponse::upgrade()` to simulate a successful WebSocket upgrade. 2. Call the `upgrade` method with `UnitHttpRequest::upgrade()` instead of `request`. 3. The result provides an `UpgradeConnection` with the upgrade response and handles to send frames in both directions. ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpResponse, UnitFrame, UnitFrameType}; #[test] fn websocket_non_text_frames_are_forwarded_unchanged() { let mut tester = UnitTestBuilder::default() .with_backend(UnitHttpResponse::upgrade()) .with_entrypoint(crate::configure); let conn = tester.upgrade(UnitHttpRequest::upgrade()).unwrap(); assert_eq!(conn.response().header("custom"), Some("Some")); // Test client to server frames conn.client().send_to_server(UnitFrame::ping()); let frame = conn.server().next(); assert!(frame.is_some()); assert_eq!(frame.unwrap().frame_type(), UnitFrameType::Ping); // Test server to client frames conn.server().send_to_client(UnitFrame::pong()); let frame = conn.client().next(); assert!(frame.is_some()); assert_eq!(frame.unwrap().frame_type(), UnitFrameType::Pong); } ``` The `UpgradeConnection` provides: - `response()`: Returns the upgrade response for asserting headers or status. - `client()`: Handle to send frames from client to server and receive frames from server. - `server()`: Handle to send frames from server to client and receive frames from client. Use `UnitFrame` to construct WebSocket frames for testing: - `UnitFrame::text(payload)`: Creates a text frame. - `UnitFrame::binary(payload)`: Creates a binary frame. - `UnitFrame::ping()`: Creates a ping control frame. - `UnitFrame::pong()`: Creates a pong control frame. - `UnitFrame::close()`: Creates a close control frame. ## Test Client ID Enforcement `add_contract_data` seeds the built-in Anypoint Platform stub with a registered API contract to test policies that validate client credentials. ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpMessage}; #[test] fn test_valid_client_id() { let mut tester = UnitTestBuilder::default() .with_config(r#"{}"#) .with_entrypoint(crate::configure); tester.add_contract_data( "my-client-id", "My App", Some("my-client-secret"), None::, ); tester.sleep(Duration::from_secs(20)); // advance the internal clock to execute the periodic task let response = tester.request( UnitHttpRequest::get() .with_path("/api/resource") .with_header("client_id", "my-client-id") .with_header("client_secret", "my-client-secret"), ); assert_eq!(response.status_code(), 200); } ``` ## Test Time-Based Behavior Unit tests use an internal clock to test timed policy functions. Use the `tick()` and `sleep()` functions to drive policies that use timers or scheduled callbacks. These functions only move the internal testing clock forward and don’t actually take the specified time. Use `Clock::now` or `Timer::now` for time in the policy: ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpMessage}; use std::time::Duration; #[test] fn test_rate_limit_resets_after_window() { let mut tester = UnitTestBuilder::default() .with_config(r#"{"requests_per_minute": 1}"#) .with_entrypoint(crate::configure); let req = || UnitHttpRequest::get().with_path("/api/resource"); let first = tester.request(req()); assert_eq!(first.status_code(), 200); let second = tester.request(req()); assert_eq!(second.status_code(), 429); // Advance time past the rate-limit window tester.sleep(Duration::from_secs(60)); let third = tester.request(req()); assert_eq!(third.status_code(), 200); } ``` > [!NOTE] Using `SystemTime::now` creates non-deterministic tests. ## `UnitTestBuilder` Methods `UnitTestBuilder::default()` is the entry point. All methods return `self` for chaining, except `with_entrypoint` that consumes the builder and returns a `UnitTest`:
MethodSignatureDescription

with_config

with_config(config: impl Into<String>) → Self

Sets the policy configuration as a JSON string.

with_backend

with_backend(backend: impl Backend + 'static) → Self

Sets the default HTTP backend when no named upstream matches the request. Defaults to a TraceBackend returning 200.

with_http_upstream_from_authority

with_http_upstream_from_authority(authority: impl AsRef<str>, backend: impl Backend + 'static) → Self

Registers an HTTP upstream matched by host authority, for example, api.example.com. The authority is converted to the internal upstream service name. Call any metadata() calls that change policy_name or policy_namespace before calling with_http_upstream_from_authority.

with_http_upstream

with_http_upstream(upstream: impl Into<String>, backend: impl Backend + 'static) → Self

Registers an HTTP upstream by its full internal service name. Use with_http_upstream_from_authority unless if you must pass the service name directly.

with_grpc_upstream_from_authority

with_grpc_upstream_from_authority(authority: impl AsRef<str>, backend: impl GrpcBackend + 'static) → Self

Registers a gRPC upstream matched by host authority. The authority is converted to the internal upstream service name.

with_grpc_upstream

with_grpc_upstream(upstream: impl Into<String>, backend: impl GrpcBackend + 'static) → Self

Registers a gRPC upstream by its full internal service name.

with_identity_management

with_identity_management(url: impl Into<String>, backend: impl Backend + 'static) → Self

Configures the identity management service URL and its HTTP backend mock. Use when the policy performs OAuth token introspection or similar identity calls.

metadata

metadata(f: impl FnOnce(&mut Metadata)) → Self

Mutates the Metadata injected into the policy context. Call the metadata method before any with_*_upstream_from_authority method as the upstream methods derive the upstream service name from metadata.

with_entrypoint

with_entrypoint(entrypoint: impl Entrypoint<C, T> + Clone + 'static) → UnitTest

Consumes the builder and creates a UnitTest. Pass crate::configure as the entrypoint. Consumes the builder.

## Core API Reference
Type / functionDescription

UnitTestBuilder

Fluent builder. Configure the policy, metadata, and backends, then call with_entrypoint to produce a UnitTest.

UnitTest

Main orchestrator. Use request for synchronous tests or request_partial plus poll for finer control.

UnitTestRequest

In-flight request handle. poll() returns Poll::Pending or Poll::Ready(response).

UnitHttpRequest

HTTP request built with method helpers (get(), post(), and so on) or custom(). Use with_path, with_header, and with_body to populate it.

UnitHttpResponse

HTTP response from new(status_code). Exposes status_code() and the UnitHttpMessage trait accessors.

UnitHttpMessage

Traits for both UnitHttpRequest and UnitHttpResponse: header(), headers(), body(), property(), authentication(), and violation().

UnitGrpcRequest and UnitGrpcResponse

gRPC wrappers for GrpcBackend implementations.

Backend

Trait for HTTP upstream mocks. Implemented for closures and for structs whose values convert to RequestResponse.

GrpcBackend

Trait for gRPC upstream mocks. Implemented for closures via the protobuf_grpc_backend.

TraceBackend

Wraps any Backend, records each call, and lets you assert on upstream requests with next().

protobuf_grpc_backend

Proc-macro that derives GrpcBackend from annotated impl methods and handles protobuf encode/decode.

UpgradeConnection

WebSocket connection handle returned by upgrade(). Provides response() for the upgrade response, client() for client-side frame operations, and server() for server-side frame operations.

UnitFrame

WebSocket frame for testing. Create with text(), binary(), ping(), pong(), or close(). Query the type with frame_type().

UnitFrameType

Enum for WebSocket frame types: Text, Binary, Ping, Pong, Close.

StopIterationMode

Controls ordering when resuming paused requests. Enabled with the enable_stop_iteration feature (stable since 1.8).

--- product: Omni Gateway Policy Development Kit (PDK) version: 1.10 is-latest-version: true --- # Writing Unit Tests > For the full documentation index, see: https://docs.mulesoft.com/llms.txt Use the `pdk-unit` testing framework for Omni Gateway Policy Development Kit (PDK) custom policies to test the full request and response lifecycle of a policy without a running Envoy proxy, a WebAssembly runtime, or external infrastructure. To see example `pdk-unit` tests, browse the [PDK Custom Policy Examples](https://github.com/mulesoft/pdk-custom-policy-examples) on GitHub. Use `pdk-unit` when you need tests that are: - **Fast feedback**: Tests run as ordinary Rust unit tests completing in milliseconds. - **Deterministic**: No network, no containers, no race conditions. - **Full lifecycle coverage**: Exercises request headers, request body, response headers, and response body phases as the real `proxy-wasm` host does. - **Code coverage**: Policy code runs directly in the Rust environment, so it works with standard coverage tools such as `cargo-tarpaulin`. - **Debugging**: Tests run as native Rust code, so you can attach a debugger or profiler without extra setup. ## Enable pdk-unit Add `pdk-unit` as a dev-dependency in your policy’s `Cargo.toml`: ```toml [dev-dependencies] pdk-unit = { version = "1.10" } ``` ### Enable pdk-unit for Non-PDK Policies PDK-Unit supports testing any policy built with [proxy-wasm-rust-sdk](https://github.com/proxy-wasm/proxy-wasm-rust-sdk). You can write and run unit tests for existing proxy-wasm policies without migrating them to PDK first. Use this functionality to: - Validate behavior before migration: Test your legacy proxy-wasm policies to establish a behavioral baseline. - Identify regressions during migration: Establish tests before migrating your policy to PDK to make sure behavioral differences surface immediately. - Adopt PDK incrementally: Migrate your policies to PDK at your own pace while still performing unit testing. To test non-PDK policies with pdk-unit: 1. Make these edits to the custom policy’s `Cargo.toml` file before compilation: - Replace the `pdk-proxy-wasm-stub` target instead of using `proxy-wasm`. > [!NOTE] Don’t make this edit for `wasm32` architecture. - Add the `pdk_unit` dependency. ```toml [target.'cfg(target_arch = "wasm32")'.dependencies] proxy-wasm = "0.2.5" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] pdk-proxy-wasm-stub = "1.10.0" [dev-dependencies] pdk_unit = { version = "1.10.0", default-features = false, features = ["proxy-wasm-rust-sdk"] } ``` 2. Conditionally import the appropriate crate in your policy code: ```rust #[cfg(target_arch = "wasm32")] use proxy_wasm as pw; #[cfg(not(target_arch = "wasm32"))] use pdk_proxy_wasm_stub as pw; ``` 3. Write your tests as you would for a PDK policy. However, use the `with_context` method instead of the `with_entrypoint` method. The `with_context` method receives a function that creates a root context of the root filter: ```rust let mut tester = UnitTestBuilder::default() .with_backend(TraceBackend::new(UnitHttpResponse::upgrade())) .with_http_upstream("name.namespace.svc", |req: UnitHttpRequest| { UnitHttpResponse::new(200) }) .with_context(|| Box::new(WebSocketRoot)); ``` ## Basic Request and Response Test To send a test request build a `UnitTest` with the `UnitTestBuilder`, send a `UnitHttpRequest`, and assert on the returned `UnitHttpResponse`. Headers and the body are available through the `UnitHttpMessage` trait: ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpMessage}; #[test] fn test_policy_allows_get() { let mut tester = UnitTestBuilder::default() .with_config(r#"{"allowed_methods": ["GET"]}"#) .with_entrypoint(crate::configure); let response = tester.request( UnitHttpRequest::get().with_path("/api/resource"), ); assert_eq!(response.status_code(), 200); } ``` The `request` method drives the request until execution finishes and returns a `UnitHttpResponse`. If the request doesn’t resolve immediately, the test advances the internal clock and retries until the request completes. ## View Backend Requests Use `TraceBackend` to record requests that reach the upstream. Supply any `Backend` as the response generator: ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpResponse, UnitHttpMessage, TraceBackend, Backend}; use std::rc::Rc; #[test] fn test_policy_adds_header() { let backend = Rc::new(TraceBackend::new(UnitHttpResponse::new(200))); let mut tester = UnitTestBuilder::default() .with_config(r#"{}"#) .with_backend(Rc::clone(&backend)) .with_entrypoint(crate::configure); tester.request(UnitHttpRequest::get().with_path("/api/resource")); let upstream_req = backend.next().unwrap(); assert_eq!(upstream_req.header("x-added-by-policy"), Some("true")); } ``` > [!NOTE] This example always returns `200`. ## Return Custom Upstream Responses Use `UnitHttpResponse` or a different closure that implements the `Backend` to mock upstream responses: ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpResponse, UnitHttpMessage}; #[test] fn test_policy_handles_upstream_error() { let mut tester = UnitTestBuilder::default() .with_config(r#"{}"#) .with_backend(|_req| { UnitHttpResponse::new(503) .with_body(r#"{"error":"unavailable"}"#) }) .with_entrypoint(crate::configure); let response = tester.request( UnitHttpRequest::get().with_path("/api/resource"), ); assert_eq!(response.status_code(), 503); } ``` ## Mock an HTTP Upstream When a policy issues an HTTP call to a specific authority, register a backend for that authority by using `with_http_upstream_from_authority`: ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpResponse, UnitHttpMessage}; #[test] fn test_policy_calls_external_service() { let mut tester = UnitTestBuilder::default() .with_config(r#"{"auth_url": "https://auth.example.com"}"#) .with_http_upstream_from_authority("auth.example.com", |_req| { UnitHttpResponse::new(200) .with_body(r#"{"valid":true}"#) .into() }) .with_entrypoint(crate::configure); let response = tester.request( UnitHttpRequest::get().with_path("/secure"), ); assert_eq!(response.status_code(), 200); } ``` ## Mock a gRPC upstream Use the `protobuf_grpc_backend` macro to derive a `GrpcBackend` implementation from a Rust struct with annotated methods: ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpMessage, protobuf_grpc_backend}; #[derive(Default)] pub struct MockAuthService; #[protobuf_grpc_backend] impl MockAuthService { #[grpc_method(service = "AuthService", method = "Verify")] fn verify(&self, _req: VerifyRequest) -> VerifyResponse { VerifyResponse { authorized: true, ..Default::default() } } } #[test] fn test_grpc_policy() { let mut tester = UnitTestBuilder::default() .with_config(r#"{}"#) .with_grpc_upstream_from_authority("grpc.backend.com", MockAuthService::default()) .with_entrypoint(crate::configure); let response = tester.request( UnitHttpRequest::post().with_path("/api/data"), ); assert_eq!(response.status_code(), 200); } ``` ## Test WebSocket Policies To test custom policies that support WebSocket APIs, use the WebSocket testing capabilities in `pdk-unit`. WebSocket tests differ from standard HTTP tests because they establish an upgrade connection and test bidirectional frame exchange. To test a WebSocket policy: 1. Configure the backend as `UnitHttpResponse::upgrade()` to simulate a successful WebSocket upgrade. 2. Call the `upgrade` method with `UnitHttpRequest::upgrade()` instead of `request`. 3. The result provides an `UpgradeConnection` with the upgrade response and handles to send frames in both directions. ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpResponse, UnitFrame, UnitFrameType}; #[test] fn websocket_non_text_frames_are_forwarded_unchanged() { let mut tester = UnitTestBuilder::default() .with_backend(UnitHttpResponse::upgrade()) .with_entrypoint(crate::configure); let conn = tester.upgrade(UnitHttpRequest::upgrade()).unwrap(); assert_eq!(conn.response().header("custom"), Some("Some")); // Test client to server frames conn.client().send_to_server(UnitFrame::ping()); let frame = conn.server().next(); assert!(frame.is_some()); assert_eq!(frame.unwrap().frame_type(), UnitFrameType::Ping); // Test server to client frames conn.server().send_to_client(UnitFrame::pong()); let frame = conn.client().next(); assert!(frame.is_some()); assert_eq!(frame.unwrap().frame_type(), UnitFrameType::Pong); } ``` The `UpgradeConnection` provides: - `response()`: Returns the upgrade response for asserting headers or status. - `client()`: Handle to send frames from client to server and receive frames from server. - `server()`: Handle to send frames from server to client and receive frames from client. Use `UnitFrame` to construct WebSocket frames for testing: - `UnitFrame::text(payload)`: Creates a text frame. - `UnitFrame::binary(payload)`: Creates a binary frame. - `UnitFrame::ping()`: Creates a ping control frame. - `UnitFrame::pong()`: Creates a pong control frame. - `UnitFrame::close()`: Creates a close control frame. ## Test Client ID Enforcement `add_contract_data` seeds the built-in Anypoint Platform stub with a registered API contract to test policies that validate client credentials. ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpMessage}; #[test] fn test_valid_client_id() { let mut tester = UnitTestBuilder::default() .with_config(r#"{}"#) .with_entrypoint(crate::configure); tester.add_contract_data( "my-client-id", "My App", Some("my-client-secret"), None::, ); tester.sleep(Duration::from_secs(20)); // advance the internal clock to execute the periodic task let response = tester.request( UnitHttpRequest::get() .with_path("/api/resource") .with_header("client_id", "my-client-id") .with_header("client_secret", "my-client-secret"), ); assert_eq!(response.status_code(), 200); } ``` ## Test Time-Based Behavior Unit tests use an internal clock to test timed policy functions. Use the `tick()` and `sleep()` functions to drive policies that use timers or scheduled callbacks. These functions only move the internal testing clock forward and don’t actually take the specified time. Use `Clock::now` or `Timer::now` for time in the policy: ```rust use pdk_unit::{UnitTestBuilder, UnitHttpRequest, UnitHttpMessage}; use std::time::Duration; #[test] fn test_rate_limit_resets_after_window() { let mut tester = UnitTestBuilder::default() .with_config(r#"{"requests_per_minute": 1}"#) .with_entrypoint(crate::configure); let req = || UnitHttpRequest::get().with_path("/api/resource"); let first = tester.request(req()); assert_eq!(first.status_code(), 200); let second = tester.request(req()); assert_eq!(second.status_code(), 429); // Advance time past the rate-limit window tester.sleep(Duration::from_secs(60)); let third = tester.request(req()); assert_eq!(third.status_code(), 200); } ``` > [!NOTE] Using `SystemTime::now` creates non-deterministic tests. ## `UnitTestBuilder` Methods `UnitTestBuilder::default()` is the entry point. All methods return `self` for chaining, except `with_entrypoint` that consumes the builder and returns a `UnitTest`:
MethodSignatureDescription

with_config

with_config(config: impl Into<String>) → Self

Sets the policy configuration as a JSON string.

with_backend

with_backend(backend: impl Backend + 'static) → Self

Sets the default HTTP backend when no named upstream matches the request. Defaults to a TraceBackend returning 200.

with_http_upstream_from_authority

with_http_upstream_from_authority(authority: impl AsRef<str>, backend: impl Backend + 'static) → Self

Registers an HTTP upstream matched by host authority, for example, api.example.com. The authority is converted to the internal upstream service name. Call any metadata() calls that change policy_name or policy_namespace before calling with_http_upstream_from_authority.

with_http_upstream

with_http_upstream(upstream: impl Into<String>, backend: impl Backend + 'static) → Self

Registers an HTTP upstream by its full internal service name. Use with_http_upstream_from_authority unless if you must pass the service name directly.

with_grpc_upstream_from_authority

with_grpc_upstream_from_authority(authority: impl AsRef<str>, backend: impl GrpcBackend + 'static) → Self

Registers a gRPC upstream matched by host authority. The authority is converted to the internal upstream service name.

with_grpc_upstream

with_grpc_upstream(upstream: impl Into<String>, backend: impl GrpcBackend + 'static) → Self

Registers a gRPC upstream by its full internal service name.

with_identity_management

with_identity_management(url: impl Into<String>, backend: impl Backend + 'static) → Self

Configures the identity management service URL and its HTTP backend mock. Use when the policy performs OAuth token introspection or similar identity calls.

metadata

metadata(f: impl FnOnce(&mut Metadata)) → Self

Mutates the Metadata injected into the policy context. Call the metadata method before any with_*_upstream_from_authority method as the upstream methods derive the upstream service name from metadata.

with_entrypoint

with_entrypoint(entrypoint: impl Entrypoint<C, T> + Clone + 'static) → UnitTest

Consumes the builder and creates a UnitTest. Pass crate::configure as the entrypoint. Consumes the builder.

## Core API Reference
Type / functionDescription

UnitTestBuilder

Fluent builder. Configure the policy, metadata, and backends, then call with_entrypoint to produce a UnitTest.

UnitTest

Main orchestrator. Use request for synchronous tests or request_partial plus poll for finer control.

UnitTestRequest

In-flight request handle. poll() returns Poll::Pending or Poll::Ready(response).

UnitHttpRequest

HTTP request built with method helpers (get(), post(), and so on) or custom(). Use with_path, with_header, and with_body to populate it.

UnitHttpResponse

HTTP response from new(status_code). Exposes status_code() and the UnitHttpMessage trait accessors.

UnitHttpMessage

Traits for both UnitHttpRequest and UnitHttpResponse: header(), headers(), body(), property(), authentication(), and violation().

UnitGrpcRequest and UnitGrpcResponse

gRPC wrappers for GrpcBackend implementations.

Backend

Trait for HTTP upstream mocks. Implemented for closures and for structs whose values convert to RequestResponse.

GrpcBackend

Trait for gRPC upstream mocks. Implemented for closures via the protobuf_grpc_backend.

TraceBackend

Wraps any Backend, records each call, and lets you assert on upstream requests with next().

protobuf_grpc_backend

Proc-macro that derives GrpcBackend from annotated impl methods and handles protobuf encode/decode.

UpgradeConnection

WebSocket connection handle returned by upgrade(). Provides response() for the upgrade response, client() for client-side frame operations, and server() for server-side frame operations.

UnitFrame

WebSocket frame for testing. Create with text(), binary(), ping(), pong(), or close(). Query the type with frame_type().

UnitFrameType

Enum for WebSocket frame types: Text, Binary, Ping, Pong, Close.

StopIterationMode

Controls ordering when resuming paused requests. Enabled with the enable_stop_iteration feature (stable since 1.8).