Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
415b2d4
Move the middleware class to the higher-level namespace context
raman-m Sep 26, 2025
2185a3c
Rename subfolder to 'Balancers'
raman-m Sep 26, 2025
47ef46e
Move Error classes
raman-m Sep 26, 2025
9ff6411
Change namespace to match folder structure
raman-m Sep 26, 2025
fe07c70
Move the interfaces to a separate folder
raman-m Sep 26, 2025
e14032f
Move LoadBalancerFactory
raman-m Sep 26, 2025
b729da9
Move LoadBalancerHouse
raman-m Sep 26, 2025
4fb9ebe
Move the creators to a separate folder
raman-m Sep 26, 2025
19ecc09
Delete LoadBalancerOptionsBuilder
raman-m Sep 26, 2025
5e0a03c
IfEmpty string extension workaround
raman-m Sep 27, 2025
61896b9
FileRoute inherits from FileDynamicRoute
raman-m Sep 27, 2025
d4a70ae
Don't inherit from FileDynamicRoute
raman-m Sep 27, 2025
cf1b8f7
Inherit from FileGlobalDynamicRoute
raman-m Sep 29, 2025
e7915ff
Relocate the RateLimiting property closer to the RateLimitOptions
raman-m Sep 29, 2025
18660e0
Rename to DiscoveryDownstreamRouteFinder
raman-m Sep 29, 2025
a143398
Move Metadata to FileGlobalDynamicRoute
raman-m Sep 29, 2025
9e77f78
Move LoadBalancerOptions to FileGlobalDynamicRoute
raman-m Sep 29, 2025
69ca0fc
Create LoadBalancerOptions based on global configuration
raman-m Sep 30, 2025
2d4f694
Parameterless (default) constructor works perfectly for the Route model
raman-m Sep 30, 2025
e430633
Delete RouteBuilder
raman-m Oct 1, 2025
716b554
Rename DynamicsCreator to DynamicRoutesCreator
raman-m Oct 1, 2025
d33b978
Rename RoutesCreator to StaticRoutesCreator
raman-m Oct 1, 2025
e85000e
Replace global LB-options of IInternalConfiguration with dynamic rout…
raman-m Oct 1, 2025
1ea98dc
Bump Ocelot.Testing to 24.0.3-beta.2
raman-m Oct 1, 2025
c197d30
Parse service namespace in URLs to init ServiceNamespace prop of dyna…
raman-m Oct 2, 2025
dcc46ff
Avoid using env vars in build-cake job, as none of them are required …
raman-m Oct 3, 2025
bfb3f5f
coverage src/Ocelot/Configuration/File/FileGlobalRateLimitByHeaderRul…
raman-m Oct 3, 2025
a47e993
Improve code coverage
raman-m Oct 3, 2025
0e54f94
Improve code coverage, 2nd attempt
raman-m Oct 5, 2025
ddc1497
Perform a code self-review
raman-m Oct 6, 2025
dec7a68
Improve code coverage, 3rd attempt
raman-m Oct 6, 2025
f09e36c
Move StickySessionsTests to the feature namespace
raman-m Oct 6, 2025
7215846
Review the RouteKeyCreator to generate a LB key using the final LoadB…
raman-m Oct 7, 2025
12a8553
Acceptance tests for static routes
raman-m Oct 7, 2025
fb92a02
Relocate the Csv helper to IEnumerableExtensions class within the Inf…
raman-m Oct 8, 2025
c62e5f2
More acceptance testing for static routes
raman-m Oct 8, 2025
453ddd2
Fix unit RouteKeyCreatorTests
raman-m Oct 8, 2025
e8c2c47
Code review by @RaynaldM
raman-m Oct 8, 2025
82f89b9
Construct load balancing key for dynamic routes
raman-m Oct 10, 2025
db60a33
Complete development and improve code coverage (4th attempt)
raman-m Oct 11, 2025
bf1959c
Fix the issue with the QoS Polly registry caching key
raman-m Oct 14, 2025
6d3b6bd
Refactor InternalConfiguration to ensure it is properly constructed f…
raman-m Oct 14, 2025
1ca8692
Ensure the query string remains intact in downstream paths for servic…
raman-m Oct 14, 2025
0322a43
Improve code coverage, 5th attempt
raman-m Oct 15, 2025
f75b028
Acceptance tests for dynamic routes
raman-m Oct 16, 2025
d1766ce
Prefer a more efficient algorithm for string comparison, such as Ordi…
raman-m Oct 16, 2025
8ca6230
Deprecate the FileCacheOptions property in static routes
raman-m Oct 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions .github/workflows/develop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,15 @@ jobs:
build-cake:
needs: build
runs-on: ubuntu-latest
environment: build.cake
# environment: build.cake
env:
# https://github.com/actions/setup-dotnet/blob/main/README.md#environment-variables
# NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
DOTNET_INSTALL_DIR: "/usr/share/dotnet" # don't override by /usr/lib/dotnet
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
GITHUB_SHA: ${{ github.sha }}
GITHUB_REF: ${{ github.ref }}
GITHUB_REF_NAME: ${{ github.ref_name }}
# COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
# GITHUB_SHA: ${{ github.sha }}
# GITHUB_REF: ${{ github.ref }}
# GITHUB_REF_NAME: ${{ github.ref_name }}
steps:
- name: .NET Info
run: |
Expand Down Expand Up @@ -144,9 +144,12 @@ jobs:
target: Build
- name: Prepare Coveralls
run: |
echo "GITHUB_REF is ${{ env.GITHUB_REF }}"
echo "GITHUB_REF_NAME is ${{ env.GITHUB_REF_NAME }}"
echo "GITHUB_SHA is ${{ env.GITHUB_SHA }}"
# echo "GITHUB_REF is ${{ env.GITHUB_REF }}"
# echo "GITHUB_REF_NAME is ${{ env.GITHUB_REF_NAME }}"
# echo "GITHUB_SHA is ${{ env.GITHUB_SHA }}"
echo "Listing environment variables:"
env | sort
echo ------------ Detect coverage file ------------
coverage_1st_folder=$(ls -d /home/runner/work/Ocelot/Ocelot/artifacts/UnitTests/*/ | head -1)
echo "Detected first folder : $coverage_1st_folder"
coverage_file="${coverage_1st_folder%/}/coverage.cobertura.xml"
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,12 @@ jobs:
build-cake:
needs: build
runs-on: ubuntu-latest
environment: build.cake
env:
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
GITHUB_SHA: ${{ github.sha }}
GITHUB_REF: ${{ github.ref }}
GITHUB_REF_NAME: ${{ github.ref_name }}
# environment: Pull-Request
# env:
# COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
# GITHUB_SHA: ${{ github.sha }}
# GITHUB_REF: ${{ github.ref }}
# GITHUB_REF_NAME: ${{ github.ref_name }}
steps:
- name: .NET Info
run: |
Expand Down
18 changes: 17 additions & 1 deletion docs/features/caching.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,17 @@ The second step is to add the following to your `Program`_:
Configuration
-------------

Finally, in order to use caching on a route in your route configuration add this setting:
Finally, in order to use caching on a route in your route configuration add these sections:

.. code-block:: json

"CacheOptions": {
"TtlSeconds": 1, // nullable integer
"Region": "",
"Header": "",
"EnableContentHashing": false // nullable boolean
},
// Warning! FileCacheOptions section is deprecated! -> use CacheOptions
"FileCacheOptions": {
"TtlSeconds": 15,
"Region": "europe-central",
Expand All @@ -48,6 +55,15 @@ Finally, in order to use caching on a route in your route configuration add this
* If a header name is defined in the ``Header`` property, that header value is looked up by the key (header name) in the ``HttpRequest`` headers, and if the header is found, its value will be included in caching key.
This causes the cache to become invalid due to the header value changing.

.. _24.1: https://github.com/ThreeMammals/Ocelot/releases/tag/24.1.0
.. _25.0: https://github.com/ThreeMammals/Ocelot/milestone/12
.. warning::
Static route ``FileCacheOptions`` section is deprecated!

The `old schema <https://github.com/ThreeMammals/Ocelot/blob/24.0.0/src/Ocelot/Configuration/File/FileRoute.cs#L75>`_ ``FileCacheOptions`` section is deprecated in version `24.1`_!
Use ``CacheOptions`` instead of ``FileCacheOptions``! Note that ``FileCacheOptions`` will be removed in version `25.0`_!
For backward compatibility in version `24.1`_, the ``FileCacheOptions`` section takes precedence over the ``CacheOptions`` section.

.. _caching-enablecontenthashing-option:

``EnableContentHashing`` option
Expand Down
7 changes: 6 additions & 1 deletion docs/features/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ You do not need to set all of these things, but this is everything that is avail
"DownstreamHttpVersionPolicy": "",
"DownstreamPathTemplate": "",
"DownstreamScheme": "",
"FileCacheOptions": {}, // object
"CacheOptions": {}, // object
"FileCacheOptions": {}, // deprecated! -> use CacheOptions
"HttpHandlerOptions": {}, // object
"Key": "",
"LoadBalancerOptions": {}, // object
Expand All @@ -103,6 +104,10 @@ You do not need to set all of these things, but this is everything that is avail

The actual route schema with all the properties can be found in the C# `FileRoute`_ class.

**Note**: The `old schema <https://github.com/ThreeMammals/Ocelot/blob/24.0.0/src/Ocelot/Configuration/File/FileRoute.cs#L75>`__ ``FileCacheOptions`` section is deprecated in version `24.1`_!
Use ``CacheOptions`` instead of ``FileCacheOptions``! Note that ``FileCacheOptions`` will be removed in version `25.0`_!
For backward compatibility in version `24.1`_, the ``FileCacheOptions`` section takes precedence over the ``CacheOptions`` section.

.. _config-dynamic-route-schema:

Dynamic Route Schema
Expand Down
2 changes: 1 addition & 1 deletion src/Ocelot.Provider.Kubernetes/KubeServiceCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ protected virtual string GetServiceName(KubeRegistryConfiguration configuration,
protected virtual ServiceHostAndPort GetServiceHostAndPort(KubeRegistryConfiguration configuration, EndpointsV1 endpoint, EndpointSubsetV1 subset, EndpointAddressV1 address)
{
var ports = subset.Ports;
bool portNameToScheme(EndpointPortV1 p) => string.Equals(p.Name, configuration.Scheme, StringComparison.InvariantCultureIgnoreCase);
bool portNameToScheme(EndpointPortV1 p) => string.Equals(p.Name, configuration.Scheme, StringComparison.OrdinalIgnoreCase);
var portV1 = string.IsNullOrEmpty(configuration.Scheme) || !ports.Any(portNameToScheme)
? ports.FirstOrDefault()
: ports.FirstOrDefault(portNameToScheme);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public ResiliencePipeline<HttpResponseMessage> GetResiliencePipeline(DownstreamR
}

return _registry.GetOrAddPipeline<HttpResponseMessage>(
key: new OcelotResiliencePipelineKey(GetRouteName(route)),
key: new OcelotResiliencePipelineKey(route.LoadBalancerKey),
configure: (builder) => ConfigureStrategies(builder, route));
}

Expand Down
9 changes: 4 additions & 5 deletions src/Ocelot/Configuration/Builder/DownstreamRouteBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Ocelot.Configuration.Creator;
using Ocelot.Infrastructure.Extensions;
using Ocelot.Values;

namespace Ocelot.Configuration.Builder;
Expand All @@ -9,7 +10,7 @@ public class DownstreamRouteBuilder
private string _loadBalancerKey;
private string _downstreamPathTemplate;
private UpstreamPathTemplate _upstreamTemplatePattern;
private List<HttpMethod> _upstreamHttpMethod;
private HashSet<HttpMethod> _upstreamHttpMethod;
private bool _isAuthenticated;
private List<ClaimToThing> _claimsToHeaders;
private List<ClaimToThing> _claimToClaims;
Expand Down Expand Up @@ -88,11 +89,9 @@ public DownstreamRouteBuilder WithUpstreamPathTemplate(UpstreamPathTemplate inpu
return this;
}

public DownstreamRouteBuilder WithUpstreamHttpMethod(List<string> input)
public DownstreamRouteBuilder WithUpstreamHttpMethod(IEnumerable<string> methods)
{
_upstreamHttpMethod = input.Count > 0
? input.Select(x => new HttpMethod(x.Trim())).ToList()
: new();
_upstreamHttpMethod = methods.ToHttpMethods();
return this;
}

Expand Down
6 changes: 0 additions & 6 deletions src/Ocelot/Configuration/Builder/QoSOptionsBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@ public QoSOptionsBuilder WithTimeoutValue(int? value)
return this;
}

public QoSOptionsBuilder WithKey(string value)
{
Key = value;
return this;
}

public QoSOptionsBuilder WithFailureRatio(double? value)
{
FailureRatio = value;
Expand Down
81 changes: 0 additions & 81 deletions src/Ocelot/Configuration/Builder/RouteBuilder.cs

This file was deleted.

24 changes: 12 additions & 12 deletions src/Ocelot/Configuration/Creator/AggregatesCreator.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.File;
using Ocelot.Infrastructure.Extensions;

namespace Ocelot.Configuration.Creator;

Expand Down Expand Up @@ -39,16 +39,16 @@ private Route SetUpAggregateRoute(IEnumerable<Route> routes, FileAggregateRoute

var upstreamTemplatePattern = _creator.Create(aggregateRoute);
var upstreamHeaderTemplates = _headerCreator.Create(aggregateRoute);
var upstreamHttpMethod = (aggregateRoute.UpstreamHttpMethod.Count == 0) ? new List<HttpMethod>()
: aggregateRoute.UpstreamHttpMethod.Select(x => new HttpMethod(x.Trim())).ToList();

return new Route(
applicableRoutes,
aggregateRoute.RouteKeysConfig,
upstreamHttpMethod,
upstreamTemplatePattern,
aggregateRoute.UpstreamHost,
aggregateRoute.Aggregator,
upstreamHeaderTemplates);
var upstreamHttpMethod = aggregateRoute.UpstreamHttpMethod.ToHttpMethods();
return new Route()
{
Aggregator = aggregateRoute.Aggregator,
DownstreamRoute = applicableRoutes,
DownstreamRouteConfig = aggregateRoute.RouteKeysConfig,
UpstreamHeaderTemplates = upstreamHeaderTemplates,
UpstreamHost = aggregateRoute.UpstreamHost,
UpstreamHttpMethod = upstreamHttpMethod,
UpstreamTemplatePattern = upstreamTemplatePattern,
};
}
}
17 changes: 10 additions & 7 deletions src/Ocelot/Configuration/Creator/CacheOptionsCreator.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
using Ocelot.Configuration.File;
using Ocelot.Infrastructure.Extensions;

namespace Ocelot.Configuration.Creator;

public class CacheOptionsCreator : ICacheOptionsCreator
{
public CacheOptions Create(FileCacheOptions options, FileGlobalConfiguration global, string upstreamPathTemplate, IList<string> upstreamHttpMethods)
public CacheOptions Create(FileCacheOptions options, FileGlobalConfiguration globalConfiguration, string upstreamPathTemplate, IReadOnlyCollection<string> upstreamHttpMethods)
{
var region = GetRegion(options.Region ?? global?.CacheOptions.Region, upstreamPathTemplate, upstreamHttpMethods);
var header = options.Header ?? global?.CacheOptions.Header;
var ttlSeconds = options.TtlSeconds ?? global?.CacheOptions.TtlSeconds;
var enableContentHashing = options.EnableContentHashing ?? global?.CacheOptions.EnableContentHashing;
options ??= new();
var global = globalConfiguration?.CacheOptions ?? new();
var region = GetRegion(options.Region.IfEmpty(global.Region), upstreamPathTemplate, upstreamHttpMethods);
var header = options.Header.IfEmpty(global.Header);
var ttlSeconds = options.TtlSeconds ?? global.TtlSeconds;
var enableHashing = options.EnableContentHashing ?? global.EnableContentHashing;

return new CacheOptions(ttlSeconds, region, header, enableContentHashing);
return new CacheOptions(ttlSeconds, region, header, enableHashing);
}

protected virtual string GetRegion(string region, string upstreamPathTemplate, IList<string> upstreamHttpMethod)
protected virtual string GetRegion(string region, string upstreamPathTemplate, IReadOnlyCollection<string> upstreamHttpMethod)
{
if (!string.IsNullOrEmpty(region))
{
Expand Down
44 changes: 24 additions & 20 deletions src/Ocelot/Configuration/Creator/ConfigurationCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public class ConfigurationCreator : IConfigurationCreator
private readonly ILoadBalancerOptionsCreator _loadBalancerOptionsCreator;
private readonly IVersionCreator _versionCreator;
private readonly IVersionPolicyCreator _versionPolicyCreator;
private readonly IMetadataCreator _metadataCreator;
private readonly IRateLimitOptionsCreator _rateLimitOptionsCreator;

public ConfigurationCreator(
IServiceProviderConfigurationCreator serviceProviderConfigCreator,
Expand All @@ -21,44 +23,46 @@ public ConfigurationCreator(
IServiceProvider serviceProvider,
ILoadBalancerOptionsCreator loadBalancerOptionsCreator,
IVersionCreator versionCreator,
IVersionPolicyCreator versionPolicyCreator
)
IVersionPolicyCreator versionPolicyCreator,
IMetadataCreator metadataCreator,
IRateLimitOptionsCreator rateLimitOptionsCreator)
{
_adminPath = serviceProvider.GetService<IAdministrationPath>();
_loadBalancerOptionsCreator = loadBalancerOptionsCreator;
_serviceProviderConfigCreator = serviceProviderConfigCreator;
_qosOptionsCreator = qosOptionsCreator;
_httpHandlerOptionsCreator = httpHandlerOptionsCreator;
_versionCreator = versionCreator;
_versionPolicyCreator = versionPolicyCreator;
_versionPolicyCreator = versionPolicyCreator;
_metadataCreator = metadataCreator;
_rateLimitOptionsCreator = rateLimitOptionsCreator;
}

public InternalConfiguration Create(FileConfiguration fileConfiguration, List<Route> routes)
public InternalConfiguration Create(FileConfiguration configuration, List<Route> routes)
{
var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileConfiguration.GlobalConfiguration);

var lbOptions = _loadBalancerOptionsCreator.Create(fileConfiguration.GlobalConfiguration.LoadBalancerOptions);

var qosOptions = _qosOptionsCreator.Create(fileConfiguration.GlobalConfiguration.QoSOptions);

var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileConfiguration.GlobalConfiguration.HttpHandlerOptions);

var adminPath = _adminPath?.Path;

var version = _versionCreator.Create(fileConfiguration.GlobalConfiguration.DownstreamHttpVersion);

var versionPolicy = _versionPolicyCreator.Create(fileConfiguration.GlobalConfiguration.DownstreamHttpVersionPolicy);
var globalConfiguration = configuration.GlobalConfiguration ?? new();
var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(globalConfiguration);
var lbOptions = _loadBalancerOptionsCreator.Create(globalConfiguration.LoadBalancerOptions);
var qosOptions = _qosOptionsCreator.Create(globalConfiguration.QoSOptions);
var httpHandlerOptions = _httpHandlerOptionsCreator.Create(globalConfiguration.HttpHandlerOptions);
var version = _versionCreator.Create(globalConfiguration.DownstreamHttpVersion);
var versionPolicy = _versionPolicyCreator.Create(globalConfiguration.DownstreamHttpVersionPolicy);
var metadataOptions = _metadataCreator.Create(null, globalConfiguration);
var rateLimitOptions = _rateLimitOptionsCreator.Create(globalConfiguration);

return new InternalConfiguration(routes,
adminPath,
serviceProviderConfiguration,
fileConfiguration.GlobalConfiguration.RequestIdKey,
globalConfiguration.RequestIdKey,
lbOptions,
fileConfiguration.GlobalConfiguration.DownstreamScheme,
globalConfiguration.DownstreamScheme,
qosOptions,
httpHandlerOptions,
version,
versionPolicy
);
versionPolicy,
metadataOptions,
rateLimitOptions,
globalConfiguration.Timeout);
}
}
Loading