日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

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

發(fā)布時(shí)間:2023/12/4 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在Ocelot中使用自定义的中间件(一) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Ocelot是ASP.NET Core下的API網(wǎng)關(guān)的一種實(shí)現(xiàn),在微服務(wù)架構(gòu)領(lǐng)域發(fā)揮了非常重要的作用。本文不會(huì)從整個(gè)微服務(wù)架構(gòu)的角度來介紹Ocelot,而是介紹一下最近在學(xué)習(xí)過程中遇到的一個(gè)問題,以及如何使用中間件(Middleware)來解決這樣的問題。

問題描述

在上文中,我介紹了一種在Angular站點(diǎn)里基于Bootstrap切換主題的方法。之后,我將多個(gè)主題的boostrap.min.css文件放到一個(gè)ASP.NET Core Web API的站點(diǎn)上,并用靜態(tài)文件的方式進(jìn)行分發(fā),在完成這部分工作之后,調(diào)用這個(gè)Web API,就可以從服務(wù)端獲得主題信息以及所對(duì)應(yīng)的樣式文件。例如:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

// GET http://localhost:5010/api/themes

{

????"version": "1.0.0",

????"themes": [

????????{

????????????"name": "蔚藍(lán) (Cerulean)",

????????????"description": "Cerulean",

????????????"category": "light",

????????????"cssMin": "http://localhost:5010/themes/cerulean/bootstrap.min.css",

????????????"navbarClass": "navbar-dark",

????????????"navbarBackgroundClass": "bg-primary",

????????????"footerTextClass": "text-light",

????????????"footerLinkClass": "text-light",

????????????"footerBackgroundClass": "bg-primary"

????????},

????????{

????????????"name": "機(jī)械 (Cyborg)",

????????????"description": "Cyborg",

????????????"category": "dark",

????????????"cssMin": "http://localhost:5010/themes/cyborg/bootstrap.min.css",

????????????"navbarClass": "navbar-dark",

????????????"navbarBackgroundClass": "bg-dark",

????????????"footerTextClass": "text-dark",

????????????"footerLinkClass": "text-dark",

????????????"footerBackgroundClass": "bg-light"

????????}

????]

}

當(dāng)然,整個(gè)項(xiàng)目中不僅僅是有這個(gè)themes API,還有另外2-3個(gè)服務(wù)在后臺(tái)運(yùn)行,項(xiàng)目是基于微服務(wù)架構(gòu)的。為了能夠讓前端有統(tǒng)一的API接口,我使用Ocelot作為服務(wù)端的API網(wǎng)關(guān),以便為Angular站點(diǎn)提供API服務(wù)。于是,我定義了如下ReRoute規(guī)則:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

{

????"ReRoutes": [

????????{

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

????????????"DownstreamScheme": "http",

????????????"DownstreamHostAndPorts": [

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

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

????????????????????"Port": 5010

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

????????????],

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

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

????????}

????]

}

假設(shè)API網(wǎng)關(guān)運(yùn)行在http://localhost:9023,那么基于上面的ReRoute規(guī)則,通過訪問http://localhost:9023/themes-api/themes,即可轉(zhuǎn)發(fā)到后臺(tái)的http://localhost:5010/api/themes,完成API的調(diào)用。運(yùn)行一下,調(diào)用結(jié)果如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

// GET http://localhost:9023/themes-api/themes

{

????"version": "1.0.0",

????"themes": [

????????{

????????????"name": "蔚藍(lán) (Cerulean)",

????????????"description": "Cerulean",

????????????"category": "light",

????????????"cssMin": "http://localhost:5010/themes/cerulean/bootstrap.min.css",

????????????"navbarClass": "navbar-dark",

????????????"navbarBackgroundClass": "bg-primary",

????????????"footerTextClass": "text-light",

????????????"footerLinkClass": "text-light",

????????????"footerBackgroundClass": "bg-primary"

????????},

????????{

????????????"name": "機(jī)械 (Cyborg)",

????????????"description": "Cyborg",

????????????"category": "dark",

????????????"cssMin": "http://localhost:5010/themes/cyborg/bootstrap.min.css",

????????????"navbarClass": "navbar-dark",

????????????"navbarBackgroundClass": "bg-dark",

????????????"footerTextClass": "text-dark",

????????????"footerLinkClass": "text-dark",

????????????"footerBackgroundClass": "bg-light"

????????}

????]

}

看上去一切正常,但是,每個(gè)主題設(shè)置的css文件地址仍然還是指向下游服務(wù)的URL地址,比如上面的cssMin中,還是使用的http://localhost:5010。從部署的角度,外部是無(wú)法訪問除了API網(wǎng)關(guān)以外的其它服務(wù)的,于是,這就造成了css文件無(wú)法被訪問的問題。

解決這個(gè)問題的思路很簡(jiǎn)單,就是API網(wǎng)關(guān)在返回response的時(shí)候,將cssMin的地址替換掉。如果在Ocelot的配置中加入以下ReRoute設(shè)置:

1

2

3

4

5

6

7

8

9

10

11

12

{

??"DownstreamPathTemplate": "/themes/{name}/bootstrap.min.css",

??"DownstreamScheme": "http",

??"DownstreamHostAndPorts": [

????{

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

??????"Port": 5010

????}

??],

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

??"UpstreamHttpMethod": [ "Get" ]

}

