public async Task Proto_Added(string startValue, string scheme, ForwardedTransformActions action, string expected)
        {
            var randomFactory = new TestRandomFactory();
            var httpContext   = new DefaultHttpContext();

            httpContext.Request.Scheme = scheme;
            var proxyRequest = new HttpRequestMessage();

            proxyRequest.Headers.Add("Forwarded", startValue.Split("|", StringSplitOptions.RemoveEmptyEntries));
            var transform = new RequestHeaderForwardedTransform(randomFactory, forFormat: NodeFormat.None,
                                                                byFormat: NodeFormat.None, host: false, proto: true, action);
            await transform.ApplyAsync(new RequestTransformContext()
            {
                HttpContext   = httpContext,
                ProxyRequest  = proxyRequest,
                HeadersCopied = true,
            });

            if (string.IsNullOrEmpty(expected))
            {
                Assert.False(proxyRequest.Headers.TryGetValues("Forwarded", out _));
            }
            else
            {
                Assert.Equal(expected.Split("|", StringSplitOptions.RemoveEmptyEntries), proxyRequest.Headers.GetValues("Forwarded"));
            }
        }
        public async Task AllValues_Added(string startValue, ForwardedTransformActions action, string expected)
        {
            var randomFactory = new TestRandomFactory();

            randomFactory.Instance = new TestRandom()
            {
                Sequence = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 }
            };
            var httpContext = new DefaultHttpContext();

            httpContext.Request.Scheme             = "https";
            httpContext.Request.Host               = new HostString("myHost", 80);
            httpContext.Connection.RemoteIpAddress = IPAddress.IPv6Loopback;
            httpContext.Connection.RemotePort      = 10;
            var proxyRequest = new HttpRequestMessage();

            proxyRequest.Headers.Add("Forwarded", startValue.Split("|", StringSplitOptions.RemoveEmptyEntries));
            var transform = new RequestHeaderForwardedTransform(randomFactory,
                                                                forFormat: NodeFormat.IpAndPort,
                                                                byFormat: NodeFormat.Random,
                                                                host: true, proto: true, action);
            await transform.ApplyAsync(new RequestTransformContext()
            {
                HttpContext   = httpContext,
                ProxyRequest  = proxyRequest,
                HeadersCopied = true,
            });

            Assert.Equal(expected.Split("|", StringSplitOptions.RemoveEmptyEntries), proxyRequest.Headers.GetValues("Forwarded"));
        }
        public async Task Scheme_Added(string startValue, string scheme, ForwardedTransformActions action, string expected)
        {
            var httpContext = new DefaultHttpContext();

            httpContext.Request.Scheme = scheme;
            var proxyRequest = new HttpRequestMessage();

            proxyRequest.Headers.Add("name", startValue.Split(";", StringSplitOptions.RemoveEmptyEntries));
            var transform = new RequestHeaderXForwardedProtoTransform("name", action);
            await transform.ApplyAsync(new RequestTransformContext()
            {
                HttpContext   = httpContext,
                ProxyRequest  = proxyRequest,
                HeadersCopied = true,
            });

            if (string.IsNullOrEmpty(expected))
            {
                Assert.False(proxyRequest.Headers.TryGetValues("name", out var _));
            }
            else
            {
                Assert.Equal(expected.Split(";", StringSplitOptions.RemoveEmptyEntries), proxyRequest.Headers.GetValues("name"));
            }
        }
Exemple #4
0
    public void AddXForwarded(Func <TransformBuilderContext, string, ForwardedTransformActions, TransformBuilderContext> addFunc,
                              string transformName, ForwardedTransformActions action)
    {
        var builderContext = CreateBuilderContext();

        addFunc(builderContext, "prefix-" + transformName, action);

        ValidateXForwarded(builderContext, transformName, "prefix-", action);
    }
 public RequestHeaderForwardedTransform(IRandomFactory randomFactory, NodeFormat forFormat, NodeFormat byFormat, bool host, bool proto, ForwardedTransformActions action)
 {
     _randomFactory = randomFactory ?? throw new ArgumentNullException(nameof(randomFactory));
     ForFormat      = forFormat;
     ByFormat       = byFormat;
     HostEnabled    = host;
     ProtoEnabled   = proto;
     Debug.Assert(action != ForwardedTransformActions.Off);
     TransformAction = action;
 }
Exemple #6
0
    public RequestHeaderXForwardedPrefixTransform(string headerName, ForwardedTransformActions action)
    {
        if (string.IsNullOrEmpty(headerName))
        {
            throw new ArgumentException($"'{nameof(headerName)}' cannot be null or empty.", nameof(headerName));
        }

        HeaderName = headerName;
        Debug.Assert(action != ForwardedTransformActions.Off);
        TransformAction = action;
    }
