|
| 1 | +# Creating an OFREP client provider |
| 2 | + |
| 3 | +OpenFeature Remote Evaluation Protocol (OFREP) is an API specification for feature flagging that allows the use of generic providers to connect to any feature flag management systems that supports the protocol. |
| 4 | + |
| 5 | +In this document, we will specify how to write an OFREP provider using the [static-context-paradigm](https://openfeature.dev/specification/glossary/#static-context-paradigm) that is used on client side applications typically operating in the context of a single user. |
| 6 | + |
| 7 | +**Pre-requisite:** |
| 8 | +- Understanding of [general provider concepts](https://openfeature.dev/docs/reference/concepts/provider/) |
| 9 | +- Understanding of the [OFREP](../../README.md) |
| 10 | +- Understanding of the [OFREP OpenAPI specification](../../service/openapi.yaml) |
| 11 | + |
| 12 | +## Configuration |
| 13 | +An OFREP client provider implementation must, at the time of creation, accept at least these options |
| 14 | +- `baseURL`: The base URL of the [flag management system](https://openfeature.dev/specification/glossary#flag-management-system). |
| 15 | + This must be the base of the URL pointing before the `/ofrep` namespace of the API. |
| 16 | + - In the constructor, the provider should check if the `baseURL` is a valid URL and return an error if the URL is invalid. |
| 17 | +- `headers`: The headers to use when calling the OFREP endpoints *(e.g.:`Authorization`, Custom headers, etc ...)*. |
| 18 | +- `pollInterval`: The polling interval defining how often to update the cached flags in the provider. |
| 19 | + - If `pollInterval` is equal to 0, polling will be disabled. |
| 20 | + - See [polling section](#polling) for more details. |
| 21 | +- `timeoutMs`: This specifies the duration to wait for a response before canceling the HTTP request. If no value is provided, a default timeout of `10_000 milliseconds` must be applied. |
| 22 | + |
| 23 | +## Initialize the provider |
| 24 | +The following describes the [initialization](https://openfeature.dev/specification/sections/providers#24-initialization) of an OFREP provider: |
| 25 | + |
| 26 | +The `initialize()` function must follow those steps: |
| 27 | +1. Make a POST request to the `/ofrep/v1/evaluate/flags` endpoint with the evaluation context in the body. |
| 28 | + |
| 29 | + **Request body example**: |
| 30 | + ```json |
| 31 | + { |
| 32 | + "context": { |
| 33 | + "targetingKey": "f021d0f9-33b7-4b22-b0bd-9fec66ba1d7d", |
| 34 | + "firstname": "foo", |
| 35 | + "lastname": "bar", |
| 36 | + "email": "foo.bar@ofrep.dev" |
| 37 | + } |
| 38 | + } |
| 39 | + ``` |
| 40 | + |
| 41 | + - If the endpoint returns an error, the `initialize()` function must error and exit. |
| 42 | + - If the request is successful: |
| 43 | + - The provider must store in a local cache all of the flags evaluation details returned by the API. |
| 44 | + - The provider must store the `ETag` header in the provider to be able to send it back later. |
| 45 | +2. If `pollInterval` is more than `0`, a polling mechanism must be started to periodically check for flag changes *([See polling section](#polling))*. |
| 46 | + |
| 47 | +## Evaluation |
| 48 | +The evaluation MUST not perform any remote API calls and use the local cache. |
| 49 | + |
| 50 | +When calling an evaluation function, the provider must follow those steps: |
| 51 | +1. Retrieve the evaluation details for this flag from the local cache. |
| 52 | +2. If the provider is not able to find the flag in the local cache, it must return an `FLAG_NOT_FOUND` error. |
| 53 | +3. If the evaluation details contains an error, the provider must map the error in provider to an OpenFeature error and return it. |
| 54 | +4. If the value of the evaluation details in the cache has a different type than the one expected by the evaluation function the provider must return a `TYPE_MISMATCH` error. |
| 55 | +5. If the evaluation details retrieved from the cache is successful, the provider returns the evaluation details. |
| 56 | + |
| 57 | + |
| 58 | +```mermaid |
| 59 | +flowchart TD |
| 60 | + A[evaluation function] --> D{Does the provider have an entry in cache for this flag key ?} |
| 61 | + D --> |NO| E(return a FLAG_NOT_FOUND error) |
| 62 | + D --> |YES| F{Is cached evaluation details in error?} |
| 63 | + F --> |YES| G(Map the error as an OpenFeature provider error and return it) |
| 64 | + F --> |NO| H{Are the flag and evaluation return types the same?} |
| 65 | + H --> |YES| I(return the evaluation response) |
| 66 | + H --> |NO| J(return a TYPE_MISMATCH error) |
| 67 | +``` |
| 68 | + |
| 69 | +## Polling |
| 70 | +The polling system must periodically (interval defined by `pollingInterval`) make a `POST` request to the `/ofrep/v1/evaluate/flags` endpoint with the evaluation context in the body to check if there is a change in the flags evaluation to be able to store it. |
| 71 | +If the flags changed, the provider cache for evaluation is updated. |
| 72 | + |
| 73 | +When calling the API, if an `ETag` of a previous evaluation is available, it must be added to the [`If-None-Match`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/If-None-Match) header with the `ETag` as value. |
| 74 | + |
| 75 | +When calling the API the provider can receive those response codes: |
| 76 | +- `304`: Means that the current cache is up-to-date. |
| 77 | +- `401`, `403`: The provider is not authorized to call the OFREP API. In that situation the provider should emit a `fatal` event and stop the polling mechanism. The provider will be in a [terminal error state](https://openfeature.dev/specification/sections/flag-evaluation#requirement-177). |
| 78 | +- `429`: The provider has reached the rate limit of the flag management system. In that situation the provider should read the `Retry-After` header from the response and ensure that no call to the endpoint happened before this date. |
| 79 | +- `200`: The cache is outdated. In that situation the provider must: |
| 80 | + 1. Clear the actual cache. |
| 81 | + 2. Cache the new evaluation details received. |
| 82 | + 3. Read the `ETag` header and store it for future call the API. |
| 83 | + 4. Emit an `ConfigurationChanged` event containing in the `flagsChanged` field, a list of the flag key that have changed. |
| 84 | + |
| 85 | +## Change context |
| 86 | +In the client providers, a change of context should be handle to retrieve a new version of the cache, it is called that the [Provider context reconciliation](https://openfeature.dev/specification/sections/providers/#26-provider-context-reconciliation). |
| 87 | + |
| 88 | +When the function `onContextChange` is called, the provider should call the `/ofrep/v1/evaluate/flags` endpoint with the evaluation context in the body to check if the cache needs to be updated. In that situation the provider must handle the response the same way it does for polling. |
0 commit comments