はじめに
Azure API Management(以下APIM)を利用したシステム開発中に、かなりハマった事象がありました。
ある日 Developer Portal を公開した後、以前までは成功していたAPIリクエストが以下のような挙動を取るようになりました。
- GETは成功する
- PUT/POSTは失敗するが、レスポンスコードは200が返る
最終的には APIM の CORS 設定が原因 だったのですが、原因に辿り着くまでかなり時間がかかったので備忘録として残しておきます。
簡単な構成図
発生した事象
するとその後、WEBアプリからAPIを実行すると以下のような挙動をするようになりました。
GETは正常
まずはApplication Insights のトレースを確認。
バックエンドのAPIサーバーに到達していることが分かります。
PUT/POSTは異常
一方 PUT/POST は Backend が呼び出されていません。
しかしレスポンスは 200 OKで返されていることが分かります。
最初に行った調査
Operation設定を疑う
まず Operation のパス定義を疑いました。
しかし設定を確認しても問題なし。
さらに試しに API 定義自体を削除してみました。
その状態でPOSTしても 200が返る という状況は変わりませんでした。
元々何も変更していないので原因ではないと思っていましたが、API定義自体を削除しても200が返るのは予想外です。
Policyを疑う
次に Policy を疑いました。
しかし API の設定を削除しても同じ挙動だったため、API単位の設定ではないように見えました。
APIM自体を疑う
さらに切り分けのため、新しいAPIMを立てて試験しました。
すると、PUT/POSTともに正常に実行できました。
一時的な結論
当時は原因が分かりませんでした。
最終的に APIM を作り直したところ PUT/POST が通るようになったため、変更点として以下だけをメモしていました。
- Developer Portalを公開していた
- Platform Versionをst1→st2へ変更していた
この時点ではDeveloper Portalが怪しいくらいしか分かっていませんでした。
後日、原因が判明
ある日、時間があったので改めて古いAPIMでAPIの設定を確認しようとしたところ、間違って All APIs という場所をクリックしてしまいました。
今まで気づいてなかったのですが、全てのAPIに対してポリシーなどの制御が追加できる設定箇所です。
するとそこに設定した覚えのない cors の文字が…
内容を確認してみます。
...
...
...
...
これだぁぁぁぁぁ!!!
真因
APIMは通常のAPIのゲートウェイとは別に、開発者ポータル用のURLが設定されています。
今回は開発者ポータルのURLのみCORSが許可されていて、通常のゲートウェイURLが許可されておらず挙動がおかしくなっていたというオチです。
しかもこのCORSポリシー、CORSエラーになった場合のレスポンスがデフォルトで200 OKを返すようになっています。(なんで403とかにしないんだろう?)

ちなみに今はデフォルトが falseになっています。
https://learn.microsoft.com/ja-jp/azure/api-management/cors-policy#attributes
なぜGETだけ正常動作していたのか
冒頭の構成図にある通り、このシステムはApplicationGatewayを介しているため、クライアントもAPIも同一ドメインです。
同一ドメインの場合、GETやHEADリクエストはOriginヘッダーが付与されません。
https://developer.mozilla.org/ja/docs/Web/HTTP/Reference/Headers/Origin
そのためGETのみ正常で、POST/PUTの挙動がおかしくなっていました。(Originヘッダーが無ければリクエストが通るというのも少し違和感がありますが)
CORSポリシーはいつ設定された?
ここで疑問が残ります。
一体いつCORSポリシーが設定されたのか。
もちろん私ではないですし、APIMは構成中だったので他のメンバーが追加することはない。
腑におちないまま改めて概要ページを確認してみると...
...
有効にしている
つまり、有効にする前の文言を理解せずになんとなく有効にしとくか、ぐらいで私が自分で有効にした可能性が大です。(全く覚えがない)
ちなみに改めてAPIMを初期状態にして「CORSを有効にする」ボタンを押下してみると、以下のようなダイアログが表示されました。
めっちゃ書いてるやん(全く覚えがない)
解決方法
利用元アプリケーションの Origin を追加しました。
<allowed-origins>
<origin>https://xxx.developer.azure-api.net</origin>
<origin>https://{AGWのドメイン}</origin> <!-- これを追加 -->
</allowed-origins>
これにより、GET/PUT/POSTすべてのリクエストが正常に Backend まで到達するようになりました。
まとめ
理解しないまま設定を変更するのはやめましょう









