< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Channels.MetadataMiddleware
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Channels/MetadataMiddleware.cs
Line coverage
85%
Covered lines: 116
Uncovered lines: 20
Coverable lines: 136
Total lines: 267
Line coverage: 85.2%
Branch coverage
80%
Covered branches: 61
Total branches: 76
Branch coverage: 80.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Channels/MetadataMiddleware.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.Net;
 6using System.Threading.Tasks;
 7using CoreWCF.Configuration;
 8using CoreWCF.Description;
 9using Microsoft.AspNetCore.Builder;
 10using Microsoft.AspNetCore.Http;
 11using Microsoft.Extensions.DependencyInjection;
 12using Microsoft.Extensions.Logging;
 13
 14namespace CoreWCF.Channels
 15{
 16    internal class MetadataMiddleware
 17    {
 18        private const string RestorePathsDelegateItemName = nameof(MetadataMiddleware) + "_RestorePathsDelegate";
 19        private readonly IApplicationBuilder _app;
 20        private readonly IServiceBuilder _serviceBuilder;
 21        private readonly IDispatcherBuilder _dispatcherBuilder;
 22        private readonly ServiceMetadataBehavior _metadataBehavior;
 23        private readonly RequestDelegate _next;
 24        private readonly ILogger<MetadataMiddleware> _logger;
 25        private RequestDelegate _branch;
 26        private bool _branchBuilt;
 27
 2428        public MetadataMiddleware(RequestDelegate next, IApplicationBuilder app, IServiceBuilder serviceBuilder, IDispat
 29        {
 2430            _app = app;
 2431            _serviceBuilder = serviceBuilder;
 2432            _dispatcherBuilder = dispatcherBuilder;
 2433            _metadataBehavior = metadataBehavior;
 2434            _next = next;
 2435            _logger = logger;
 2436            _branch = BuildBranchAndInvoke;
 2437            serviceBuilder.Opened += ServiceBuilderOpenedCallback;
 2438        }
 39
 40        public async Task InvokeAsync(HttpContext context)
 41        {
 42            // Update the path
 2643            var path = context.Request.Path;
 2644            var pathBase = context.Request.PathBase;
 2645            context.Request.Path = pathBase.Add(path);
 2646            context.Request.PathBase = "";
 2647            Action restorePaths = () =>
 2648            {
 149                context.Request.PathBase = pathBase;
 150                context.Request.Path = path;
 2751            };
 2652            context.Items[RestorePathsDelegateItemName] = restorePaths;
 2653            await _branch(context);
 2654        }
 55
 56        private Task BuildBranchAndInvoke(HttpContext request)
 57        {
 058            EnsureBranchBuilt();
 059            return _branch(request);
 60        }
 61
 62        private void EnsureBranchBuilt()
 63        {
 2464            lock (this)
 65            {
 2466                if (!_branchBuilt)
 67                {
 2468                    _branch = BuildBranch();
 2469                    _branchBuilt = true;
 70                }
 2471            }
 2472        }
 73
 74        private void ServiceBuilderOpenedCallback(object sender, EventArgs e)
 75        {
 2476            EnsureBranchBuilt();
 2477        }
 78
 79        private RequestDelegate BuildBranch()
 80        {
 2481            _logger.LogDebug("Building branch map");
 2482            IApplicationBuilder branchApp = _app.New();
 2483            branchApp.Use(branchNext => {
 2484                return reqContext =>
 2485                {
 2686                    if ("GET".Equals(reqContext.Request.Method, StringComparison.OrdinalIgnoreCase))
 2487                    {
 2488                        // If request is a GET request, continue on the branchApp middleware chain
 2489                        // to handle requests for WSDL, HelpPage etc
 2590                        return branchNext(reqContext);
 2491                    }
 2492
 2493                    // Not a GET request so short circuit to the next middleware after MetadataMiddleware.
 194                    if (reqContext.Items.TryGetValue(RestorePathsDelegateItemName, out object restorePathsDelegateAsObje
 2495                    {
 196                        (restorePathsDelegateAsObject as Action)?.Invoke();
 2497                    }
 2498                    else
 2499                    {
 0100                        _logger.LogWarning("RequestContext missing delegate with key {key}", RestorePathsDelegateItemNam
 24101                    }
 24102
 1103                    return _next(reqContext);
 24104                };
 24105            });
 106
 98107            foreach (Type serviceType in _serviceBuilder.Services)
 108            {
 109                void MapMetadata(IApplicationBuilder app, string path, Func<RequestDelegate, RequestDelegate> middleware
 110                {
 34111                    _logger.LogInformation("Configuring metadata to {path}", path);
 34112                    app.Use(middleware);
 34113                }
 114
 25115                var dispatchers = _dispatcherBuilder.BuildDispatchers(serviceType);
 25116                var serviceHost = _app.ApplicationServices.GetRequiredService(typeof(ServiceHostObjectModel<>).MakeGener
 25117                var metadataExtension = serviceHost.Extensions.Find<ServiceMetadataExtension>();
 25118                if (metadataExtension == null)
 119                {
 120                    continue; // No ServiceMetadataExtension on this service
 121                }
 122
 123                // Look for endpoints listening on HTTP and HTTPS and use them for fallback paths
 25124                Uri fallbackHttpEndpointAddress = null;
 25125                Uri fallbackHttpsEndpointAddress = null;
 116126                foreach (var dispatcher in dispatchers)
 127                {
 33128                    var scheme = dispatcher.BaseAddress?.Scheme;
 33129                    if (fallbackHttpEndpointAddress == null && Uri.UriSchemeHttp.Equals(scheme))
 130                    {
 19131                        fallbackHttpEndpointAddress = dispatcher.BaseAddress;
 19132                        if (IPAddress.TryParse(fallbackHttpEndpointAddress.Host, out IPAddress hostAsAddress))
 133                        {
 1134                            var uriBuilder = new UriBuilder(fallbackHttpEndpointAddress);
 1135                            if (hostAsAddress.Equals(IPAddress.Any) || hostAsAddress.Equals(IPAddress.IPv6Any))
 136                            {
 0137                                uriBuilder.Host = DnsCache.MachineName;
 0138                                fallbackHttpEndpointAddress = uriBuilder.Uri;
 139                            }
 1140                            else if (IPAddress.IsLoopback(hostAsAddress))
 141                            {
 1142                                uriBuilder.Host = "localhost";
 1143                                fallbackHttpEndpointAddress = uriBuilder.Uri;
 144                            }
 145                        }
 146
 1147                        continue;
 148                    }
 149
 14150                    if (fallbackHttpsEndpointAddress == null && Uri.UriSchemeHttps.Equals(scheme))
 151                    {
 6152                        fallbackHttpsEndpointAddress = dispatcher.BaseAddress;
 6153                        if (IPAddress.TryParse(fallbackHttpsEndpointAddress.Host, out IPAddress hostAsAddress))
 154                        {
 0155                            var uriBuilder = new UriBuilder(fallbackHttpsEndpointAddress);
 0156                            if (hostAsAddress.Equals(IPAddress.Any) || hostAsAddress.Equals(IPAddress.IPv6Any))
 157                            {
 0158                                uriBuilder.Host = DnsCache.MachineName;
 0159                                fallbackHttpsEndpointAddress = uriBuilder.Uri;
 160                            }
 0161                            else if (IPAddress.IsLoopback(hostAsAddress))
 162                            {
 0163                                uriBuilder.Host = "localhost";
 0164                                fallbackHttpsEndpointAddress = uriBuilder.Uri;
 165                            }
 166                        }
 167
 168                        continue;
 169                    }
 170                }
 171
 25172                Uri httpMetadataUri = null;
 25173                Uri httpsMetadataUri = null;
 25174                if (metadataExtension.HttpGetEnabled)
 175                {
 21176                    if (metadataExtension.HttpGetUrl != null && metadataExtension.HttpGetUrl.AbsolutePath != "/")
 177                    {
 21178                        httpMetadataUri = metadataExtension.HttpGetUrl;
 179                    }
 180                    else
 181                    {
 0182                        httpMetadataUri = fallbackHttpEndpointAddress;
 0183                        metadataExtension.HttpGetUrl = fallbackHttpEndpointAddress;
 184                    }
 185
 21186                    if(httpMetadataUri != null)
 187                    {
 21188                        MapMetadata(branchApp, httpMetadataUri.AbsolutePath, metadataExtension.CreateMiddleware(httpMeta
 189                    }
 190                }
 191
 25192                if (metadataExtension.HttpHelpPageEnabled)
 193                {
 194                    Uri helpPageUri;
 25195                    if (metadataExtension.HttpHelpPageUrl != null && metadataExtension.HttpHelpPageUrl.AbsolutePath != "
 196                    {
 5197                        helpPageUri = metadataExtension.HttpHelpPageUrl;
 198                    }
 199                    else
 200                    {
 20201                        helpPageUri = fallbackHttpEndpointAddress;
 20202                        metadataExtension.HttpHelpPageUrl = fallbackHttpEndpointAddress;
 203                    }
 25204                    if (helpPageUri != null && !helpPageUri.Equals(httpMetadataUri))
 205                    {
 206                        // Only map the help page uri if it's not null, and different from http metadata uri.
 4207                        MapMetadata(branchApp, helpPageUri.AbsolutePath, metadataExtension.CreateMiddleware(helpPageUri,
 208                    }
 209                }
 210
 25211                if (metadataExtension.HttpsGetEnabled)
 212                {
 6213                    if (metadataExtension.HttpsGetUrl != null && metadataExtension.HttpsGetUrl.AbsolutePath != "/")
 214                    {
 6215                        httpsMetadataUri = metadataExtension.HttpsGetUrl;
 216                    }
 217                    else
 218                    {
 0219                        httpsMetadataUri = fallbackHttpsEndpointAddress;
 0220                        metadataExtension.HttpsGetUrl = fallbackHttpsEndpointAddress;
 221                    }
 222
 6223                    if (httpsMetadataUri != null)
 224                    {
 6225                        MapMetadata(branchApp, httpsMetadataUri.AbsolutePath, metadataExtension.CreateMiddleware(httpsMe
 226                    }
 227                }
 228
 25229                if (metadataExtension.HttpsHelpPageEnabled)
 230                {
 231                    Uri helpPageUri;
 25232                    if (metadataExtension.HttpsHelpPageUrl != null && metadataExtension.HttpsHelpPageUrl.AbsolutePath !=
 233                    {
 3234                        helpPageUri = metadataExtension.HttpsHelpPageUrl;
 235                    }
 236                    else
 237                    {
 22238                        helpPageUri = fallbackHttpsEndpointAddress;
 22239                        metadataExtension.HttpsHelpPageUrl = fallbackHttpsEndpointAddress;
 240                    }
 25241                    if (helpPageUri != null && !helpPageUri.Equals(httpsMetadataUri))
 242                    {
 243                        // Only map the help page uri if it's not null, and different from https metadata uri.
 3244                        MapMetadata(branchApp, helpPageUri.AbsolutePath, metadataExtension.CreateMiddleware(helpPageUri,
 245                    }
 246                }
 247            }
 248
 24249            branchApp.Use(_ => {
 24250                return reqContext =>
 24251                {
 0252                    if (reqContext.Items.TryGetValue(RestorePathsDelegateItemName, out object restorePathsDelegateAsObje
 24253                    {
 0254                        (restorePathsDelegateAsObject as Action)?.Invoke();
 24255                    }
 24256                    else
 24257                    {
 0258                        _logger.LogWarning("RequestContext missing delegate with key {key}", RestorePathsDelegateItemNam
 24259                    }
 24260
 0261                    return _next(reqContext);
 24262                };
 24263            });
 24264            return branchApp.Build();
 265        }
 266    }
 267}