Extensibility: Configuration Providers
The Basic Yarp Sample show proxy configuration being loaded from appsettings.json. Instead proxy configuration can be loaded programmatically from the source of your choosing. You do this by providing a couple of classes implementing IProxyConfigProvider and IProxyConfig.
See ReverseProxy.Code.Sample for an example of a custom configuration provider.
Configuration can be modified during the load sequence using Configuration Filters.
IProxyConfigProvider has a single method
GetConfig() that should return an IProxyConfig instance. The IProxyConfig has lists of the current routes and clusters, as well as an
IChangeToken to notify the proxy when this information is out of date and should be reloaded, which will cause
GetConfig() to be called again.
The routes section is an unordered collection of named routes. A route contains matches and their associated configuration. A route requires at least the following fields:
- RouteId - a unique name
- ClusterId - refers to the name of an entry in the clusters section.
- Match - contains either a Hosts array or a Path pattern string. Path is an ASP.NET Core route template that can be defined as explained here.
The proxy will apply the given matching criteria and policies, and then pass off the request to the specified cluster.
The clusters section is an unordered collection of named clusters. A cluster primarily contains a collection of named destinations and their addresses, any of which is considered capable of handling requests for a given route. The proxy will process the request according to the route and cluster configuration to select a destination.
For additional fields see ClusterConfig.
In Memory Config
IProxyConfigProvider and enables specifying routes and clusters directly in code by calling
To update the config later, resolve the
InMemoryConfigProvider from the services container and call
Update with the new lists of routes and clusters.
IProxyConfigProvider should be registered in the DI container as a singleton. At startup, the proxy will resolve this instance and call
GetConfig(). On this first call the provider may choose to:
- Throw an exception if the provider cannot produce a valid proxy configuration for any reason. This will prevent the application from starting.
- Synchronously block while it loads the configuration. This will block the application from starting until valid route data is available.
- Or, it may choose to return an empty
IProxyConfiginstance while it loads the configuration in the background. The provider will need to trigger the
IChangeTokenwhen the configuration is available.
The proxy will validate the given configuration and if it's invalid, an exception will be thrown that prevents the application from starting. The provider can avoid this by using the IConfigValidator to pre-validate routes and clusters and take whatever action it deems appropriate such as excluding invalid entries.
The configuration objects and collections supplied to the proxy should be read-only and not modified once they have been handed to the proxy via
ActiveChangeCallbacks, once the proxy has processed the initial set of configurations it will register a callback with this token. If the provider does not support callbacks then
HasChanged will be polled every 5 minutes.
When the provider wants to provide a new configuration to the proxy it should:
- load that configuration in the background.
- Route and cluster objects are immutable, so new instances have to be created for any new data.
- Objects for unchanged routes and clusters can be re-used, or new instances can be created - changes will be detected by diffing them.
- optionally validate the configuration using the IConfigValidator, and only then signal the
IChangeTokenfrom the prior
IProxyConfiginstance that new data is available. The proxy will call
GetConfig()again to retrieve the new data.
There are important differences when reloading configuration vs the first configuration load.
- The new configuration will be diffed against the current one and only modified routes or clusters will be updated. The update will be applied atomically and will only affect new requests, not requests currently in progress.
- Any errors in the reload process will be logged and suppressed. The application will continue using the last known good configuration.
GetConfig()throws the proxy will be unable to listen for future changes because
IChangeTokens are single-use.
Once the new configuration has been validated and applied, the proxy will register a callback with the new
IChangeToken. Note if there are multiple reloads signaled in close succession, the proxy may skip some and load the next available configuration as soon as it's ready. Each
IProxyConfig contains the full configuration state so nothing will be lost.
Multiple Configuration Sources
As of 1.1, YARP supports loading the proxy configuration from multiple sources. Multiple
IProxyConfigProvider's can be registered as singleton services and all will be resolved and combined. The sources may be the same or different types such as IConfiguration or InMemory. Routes can reference clusters from other sources. Note merging partial config from different sources for a given route or cluster is not supported.
services.AddReverseProxy() .LoadFromConfig(Configuration.GetSection("ReverseProxy1")) .LoadFromConfig(Configuration.GetSection("ReverseProxy2"));
services.AddReverseProxy() .LoadFromMemory(routes, clusters) .LoadFromConfig(Configuration.GetSection("ReverseProxy"));
The InMemoryConfigProvider gives an example of an
IProxyConfigProvider that has routes and clusters manually loaded into it.