ASP.NET Core の URL リライト ミドルウェア
Note
これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 9 バージョンを参照してください。
警告
このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、「.NET および .NET Core サポート ポリシー」を参照してください。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
重要
この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。
現在のリリースについては、この記事の .NET 9 バージョンを参照してください。
作成者: Kirk Larkin、Rick Anderson
この記事では、ASP.NET Core アプリの URL リライト ミドルウェアを使用して URL を書き換える手順について説明します。
URL の書き換えは、1 つまたは複数の事前定義された規則に基づいて URL 要求を変更する操作です。 URL 書き換えは、リソースの場所とそれらのアドレスの間の抽象化を作成し、場所とアドレスが緊密にリンクされていないようにします。 URL 書き換えは複数のシナリオで使用できます。
- サーバー リソースを一時的または永続的に移動するか置き換えて、リソースに対する安定したロケーターを維持します。
- 要求処理を異なる複数のアプリまたは 1 つのアプリの複数の区分に分割します。
- 受信した要求の URL セグメントを削除、追加、または再編成します。
- 検索エンジン最適化 (SEO) のためにパブリック URL を最適化します。
- ビジターがリソースの要求から返される内容を予測しやすいように、フレンドリなパブリック URL の使用を許可します。
- セキュリティで保護されていない要求をセキュリティで保護されたエンドポイントにリダイレクトします。
- 外部サイトが別のサイトでホストされている静的資産を独自のコンテンツにリンクすることによってその資産を使用するホットリンクを防止します。
"URL の書き換えによってアプリのパフォーマンスが低下することがあります"。 ルールの複雑さと数を制限します。
URL リダイレクトと URL 書き換え
"URL リダイレクト" と "URL 書き換え" では表現上はあまり違いがないように見えますが、クライアントへのリソースの提供に関しては重要な意味を持っています。 ASP.NET Core の URL リライト ミドルウェアは、両方のニーズを満たすことができます。
"URL リダイレクト" にはクライアント側の操作が関係しており、クライアントはもともと要求したものとは異なるアドレスにあるリソースにアクセスするよう指示されます。 これによりサーバーへのラウンドトリップが必要になります。 クライアントが、リソースの新しい要求を実行するときに、クライアントに返されたリダイレクト URL がブラウザーのアドレス バーに表示されます。
/resource
が /different-resource
に "リダイレクトされる" 場合、サーバーからの応答では、クライアントが /different-resource
にあるリソースを取得する必要があることと、リダイレクトが一時的または永続的のどちらかを示す状態コードが示されます。
要求を別の URL にリダイレクトする場合は、応答で状態コードを指定することにより、リダイレクトが永続的か一時的かのどちらかを示します。
301 - Moved Permanently
状態コードは、リソースに新しい永続的な URL があり、リソースに対する将来のすべての要求で新しい URL を使用する必要がある場合に使用します。 "301 状態コードを受信すると、クライアントは応答をキャッシュに入れて再利用することができます。 ""
302 - Found
" 状態コードは、リダイレクトが一時的である場合、または一般に変更される可能性がある場合に使用されます。 302 状態コードは、URL を保存して後で再利用しないようクライアントに指示します。
状態コードについて詳しくは、RFC 9110: 状態コードの定義に関するページを参照してください。
"URL 書き換え" はサーバー側の操作であり、クライアントが要求したものとは異なるリソース アドレスからリソースが提供されます。 URL 書き換えでは、サーバーへのラウンドトリップは必要ありません。 書き換えられた URL は、クライアントに返されず、ブラウザーのアドレス バーに表示されません。
/resource
が /different-resource
に "書き換えられた" 場合、サーバーは /different-resource
にあるリソースを "内部的に" 取得して返します。
クライアントは、書き換えられた URL にあるリソースを取得できる場合がありますが、クライアントは、その要求を実行して応答を受信したときに、書き換えられた URL にリソースが存在することは通知されません。
URL リライト サンプル アプリ
サンプル アプリを使用して、URL リライト ミドルウェアの機能を調べます。 そのアプリは、リダイレクトと書き換えのルールを適用し、複数のシナリオについて、リダイレクトされた URL または書き換えられた URL を表示します。
URL リライト ミドルウェアを使用する状況
以下の方法では要件が満たされない場合に、URL リライト ミドルウェアを使用します。
アプリが HTTP.sys サーバーでホストされている場合は、URL リライト ミドルウェアを使用します。
IIS、Apache、Nginx でサーバー ベースの URL 書き換えテクノロジが使用される主な理由は次のとおりです。
ミドルウェアでは、これらのモジュールの完全な機能がサポートされていません。
IIS 書き換えモジュールの
IsFile
制約やIsDirectory
制約など、サーバー モジュールの一部の機能は、ASP.NET Core プロジェクトでは動作しません。 これらのシナリオでは、代わりにミドルウェアを使用します。通常、ミドルウェアのパフォーマンスはモジュールより劣ります。
どちらのアプローチの方がパフォーマンスの低下が大きいか、またはパフォーマンスが低下した場合でもごくわずかかどうかを確実に知るには、ベンチマークが唯一の方法です。
拡張機能とオプション
各書き換えルールに対する拡張メソッドを含む RewriteOptions クラスのインスタンスを作成することにより、URL 書き換えとリダイレクトのルールを設定します。 "処理する順序で" 複数のルールを連結します。 UseRewriter によって URL リライト ミドルウェアが要求パイプラインに追加されると、RewriteOptions
が渡されます。
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
上記のコードでは、MethodRules
はユーザー定義クラスです。 詳細については、この記事の RewriteRules.cs
を参照してください。
非 WWW を WWW にリダイレクトする
アプリで非 www
の要求を www
にリダイレクトできる 3 つのオプションがあります。
AddRedirectToWwwPermanent:要求が非
www
の場合、要求をwww
サブドメインに永続的にリダイレクトします。 Status308PermanentRedirect 状態コードでリダイレクトします。AddRedirectToWww:受信した要求が非
www
の場合、要求をwww
サブドメインにリダイレクトします。 Status307TemporaryRedirect 状態コードでリダイレクトします。 オーバーロードにより、応答に対する状態コードを提供することができます。 状態コードの割り当てには、StatusCodes クラスのフィールドを使用します。
URL リダイレクト
要求をリダイレクトするには、AddRedirect を使用します。 最初のパラメーターには、着信 URL のパスに一致する .NET 正規表現 (Regex) が含まれています。 2 番目のパラメーターは、置換文字列です。 3 番目のパラメーター (存在する場合) は、状態コードを指定します。 状態コードを指定しない場合、状態コードは既定で "302 - 検出" に設定されます。これは、リソースが一時的に移動されるか置き換えられることを示します。
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
開発者ツールが有効になっているブラウザーで、パス /redirect-rule/1234/5678
を指定してサンプル アプリに対する要求を実行します。 正規表現が redirect-rule/(.*)
の要求のパスに一致し、パスが /redirected/1234/5678
に置き換えられます。 リダイレクト URL が、"302 - 検出" 状態コードでクライアントに返されます。 ブラウザーは、ブラウザーのアドレス バーに表示されるリダイレクト URL に新しい要求を実行します リダイレクト URL にはサンプル アプリに一致するルールがないため、次のようになります。
- 2 番目の要求は、アプリから 200 - OK 応答を受け取ります。
- 応答の本文では、リダイレクト URL が示されています。
URL が "リダイレクト" されるときに、サーバーへのラウンドトリップが実行されます。
警告
リダイレクト ルールを設定するときは注意してください。 リダイレクト ルールは、リダイレクト後を含めて、アプリへのすべての要求で評価されます。 "無限" リダイレクトのループが誤って作成されることがよくあります。
かっこ内に含まれる式の一部は、キャプチャ グループと呼ばれます。 式のドット (.
) は、どの文字とも一致することを意味します。 アスタリスク (*
) は、直前の文字に 0 回以上一致することを示します。 そのため、URL の最後の 2 つのパス セグメント 1234/5678
は、キャプチャ グループ (.*)
によってキャプチャされます。 要求 URL で redirect-rule/
の後に指定した任意の値が、この単一のキャプチャ グループによってキャプチャされます。
置換文字列では、キャプチャされたグループがドル記号 ($
) を使用して文字列に挿入され、その後にキャプチャのシーケンス番号が続きます。 最初のキャプチャ グループ値は、$1
で取得され、2 番目は $2
で取得され、これらは正規表現内のキャプチャ グループの順序で続行されます。 redirect-rule/(.*)
では、リダイレクト ルールの正規表現内に 1 つのキャプチャ グループだけがあるので、置換文字列に 1 つの挿入されたグループ ($1
) だけがあります。 ルールが適用されるときに、URL /redirected/1234/5678
になります。
ブラウザー ツールのネットワーク タブで /redirect-rule/1234/5678
を試してみてください。
セキュリティで保護されたエンドポイントへの URL リダイレクト
HTTP 要求を、同じホストとパスに HTTPS プロトコルを使用してリダイレクトするには、AddRedirectToHttps を使用します。 状態コードが指定されていない場合、ミドルウェアは既定で "302 - 検出" に設定します。 ポートが指定されていない場合は、次のようになります。
- ミドルウェアの既定値
null
に設定されます。 - スキームは
https
(HTTPS プロトコル) に変更されて、クライアントはポート 443 でリソースにアクセスします。
次の例では、状態コードを 301 - Moved Permanently
に設定し、ポートを localhost で Kestrel によって使用される HTTPS ポートに変更する方法を示します。 運用環境では、HTTPS ポートは null 値に設定されます。
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
int? localhostHTTPSport = null;
if (app.Environment.IsDevelopment())
{
localhostHTTPSport = Int32.Parse(Environment.GetEnvironmentVariable(
"ASPNETCORE_URLS")!.Split(new Char[] { ':', ';' })[2]);
}
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
// localhostHTTPport not needed for production, used only with localhost.
.AddRedirectToHttps(301, localhostHTTPSport)
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
セキュリティで保護されていない要求を、セキュリティで保護された HTTPS プロトコル (ポート 443) を使用して同じホストとパスにリダイレクトするには、AddRedirectToHttpsPermanent を使用します。 ミドルウェアによって状態コードが 301 - Moved Permanently
に設定されます。
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Note
リダイレクト規則を追加せずにセキュリティで保護されたエンドポイントにリダイレクトするときは、HTTPS リダイレクト ミドルウェアを使用することをお勧めします。 詳細については、HTTPS の適用に関するページをご覧ください。
サンプル アプリは、AddRedirectToHttps
または AddRedirectToHttpsPermanent
の使用方法が示されています。 http://redirect6.azurewebsites.net/iis-rules-rewrite/xyz
でアプリに対してセキュリティ保護されていない HTTP 要求を行います。 localhost を使用して HTTP から HTTPS へのリダイレクトをテストする場合:
- HTTPS URL とは異なるポートを持つ、HTTP URL を使用します。 HTTP URL は
Properties/launchSettings.json
ファイルにあります。 https://localhost/{port}
からs
を削除すると失敗します。localhost が HTTPS ポートに対する HTTP に応答しないためです。
次の図は、上記のコードを使用した http://redirect6.azurewebsites.net/iis-rules-rewrite/xyz
に対する要求の F12 ブラウザー ツールの図を示しています。
URL 書き換え
URL 書き換えのルールを作成するには、AddRewrite を使用します。 最初のパラメーターには、着信 URL のパスに一致する正規表現が含まれています。 2 番目のパラメーターは、置換文字列です。 3 番目のパラメーター skipRemainingRules: {true|false}
は、現在のルールが適用される場合に追加の書き換えルールをスキップするかどうかをミドルウェアに示します。
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
https://redirect6.azurewebsites.net/rewrite-rule/1234/5678
に対する要求を行ってみてください
式の先頭にあるキャレット (^
) は、URL パスの先頭からマッチングが開始されることを意味します。
前のリダイレクト ルール redirect-rule/(.*)
の例では、正規表現の先頭にキャレット (^
) がありません。 したがって、パスの redirect-rule/
の前にどのような文字があっても一致します。
パス | 一致したもの |
---|---|
/redirect-rule/1234/5678 |
はい |
/my-cool-redirect-rule/1234/5678 |
イエス |
/anotherredirect-rule/1234/5678 |
はい |
書き換えルール ^rewrite-rule/(\d+)/(\d+)
は、rewrite-rule/
で始まる場合のみパスと一致します。 次の表では、一致の違いに注意してください。
パス | 一致したもの |
---|---|
/rewrite-rule/1234/5678 |
はい |
/my-cool-rewrite-rule/1234/5678 |
いいえ |
/anotherrewrite-rule/1234/5678 |
いいえ |
式の ^rewrite-rule/
に続く部分に、2 つのキャプチャ グループ (\d+)/(\d+)
があります。 \d
は、1 桁 (数字) に一致することを示します。 プラス記号 (+
) は、直前の 1 つ以上の文字に一致することを意味します。 そのため、URL は、数字とその後に続くスラッシュ、さらにその後に続く別の数字を含んでいる必要があります。 これらのキャプチャ グループが $1
および $2
として書き換えられた URL に挿入されます。 書き換えルールの置換文字列は、クエリ文字列にキャプチャされたグループを配置します。 要求されたパス /rewrite-rule/1234/5678
は、/rewritten?var1=1234&var2=5678
でリソースを返すように書き換えられます。 クエリ文字列が元の要求に存在する場合、URL が書き換えられるときに保持されます。
リソースを返すためのサーバーへのラウンド トリップはありません。 リソースが存在する場合は、取得され、200 - OK 状態コードと共にクライアントに返されます。 クライアントはリダイレクトされていないため、ブラウザーのアドレス バーの URL は変更されません。 クライアントは、URL の書き換え操作がサーバーで発生したことを検出できません。
URL 書き換えとリダイレクトのパフォーマンスに関するヒント
最速の応答を実現するには:
- 一致する頻度が最も多いルールから一致頻度が最も少ないルールへの順番で書き換えルールを並べ替えます。
- 式内の照合ルールは計算量が多く、アプリの応答時間が長くなるので、可能な限り
skipRemainingRules: true
を使用します。 一致が発生し、追加の処理が必要ないときに残りのルールの処理をスキップします。
警告
悪意のあるユーザーがプロセスに高い負荷がかかる入力を RegularExpressions
に提供して、サービス拒否攻撃を引き起こす可能性があります。 RegularExpressions
を使用する ASP.NET Core フレームワーク API は、タイムアウトを渡します。 たとえば、RedirectRule クラスと RewriteRule クラスは、どちらも 1 秒のタイムアウトを渡します。
Apache mod_rewrite
AddApacheModRewrite を使用して Apache mod_rewrite ルールを適用します。 ルール ファイルがアプリと共に展開されていることを確認します。 mod_rewrite ルールの情報と例については、「Apache mod_rewrite」を参照してください。
ApacheModRewrite.txt ルール ファイルからルールを読み取るには、StreamReader を使用します。
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
サンプル アプリは、要求を /apache-mod-rules-redirect/(.\*)
から /redirected?id=$1
にリダイレクトします。 応答の状態コードは "302 -検出" です。
# Rewrite path with additional sub directory
RewriteRule ^/apache-mod-rules-redirect/(.*) /redirected?id=$1 [L,R=302]
https://redirect6.azurewebsites.net/apache-mod-rules-redirect/1234
に対する要求を行ってみてください
Apache ミドルウェアでは、次の Apache mod_rewrite サーバー変数がサポートされています。
- CONN_REMOTE_ADDR
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_FORWARDED
- HTTP_HOST
- HTTP_REFERER
- HTTP_USER_AGENT
- HTTPS
- IPV6
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_METHOD
- REQUEST_SCHEME
- REQUEST_URI
- SCRIPT_FILENAME
- SERVER_ADDR
- SERVER_PORT
- SERVER_PROTOCOL
- TIME
- TIME_DAY
- TIME_HOUR
- TIME_MIN
- TIME_MON
- TIME_SEC
- TIME_WDAY
- TIME_YEAR
IIS URL リライト モジュールのルール
IIS URL リライト モジュールに適用される同じルール セットを使用するには、AddIISUrlRewrite を使用します。 ルール ファイルがアプリと共に展開されていることを確認します。 Windows Server IIS で実行されているときにミドルウェアでアプリの web.config ファイルを使用するように指定しないでください。 IIS を使用する場合、IIS リライト モジュールとの競合を避けるため、これらのルールをアプリの web.config の外部に保存する必要があります。 IIS URL リライト モジュールのルールの詳細と例については、「Using Url Rewrite Module 2.0」(URL リライト モジュール 2.0 の使用 ) と「URL Rewrite Module Configuration Reference」(URL リライト モジュール構成リファレンス) を参照してください。
IISUrlRewrite.xml
ルール ファイルからルールを読み取るには、StreamReader を使用します。
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
サンプル アプリは、要求を /iis-rules-rewrite/(.*)
から /rewritten?id=$1
に書き換えます。 応答は、200 - OK 状態コードでクライアントに送信されます。
<rewrite>
<rules>
<rule name="Rewrite segment to id querystring" stopProcessing="true">
<match url="^iis-rules-rewrite/(.*)$" />
<action type="Rewrite" url="rewritten?id={R:1}" appendQueryString="false"/>
</rule>
</rules>
</rewrite>
https://redirect6.azurewebsites.net/iis-rules-rewrite/xyz
に対する要求を行ってみてください
アプリでサーバーレベルのルールを含むアクティブな IIS リライト モジュールが構成されていて、望ましくない方法でアプリに影響を与える場合:
- アプリの IIS リライト モジュールを無効にすることを検討してください。
- 詳細については、「Disabling IIS modules」 (IIS モジュールの無効化) を参照してください。
サポートされていない機能
ミドルウェアでは、次の IIS URL リライト モジュールの機能がサポートされていません。
- 送信ルール
- カスタム サーバー変数
- ワイルドカード
- LogRewrittenUrl
サポートされるサーバー変数
ミドルウェアでは、次の IIS URL リライト モジュール サーバー変数がサポートされています。
- CONTENT_LENGTH
- CONTENT_TYPE
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_HOST
- HTTP_REFERER
- HTTP_URL
- HTTP_USER_AGENT
- HTTPS
- LOCAL_ADDR
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_URI
IFileProvider は PhysicalFileProvider 経由で取得できます。 このアプローチにより、書き換えルール ファイルの場所に関する柔軟性が向上する場合があります。 書き換えルール ファイルが指定したパスでサーバーに展開されていることを確認してください。
var fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
メソッド ベースのルール
メソッド内でカスタム ルール ロジックを実装するには、Add を使用します。 Add
によって RewriteContext が公開され、リダイレクト メソッドで HttpContext を使用できるようになります。 RewriteContext.Result プロパティによって、追加のパイプライン処理の実行方法を決定します。 次の表で説明する RuleResult フィールドのいずれかに値を設定します。
コンテキストの書き換えの結果 | アクション |
---|---|
RuleResult.ContinueRules (既定値) |
ルールの適用を続けます。 |
RuleResult.EndResponse |
ルールの適用を停止し、応答を送信します。 |
RuleResult.SkipRemainingRules |
ルールの適用を停止し、次のミドルウェアにコンテキストを送信します。 |
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
サンプル アプリは、 .xml
で終了するパスの要求をリダイレクトするメソッドの例を示します。 /file.xml
に対して要求が行われるとき:
- 要求は
/xmlfiles/file.xml
にリダイレクトされます - 状態コードは
301 - Moved Permanently
に設定されます。 ブラウザーが/xmlfiles/file.xml
に対する新しい要求を行うと、静的ファイル ミドルウェアはクライアントに wwwroot/xmlfiles フォルダーからファイルを提供します。 リダイレクトの場合は、応答の状態コードを明示的に設定します。 それ以外の場合は、200 - OK 状態コードが返され、クライアントでのリダイレクトは発生しません。
RewriteRules.cs
:
public static void RedirectXmlFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because the client is redirecting back to the same app, stop
// processing if the request has already been redirected.
if (request.Path.StartsWithSegments(new PathString("/xmlfiles")) ||
request.Path.Value==null)
{
return;
}
if (request.Path.Value.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
"/xmlfiles" + request.Path + request.QueryString;
}
}
このアプローチでは、要求を書き換えることもできます。 サンプル アプリでは、wwwroot フォルダーから file.txt テキスト ファイルを提供するためにテキスト ファイル要求のパスを書き換える処理が示されています。 静的ファイル ミドルウェアでは、更新された要求パスに基づいてファイルが提供されます。
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
RewriteRules.cs
:
public static void RewriteTextFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
if (request.Path.Value != null &&
request.Path.Value.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.SkipRemainingRules;
request.Path = "/file.txt";
}
}
IRule ベースのルール
IRule インターフェイスを実装するクラス内のルール ロジックを使用するには、Add を使用します。 IRule
では、メソッド ベースのルール アプローチを使用する場合より高い柔軟性が提供されます。 実装クラスには、ApplyRule メソッドに対してパラメーターを渡すことができるコンストラクターを含めることができます。
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
サンプル アプリの extension
と newPath
のパラメーターの値は、いくつかの条件を満たすかチェックされます。 extension
は値を含んでいる必要があり、その値は .png
、.jpg
、または .gif
でなければなりません。 newPath
が有効ではない場合、ArgumentException がスローされます。 image.png
に対して要求が行われた場合、要求は /png-images/image.png
にリダイレクトされます。 image.jpg
に対して要求が行われた場合、要求は /jpg-images/image.jpg
にリダイレクトされます。 状態コードは 301 - Moved Permanently
に設定され、context.Result
はルールの処理を停止して応答を送信するように設定されます。
public class RedirectImageRequests : IRule
{
private readonly string _extension;
private readonly PathString _newPath;
public RedirectImageRequests(string extension, string newPath)
{
if (string.IsNullOrEmpty(extension))
{
throw new ArgumentException(nameof(extension));
}
if (!Regex.IsMatch(extension, @"^\.(png|jpg|gif)$"))
{
throw new ArgumentException("Invalid extension", nameof(extension));
}
if (!Regex.IsMatch(newPath, @"(/[A-Za-z0-9]+)+?"))
{
throw new ArgumentException("Invalid path", nameof(newPath));
}
_extension = extension;
_newPath = new PathString(newPath);
}
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because we're redirecting back to the same app, stop
// processing if the request has already been redirected
if (request.Path.StartsWithSegments(new PathString(_newPath)) ||
request.Path.Value == null)
{
return;
}
if (request.Path.Value.EndsWith(_extension, StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
_newPath + request.Path + request.QueryString;
}
}
}
次のメソッドを試してください。
- PNG 要求:
https://redirect6.azurewebsites.net/image.png
- JPG 要求:
https://redirect6.azurewebsites.net/image.jpg
正規表現の例
Goal | 正規表現文字列と 一致の例 |
置換文字列と 出力の例 |
---|---|---|
クエリ文字列内のパスを書き換える | ^path/(.*)/(.*) /path/abc/123 |
path?var1=$1&var2=$2 /path?var1=abc&var2=123 |
末尾のスラッシュを除去する | ^path2/(.*)/$ /path2/xyz/ |
$1 /path2/xyz |
末尾のスラッシュを強制する | ^path3/(.*[^/])$ /path3/xyz |
$1/ /path3/xyz/ |
特定の要求を書き換えを回避する | ^(.*)(?<!\.axd)$ または ^(?!.*\.axd$)(.*)$ はい: /path4/resource.htm いいえ: /path4/resource.axd |
rewritten/$1 /rewritten/resource.htm /resource.axd |
URL セグメントを再配置する | path5/(.*)/(.*)/(.*) path5/1/2/3 |
path5/$3/$2/$1 path5/3/2/1 |
URL セグメントを置き換える | ^path6/(.*)/segment2/(.*) ^path6/segment1/segment2/segment3 |
path6/$1/replaced/$2 /path6/segment1/replaced/segment3 |
上記の表のリンクでは、Azure にデプロイされた次のコードが使用されています。
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
// Rewrite path to QS.
.AddRewrite(@"^path/(.*)/(.*)", "path?var1=$1&var2=$2",
skipRemainingRules: true)
// Skip trailing slash.
.AddRewrite(@"^path2/(.*)/$", "path2/$1",
skipRemainingRules: true)
// Enforce trailing slash.
.AddRewrite(@"^path3/(.*[^/])$", "path3/$1/",
skipRemainingRules: true)
// Avoid rewriting specific requests.
.AddRewrite(@"^path4/(.*)(?<!\.axd)$", "rewritten/$1",
skipRemainingRules: true)
// Rearrange URL segments
.AddRewrite(@"^path5/(.*)/(.*)/(.*)", "path5/$3/$2/$1",
skipRemainingRules: true)
// Replace a URL segment
.AddRewrite(@"^path6/(.*)/segment2/(.*)", "path6/$1/replaced/$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
上記の正規表現サンプルのほとんどでは、リテラル path
を使って、デプロイされたサンプルに対する一意のテスト可能な書き換えルールを作成しています。 通常、正規表現には path
は含まれません。 たとえば、こちらの正規表現の例の表を参照してください。
このドキュメントでは、ASP.NET Core アプリの URL リライト ミドルウェアを使用して URL を書き換える手順について説明します。
URL の書き換えは、1 つまたは複数の事前定義された規則に基づいて URL 要求を変更する操作です。 URL 書き換えは、リソースの場所とそれらのアドレスの間の抽象化を作成し、場所とアドレスが緊密にリンクされていないようにします。 URL 書き換えは複数のシナリオで使用できます。
- サーバー リソースを一時的または永続的に移動するか置き換えて、リソースに対する安定したロケーターを維持します。
- 要求処理を異なる複数のアプリまたは 1 つのアプリの複数の区分に分割します。
- 受信した要求の URL セグメントを削除、追加、または再編成します。
- 検索エンジン最適化 (SEO) のためにパブリック URL を最適化します。
- ビジターがリソースの要求から返される内容を予測しやすいように、フレンドリなパブリック URL の使用を許可します。
- セキュリティで保護されていない要求をセキュリティで保護されたエンドポイントにリダイレクトします。
- 外部サイトが別のサイトでホストされている静的資産を独自のコンテンツにリンクすることによってその資産を使用するホットリンクを防止します。
Note
URL の書き換えによってアプリのパフォーマンスが低下することがあります。 可能であれば、ルールの複雑さと数を制限します。
サンプル コードを表示またはダウンロードします (ダウンロード方法)。
URL リダイレクトと URL 書き換え
"URL リダイレクト" と "URL 書き換え" では表現上はあまり違いがないように見えますが、クライアントへのリソースの提供に関しては重要な意味を持っています。 ASP.NET Core の URL リライト ミドルウェアは、両方のニーズを満たすことができます。
"URL リダイレクト" にはクライアント側の操作が関係しており、クライアントはもともと要求したものとは異なるアドレスにあるリソースにアクセスするよう指示されます。 これによりサーバーへのラウンドトリップが必要になります。 クライアントが、リソースの新しい要求を実行するときに、クライアントに返されたリダイレクト URL がブラウザーのアドレス バーに表示されます。
/resource
が /different-resource
に "リダイレクトされる" 場合、サーバーからの応答では、クライアントが /different-resource
にあるリソースを取得する必要があることと、リダイレクトが一時的または永続的のどちらかを示す状態コードが示されます。
要求を別の URL にリダイレクトする場合は、応答で状態コードを指定することにより、リダイレクトが永続的か一時的かのどちらかを示します。
301 - Moved Permanently
状態コードは、リソースに新しい永続的な URL があり、リソースに対する将来のすべての要求で新しい URL を使用する必要があることをクライアントに指示したい場合に使用します。 "301 状態コードを受信すると、クライアントは応答をキャッシュに入れて再利用することができます。 ""302 - 検出" 状態コードは、リダイレクトが一時的である場合、または一般に変更される可能性がある場合に使用されます。 302 状態コードは、URL を保存して後で再利用しないようクライアントに指示します。
状態コードについて詳しくは、RFC 9110: 状態コードの定義に関するページを参照してください。
"URL 書き換え" はサーバー側の操作であり、クライアントが要求したものとは異なるリソース アドレスからリソースが提供されます。 URL 書き換えでは、サーバーへのラウンドトリップは必要ありません。 書き換えられた URL は、クライアントに返されず、ブラウザーのアドレス バーに表示されません。
/resource
が /different-resource
に "書き換えられた" 場合、サーバーは /different-resource
にあるリソースを "内部的に" 取得して返します。
クライアントは、書き換えられた URL にあるリソースを取得できる場合がありますが、クライアントは、その要求を実行して応答を受信したときに、書き換えられた URL にリソースが存在することは通知されません。
URL リライト サンプル アプリ
サンプル アプリを使用して、URL リライト ミドルウェアの機能を調べることができます。 そのアプリは、リダイレクトと書き換えのルールを適用し、複数のシナリオについて、リダイレクトされた URL または書き換えられた URL を表示します。
URL リライト ミドルウェアを使用する状況
次の方法を使用できない場合は、URL リライト ミドルウェアを使用します。
アプリが HTTP.sys サーバーでホストされている場合は、URL リライト ミドルウェアを使用します。
IIS、Apache、Nginx でサーバー ベースの URL 書き換えテクノロジが使用される主な理由は次のとおりです。
ミドルウェアでは、これらのモジュールの完全な機能がサポートされていません。
IIS 書き換えモジュールの
IsFile
制約やIsDirectory
制約など、サーバー モジュールの一部の機能は、ASP.NET Core プロジェクトでは動作しません。 これらのシナリオでは、代わりにミドルウェアを使用します。通常、ミドルウェアのパフォーマンスはモジュールより劣ります。
どちらのアプローチの方がパフォーマンスの低下が大きいか、またはパフォーマンスが低下した場合でもごくわずかかどうかを確実に知るには、ベンチマークが唯一の方法です。
Package
URL リライト ミドルウェアは、Microsoft.AspNetCore.Rewrite パッケージによって提供されます。このパッケージは ASP.NET Core アプリに暗黙的に含まれています。
拡張機能とオプション
各書き換えルールに対する拡張メソッドを含む RewriteOptions クラスのインスタンスを作成することにより、URL 書き換えとリダイレクトのルールを設定します。 処理したい順序で複数のルールを連結します。 UseRewriter によって URL リライト ミドルウェアが要求パイプラインに追加されると、RewriteOptions
が渡されます。
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
非 WWW を WWW にリダイレクトする
アプリで非 www
の要求を www
にリダイレクトできる 3 つのオプションがあります。
AddRedirectToWwwPermanent:要求が非
www
の場合、要求をwww
サブドメインに永続的にリダイレクトします。 Status308PermanentRedirect 状態コードでリダイレクトします。AddRedirectToWww:受信した要求が非
www
の場合、要求をwww
サブドメインにリダイレクトします。 Status307TemporaryRedirect 状態コードでリダイレクトします。 オーバーロードにより、応答に対する状態コードを提供することができます。 状態コードの割り当てには、StatusCodes クラスのフィールドを使用します。
URL リダイレクト
要求をリダイレクトするには、AddRedirect を使用します。 最初のパラメーターには、着信 URL のパスに一致する正規表現が含まれています。 2 番目のパラメーターは、置換文字列です。 3 番目のパラメーター (存在する場合) は、状態コードを指定します。 状態コードを指定しない場合、状態コードは既定で "302 - 検出" に設定されます。これは、リソースが一時的に移動されるか置き換えられることを示します。
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
開発者ツールが有効になっているブラウザーで、パス /redirect-rule/1234/5678
を指定してサンプル アプリに対する要求を実行します。 正規表現が redirect-rule/(.*)
の要求のパスに一致し、パスが /redirected/1234/5678
に置き換えられます。 リダイレクト URL が、"302 - 検出" 状態コードでクライアントに返されます。 ブラウザーは、ブラウザーのアドレス バーに表示されるリダイレクト URL に新しい要求を実行します リダイレクト URL にはサンプル アプリに一致するルールがないため、次のようになります。
- 2 番目の要求は、アプリから 200 - OK 応答を受け取ります。
- 応答の本文では、リダイレクト URL が示されています。
URL が "リダイレクト" されるときに、サーバーへのラウンドトリップが実行されます。
警告
リダイレクト ルールを設定するときは注意してください。 リダイレクト ルールは、リダイレクト後を含めて、アプリへのすべての要求で評価されます。 "無限リダイレクトのループ" が誤って作成されることがよくあります。
元の要求: /redirect-rule/1234/5678
かっこ内に含まれる式の一部は、キャプチャ グループと呼ばれます。 式のドット (.
) は、どの文字とも一致することを意味します。 アスタリスク (*
) は、直前の文字に 0 回以上一致することを示します。 そのため、URL の最後の 2 つのパス セグメント 1234/5678
は、キャプチャ グループ (.*)
によってキャプチャされます。 要求 URL で redirect-rule/
の後に指定した任意の値が、この単一のキャプチャ グループによってキャプチャされます。
置換文字列では、キャプチャされたグループがドル記号 ($
) を使用して文字列に挿入され、その後にキャプチャのシーケンス番号が続きます。 最初のキャプチャ グループ値は、$1
で取得され、2 番目は $2
で取得され、これらは正規表現内のキャプチャ グループの順序で続行されます。 サンプル アプリでは、リダイレクト ルールの正規表現内に 1 つのキャプチャ グループだけがあるので、置換文字列に 1 つの挿入されたグループ ($1
) だけがあります。 ルールが適用されるときに、URL /redirected/1234/5678
になります。
セキュリティで保護されたエンドポイントへの URL リダイレクト
HTTP 要求を、同じホストとパスに HTTPS プロトコルを使用してリダイレクトするには、AddRedirectToHttps を使用します。 状態コードが指定されていない場合、ミドルウェアは既定で "302 - 検出" に設定します。 ポートが指定されていない場合は、次のようになります。
- ミドルウェアの既定値
null
に設定されます。 - スキームは
https
(HTTPS プロトコル) に変更されて、クライアントはポート 443 でリソースにアクセスします。
次の例では、状態コードを "301 - Moved Permanently
" に設定し、ポートを 5001 に変更する方法を示します。
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttps(301, 5001);
app.UseRewriter(options);
}
セキュリティで保護されていない要求を、セキュリティで保護された HTTPS プロトコル (ポート 443) を使用して同じホストとパスにリダイレクトするには、AddRedirectToHttpsPermanent を使用します。 ミドルウェアによって状態コードが 301 - Moved Permanently
に設定されます。
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent();
app.UseRewriter(options);
}
Note
リダイレクト規則を追加せずにセキュリティで保護されたエンドポイントにリダイレクトするときは、HTTPS リダイレクト ミドルウェアを使用することをお勧めします。 詳細については、「HTTPS の適用」のトピックをご覧ください。
サンプル アプリは、AddRedirectToHttps
または AddRedirectToHttpsPermanent
の使用方法の例を示すことができます。 拡張メソッドを RewriteOptions
に追加します。 任意の URL でセキュリティ保護されていない要求をアプリに対して行います。 自己署名証明書が信頼できないことを示すブラウザーのセキュリティ警告を消去するか、証明書を信頼する例外を作成します。
AddRedirectToHttps(301, 5001)
: http://localhost:5000/secure
を使用する元の要求
AddRedirectToHttpsPermanent
: http://localhost:5000/secure
を使用する元の要求
URL 書き換え
URL 書き換えのルールを作成するには、AddRewrite を使用します。 最初のパラメーターには、着信 URL のパスに一致する正規表現が含まれています。 2 番目のパラメーターは、置換文字列です。 3 番目のパラメーター skipRemainingRules: {true|false}
は、現在のルールが適用される場合に追加の書き換えルールをスキップするかどうかをミドルウェアに示します。
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
元の要求: /rewrite-rule/1234/5678
式の先頭にあるキャレット (^
) は、URL パスの先頭からマッチングが開始されることを意味します。
前のリダイレクト ルール redirect-rule/(.*)
の例では、正規表現の先頭にキャレット (^
) がありません。 したがって、パスの redirect-rule/
の前にどのような文字があっても一致します。
パス | 一致したもの |
---|---|
/redirect-rule/1234/5678 |
はい |
/my-cool-redirect-rule/1234/5678 |
イエス |
/anotherredirect-rule/1234/5678 |
はい |
書き換えルール ^rewrite-rule/(\d+)/(\d+)
は、rewrite-rule/
で始まる場合のみパスと一致します。 次の表では、一致の違いに注意してください。
パス | 一致したもの |
---|---|
/rewrite-rule/1234/5678 |
はい |
/my-cool-rewrite-rule/1234/5678 |
いいえ |
/anotherrewrite-rule/1234/5678 |
いいえ |
式の ^rewrite-rule/
に続く部分に、2 つのキャプチャ グループ (\d+)/(\d+)
があります。 \d
は、1 桁 (数字) に一致することを示します。 プラス記号 (+
) は、直前の 1 つ以上の文字に一致することを意味します。 そのため、URL は、数字とその後に続くスラッシュ、さらにその後に続く別の数字を含んでいる必要があります。 これらのキャプチャ グループが $1
および $2
として書き換えられた URL に挿入されます。 書き換えルールの置換文字列は、クエリ文字列にキャプチャされたグループを配置します。 /rewrite-rule/1234/5678
の要求されたパスは、/rewritten?var1=1234&var2=5678
でリソースを取得するように書き換えられます。 クエリ文字列が元の要求に存在する場合、URL が書き換えられるときに保持されます。
リソースを取得するためのサーバーへのラウンドトリップはありません。 リソースが存在する場合は、取得され、200 - OK 状態コードと共にクライアントに返されます。 クライアントはリダイレクトされていないため、ブラウザーのアドレス バーの URL は変更されません。 クライアントは、URL の書き換え操作がサーバーで発生したことを検出できません。
Note
式内の照合ルールは計算量が多く、アプリの応答時間が長くなるので、可能な限り skipRemainingRules: true
を使用します。 最も高速なアプリの応答を実現するには以下のようにします。
- 一致する頻度が最も多いルールから一致頻度が最も少ないルールへの順番で書き換えルールを並べ替えます。
- 一致が発生し、追加の処理が必要ないときに残りのルールの処理をスキップします。
Apache mod_rewrite
AddApacheModRewrite を使用して Apache mod_rewrite ルールを適用します。 ルール ファイルがアプリと共に展開されていることを確認します。 mod_rewrite ルールの情報と例については、「Apache mod_rewrite」を参照してください。
ApacheModRewrite.txt ルール ファイルからルールを読み取るには、StreamReader を使用します。
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
サンプル アプリは、要求を /apache-mod-rules-redirect/(.\*)
から /redirected?id=$1
にリダイレクトします。 応答の状態コードは "302 -検出" です。
# Rewrite path with additional sub directory
RewriteRule ^/apache-mod-rules-redirect/(.*) /redirected?id=$1 [L,R=302]
元の要求: /apache-mod-rules-redirect/1234
ミドルウェアは、次の Apache mod_rewrite サーバー変数をサポートします。
- CONN_REMOTE_ADDR
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_FORWARDED
- HTTP_HOST
- HTTP_REFERER
- HTTP_USER_AGENT
- HTTPS
- IPV6
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_METHOD
- REQUEST_SCHEME
- REQUEST_URI
- SCRIPT_FILENAME
- SERVER_ADDR
- SERVER_PORT
- SERVER_PROTOCOL
- TIME
- TIME_DAY
- TIME_HOUR
- TIME_MIN
- TIME_MON
- TIME_SEC
- TIME_WDAY
- TIME_YEAR
IIS URL リライト モジュールのルール
IIS URL リライト モジュールに適用される同じルール セットを使用するには、AddIISUrlRewrite を使用します。 ルール ファイルがアプリと共に展開されていることを確認します。 Windows Server IIS で実行されているときにミドルウェアでアプリの web.config ファイルを使用するように指定しないでください。 IIS を使用する場合、IIS リライト モジュールとの競合を避けるため、これらのルールをアプリの web.config の外部に保存する必要があります。 IIS URL リライト モジュールのルールの詳細と例については、「Using Url Rewrite Module 2.0」(URL リライト モジュール 2.0 の使用 ) と「URL Rewrite Module Configuration Reference」(URL リライト モジュール構成リファレンス) を参照してください。
IISUrlRewrite.xml
ルール ファイルからルールを読み取るには、StreamReader を使用します。
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
サンプル アプリは、要求を /iis-rules-rewrite/(.*)
から /rewritten?id=$1
に書き換えます。 応答は、200 - OK 状態コードでクライアントに送信されます。
<rewrite>
<rules>
<rule name="Rewrite segment to id querystring" stopProcessing="true">
<match url="^iis-rules-rewrite/(.*)$" />
<action type="Rewrite" url="rewritten?id={R:1}" appendQueryString="false"/>
</rule>
</rules>
</rewrite>
元の要求: /iis-rules-rewrite/1234
望ましくない方法でアプリに影響するように構成されたサーバー レベル ルールを使用するアクティブな IIS リライト モジュールがある場合は、アプリに対して IIS リライト モジュールを無効にできます。 詳細については、「Disabling IIS modules」 (IIS モジュールの無効化) を参照してください。
サポートされていない機能
ミドルウェアでは、次の IIS URL リライト モジュールの機能がサポートされていません。
- 送信ルール
- カスタム サーバー変数
- ワイルドカード
- LogRewrittenUrl
サポートされるサーバー変数
ミドルウェアは、次の IIS URL リライト モジュール サーバー変数をサポートします。
- CONTENT_LENGTH
- CONTENT_TYPE
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_HOST
- HTTP_REFERER
- HTTP_URL
- HTTP_USER_AGENT
- HTTPS
- LOCAL_ADDR
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_URI
Note
PhysicalFileProvider を介して IFileProvider を取得することもできます。 このアプローチは、書き換えルール ファイルの場所に関する大きな柔軟性を提供する場合があります。 書き換えルール ファイルを指定したパスでサーバーに導入されていることを確認してください。
PhysicalFileProvider fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
メソッド ベースのルール
メソッド内で独自のルール ロジックを実装するには、Add を使用します。 Add
は RewriteContext を公開し、メソッドで HttpContext を使用できるようにします。 RewriteContext.Result は、追加のパイプライン処理の実行方法を決定します。 次の表で説明する RuleResult フィールドのいずれかに値を設定します。
コンテキストの書き換えの結果 | アクション |
---|---|
RuleResult.ContinueRules (既定値) |
ルールの適用を続けます。 |
RuleResult.EndResponse |
ルールの適用を停止し、応答を送信します。 |
RuleResult.SkipRemainingRules |
ルールの適用を停止し、次のミドルウェアにコンテキストを送信します。 |
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
サンプル アプリは、 .xml
で終了するパスの要求をリダイレクトするメソッドの例を示します。 /file.xml
に対して要求が行われた場合、要求は /xmlfiles/file.xml
にリダイレクトされます。 状態コードは 301 - Moved Permanently
に設定されます。 ブラウザーが /xmlfiles/file.xml
に対する新しい要求を行うと、静的ファイル ミドルウェアはクライアントに wwwroot/xmlfiles フォルダーからファイルを提供します。 リダイレクトの場合は、応答の状態コードを明示的に設定します。 それ以外の場合は、200 - OK 状態コードが返され、クライアントでのリダイレクトは発生しません。
RewriteRules.cs
:
public static void RedirectXmlFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because the client is redirecting back to the same app, stop
// processing if the request has already been redirected.
if (request.Path.StartsWithSegments(new PathString("/xmlfiles")))
{
return;
}
if (request.Path.Value.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
"/xmlfiles" + request.Path + request.QueryString;
}
}
このアプローチでは、要求を書き換えることもできます。 サンプル アプリでは、wwwroot フォルダーから file.txt テキスト ファイルを提供するためにテキスト ファイル要求のパスを書き換える処理が示されています。 静的ファイル ミドルウェアでは、更新された要求パスに基づいてファイルが提供されます。
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
RewriteRules.cs
:
public static void RewriteTextFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
if (request.Path.Value.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.SkipRemainingRules;
request.Path = "/file.txt";
}
}
IRule ベースのルール
IRule インターフェイスを実装するクラス内のルール ロジックを使用するには、Add を使用します。 IRule
では、メソッド ベースのルール アプローチを使用する場合より高い柔軟性が提供されます。 実装クラスには、ApplyRule メソッドに対してパラメーターを渡すことができるコンストラクターを含めることができます。
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
サンプル アプリの extension
と newPath
のパラメーターの値は、いくつかの条件を満たすかチェックされます。 extension
は、値を含んでいる必要があり、値は .png
、.jpg
、または .gif でなければなりません。 newPath
が有効ではない場合、ArgumentException がスローされます。 image.png
に対して要求が行われた場合、要求は /png-images/image.png
にリダイレクトされます。 image.jpg
に対して要求が行われた場合、要求は /jpg-images/image.jpg
にリダイレクトされます。 状態コードは 301 - Moved Permanently
に設定され、context.Result
はルールの処理を停止して応答を送信するように設定されます。
public class RedirectImageRequests : IRule
{
private readonly string _extension;
private readonly PathString _newPath;
public RedirectImageRequests(string extension, string newPath)
{
if (string.IsNullOrEmpty(extension))
{
throw new ArgumentException(nameof(extension));
}
if (!Regex.IsMatch(extension, @"^\.(png|jpg|gif)$"))
{
throw new ArgumentException("Invalid extension", nameof(extension));
}
if (!Regex.IsMatch(newPath, @"(/[A-Za-z0-9]+)+?"))
{
throw new ArgumentException("Invalid path", nameof(newPath));
}
_extension = extension;
_newPath = new PathString(newPath);
}
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because we're redirecting back to the same app, stop
// processing if the request has already been redirected
if (request.Path.StartsWithSegments(new PathString(_newPath)))
{
return;
}
if (request.Path.Value.EndsWith(_extension, StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
_newPath + request.Path + request.QueryString;
}
}
}
元の要求: /image.png
元の要求: /image.jpg
正規表現の例
Goal | 正規表現文字列と 一致の例 |
置換文字列と 出力の例 |
---|---|---|
クエリ文字列内のパスを書き換える | ^path/(.*)/(.*) /path/abc/123 |
path?var1=$1&var2=$2 /path?var1=abc&var2=123 |
末尾のスラッシュを除去する | (.*)/$ /path/ |
$1 /path |
末尾のスラッシュを強制する | (.*[^/])$ /path |
$1/ /path/ |
特定の要求を書き換えを回避する | ^(.*)(?<!\.axd)$ または ^(?!.*\.axd$)(.*)$ はい: /resource.htm いいえ: /resource.axd |
rewritten/$1 /rewritten/resource.htm /resource.axd |
URL セグメントを再配置する | path/(.*)/(.*)/(.*) path/1/2/3 |
path/$3/$2/$1 path/3/2/1 |
URL セグメントを置き換える | ^(.*)/segment2/(.*) /segment1/segment2/segment3 |
$1/replaced/$2 /segment1/replaced/segment3 |
このドキュメントでは、ASP.NET Core アプリの URL リライト ミドルウェアを使用して URL を書き換える手順について説明します。
URL の書き換えは、1 つまたは複数の事前定義された規則に基づいて URL 要求を変更する操作です。 URL 書き換えは、リソースの場所とそれらのアドレスの間の抽象化を作成し、場所とアドレスが緊密にリンクされていないようにします。 URL 書き換えは複数のシナリオで使用できます。
- サーバー リソースを一時的または永続的に移動するか置き換えて、リソースに対する安定したロケーターを維持します。
- 要求処理を異なる複数のアプリまたは 1 つのアプリの複数の区分に分割します。
- 受信した要求の URL セグメントを削除、追加、または再編成します。
- 検索エンジン最適化 (SEO) のためにパブリック URL を最適化します。
- ビジターがリソースの要求から返される内容を予測しやすいように、フレンドリなパブリック URL の使用を許可します。
- セキュリティで保護されていない要求をセキュリティで保護されたエンドポイントにリダイレクトします。
- 外部サイトが別のサイトでホストされている静的資産を独自のコンテンツにリンクすることによってその資産を使用するホットリンクを防止します。
Note
URL の書き換えによってアプリのパフォーマンスが低下することがあります。 可能であれば、ルールの複雑さと数を制限します。
サンプル コードを表示またはダウンロードします (ダウンロード方法)。
URL リダイレクトと URL 書き換え
"URL リダイレクト" と "URL 書き換え" では表現上はあまり違いがないように見えますが、クライアントへのリソースの提供に関しては重要な意味を持っています。 ASP.NET Core の URL リライト ミドルウェアは、両方のニーズを満たすことができます。
"URL リダイレクト" にはクライアント側の操作が関係しており、クライアントはもともと要求したものとは異なるアドレスにあるリソースにアクセスするよう指示されます。 これによりサーバーへのラウンドトリップが必要になります。 クライアントが、リソースの新しい要求を実行するときに、クライアントに返されたリダイレクト URL がブラウザーのアドレス バーに表示されます。
/resource
が /different-resource
に "リダイレクトされる" 場合、サーバーからの応答では、クライアントが /different-resource
にあるリソースを取得する必要があることと、リダイレクトが一時的または永続的のどちらかを示す状態コードが示されます。
要求を別の URL にリダイレクトする場合は、応答で状態コードを指定することにより、リダイレクトが永続的か一時的かのどちらかを示します。
301 - Moved Permanently
状態コードは、リソースに新しい永続的な URL があり、リソースに対する将来のすべての要求で新しい URL を使用する必要があることをクライアントに指示したい場合に使用します。 "301 状態コードを受信すると、クライアントは応答をキャッシュに入れて再利用することができます。 ""302 - 検出" 状態コードは、リダイレクトが一時的である場合、または一般に変更される可能性がある場合に使用されます。 302 状態コードは、URL を保存して後で再利用しないようクライアントに指示します。
状態コードについて詳しくは、RFC 9110: 状態コードの定義に関するページを参照してください。
"URL 書き換え" はサーバー側の操作であり、クライアントが要求したものとは異なるリソース アドレスからリソースが提供されます。 URL 書き換えでは、サーバーへのラウンドトリップは必要ありません。 書き換えられた URL は、クライアントに返されず、ブラウザーのアドレス バーに表示されません。
/resource
が /different-resource
に "書き換えられた" 場合、サーバーは /different-resource
にあるリソースを "内部的に" 取得して返します。
クライアントは、書き換えられた URL にあるリソースを取得できる場合がありますが、クライアントは、その要求を実行して応答を受信したときに、書き換えられた URL にリソースが存在することは通知されません。
URL リライト サンプル アプリ
サンプル アプリを使用して、URL リライト ミドルウェアの機能を調べることができます。 そのアプリは、リダイレクトと書き換えのルールを適用し、複数のシナリオについて、リダイレクトされた URL または書き換えられた URL を表示します。
URL リライト ミドルウェアを使用する状況
次の方法を使用できない場合は、URL リライト ミドルウェアを使用します。
また、アプリが HTTP.sys サーバー (旧称 WebListener) でホストされているときも、ミドルウェアを使用します。
IIS、Apache、Nginx でサーバー ベースの URL 書き換えテクノロジが使用される主な理由は次のとおりです。
ミドルウェアでは、これらのモジュールの完全な機能がサポートされていません。
IIS 書き換えモジュールの
IsFile
制約やIsDirectory
制約など、サーバー モジュールの一部の機能は、ASP.NET Core プロジェクトでは動作しません。 これらのシナリオでは、代わりにミドルウェアを使用します。通常、ミドルウェアのパフォーマンスはモジュールより劣ります。
どちらのアプローチの方がパフォーマンスの低下が大きいか、またはパフォーマンスが低下した場合でもごくわずかかどうかを確実に知るには、ベンチマークが唯一の方法です。
Package
ミドルウェアをプロジェクトに組み込むには、Microsoft.AspNetCore.App メタパッケージへのパッケージ参照をプロジェクト ファイルに追加します。これには、Microsoft.AspNetCore.Rewrite パッケージが含まれます。
Microsoft.AspNetCore.App
メタパッケージを使用しない場合は、Microsoft.AspNetCore.Rewrite
パッケージへのプロジェクト参照を追加します。
拡張機能とオプション
各書き換えルールに対する拡張メソッドを含む RewriteOptions クラスのインスタンスを作成することにより、URL 書き換えとリダイレクトのルールを設定します。 処理したい順序で複数のルールを連結します。 UseRewriter によって URL リライト ミドルウェアが要求パイプラインに追加されると、RewriteOptions
が渡されます。
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
非 WWW を WWW にリダイレクトする
アプリで非 www
の要求を www
にリダイレクトできる 3 つのオプションがあります。
AddRedirectToWwwPermanent:要求が非
www
の場合、要求をwww
サブドメインに永続的にリダイレクトします。 Status308PermanentRedirect 状態コードでリダイレクトします。AddRedirectToWww:受信した要求が非
www
の場合、要求をwww
サブドメインにリダイレクトします。 Status307TemporaryRedirect 状態コードでリダイレクトします。 オーバーロードにより、応答に対する状態コードを提供することができます。 状態コードの割り当てには、StatusCodes クラスのフィールドを使用します。
URL リダイレクト
要求をリダイレクトするには、AddRedirect を使用します。 最初のパラメーターには、着信 URL のパスに一致する正規表現が含まれています。 2 番目のパラメーターは、置換文字列です。 3 番目のパラメーター (存在する場合) は、状態コードを指定します。 状態コードを指定しない場合、状態コードは既定で "302 - 検出" に設定されます。これは、リソースが一時的に移動されるか置き換えられることを示します。
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
開発者ツールが有効になっているブラウザーで、パス /redirect-rule/1234/5678
を指定してサンプル アプリに対する要求を実行します。 正規表現が redirect-rule/(.*)
の要求のパスに一致し、パスが /redirected/1234/5678
に置き換えられます。 リダイレクト URL が、"302 - 検出" 状態コードでクライアントに返されます。 ブラウザーは、ブラウザーのアドレス バーに表示されるリダイレクト URL に新しい要求を実行します リダイレクト URL にはサンプル アプリに一致するルールがないため、次のようになります。
- 2 番目の要求は、アプリから 200 - OK 応答を受け取ります。
- 応答の本文では、リダイレクト URL が示されています。
URL が "リダイレクト" されるときに、サーバーへのラウンドトリップが実行されます。
警告
リダイレクト ルールを設定するときは注意してください。 リダイレクト ルールは、リダイレクト後を含めて、アプリへのすべての要求で評価されます。 "無限リダイレクトのループ" が誤って作成されることがよくあります。
元の要求: /redirect-rule/1234/5678
かっこ内に含まれる式の一部は、キャプチャ グループと呼ばれます。 式のドット (.
) は、どの文字とも一致することを意味します。 アスタリスク (*
) は、直前の文字に 0 回以上一致することを示します。 そのため、URL の最後の 2 つのパス セグメント 1234/5678
は、キャプチャ グループ (.*)
によってキャプチャされます。 要求 URL で redirect-rule/
の後に指定した任意の値が、この単一のキャプチャ グループによってキャプチャされます。
置換文字列では、キャプチャされたグループがドル記号 ($
) を使用して文字列に挿入され、その後にキャプチャのシーケンス番号が続きます。 最初のキャプチャ グループ値は、$1
で取得され、2 番目は $2
で取得され、これらは正規表現内のキャプチャ グループの順序で続行されます。 サンプル アプリでは、リダイレクト ルールの正規表現内に 1 つのキャプチャ グループだけがあるので、置換文字列に 1 つの挿入されたグループ ($1
) だけがあります。 ルールが適用されるときに、URL /redirected/1234/5678
になります。
セキュリティで保護されたエンドポイントへの URL リダイレクト
HTTP 要求を、同じホストとパスに HTTPS プロトコルを使用してリダイレクトするには、AddRedirectToHttps を使用します。 状態コードが指定されていない場合、ミドルウェアは既定で "302 - 検出" に設定します。 ポートが指定されていない場合は、次のようになります。
- ミドルウェアの既定値
null
に設定されます。 - スキームは
https
(HTTPS プロトコル) に変更されて、クライアントはポート 443 でリソースにアクセスします。
次の例では、状態コードを "301 - Moved Permanently
" に設定し、ポートを 5001 に変更する方法を示します。
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttps(301, 5001);
app.UseRewriter(options);
}
セキュリティで保護されていない要求を、セキュリティで保護された HTTPS プロトコル (ポート 443) を使用して同じホストとパスにリダイレクトするには、AddRedirectToHttpsPermanent を使用します。 ミドルウェアによって状態コードが 301 - Moved Permanently
に設定されます。
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent();
app.UseRewriter(options);
}
Note
リダイレクト規則を追加せずにセキュリティで保護されたエンドポイントにリダイレクトするときは、HTTPS リダイレクト ミドルウェアを使用することをお勧めします。 詳細については、「HTTPS の適用」のトピックをご覧ください。
サンプル アプリは、AddRedirectToHttps
または AddRedirectToHttpsPermanent
の使用方法の例を示すことができます。 拡張メソッドを RewriteOptions
に追加します。 任意の URL でセキュリティ保護されていない要求をアプリに対して行います。 自己署名証明書が信頼できないことを示すブラウザーのセキュリティ警告を消去するか、証明書を信頼する例外を作成します。
AddRedirectToHttps(301, 5001)
: http://localhost:5000/secure
を使用する元の要求
AddRedirectToHttpsPermanent
: http://localhost:5000/secure
を使用する元の要求
URL 書き換え
URL 書き換えのルールを作成するには、AddRewrite を使用します。 最初のパラメーターには、着信 URL のパスに一致する正規表現が含まれています。 2 番目のパラメーターは、置換文字列です。 3 番目のパラメーター skipRemainingRules: {true|false}
は、現在のルールが適用される場合に追加の書き換えルールをスキップするかどうかをミドルウェアに示します。
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
元の要求: /rewrite-rule/1234/5678
式の先頭にあるキャレット (^
) は、URL パスの先頭からマッチングが開始されることを意味します。
前のリダイレクト ルール redirect-rule/(.*)
の例では、正規表現の先頭にキャレット (^
) がありません。 したがって、パスの redirect-rule/
の前にどのような文字があっても一致します。
パス | 一致したもの |
---|---|
/redirect-rule/1234/5678 |
はい |
/my-cool-redirect-rule/1234/5678 |
イエス |
/anotherredirect-rule/1234/5678 |
はい |
書き換えルール ^rewrite-rule/(\d+)/(\d+)
は、rewrite-rule/
で始まる場合のみパスと一致します。 次の表では、一致の違いに注意してください。
パス | 一致したもの |
---|---|
/rewrite-rule/1234/5678 |
はい |
/my-cool-rewrite-rule/1234/5678 |
いいえ |
/anotherrewrite-rule/1234/5678 |
いいえ |
式の ^rewrite-rule/
に続く部分に、2 つのキャプチャ グループ (\d+)/(\d+)
があります。 \d
は、1 桁 (数字) に一致することを示します。 プラス記号 (+
) は、直前の 1 つ以上の文字に一致することを意味します。 そのため、URL は、数字とその後に続くスラッシュ、さらにその後に続く別の数字を含んでいる必要があります。 これらのキャプチャ グループが $1
および $2
として書き換えられた URL に挿入されます。 書き換えルールの置換文字列は、クエリ文字列にキャプチャされたグループを配置します。 /rewrite-rule/1234/5678
の要求されたパスは、/rewritten?var1=1234&var2=5678
でリソースを取得するように書き換えられます。 クエリ文字列が元の要求に存在する場合、URL が書き換えられるときに保持されます。
リソースを取得するためのサーバーへのラウンドトリップはありません。 リソースが存在する場合は、取得され、200 - OK 状態コードと共にクライアントに返されます。 クライアントはリダイレクトされていないため、ブラウザーのアドレス バーの URL は変更されません。 クライアントは、URL の書き換え操作がサーバーで発生したことを検出できません。
Note
式内の照合ルールは計算量が多く、アプリの応答時間が長くなるので、可能な限り skipRemainingRules: true
を使用します。 最も高速なアプリの応答を実現するには以下のようにします。
- 一致する頻度が最も多いルールから一致頻度が最も少ないルールへの順番で書き換えルールを並べ替えます。
- 一致が発生し、追加の処理が必要ないときに残りのルールの処理をスキップします。
Apache mod_rewrite
AddApacheModRewrite を使用して Apache mod_rewrite ルールを適用します。 ルール ファイルがアプリと共に展開されていることを確認します。 mod_rewrite ルールの情報と例については、「Apache mod_rewrite」を参照してください。
ApacheModRewrite.txt ルール ファイルからルールを読み取るには、StreamReader を使用します。
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
サンプル アプリは、要求を /apache-mod-rules-redirect/(.\*)
から /redirected?id=$1
にリダイレクトします。 応答の状態コードは "302 -検出" です。
# Rewrite path with additional sub directory
RewriteRule ^/apache-mod-rules-redirect/(.*) /redirected?id=$1 [L,R=302]
元の要求: /apache-mod-rules-redirect/1234
ミドルウェアは、次の Apache mod_rewrite サーバー変数をサポートします。
- CONN_REMOTE_ADDR
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_FORWARDED
- HTTP_HOST
- HTTP_REFERER
- HTTP_USER_AGENT
- HTTPS
- IPV6
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_METHOD
- REQUEST_SCHEME
- REQUEST_URI
- SCRIPT_FILENAME
- SERVER_ADDR
- SERVER_PORT
- SERVER_PROTOCOL
- TIME
- TIME_DAY
- TIME_HOUR
- TIME_MIN
- TIME_MON
- TIME_SEC
- TIME_WDAY
- TIME_YEAR
IIS URL リライト モジュールのルール
IIS URL リライト モジュールに適用される同じルール セットを使用するには、AddIISUrlRewrite を使用します。 ルール ファイルがアプリと共に展開されていることを確認します。 Windows Server IIS で実行されているときにミドルウェアでアプリの web.config ファイルを使用するように指定しないでください。 IIS を使用する場合、IIS リライト モジュールとの競合を避けるため、これらのルールをアプリの web.config の外部に保存する必要があります。 IIS URL リライト モジュールのルールの詳細と例については、「Using Url Rewrite Module 2.0」(URL リライト モジュール 2.0 の使用 ) と「URL Rewrite Module Configuration Reference」(URL リライト モジュール構成リファレンス) を参照してください。
IISUrlRewrite.xml
ルール ファイルからルールを読み取るには、StreamReader を使用します。
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
サンプル アプリは、要求を /iis-rules-rewrite/(.*)
から /rewritten?id=$1
に書き換えます。 応答は、200 - OK 状態コードでクライアントに送信されます。
<rewrite>
<rules>
<rule name="Rewrite segment to id querystring" stopProcessing="true">
<match url="^iis-rules-rewrite/(.*)$" />
<action type="Rewrite" url="rewritten?id={R:1}" appendQueryString="false"/>
</rule>
</rules>
</rewrite>
元の要求: /iis-rules-rewrite/1234
望ましくない方法でアプリに影響するように構成されたサーバー レベル ルールを使用するアクティブな IIS リライト モジュールがある場合は、アプリに対して IIS リライト モジュールを無効にできます。 詳細については、「Disabling IIS modules」 (IIS モジュールの無効化) を参照してください。
サポートされていない機能
ASP.NET Core 2.x でリリースされたミドルウェアは、次の IIS URL リライト モジュールの機能をサポートしていません。
- 送信ルール
- カスタム サーバー変数
- ワイルドカード
- LogRewrittenUrl
サポートされるサーバー変数
ミドルウェアは、次の IIS URL リライト モジュール サーバー変数をサポートします。
- CONTENT_LENGTH
- CONTENT_TYPE
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_HOST
- HTTP_REFERER
- HTTP_URL
- HTTP_USER_AGENT
- HTTPS
- LOCAL_ADDR
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_URI
Note
PhysicalFileProvider を介して IFileProvider を取得することもできます。 このアプローチは、書き換えルール ファイルの場所に関する大きな柔軟性を提供する場合があります。 書き換えルール ファイルを指定したパスでサーバーに導入されていることを確認してください。
PhysicalFileProvider fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
メソッド ベースのルール
メソッド内で独自のルール ロジックを実装するには、Add を使用します。 Add
は RewriteContext を公開し、メソッドで HttpContext を使用できるようにします。 RewriteContext.Result は、追加のパイプライン処理の実行方法を決定します。 次の表で説明する RuleResult フィールドのいずれかに値を設定します。
コンテキストの書き換えの結果 | アクション |
---|---|
RuleResult.ContinueRules (既定値) |
ルールの適用を続けます。 |
RuleResult.EndResponse |
ルールの適用を停止し、応答を送信します。 |
RuleResult.SkipRemainingRules |
ルールの適用を停止し、次のミドルウェアにコンテキストを送信します。 |
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
サンプル アプリは、 .xml
で終了するパスの要求をリダイレクトするメソッドの例を示します。 /file.xml
に対して要求が行われた場合、要求は /xmlfiles/file.xml
にリダイレクトされます。 状態コードは 301 - Moved Permanently
に設定されます。 ブラウザーが /xmlfiles/file.xml
に対する新しい要求を行うと、静的ファイル ミドルウェアはクライアントに wwwroot/xmlfiles フォルダーからファイルを提供します。 リダイレクトの場合は、応答の状態コードを明示的に設定します。 それ以外の場合は、200 - OK 状態コードが返され、クライアントでのリダイレクトは発生しません。
RewriteRules.cs
:
public static void RedirectXmlFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because the client is redirecting back to the same app, stop
// processing if the request has already been redirected.
if (request.Path.StartsWithSegments(new PathString("/xmlfiles")))
{
return;
}
if (request.Path.Value.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
"/xmlfiles" + request.Path + request.QueryString;
}
}
このアプローチでは、要求を書き換えることもできます。 サンプル アプリでは、wwwroot フォルダーから file.txt テキスト ファイルを提供するためにテキスト ファイル要求のパスを書き換える処理が示されています。 静的ファイル ミドルウェアでは、更新された要求パスに基づいてファイルが提供されます。
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
RewriteRules.cs
:
public static void RewriteTextFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
if (request.Path.Value.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.SkipRemainingRules;
request.Path = "/file.txt";
}
}
IRule ベースのルール
IRule インターフェイスを実装するクラス内のルール ロジックを使用するには、Add を使用します。 IRule
では、メソッド ベースのルール アプローチを使用する場合より高い柔軟性が提供されます。 実装クラスには、ApplyRule メソッドに対してパラメーターを渡すことができるコンストラクターを含めることができます。
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
サンプル アプリの extension
と newPath
のパラメーターの値は、いくつかの条件を満たすかチェックされます。 extension
は、値を含んでいる必要があり、値は .png
、.jpg
、または .gif でなければなりません。 newPath
が有効ではない場合、ArgumentException がスローされます。 image.png
に対して要求が行われた場合、要求は /png-images/image.png
にリダイレクトされます。 image.jpg
に対して要求が行われた場合、要求は /jpg-images/image.jpg
にリダイレクトされます。 状態コードは 301 - Moved Permanently
に設定され、context.Result
はルールの処理を停止して応答を送信するように設定されます。
public class RedirectImageRequests : IRule
{
private readonly string _extension;
private readonly PathString _newPath;
public RedirectImageRequests(string extension, string newPath)
{
if (string.IsNullOrEmpty(extension))
{
throw new ArgumentException(nameof(extension));
}
if (!Regex.IsMatch(extension, @"^\.(png|jpg|gif)$"))
{
throw new ArgumentException("Invalid extension", nameof(extension));
}
if (!Regex.IsMatch(newPath, @"(/[A-Za-z0-9]+)+?"))
{
throw new ArgumentException("Invalid path", nameof(newPath));
}
_extension = extension;
_newPath = new PathString(newPath);
}
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because we're redirecting back to the same app, stop
// processing if the request has already been redirected
if (request.Path.StartsWithSegments(new PathString(_newPath)))
{
return;
}
if (request.Path.Value.EndsWith(_extension, StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
_newPath + request.Path + request.QueryString;
}
}
}
元の要求: /image.png
元の要求: /image.jpg
正規表現の例
Goal | 正規表現文字列と 一致の例 |
置換文字列と 出力の例 |
---|---|---|
クエリ文字列内のパスを書き換える | ^path/(.*)/(.*) /path/abc/123 |
path?var1=$1&var2=$2 /path?var1=abc&var2=123 |
末尾のスラッシュを除去する | (.*)/$ /path/ |
$1 /path |
末尾のスラッシュを強制する | (.*[^/])$ /path |
$1/ /path/ |
特定の要求を書き換えを回避する | ^(.*)(?<!\.axd)$ または ^(?!.*\.axd$)(.*)$ はい: /resource.htm いいえ: /resource.axd |
rewritten/$1 /rewritten/resource.htm /resource.axd |
URL セグメントを再配置する | path/(.*)/(.*)/(.*) path/1/2/3 |
path/$3/$2/$1 path/3/2/1 |
URL セグメントを置き換える | ^(.*)/segment2/(.*) /segment1/segment2/segment3 |
$1/replaced/$2 /segment1/replaced/segment3 |
その他の技術情報
ASP.NET Core