Я создаю приложение с клиентским приложением java / kotlin и сервером на основе .Net Core, работающим на aws эластичный beanstalk. Я пытаюсь реализовать уведомления в режиме реального времени, используя библиотеку Signalr Core, но у меня возникли некоторые проблемы. Кажется, всякий раз, когда я пытаюсь установить соединение между клиентом и сервером, происходит сбой рукопожатия при попытке обновления до веб-сокетов.
Ошибка Java: WebSocket закрылся из-за ошибки: ожидалось значение заголовка «Соединение» «Обновление», но было «пусто».
Кажется, что мой ответ от сервера правильный во всем, за исключением того, что отсутствует заголовок "Соединение": "Обновление", что приводит к сбою моего кода. Я подробно изучил это, но ничего не добился.
Мой сервер работает на экземпляре "Windows Server 2016 Datacenter" с использованием IIS 10 и Net Core 2.2.
Мой код:
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, я даже пытался вручную добавить заголовок в ответ, используя промежуточное ПО, но заголовок все равно не появлялся в моем клиенте. Возможно, я не до конца понимаю, как работает конвейер промежуточного программного обеспечения (поскольку я довольно плохо знаком с большинством из этого), или могут быть другие факторы.