|
| 1 | +--- |
| 2 | +sidebar_position: 53 |
| 3 | +title: Rust |
| 4 | +description: How to use GO Feature Flag with Rust through the OpenFeature OFREP provider |
| 5 | +--- |
| 6 | +import { sdk } from "@site/data/sdk"; |
| 7 | +import { FeatureTable } from "@site/src/components/doc/featureTable"; |
| 8 | + |
| 9 | +# Rust |
| 10 | +[](https://github.com/open-feature/rust-sdk-contrib/tree/main/crates/ofrep) |
| 11 | + |
| 12 | +The OpenFeature OFREP provider connects the OpenFeature Rust SDK to a GO Feature Flag relay-proxy. |
| 13 | + |
| 14 | +It supports a single evaluation mode: |
| 15 | + |
| 16 | +- `REMOTE` delegates every evaluation to the relay-proxy via OFREP: the relay-proxy remains the single source of truth, no local configuration or polling is needed, and flag changes take effect immediately on the server. |
| 17 | + |
| 18 | +:::info This is not a GO Feature Flag specific provider |
| 19 | +There is no GO Feature Flag specific provider for Rust. |
| 20 | +The integration is done through the **generic [OpenFeature OFREP provider](https://github.com/open-feature/rust-sdk-contrib/tree/main/crates/ofrep)** (`open-feature-ofrep` crate), |
| 21 | +which works with any backend that implements the [OpenFeature Remote Evaluation Protocol (OFREP)](../ofrep). |
| 22 | + |
| 23 | +Because the [GO Feature Flag relay-proxy](../../relay-proxy) implements OFREP, |
| 24 | +you can use this provider to evaluate your GO Feature Flag flags from any Rust application. |
| 25 | +As a consequence, only the OFREP-compatible features are available — see [Features status](#features-status) below. |
| 26 | +::: |
| 27 | + |
| 28 | +## Install dependencies |
| 29 | + |
| 30 | +Install the provider and the OpenFeature Rust SDK: |
| 31 | + |
| 32 | +```shell |
| 33 | +cargo add open-feature |
| 34 | +cargo add open-feature-ofrep |
| 35 | +``` |
| 36 | + |
| 37 | +## Initialize your provider |
| 38 | + |
| 39 | +Create an `OfrepProvider` pointing at your GO Feature Flag relay-proxy: |
| 40 | + |
| 41 | +```rust |
| 42 | +use std::time::Duration; |
| 43 | +use open_feature_ofrep::{OfrepProvider, OfrepOptions}; |
| 44 | +use reqwest::header::HeaderMap; |
| 45 | + |
| 46 | +let provider = OfrepProvider::new(OfrepOptions { |
| 47 | + base_url: "http://localhost:1031".to_string(), |
| 48 | + headers: HeaderMap::new(), |
| 49 | + connect_timeout: Duration::from_secs(10), |
| 50 | + ..Default::default() |
| 51 | +}) |
| 52 | +.await |
| 53 | +.expect("failed to create OFREP provider"); |
| 54 | +``` |
| 55 | + |
| 56 | +## Initialize your OpenFeature client |
| 57 | + |
| 58 | +Register the provider in the OpenFeature SDK and then create a client: |
| 59 | + |
| 60 | +```rust |
| 61 | +use std::time::Duration; |
| 62 | +use open_feature::OpenFeature; |
| 63 | +use open_feature_ofrep::{OfrepProvider, OfrepOptions}; |
| 64 | +use reqwest::header::HeaderMap; |
| 65 | + |
| 66 | +let provider = OfrepProvider::new(OfrepOptions { |
| 67 | + base_url: "http://localhost:1031".to_string(), |
| 68 | + headers: HeaderMap::new(), |
| 69 | + connect_timeout: Duration::from_secs(10), |
| 70 | + ..Default::default() |
| 71 | +}) |
| 72 | +.await |
| 73 | +.expect("failed to create OFREP provider"); |
| 74 | + |
| 75 | +let mut api = OpenFeature::singleton_mut().await; |
| 76 | +api.set_provider(provider).await; |
| 77 | + |
| 78 | +let client = api.create_client(); |
| 79 | +``` |
| 80 | + |
| 81 | +## Evaluate a flag |
| 82 | + |
| 83 | +Create an `EvaluationContext` and use the OpenFeature client as usual. |
| 84 | + |
| 85 | +> In this example we evaluate a boolean flag, but the provider also supports string, integer, float, and struct evaluations. |
| 86 | +> |
| 87 | +> See the [OpenFeature evaluation API documentation](https://openfeature.dev/docs/reference/concepts/evaluation-api#basic-evaluation) for the full API surface. |
| 88 | +
|
| 89 | +```rust |
| 90 | +use open_feature::EvaluationContext; |
| 91 | + |
| 92 | +let evaluation_ctx = EvaluationContext::default() |
| 93 | + .with_targeting_key("1d1b9238-2591-4a47-94cf-d2bc080892f1") |
| 94 | + .with_custom_field("firstname", "john") |
| 95 | + .with_custom_field("lastname", "doe") |
| 96 | + .with_custom_field("email", "john.doe@gofeatureflag.org") |
| 97 | + .with_custom_field("admin", true) |
| 98 | + .with_custom_field("anonymous", false); |
| 99 | + |
| 100 | +let admin_flag = client |
| 101 | + .get_bool_value("flag-only-for-admin", Some(&evaluation_ctx), None) |
| 102 | + .await |
| 103 | + .unwrap_or(false); |
| 104 | + |
| 105 | +if admin_flag { |
| 106 | + // flag "flag-only-for-admin" evaluated to true |
| 107 | +} else { |
| 108 | + // flag "flag-only-for-admin" evaluated to false |
| 109 | +} |
| 110 | +``` |
| 111 | + |
| 112 | +## Provider options |
| 113 | + |
| 114 | +`base_url` is required (a default is provided but it almost certainly does not match your relay-proxy). The other options are optional. |
| 115 | + |
| 116 | +| Option | Type | Default | Description | |
| 117 | +|-------------------|-------------|-------------------------|-----------------------------------------------------------------------------------------------------| |
| 118 | +| `base_url` | `String` | `http://localhost:8016` | Base URL of the GO Feature Flag relay-proxy (e.g. `http://localhost:1031`). | |
| 119 | +| `headers` | `HeaderMap` | empty | Extra headers added to provider HTTP requests. Use this to send `X-API-Key` or `Authorization`. | |
| 120 | +| `connect_timeout` | `Duration` | `10s` | Connection timeout for HTTP requests to the relay-proxy. | |
| 121 | + |
| 122 | +To send an API key: |
| 123 | + |
| 124 | +```rust |
| 125 | +use reqwest::header::{HeaderMap, HeaderValue}; |
| 126 | + |
| 127 | +let mut headers = HeaderMap::new(); |
| 128 | +headers.insert("X-API-Key", HeaderValue::from_static("my-api-key")); |
| 129 | +``` |
| 130 | + |
| 131 | +:::warning Flag sets require `X-API-Key` |
| 132 | +If your relay-proxy is configured with [flag sets](../../relay-proxy/configure-relay-proxy#use-multiple-flag-sets), you **must** send your API key in the `X-API-Key` header. The relay-proxy uses the API key to resolve which flag set the request belongs to, so requests without it (or using a different auth header) will not be routed to the right flag set. |
| 133 | + |
| 134 | +```rust |
| 135 | +headers.insert("X-API-Key", HeaderValue::from_static("my-api-key")); |
| 136 | +``` |
| 137 | +::: |
| 138 | + |
| 139 | +If your relay-proxy expects bearer-token auth instead of `X-API-Key`, use `Authorization`: |
| 140 | + |
| 141 | +```rust |
| 142 | +headers.insert( |
| 143 | + "Authorization", |
| 144 | + HeaderValue::from_static("Bearer <token>"), |
| 145 | +); |
| 146 | +``` |
| 147 | + |
| 148 | +## Tracking and event collection |
| 149 | + |
| 150 | +### Flag usage events (automatic) |
| 151 | + |
| 152 | +Every flag evaluation goes through the relay-proxy via OFREP, so the relay-proxy itself records each evaluation as part of its built-in [export evaluation data](../../integrations/export-evaluation-data) pipeline. No additional configuration is required on the Rust side — once an exporter is configured on the relay-proxy, every Rust evaluation will be exported alongside evaluations from other languages. |
| 153 | + |
| 154 | +### Custom tracking events (OpenFeature Track API) |
| 155 | + |
| 156 | +The OFREP protocol does not yet specify a tracking endpoint. As a result, `client.track()` calls made through this provider are **not** forwarded to the relay-proxy. If you need custom tracking events from a server application, use a GO Feature Flag specific provider (Go, Java, Python, .NET, ...). |
| 157 | + |
| 158 | +## Operational notes |
| 159 | + |
| 160 | +- Every evaluation is a network call to the relay-proxy via OFREP. There is no local cache or polling, so flag changes are picked up immediately on the next evaluation. |
| 161 | +- The provider does not emit `ProviderConfigChange` / `ProviderStale` events — OFREP has no streaming/push channel from the relay-proxy to the client. |
| 162 | +- In-process evaluation is not available for Rust today; if you need lower evaluation latency, host the relay-proxy close to your Rust workload. |
| 163 | + |
| 164 | +## Features status |
| 165 | +<FeatureTable sdk={sdk.find(it => it.key === 'rust')} /> |
| 166 | + |
| 167 | +## Contribute to the provider |
| 168 | +You can find the source of the OFREP provider in the [`open-feature/rust-sdk-contrib`](https://github.com/open-feature/rust-sdk-contrib/tree/main/crates/ofrep) repository — please open issues or pull requests there for provider-level changes. |
0 commit comments