Ejemplo n.º 1
0
        private static StructuredTransformer CreateTransformer(TransformBuilderContext context)
        {
            // RequestHeaderOriginalHostKey defaults to false, and CopyRequestHeaders defaults to true.
            // If RequestHeaderOriginalHostKey was not specified then we need to make sure the transform gets
            // added anyways to remove the original host. If CopyRequestHeaders is false then we can omit the
            // transform.
            if (context.CopyRequestHeaders.GetValueOrDefault(true) &&
                !context.RequestTransforms.Any(item => item is RequestHeaderOriginalHostTransform))
            {
                context.AddOriginalHost(false);
            }

            // Add default forwarders only if they haven't already been added or disabled.
            if (context.UseDefaultForwarders.GetValueOrDefault(true))
            {
                context.AddXForwarded();
            }

            return(new StructuredTransformer(
                       context.CopyRequestHeaders,
                       context.CopyResponseHeaders,
                       context.CopyResponseTrailers,
                       context.RequestTransforms,
                       context.ResponseTransforms,
                       context.ResponseTrailersTransforms));
        }
Ejemplo n.º 2
0
        public bool Build(TransformBuilderContext context, IReadOnlyDictionary <string, string> transformValues)
        {
            if (transformValues.TryGetValue(XForwardedKey, out var xforwardedHeaders))
            {
                var expected = 1;

                var append = true;
                if (transformValues.TryGetValue(AppendKey, out var appendValue))
                {
                    expected++;
                    append = bool.Parse(appendValue);
                }

                var prefix = "X-Forwarded-";
                if (transformValues.TryGetValue(PrefixForwardedKey, out var prefixValue))
                {
                    expected++;
                    prefix = prefixValue;
                }

                TransformHelpers.CheckTooManyParameters(transformValues, expected);

                // for, host, proto, Prefix
                var  tokens = xforwardedHeaders.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                bool useFor, useHost, useProto, usePrefix;
                useFor = useHost = useProto = usePrefix = false;

                foreach (var token in tokens)
                {
                    if (string.Equals(token, ForKey, StringComparison.OrdinalIgnoreCase))
                    {
                        useFor = true;
                    }
                    else if (string.Equals(token, HostKey, StringComparison.OrdinalIgnoreCase))
                    {
                        useHost = true;
                    }
                    else if (string.Equals(token, ProtoKey, StringComparison.OrdinalIgnoreCase))
                    {
                        useProto = true;
                    }
                    else if (string.Equals(token, PrefixKey, StringComparison.OrdinalIgnoreCase))
                    {
                        usePrefix = true;
                    }
                    else
                    {
                        throw new ArgumentException($"Unexpected value for X-Forwarded: {token}. Expected 'for', 'host', 'proto', or 'Prefix'");
                    }
                }

                context.AddXForwarded(prefix, useFor, useHost, useProto, usePrefix, append);
            }
            else if (transformValues.TryGetValue(ForwardedKey, out var forwardedHeader))
            {
                var useHost   = false;
                var useProto  = false;
                var useFor    = false;
                var useBy     = false;
                var forFormat = NodeFormat.None;
                var byFormat  = NodeFormat.None;

                // for, host, proto, Prefix
                var tokens = forwardedHeader.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);

                foreach (var token in tokens)
                {
                    if (string.Equals(token, ForKey, StringComparison.OrdinalIgnoreCase))
                    {
                        useFor    = true;
                        forFormat = NodeFormat.Random; // RFC Default
                    }
                    else if (string.Equals(token, ByKey, StringComparison.OrdinalIgnoreCase))
                    {
                        useBy    = true;
                        byFormat = NodeFormat.Random; // RFC Default
                    }
                    else if (string.Equals(token, HostKey, StringComparison.OrdinalIgnoreCase))
                    {
                        useHost = true;
                    }
                    else if (string.Equals(token, ProtoKey, StringComparison.OrdinalIgnoreCase))
                    {
                        useProto = true;
                    }
                    else
                    {
                        throw new ArgumentException($"Unexpected value for X-Forwarded: {token}. Expected 'for', 'host', 'proto', or 'by'");
                    }
                }

                var expected = 1;

                var append = true;
                if (transformValues.TryGetValue(AppendKey, out var appendValue))
                {
                    expected++;
                    append = bool.Parse(appendValue);
                }

                if (useFor && transformValues.TryGetValue(ForFormatKey, out var forFormatString))
                {
                    expected++;
                    forFormat = Enum.Parse <NodeFormat>(forFormatString, ignoreCase: true);
                }

                if (useBy && transformValues.TryGetValue(ByFormatKey, out var byFormatString))
                {
                    expected++;
                    byFormat = Enum.Parse <NodeFormat>(byFormatString, ignoreCase: true);
                }

                TransformHelpers.CheckTooManyParameters(transformValues, expected);

                context.UseDefaultForwarders = false;
                if (useBy || useFor || useHost || useProto)
                {
                    // Not using the extension to avoid resolving the random factory each time.
                    context.RequestTransforms.Add(new RequestHeaderForwardedTransform(_randomFactory, forFormat, byFormat, useHost, useProto, append));
                }
            }
            else if (transformValues.TryGetValue(ClientCertKey, out var clientCertHeader))
            {
                TransformHelpers.CheckTooManyParameters(transformValues, expected: 1);
                context.AddClientCertHeader(clientCertHeader);
            }
            else
            {
                return(false);
            }

            return(true);
        }
