< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Channels.ServiceModelHttpMiddleware
Assembly: CoreWCF.Http
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Http/src/CoreWCF/Channels/ServiceModelHttpMiddleware.cs
Line coverage
88%
Covered lines: 92
Uncovered lines: 12
Coverable lines: 104
Total lines: 203
Line coverage: 88.4%
Branch coverage
87%
Covered branches: 42
Total branches: 48
Branch coverage: 87.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%11100%
InvokeAsync()100%11100%
BuildBranchAndInvoke(...)100%110%
EnsureBranchBuilt()100%22100%
ServiceBuilderOpenedCallback(...)100%11100%
BuildBranch()85.71%424285.71%
ExecHandler(Microsoft.AspNetCore.Http.HttpContext)100%44100%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Http/src/CoreWCF/Channels/ServiceModelHttpMiddleware.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Threading.Tasks;
 6using CoreWCF.Configuration;
 7using Microsoft.AspNetCore.Builder;
 8using Microsoft.AspNetCore.Http;
 9using Microsoft.Extensions.DependencyInjection;
 10using Microsoft.Extensions.Logging;
 11
 12namespace CoreWCF.Channels
 13{
 14    public partial class ServiceModelHttpMiddleware
 15    {
 16        private const string RestorePathsDelegateItemName = nameof(ServiceModelHttpMiddleware) + "_RestorePathsDelegate"
 17        private readonly IApplicationBuilder _app;
 18        private readonly IServiceBuilder _serviceBuilder;
 19        private readonly IDispatcherBuilder _dispatcherBuilder;
 20        private readonly RequestDelegate _next;
 21        private readonly ILogger<ServiceModelHttpMiddleware> _logger;
 22        private RequestDelegate _branch;
 23        private bool _branchBuilt;
 24
 38225        public ServiceModelHttpMiddleware(RequestDelegate next, IApplicationBuilder app, IServiceBuilder serviceBuilder,
 26        {
 38227            _app = app;
 38228            _serviceBuilder = serviceBuilder;
 38229            _dispatcherBuilder = dispatcherBuilder;
 38230            _next = next;
 38231            _logger = logger;
 38232            _branch = BuildBranchAndInvoke;
 38233            serviceBuilder.Opened += ServiceBuilderOpenedCallback;
 38234        }
 35
 36        public async Task InvokeAsync(HttpContext context)
 37        {
 38            // Update the path
 68839            var path = context.Request.Path;
 68840            var pathBase = context.Request.PathBase;
 68841            context.Request.Path = pathBase.Add(path);
 68842            context.Request.PathBase = "";
 68843            Action restorePaths = () =>
 68844            {
 145                context.Request.PathBase = pathBase;
 146                context.Request.Path = path;
 68947            };
 68848            context.Items[RestorePathsDelegateItemName] = restorePaths;
 68849            await _branch(context);
 68650        }
 51
 52        private Task BuildBranchAndInvoke(HttpContext request)
 53        {
 054            EnsureBranchBuilt();
 055            return _branch(request);
 56        }
 57
 58        private void EnsureBranchBuilt()
 59        {
 38260            lock (this)
 61            {
 38262                if (!_branchBuilt)
 63                {
 38264                    _branch = BuildBranch();
 37265                    _branchBuilt = true;
 66                }
 37267            }
 37268        }
 69
 70        private void ServiceBuilderOpenedCallback(object sender, EventArgs e)
 71        {
 38272            EnsureBranchBuilt();
 37273        }
 74
 75        private RequestDelegate BuildBranch()
 76        {
 38277            _logger.LogDebug("Building branch map");
 38278            IApplicationBuilder branchApp = _app.New();
 79
 153880            foreach (Type serviceType in _serviceBuilder.Services)
 81            {
 39282                System.Collections.Generic.List<IServiceDispatcher> dispatchers = _dispatcherBuilder.BuildDispatchers(se
 161083                foreach (IServiceDispatcher dispatcher in dispatchers)
 84                {
 42385                    if (dispatcher.BaseAddress == null)
 86                    {
 87                        // TODO: Should we throw? Ignore?
 88                        continue;
 89                    }
 90
 42391                    if (!(dispatcher.Binding is CustomBinding binding))
 92                    {
 35193                        binding = new CustomBinding(dispatcher.Binding);
 94                    }
 42395                    if (binding.Elements.Find<HttpTransportBindingElement>() == null)
 96                    {
 097                        _logger.LogDebug("Binding for address {baseAddress} is not an HTTP[S] binding so skipping", disp
 098                        continue; // Not an HTTP(S) dispatcher
 99                    }
 100
 423101                    var parameters = new BindingParameterCollection
 423102                    {
 423103                        _app
 423104                    };
 423105                    IServiceDispatcher serviceDispatcher = null;
 423106                    System.Collections.Generic.IList<Type> supportedChannels = dispatcher.SupportedChannelTypes;
 4230107                    for (int i = 0; i < supportedChannels.Count; i++)
 108                    {
 1692109                        Type channelType = supportedChannels[i];
 1692110                        if (channelType == typeof(IInputChannel))
 111                        {
 2112                            if (binding.CanBuildServiceDispatcher<IInputChannel>(parameters))
 113                            {
 0114                                serviceDispatcher = binding.BuildServiceDispatcher<IInputChannel>(parameters, dispatcher
 0115                                break;
 116                            }
 117                        }
 1692118                        if (channelType == typeof(IReplyChannel))
 119                        {
 421120                            if (binding.CanBuildServiceDispatcher<IReplyChannel>(parameters))
 121                            {
 413122                                serviceDispatcher = binding.BuildServiceDispatcher<IReplyChannel>(parameters, dispatcher
 123                            }
 124                        }
 1692125                        if (channelType == typeof(IDuplexChannel))
 126                        {
 422127                            if (binding.CanBuildServiceDispatcher<IDuplexChannel>(parameters))
 128                            {
 0129                                serviceDispatcher = binding.BuildServiceDispatcher<IDuplexChannel>(parameters, dispatche
 130                            }
 131                        }
 1692132                        if (channelType == typeof(IInputSessionChannel))
 133                        {
 2134                            if (binding.CanBuildServiceDispatcher<IInputSessionChannel>(parameters))
 135                            {
 0136                                serviceDispatcher = binding.BuildServiceDispatcher<IInputSessionChannel>(parameters, dis
 137                            }
 138                        }
 1692139                        if (channelType == typeof(IReplySessionChannel))
 140                        {
 422141                            if (binding.CanBuildServiceDispatcher<IReplySessionChannel>(parameters))
 142                            {
 0143                                serviceDispatcher = binding.BuildServiceDispatcher<IReplySessionChannel>(parameters, dis
 144                            }
 145                        }
 1692146                        if (channelType == typeof(IDuplexSessionChannel))
 147                        {
 423148                            if (binding.CanBuildServiceDispatcher<IDuplexSessionChannel>(parameters))
 149                            {
 22150                                serviceDispatcher = binding.BuildServiceDispatcher<IDuplexSessionChannel>(parameters, di
 151                            }
 152                        }
 153                    }
 154
 423155                    if (serviceDispatcher is null)
 156                    {
 0157                        _logger.LogError("Unable to map CoreWCF branch app for path {path}", dispatcher.BaseAddress.Abso
 0158                        continue;
 159                    }
 160
 423161                    _logger.LogInformation("Mapping CoreWCF branch app for path {path}", dispatcher.BaseAddress.Absolute
 162
 163                    bool ExecHandler(HttpContext context)
 164                    {
 737165                        return (dispatcher.BaseAddress.AbsolutePath == "/"
 737166                               || context.Request.Path.StartsWithSegments(dispatcher.BaseAddress.AbsolutePath, out _, ou
 737167                               dispatcher.Binding.Scheme == context.Request.Scheme;
 168                    }
 169
 423170                    branchApp.MapWhen(ExecHandler, wcfApp =>
 423171                    {
 423172                        IServiceScopeFactory servicesScopeFactory = wcfApp.ApplicationServices.GetRequiredService<IServi
 423173                        var requestHandler = new RequestDelegateHandler(serviceDispatcher, servicesScopeFactory);
 423174                        if (requestHandler.IsAuthenticationRequired)
 423175                        {
 109176                            wcfApp.UseAuthentication();
 423177                        }
 423178                        if (requestHandler.WebSocketOptions != null)
 423179                        {
 22180                            wcfApp.UseWebSockets(requestHandler.WebSocketOptions);
 423181                        }
 423182                        wcfApp.Run(requestHandler.HandleRequest);
 846183                    });
 184                }
 185            }
 186
 744187            branchApp.Use(_ => { return reqContext =>
 744188            {
 1189                if (reqContext.Items.TryGetValue(RestorePathsDelegateItemName, out object restorePathsDelegateAsObject))
 744190                {
 1191                    (restorePathsDelegateAsObject as Action)?.Invoke();
 744192                }
 744193                else
 744194                {
 0195                    _logger.LogWarning("RequestContext missing delegate with key {key}", RestorePathsDelegateItemName);
 744196                }
 744197
 1198                return _next(reqContext);
 744199            }; });
 372200            return branchApp.Build();
 201        }
 202    }
 203}