Share via


Azure API Management hizmetinden dış hizmetleri kullanma

UYGULANANLAR: Tüm API Management katmanları

Azure API Management hizmetinde sağlanan ilkeler yalnızca gelen istek, giden yanıt ve temel yapılandırma bilgilerine dayalı olarak çok çeşitli yararlı işler yapabilir. Ancak, API Management ilkelerinden dış hizmetlerle etkileşim kurabilmek birçok farklı fırsat sunar.

Daha önce günlüğe kaydetme, izleme ve analiz için Azure Event Hub hizmetiyle nasıl etkileşim kurabileceğinizi gördünüz. Bu makalede, herhangi bir dış HTTP tabanlı hizmetle etkileşim kurmanıza olanak sağlayan ilkeler gösterilmektedir. Bu ilkeler, uzak olayları tetikleme veya özgün isteği ve yanıtı bir şekilde işlemek için kullanılan bilgileri almak için kullanılabilir.

Tek Yönlü İstek Gönder

Büyük olasılıkla en basit dış etkileşim, bir dış hizmete önemli bir olay hakkında bildirim gönderilmesini sağlayan isteğin tetikle ve unut stilidir. Denetim akışı ilkesi choose , ilgilendiğiniz her türlü koşulu algılamak için kullanılabilir. Koşul karşılanırsa, send-one-way-request ilkesini kullanarak bir dış HTTP isteği oluşturabilirsiniz. Bu, Hipchat veya Slack gibi bir mesajlaşma sistemine veya SendGrid veya MailChimp gibi bir posta API'sine yönelik bir istek veya PagerDuty gibi kritik destek olayları için olabilir. Bu mesajlaşma sistemlerinin tümü çağrılabilen basit HTTP API'lerine sahiptir.

Slack ile uyarı oluşturma

Aşağıdaki örnekte, HTTP yanıt durumu kodu 500'den büyük veya buna eşitse Slack sohbet odasına ileti gönderme işlemi gösterilmektedir. 500 aralık hatası, arka uç API'siyle ilgili, API istemcisinin kendi kendine çözümleyemediği bir sorunu gösterir. Genellikle API Management bölümünde bir tür müdahale gerektirir.

<choose>
  <when condition="@(context.Response.StatusCode >= 500)">
    <send-one-way-request mode="new">
      <set-url>https://hooks.slack.com/services/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</set-url>
      <set-method>POST</set-method>
      <set-body>@{
        return new JObject(
          new JProperty("username","APIM Alert"),
          new JProperty("icon_emoji", ":ghost:"),
          new JProperty("text", String.Format("{0} {1}\nHost: {2}\n{3} {4}\n User: {5}",
            context.Request.Method,
            context.Request.Url.Path + context.Request.Url.QueryString,
            context.Request.Url.Host,
            context.Response.StatusCode,
            context.Response.StatusReason,
            context.User.Email
          ))
        ).ToString();
      }</set-body>
    </send-one-way-request>
  </when>
</choose>

Slack,gelen web kancaları şeklinde bir düşünceye sahiptir. Gelen web kancasını yapılandırırken Slack, basit bir POST isteği yapmanıza ve Slack kanalına bir ileti iletmenize olanak tanıyan özel bir URL oluşturur. Oluşturduğunuz JSON gövdesi Slack tarafından tanımlanan bir biçimi temel alır.

Slack Web Kancası

Ateş ve unutmak yeterli mi?

İstekte ateş ve unutma stili kullanılırken bazı dezavantajlar vardır. Bir nedenden dolayı istek başarısız olursa, hata bildirilmeyecektir. Bu özel durumda, ikincil hata raporlama sistemine sahip olmanın karmaşıklığı ve yanıtı beklemenin ek performans maliyeti garanti değildir. Yanıtı denetlemenin gerekli olduğu senaryolar için, istek gönder ilkesi daha iyi bir seçenektir.

