﻿
{"id":26960,"date":"2024-04-20T23:00:08","date_gmt":"2024-04-20T23:00:08","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=26960"},"modified":"2024-04-20T23:00:08","modified_gmt":"2024-04-20T23:00:08","slug":"yarp-ile-microserviceler-de-api-gateway-implementasyonu","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/yarp-ile-microserviceler-de-api-gateway-implementasyonu\/","title":{"rendered":"YARP \u0130le Microservice&#8217;ler de API Gateway Implementasyonu"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>Microserve mimarisinde yap\u0131lan \u00e7al\u0131\u015fmalarda client&#8217;lar a\u00e7\u0131s\u0131ndan en \u00f6nemli konulardan biri servislere istekte bulunabilmek i\u00e7in t\u00fcm servislerin bilgilerine sahip olmas\u0131 gereklili\u011fidir ki b\u00f6ylece hedef servis odakl\u0131 bir istek s\u00fcreci y\u00fcr\u00fctebilsin. Amma velakin microservice gibi b\u00fcy\u00fck sistemlerin s\u00f6z konusu oldu\u011fu \u00e7al\u0131\u015fmalarda bu hi\u00e7te kolay bir \u00e7\u00f6z\u00fcm olmayacak, hatta bir client&#8217;\u0131n t\u00fcm servislerle ilgili bilgilere sahip olmas\u0131 hem g\u00fcvenlik riski hem de s\u00fcrekli artan karma\u015f\u0131kl\u0131k gibi zorluklar e\u015fli\u011finde \u00e7\u0131\u011f gibi b\u00fcy\u00fcyen sorunlarla devam edecektir. \u0130\u015fte bu tarz durumlara kar\u015f\u0131n bizler <a href=\"https:\/\/www.gencayyildiz.com\/blog\/microservice-mimarisinde-api-gateway-nedir\/\" rel=\"noopener\" target=\"_blank\">API Gateway<\/a>&#8216;ler e\u015fli\u011finde \u00e7\u00f6z\u00fcmler getirerek hem g\u00fc\u00e7l\u00fc bir g\u00fcvenlik sunmakta hem de \u00f6l\u00e7eklenebilirlik e\u015fli\u011finde y\u00fcksek kullan\u0131labilirlik sa\u011flayabilmekteyiz. Bizler \u00f6nceki i\u00e7eriklerimizde API Gateway olarak <a href=\"https:\/\/www.gencayyildiz.com\/blog\/net-core-microservices-ocelot-api-gateway\/\" rel=\"noopener\" target=\"_blank\">Ocelot<\/a> arac\u0131n\u0131 teferruatl\u0131 inceleyerek konuya dair teknik bir tecr\u00fcbeyi kaleme alm\u0131\u015ft\u0131k. Bu i\u00e7eri\u011fimizde ise ara\u00e7 olarak <em>YARP<\/em> k\u00fct\u00fcphanesini kullanacak ve b\u00f6ylece reverse proxy davran\u0131\u015fa sahip API Gateway \u00e7al\u0131\u015fmas\u0131n\u0131 da tecr\u00fcbe etmi\u015f olaca\u011f\u0131z. O halde buyurun ba\u015flayal\u0131m&#8230;<\/p>\n<h4>API Gateway Nedir?<\/h4>\n<p>API Gateway, bir yaz\u0131l\u0131m mimarisi bile\u015fenidir ve genellikle microservice mimarilerinde kullan\u0131lan ve temel olarak client ile servisler aras\u0131ndaki ileti\u015fimi kolayla\u015ft\u0131ran bir giri\u015f noktas\u0131 yahut y\u00f6nlendiricidir. API Gateway sayesinde, sorumlulu\u011fu birden fazla servise da\u011f\u0131t\u0131lm\u0131\u015f olan uygulaman\u0131n t\u00fcm servislerine tek bir eri\u015fim noktas\u0131 sa\u011flanabilmekte ve bu g\u00fcvenli bir \u015fekilde ger\u00e7ekle\u015ftirilebilmektedir. Ayr\u0131ca servislerin farkl\u0131 protokoller kullanma ihtimaline kar\u015f\u0131n gelen istekleri do\u011fru servislere y\u00f6nlendirdikten sonra istekleri ilgili servisin kulland\u0131\u011f\u0131 protokollere de d\u00f6n\u00fc\u015ft\u00fcrebilmektedir. Bunlar\u0131n d\u0131\u015f\u0131nda API Gateway sayesinde rahatl\u0131kla <a href=\"https:\/\/www.gencayyildiz.com\/blog\/load-balancingyuk-dengeleme-ve-load-balanceryuk-dengeleyici-nedir\/\" rel=\"noopener\" target=\"_blank\">load balancing<\/a> sa\u011flanabilmekte ve istekler trace edilerek analiz edilebilmektedir.<\/p>\n<p><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/06\/Microservice-Mimarisinde-API-Gateway-Nedir.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/06\/Microservice-Mimarisinde-API-Gateway-Nedir.png\" alt=\"Microservice Mimarisinde API Gateway Nedir\" width=\"771\" height=\"461\" class=\"aligncenter size-full wp-image-16412\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/06\/Microservice-Mimarisinde-API-Gateway-Nedir.png 771w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/06\/Microservice-Mimarisinde-API-Gateway-Nedir-300x179.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/06\/Microservice-Mimarisinde-API-Gateway-Nedir-768x459.png 768w\" sizes=\"auto, (max-width: 771px) 100vw, 771px\" \/><\/a><\/p>\n<h4>YARP Nedir?<\/h4>\n<p><em>YARP(Yet Another Reverse Proxy)<\/em>, Microsoft taraf\u0131ndan geli\u015ftirilen open source bir API Gateway ve reverse proxy k\u00fct\u00fcphanesidir. YARP sayesinde; y\u00fcksek performansl\u0131, \u00fcretime haz\u0131r ve son derece \u00f6zelle\u015ftirilebilir reverse proxy sunucular\u0131 olu\u015fturulabilmektedir.<\/p>\n<p>YARP, her bir deployment senaryosunun \u00f6zel ihtiya\u00e7lar\u0131na g\u00f6re kolayca \u00f6zelle\u015ftirilebilecek \u015fekilde tasarlanm\u0131\u015ft\u0131r.<\/p>\n<blockquote><p><em style=\"color:green;\">API Gateway, API&#8217;leri y\u00f6netmek i\u00e7in tasarlanm\u0131\u015f olan \u00f6zel bir <em>reverse proxy<\/em>&#8216;dir diyebiliriz.<\/em><\/p><\/blockquote>\n<p><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/04\/YARP-Ile-Microserviceler-de-API-Gateway-Implementasyonu.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/04\/YARP-Ile-Microserviceler-de-API-Gateway-Implementasyonu.png\" alt=\"YARP \u0130le Microservice&#039;ler de API Gateway Implementasyonu\" width=\"618\" height=\"326\" class=\"aligncenter size-full wp-image-26965\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/04\/YARP-Ile-Microserviceler-de-API-Gateway-Implementasyonu.png 618w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/04\/YARP-Ile-Microserviceler-de-API-Gateway-Implementasyonu-300x158.png 300w\" sizes=\"auto, (max-width: 618px) 100vw, 618px\" \/><\/a><\/p>\n<h4>YARP Kurulumu ve Konfig\u00fcrasyonu<\/h4>\n<p>YARP&#8217;\u0131 kullanabilmek i\u00e7in ilgili projeye <a href=\"https:\/\/www.nuget.org\/packages\/Yarp.ReverseProxy\/\" rel=\"noopener\" target=\"_blank\">Yarp.ReverseProxy<\/a> k\u00fct\u00fcphanesinin y\u00fcklenmesi ve ard\u0131ndan a\u015fa\u011f\u0131daki gibi yap\u0131land\u0131r\u0131lmas\u0131 gerekmektedir.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nvar builder = WebApplication.CreateBuilder(args);\r\n\r\nbuilder.Services.AddReverseProxy()\r\n    .LoadFromConfig(builder.Configuration.GetSection(&quot;ReverseProxy&quot;));\r\n\r\nvar app = builder.Build();\r\n\r\napp.MapReverseProxy();\r\n\r\napp.Run();\r\n<\/pre>\n<\/div>\n<p>Burada g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere <code>AddReverseProxy<\/code> metoduyla YARP i\u00e7in gerekli servisi ekliyor, <code>MapReverseProxy<\/code> middleware&#8217;i ile de reverse proxy \u00f6zelli\u011fini uygulamada aktifle\u015ftiriyoruz. <code>LoadFromConfig<\/code> metoduyla ise YARP&#8217;\u0131n konfig\u00fcrasyonunu &#8216;appsettings.json&#8217; dosyas\u0131 \u00fczerinden yap\u0131land\u0131r\u0131yoruz. Bu yap\u0131land\u0131rma i\u00e7in kullanaca\u011f\u0131m\u0131z \u015fablon a\u015fa\u011f\u0131daki gibidir;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n{\r\n  &quot;ReverseProxy&quot;: {\r\n    &quot;Routes&quot;: {\r\n      &quot;...&quot;\r\n    },\r\n    &quot;Clusters&quot;: {\r\n      &quot;...&quot;\r\n    }\r\n  }\r\n}\r\n<\/pre>\n<\/div>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere YARP&#8217;\u0131n yap\u0131land\u0131rmas\u0131 <em style=\"color:orange;\">Clusters<\/em> ve <em style=\"color:green;\">Routes<\/em> ayarlar\u0131na g\u00f6re temellendirilmi\u015ftir.<\/p>\n<p><em style=\"color:orange;\">Clusters<\/em> ile reverse proxy taraf\u0131ndan y\u00f6nlendirilen isteklerin hedeflerini belirleyebilmek i\u00e7in birden fazla hedef sunucu veya hizmet grupland\u0131r\u0131lmaktad\u0131r. Misal olarak bir uygulamadaki farkl\u0131 y\u00fckseklikteki sunucular\u0131 veya servisleri bir k\u00fcme olarak cluster ile tan\u0131mlayabiliriz.  Her bir cluster, i\u00e7erisinde hedef sunucunun ya da servisin adresini belirtilen destination bar\u0131nd\u0131rmaktad\u0131r ve bunlar\u0131n say\u0131s\u0131 bir veya birden fazla olabilmektedir. B\u00f6ylece istekler belirli bir k\u00fcme i\u00e7indeki farkl\u0131 hedeflere y\u00f6nlendirilebilir, bu da hedef sunucularda \u00e7e\u015fitlilik sunabilece\u011fi gibi load balancing vs. gibi imkanlarda ekstradan avantajlar sa\u011flayabilmektedir.<\/p>\n<p>Bir cluster \u015fablonu a\u015fa\u011f\u0131daki gibi olabilir;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &quot;Clusters&quot;: {\r\n      &quot;Example-Cluster&quot;: {\r\n        &quot;Destinations&quot;: {\r\n          &quot;destination1&quot;: {\r\n            &quot;Address&quot;: &quot;https:\/\/....\/server1&quot;\r\n          },\r\n          &quot;destination2&quot;: {\r\n            &quot;Address&quot;: &quot;https:\/\/....\/server2&quot;\r\n          }\r\n        }\r\n      }\r\n    }\r\n<\/pre>\n<\/div>\n<p><em style=\"color:green;\">Routes<\/em> ise isteklerin reverse proxy taraf\u0131ndan y\u00f6nlendirilmesinin hangi kurala, cluster&#8217;a ve hedefe g\u00f6re y\u00f6nlendirilece\u011fi tan\u0131mlar\u0131n\u0131 bar\u0131nd\u0131r\u0131r. Misal olarak;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &quot;Routes&quot;: {\r\n      &quot;Example-Route&quot;: {\r\n        &quot;ClusterId&quot;: &quot;Example-Cluster&quot;,\r\n        &quot;Match&quot;: {\r\n          &quot;Path&quot;: &quot;...&quot;\r\n        },\r\n        &quot;Transforms&quot;: &#x5B;\r\n          { &quot;RequestHeader&quot;: &quot;...&quot; },\r\n          { &quot;ResponseHeader&quot;: &quot;...&quot; }\r\n        ]\r\n      }\r\n    }\r\n<\/pre>\n<\/div>\n<p>B\u00fct\u00fcnsel olarak ger\u00e7ek bir YARP yap\u0131land\u0131rmas\u0131 i\u00e7in a\u015fa\u011f\u0131daki \u00f6rne\u011fi inceleyebilirsiniz;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n{\r\n  .\r\n  .\r\n  .\r\n  &quot;ReverseProxy&quot;: {\r\n    &quot;Routes&quot;: {\r\n      &quot;API1-Route&quot;: {\r\n        &quot;ClusterId&quot;: &quot;API1-Cluster&quot;,\r\n        &quot;Match&quot;: {\r\n          &quot;Path&quot;: &quot;\/api1\/{**catch-all}&quot;\r\n        },\r\n        &quot;Transforms&quot;: &#x5B;\r\n          {\r\n            &quot;RequestHeader&quot;: &quot;api1-request-header&quot;,\r\n            &quot;Append&quot;: &quot;api1 request&quot;\r\n          },\r\n          {\r\n            &quot;ResponseHeader&quot;: &quot;api1-response-header&quot;,\r\n            &quot;Append&quot;: &quot;api1 response&quot;,\r\n            &quot;When&quot;: &quot;Always&quot;\r\n          }\r\n        ]\r\n      },\r\n      &quot;API2-Route&quot;: {\r\n        &quot;ClusterId&quot;: &quot;API2-Cluster&quot;,\r\n        &quot;Match&quot;: {\r\n          &quot;Path&quot;: &quot;\/api2\/{**catch-all}&quot;\r\n        },\r\n        &quot;Transforms&quot;: &#x5B;\r\n          {\r\n            &quot;RequestHeader&quot;: &quot;api2-request-header&quot;,\r\n            &quot;Append&quot;: &quot;api2 request&quot;\r\n          },\r\n          {\r\n            &quot;ResponseHeader&quot;: &quot;api2-response-header&quot;,\r\n            &quot;Append&quot;: &quot;api2 response&quot;,\r\n            &quot;When&quot;: &quot;Always&quot;\r\n          }\r\n        ]\r\n      },\r\n      &quot;API3-Route&quot;: {\r\n        &quot;ClusterId&quot;: &quot;API3-Cluster&quot;,\r\n        &quot;Match&quot;: {\r\n          &quot;Path&quot;: &quot;\/api3\/{**catch-all}&quot;\r\n        },\r\n        &quot;Transforms&quot;: &#x5B;\r\n          {\r\n            &quot;RequestHeader&quot;: &quot;api3-request-header&quot;,\r\n            &quot;Append&quot;: &quot;api3 request&quot;\r\n          },\r\n          {\r\n            &quot;ResponseHeader&quot;: &quot;api3-response-header&quot;,\r\n            &quot;Append&quot;: &quot;api3 response&quot;,\r\n            &quot;When&quot;: &quot;Always&quot;\r\n          }\r\n        ]\r\n      }\r\n    },\r\n    &quot;Clusters&quot;: {\r\n      &quot;API1-Cluster&quot;: {\r\n        &quot;Destinations&quot;: {\r\n          &quot;destination1&quot;: {\r\n            &quot;Address&quot;: &quot;https:\/\/localhost:7018&quot;\r\n          }\r\n        }\r\n      },\r\n      &quot;API2-Cluster&quot;: {\r\n        &quot;Destinations&quot;: {\r\n          &quot;destination1&quot;: {\r\n            &quot;Address&quot;: &quot;https:\/\/localhost:7210&quot;\r\n          }\r\n        }\r\n      },\r\n      &quot;API3-Cluster&quot;: {\r\n        &quot;Destinations&quot;: {\r\n          &quot;destination1&quot;: {\r\n            &quot;Address&quot;: &quot;https:\/\/localhost:7144&quot;\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n}\r\n<\/pre>\n<\/div>\n<p>Tabi YARP yap\u0131land\u0131rmas\u0131n\u0131 <code>LoadFromConfig<\/code> metodunun d\u0131\u015f\u0131nda <code>LoadFromMemory<\/code> metodu e\u015fli\u011finde in-memory \u00fczerinden de a\u015fa\u011f\u0131daki gibi konfig\u00fcre edebilirsiniz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nusing Yarp.ReverseProxy.Configuration;\r\n\r\nvar builder = WebApplication.CreateBuilder(args);\r\n\r\nbuilder.Services.AddReverseProxy()\r\n\/\/.LoadFromConfig(builder.Configuration.GetSection(&quot;ReverseProxy&quot;));\r\n.LoadFromMemory(new List&lt;RouteConfig&gt;\r\n{\r\n     new RouteConfig()\r\n     {\r\n        RouteId = &quot;API1-Route&quot;,\r\n        ClusterId = &quot;API1-Cluster&quot;,\r\n        Match = new(){ Path = &quot;\/api1\/{**catch-all}&quot; },\r\n        Transforms = new List&lt;Dictionary&lt;string, string&gt;&gt;()\r\n        {\r\n            new()\r\n            {\r\n                { &quot;RequestHeader&quot;, &quot;api1-request-header&quot; },\r\n                { &quot;Append&quot;, &quot;api1 request&quot; }\r\n            },\r\n            new()\r\n            {\r\n                { &quot;ResponseHeader&quot;, &quot;api1-response-header&quot; },\r\n                { &quot;Append&quot;, &quot;api1 response&quot; },\r\n                { &quot;When&quot;, &quot;Always&quot; },\r\n            }\r\n        }\r\n     },\r\n     new RouteConfig()\r\n     {\r\n        RouteId = &quot;API2-Route&quot;,\r\n        ClusterId = &quot;API2-Cluster&quot;,\r\n        Match = new(){ Path = &quot;\/api2\/{**catch-all}&quot; },\r\n        Transforms = new List&lt;Dictionary&lt;string, string&gt;&gt;()\r\n        {\r\n            new()\r\n            {\r\n                { &quot;RequestHeader&quot;, &quot;api2-request-header&quot; },\r\n                { &quot;Append&quot;, &quot;api2 request&quot; }\r\n            },\r\n            new()\r\n            {\r\n                { &quot;ResponseHeader&quot;, &quot;api2-response-header&quot; },\r\n                { &quot;Append&quot;, &quot;api2 response&quot; },\r\n                { &quot;When&quot;, &quot;Always&quot; },\r\n            }\r\n        }\r\n     },\r\n     new RouteConfig()\r\n     {\r\n        RouteId = &quot;API3-Route&quot;,\r\n        ClusterId = &quot;API3-Cluster&quot;,\r\n        Match = new(){ Path = &quot;\/api3\/{**catch-all}&quot; },\r\n        Transforms = new List&lt;Dictionary&lt;string, string&gt;&gt;()\r\n        {\r\n            new()\r\n            {\r\n                { &quot;RequestHeader&quot;, &quot;api3-request-header&quot; },\r\n                { &quot;Append&quot;, &quot;api3 request&quot; }\r\n            },\r\n            new()\r\n            {\r\n                { &quot;ResponseHeader&quot;, &quot;api3-response-header&quot; },\r\n                { &quot;Append&quot;, &quot;api3 response&quot; },\r\n                { &quot;When&quot;, &quot;Always&quot; },\r\n            }\r\n        }\r\n     }\r\n},\r\nnew List&lt;ClusterConfig&gt;\r\n{\r\n    new ClusterConfig(){\r\n        ClusterId = &quot;API1-Cluster&quot;,\r\n        Destinations = new Dictionary&lt;string, DestinationConfig&gt;()\r\n        {\r\n            { &quot;destination1&quot;, new(){  Address = &quot;https:\/\/localhost:7018&quot; } }\r\n        }\r\n    },\r\n    new ClusterConfig(){\r\n        ClusterId = &quot;API2-Cluster&quot;,\r\n        Destinations = new Dictionary&lt;string, DestinationConfig&gt;()\r\n        {\r\n            { &quot;destination2&quot;, new(){  Address = &quot;https:\/\/localhost:7210&quot; } }\r\n        }\r\n    },\r\n    new ClusterConfig(){\r\n        ClusterId = &quot;API3-Cluster&quot;,\r\n        Destinations = new Dictionary&lt;string, DestinationConfig&gt;()\r\n        {\r\n            { &quot;destination3&quot;, new(){  Address = &quot;https:\/\/localhost:7144&quot; } }\r\n        }\r\n    }\r\n});\r\n\r\nvar app = builder.Build();\r\n\r\napp.MapReverseProxy();\r\n\r\napp.Run();\r\n<\/pre>\n<\/div>\n<p>Art\u0131k karar sizin&#8230; \ud83d\ude42<\/p>\n<h4>Authentication &#038; Authorization Yap\u0131land\u0131rmas\u0131<\/h4>\n<p>Bir API Gateway&#8217;den beklenece\u011fi \u00fczere YARP ile de istekleri hedef servislere y\u00f6nlendirirken \u00f6ncelikle kimlik do\u011frulama ve yetki kontrol\u00fc zorunlu k\u0131l\u0131nabilmektedir. Bunu \u00f6rneklendirebilmek i\u00e7in a\u015fa\u011f\u0131daki gibi g\u00fcvenlik protokol\u00fc uygulam\u0131\u015f olan &#8216;API1&#8217; servisine API Gateway \u00fczerinden eri\u015fim g\u00f6sterilmeye \u00e7al\u0131\u015f\u0131ld\u0131\u011f\u0131n\u0131 varsayal\u0131m;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nusing Microsoft.AspNetCore.Authentication.JwtBearer;\r\nusing Microsoft.IdentityModel.Tokens;\r\nusing System.Text;\r\n\r\nvar builder = WebApplication.CreateBuilder(args);\r\n\r\nbuilder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)\r\n        .AddJwtBearer(options =&gt;\r\n        {\r\n            options.TokenValidationParameters = new TokenValidationParameters\r\n            {\r\n                ValidateIssuer = true,\r\n                ValidateAudience = true,\r\n                ValidateLifetime = true,\r\n                ValidateIssuerSigningKey = true,\r\n                ValidIssuer = builder.Configuration&#x5B;&quot;Jwt:Issuer&quot;],\r\n                ValidAudience = builder.Configuration&#x5B;&quot;Jwt:Audience&quot;],\r\n                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration&#x5B;&quot;Jwt:Key&quot;]))\r\n            };\r\n        });\r\n\r\nbuilder.Services.AddAuthorization(options =&gt;\r\n{\r\n    options.AddPolicy(&quot;Authenticated&quot;, policy =&gt; policy.RequireAuthenticatedUser());\r\n});\r\n\r\nvar app = builder.Build();\r\n\r\napp.MapGet(&quot;\/api1&quot;, (HttpContext httpContext) =&gt;\r\n{\r\n    return &quot;API 1&quot;;\r\n}).RequireAuthorization(&quot;Authenticated&quot;);\r\n\r\napp.UseAuthentication();\r\napp.UseAuthorization();\r\n\r\napp.Run();\r\n<\/pre>\n<\/div>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere ilgili servisin &#8216;\/api1&#8217; endpoint&#8217;ine eri\u015fim g\u00f6sterilebilmesi i\u00e7in &#8216;Authenticated&#8217; politikas\u0131 gere\u011fi sadece kimli\u011fi do\u011frulanm\u0131\u015f bir kullan\u0131c\u0131 olmak yeterlidir. Bunu kontrol edebilmek i\u00e7in <a href=\"http:\/\/jwtbuilder.jamiekurtz.com\/\" rel=\"noopener\" target=\"_blank\">http:\/\/jwtbuilder.jamiekurtz.com\/<\/a> adresi \u00fczerinden pekte g\u00fcvenli olmasa da \u015fimdilik test ama\u00e7l\u0131 token validation parametrelerine uygun bir JWT \u00fcretip deneyde bulunabiliriz. \u0130lgili parametrelerin de\u011ferlerini i\u00e7eri\u011fimizin sonunda payla\u015f\u0131lan github linkinden edinebilecek olsan\u0131z da i\u015finizi kolayla\u015ft\u0131rmak i\u00e7in a\u015fa\u011f\u0131da payla\u015fmakta fayda g\u00f6rmekteyim(tabi sizler kendinize g\u00f6re bu de\u011ferleri \u00f6zelle\u015ftirebilirsiniz);<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n{\r\n  .\r\n  .\r\n  .\r\n  &quot;Jwt&quot;: {\r\n    &quot;Issuer&quot;: &quot;www.gencayyildiz.com&quot;,\r\n    &quot;Audience&quot;: &quot;www.filanca.com&quot;,\r\n    &quot;Key&quot;: &quot;laylaylom galiba sana g\u00f6re sevmeler...&quot;\r\n  }\r\n}\r\n<\/pre>\n<\/div>\n<p><div id=\"attachment_26973\" style=\"width: 913px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/04\/Ekran-goruntusu-2024-04-21-003652.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-26973\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/04\/Ekran-goruntusu-2024-04-21-003652.png\" alt=\"YARP \u0130le Microservice&#039;ler de API Gateway Implementasyonu\" width=\"903\" height=\"203\" class=\"size-full wp-image-26973\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/04\/Ekran-goruntusu-2024-04-21-003652.png 903w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/04\/Ekran-goruntusu-2024-04-21-003652-300x67.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/04\/Ekran-goruntusu-2024-04-21-003652-768x173.png 768w\" sizes=\"auto, (max-width: 903px) 100vw, 903px\" \/><\/a><p id=\"caption-attachment-26973\" class=\"wp-caption-text\">Test ama\u00e7l\u0131 \u00fcretilmi\u015f olan JWT&#8230;<\/p><\/div>Velhas\u0131l kelam, \u015fimdi bu JWT de\u011ferini kullanarak API Gateway \u00fczerinden istekte bulunulmak isteniliyorsa e\u011fer \u00f6ncelikle YARP&#8217;\u0131n kullan\u0131ld\u0131\u011f\u0131 serviste de bir authentication ve authorization yap\u0131land\u0131rmas\u0131nda bulunulmas\u0131 gerekmektedir.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nusing Microsoft.AspNetCore.Authentication.JwtBearer;\r\nusing Microsoft.IdentityModel.Tokens;\r\nusing System.Text;\r\n\r\nvar builder = WebApplication.CreateBuilder(args);\r\n\r\nbuilder.Services.AddReverseProxy()\r\n.LoadFromConfig(builder.Configuration.GetSection(&quot;ReverseProxy&quot;));\r\n\r\nbuilder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)\r\n       .AddJwtBearer(options =&gt;\r\n       {\r\n           options.TokenValidationParameters = new TokenValidationParameters\r\n           {\r\n               ValidateIssuer = true,\r\n               ValidateAudience = true,\r\n               ValidateLifetime = true,\r\n               ValidateIssuerSigningKey = true,\r\n               ValidIssuer = builder.Configuration&#x5B;&quot;Jwt:Issuer&quot;],\r\n               ValidAudience = builder.Configuration&#x5B;&quot;Jwt:Audience&quot;],\r\n               IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration&#x5B;&quot;Jwt:Key&quot;]))\r\n           };\r\n       });\r\n\r\nbuilder.Services.AddAuthorization(options =&gt;\r\n{\r\n    options.AddPolicy(&quot;Authenticated&quot;, policy =&gt; policy.RequireAuthenticatedUser());\r\n});\r\n\r\nvar app = builder.Build();\r\n\r\napp.UseAuthentication();\r\napp.UseAuthorization();\r\n\r\napp.MapReverseProxy();\r\n\r\napp.Run();\r\n<\/pre>\n<\/div>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere yukar\u0131daki gibi YARP \u00fczerinden de bir yetkilendirme politikas\u0131 tan\u0131mlanmal\u0131d\u0131r ve bu politika hedef servistekiyle birebir ayn\u0131 olmal\u0131d\u0131r. Ayr\u0131ca art\u0131k kimlik do\u011frulama ve yetkilendirme i\u015flemleri yap\u0131laca\u011f\u0131 i\u00e7in <code>MapReverseProxy<\/code> middleware&#8217;inden \u00f6nce <code>UseAuthentication<\/code> ve <code>UseAuthorization<\/code> middleware&#8217;lerinin \u00e7a\u011fr\u0131lmas\u0131 gerekmektedir.<\/p>\n<p>Ve son olarak tan\u0131mlanm\u0131\u015f olan bu politikan\u0131n hangi hedef servisle ili\u015fkili oldu\u011funu ifade edebilmek i\u00e7in bunu yap\u0131land\u0131rmada a\u015fa\u011f\u0131daki gibi <code>AuthorizationPolicy<\/code> e\u015fli\u011finde bildirmek gerekmektedir;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n  &quot;ReverseProxy&quot;: {\r\n    &quot;Routes&quot;: {\r\n      &quot;API1-Route&quot;: {\r\n        &quot;ClusterId&quot;: &quot;API1-Cluster&quot;,\r\n        &quot;AuthorizationPolicy&quot;: &quot;Authenticated&quot;,\r\n        &quot;Match&quot;: {\r\n          &quot;Path&quot;: &quot;\/api1\/{**catch-all}&quot;\r\n        },\r\n        &quot;Transforms&quot;: &#x5B;\r\n          {\r\n            &quot;RequestHeader&quot;: &quot;api1-request-header&quot;,\r\n            &quot;Append&quot;: &quot;api1 request&quot;\r\n          },\r\n          {\r\n            &quot;ResponseHeader&quot;: &quot;api1-response-header&quot;,\r\n            &quot;Append&quot;: &quot;api1 response&quot;,\r\n            &quot;When&quot;: &quot;Always&quot;\r\n          }\r\n        ]\r\n      }\r\n    },\r\n    .\r\n    .\r\n    .\r\n  }\r\n<\/pre>\n<\/div>\n<p>Bu bildirim neticesinde ilgili politikay\u0131 uygulayan hedef servis, yukar\u0131da olu\u015fturdu\u011fumuz JWT e\u015fli\u011finde yap\u0131lacak olan istekte API Gateway taraf\u0131ndan tetiklenebilecektir. \u0130\u015fte YARP, mevcut authentication ve authorization middleware mekanizmalar\u0131na bu \u015fekilde entegre olabilmektedir.<\/p>\n<h4>Rate Limiting Yap\u0131land\u0131rmas\u0131<\/h4>\n<p>YARP ile geli\u015ftirilen sisteme, g\u00fcvenli\u011fi art\u0131rmak ve sunucular \u00fczerindeki y\u00fck\u00fc azaltmak i\u00e7in rate limiting&#8217;de uygulanabilmektedir.  Rate limiting sayesinde, hedef API&#8217;lere gelen istek say\u0131lar\u0131n\u0131 s\u0131n\u0131rland\u0131rabilmekte ve \u00f6l\u00e7eklendirebilmekteyiz. YARP taraf\u0131ndan .NET mimarisinde dahili olarak varl\u0131k g\u00f6steren rate limiting davran\u0131\u015f\u0131 desteklenmektedir. <span style=\"font-size:12px;\">.NET 7 ile gelmi\u015f olan build-in rate limiting mekanizmas\u0131na dair \u00e7ekmi\u015f oldu\u011fum ders videosunu izlemek i\u00e7in <a href=\"https:\/\/www.youtube.com\/watch?v=TVrKJD9Tg5A\" rel=\"noopener\" target=\"_blank\">t\u0131klay\u0131n\u0131z<\/a>.<\/span> <\/p>\n<p>Bunun i\u00e7in tek yap\u0131lmas\u0131 gereken bir rate limiting politikas\u0131 belirlemektir;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nbuilder.Services.AddRateLimiter(rateLimiterOptions =&gt;\r\n{\r\n    rateLimiterOptions.AddFixedWindowLimiter(&quot;fixed&quot;, options =&gt;\r\n    {\r\n        options.Window = TimeSpan.FromSeconds(10);\r\n        options.PermitLimit = 5;\r\n    });\r\n});\r\n<\/pre>\n<\/div>\n<p>Ve ard\u0131ndan <code>UseRateLimiter<\/code> middleware&#8217;i <code>MapReverseProxy<\/code>&#8216;den \u00f6nce \u00e7a\u011fr\u0131lmal\u0131d\u0131r.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\napp.UseRateLimiter();\r\n\r\napp.MapReverseProxy();\r\n<\/pre>\n<\/div>\n<p>Bu a\u015famadan sonra a\u015fa\u011f\u0131daki gibi yap\u0131land\u0131rma \u00fczerinden <code>RateLimiterPolicy<\/code> ile istenilen route&#8217;a tan\u0131mlanan politikaya uygun istek s\u0131n\u0131rland\u0131rmas\u0131 uygulanabilir;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n  &quot;ReverseProxy&quot;: {\r\n    &quot;Routes&quot;: {\r\n      &quot;API1-Route&quot;: {\r\n        &quot;ClusterId&quot;: &quot;API1-Cluster&quot;,\r\n        &quot;AuthorizationPolicy&quot;: &quot;Authenticated&quot;,\r\n        &quot;RateLimiterPolicy&quot;: &quot;fixed&quot;,\r\n        &quot;Match&quot;: {\r\n          &quot;Path&quot;: &quot;\/api1\/{**catch-all}&quot;\r\n        },\r\n        &quot;Transforms&quot;: &#x5B;\r\n          {\r\n            &quot;RequestHeader&quot;: &quot;api1-request-header&quot;,\r\n            &quot;Append&quot;: &quot;api1 request&quot;\r\n          },\r\n          {\r\n            &quot;ResponseHeader&quot;: &quot;api1-response-header&quot;,\r\n            &quot;Append&quot;: &quot;api1 response&quot;,\r\n            &quot;When&quot;: &quot;Always&quot;\r\n          }\r\n        ]\r\n      }\r\n    },\r\n    .\r\n    .\r\n    .\r\n  }\r\n<\/pre>\n<\/div>\n<p><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/04\/YARP-Ile-Microserviceler-de-API-Gateway-Implementasyonu.gif\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/04\/YARP-Ile-Microserviceler-de-API-Gateway-Implementasyonu.gif\" alt=\"YARP \u0130le Microservice&#039;ler de API Gateway Implementasyonu\" width=\"792\" height=\"390\" class=\"aligncenter size-full wp-image-26975\" \/><\/a>Nihai olarak;<\/p>\n<p>Microservice mimarisinde olmazsa olmaz diyebilece\u011fimiz API Gateway yap\u0131lanmas\u0131 i\u00e7in olduk\u00e7a etkili bir ara\u00e7 olan YARP neredeyse m\u00fckemmel bir se\u00e7enektir diyebiliriz. Bu i\u00e7eri\u011fimizde; temel yap\u0131land\u0131rma, kimlik do\u011frulama, yetkilendirme ve rate limiting gibi YARP&#8217;\u0131n s\u0131kl\u0131kla kullan\u0131lacak bir\u00e7ok \u00f6zelli\u011fini ele alm\u0131\u015f bulunuyoruz. Haliyle b\u00f6ylece sonraki yaz\u0131lar\u0131m\u0131zdan birinde klavyeye alaca\u011f\u0131m\u0131z YARP ile load balancing davran\u0131\u015f\u0131na temel atm\u0131\u015f bulunuyoruz.<\/p>\n<p>\u0130lgilenenlerin faydalanmas\u0131 dile\u011fiyle&#8230;<br \/>\nSonraki yaz\u0131lar\u0131mda g\u00f6r\u00fc\u015fmek \u00fczere&#8230;<br \/>\n\u0130yi \u00e7al\u0131\u015fmalar&#8230;<\/p>\n<p>Not : \u00d6rnek \u00e7al\u0131\u015fmaya a\u015fa\u011f\u0131daki github adresinden eri\u015febilirsiniz.<br \/>\n<a href=\"https:\/\/github.com\/gncyyldz\/Microservice_API_Gateway_With_YARP\" rel=\"noopener\" target=\"_blank\">https:\/\/github.com\/gncyyldz\/Microservice_API_Gateway_With_YARP<\/a><\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Merhaba, Microserve mimarisinde yap\u0131lan \u00e7al\u0131\u015fmalarda client&#8217;lar a\u00e7\u0131s\u0131ndan en \u00f6nemli konulardan biri servislere istekte bulunabilmek i\u00e7in t\u00fcm servislerin bilgilerine sahip olmas\u0131 gereklili\u011fidir ki b\u00f6ylece hedef servis odakl\u0131 bir istek s\u00fcreci y\u00fcr\u00fctebilsin. Amma velakin microservice gibi&#46;&#46;&#46;<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":26965,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2739,3573],"tags":[3579,3580,4257,4276,5048,5046,5047,5049],"class_list":["post-26960","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net-core","category-microservices","tag-api-gateway","tag-api-gateway-nedir","tag-load-balancing","tag-ocelot","tag-reverse-proxy","tag-yarp","tag-yarp-api-gateway","tag-yet-another-reverse-proxy"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/26960","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/comments?post=26960"}],"version-history":[{"count":12,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/26960\/revisions"}],"predecessor-version":[{"id":26977,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/26960\/revisions\/26977"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/26965"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=26960"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=26960"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=26960"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}