Exemple #7
0
    public void WithTransformXForwarded(
        ForwardedTransformActions xDefault,
        ForwardedTransformActions?xFor,
        ForwardedTransformActions?xHost,
        ForwardedTransformActions?xProto,
        ForwardedTransformActions?xPrefix)
    {
        var routeConfig = new RouteConfig();
        var prefix      = "prefix-";

        routeConfig = routeConfig.WithTransformXForwarded(prefix, xDefault, xFor, xHost, xProto, xPrefix);

        var builderContext = ValidateAndBuild(routeConfig, _factory);

        if (xFor != ForwardedTransformActions.Off)
        {
            ValidateXForwardedTransform("For", prefix, xFor ?? xDefault, builderContext.RequestTransforms.OfType <RequestHeaderXForwardedForTransform>().Single());
        }
        else
        {
            Assert.Empty(builderContext.RequestTransforms.OfType <RequestHeaderXForwardedForTransform>());
        }

        if (xHost != ForwardedTransformActions.Off)
        {
            ValidateXForwardedTransform("Host", prefix, xHost ?? xDefault, builderContext.RequestTransforms.OfType <RequestHeaderXForwardedHostTransform>().Single());
        }
        else
        {
            Assert.Empty(builderContext.RequestTransforms.OfType <RequestHeaderXForwardedHostTransform>());
        }

        if (xProto != ForwardedTransformActions.Off)
        {
            ValidateXForwardedTransform("Proto", prefix, xProto ?? xDefault, builderContext.RequestTransforms.OfType <RequestHeaderXForwardedProtoTransform>().Single());
        }
        else
        {
            Assert.Empty(builderContext.RequestTransforms.OfType <RequestHeaderXForwardedProtoTransform>());
        }

        if (xPrefix != ForwardedTransformActions.Off)
        {
            ValidateXForwardedTransform("Prefix", prefix, xPrefix ?? xDefault, builderContext.RequestTransforms.OfType <RequestHeaderXForwardedPrefixTransform>().Single());
        }
        else
        {
            Assert.Empty(builderContext.RequestTransforms.OfType <RequestHeaderXForwardedPrefixTransform>());
        }
    }
Exemple #8
0
        /// <summary>
        /// Clones the route and adds the transform which will add X-Forwarded-* headers.
        /// </summary>
        public static RouteConfig WithTransformXForwarded(
            this RouteConfig route,
            string headerPrefix = "X-Forwarded-",
            ForwardedTransformActions xDefault = ForwardedTransformActions.Set,
            ForwardedTransformActions?xFor     = null,
            ForwardedTransformActions?xHost    = null,
            ForwardedTransformActions?xProto   = null,
            ForwardedTransformActions?xPrefix  = null)
        {
            return(route.WithTransform(transform =>
            {
                transform[ForwardedTransformFactory.XForwardedKey] = xDefault.ToString();

                if (xFor != null)
                {
                    transform[ForwardedTransformFactory.ForKey] = xFor.Value.ToString();
                }

                if (xPrefix != null)
                {
                    transform[ForwardedTransformFactory.PrefixKey] = xPrefix.Value.ToString();
                }

                if (xHost != null)
                {
                    transform[ForwardedTransformFactory.HostKey] = xHost.Value.ToString();
                }

                if (xProto != null)
                {
                    transform[ForwardedTransformFactory.ProtoKey] = xProto.Value.ToString();
                }

                transform[ForwardedTransformFactory.HeaderPrefixKey] = headerPrefix;
            }));
        }
Exemple #9
0
 /// <summary>
 /// Adds the transform which will add X-Forwarded-Proto request header.
 /// </summary>
 public static TransformBuilderContext AddXForwardedProto(this TransformBuilderContext context, string headerName = "X-Forwarded-Proto", ForwardedTransformActions action = ForwardedTransformActions.Set)
 {
     context.UseDefaultForwarders = false;
     if (action == ForwardedTransformActions.Off)
     {
         return(context);
     }
     context.RequestTransforms.Add(new RequestHeaderXForwardedProtoTransform(headerName, action));
     return(context);
 }