Ejemplo n.º 3
0
        // This is separate from Build for testing purposes.
        internal StructuredTransformer BuildInternal(ProxyRoute route, Cluster cluster)
        {
            var rawTransforms = route.Transforms;

            var context = new TransformBuilderContext
            {
                Services = _services,
                Route    = route,
                Cluster  = cluster,
            };

            if (rawTransforms?.Count > 0)
            {
                foreach (var rawTransform in rawTransforms)
                {
                    var handled = false;
                    foreach (var factory in _factories)
                    {
                        if (factory.Build(context, rawTransform))
                        {
                            handled = true;
                            break;
                        }
                    }

                    if (!handled)
                    {
                        throw new ArgumentException($"Unknown transform: {string.Join(';', rawTransform.Keys)}");
                    }
                }
            }

            // Let the app add any more transforms it wants.
            foreach (var transformProvider in _providers)
            {
                transformProvider.Apply(context);
            }

            // Suppress the host by default
            if (context.CopyRequestHeaders.GetValueOrDefault(true) && !context.UseOriginalHost.GetValueOrDefault())
            {
                // Headers were automatically copied, remove the Host header afterwards.
                context.RequestTransforms.Add(new RequestHeaderValueTransform(HeaderNames.Host, string.Empty, append: false));
            }
            else if (!context.CopyRequestHeaders.GetValueOrDefault(true) && context.UseOriginalHost.GetValueOrDefault())
            {
                // Headers were not copied, copy the Host manually.
                context.RequestTransforms.Add(RequestCopyHostTransform.Instance);
            }

            // Add default forwarders only if they haven't already been added or disabled.
            if (context.UseDefaultForwarders.GetValueOrDefault(true))
            {
                context.AddXForwarded();
            }

            return(new StructuredTransformer(
                       context.CopyRequestHeaders,
                       context.CopyResponseHeaders,
                       context.CopyResponseTrailers,
                       context.RequestTransforms,
                       context.ResponseTransforms,
                       context.ResponseTrailersTransforms));
        }
        // This is separate from Build for testing purposes.
        internal StructuredTransformer BuildInternal(ProxyRoute route, Cluster cluster)
        {
            var rawTransforms = route.Transforms;

            var context = new TransformBuilderContext
            {
                Services = _services,
                Route    = route,
                Cluster  = cluster,
            };

            if (rawTransforms?.Count > 0)
            {
                foreach (var rawTransform in rawTransforms)
                {
                    var handled = false;
                    foreach (var factory in _factories)
                    {
                        if (factory.Build(context, rawTransform))
                        {
                            handled = true;
                            break;
                        }
                    }

                    if (!handled)
                    {
                        throw new ArgumentException($"Unknown transform: {string.Join(';', rawTransform.Keys)}");
                    }
                }
            }

            // Let the app add any more transforms it wants.
            foreach (var transformProvider in _providers)
            {
                transformProvider.Apply(context);
            }

            // RequestHeaderOriginalHostKey defaults to false, and CopyRequestHeaders defaults to true.
            // If RequestHeaderOriginalHostKey was not specified then we need to make sure the transform gets
            // added anyways to remove the original host. If CopyRequestHeaders is false then we can omit the
            // transform.
            if (context.CopyRequestHeaders.GetValueOrDefault(true) &&
                !context.RequestTransforms.Any(item => item is RequestHeaderOriginalHostTransform))
            {
                context.AddOriginalHost(false);
            }

            // Add default forwarders only if they haven't already been added or disabled.
            if (context.UseDefaultForwarders.GetValueOrDefault(true))
            {
                context.AddXForwarded();
            }

            return(new StructuredTransformer(
                       context.CopyRequestHeaders,
                       context.CopyResponseHeaders,
                       context.CopyResponseTrailers,
                       context.RequestTransforms,
                       context.ResponseTransforms,
                       context.ResponseTrailersTransforms));
        }