Fix SPA refresh bug.

This commit is contained in:
Haiping Chen 2024-01-10 18:57:30 -06:00
parent 24319f5213
commit 46429501f5
5 changed files with 121 additions and 113 deletions

View file

@ -2,6 +2,12 @@ namespace BotSharp.Logger;
public static class BotSharpLoggerExtensions public static class BotSharpLoggerExtensions
{ {
/// <summary>
/// BotSharp conversation log
/// </summary>
/// <param name="services"></param>
/// <param name="config"></param>
/// <returns></returns>
public static IServiceCollection AddBotSharpLogger(this IServiceCollection services, IConfiguration config) public static IServiceCollection AddBotSharpLogger(this IServiceCollection services, IConfiguration config)
{ {
services.AddScoped<IContentGeneratingHook, CommonContentGeneratingHook>(); services.AddScoped<IContentGeneratingHook, CommonContentGeneratingHook>();

View file

@ -1,28 +1,117 @@
using BotSharp.Abstraction.Messaging.JsonConverters;
using BotSharp.Core.Users.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
namespace BotSharp.OpenAPI; namespace BotSharp.OpenAPI;
public static class BotSharpOpenApiExtensions public static class BotSharpOpenApiExtensions
{ {
private static string policy = "BotSharpCorsPolicy";
/// <summary>
/// Add Swagger/OpenAPI
/// </summary>
/// <param name="services"></param>
/// <param name="config"></param>
/// <returns></returns>
public static IServiceCollection AddBotSharpOpenAPI(this IServiceCollection services,
IConfiguration config,
string[] origins,
IHostEnvironment env,
bool enableValidation)
{
services.AddScoped<IUserIdentity, UserIdentity>();
// Add bearer authentication
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
o.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = config["Jwt:Issuer"],
ValidAudience = config["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["Jwt:Key"])),
ValidateIssuer = enableValidation,
ValidateAudience = enableValidation,
ValidateLifetime = enableValidation,
ValidateIssuerSigningKey = enableValidation
};
if (!enableValidation)
{
o.TokenValidationParameters.SignatureValidator = (string token, TokenValidationParameters parameters) =>
new JwtSecurityToken(token);
}
});
// Add services to the container.
services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new RichContentJsonConverter());
options.JsonSerializerOptions.Converters.Add(new TemplateMessageJsonConverter());
});
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
services.AddEndpointsApiExplorer();
services.AddSwaggerGen();
services.AddHttpContextAccessor();
services.AddCors(options =>
{
options.AddPolicy(policy,
builder => builder.WithOrigins(origins)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
return services;
}
/// <summary> /// <summary>
/// Use Swagger/OpenAPI /// Use Swagger/OpenAPI
/// </summary> /// </summary>
/// <param name="services"></param> /// <param name="services"></param>
/// <param name="config"></param> /// <param name="config"></param>
/// <returns></returns> /// <returns></returns>
public static IApplicationBuilder UseBotSharpOpenAPI(this IApplicationBuilder app, bool isDevelopment = false) public static IApplicationBuilder UseBotSharpOpenAPI(this IApplicationBuilder app, IHostEnvironment env)
{ {
if (app == null) if (app == null)
{ {
throw new ArgumentNullException(nameof(app)); throw new ArgumentNullException(nameof(app));
} }
app.UseCors(policy);
app.UseSwagger(); app.UseSwagger();
if (isDevelopment) if (env.IsDevelopment())
{ {
app.UseSwaggerUI(); app.UseSwaggerUI();
app.UseDeveloperExceptionPage();
} }
app.UseAuthentication();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(
endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
return app; return app;
} }
@ -42,6 +131,14 @@ public static class BotSharpOpenApiExtensions
// app.UseFileServer(); // app.UseFileServer();
app.UseDefaultFiles(); app.UseDefaultFiles();
app.UseStaticFiles(); app.UseStaticFiles();
app.UseEndpoints(
endpoints =>
{
// For SPA static file routing
endpoints.MapFallbackToFile("/index.html");
});
app.UseSpa(config => app.UseSpa(config =>
{ {
if (isDevelopment) if (isDevelopment)

View file

@ -1,51 +0,0 @@
using BotSharp.Abstraction.Messaging.JsonConverters;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
namespace BotSharp.Plugin.ChatHub;
public static class ChatHubServiceExtensions
{
/// <summary>
/// Add Swagger/OpenAPI
/// </summary>
/// <param name="services"></param>
/// <param name="config"></param>
/// <returns></returns>
public static IServiceCollection AddBotSharpOpenAPI(this IServiceCollection services, IConfiguration config)
{
// Add services to the container.
services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new RichContentJsonConverter());
options.JsonSerializerOptions.Converters.Add(new TemplateMessageJsonConverter());
});
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
services.AddEndpointsApiExplorer();
services.AddSwaggerGen();
services.AddHttpContextAccessor();
return services;
}
/// <summary>
/// Host BotSharp UI built in adapter-static
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static IApplicationBuilder UseChatHub(this IApplicationBuilder app)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
app.UseMiddleware<WebSocketsMiddleware>();
return app;
}
}

View file

@ -49,9 +49,4 @@ public class SignalRHub : Hub
await base.OnConnectedAsync(); await base.OnConnectedAsync();
} }
public Task PushEventLog(string message)
{
return Task.CompletedTask;
}
} }

View file

@ -1,18 +1,13 @@
using BotSharp.Abstraction.Users;
using BotSharp.Core; using BotSharp.Core;
using BotSharp.OpenAPI; using BotSharp.OpenAPI;
using BotSharp.Core.Users.Services;
using BotSharp.Logger; using BotSharp.Logger;
using BotSharp.Plugin.ChatHub; using BotSharp.Plugin.ChatHub;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Serilog; using Serilog;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
var loggerConfig = new LoggerConfiguration(); // Use Serilog
Log.Logger = loggerConfig Log.Logger = new LoggerConfiguration()
#if DEBUG #if DEBUG
.MinimumLevel.Debug() .MinimumLevel.Debug()
#else #else
@ -23,62 +18,28 @@ Log.Logger = loggerConfig
.CreateLogger(); .CreateLogger();
builder.Host.UseSerilog(); builder.Host.UseSerilog();
builder.Services.AddScoped<IUserIdentity, UserIdentity>();
// Add bearer authentication
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
o.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])),
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = false,
ValidateIssuerSigningKey = true
};
});
// Add BotSharp // Add BotSharp
builder.Services.AddBotSharpCore(builder.Configuration); builder.Services.AddBotSharpCore(builder.Configuration)
builder.Services.AddBotSharpOpenAPI(builder.Configuration); .AddBotSharpOpenAPI(builder.Configuration, new[]
builder.Services.AddBotSharpLogger(builder.Configuration); {
"http://localhost:5015",
builder.Services.AddCors(options => "https://botsharp.scisharpstack.org",
{ "https://chat.scisharpstack.org"
options.AddPolicy("MyCorsPolicy", }, builder.Environment, true)
builder => builder.WithOrigins("http://localhost:5015", .AddBotSharpLogger(builder.Configuration);
"http://localhost:5500",
"https://botsharp.scisharpstack.org",
"https://chat.scisharpstack.org")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
// Add SignalR for WebSocket
builder.Services.AddSignalR(); builder.Services.AddSignalR();
var app = builder.Build(); var app = builder.Build();
// Configure the HTTP request pipeline. // Enable SignalR
app.MapHub<SignalRHub>("/chatHub"); app.MapHub<SignalRHub>("/chatHub");
app.UseChatHub(); app.UseMiddleware<WebSocketsMiddleware>();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
// Use BotSharp // Use BotSharp
app.UseBotSharp(); app.UseBotSharp()
app.UseBotSharpOpenAPI(); .UseBotSharpOpenAPI(app.Environment)
app.UseBotSharpUI(); .UseBotSharpUI();
app.UseCors("MyCorsPolicy");
app.Run(); app.Run();