Exemple #10
0
        /// <summary>
        /// Adds the transform which will add the Forwarded header as defined by [RFC 7239](https://tools.ietf.org/html/rfc7239).
        /// </summary>
        public static TransformBuilderContext AddForwarded(this TransformBuilderContext context,
                                                           bool useHost        = true, bool useProto = true, NodeFormat forFormat = NodeFormat.Random,
                                                           NodeFormat byFormat = NodeFormat.Random, ForwardedTransformActions action = ForwardedTransformActions.Set)
        {
            context.UseDefaultForwarders = false;

            if (action == ForwardedTransformActions.Off)
            {
                return(context);
            }

            if (byFormat != NodeFormat.None || forFormat != NodeFormat.None || useHost || useProto)
            {
                var random = context.Services.GetRequiredService <IRandomFactory>();
                context.RequestTransforms.Add(new RequestHeaderForwardedTransform(random,
                                                                                  forFormat, byFormat, useHost, useProto, action));

                // Remove the X-Forwarded headers when an Forwarded transform is enabled
                TransformHelpers.RemoveAllXForwardedHeaders(context, ForwardedTransformFactory.DefaultXForwardedPrefix);
            }
            return(context);
        }
Exemple #11
0
        /// <summary>
        /// Clones the route and adds the transform which will add the Forwarded header as defined by [RFC 7239](https://tools.ietf.org/html/rfc7239).
        /// </summary>
        public static RouteConfig WithTransformForwarded(this RouteConfig route, bool useHost = true, bool useProto    = true,
                                                         NodeFormat forFormat = NodeFormat.Random, NodeFormat byFormat = NodeFormat.Random, ForwardedTransformActions action = ForwardedTransformActions.Set)
        {
            var headers = new List <string>();

            if (forFormat != NodeFormat.None)
            {
                headers.Add(ForwardedTransformFactory.ForKey);
            }

            if (byFormat != NodeFormat.None)
            {
                headers.Add(ForwardedTransformFactory.ByKey);
            }

            if (useHost)
            {
                headers.Add(ForwardedTransformFactory.HostKey);
            }

            if (useProto)
            {
                headers.Add(ForwardedTransformFactory.ProtoKey);
            }

            return(route.WithTransform(transform =>
            {
                transform[ForwardedTransformFactory.ForwardedKey] = string.Join(',', headers);
                transform[ForwardedTransformFactory.ActionKey] = action.ToString();

                if (forFormat != NodeFormat.None)
                {
                    transform.Add(ForwardedTransformFactory.ForFormatKey, forFormat.ToString());
                }

                if (byFormat != NodeFormat.None)
                {
                    transform.Add(ForwardedTransformFactory.ByFormatKey, byFormat.ToString());
                }
            }));
        }
Exemple #12
0
        /// <summary>
        /// Adds the transform which will add X-Forwarded-* request headers.
        /// </summary>
        public static TransformBuilderContext AddXForwarded(this TransformBuilderContext context, ForwardedTransformActions action = ForwardedTransformActions.Set)
        {
            context.AddXForwardedFor(action: action);
            context.AddXForwardedPrefix(action: action);
            context.AddXForwardedHost(action: action);
            context.AddXForwardedProto(action: action);

            // Remove the Forwarded header when an X-Forwarded transform is enabled
            TransformHelpers.RemoveForwardedHeader(context);
            return(context);
        }
        public async Task By_Added(string startValue, string ip, int port, NodeFormat format, ForwardedTransformActions action, string expected)
        {
            var randomFactory = new TestRandomFactory();

            randomFactory.Instance = new TestRandom()
            {
                Sequence = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 }
            };
            var httpContext = new DefaultHttpContext();

            httpContext.Connection.LocalIpAddress = string.IsNullOrEmpty(ip) ? null : IPAddress.Parse(ip);
            httpContext.Connection.LocalPort      = port;
            var proxyRequest = new HttpRequestMessage();

            proxyRequest.Headers.Add("Forwarded", startValue.Split("|", StringSplitOptions.RemoveEmptyEntries));
            var transform = new RequestHeaderForwardedTransform(randomFactory, forFormat: NodeFormat.None,
                                                                byFormat: format, host: false, proto: false, action);
            await transform.ApplyAsync(new RequestTransformContext()
            {
                HttpContext   = httpContext,
                ProxyRequest  = proxyRequest,
                HeadersCopied = true,
            });

            Assert.Equal(expected.Split("|", StringSplitOptions.RemoveEmptyEntries), proxyRequest.Headers.GetValues("Forwarded"));
        }
 /// <summary>
 /// Adds the transform which will add X-Forwarded-* request headers.
 /// </summary>
 public static TransformBuilderContext AddXForwarded(this TransformBuilderContext context, ForwardedTransformActions action = ForwardedTransformActions.Set)
 {
     context.AddXForwardedFor(action: action);
     context.AddXForwardedPrefix(action: action);
     context.AddXForwardedHost(action: action);
     context.AddXForwardedProto(action: action);
     return(context);
 }