public async Task AllowVersionPlaceholder()
        {
            // Arrange
            const string version     = "v1";
            const string key         = "projects";
            var          httpContext = GetHttpContext(requestPath: $"/{version}/{key}");

            var next = new TestRequestDelegate();

            // What is being tested
            var swaggerForOcelotOptions = new SwaggerForOcelotUIOptions();
            var swaggerEndpointOptions  = CreateSwaggerEndpointOptions(key, version);
            var rerouteOptions          = new TestReRouteOptions(new List <ReRouteOptions>
            {
                new ReRouteOptions
                {
                    SwaggerKey             = "projects",
                    UpstreamPathTemplate   = "/api/{version}/projects/Values/{everything}",
                    DownstreamPathTemplate = "/api/{version}/Values/{everything}",
                },
                new ReRouteOptions
                {
                    SwaggerKey             = "projects",
                    UpstreamPathTemplate   = "/api/projects/Projects",
                    DownstreamPathTemplate = "/api/Projects",
                },
                new ReRouteOptions
                {
                    SwaggerKey             = "projects",
                    UpstreamPathTemplate   = "/api/projects/Projects/{everything}",
                    DownstreamPathTemplate = "/api/Projects/{everything}",
                }
            });

            // downstreamSwagger is returned when client.GetStringAsync is called by the middleware.
            var downstreamSwagger = await GetBaseOpenApi("OpenApiWithVersionPlaceholderBase");

            var httClientMock     = GetHttpClient(downstreamSwagger);
            var httpClientFactory = new TestHttpClientFactory(httClientMock);

            // upstreamSwagger is returned after swaggerJsonTransformer transforms the downstreamSwagger
            var expectedSwagger = await GetBaseOpenApi("OpenApiWithVersionPlaceholderBaseTransformed");

            var swaggerJsonTransformerMock = new Mock <ISwaggerJsonTransformer>();

            swaggerJsonTransformerMock
            .Setup(x => x.Transform(
                       It.IsAny <string>(),
                       It.IsAny <IEnumerable <ReRouteOptions> >(),
                       It.IsAny <string>()))
            .Returns((
                         string swaggerJson,
                         IEnumerable <ReRouteOptions> reRouteOptions,
                         string hostOverride) => new SwaggerJsonTransformer()
                     .Transform(swaggerJson, reRouteOptions, hostOverride));
            var swaggerForOcelotMiddleware = new SwaggerForOcelotMiddleware(
                next.Invoke,
                swaggerForOcelotOptions,
                rerouteOptions,
                swaggerEndpointOptions,
                httpClientFactory,
                swaggerJsonTransformerMock.Object);

            // Act
            await swaggerForOcelotMiddleware.Invoke(httpContext);

            httpContext.Response.Body.Seek(0, SeekOrigin.Begin);

            // Assert
            using (var streamReader = new StreamReader(httpContext.Response.Body))
            {
                var transformedUpstreamSwagger = await streamReader.ReadToEndAsync();

                AreEqual(transformedUpstreamSwagger, expectedSwagger);
            }
            swaggerJsonTransformerMock.Verify(x => x.Transform(
                                                  It.IsAny <string>(),
                                                  It.IsAny <IEnumerable <ReRouteOptions> >(),
                                                  It.IsAny <string>()), Times.Once);
        }
Example #2
0
        public void Factory_CreateClient_FiltersCanDecorateBuilder()
        {
            // Arrange
            var expected = new HttpMessageHandler[]
            {
                Mock.Of <DelegatingHandler>(),  // Added by filter1
                Mock.Of <DelegatingHandler>(),  // Added by filter2
                Mock.Of <DelegatingHandler>(),  // Added by filter3
                Mock.Of <DelegatingHandler>(),  // Added in options
                Mock.Of <DelegatingHandler>(),  // Added by filter3
                Mock.Of <DelegatingHandler>(),  // Added by filter2
                Mock.Of <DelegatingHandler>(),  // Added by filter1

                Mock.Of <HttpMessageHandler>(), // Set as primary handler by options
            };

            Options.Get("github").HttpMessageHandlerBuilderActions.Add(b =>
            {
                b.PrimaryHandler = expected[7];

                b.AdditionalHandlers.Add((DelegatingHandler)expected[3]);
            });

            var filter1 = new Mock <IHttpMessageHandlerBuilderFilter>();

            filter1
            .Setup(f => f.Configure(It.IsAny <Action <HttpMessageHandlerBuilder> >()))
            .Returns <Action <HttpMessageHandlerBuilder> >(next => (b) =>
            {
                next(b);     // Calls filter2
                b.AdditionalHandlers.Insert(0, (DelegatingHandler)expected[0]);
                b.AdditionalHandlers.Add((DelegatingHandler)expected[6]);
            });

            var filter2 = new Mock <IHttpMessageHandlerBuilderFilter>();

            filter2
            .Setup(f => f.Configure(It.IsAny <Action <HttpMessageHandlerBuilder> >()))
            .Returns <Action <HttpMessageHandlerBuilder> >(next => (b) =>
            {
                next(b);     // Calls filter3
                b.AdditionalHandlers.Insert(0, (DelegatingHandler)expected[1]);
                b.AdditionalHandlers.Add((DelegatingHandler)expected[5]);
            });

            var filter3 = new Mock <IHttpMessageHandlerBuilderFilter>();

            filter3
            .Setup(f => f.Configure(It.IsAny <Action <HttpMessageHandlerBuilder> >()))
            .Returns <Action <HttpMessageHandlerBuilder> >(next => (b) =>
            {
                b.AdditionalHandlers.Add((DelegatingHandler)expected[2]);
                next(b);     // Calls options
                b.AdditionalHandlers.Add((DelegatingHandler)expected[4]);
            });

            var factory = new TestHttpClientFactory(Services, LoggerFactory, Options, new[]
            {
                filter1.Object,
                filter2.Object,
                filter3.Object,
            });

            // Act
            var handler = (HttpMessageHandler)factory.CreateHandlerEntry("github").Handler;

            // Assert
            //
            // The outer-most handler is always a lifetime tracking handler.
            Assert.IsType <LifetimeTrackingHttpMessageHandler>(handler);
            handler = Assert.IsAssignableFrom <DelegatingHandler>(handler).InnerHandler;

            for (var i = 0; i < expected.Length - 1; i++)
            {
                Assert.Same(expected[i], handler);
                handler = Assert.IsAssignableFrom <DelegatingHandler>(handler).InnerHandler;
            }

            Assert.Same(expected[7], handler);
        }
