重定向到另一个侦听器的服务侦听器
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);
}
在我的服务结构应用程序中,我目前有一个基于 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);
}