重定向到另一个侦听器的服务侦听器

Service listener that redirects to another listener

在我的服务结构应用程序中,我目前有一个基于 HTTPS 的 运行 核心 Web 服务。这工作正常,但我想这样做,如果通过 HTTP 访问 Web 服务,它将重定向到 HTTPS 版本。

我已经通过创建第二个服务侦听器解决了这个问题,该侦听器也在 HTTP 端点上加载 Web 项目,然后通过中间件重定向到 HTTPS 版本。这工作得相当好,我唯一的疑虑是在加载项目时它显然需要加载 Web 项目的两个版本,这需要一些时间。

理想情况下,有一些方法可以在服务侦听器级别进行简单的重定向,我可以在其中重定向到我的 HTTPS 侦听器,而无需启动完整的 kestrel 版本的 Web 应用程序。

有什么想法吗?这是目前的样子。

internal sealed class Web : StatelessService
    {
        public Web(StatelessServiceContext context)
            : base(context)
        { }

        /// <summary>
        /// Optional override to create listeners (like tcp, http) for this service instance.
        /// </summary>
        /// <returns>The collection of listeners.</returns>
        protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
        {
            return new ServiceInstanceListener[]
            {
                new ServiceInstanceListener(serviceContext =>
                    new WebListenerCommunicationListener(serviceContext, "ServiceEndpointSecure", url =>
                    {
                        ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting WebListener on {url}");

                        var context = FabricRuntime.GetActivationContext();
                        var config = context.GetConfigurationPackageObject("Config");
                        var environment = config.Settings.Sections["Environment"].Parameters["ASPNETCORE_ENVIRONMENT"].Value;

                        return new WebHostBuilder().UseWebListener()
                                    .ConfigureServices(
                                        services => services
                                            .AddSingleton<StatelessServiceContext>(serviceContext))
                                    .UseContentRoot(Directory.GetCurrentDirectory())
                                    .UseStartup<Startup>()
                                    .UseEnvironment(environment)
                                    .UseUrls(url)
                                    .Build();
                    }),"HttpsListener"),
                 new ServiceInstanceListener(serviceContext =>
                    new WebListenerCommunicationListener(serviceContext, "ServiceEndpoint", url =>
                    {
                        ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting WebListener on {url}");

                        var context = FabricRuntime.GetActivationContext();
                        var config = context.GetConfigurationPackageObject("Config");
                        var environment = config.Settings.Sections["Environment"].Parameters["ASPNETCORE_ENVIRONMENT"].Value;

                        return new WebHostBuilder().UseWebListener()
                                    .ConfigureServices(
                                        services => services
                                            .AddSingleton<StatelessServiceContext>(serviceContext))
                                    .UseContentRoot(Directory.GetCurrentDirectory())
                                    .UseStartup<Startup>()
                                    .UseEnvironment(environment)
                                    .UseUrls(url)
                                    .Build();
                    }),"HttpListener")
            };
        }
    }

并且在 ServiceManifest.xml

<Resources>
    <Endpoints>         
      <Endpoint Protocol="http" Name="ServiceEndpoint" Type="Input" Port="80" />
      <Endpoint Protocol="https" Name="ServiceEndpointSecure" Type="Input" Port="443" />
    </Endpoints>
  </Resources>

您可以简单地从一个 WebListener:

中听两个 url

.UseUrls("http://+:80", "https://+:443")

添加一些 middleware 以强制执行 https。类似于:

 HttpRequest req = context.Request;
 if (req.IsHttps == false)
 {
     string url = "https://" + req.Host + req.Path + req.QueryString;
     context.Response.Redirect(url, permanent: true);
 }