日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

在Ocelot中使用自定义的中间件(二)

發布時間:2023/12/4 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在Ocelot中使用自定义的中间件(二) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在上文中《在Ocelot中使用自定義的中間件(一)》,我介紹了如何在Ocelot中使用自定義的中間件來修改下游服務的response body。今天,我們再擴展一下設計,讓我們自己設計的中間件變得更為通用,使其能夠應用在不同的Route上。比如,我們可以設計一個通用的替換response body的中間件,然后將其應用在多個Route上。

Ocelot的配置文件

我們可以將Ocelot的配置信息寫在appsettings.json中,當然也可以將其放在單獨的json文件里,然后通過ConfigureAppConfiguration的調用,將單獨的json文件添加到配置系統中。無論如何,基于JSON文件的Ocelot配置都是可以加入我們自定義的內容的,基于數據庫的或者其它存儲的配置文件信息或許擴展起來并不方便,因此,使用JSON文件作為配置源還是一個不錯的選擇。比如,我們可以在ReRoute的某個配置中添加以下內容:


{

??"DownstreamPathTemplate": "/api/themes",

??"DownstreamScheme": "http",

??"DownstreamHostAndPorts": [

????{

??????"Host": "localhost",

??????"Port": 5010

????}

??],

??"UpstreamPathTemplate": "/themes-api/themes",

??"UpstreamHttpMethod": [ "Get" ],

??"CustomMiddlewares": [

????{

??????"Name": "themeCssMinUrlReplacer",

??????"Enabled": true,

??????"Config": {

????????"replacementTemplate": "/themes-api/theme-css/{name}"

??????}

????}

??]

}

然后就需要有一個方法能夠解析這部分配置內容。為了方便處理,可以增加以下配置Model,專門存放CustomMiddlewares下的配置信息:


public class CustomMiddlewareConfiguration

{

????public string DownstreamPathTemplate { get; set; }

????public string UpstreamPathTemplate { get; set; }

????public int ReRouteConfigurationIndex { get; set; }

????public string Name { get; set; }

????public bool Enabled { get; set; }

????public Dictionary<string, object> Config { get; set; }

}

然后定義下面的擴展方法,用以從IConfiguration對象中解析出所有的CustomMiddleware的配置信息:


public static IEnumerable<CustomMiddlewareConfiguration> GetCustomMiddlewareConfigurations(this IConfiguration config)

{

????var reRoutesConfigSection = config.GetSection("ReRoutes");

????if (reRoutesConfigSection.Exists())

????{

????????var reRoutesConfigList = reRoutesConfigSection.GetChildren();

????????for (var idx = 0; idx < reRoutesConfigList.Count(); idx++)

????????{

????????????var reRouteConfigSection = reRoutesConfigList.ElementAt(idx);

????????????var upstreamPathTemplate = reRouteConfigSection.GetSection("UpstreamPathTemplate").Value;

????????????var downstreamPathTemplate = reRouteConfigSection.GetSection("DownstreamPathTemplate").Value;

????????????var customMidwareConfigSection = reRouteConfigSection.GetSection("CustomMiddlewares");

????????????if (customMidwareConfigSection.Exists())

????????????{

????????????????var customMidwareConfigList = customMidwareConfigSection.GetChildren();

????????????????foreach (var customMidwareConfig in customMidwareConfigList)

????????????????{

????????????????????var customMiddlewareConfiguration = customMidwareConfig.Get<CustomMiddlewareConfiguration>();

????????????????????customMiddlewareConfiguration.UpstreamPathTemplate = upstreamPathTemplate;

????????????????????customMiddlewareConfiguration.DownstreamPathTemplate = downstreamPathTemplate;

????????????????????customMiddlewareConfiguration.ReRouteConfigurationIndex = idx;

????????????????????yield return customMiddlewareConfiguration;

????????????????}

????????????}

????????}

????}

?

????yield break;

}

CustomMiddleware基類

為了提高程序員的開發體驗,我們引入CustomMiddleware基類,在Invoke方法中,CustomMiddleware對象會讀取所有的CustomMiddleware配置信息,并找到屬于當前ReRoute的CustomMiddleware配置信息,從而決定當前的CustomMiddleware是否應該被執行。相關代碼如下:


public abstract class CustomMiddleware : OcelotMiddleware