Example #3
0
    public async void PostAsyncTests(
        Uri endpoint,
        SoapVersion version,
        IEnumerable <XElement> bodies,
        IEnumerable <XElement> headers,
        string action)
    {
        // Setup
        var testFactory = new TestHttpClientFactory();
        var sut         = new SoapClient(testFactory);

        // Exercise
        var result = await sut.PostAsync(endpoint, version, bodies, headers, action);

        // Verify outcome
        var actual = testFactory.Handler.CallStack.Single();

        Assert.Equal(HttpStatusCode.OK, result.StatusCode);
        Assert.Equal(endpoint, actual.Uri);

        // Assert action and version
        var actualHeaders = actual.Headers;

        if (actualHeaders.Contains("ActionHeader"))
        {
            var actualVersion = SoapVersion.Soap11;
            Assert.Equal(version, actualVersion);
            Assert.Equal(action, actualHeaders.GetValues("ActionHeader").Single());
        }
        else
        {
            var actionParam = actualHeaders.ContentType?.Parameters?.SingleOrDefault(e => e.Name == "ActionParameter");
            if (actionParam != null)
            {
                var actualVersion = SoapVersion.Soap12;
                Assert.Equal(version, actualVersion);
                Assert.Equal($"\"{action}\"", actionParam.Value);
            }
        }

        // Assert namespace
        var actualEnvelope    = XElement.Parse(actual.Body);
        var expectedNamespace = new SoapMessageConfiguration(version).Schema;

        Assert.Equal("Envelope", actualEnvelope.Name.LocalName);
        Assert.Equal(expectedNamespace, actualEnvelope.Name.Namespace.NamespaceName);

        // Assert Headers
        if (headers != null && headers.Any())
        {
            var actualHeader =
                actualEnvelope.Elements()
                .Where(e => e.Name.LocalName == "Header")
                .Where(e => e.Name.Namespace.NamespaceName == expectedNamespace)
                .Single();

            Assert.Equal(
                headers.Select(e => e.ToString()),
                actualHeader.Elements().Select(e => e.ToString()));
        }

        // Assert Bodies
        var actualBody =
            actualEnvelope.Elements()
            .Where(e => e.Name.LocalName == "Body")
            .Where(e => e.Name.Namespace.NamespaceName == expectedNamespace)
            .Single();

        Assert.Equal(
            bodies.Select(e => e.ToString()),
            actualBody.Elements().Select(e => e.ToString()));
    }
        private async Task <ExpiredHandlerTrackingEntry> SimulateClientUse_Factory_CleanupCycle_DisposesEligibleHandler(TestHttpClientFactory factory)
        {
            // Create a handler and move it to the expired state
            var client1 = factory.CreateClient("github");

            var kvp = Assert.Single(factory.ActiveEntryState);

            kvp.Value.Item1.SetResult(kvp.Key);
            await kvp.Value.Item2;

            // Our handler is now in the cleanup state.
            var cleanupEntry = Assert.Single(factory._expiredHandlers);

            Assert.True(factory.CleanupTimerStarted.IsSet, "Cleanup timer started");

            // We need to make sure that the outer handler actually gets GCed, so drop our references to it.
            // This is important because the factory relies on this possibility for correctness. We need to ensure that
            // the factory isn't keeping any references.
            kvp     = default;
            client1 = null;

            return(cleanupEntry);
        }
Example #5
0
 public UserControllerTests(ITestOutputHelper output)
 {
     _HttpClient = TestHttpClientFactory.Create();
     _Output     = output;
 }