寫個重新加載 ocelot 配置的接口
Intro
我們想把 ocelot 的配置放在自己的存儲中,放在 Redis 或者數據庫中,當修改了 Ocelot 的配置之后希望即時生效,又不想在網關這邊定時刷新 ocelot 配置,ocelot 配置沒變化的時候,定時刷新配置是一種無意義的資源浪費,ocelot 自帶的有一個 Administration ,感覺對於我來說,有點太重了,不想去集成這個東西,於是就想自己實現一個重新加載配置的接口。
實現代碼
在集成 Ocelot 網關的項目的 Startup 里的 Configure
方法中添加如下代碼:
#region 更新 Ocelot 配置接口
// PUT /ocelot/admin/configuration 需要 Admin 的角色
app.Map(new PathString("/ocelot/admin/configuration"), appBuilder =>
{
appBuilder.Use(async (context, next) =>
{
if (context.Request.Method.ToUpper() != "PUT")
{
context.Response.StatusCode = 404;
return;
}
var authenticateResult = await context.AuthenticateAsync(AuthenticationProviderKey);
if (!authenticateResult.Succeeded)
{
context.Response.StatusCode = 401;
return;
}
if (authenticateResult.Principal.IsInRole("Admin"))
{
var configurationRepo =
context.RequestServices.GetRequiredService<IFileConfigurationRepository>();
var ocelotConfiguration = await configurationRepo.Get();
var logger = context.RequestServices.GetRequiredService<ILoggerFactory>().CreateLogger("OcelotConfiguration");
if (!ocelotConfiguration.IsError)
{
var internalConfigurationRepo = context.RequestServices.GetRequiredService<IInternalConfigurationRepository>();
var internalConfigurationCreator =
context.RequestServices.GetRequiredService<IInternalConfigurationCreator>();
var internalConfiguration = await internalConfigurationCreator.Create(ocelotConfiguration.Data);
if (!internalConfiguration.IsError)
{
internalConfigurationRepo.AddOrReplace(internalConfiguration.Data);
context.Response.StatusCode = 200;
return;
}
else
{
logger.LogError($"update ocelot configuration error, error in create ocelot internal configuration, error messages:{string.Join(", ", ocelotConfiguration.Errors)}");
}
}
else
{
logger.LogError($"update ocelot configuration error, error in get ocelot configuration from configurationRepo, error messages:{string.Join(", ", ocelotConfiguration.Errors)}");
}
context.Response.StatusCode = 500;
}
else
{
context.Response.StatusCode = 403;
}
});
});
#endregion 更新 Ocelot 配置接口
這里的代碼包含了一些邏輯,檢查了要操作的用戶是否擁有 Admin
的角色,可以自己根據自己的需要自行修改進行定制,可以自定義要操作的角色,自定義要操作的接口地址以及請求方式。
AuthenticationProviderKey
是在 ConfigureServices
方法中定義的認證方式,示例代碼如下:
public IConfiguration Configuration { get; }
private readonly string AuthenticationProviderKey = "IdentityApiKey";
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//…
services.AddAuthentication()
.AddIdentityServerAuthentication(AuthenticationProviderKey, x =>
{
x.Authority = Configuration["Authorization:Authority"];
x.ClaimsIssuer = Configuration["Authorization:ClaimsIssuer"];
x.RequireHttpsMetadata = false;
});
services.AddOcelot();
// ......
}
調用 API 接口更新配置
可以使用 Postman 或者 fiddler 等調用 API 來測試
返回 200 即配置更新成功
Memo
Enjoy it~