---
schema_version: "1"
id: 55e4fec946375a5d2984dd4e12f56d12427534474dca5637a067cb97d5a4a074
title: Implementing Your Custom Policy Features in Rust
collection: mulesoft
version: current
locale: en-us
portal_url: https://docs.salesforce.com/mulesoft/current/en-us/pdk/1.7/policies-pdk-configure-features.md
canonical_url: https://docs.mulesoft.com/pdk/1.7/policies-pdk-configure-features
source_site: docs.mulesoft.com
content_type: documentation
content_hash: 43914c2d7ccb4c0b4a13961a8f2d7c94de585aa5cb636928c6ac98cc8770fce1
description: MuleSoft Documentation Site
release: "1.7"
latest: false
---
---
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)