İstek Gönder

İlke, send-request karmaşık işleme işlevleri gerçekleştirmek ve daha fazla ilke işleme için kullanılabilecek verileri API yönetim hizmetine döndürmek için bir dış hizmet kullanılmasını sağlar.

Başvuru belirteçlerini yetkilendirme

API Management'ın önemli bir işlevi arka uç kaynaklarını korumaktır. API'niz tarafından kullanılan yetkilendirme sunucusu, Microsoft Entra Id'nin yaptığı gibi OAuth2 akışının bir parçası olarak JWT belirteçleri oluşturursa, belirtecin geçerliliğini doğrulamak için ilkeyi veya validate-azure-ad-token ilkeyi kullanabilirsinizvalidate-jwt. Bazı yetkilendirme sunucuları, yetkilendirme sunucusuna geri çağırma yapmadan doğrulanamayan başvuru belirteçleri olarak adlandırılan belirteçleri oluşturur.

Standartlaştırılmış iç gözlem

Geçmişte, bir yetkilendirme sunucusuyla başvuru belirtecini doğrulamanın standart bir yolu yoktu. Ancak yakın zamanda önerilen standart rfc 7662 , bir kaynak sunucusunun bir belirtecin geçerliliğini nasıl doğrulayabildiğini tanımlayan IETF tarafından yayımlandı.

Belirteci ayıklama

İlk adım, yetkilendirme üst bilgisinden belirteci ayıklamaktır. Üst bilgi değeri yetkilendirme düzeni, tek bir alan ve ardından RFC 6750'ye göre yetkilendirme belirteci ile Bearer biçimlendirilmelidir. Ne yazık ki yetkilendirme düzeninin atlandığı durumlar vardır. Ayrıştırma sırasında bunu hesaba eklemek için API Management, üst bilgi değerini bir alana böler ve döndürülen dize dizisinden son dizeyi seçer. Bu, hatalı biçimlendirilmiş yetkilendirme üst bilgileri için geçici bir çözüm sağlar.

<set-variable name="token" value="@(context.Request.Headers.GetValueOrDefault("Authorization","scheme param").Split(' ').Last())" />

Doğrulama isteğinde bulunma

API Management yetkilendirme belirtecine sahip olduktan sonra API Management, belirteci doğrulama isteğinde bulunabilir. RFC 7662 bu işlem iç gözlemini çağırır ve iç gözlem kaynağına bir HTML formu göndermenizi POST gerektirir. HTML formu en azından anahtarıyla tokenbir anahtar/değer çifti içermelidir. Kötü amaçlı istemcilerin geçerli belirteçler için trolleme yapamayacağından emin olmak için yetkilendirme sunucusuna yönelik bu isteğin de kimliği doğrulanmalıdır.

<send-request mode="new" response-variable-name="tokenstate" timeout="20" ignore-error="true">
  <set-url>https://microsoft-apiappec990ad4c76641c6aea22f566efc5a4e.azurewebsites.net/introspection</set-url>
  <set-method>POST</set-method>
  <set-header name="Authorization" exists-action="override">
    <value>basic dXNlcm5hbWU6cGFzc3dvcmQ=</value>
  </set-header>
  <set-header name="Content-Type" exists-action="override">
    <value>application/x-www-form-urlencoded</value>
  </set-header>
  <set-body>@($"token={(string)context.Variables["token"]}")</set-body>
</send-request>

Yanıtı denetleme

response-variable-name özniteliği, döndürülen yanıta erişim vermek için kullanılır. Bu özellikte tanımlanan ad, nesneye erişmek IResponse için sözlükte context.Variables anahtar olarak kullanılabilir.

Yanıt nesnesinden gövdeyi alabilirsiniz ve RFC 7622 API Management'a yanıtın bir JSON nesnesi olması gerektiğini ve boole değeri olarak adlandırılan active en az bir özellik içermesi gerektiğini söyler. True active olduğunda belirteç geçerli kabul edilir.

