我正在使用Java / kotlin客户端应用程序和在AWS Elastic beantalk上运行的基于.Net Core的服务器创建应用程序。我正在尝试使用Signalr Core库实现实时通知,但是遇到了一些问题。似乎每当我尝试在客户端和服务器之间建立连接时,尝试升级到Websocket时握手都会失败。
Java错误:WebSocket因错误而关闭:预期的“连接”标头值为“升级”,但为“空”。
似乎服务器发出的响应在所有情况下都是正确的,只是缺少标题“ Connection”:“ Upgrade”并导致我的代码失败。我已经对此进行了广泛研究,但在任何方面都没有成功。
我的服务器正在使用IIS 10和Net Core 2.2在“ Window Server 2016数据中心”实例上运行。
我的代码:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddRouting(options => options.LowercaseUrls = true);
services.AddMvc();
services.AddSignalR(options =>
{
options.EnableDetailedErrors = true;
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
app.UseDefaultFiles(new DefaultFilesOptions
{
DefaultFileNames = new
List<string> { "index.html" }
});
app.Use(async (context, nextMiddleWare) =>
{
context.Response.OnStarting(() =>
{
if (!context.Response.Headers.Keys.Contains("Connection"))
{
context.Response.Headers.Add("Connection", "Upgrade");
}
else
{
context.Response.Headers["Connection"] = "Upgrade";
}
return Task.FromResult(0);
});
await nextMiddleWare();
context.Response.OnCompleted(() =>
{
Console.WriteLine("LOG: Hitting Custom Middleware with status code: {0}", context.Response.StatusCode);
return Task.FromResult(0);
});
;
});
app.UseSignalR(routes =>
{
routes.MapHub<MainHub>("/mainHub");
});
app.UseMvc();
...
class Program
{
public static void Main(string[] args)
{
SetEbConfig();
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
private static void SetEbConfig()
{
var tempConfigBuilder = new ConfigurationBuilder();
tempConfigBuilder.AddJsonFile(
@"C:\Program Files\Amazon\ElasticBeanstalk\config\containerconfiguration",
optional: true,
reloadOnChange: true
);
var configuration = tempConfigBuilder.Build();
var ebEnv =
configuration.GetSection("iis:env")
.GetChildren()
.Select(pair => pair.Value.Split(new[] { '=' }, 2))
.ToDictionary(keypair => keypair[0], keypair => keypair[1]);
foreach (var keyVal in ebEnv)
{
Environment.SetEnvironmentVariable(keyVal.Key, keyVal.Value);
}
}
}
...
public class MainHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
public async Task BroadcastOrder(string groupName, Order order)
{
await Clients.Group(groupName).SendAsync("New Order", order);
}
public Task JoinGroup(string groupName)
{
return Groups.AddToGroupAsync(Context.ConnectionId, groupName);
}
public Task LeaveGroup(string groupName)
{
return Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
}
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception exception)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnDisconnectedAsync(exception);
}
}
正如您在Startup.cs中看到的那样,我什至尝试使用中间件将标头手动添加到响应中,但标头仍不会出现在客户端中。我可能不完全了解中间件管道的工作方式(因为我对其中的大多数还相当陌生)或其他因素在起作用。