public void FindAffinitizedDestination_AffinityDisabledOnCluster_ReturnsAffinityDisabled()
        {
            var provider = new ProviderStub(GetDataProtector().Object, AffinityTestHelper.GetLogger <BaseSessionAffinityProvider <string> >().Object);
            var options  = new ClusterSessionAffinityOptions(false, _defaultOptions.Mode, _defaultOptions.FailurePolicy, _defaultOptions.Settings);

            Assert.Throws <InvalidOperationException>(() => provider.FindAffinitizedDestinations(new DefaultHttpContext(), new[] { new DestinationInfo("1") }, "cluster-1", options));
        }
Example #2
0
        public Task <bool> Handle(HttpContext context, ClusterSessionAffinityOptions options, AffinityStatus affinityStatus)
        {
            if (affinityStatus == AffinityStatus.OK ||
                affinityStatus == AffinityStatus.AffinityKeyNotSet)
            {
                throw new InvalidOperationException($"{nameof(Return503ErrorAffinityFailurePolicy)} is called to handle a successful request's affinity status {affinityStatus}.");
            }

            context.Response.StatusCode = 503;
            return(TaskUtilities.FalseTask);
        }
        public Task <bool> Handle(HttpContext context, ClusterSessionAffinityOptions options, AffinityStatus affinityStatus)
        {
            if (affinityStatus == AffinityStatus.OK ||
                affinityStatus == AffinityStatus.AffinityKeyNotSet)
            {
                throw new InvalidOperationException($"{nameof(RedistributeAffinityFailurePolicy)} is called to handle a successful request's affinity status {affinityStatus}.");
            }

            // Available destinations list have not been changed in the context,
            // so simply allow processing to proceed to load balancing.
            return(TaskUtilities.TrueTask);
        }
        public void FindAffinitizedDestination_CustomHeaderNameIsNotSpecified_UseDefaultName(Dictionary <string, string> settings)
        {
            var options  = new ClusterSessionAffinityOptions(true, "CustomHeader", "Return503", settings);
            var provider = new CustomHeaderSessionAffinityProvider(AffinityTestHelper.GetDataProtector().Object, AffinityTestHelper.GetLogger <CustomHeaderSessionAffinityProvider>().Object);
            var context  = new DefaultHttpContext();
            var affinitizedDestination = _destinations[1];

            context.Request.Headers[CustomHeaderSessionAffinityProvider.DefaultCustomHeaderName] = new[] { affinitizedDestination.DestinationId.ToUTF8BytesInBase64() };

            var affinityResult = provider.FindAffinitizedDestinations(context, _destinations, "cluster-1", options);

            Assert.Equal(AffinityStatus.OK, affinityResult.Status);
            Assert.Equal(1, affinityResult.Destinations.Count);
            Assert.Same(affinitizedDestination, affinityResult.Destinations[0]);
        }
        private void AffinitizeRequest(HttpContext context, ClusterSessionAffinityOptions options, DestinationInfo destination)
        {
            var currentProvider = _sessionAffinityProviders.GetRequiredServiceById(options.Mode, SessionAffinityConstants.Modes.Cookie);

            currentProvider.AffinitizeRequest(context, options, destination);
        }
        private async Task InvokeInternal(HttpContext context, IReverseProxyFeature proxyFeature, ClusterSessionAffinityOptions options, string clusterId)
        {
            var destinations = proxyFeature.AvailableDestinations;

            var currentProvider = _sessionAffinityProviders.GetRequiredServiceById(options.Mode, SessionAffinityConstants.Modes.Cookie);
            var affinityResult  = currentProvider.FindAffinitizedDestinations(context, destinations, clusterId, options);

            switch (affinityResult.Status)
            {
            case AffinityStatus.OK:
                proxyFeature.AvailableDestinations = affinityResult.Destinations;
                break;

            case AffinityStatus.AffinityKeyNotSet:
                // Nothing to do so just continue processing
                break;

            case AffinityStatus.AffinityKeyExtractionFailed:
            case AffinityStatus.DestinationNotFound:

                var failurePolicy  = _affinityFailurePolicies.GetRequiredServiceById(options.FailurePolicy, SessionAffinityConstants.AffinityFailurePolicies.Redistribute);
                var keepProcessing = await failurePolicy.Handle(context, options, affinityResult.Status);

                if (!keepProcessing)
                {
                    // Policy reported the failure is unrecoverable and took the full responsibility for its handling,
                    // so we simply stop processing.
                    Log.AffinityResolutionFailedForCluster(_logger, clusterId);
                    return;
                }

                Log.AffinityResolutionFailureWasHandledProcessingWillBeContinued(_logger, clusterId, options.FailurePolicy);

                break;

            default:
                throw new NotSupportedException($"Affinity status '{affinityResult.Status}' is not supported.");
            }

            await _next(context);
        }