Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
BERLAKU UNTUK: Semua tingkatan manajemen API
Kebijakan yang tersedia di layanan Azure API Management dapat melakukan berbagai pekerjaan yang berguna berdasarkan murni pada permintaan masuk, respons keluar, dan informasi konfigurasi dasar. Namun, dapat berinteraksi dengan layanan eksternal dari kebijakan API Management membuka lebih banyak peluang.
Anda sebelumnya telah melihat cara berinteraksi dengan layanan Azure Event Hubs untuk pengelogan, pemantauan, dan analitik. Artikel ini menunjukkan kebijakan yang memungkinkan Anda berinteraksi dengan layanan berbasis HTTP eksternal apa pun. Kebijakan ini dapat digunakan untuk memicu peristiwa jarak jauh atau untuk mengambil informasi yang digunakan untuk memanipulasi permintaan dan respons asli dalam beberapa cara.
Send-One-Way-Request
Mungkin interaksi eksternal yang paling sederhana adalah gaya permintaan fire-and-forget yang memungkinkan layanan eksternal diberi tahu tentang beberapa jenis peristiwa penting. Kebijakan choose
alur kontrol dapat digunakan untuk mendeteksi segala jenis kondisi yang Anda minati. Jika kondisi terpenuhi, Anda dapat membuat permintaan HTTP eksternal menggunakan kebijakan send-one-way-request. Ini bisa menjadi permintaan ke sistem olahpesan seperti Hipchat atau Slack, atau API email seperti SendGrid atau MailChimp, atau untuk insiden dukungan penting seperti PagerDuty. Semua sistem olahpesan ini memiliki API HTTP sederhana yang dapat dipanggil.
Pemberitahuan dengan Slack
Contoh berikut menunjukkan cara mengirim pesan ke ruang obrolan Slack jika kode status respons HTTP lebih besar dari atau sama dengan 500. Kesalahan rentang 500 menunjukkan masalah dengan API backend yang tidak dapat diselesaikan sendiri oleh klien API. Biasanya membutuhkan semacam intervensi pada bagian API Management.
<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 memiliki konsep inbound webhook. Saat mengonfigurasi web hook masuk, Slack menghasilkan URL khusus, yang memungkinkan Anda melakukan permintaan POST sederhana dan meneruskan pesan ke saluran Slack. Isi JSON yang Anda buat didasarkan pada format yang ditentukan oleh Slack.
Apakah api dan lupa cukup baik?
Ada kompromi tertentu saat menggunakan gaya permintaan yang tidak memerlukan tindak lanjut. Jika karena alasan tertentu, permintaan gagal, maka kegagalan tidak akan dilaporkan. Dalam situasi khusus ini, kompleksitas memiliki sistem pelaporan kegagalan sekunder dan biaya performa tambahan untuk menunggu respons tidaklah diperlukan. Untuk skenario di mana penting untuk memeriksa respons, maka kebijakan permintaan kirim adalah opsi yang lebih baik.
Send-Request
Kebijakan ini send-request
memungkinkan penggunaan layanan eksternal untuk melakukan fungsi pemrosesan yang kompleks dan mengembalikan data ke layanan manajemen API yang dapat digunakan untuk pemrosesan kebijakan lebih lanjut.
Mengotorisasi token referensi
Fungsi utama API Management adalah melindungi sumber daya backend. Jika server otorisasi yang digunakan oleh API Anda membuat JWT sebagai bagian dari alur OAuth2-nya, seperti yang dilakukan Microsoft Entra ID , maka Anda dapat menggunakan validate-jwt
kebijakan atau validate-azure-ad-token
kebijakan untuk memverifikasi validitas token. Beberapa server otorisasi membuat apa yang disebut token referensi yang tidak dapat diverifikasi tanpa melakukan panggilan balik ke server otorisasi.
Introspeksi yang distandarisasi
Di masa lalu, belum ada cara standar untuk memverifikasi token referensi dengan server otorisasi. Namun RFC 7662 standar yang baru-baru ini diusulkan diterbitkan oleh IETF yang menentukan bagaimana server sumber daya dapat memverifikasi validitas token.
Menarik token
Langkah pertama adalah mengekstrak token dari header Otorisasi. Nilai header harus diformat dengan Bearer
skema otorisasi, spasi tunggal, lalu token otorisasi sesuai RFC 6750. Sayangnya ada kasus di mana skema otorisasi dihilangkan. Untuk memperhitungkan hal ini saat mengurai, API Management membagi nilai header pada spasi dan memilih string terakhir dari array string yang dikembalikan. Ini menyediakan solusi untuk header otorisasi yang diformat dengan buruk.
<set-variable name="token" value="@(context.Request.Headers.GetValueOrDefault("Authorization","scheme param").Split(' ').Last())" />
Membuat permintaan validasi
Setelah API Management memiliki token otorisasi, API Management dapat membuat permintaan untuk memvalidasi token. RFC 7662 menyebut proses ini introspeksi dan mengharuskan Anda mengirimkan formulir HTML ke sumber daya introspeksi. Formulir HTML setidaknya harus berisi pasangan kunci/nilai dengan kunci token
. Permintaan ke server otorisasi ini juga harus diautentikasi, untuk memastikan bahwa klien berbahaya tidak dapat menelusuri token yang valid.
<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>
Memeriksa respons
Atribut response-variable-name
digunakan untuk memberikan akses respons yang dikembalikan. Nama yang ditentukan dalam properti ini dapat digunakan sebagai kunci ke dalam context.Variables
kamus untuk mengakses IResponse
objek.
Dari objek respons, Anda dapat mengambil isi dan RFC 7622 memberi tahu API Management bahwa respons harus berupa objek JSON dan harus berisi setidaknya properti yang disebut active
yang merupakan nilai boolean. Ketika active
benar maka token dianggap valid.
Atau, jika server otorisasi tidak menyertakan bidang "aktif" untuk menunjukkan apakah token valid, gunakan alat klien HTTP seperti curl
untuk menentukan properti apa yang diatur dalam token yang valid. Misalnya, jika respons token yang valid berisi properti yang disebut "expires_in", periksa apakah nama properti ini ada di respons server otorisasi dengan cara ini:
<when condition="@(((IResponse)context.Variables["tokenstate"]).Body.As<JObject>().Property("expires_in") == null)">
Kegagalan pelaporan
Anda dapat menggunakan <choose>
kebijakan untuk mendeteksi apakah token tidak valid dan jika demikian, kembalikan respons 401.
<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>
Sesuai RFC 6750 yang menjelaskan bagaimana bearer
token harus digunakan, API Management juga mengembalikan WWW-Authenticate
header dengan respons 401. WWW-Authenticate dimaksudkan untuk menginstruksikan klien tentang cara membuat permintaan yang diotorisasi dengan benar. Karena berbagai pendekatan yang mungkin dilakukan dengan kerangka kerja OAuth2, sulit untuk mengomunikasikan semua informasi yang diperlukan. Untungnya ada upaya yang sedang dilakukan untuk membantu klien menemukan cara mengotorisasi permintaan dengan benar ke server sumber daya.
Solusi akhir
Pada akhirnya, Anda mendapatkan kebijakan berikut:
<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>
Ini hanya salah satu dari banyak contoh bagaimana send-request
kebijakan dapat digunakan untuk mengintegrasikan layanan eksternal yang berguna ke dalam proses permintaan dan respons yang mengalir melalui layanan API Management.
Komposisi Respons
Kebijakan send-request
dapat digunakan untuk meningkatkan permintaan utama ke sistem backend, seperti yang Anda lihat dalam contoh sebelumnya, atau dapat digunakan sebagai pengganti lengkap untuk panggilan backend. Menggunakan teknik ini Anda dapat dengan mudah membuat sumber daya komposit yang dikumpulkan dari beberapa sistem yang berbeda.
Membangun dasbor
Terkadang Anda ingin bisa mengekspos informasi yang ada di beberapa sistem backend, misalnya, untuk mengoperasikan dasbor. KPI berasal dari semua back-end yang berbeda, tetapi Anda lebih suka tidak memberikan akses langsung kepada mereka dan akan lebih baik jika semua informasi dapat diambil dalam satu permintaan. Mungkin beberapa informasi data backend perlu diolah dan dibersihkan terlebih dahulu! Kemampuan untuk menyimpan sumber daya komposit tersebut akan berguna untuk mengurangi beban backend karena Anda tahu pengguna memiliki kebiasaan memencet tombol F5 berulang kali untuk melihat apakah metrik yang kurang memadai mungkin berubah.
Memalsukan sumber daya
Langkah pertama untuk membangun sumber daya dasbor adalah mengonfigurasi operasi baru di portal Microsoft Azure. Ini adalah operasi sementara yang digunakan untuk mengonfigurasi kebijakan komposisi untuk membangun sumber daya yang dinamis.
Membuat permintaan
Setelah operasi dibuat, Anda dapat mengonfigurasi kebijakan khusus untuk operasi tersebut.
Langkah pertama adalah mengekstrak parameter kueri apa pun dari permintaan masuk, sehingga Anda dapat meneruskannya ke backend. Dalam contoh ini, dasbor menampilkan informasi berdasarkan periode waktu dan karenanya memiliki fromDate
parameter dan toDate
. Anda dapat menggunakan set-variable
kebijakan untuk mengekstrak informasi dari URL permintaan.
<set-variable name="fromDate" value="@(context.Request.Url.Query["fromDate"].Last())">
<set-variable name="toDate" value="@(context.Request.Url.Query["toDate"].Last())">
Setelah Anda memiliki informasi ini, Anda dapat membuat permintaan ke semua sistem backend. Setiap permintaan membuat URL baru dengan informasi parameter dan memanggil server masing-masing dan menyimpan respons dalam variabel konteks.
<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 akan mengirim permintaan ini secara berurutan.
Merespons
Untuk membangun respons komposit, Anda dapat menggunakan kebijakan respons pengembalian . Elemen set-body
dapat menggunakan ekspresi untuk membangun yang baru JObject
dengan semua representasi komponen yang disematkan sebagai properti.
<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>
Kebijakan lengkap terlihat sebagai berikut:
<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>
Ringkasan
Layanan Azure API Management menyediakan kebijakan fleksibel yang dapat diterapkan secara selektif pada lalu lintas HTTP dan memungkinkan komposisi layanan backend. Apakah Anda ingin meningkatkan gateway API Anda dengan fungsi pemberitahuan, verifikasi, kemampuan validasi, atau membuat sumber daya komposit baru berdasarkan beberapa layanan backend, send-request
dan kebijakan terkait membuka dunia kemungkinan.