BEACHSIDE BLOG

Azure と GitHub と C# が好きなエンジニアの個人メモ ( ・ㅂ・)و ̑̑

Swagger UI の相対パスをカスタマイズする ( ASP.NET Core, OpenAPI, Swashbuckle )

最近 OpenAPI ( Swagger ) を設定するのに Swashbuckle の使い方を書いてましたが、その流れで相対パスの変更方法をメモしておきます。

相対パスの変更には2つのポイントがあります。

  • Swagger UI の相対パス
  • swagger.json の相対パス

それぞれ見てきます。

ちなみに Swashbuckle.AspNetCore のバージョンは現時点で最新の v5.6.3 を使っています。

Swagger UI の相対パスを変更する

Swagger UI のデフォルトの相対パスは、/swagger ( /swagger/index.html ) になっています。
これを例えば api/docs に変更してみましょう。

私の個人的なケースを書いておくと、下図のように Azure の Web App に Web API をホストしてるんだけどその手前に Azure Front Door があり、Web API の routeing は /api/* になっています。つまーり /api/ 配下じゃないと Web API に routing されないので、今回の変更をするわけです。

f:id:beachside:20210127132112p:plain

Front Door の Routing rule を追加するって解決策もありますが今回だと Production 環境じゃ OpenAPI を公開しないので、DEV/Production といった環境で設定差が出るのは IaC を構築する上でもうざいので Swagger の path を変更します。

と余談なユースケースを書きましたが、設定はいたって簡単。
Startup.cs の ConfigureServices メソッド内の UseSwaggerUI に以下のように1行追加するだけです。

app.UseSwaggerUI(c =>
{
    c.RoutePrefix = "api/docs";  // この行を追加
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "AspnetCore50 Route Customize v1");
});

ローカルデバッグ時に Swagger UI を起動するように Properties >launchSettings.json を開いて launchUrlapi/docs に変えておきます。

デバッグすると想定通りの動作ですね。URL の相対パスが api/docs になってます。ちなみにローカルデバッグは kestrel で、あとは Web App にデプロイして動作確認済みです。

f:id:beachside:20210127133451p:plain

これが多分、多くの場合やりたいことですよね。

swagger.json の相対パスを変更する

Swagger UI を構成する元の swagger.json のパスは変えなくても問題ないケースがほとんどだと思いますが、前述で書いたFront Door の routing がある構成だとデフォルトのパス ( /swagger/v1/swagger.json) だと Web API に routing されません。

ということで、swagger.json のパスも変更します。

Startup.cs の ConfigureServices メソッド内で、以下のようにコメントをつけた2か所を変えるだけです。ちなみに {documentName} ってありますが、このままで大丈夫です。

// UserSwagger を以下のように変える
app.UseSwagger(c => c.RouteTemplate = "api/swagger/{documentName}/swagger.json");
app.UseSwaggerUI(c =>
{
    c.RoutePrefix = "api/docs";
    // SwaggerEndpoint の url を RouteTemplate の設定と同じにする
    c.SwaggerEndpoint("/api/swagger/v1/swagger.json", "AspnetCore50 Route Customize v1");
});

以下のドキュメントに書いてあるのですが、UseSwagger で RouteTemplate を設定するときは、{documentName} パラメーターは必須のようです。このパラメーターにはデフォルトだとバージョンが入ってくるようですねー 。

もちろん swagger.jsondocs.json とかに変えても大丈夫です。変えたければ、前述同様に2か所を変えましょう。

デバッグで実行するとこんな感じ。

f:id:beachside:20210127154637p:plain

コードサンプル

今回のサンプルコードの完成版はこちら:

トラブルシュート

私が遭遇したエラーの原因に戻づいて注意を書いておくと、

  • c.SwaggerEndpoint( の引数のパスには、先頭に / が必要です。ないとパスが変になってエラーになります。
  • UseSwagger(c => c.RouteTemplate にセットするパスは先頭に / があってもなくても大丈夫...。

ぐぬぬってお気持ちになりました。

参考