Alternatif olarak, yetkilendirme sunucusu belirtecin geçerli olup olmadığını belirtmek için "etkin" alanı içermiyorsa, geçerli bir belirteçte hangi özelliklerin ayarlandığını belirlemek için Postman gibi bir araç kullanın. Örneğin, geçerli bir belirteç yanıtı "expires_in" adlı bir özellik içeriyorsa, yetkilendirme sunucusu yanıtında bu özellik adının şu şekilde var olup olmadığını denetleyin:

<when condition="@(((IResponse)context.Variables["tokenstate"]).Body.As<JObject>().Property("expires_in") == null)">

Raporlama hatası

Belirtecin geçersiz olup olmadığını algılamak ve varsa 401 yanıtı döndürmek için bir ilke kullanabilirsiniz <choose> .

<choose>
  <when condition="@((bool)((IResponse)context.Variables["tokenstate"]).Body.As<JObject>()["active"] == false)">
    <return-response response-variable-name="existing response variable">
      <set-status code="401" reason="Unauthorized" />
      <set-header name="WWW-Authenticate" exists-action="override">
        <value>Bearer error="invalid_token"</value>
      </set-header>
    </return-response>
  </when>
</choose>

Belirteçlerin nasıl bearer kullanılması gerektiğini açıklayan RFC 6750'ye göre API Management, 401 yanıtını içeren bir WWW-Authenticate üst bilgi de döndürür. WWW-Authenticate, bir istemciye doğru yetkilendirilmiş istek oluşturma hakkında bilgi vermek için tasarlanmıştır. OAuth2 çerçevesiyle mümkün olan çok çeşitli yaklaşımlar nedeniyle, gerekli tüm bilgileri iletmek zordur. Neyse ki istemcilerin bir kaynak sunucusuna yönelik istekleri düzgün bir şekilde yetkilendirmesini keşfetmesine yardımcı olmak için çalışmalar devam ediyor.

Son çözüm

Sonunda aşağıdaki ilkeyi alırsınız:

<inbound>
  <!-- Extract Token from Authorization header parameter -->
  <set-variable name="token" value="@(context.Request.Headers.GetValueOrDefault("Authorization","scheme param").Split(' ').Last())" />

  <!-- Send request to Token Server to validate token (see RFC 7662) -->
  <send-request mode="new" response-variable-name="tokenstate" timeout="20" ignore-error="true">
    <set-url>https://microsoft-apiappec990ad4c76641c6aea22f566efc5a4e.azurewebsites.net/introspection</set-url>
    <set-method>POST</set-method>
    <set-header name="Authorization" exists-action="override">
      <value>basic dXNlcm5hbWU6cGFzc3dvcmQ=</value>
    </set-header>
    <set-header name="Content-Type" exists-action="override">
      <value>application/x-www-form-urlencoded</value>
    </set-header>
    <set-body>@($"token={(string)context.Variables["token"]}")</set-body>
  </send-request>

  <choose>
    <!-- Check active property in response -->
    <when condition="@((bool)((IResponse)context.Variables["tokenstate"]).Body.As<JObject>()["active"] == false)">
      <!-- Return 401 Unauthorized with http-problem payload -->
      <return-response response-variable-name="existing response variable">
        <set-status code="401" reason="Unauthorized" />
        <set-header name="WWW-Authenticate" exists-action="override">
          <value>Bearer error="invalid_token"</value>
        </set-header>
      </return-response>
    </when>
  </choose>
  <base />
</inbound>

Bu, ilkenin send-request yararlı dış hizmetleri API Management hizmeti aracılığıyla akan istekler ve yanıtlar süreciyle tümleştirmek için nasıl kullanılabileceğini gösteren birçok örnekten yalnızca biridir.

Yanıt Oluşturma

