問題点
Azure Functions で作成した関数アプリを Web API として Blazor から叩こうとしたがこのようなエラーが発生する。
Access to fetch at '<関数アプリのURL>' from origin '<実行元アドレス(localhost)>' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
どうやら、CORS ポリシー によって HTTP リクエストがブロックされているらしい。
普段からWeb開発をやらないので、こういったことへの知識は疎いなぁと痛感。(もしかするとWeb界隈では常識なのかもしれない)
やりたいこと
Blazor WebAssembly から Azure Functions を実行したいだけ。(ちなみに Blazor Server のほうは問題なく実行できる。)
解決策
Azure Functions の CORS 設定から、リクエスト元になるアドレスを追加する。Blazor のソースコードはいじる必要はなかった。
自分の場合は Azure Static Web Apps からリクエストを送る予定だったので、デプロイしてからの URL を入力した。
ちなみに、ローカルホストから実行したい場合はそのアドレスを追記すれば良いみたい。(グローバル IP かと思っていた。)
めでたく花火が打ち上がった。(ちなみに、この内容は執筆中の本に載せる予定)
正直、たったこれだけか...とは思った。Blazor のリクエストヘッダになにかを追記したりしないといけないものかと丸一日悩んだけど、理由は単純だった...。
試したこと
一応、色々やってみたこともメモ。
1. リファレンスに忠実に
とりあえず、リファレンスを読み漁った。
この中に クロスオリジン リソース共有 (CORS) というセクションがあるのだが、どうやら次のコードを貼り付けてくれとのこと。
app.UseCors(policy => policy.WithOrigins("http://localhost:5000", "https://localhost:5001") .AllowAnyMethod() .WithHeaders(HeaderNames.ContentType, HeaderNames.Authorization, "x-custom-header") .AllowCredentials());
だが、どこに貼り付ければいいのかわからず、もう一つのリファレンスへ。
ここに書かれている次のコードを見てみると、どう見ても Blazor Server 向けになっている。特にこのへんとか
一応試してみたが、そもそも UseCors()
メソッドがない。
なのでこの方法は断念。
2. NuGet パッケージからの追加
どうやら、HttpConfiguration クラスの EnableCors() メソッドを使う手があるらしい?とのことなので、とりあえずパッケージを追加。
Install-Package Microsoft.Extensions.Http -Version 6.0.0
Program.cs
に下記を追記。
HttpConfiguration configuration = new HttpConfiguration();
configuration.EnableCors();
Index.razor
の API を呼び出すメソッドに属性を追記。
@code { [EnableCors(origins: "https://localhost:7159", headers: "*", methods: "*")] async Task FireworksButton() { using (HttpClient client = new HttpClient()) { await client.GetAsync("<関数アプリの URL>"); } } }
しかし、実行結果は変わらなかったので断念。
3. HttpRequestMessage クラスの使用
次に、こんな記事を見つけた。
これによると、httpRequest.SetBrowserRequestMode(BrowserRequestMode.Cors)) をつけろということなので、Index.razor
を少し変更。Cors を NoCors にすることで、CORS を使わない宣言することができるようになるみたい。
@code { async Task FireworksButton() { HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "<関数アプリの URL>"); request.SetBrowserRequestMode(BrowserRequestMode.NoCors); using (HttpClient client = new HttpClient()) { await client.SendAsync(request); } } }
実行してみると、確かにエラーは出なくなったが、2回目以降が実行できない。もしかしたらレスポンス待ちになってしまっているのかもしれない。
ということでこれも断念。