{

????#region Private Fields

?

????private readonly ICustomMiddlewareConfigurationManager customMiddlewareConfigurationManager;

????private readonly OcelotRequestDelegate next;

?

????#endregion Private Fields

?

????#region Protected Constructors

?

????protected CustomMiddleware(OcelotRequestDelegate next,

????????ICustomMiddlewareConfigurationManager customMiddlewareConfigurationManager,

????????IOcelotLogger logger) : base(logger)

????{

????????this.next = next;

????????this.customMiddlewareConfigurationManager = customMiddlewareConfigurationManager;

????}

?

????#endregion Protected Constructors

?

????#region Public Methods

?

????public async Task Invoke(DownstreamContext context)

????{

????????var customMiddlewareConfigurations = from cmc in this

????????????????????????????????????????????????.customMiddlewareConfigurationManager

????????????????????????????????????????????????.GetCustomMiddlewareConfigurations()

?????????????????????????????????????????????where cmc.DownstreamPathTemplate == context

????????????????????????????????????????????????????.DownstreamReRoute

????????????????????????????????????????????????????.DownstreamPathTemplate

????????????????????????????????????????????????????.Value &&

???????????????????????????????????????????????????cmc.UpstreamPathTemplate == context

????????????????????????????????????????????????????.DownstreamReRoute

????????????????????????????????????????????????????.UpstreamPathTemplate

????????????????????????????????????????????????????.OriginalValue

?????????????????????????????????????????????select cmc;

?

????????var thisMiddlewareName = this.GetType().GetCustomAttribute<CustomMiddlewareAttribute>(false)?.Name;

????????var customMiddlewareConfiguration = customMiddlewareConfigurations.FirstOrDefault(x => x.Name == thisMiddlewareName);

????????if (customMiddlewareConfiguration?.Enabled ?? false)

????????{

????????????await this.DoInvoke(context, customMiddlewareConfiguration);

????????}

?

????????await this.next(context);

????}

?

????#endregion Public Methods

?

????#region Protected Methods

?

????protected abstract Task DoInvoke(DownstreamContext context, CustomMiddlewareConfiguration configuration);

?

????#endregion Protected Methods

}

接下來就簡單了,只需要讓自定義的Ocelot中間件繼承于CustomMiddleware基類就行了,當然,為了解耦類型名稱與中間件名稱,使用一個自定義的CustomMiddlewareAttribute:


[CustomMiddleware("themeCssMinUrlReplacer")]

public class ThemeCssMinUrlReplacer : CustomMiddleware

{

????private readonly Regex regex = new Regex(@"\w+://[a-zA-Z0-9]+(\:\d+)?/themes/(?<theme_name>[a-zA-Z0-9_]+)/bootstrap.min.css");

????public ThemeCssMinUrlReplacer(OcelotRequestDelegate next,

????????ICustomMiddlewareConfigurationManager customMiddlewareConfigurationManager,

????????IOcelotLoggerFactory loggerFactory)

????????: base(next, customMiddlewareConfigurationManager, loggerFactory.CreateLogger<ThemeCssMinUrlReplacer>())

????{

????}

?

????protected override async Task DoInvoke(DownstreamContext context, CustomMiddlewareConfiguration configuration)

????{

????????var downstreamResponseString = await context.DownstreamResponse.Content.ReadAsStringAsync();

????????var downstreamResponseJson = JObject.Parse(downstreamResponseString);

????????var themesArray = (JArray)downstreamResponseJson["themes"];

????????foreach(var token in themesArray)

????????{

????????????var cssMinToken = token["cssMin"];

????????????var cssMinValue = cssMinToken.Value<string>();

????????????if (regex.IsMatch(cssMinValue))

????????????{

????????????????var themeName = regex.Match(cssMinValue).Groups["theme_name"].Value;

????????????????var replacementTemplate = configuration.Config["replacementTemplate"].ToString();

????????????????var replacement = $"{context.HttpContext.Request.Scheme}://{context.HttpContext.Request.Host}{replacementTemplate}"

????????????????????.Replace("{name}", themeName);

????????????????cssMinToken.Replace(replacement);

????????????}

????????}

?

????????context.DownstreamResponse = new DownstreamResponse(

????????????new StringContent(downstreamResponseJson.ToString(Formatting.None), Encoding.UTF8, "application/json"),

????????????context.DownstreamResponse.StatusCode, context.DownstreamResponse.Headers, context.DownstreamResponse.ReasonPhrase);

????}

}

自定義中間件的注冊

在上文介紹的BuildCustomOcelotPipeline擴展方法中,加入以下幾行,就完成所有自定義中間件的注冊:


var customMiddlewareTypes = from type in typeof(Startup).Assembly.GetTypes()

????????????????????????????where type.BaseType == typeof(CustomMiddleware) &&

??????????????????????????????????type.IsDefined(typeof(CustomMiddlewareAttribute), false)

????????????????????????????select type;

foreach (var customMiddlewareType in customMiddlewareTypes)

{

????builder.UseMiddleware(customMiddlewareType);

}

當然,app.UseOcelot的調用要調整為:

1

app.UseOcelot((b, c) => b.BuildCustomOcelotPipeline(c).Build()).Wait();

運行

重新運行API網關,得到結果跟之前的一樣。所不同的是,我們可以將ThemeCssMinUrlReplacer在其它的ReRoute配置上重用了。

總結

以上是生活随笔為你收集整理的在Ocelot中使用自定义的中间件(二)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。