İlke send-request , önceki örnekte gördüğünüz gibi bir arka uç sistemine yönelik birincil isteği geliştirmek için kullanılabilir veya arka uç çağrısının tam yerine kullanılabilir. Bu tekniği kullanarak, birden çok farklı sistemden toplanan bileşik kaynakları kolayca oluşturabilirsiniz.

Pano oluşturma

Bazen birden çok arka uç sisteminde bulunan bilgileri (örneğin, bir panoyu yönlendirmek için) kullanıma sunmanız gerekir. KPI'ler tüm farklı arka uçlardan gelir, ancak bunlara doğrudan erişim sağlamayı tercih etmek istemezsiniz ve tüm bilgiler tek bir istekte alınabiliyorsa iyi olur. Belki de arka uç bilgilerinden bazılarının önce dilimleme ve dizinleme ve biraz temizlemeye ihtiyacı vardır! Bu bileşik kaynağı önbelleğe alabilmek, kullanıcıların düşük performans gösteren ölçümlerinin değişip değişmeyeceğini görmek için F5 anahtarını çekiçleme alışkanlığına sahip olduğunu bildiğiniz için arka uç yükünü azaltmak için yararlı olabilir.

Kaynakta numara oluşturma

Pano kaynağını oluşturmanın ilk adımı, Azure portalında yeni bir işlem yapılandırmaktır. Bu, dinamik kaynağı derlemek için bir oluşturma ilkesi yapılandırmak için kullanılan bir yer tutucu işlemidir.

Pano işlemi

İstekleri yapma

İşlem oluşturulduktan sonra, özellikle bu işlem için bir ilke yapılandırabilirsiniz.

İlke kapsamı ekranını gösteren ekran görüntüsü.

İlk adım, gelen istekten tüm sorgu parametrelerini ayıklamaktır, böylece bunları arka uçtan iletebilirsiniz. Bu örnekte pano, belirli bir süreye göre bilgileri gösterir ve bu nedenle ve fromDatetoDate parametresine sahiptir. İstek URL'sinden set-variable bilgileri ayıklamak için ilkeyi kullanabilirsiniz.

<set-variable name="fromDate" value="@(context.Request.Url.Query["fromDate"].Last())">
<set-variable name="toDate" value="@(context.Request.Url.Query["toDate"].Last())">

Bu bilgilere sahip olduktan sonra tüm arka uç sistemlerine istekte bulunabilirsiniz. Her istek, parametre bilgileriyle yeni bir URL oluşturur ve ilgili sunucusunu çağırır ve yanıtı bir bağlam değişkeninde depolar.

<send-request mode="new" response-variable-name="revenuedata" timeout="20" ignore-error="true">
  <set-url>@($"https://accounting.acme.com/salesdata?from={(string)context.Variables["fromDate"]}&to={(string)context.Variables["fromDate"]}")</set-url>
  <set-method>GET</set-method>
</send-request>

<send-request mode="new" response-variable-name="materialdata" timeout="20" ignore-error="true">
  <set-url>@($"https://inventory.acme.com/materiallevels?from={(string)context.Variables["fromDate"]}&to={(string)context.Variables["fromDate"]}")</set-url>
  <set-method>GET</set-method>
</send-request>

<send-request mode="new" response-variable-name="throughputdata" timeout="20" ignore-error="true">
  <set-url>@($"https://production.acme.com/throughput?from={(string)context.Variables["fromDate"]}&to={(string)context.Variables["fromDate"]}")</set-url>
  <set-method>GET</set-method>
</send-request>

<send-request mode="new" response-variable-name="accidentdata" timeout="20" ignore-error="true">
  <set-url>@($"https://production.acme.com/accidentdata?from={(string)context.Variables["fromDate"]}&to={(string)context.Variables["fromDate"]}")</set-url>
  <set-method>GET</set-method>
</send-request>

API Management bu istekleri sırayla gönderir.

Yanıt