那么只需要將下游response中cssMin的值(比如http://localhost:5010/themes/cyborg/bootstrap.min.css)替換為Ocelot網(wǎng)關(guān)中設(shè)置的上游URL(比如http://localhost:9023/themes-api/theme-css/cyborg),然后將替換后的response返回給API調(diào)用方即可。這個(gè)過程,可以使用Ocelot中間件完成。

使用Ocelot中間件

Ocelot中間件是繼承于OcelotMiddleware類的子類,并且可以在Startup.Configure方法中,通過app.UseOcelot方法將中間件注入到Ocelot管道中,然而,簡(jiǎn)單地調(diào)用IOcelotPipelineBuilder的UseMiddleware方法是不行的,它會(huì)導(dǎo)致整個(gè)Ocelot網(wǎng)關(guān)不可用。比如下面的方法是不行的:



這是因?yàn)闆]有將Ocelot的其它Middleware加入到管道中,Ocelot管道中只有ThemeCssMinUrlReplacer中間件。要解決這個(gè)問題,我目前的方法就是通過使用擴(kuò)展方法,將所有Ocelot中間全部注冊(cè)好,然后再注冊(cè)自定義的中間件,比如:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

public static IOcelotPipelineBuilder BuildCustomOcelotPipeline(this IOcelotPipelineBuilder builder,

????OcelotPipelineConfiguration pipelineConfiguration)

{

????builder.UseExceptionHandlerMiddleware();

????builder.MapWhen(context => context.HttpContext.WebSockets.IsWebSocketRequest,

????????app =>

????????{

????????????app.UseDownstreamRouteFinderMiddleware();

????????????app.UseDownstreamRequestInitialiser();

????????????app.UseLoadBalancingMiddleware();

????????????app.UseDownstreamUrlCreatorMiddleware();

????????????app.UseWebSocketsProxyMiddleware();

????????});

????builder.UseIfNotNull(pipelineConfiguration.PreErrorResponderMiddleware);

????builder.UseResponderMiddleware();

????builder.UseDownstreamRouteFinderMiddleware();

????builder.UseSecurityMiddleware();

????if (pipelineConfiguration.MapWhenOcelotPipeline != null)

????{

????????foreach (var pipeline in pipelineConfiguration.MapWhenOcelotPipeline)

????????{

????????????builder.MapWhen(pipeline);

????????}

????}

????builder.UseHttpHeadersTransformationMiddleware();

????builder.UseDownstreamRequestInitialiser();

????builder.UseRateLimiting();

?

????builder.UseRequestIdMiddleware();

????builder.UseIfNotNull(pipelineConfiguration.PreAuthenticationMiddleware);

????if (pipelineConfiguration.AuthenticationMiddleware == null)

????{

????????builder.UseAuthenticationMiddleware();

????}

????else

????{

????????builder.Use(pipelineConfiguration.AuthenticationMiddleware);

????}

????builder.UseClaimsToClaimsMiddleware();

????builder.UseIfNotNull(pipelineConfiguration.PreAuthorisationMiddleware);

????if (pipelineConfiguration.AuthorisationMiddleware == null)

????{

????????builder.UseAuthorisationMiddleware();

????}

????else

????{

????????builder.Use(pipelineConfiguration.AuthorisationMiddleware);

????}

????builder.UseClaimsToHeadersMiddleware();

????builder.UseIfNotNull(pipelineConfiguration.PreQueryStringBuilderMiddleware);

????builder.UseClaimsToQueryStringMiddleware();

????builder.UseLoadBalancingMiddleware();

????builder.UseDownstreamUrlCreatorMiddleware();

????builder.UseOutputCacheMiddleware();

????builder.UseHttpRequesterMiddleware();

?????

????return builder;

}

然后再調(diào)用app.UseOcelot即可:

1

2

3

4

5

6

app.UseOcelot((builder, config) =>

{

????builder.BuildCustomOcelotPipeline(config)

????.UseMiddleware<ThemeCssMinUrlReplacer>()

????.Build();

});

這種做法其實(shí)聽起來不是特別的優(yōu)雅,但是目前也沒找到更合適的方式來解決Ocelot中間件注冊(cè)的問題。

以下便是ThemeCssMinUrlReplacer中間件的代碼,可以看到,我們使用正則表達(dá)式替換了cssMin的URL部分,使得css文件的地址可以正確被返回:



執(zhí)行結(jié)果如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

// GET http://localhost:9023/themes-api/themes

{

??"version": "1.0.0",

??"themes": [

????{

??????"name": "蔚藍(lán) (Cerulean)",

??????"description": "Cerulean",

??????"category": "light",

??????"cssMin": "http://localhost:9023/themes-api/theme-css/cerulean",

??????"navbarClass": "navbar-dark",

??????"navbarBackgroundClass": "bg-primary",

??????"footerTextClass": "text-light",

??????"footerLinkClass": "text-light",

??????"footerBackgroundClass": "bg-primary"

????},

????{

??????"name": "機(jī)械 (Cyborg)",

??????"description": "Cyborg",

??????"category": "dark",

??????"cssMin": "http://localhost:9023/themes-api/theme-css/cyborg",

??????"navbarClass": "navbar-dark",

??????"navbarBackgroundClass": "bg-dark",

??????"footerTextClass": "text-dark",

??????"footerLinkClass": "text-dark",

??????"footerBackgroundClass": "bg-light"

????}

??]

}

總結(jié)

本文介紹了使用Ocelot中間件實(shí)現(xiàn)下游服務(wù)response body的替換任務(wù),在ThemeCssMinUrlReplacer的實(shí)現(xiàn)代碼中,我們使用了context.DownstreamReRoute.DownstreamPathTemplate.Value來判斷當(dāng)前執(zhí)行的URL是否需要由該中間件進(jìn)行處理,以避免不必要的中間件邏輯執(zhí)行。這個(gè)設(shè)計(jì)可以再優(yōu)化一下,使用一個(gè)簡(jiǎn)單的框架讓程序員可以通過Ocelot的配置文件來更為靈活地使用Ocelot中間件,下文介紹這部分內(nèi)容。

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。