public async Task SetHeadersAsync_UpdateSetCookiesHeaderWithExistingValues_SetCookiesIsUpdatedAsync()
        {
            // Arrange
            var options = TestExtensions.CreateDefaultOptions();
            var proxy   = options.Routes["/api/"].Proxy !;

            proxy.DownstreamResponse.Headers.Cookies.Add(
                "sessionid",
                new GatewayOptions.RouteOptions.ProxyOptions.DownstreamResponseOptions.HeadersOptions.CookieOptions
            {
                Domain   = "new.com",
                HttpOnly = false,
                Secure   = false,
                SameSite = "lax"
            });

            var message = new HttpResponseMessage();

            message.Headers.Add(HeaderNames.SetCookie, "sessionId=a3fWa; Max-Age=2592000; httponly; samesite=none; secure; domain=old.com");

            // Act
            var response = await SetHeadersAsync(message, options);

            // Assert
            response.Headers[HeaderNames.SetCookie].Should().BeEquivalentTo(
                new[]
            {
                "sessionId=a3fWa; max-age=2592000; domain=new.com; samesite=lax"
            });
        }
        public async Task SetHeadersAsync_UpdateSetCookiesHeaderWithNotMatchingName_SetCookiesIsNotUpdatedAsync()
        {
            // Arrange
            var options = TestExtensions.CreateDefaultOptions();
            var proxy   = options.Routes["/api/"].Proxy !;

            proxy.DownstreamResponse.Headers.Cookies.Add(
                "randomCookieName",
                new GatewayOptions.RouteOptions.ProxyOptions.DownstreamResponseOptions.HeadersOptions.CookieOptions
            {
                Domain   = "new.com",
                HttpOnly = true,
                Secure   = true,
                SameSite = "lax"
            });

            var message = new HttpResponseMessage();

            message.Headers.Add(HeaderNames.SetCookie, "sessionId=a3fWa; Max-Age=2592000");

            // Act
            var response = await SetHeadersAsync(message, options);

            // Assert
            response.Headers[HeaderNames.SetCookie].Should().BeEquivalentTo(
                new[]
            {
                "sessionId=a3fWa; Max-Age=2592000"
            });
        }
        public void Evaluate_RouteVariableThatDoesntExist_EvaluatedToNull()
        {
            var options   = TestExtensions.CreateDefaultOptions("/product/:id");
            var variables = new Dictionary <string, string>();

            Evaluate("$id", options: options, variables: variables).Should().BeEmpty();
        }
        public async Task SetHeadersAsync_HeaderOverrides_HeadersIncludedAsync()
        {
            // Arrange
            var options        = TestExtensions.CreateDefaultOptions();
            var headersOptions = options.Routes["/api/"].Proxy !.DownstreamResponse.Headers;

            headersOptions.Overrides = new Dictionary <string, string[]>()
            {
        public void Evaluate_RouteVariableThatDoesntExistInPattern_EvaluatedToNull()
        {
            var options   = TestExtensions.CreateDefaultOptions("/product/");
            var variables = new Dictionary <string, string> {
                ["id"] = "some-prod-id"
            };

            Evaluate("$id", options: options, variables: variables).Should().Be("$id");
        }
        public void Evaluate_RouteVariable_Evaluated()
        {
            const string value     = "some-prod-id";
            var          options   = TestExtensions.CreateDefaultOptions("/product/:id");
            var          variables = new Dictionary <string, string> {
                ["id"] = value
            };

            Evaluate(GetVarName("id"), options: options, variables: variables).Should().Be(value);
        }
        public void Evaluate_RouteVariables_Evaluated()
        {
            const string idValue   = "some-prod-id";
            const string catValue  = "some-cat-id";
            var          options   = TestExtensions.CreateDefaultOptions("/category/:catid/product/:id");
            var          variables = new Dictionary <string, string>
            {
                ["id"]    = idValue,
                ["catid"] = catValue
            };

            Evaluate("cat-id = $catid, id = $id", options: options, variables: variables)
            .Should().Be($"cat-id = {catValue}, id = {idValue}");
        }
        public async Task SetHeadersAsync_ProxyNameNotNull_ViaHeaderHasProxyNameAsync()
        {
            // Arrange
            var options = TestExtensions.CreateDefaultOptions();

            options.Routes["/api/"].Proxy !.ProxyName = "some-proxy";

            var context = new DefaultHttpContext();

            context.Request.Protocol = "HTTP/2";

            // Act
            var message = await SetHeadersAsync(context, options);

            // Assert
            message.Headers.GetValues(HeaderNames.Via).SingleOrDefault().Should().Be("2.0 some-proxy");
        }
        public async Task SetHeadersAsync_ProxyNameIsNull_DefaultViaHeaderAsync()
        {
            // Arrange
            var options = TestExtensions.CreateDefaultOptions();

            options.Routes["/api/"].Proxy !.ProxyName = null;

            var context = new DefaultHttpContext();

            context.Request.Protocol = "HTTP/1.1";

            // Act
            var message = await SetHeadersAsync(context, options);

            // Assert
            message.Headers.GetValues(HeaderNames.Via).SingleOrDefault().Should().Be("1.1 " + Constants.ServerName);
        }
        public async Task SetContentAsync_IgnoreHeaders_ContentHeadersNotIncludedAsync()
        {
            // Arrange
            var          header  = HeaderNames.ContentDisposition;
            const string value   = "some-value";
            var          message = CreateHttpResponseMessage((header, value));

            var options = TestExtensions.CreateDefaultOptions();

            options.Routes["/api/"].Proxy !.DownstreamResponse.Headers.DiscardInboundHeaders = true;

            // Act
            var response = await SetContentAsync(message, options : options);

            // Assert
            response.Headers.ContainsKey(header).Should().BeFalse();
        }
        public async Task SetHeadersAsync_ProxyNameIsNull_HeaderNotIncludedAsync()
        {
            // Arrange
            const string HeaderName = "x-gwcore-proxy-name";
            var          options    = TestExtensions.CreateDefaultOptions();

            options.Routes["/api/"].Proxy !.ProxyName = null;

            var context = new DefaultHttpContext();

            context.Request.Headers.Add(HeaderName, "some-value");

            // Act
            var message = await SetHeadersAsync(context, options);

            // Assert
            message.Headers.Contains(HeaderName).Should().BeFalse();
        }
        public async Task SetHeadersAsync_ProxyNameNotNullWithExistingViaSeparateHeaders_ViaHeaderHasProxyNameAsync()
        {
            // Arrange
            var options = TestExtensions.CreateDefaultOptions();

            options.Routes["/api/"].Proxy !.ProxyName = "some-proxy";

            var context = new DefaultHttpContext();

            context.Request.Protocol = "HTTP/2";
            context.Request.Headers.Add(HeaderNames.Via, new[] { "1.0 test", "1.1 test2" });

            // Act
            var message = await SetHeadersAsync(context, options);

            // Assert
            message.Headers.GetValues(HeaderNames.Via).Should().BeEquivalentTo(new[] { "1.0 test", "1.1 test2", "2.0 some-proxy" });
        }
        public async Task SetHeadersAsync_DiscardEmptyValue_HeaderDiscardedAsync()
        {
            // Arrange
            var options        = TestExtensions.CreateDefaultOptions();
            var headersOptions = options.Routes["/api/"].Proxy !.UpstreamRequest.Headers;

            headersOptions.DiscardEmpty = true;

            var context = new DefaultHttpContext();

            context.Request.Headers.Add("X-Empty-Header", string.Empty);

            // Act
            var message = await SetHeadersAsync(context, options);

            // Assert
            message.Headers.Contains("X-Empty-Header").Should().BeFalse();
        }
        public async Task SetHeadersAsync_RequestHasProxyNameHeaderWithProxyNameInSetings_HeaderNotIncludedAsync()
        {
            // Arrange
            var options = TestExtensions.CreateDefaultOptions();

            options.Routes["/api/"].Proxy !.ProxyName = "new-value";

            const string HeaderName = "x-gwcore-proxy-name";
            var          context    = new DefaultHttpContext();

            context.Request.Headers.Add(HeaderName, "some-value");

            // Act
            var message = await SetHeadersAsync(context, options : options);

            // Assert
            message.Headers.GetValues(HeaderName).SingleOrDefault().Should().Be("new-value");
        }
Example #15
0
        public async Task SetContentAsync_IgnoreHeaders_ContentHeadersNotIncludedAsync()
        {
            // Arrange
            var context = new DefaultHttpContext();
            var header  = HeaderNames.ContentLocation;

            context.Request.Headers.Add(header, "some-value");

            var options = TestExtensions.CreateDefaultOptions();

            options.Routes["/api/"].Proxy !.UpstreamRequest.Headers.DiscardInboundHeaders = true;

            // Act
            var message = await SetContentAsync(context, options : options);

            // Assert
            message.Content !.Headers.TryGetValues(header, out _).Should().BeFalse();
        }
        public async Task SetHeadersAsync_ProxyNameNotNull_ViaHeaderHasProxyNameAsync()
        {
            // Arrange
            var options = TestExtensions.CreateDefaultOptions();
            var proxy   = options.Routes["/api/"].Proxy !;

            proxy.ProxyName = "some-proxy";
            proxy.DownstreamResponse.Headers.DiscardInboundHeaders = false;
            proxy.DownstreamResponse.Headers.AddVia = true;

            var message = new HttpResponseMessage();

            // Act
            var response = await SetHeadersAsync(message, options);

            // Assert
            response.Headers[HeaderNames.Via].Should().BeEquivalentTo(new[] { "1.1 some-proxy" });
        }
        public async Task SetHeadersAsync_NotIncludeServer_HeaderNotIncludedAsync()
        {
            // Arrange
            var options        = TestExtensions.CreateDefaultOptions();
            var headersOptions = options.Routes["/api/"].Proxy !.DownstreamResponse.Headers;

            headersOptions.AddServer = false;

            var message = new HttpResponseMessage();

            message.Headers.Add(HeaderNames.Server, "old-value");

            // Act
            var response = await SetHeadersAsync(message, options);

            // Assert
            response.Headers.ContainsKey(HeaderNames.Server).Should().BeFalse();
        }
        public async Task SetHeadersAsync_IncludeServer_HeaderIncludedAsync()
        {
            // Arrange
            var options        = TestExtensions.CreateDefaultOptions();
            var headersOptions = options.Routes["/api/"].Proxy !.DownstreamResponse.Headers;

            headersOptions.AddServer = true;

            var message = new HttpResponseMessage();

            message.Headers.Add(HeaderNames.Server, "old-value");

            // Act
            var response = await SetHeadersAsync(message, options);

            // Assert
            response.Headers[HeaderNames.Server].Should().BeEquivalentTo(Constants.ServerName);
        }
        public async Task SetHeadersAsync_NotAddExternalAddress_HeaderNotIncludedAsync()
        {
            // Arrange
            const string HeaderName     = "x-gwcore-external-address";
            var          options        = TestExtensions.CreateDefaultOptions();
            var          headersOptions = options.Routes["/api/"].Proxy !.UpstreamRequest.Headers;

            headersOptions.AddExternalAddress = false;

            var context = new DefaultHttpContext();

            context.Connection.RemoteIpAddress = IpV4Sample;

            // Act
            var message = await SetHeadersAsync(context, options);

            // Assert
            message.Headers.Contains(HeaderName).Should().BeFalse();
        }
        public async Task SetHeadersAsync_IgnoreAllDownstreamHeaders_NoDownstreamHeaderIsIncludedAsync()
        {
            // Arrange
            const string HeaderName     = "x-custom-test";
            var          options        = TestExtensions.CreateDefaultOptions();
            var          headersOptions = options.Routes["/api/"].Proxy !.UpstreamRequest.Headers;

            headersOptions.DiscardInboundHeaders = true;

            var context = new DefaultHttpContext();

            context.Request.Headers.Add(HeaderName, "some-value");

            // Act
            var message = await SetHeadersAsync(context, options);

            // Assert
            message.Headers.Contains(HeaderName).Should().BeFalse();
        }
        public async Task SetHeadersAsync_NotIgnoreAllDownstreamHeaders_DownstreamHeadersAreIncludedAsync()
        {
            // Arrange
            const string HeaderName     = "x-custom-test";
            var          options        = TestExtensions.CreateDefaultOptions();
            var          headersOptions = options.Routes["/api/"].Proxy !.UpstreamRequest.Headers;

            headersOptions.DiscardInboundHeaders = false;

            var context = new DefaultHttpContext();

            context.Request.Headers.Add(HeaderName, new[] { "first-value", "second-value" });

            // Act
            var message = await SetHeadersAsync(context, options);

            // Assert
            message.Headers.GetValues(HeaderName).Should().BeEquivalentTo(new[] { "first-value", "second-value" });
        }
        public async Task SetHeadersAsync_NotIgnoreAllUpstreamResponseHeaders_DownstreamHeadersAreIncludedAsync()
        {
            // Arrange
            const string HeaderName     = "x-custom-test";
            var          options        = TestExtensions.CreateDefaultOptions();
            var          headersOptions = options.Routes["/api/"].Proxy !.DownstreamResponse.Headers;

            headersOptions.DiscardInboundHeaders = false;

            var message = new HttpResponseMessage();

            message.Headers.Add(HeaderName, new[] { "value-1", "value-2" });

            // Act
            var response = await SetHeadersAsync(message, options);

            // Assert
            response.Headers[HeaderName].Should().BeEquivalentTo(new[] { "value-1", "value-2" });
        }
        public async Task SetHeadersAsync_IgnoreAllUpstreamResponseHeaders_NoDownstreamHeaderIsIncludedAsync()
        {
            // Arrange
            const string HeaderName     = "x-custom-test";
            var          options        = TestExtensions.CreateDefaultOptions();
            var          headersOptions = options.Routes["/api/"].Proxy !.DownstreamResponse.Headers;

            headersOptions.DiscardInboundHeaders = true;

            var message = new HttpResponseMessage();

            message.Headers.Add(HeaderName, "some-value");

            // Act
            var response = await SetHeadersAsync(message, options);

            // Assert
            response.Headers.ContainsKey(HeaderName).Should().BeFalse();
        }
Example #24
0
        private static async Task CreateAndValidateAsync(
            string routePattern,
            string toExpression,
            string url,
            string expectedUrl)
        {
            var options         = TestExtensions.CreateDefaultOptions(routePattern, toExpression);
            var services        = new ServiceCollection().AddTest(gatewayOptions: options);
            var serviceProvider = services.BuildServiceProvider();
            var patternEngine   = serviceProvider.GetRequiredService <IPatternEngine>();
            var urlRewriter     = serviceProvider.GetRequiredService <IUpstreamUrlCreator>();

            UriHelper.FromAbsolute(
                url,
                out string scheme,
                out var host,
                out var path,
                out var query,
                out var _);

            patternEngine.TryMatch(
                routePattern,
                path.ToString(),
                out var match,
                out var why).Should().BeTrue();

            why.Should().BeNull();
            match.Should().NotBeNull();

            var httpContext = new DefaultHttpContext();
            var request     = httpContext.Request;

            request.Scheme      = scheme;
            request.Host        = host;
            request.Path        = path;
            request.QueryString = query;

            var context = serviceProvider.GetProxyContext(httpContext, match !.PathSuffix, match.Variables);
            var uri     = await urlRewriter.CreateAsync(context, default);

            uri.ToString().Should().BeEquivalentTo(expectedUrl);
        }
        public async Task SetHeadersAsync_DiscardWithUnderscore_HeaderDiscardedAsync()
        {
            // Arrange
            var options        = TestExtensions.CreateDefaultOptions();
            var headersOptions = options.Routes["/api/"].Proxy !.UpstreamRequest.Headers;

            headersOptions.DiscardUnderscore = true;

            var context = new DefaultHttpContext();

            context.Request.Headers.Add("X-Good-Header", "some-value");
            context.Request.Headers.Add("X_Bad_Header", "some-value");

            // Act
            var message = await SetHeadersAsync(context, options);

            // Assert
            message.Headers.Contains("X-Good-Header").Should().BeTrue();
            message.Headers.Contains("X_Bad_Header").Should().BeFalse();
        }
        public async Task SetHeadersAsync_DiscardUnderscore_HeaderDiscardedAsync()
        {
            // Arrange
            var options        = TestExtensions.CreateDefaultOptions();
            var headersOptions = options.Routes["/api/"].Proxy !.DownstreamResponse.Headers;

            headersOptions.DiscardUnderscore = true;

            var message = new HttpResponseMessage();

            message.Headers.Add("X-Good-Header", "some-value");
            message.Headers.Add("X_Bad_Header", "some-value");

            // Act
            var response = await SetHeadersAsync(message, options);

            // Assert
            response.Headers.ContainsKey("X-Good-Header").Should().BeTrue();
            response.Headers.ContainsKey("X_Bad_Header").Should().BeFalse();
        }
        public async Task SetHeadersAsync_ProxyNameIsNull_DefaultViaHeaderAsync()
        {
            // Arrange
            var options = TestExtensions.CreateDefaultOptions();
            var proxy   = options.Routes["/api/"].Proxy !;

            proxy.ProxyName = null;
            proxy.DownstreamResponse.Headers.DiscardInboundHeaders = false;
            proxy.DownstreamResponse.Headers.AddVia = true;

            var message = new HttpResponseMessage();

            message.Version = new System.Version(2, 0);

            // Act
            var response = await SetHeadersAsync(message, options);

            // Assert
            response.Headers[HeaderNames.Via].Should().BeEquivalentTo(new[] { "2.0 " + Constants.ServerName });
        }
        public async Task SetHeadersAsync_ProxyNameNotNullWithExistingViaHeadersAndIgnoreVia_ViaHeaderNotIncludedAsync()
        {
            // Arrange
            var options = TestExtensions.CreateDefaultOptions();
            var proxy   = options.Routes["/api/"].Proxy !;

            proxy.ProxyName = "some-proxy";
            proxy.UpstreamRequest.Headers.SkipVia = true;

            var context = new DefaultHttpContext();

            context.Request.Protocol = "HTTP/2";
            context.Request.Headers.Add(HeaderNames.Via, "1.0 test, 1.1 test2");

            // Act
            var message = await SetHeadersAsync(context, options);

            // Assert
            message.Headers.Contains(HeaderNames.Via).Should().BeFalse();
        }
        public async Task SetHeadersAsync_ProxyNameNotNullWithExistingViaHeadersAndIgnoreAllUpstreamHeaders_UpstreamViaHeaderNotIncludedAsync()
        {
            // Arrange
            var options = TestExtensions.CreateDefaultOptions();
            var proxy   = options.Routes["/api/"].Proxy !;

            proxy.ProxyName = "some-proxy";
            proxy.DownstreamResponse.Headers.DiscardInboundHeaders = true;
            proxy.DownstreamResponse.Headers.AddVia = true;

            var message = new HttpResponseMessage();

            message.Version = new System.Version(2, 0);
            message.Headers.Add(HeaderNames.Via, "1.0 test, 1.1 test2");

            // Act
            var response = await SetHeadersAsync(message, options);

            // Assert
            response.Headers[HeaderNames.Via].Should().BeEquivalentTo(new[] { "2.0 some-proxy" });
        }
        public async Task SetHeadersAsync_ProxyNameNotNullWithExistingViaHeadersAndIgnoreVia_ViaHeaderNotIncludedAsync()
        {
            // Arrange
            var options = TestExtensions.CreateDefaultOptions();
            var proxy   = options.Routes["/api/"].Proxy !;

            proxy.ProxyName = "some-proxy";
            proxy.DownstreamResponse.Headers.DiscardInboundHeaders = false;
            proxy.DownstreamResponse.Headers.AddVia = false;

            var message = new HttpResponseMessage();

            message.Version = new System.Version(2, 0);
            message.Headers.Add(HeaderNames.Via, "1.0 test");

            // Act
            var response = await SetHeadersAsync(message, options);

            // Assert
            response.Headers.ContainsKey(HeaderNames.Via).Should().BeFalse();
        }