Bileşik yanıtı oluşturmak için return-response ilkesini kullanabilirsiniz. öğesi, set-body özellik olarak eklenmiş tüm bileşen gösterimleriyle yeni JObject bir ifade oluşturmak için bir ifade kullanabilir.

<return-response response-variable-name="existing response variable">
  <set-status code="200" reason="OK" />
  <set-header name="Content-Type" exists-action="override">
    <value>application/json</value>
  </set-header>
  <set-body>
    @(new JObject(new JProperty("revenuedata",((IResponse)context.Variables["revenuedata"]).Body.As<JObject>()),
                  new JProperty("materialdata",((IResponse)context.Variables["materialdata"]).Body.As<JObject>()),
                  new JProperty("throughputdata",((IResponse)context.Variables["throughputdata"]).Body.As<JObject>()),
                  new JProperty("accidentdata",((IResponse)context.Variables["accidentdata"]).Body.As<JObject>())
                  ).ToString())
  </set-body>
</return-response>

İlkenin tamamı aşağıdaki gibi görünür:

<policies>
  <inbound>
    <set-variable name="fromDate" value="@(context.Request.Url.Query["fromDate"].Last())">
    <set-variable name="toDate" value="@(context.Request.Url.Query["toDate"].Last())">

    <send-request mode="new" response-variable-name="revenuedata" timeout="20" ignore-error="true">
      <set-url>@($"https://accounting.acme.com/salesdata?from={(string)context.Variables["fromDate"]}&to={(string)context.Variables["fromDate"]}")"</set-url>
      <set-method>GET</set-method>
    </send-request>

    <send-request mode="new" response-variable-name="materialdata" timeout="20" ignore-error="true">
      <set-url>@($"https://inventory.acme.com/materiallevels?from={(string)context.Variables["fromDate"]}&to={(string)context.Variables["fromDate"]}")"</set-url>
      <set-method>GET</set-method>
    </send-request>

    <send-request mode="new" response-variable-name="throughputdata" timeout="20" ignore-error="true">
      <set-url>@($"https://production.acme.com/throughput?from={(string)context.Variables["fromDate"]}&to={(string)context.Variables["fromDate"]}")"</set-url>
      <set-method>GET</set-method>
    </send-request>

    <send-request mode="new" response-variable-name="accidentdata" timeout="20" ignore-error="true">
      <set-url>@($"https://production.acme.com/accidentdata?from={(string)context.Variables["fromDate"]}&to={(string)context.Variables["fromDate"]}")"</set-url>
      <set-method>GET</set-method>
    </send-request>

    <return-response response-variable-name="existing response variable">
      <set-status code="200" reason="OK" />
      <set-header name="Content-Type" exists-action="override">
        <value>application/json</value>
      </set-header>
      <set-body>
        @(new JObject(new JProperty("revenuedata",((IResponse)context.Variables["revenuedata"]).Body.As<JObject>()),
                      new JProperty("materialdata",((IResponse)context.Variables["materialdata"]).Body.As<JObject>()),
                      new JProperty("throughputdata",((IResponse)context.Variables["throughputdata"]).Body.As<JObject>()),
                      new JProperty("accidentdata",((IResponse)context.Variables["accidentdata"]).Body.As<JObject>())
        ).ToString())
      </set-body>
    </return-response>
  </inbound>
  <backend>
    <base />
  </backend>
  <outbound>
    <base />
  </outbound>
</policies>

Özet

Azure API Management hizmeti, HTTP trafiğine seçmeli olarak uygulanabilen esnek ilkeler sağlar ve arka uç hizmetlerinin bileşimini sağlar. API ağ geçidinizi uyarı işlevleri, doğrulama, doğrulama özellikleriyle geliştirmek veya birden çok arka uç hizmetini send-request temel alan yeni bileşik kaynaklar oluşturmak istediğinizde ve ilgili ilkeler birçok olasılık sunar.