ASP.NET Core の URL リライト ミドルウェアURL Rewriting Middleware in ASP.NET Core

作成者: Mikael MengistuBy Mikael Mengistu

このドキュメントでは、ASP.NET Core アプリの URL リライト ミドルウェアを使用して URL を書き換える手順について説明します。This document introduces URL rewriting with instructions on how to use URL Rewriting Middleware in ASP.NET Core apps.

URL の書き換えは、1 つまたは複数の事前定義された規則に基づいて URL 要求を変更する操作です。URL rewriting is the act of modifying request URLs based on one or more predefined rules. URL 書き換えは、リソースの場所とそれらのアドレスの間の抽象化を作成し、場所とアドレスが緊密にリンクされていないようにします。URL rewriting creates an abstraction between resource locations and their addresses so that the locations and addresses aren't tightly linked. URL 書き換えは複数のシナリオで使用できます。URL rewriting is valuable in several scenarios to:

  • サーバー リソースを一時的または永続的に移動するか置き換えて、リソースに対する安定したロケーターを維持します。Move or replace server resources temporarily or permanently and maintain stable locators for those resources.
  • 要求処理を異なる複数のアプリまたは 1 つのアプリの複数の区分に分割します。Split request processing across different apps or across areas of one app.
  • 受信した要求の URL セグメントを削除、追加、または再編成します。Remove, add, or reorganize URL segments on incoming requests.
  • 検索エンジン最適化 (SEO) のためにパブリック URL を最適化します。Optimize public URLs for Search Engine Optimization (SEO).
  • ビジターがリソースの要求から返される内容を予測しやすいように、フレンドリなパブリック URL の使用を許可します。Permit the use of friendly public URLs to help visitors predict the content returned by requesting a resource.
  • セキュリティで保護されていない要求をセキュリティで保護されたエンドポイントにリダイレクトします。Redirect insecure requests to secure endpoints.
  • 外部サイトが別のサイトでホストされている静的資産を独自のコンテンツにリンクすることによってその資産を使用するホットリンクを防止します。Prevent hotlinking, where an external site uses a hosted static asset on another site by linking the asset into its own content.

注意

URL の書き換えによってアプリのパフォーマンスが低下することがあります。URL rewriting can reduce the performance of an app. 可能であれば、ルールの複雑さと数を制限します。Where feasible, limit the number and complexity of rules.

サンプル コードを表示またはダウンロードします (ダウンロード方法)。View or download sample code (how to download)

URL リダイレクトと URL 書き換えURL redirect and URL rewrite

"URL リダイレクト" と "URL 書き換え" では表現上はあまり違いがないように見えますが、クライアントへのリソースの提供に関しては重要な意味を持っています。The difference in wording between URL redirect and URL rewrite is subtle but has important implications for providing resources to clients. ASP.NET Core の URL リライト ミドルウェアは、両方のニーズを満たすことができます。ASP.NET Core's URL Rewriting Middleware is capable of meeting the need for both.

"URL リダイレクト" にはクライアント側の操作が関係しており、クライアントはもともと要求したものとは異なるアドレスにあるリソースにアクセスするよう指示されます。A URL redirect involves a client-side operation, where the client is instructed to access a resource at a different address than the client originally requested. これによりサーバーへのラウンドトリップが必要になります。This requires a round trip to the server. クライアントが、リソースの新しい要求を実行するときに、クライアントに返されたリダイレクト URL がブラウザーのアドレス バーに表示されます。The redirect URL returned to the client appears in the browser's address bar when the client makes a new request for the resource.

/resource/different-resource に "リダイレクトされる" 場合、サーバーからの応答では、クライアントが /different-resource にあるリソースを取得する必要があることと、リダイレクトが一時的または永続的のどちらかを示す状態コードが示されます。If /resource is redirected to /different-resource, the server responds that the client should obtain the resource at /different-resource with a status code indicating that the redirect is either temporary or permanent.

WebAPI サービス エンドポイントは、サーバー上でバージョン 1 (v1) からバージョン 2 (v2) に一時的に変更されました。

要求を別の URL にリダイレクトする場合は、応答で状態コードを指定することにより、リダイレクトが永続的か一時的かのどちらかを示します。When redirecting requests to a different URL, indicate whether the redirect is permanent or temporary by specifying the status code with the response:

  • "301 - 完全な移動" 状態コードは、リソースに新しい永続的な URL があり、リソースに対する将来のすべての要求で新しい URL を使用する必要があることをクライアントに指示したい場合に使用します。The 301 - Moved Permanently status code is used where the resource has a new, permanent URL and you wish to instruct the client that all future requests for the resource should use the new URL. "301 状態コードを受信すると、クライアントは応答をキャッシュに入れて再利用することができます。 "The client may cache and reuse the response when a 301 status code is received.

  • "302 - 検出" 状態コードは、リダイレクトが一時的である場合、または一般に変更される可能性がある場合に使用されます。The 302 - Found status code is used where the redirection is temporary or generally subject to change. 302 状態コードは、URL を保存して後で再利用しないようクライアントに指示します。The 302 status code indicates to the client not to store the URL and use it in the future.

状態コードの詳細については、RFC 2616: 状態コードの定義に関するページを参照してください。For more information on status codes, see RFC 2616: Status Code Definitions.

"URL 書き換え" はサーバー側の操作であり、クライアントが要求したものとは異なるリソース アドレスからリソースが提供されます。A URL rewrite is a server-side operation that provides a resource from a different resource address than the client requested. URL 書き換えでは、サーバーへのラウンドトリップは必要ありません。Rewriting a URL doesn't require a round trip to the server. 書き換えられた URL は、クライアントに返されず、ブラウザーのアドレス バーに表示されません。The rewritten URL isn't returned to the client and doesn't appear in the browser's address bar.

/resource/different-resource に "書き換えられた" 場合、サーバーは /different-resource にあるリソースを "内部的に" 取得して返します。If /resource is rewritten to /different-resource, the server internally fetches and returns the resource at /different-resource.

クライアントは、書き換えられた URL にあるリソースを取得できる場合がありますが、クライアントは、その要求を実行して応答を受信したときに、書き換えられた URL にリソースが存在することは通知されません。Although the client might be able to retrieve the resource at the rewritten URL, the client isn't informed that the resource exists at the rewritten URL when it makes its request and receives the response.

WebAPI サービス エンドポイントは、サーバー上でバージョン 1 (v1) からバージョン 2 (v2) に変更されました。

URL リライト サンプル アプリURL rewriting sample app

サンプル アプリを使用して、URL リライト ミドルウェアの機能を調べることができます。You can explore the features of the URL Rewriting Middleware with the sample app. そのアプリは、リダイレクトと書き換えのルールを適用し、複数のシナリオについて、リダイレクトされた URL または書き換えられた URL を表示します。The app applies redirect and rewrite rules and shows the redirected or rewritten URL for several scenarios.

URL リライト ミドルウェアを使用する状況When to use URL Rewriting Middleware

次の方法を使用できない場合は、URL リライト ミドルウェアを使用します。Use URL Rewriting Middleware when you're unable to use the following approaches:

また、アプリが HTTP.sys サーバー (旧称 WebListener) でホストされているときも、ミドルウェアを使用します。Also, use the middleware when the app is hosted on HTTP.sys server (formerly called WebListener).

IIS、Apache、Nginx でサーバー ベースの URL 書き換えテクノロジが使用される主な理由は次のとおりです。The main reasons to use the server-based URL rewriting technologies in IIS, Apache, and Nginx are:

  • ミドルウェアでは、これらのモジュールの完全な機能がサポートされていません。The middleware doesn't support the full features of these modules.

    IIS 書き換えモジュールの IsFile 制約や IsDirectory 制約など、サーバー モジュールの一部の機能は、ASP.NET Core プロジェクトでは動作しません。Some of the features of the server modules don't work with ASP.NET Core projects, such as the IsFile and IsDirectory constraints of the IIS Rewrite module. これらのシナリオでは、代わりにミドルウェアを使用します。In these scenarios, use the middleware instead.

  • 通常、ミドルウェアのパフォーマンスはモジュールより劣ります。The performance of the middleware probably doesn't match that of the modules.

    どちらのアプローチの方がパフォーマンスの低下が大きいか、またはパフォーマンスが低下した場合でもごくわずかかどうかを確実に知るには、ベンチマークが唯一の方法です。Benchmarking is the only way to know for sure which approach degrades performance the most or if degraded performance is negligible.

PackagePackage

URL リライト ミドルウェアは、Microsoft.AspNetCore.Rewrite パッケージによって提供されます。このパッケージは ASP.NET Core アプリに暗黙的に含まれています。URL Rewriting Middleware is provided by the Microsoft.AspNetCore.Rewrite package, which is implicitly included in ASP.NET Core apps.

拡張機能とオプションExtension and options

各書き換えルールに対する拡張メソッドを含む RewriteOptions クラスのインスタンスを作成することにより、URL 書き換えとリダイレクトのルールを設定します。Establish URL rewrite and redirect rules by creating an instance of the RewriteOptions class with extension methods for each of your rewrite rules. 処理したい順序で複数のルールを連結します。Chain multiple rules in the order that you would like them processed. UseRewriter によって URL リライト ミドルウェアが要求パイプラインに追加されると、RewriteOptions が渡されます。The RewriteOptions are passed into the URL Rewriting Middleware as it's added to the request pipeline with UseRewriter:

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 にリダイレクトするRedirect non-www to www

アプリで非 www の要求を www にリダイレクトできる 3 つのオプションがあります。Three options permit the app to redirect non-www requests to www:

  • AddRedirectToWwwPermanent:要求が非 www の場合、要求を www サブドメインに永続的にリダイレクトします。AddRedirectToWwwPermanent: Permanently redirect the request to the www subdomain if the request is non-www. Status308PermanentRedirect 状態コードでリダイレクトします。Redirects with a Status308PermanentRedirect status code.

  • AddRedirectToWww:受信した要求が非 www の場合、要求を www サブドメインにリダイレクトします。AddRedirectToWww: Redirect the request to the www subdomain if the incoming request is non-www. Status307TemporaryRedirect 状態コードでリダイレクトします。Redirects with a Status307TemporaryRedirect status code. オーバーロードにより、応答に対する状態コードを提供することができます。An overload permits you to provide the status code for the response. 状態コードの割り当てには、StatusCodes クラスのフィールドを使用します。Use a field of the StatusCodes class for a status code assignment.

URL リダイレクトURL redirect

要求をリダイレクトするには、AddRedirect を使用します。Use AddRedirect to redirect requests. 最初のパラメーターには、着信 URL のパスに一致する正規表現が含まれています。The first parameter contains your regex for matching on the path of the incoming URL. 2 番目のパラメーターは、置換文字列です。The second parameter is the replacement string. 3 番目のパラメーター (存在する場合) は、状態コードを指定します。The third parameter, if present, specifies the status code. 状態コードを指定しない場合、状態コードは既定で "302 - 検出" に設定されます。これは、リソースが一時的に移動されるか置き換えられることを示します。If you don't specify the status code, the status code defaults to 302 - Found, which indicates that the resource is temporarily moved or replaced.

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 を指定してサンプル アプリに対する要求を実行します。In a browser with developer tools enabled, make a request to the sample app with the path /redirect-rule/1234/5678. 正規表現が redirect-rule/(.*) の要求のパスに一致し、パスが /redirected/1234/5678 に置き換えられます。The regex matches the request path on redirect-rule/(.*), and the path is replaced with /redirected/1234/5678. リダイレクト URL が、"302 - 検出" 状態コードでクライアントに返されます。The redirect URL is sent back to the client with a 302 - Found status code. ブラウザーは、ブラウザーのアドレス バーに表示されるリダイレクト URL に新しい要求を実行しますThe browser makes a new request at the redirect URL, which appears in the browser's address bar. リダイレクト URL にはサンプル アプリに一致するルールがないため、次のようになります。Since no rules in the sample app match on the redirect URL:

  • 2 番目の要求は、アプリから 200 - OK 応答を受け取ります。The second request receives a 200 - OK response from the app.
  • 応答の本文では、リダイレクト URL が示されています。The body of the response shows the redirect URL.

URL が "リダイレクト" されるときに、サーバーへのラウンドトリップが実行されます。A round trip is made to the server when a URL is redirected.

警告

リダイレクト ルールを設定するときは注意してください。Be cautious when establishing redirect rules. リダイレクト ルールは、リダイレクト後を含めて、アプリへのすべての要求で評価されます。Redirect rules are evaluated on every request to the app, including after a redirect. "無限リダイレクトのループ" が誤って作成されることがよくあります。It's easy to accidentally create a loop of infinite redirects.

元の要求: /redirect-rule/1234/5678Original Request: /redirect-rule/1234/5678

要求および応答を追跡する開発者ツールを備えたブラウザー ウィンドウ

かっこ内に含まれる式の一部は、キャプチャ グループと呼ばれます。The part of the expression contained within parentheses is called a capture group. 式のドット (.) は、どの文字とも一致することを意味します。The dot (.) of the expression means match any character. アスタリスク (*) は、直前の文字に 0 回以上一致することを示します。The asterisk (*) indicates match the preceding character zero or more times. そのため、URL の最後の 2 つのパス セグメント 1234/5678 は、キャプチャ グループ (.*) によってキャプチャされます。Therefore, the last two path segments of the URL, 1234/5678, are captured by capture group (.*). 要求 URL で redirect-rule/ の後に指定した任意の値が、この単一のキャプチャ グループによってキャプチャされます。Any value you provide in the request URL after redirect-rule/ is captured by this single capture group.

置換文字列では、キャプチャされたグループがドル記号 ($) を使用して文字列に挿入され、その後にキャプチャのシーケンス番号が続きます。In the replacement string, captured groups are injected into the string with the dollar sign ($) followed by the sequence number of the capture. 最初のキャプチャ グループ値は、$1 で取得され、2 番目は $2 で取得され、これらは正規表現内のキャプチャ グループの順序で続行されます。The first capture group value is obtained with $1, the second with $2, and they continue in sequence for the capture groups in your regex. サンプル アプリでは、リダイレクト ルールの正規表現内に 1 つのキャプチャ グループだけがあるので、置換文字列に 1 つの挿入されたグループ ($1) だけがあります。There's only one captured group in the redirect rule regex in the sample app, so there's only one injected group in the replacement string, which is $1. ルールが適用されるときに、URL /redirected/1234/5678 になります。When the rule is applied, the URL becomes /redirected/1234/5678.

セキュリティで保護されたエンドポイントへの URL リダイレクトURL redirect to a secure endpoint

HTTP 要求を、同じホストとパスに HTTPS プロトコルを使用してリダイレクトするには、AddRedirectToHttps を使用します。Use AddRedirectToHttps to redirect HTTP requests to the same host and path using the HTTPS protocol. 状態コードが指定されていない場合、ミドルウェアは既定で "302 - 検出" に設定します。If the status code isn't supplied, the middleware defaults to 302 - Found. ポートが指定されていない場合は、次のようになります。If the port isn't supplied:

  • ミドルウェアの既定値 null に設定されます。The middleware defaults to null.
  • スキームは https (HTTPS プロトコル) に変更されて、クライアントはポート 443 でリソースにアクセスします。The scheme changes to https (HTTPS protocol), and the client accesses the resource on port 443.

次の例では、状態コードを "301 - 完全な移動" に設定し、ポートを 5001 に変更する方法を示します。The following example shows how to set the status code to 301 - Moved Permanently and change the port to 5001.

public void Configure(IApplicationBuilder app)
{
    var options = new RewriteOptions()
        .AddRedirectToHttps(301, 5001);

    app.UseRewriter(options);
}

セキュリティで保護されていない要求を、セキュリティで保護された HTTPS プロトコル (ポート 443) を使用して同じホストとパスにリダイレクトするには、AddRedirectToHttpsPermanent を使用します。Use AddRedirectToHttpsPermanent to redirect insecure requests to the same host and path with secure HTTPS protocol on port 443. ミドルウェアは状態コードを "301 -完全な移動" に設定します。The middleware sets the status code to 301 - Moved Permanently.

public void Configure(IApplicationBuilder app)
{
    var options = new RewriteOptions()
        .AddRedirectToHttpsPermanent();

    app.UseRewriter(options);
}

注意

リダイレクト規則を追加せずにセキュリティで保護されたエンドポイントにリダイレクトするときは、HTTPS リダイレクト ミドルウェアを使用することをお勧めします。When redirecting to a secure endpoint without the requirement for additional redirect rules, we recommend using HTTPS Redirection Middleware. 詳細については、「HTTPS の適用」のトピックをご覧ください。For more information, see the Enforce HTTPS topic.

サンプル アプリは、AddRedirectToHttps または AddRedirectToHttpsPermanent の使用方法の例を示すことができます。The sample app is capable of demonstrating how to use AddRedirectToHttps or AddRedirectToHttpsPermanent. 拡張メソッドを RewriteOptions に追加します。Add the extension method to the RewriteOptions. 任意の URL でセキュリティ保護されていない要求をアプリに対して行います。Make an insecure request to the app at any URL. 自己署名証明書が信頼できないことを示すブラウザーのセキュリティ警告を消去するか、証明書を信頼する例外を作成します。Dismiss the browser security warning that the self-signed certificate is untrusted or create an exception to trust the certificate.

AddRedirectToHttps(301, 5001): http://localhost:5000/secure を使用する元の要求Original Request using AddRedirectToHttps(301, 5001): http://localhost:5000/secure

要求および応答を追跡する開発者ツールを備えたブラウザー ウィンドウ

AddRedirectToHttpsPermanent: http://localhost:5000/secure を使用する元の要求Original Request using AddRedirectToHttpsPermanent: http://localhost:5000/secure

要求および応答を追跡する開発者ツールを備えたブラウザー ウィンドウ

URL 書き換えURL rewrite

URL 書き換えのルールを作成するには、AddRewrite を使用します。Use AddRewrite to create a rule for rewriting URLs. 最初のパラメーターには、着信 URL のパスに一致する正規表現が含まれています。The first parameter contains the regex for matching on the incoming URL path. 2 番目のパラメーターは、置換文字列です。The second parameter is the replacement string. 3 番目のパラメーター skipRemainingRules: {true|false} は、現在のルールが適用される場合に追加の書き換えルールをスキップするかどうかをミドルウェアに示します。The third parameter, skipRemainingRules: {true|false}, indicates to the middleware whether or not to skip additional rewrite rules if the current rule is applied.

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/5678Original Request: /rewrite-rule/1234/5678

要求および応答を追跡する開発者ツールを備えたブラウザー ウィンドウ

式の先頭にあるキャレット (^) は、URL パスの先頭からマッチングが開始されることを意味します。The carat (^) at the beginning of the expression means that matching starts at the beginning of the URL path.

前のリダイレクト ルール redirect-rule/(.*) の例では、正規表現の先頭にキャレット (^) がありません。In the earlier example with the redirect rule, redirect-rule/(.*), there's no carat (^) at the start of the regex. したがって、パスの redirect-rule/ の前にどのような文字があっても一致します。Therefore, any characters may precede redirect-rule/ in the path for a successful match.

パスPath 一致したものMatch
/redirect-rule/1234/5678 はいYes
/my-cool-redirect-rule/1234/5678 はいYes
/anotherredirect-rule/1234/5678 はいYes

書き換えルール ^rewrite-rule/(\d+)/(\d+) は、rewrite-rule/ で始まる場合のみパスと一致します。The rewrite rule, ^rewrite-rule/(\d+)/(\d+), only matches paths if they start with rewrite-rule/. 次の表では、一致の違いに注意してください。In the following table, note the difference in matching.

パスPath 一致したものMatch
/rewrite-rule/1234/5678 はいYes
/my-cool-rewrite-rule/1234/5678 いいえNo
/anotherrewrite-rule/1234/5678 いいえNo

式の ^rewrite-rule/ に続く部分に、2 つのキャプチャ グループ (\d+)/(\d+) があります。Following the ^rewrite-rule/ portion of the expression, there are two capture groups, (\d+)/(\d+). \d は、1 桁 (数字) に一致することを示します。The \d signifies match a digit (number). プラス記号 (+) は、直前の 1 つ以上の文字に一致することを意味します。The plus sign (+) means match one or more of the preceding character. そのため、URL は、数字とその後に続くスラッシュ、さらにその後に続く別の数字を含んでいる必要があります。Therefore, the URL must contain a number followed by a forward-slash followed by another number. これらのキャプチャ グループが $1 および $2 として書き換えられた URL に挿入されます。These capture groups are injected into the rewritten URL as $1 and $2. 書き換えルールの置換文字列は、クエリ文字列にキャプチャされたグループを配置します。The rewrite rule replacement string places the captured groups into the query string. /rewrite-rule/1234/5678 の要求されたパスは、/rewritten?var1=1234&var2=5678 でリソースを取得するように書き換えられます。The requested path of /rewrite-rule/1234/5678 is rewritten to obtain the resource at /rewritten?var1=1234&var2=5678. クエリ文字列が元の要求に存在する場合、URL が書き換えられるときに保持されます。If a query string is present on the original request, it's preserved when the URL is rewritten.

リソースを取得するためのサーバーへのラウンドトリップはありません。There's no round trip to the server to obtain the resource. リソースが存在する場合は、取得され、200 - OK 状態コードと共にクライアントに返されます。If the resource exists, it's fetched and returned to the client with a 200 - OK status code. クライアントはリダイレクトされていないため、ブラウザーのアドレス バーの URL は変更されません。Because the client isn't redirected, the URL in the browser's address bar doesn't change. クライアントは、URL の書き換え操作がサーバーで発生したことを検出できません。Clients can't detect that a URL rewrite operation occurred on the server.

注意

式内の照合ルールは計算量が多く、アプリの応答時間が長くなるので、可能な限り skipRemainingRules: true を使用します。Use skipRemainingRules: true whenever possible because matching rules is computationally expensive and increases app response time. 最も高速なアプリの応答を実現するには以下のようにします。For the fastest app response:

  • 一致する頻度が最も多いルールから一致頻度が最も少ないルールへの順番で書き換えルールを並べ替えます。Order rewrite rules from the most frequently matched rule to the least frequently matched rule.
  • 一致が発生し、追加の処理が必要ないときに残りのルールの処理をスキップします。Skip the processing of the remaining rules when a match occurs and no additional rule processing is required.

Apache mod_rewriteApache mod_rewrite

AddApacheModRewrite を使用して Apache mod_rewrite ルールを適用します。Apply Apache mod_rewrite rules with AddApacheModRewrite. ルール ファイルがアプリと共に展開されていることを確認します。Make sure that the rules file is deployed with the app. mod_rewrite ルールの情報と例については、「Apache mod_rewrite」を参照してください。For more information and examples of mod_rewrite rules, see Apache mod_rewrite.

ApacheModRewrite.txt ルール ファイルからルールを読み取るには、StreamReader を使用します。A StreamReader is used to read the rules from the ApacheModRewrite.txt rules file:

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 にリダイレクトします。The sample app redirects requests from /apache-mod-rules-redirect/(.\*) to /redirected?id=$1. 応答の状態コードは "302 -検出" です。The response status code is 302 - Found.

# Rewrite path with additional sub directory
RewriteRule ^/apache-mod-rules-redirect/(.*) /redirected?id=$1 [L,R=302]

元の要求: /apache-mod-rules-redirect/1234Original Request: /apache-mod-rules-redirect/1234

要求および応答を追跡する開発者ツールを備えたブラウザー ウィンドウ

ミドルウェアは、次の Apache mod_rewrite サーバー変数をサポートします。The middleware supports the following Apache mod_rewrite server variables:

  • CONN_REMOTE_ADDRCONN_REMOTE_ADDR
  • HTTP_ACCEPTHTTP_ACCEPT
  • HTTP_CONNECTIONHTTP_CONNECTION
  • HTTP_COOKIEHTTP_COOKIE
  • HTTP_FORWARDEDHTTP_FORWARDED
  • HTTP_HOSTHTTP_HOST
  • HTTP_REFERERHTTP_REFERER
  • HTTP_USER_AGENTHTTP_USER_AGENT
  • HTTPSHTTPS
  • IPV6IPV6
  • QUERY_STRINGQUERY_STRING
  • REMOTE_ADDRREMOTE_ADDR
  • REMOTE_PORTREMOTE_PORT
  • REQUEST_FILENAMEREQUEST_FILENAME
  • REQUEST_METHODREQUEST_METHOD
  • REQUEST_SCHEMEREQUEST_SCHEME
  • REQUEST_URIREQUEST_URI
  • SCRIPT_FILENAMESCRIPT_FILENAME
  • SERVER_ADDRSERVER_ADDR
  • SERVER_PORTSERVER_PORT
  • SERVER_PROTOCOLSERVER_PROTOCOL
  • TIMETIME
  • TIME_DAYTIME_DAY
  • TIME_HOURTIME_HOUR
  • TIME_MINTIME_MIN
  • TIME_MONTIME_MON
  • TIME_SECTIME_SEC
  • TIME_WDAYTIME_WDAY
  • TIME_YEARTIME_YEAR

IIS URL リライト モジュールのルールIIS URL Rewrite Module rules

IIS URL リライト モジュールに適用される同じルール セットを使用するには、AddIISUrlRewrite を使用します。To use the same rule set that applies to the IIS URL Rewrite Module, use AddIISUrlRewrite. ルール ファイルがアプリと共に展開されていることを確認します。Make sure that the rules file is deployed with the app. Windows Server IIS で実行されているときにミドルウェアでアプリの web.config ファイルを使用するように指定しないでください。Don't direct the middleware to use the app's web.config file when running on Windows Server IIS. IIS を使用する場合、IIS リライト モジュールとの競合を避けるため、これらのルールをアプリの web.config の外部に保存する必要があります。With IIS, these rules should be stored outside of the app's web.config file in order to avoid conflicts with the IIS Rewrite module. IIS URL リライト モジュールのルールの詳細と例については、「Using Url Rewrite Module 2.0」(URL リライト モジュール 2.0 の使用 ) と「URL Rewrite Module Configuration Reference」(URL リライト モジュール構成リファレンス) を参照してください。For more information and examples of IIS URL Rewrite Module rules, see Using Url Rewrite Module 2.0 and URL Rewrite Module Configuration Reference.

IISUrlRewrite.xml ルール ファイルからルールを読み取るには、StreamReader を使用します。A StreamReader is used to read the rules from the IISUrlRewrite.xml rules file:

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 に書き換えます。The sample app rewrites requests from /iis-rules-rewrite/(.*) to /rewritten?id=$1. 応答は、200 - OK 状態コードでクライアントに送信されます。The response is sent to the client with a 200 - OK status code.

<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/1234Original Request: /iis-rules-rewrite/1234

要求および応答を追跡する開発者ツールを備えたブラウザー ウィンドウ

望ましくない方法でアプリに影響するように構成されたサーバー レベル ルールを使用するアクティブな IIS リライト モジュールがある場合は、アプリに対して IIS リライト モジュールを無効にできます。If you have an active IIS Rewrite Module with server-level rules configured that would impact your app in undesirable ways, you can disable the IIS Rewrite Module for an app. 詳細については、「Disabling IIS modules」 (IIS モジュールの無効化) を参照してください。For more information, see Disabling IIS modules.

サポートされていない機能Unsupported features

ASP.NET Core 2.x でリリースされたミドルウェアは、次の IIS URL リライト モジュールの機能をサポートしていません。The middleware released with ASP.NET Core 2.x doesn't support the following IIS URL Rewrite Module features:

  • 送信ルールOutbound Rules
  • カスタム サーバー変数Custom Server Variables
  • ワイルドカードWildcards
  • LogRewrittenUrlLogRewrittenUrl

サポートされるサーバー変数Supported server variables

ミドルウェアは、次の IIS URL リライト モジュール サーバー変数をサポートします。The middleware supports the following IIS URL Rewrite Module server variables:

  • CONTENT_LENGTHCONTENT_LENGTH
  • CONTENT_TYPECONTENT_TYPE
  • HTTP_ACCEPTHTTP_ACCEPT
  • HTTP_CONNECTIONHTTP_CONNECTION
  • HTTP_COOKIEHTTP_COOKIE
  • HTTP_HOSTHTTP_HOST
  • HTTP_REFERERHTTP_REFERER
  • HTTP_URLHTTP_URL
  • HTTP_USER_AGENTHTTP_USER_AGENT
  • HTTPSHTTPS
  • LOCAL_ADDRLOCAL_ADDR
  • QUERY_STRINGQUERY_STRING
  • REMOTE_ADDRREMOTE_ADDR
  • REMOTE_PORTREMOTE_PORT
  • REQUEST_FILENAMEREQUEST_FILENAME
  • REQUEST_URIREQUEST_URI

注意

PhysicalFileProvider を介して IFileProvider を取得することもできます。You can also obtain an IFileProvider via a PhysicalFileProvider. このアプローチは、書き換えルール ファイルの場所に関する大きな柔軟性を提供する場合があります。This approach may provide greater flexibility for the location of your rewrite rules files. 書き換えルール ファイルを指定したパスでサーバーに導入されていることを確認してください。Make sure that your rewrite rules files are deployed to the server at the path you provide.

PhysicalFileProvider fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());

メソッド ベースのルールMethod-based rule

メソッド内で独自のルール ロジックを実装するには、Add を使用します。Use Add to implement your own rule logic in a method. AddRewriteContext を公開し、メソッドで HttpContext を使用できるようにします。Add exposes the RewriteContext, which makes available the HttpContext for use in your method. RewriteContext.Result は、追加のパイプライン処理の実行方法を決定します。The RewriteContext.Result determines how additional pipeline processing is handled. 次の表で説明する RuleResult フィールドのいずれかに値を設定します。Set the value to one of the RuleResult fields described in the following table.

コンテキストの書き換えの結果Rewrite context result アクションAction
RuleResult.ContinueRules (既定値)RuleResult.ContinueRules (default) ルールの適用を続けます。Continue applying rules.
RuleResult.EndResponse ルールの適用を停止し、応答を送信します。Stop applying rules and send the response.
RuleResult.SkipRemainingRules ルールの適用を停止し、次のミドルウェアにコンテキストを送信します。Stop applying rules and send the context to the next middleware.
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 で終了するパスの要求をリダイレクトするメソッドの例を示します。The sample app demonstrates a method that redirects requests for paths that end with .xml. /file.xml に対して要求が行われた場合、要求は /xmlfiles/file.xml にリダイレクトされます。If a request is made for /file.xml, the request is redirected to /xmlfiles/file.xml. 状態コードは "301 - 完全な移動" に設定されます。The status code is set to 301 - Moved Permanently. ブラウザーが /xmlfiles/file.xml に対する新しい要求を行うと、静的ファイル ミドルウェアはクライアントに wwwroot/xmlfiles フォルダーからファイルを提供します。When the browser makes a new request for /xmlfiles/file.xml, Static File Middleware serves the file to the client from the wwwroot/xmlfiles folder. リダイレクトの場合は、応答の状態コードを明示的に設定します。For a redirect, explicitly set the status code of the response. それ以外の場合は、200 - OK 状態コードが返され、クライアントでのリダイレクトは発生しません。Otherwise, a 200 - OK status code is returned, and the redirect doesn't occur on the client.

RewriteRules.cs: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 = StatusCodes.Status301MovedPermanently;
        context.Result = RuleResult.EndResponse;
        response.Headers[HeaderNames.Location] = 
            "/xmlfiles" + request.Path + request.QueryString;
    }
}

このアプローチでは、要求を書き換えることもできます。This approach can also rewrite requests. サンプル アプリでは、wwwroot フォルダーから file.txt テキスト ファイルを提供するためにテキスト ファイル要求のパスを書き換える処理が示されています。The sample app demonstrates rewriting the path for any text file request to serve the file.txt text file from the wwwroot folder. 静的ファイル ミドルウェアでは、更新された要求パスに基づいてファイルが提供されます。Static File Middleware serves the file based on the updated request path:

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: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-based rule

IRule インターフェイスを実装するクラス内のルール ロジックを使用するには、Add を使用します。Use Add to use rule logic in a class that implements the IRule interface. IRule では、メソッド ベースのルール アプローチを使用する場合より高い柔軟性が提供されます。IRule provides greater flexibility over using the method-based rule approach. 実装クラスには、ApplyRule メソッドに対してパラメーターを渡すことができるコンストラクターを含めることができます。Your implementation class may include a constructor that allows you can pass in parameters for the ApplyRule method.

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}"));
}

サンプル アプリの extensionnewPath のパラメーターの値は、いくつかの条件を満たすかチェックされます。The values of the parameters in the sample app for the extension and the newPath are checked to meet several conditions. extension は、値を含んでいる必要があり、値は .png.jpg、または .gif でなければなりません。The extension must contain a value, and the value must be .png, .jpg, or .gif. newPath が有効ではない場合、ArgumentException がスローされます。If the newPath isn't valid, an ArgumentException is thrown. image.png に対して行われた要求は、/png-images/image.png にリダイレクトされます。If a request is made for image.png, the request is redirected to /png-images/image.png. image.jpg に対して行われた要求は、/jpg-images/image.jpg にリダイレクトされます。If a request is made for image.jpg, the request is redirected to /jpg-images/image.jpg. 状態コードは "301 - 完全な移動" に設定され、context.Result はルールの処理を停止して応答を送信するように設定されます。The status code is set to 301 - Moved Permanently, and the context.Result is set to stop processing rules and send the response.

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 = StatusCodes.Status301MovedPermanently;
            context.Result = RuleResult.EndResponse;
            response.Headers[HeaderNames.Location] = 
                _newPath + request.Path + request.QueryString;
        }
    }
}

元の要求: /image.pngOriginal Request: /image.png

image.png の要求および応答を追跡する開発者ツールを備えたブラウザー ウィンドウ

元の要求: /image.jpgOriginal Request: /image.jpg

image.jpg の要求および応答を追跡する開発者ツールを備えたブラウザー ウィンドウ

正規表現の例Regex examples

GoalGoal 正規表現文字列とRegex String &
一致の例Match Example
置換文字列とReplacement String &
出力の例Output Example
クエリ文字列内のパスを書き換えるRewrite path into querystring ^path/(.*)/(.*)
/path/abc/123
path?var1=$1&var2=$2
/path?var1=abc&var2=123
末尾のスラッシュを除去するStrip trailing slash (.*)/$
/path/
$1
/path
末尾のスラッシュを強制するEnforce trailing slash (.*[^/])$
/path
$1/
/path/
特定の要求を書き換えを回避するAvoid rewriting specific requests ^(.*)(?<!\.axd)$ または ^(?!.*\.axd$)(.*)$^(.*)(?<!\.axd)$ or ^(?!.*\.axd$)(.*)$
はい: /resource.htmYes: /resource.htm
いいえ: /resource.axdNo: /resource.axd
rewritten/$1
/rewritten/resource.htm
/resource.axd
URL セグメントを再配置するRearrange URL segments path/(.*)/(.*)/(.*)
path/1/2/3
path/$3/$2/$1
path/3/2/1
URL セグメントを置き換えるReplace a URL segment ^(.*)/segment2/(.*)
/segment1/segment2/segment3
$1/replaced/$2
/segment1/replaced/segment3

このドキュメントでは、ASP.NET Core アプリの URL リライト ミドルウェアを使用して URL を書き換える手順について説明します。This document introduces URL rewriting with instructions on how to use URL Rewriting Middleware in ASP.NET Core apps.

URL の書き換えは、1 つまたは複数の事前定義された規則に基づいて URL 要求を変更する操作です。URL rewriting is the act of modifying request URLs based on one or more predefined rules. URL 書き換えは、リソースの場所とそれらのアドレスの間の抽象化を作成し、場所とアドレスが緊密にリンクされていないようにします。URL rewriting creates an abstraction between resource locations and their addresses so that the locations and addresses aren't tightly linked. URL 書き換えは複数のシナリオで使用できます。URL rewriting is valuable in several scenarios to:

  • サーバー リソースを一時的または永続的に移動するか置き換えて、リソースに対する安定したロケーターを維持します。Move or replace server resources temporarily or permanently and maintain stable locators for those resources.
  • 要求処理を異なる複数のアプリまたは 1 つのアプリの複数の区分に分割します。Split request processing across different apps or across areas of one app.
  • 受信した要求の URL セグメントを削除、追加、または再編成します。Remove, add, or reorganize URL segments on incoming requests.
  • 検索エンジン最適化 (SEO) のためにパブリック URL を最適化します。Optimize public URLs for Search Engine Optimization (SEO).
  • ビジターがリソースの要求から返される内容を予測しやすいように、フレンドリなパブリック URL の使用を許可します。Permit the use of friendly public URLs to help visitors predict the content returned by requesting a resource.
  • セキュリティで保護されていない要求をセキュリティで保護されたエンドポイントにリダイレクトします。Redirect insecure requests to secure endpoints.
  • 外部サイトが別のサイトでホストされている静的資産を独自のコンテンツにリンクすることによってその資産を使用するホットリンクを防止します。Prevent hotlinking, where an external site uses a hosted static asset on another site by linking the asset into its own content.

注意

URL の書き換えによってアプリのパフォーマンスが低下することがあります。URL rewriting can reduce the performance of an app. 可能であれば、ルールの複雑さと数を制限します。Where feasible, limit the number and complexity of rules.

サンプル コードを表示またはダウンロードします (ダウンロード方法)。View or download sample code (how to download)

URL リダイレクトと URL 書き換えURL redirect and URL rewrite

"URL リダイレクト" と "URL 書き換え" では表現上はあまり違いがないように見えますが、クライアントへのリソースの提供に関しては重要な意味を持っています。The difference in wording between URL redirect and URL rewrite is subtle but has important implications for providing resources to clients. ASP.NET Core の URL リライト ミドルウェアは、両方のニーズを満たすことができます。ASP.NET Core's URL Rewriting Middleware is capable of meeting the need for both.

"URL リダイレクト" にはクライアント側の操作が関係しており、クライアントはもともと要求したものとは異なるアドレスにあるリソースにアクセスするよう指示されます。A URL redirect involves a client-side operation, where the client is instructed to access a resource at a different address than the client originally requested. これによりサーバーへのラウンドトリップが必要になります。This requires a round trip to the server. クライアントが、リソースの新しい要求を実行するときに、クライアントに返されたリダイレクト URL がブラウザーのアドレス バーに表示されます。The redirect URL returned to the client appears in the browser's address bar when the client makes a new request for the resource.

/resource/different-resource に "リダイレクトされる" 場合、サーバーからの応答では、クライアントが /different-resource にあるリソースを取得する必要があることと、リダイレクトが一時的または永続的のどちらかを示す状態コードが示されます。If /resource is redirected to /different-resource, the server responds that the client should obtain the resource at /different-resource with a status code indicating that the redirect is either temporary or permanent.

WebAPI サービス エンドポイントは、サーバー上でバージョン 1 (v1) からバージョン 2 (v2) に一時的に変更されました。

要求を別の URL にリダイレクトする場合は、応答で状態コードを指定することにより、リダイレクトが永続的か一時的かのどちらかを示します。When redirecting requests to a different URL, indicate whether the redirect is permanent or temporary by specifying the status code with the response:

  • "301 - 完全な移動" 状態コードは、リソースに新しい永続的な URL があり、リソースに対する将来のすべての要求で新しい URL を使用する必要があることをクライアントに指示したい場合に使用します。The 301 - Moved Permanently status code is used where the resource has a new, permanent URL and you wish to instruct the client that all future requests for the resource should use the new URL. "301 状態コードを受信すると、クライアントは応答をキャッシュに入れて再利用することができます。 "The client may cache and reuse the response when a 301 status code is received.

  • "302 - 検出" 状態コードは、リダイレクトが一時的である場合、または一般に変更される可能性がある場合に使用されます。The 302 - Found status code is used where the redirection is temporary or generally subject to change. 302 状態コードは、URL を保存して後で再利用しないようクライアントに指示します。The 302 status code indicates to the client not to store the URL and use it in the future.

状態コードの詳細については、RFC 2616: 状態コードの定義に関するページを参照してください。For more information on status codes, see RFC 2616: Status Code Definitions.

"URL 書き換え" はサーバー側の操作であり、クライアントが要求したものとは異なるリソース アドレスからリソースが提供されます。A URL rewrite is a server-side operation that provides a resource from a different resource address than the client requested. URL 書き換えでは、サーバーへのラウンドトリップは必要ありません。Rewriting a URL doesn't require a round trip to the server. 書き換えられた URL は、クライアントに返されず、ブラウザーのアドレス バーに表示されません。The rewritten URL isn't returned to the client and doesn't appear in the browser's address bar.

/resource/different-resource に "書き換えられた" 場合、サーバーは /different-resource にあるリソースを "内部的に" 取得して返します。If /resource is rewritten to /different-resource, the server internally fetches and returns the resource at /different-resource.

クライアントは、書き換えられた URL にあるリソースを取得できる場合がありますが、クライアントは、その要求を実行して応答を受信したときに、書き換えられた URL にリソースが存在することは通知されません。Although the client might be able to retrieve the resource at the rewritten URL, the client isn't informed that the resource exists at the rewritten URL when it makes its request and receives the response.

WebAPI サービス エンドポイントは、サーバー上でバージョン 1 (v1) からバージョン 2 (v2) に変更されました。

URL リライト サンプル アプリURL rewriting sample app

サンプル アプリを使用して、URL リライト ミドルウェアの機能を調べることができます。You can explore the features of the URL Rewriting Middleware with the sample app. そのアプリは、リダイレクトと書き換えのルールを適用し、複数のシナリオについて、リダイレクトされた URL または書き換えられた URL を表示します。The app applies redirect and rewrite rules and shows the redirected or rewritten URL for several scenarios.

URL リライト ミドルウェアを使用する状況When to use URL Rewriting Middleware

次の方法を使用できない場合は、URL リライト ミドルウェアを使用します。Use URL Rewriting Middleware when you're unable to use the following approaches:

また、アプリが HTTP.sys サーバー (旧称 WebListener) でホストされているときも、ミドルウェアを使用します。Also, use the middleware when the app is hosted on HTTP.sys server (formerly called WebListener).

IIS、Apache、Nginx でサーバー ベースの URL 書き換えテクノロジが使用される主な理由は次のとおりです。The main reasons to use the server-based URL rewriting technologies in IIS, Apache, and Nginx are:

  • ミドルウェアでは、これらのモジュールの完全な機能がサポートされていません。The middleware doesn't support the full features of these modules.

    IIS 書き換えモジュールの IsFile 制約や IsDirectory 制約など、サーバー モジュールの一部の機能は、ASP.NET Core プロジェクトでは動作しません。Some of the features of the server modules don't work with ASP.NET Core projects, such as the IsFile and IsDirectory constraints of the IIS Rewrite module. これらのシナリオでは、代わりにミドルウェアを使用します。In these scenarios, use the middleware instead.

  • 通常、ミドルウェアのパフォーマンスはモジュールより劣ります。The performance of the middleware probably doesn't match that of the modules.

    どちらのアプローチの方がパフォーマンスの低下が大きいか、またはパフォーマンスが低下した場合でもごくわずかかどうかを確実に知るには、ベンチマークが唯一の方法です。Benchmarking is the only way to know for sure which approach degrades performance the most or if degraded performance is negligible.

PackagePackage

ミドルウェアをプロジェクトに組み込むには、Microsoft.AspNetCore.App メタパッケージへのパッケージ参照をプロジェクト ファイルに追加します。これには、Microsoft.AspNetCore.Rewrite パッケージが含まれます。To include the middleware in your project, add a package reference to the Microsoft.AspNetCore.App metapackage in the project file, which contains the Microsoft.AspNetCore.Rewrite package.

Microsoft.AspNetCore.App メタパッケージを使用しない場合は、Microsoft.AspNetCore.Rewrite パッケージへのプロジェクト参照を追加します。When not using the Microsoft.AspNetCore.App metapackage, add a project reference to the Microsoft.AspNetCore.Rewrite package.

拡張機能とオプションExtension and options

各書き換えルールに対する拡張メソッドを含む RewriteOptions クラスのインスタンスを作成することにより、URL 書き換えとリダイレクトのルールを設定します。Establish URL rewrite and redirect rules by creating an instance of the RewriteOptions class with extension methods for each of your rewrite rules. 処理したい順序で複数のルールを連結します。Chain multiple rules in the order that you would like them processed. UseRewriter によって URL リライト ミドルウェアが要求パイプラインに追加されると、RewriteOptions が渡されます。The RewriteOptions are passed into the URL Rewriting Middleware as it's added to the request pipeline with UseRewriter:

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 にリダイレクトするRedirect non-www to www

アプリで非 www の要求を www にリダイレクトできる 3 つのオプションがあります。Three options permit the app to redirect non-www requests to www:

  • AddRedirectToWwwPermanent:要求が非 www の場合、要求を www サブドメインに永続的にリダイレクトします。AddRedirectToWwwPermanent: Permanently redirect the request to the www subdomain if the request is non-www. Status308PermanentRedirect 状態コードでリダイレクトします。Redirects with a Status308PermanentRedirect status code.

  • AddRedirectToWww:受信した要求が非 www の場合、要求を www サブドメインにリダイレクトします。AddRedirectToWww: Redirect the request to the www subdomain if the incoming request is non-www. Status307TemporaryRedirect 状態コードでリダイレクトします。Redirects with a Status307TemporaryRedirect status code. オーバーロードにより、応答に対する状態コードを提供することができます。An overload permits you to provide the status code for the response. 状態コードの割り当てには、StatusCodes クラスのフィールドを使用します。Use a field of the StatusCodes class for a status code assignment.

URL リダイレクトURL redirect

要求をリダイレクトするには、AddRedirect を使用します。Use AddRedirect to redirect requests. 最初のパラメーターには、着信 URL のパスに一致する正規表現が含まれています。The first parameter contains your regex for matching on the path of the incoming URL. 2 番目のパラメーターは、置換文字列です。The second parameter is the replacement string. 3 番目のパラメーター (存在する場合) は、状態コードを指定します。The third parameter, if present, specifies the status code. 状態コードを指定しない場合、状態コードは既定で "302 - 検出" に設定されます。これは、リソースが一時的に移動されるか置き換えられることを示します。If you don't specify the status code, the status code defaults to 302 - Found, which indicates that the resource is temporarily moved or replaced.

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 を指定してサンプル アプリに対する要求を実行します。In a browser with developer tools enabled, make a request to the sample app with the path /redirect-rule/1234/5678. 正規表現が redirect-rule/(.*) の要求のパスに一致し、パスが /redirected/1234/5678 に置き換えられます。The regex matches the request path on redirect-rule/(.*), and the path is replaced with /redirected/1234/5678. リダイレクト URL が、"302 - 検出" 状態コードでクライアントに返されます。The redirect URL is sent back to the client with a 302 - Found status code. ブラウザーは、ブラウザーのアドレス バーに表示されるリダイレクト URL に新しい要求を実行しますThe browser makes a new request at the redirect URL, which appears in the browser's address bar. リダイレクト URL にはサンプル アプリに一致するルールがないため、次のようになります。Since no rules in the sample app match on the redirect URL:

  • 2 番目の要求は、アプリから 200 - OK 応答を受け取ります。The second request receives a 200 - OK response from the app.
  • 応答の本文では、リダイレクト URL が示されています。The body of the response shows the redirect URL.

URL が "リダイレクト" されるときに、サーバーへのラウンドトリップが実行されます。A round trip is made to the server when a URL is redirected.

警告

リダイレクト ルールを設定するときは注意してください。Be cautious when establishing redirect rules. リダイレクト ルールは、リダイレクト後を含めて、アプリへのすべての要求で評価されます。Redirect rules are evaluated on every request to the app, including after a redirect. "無限リダイレクトのループ" が誤って作成されることがよくあります。It's easy to accidentally create a loop of infinite redirects.

元の要求: /redirect-rule/1234/5678Original Request: /redirect-rule/1234/5678

要求および応答を追跡する開発者ツールを備えたブラウザー ウィンドウ

かっこ内に含まれる式の一部は、キャプチャ グループと呼ばれます。The part of the expression contained within parentheses is called a capture group. 式のドット (.) は、どの文字とも一致することを意味します。The dot (.) of the expression means match any character. アスタリスク (*) は、直前の文字に 0 回以上一致することを示します。The asterisk (*) indicates match the preceding character zero or more times. そのため、URL の最後の 2 つのパス セグメント 1234/5678 は、キャプチャ グループ (.*) によってキャプチャされます。Therefore, the last two path segments of the URL, 1234/5678, are captured by capture group (.*). 要求 URL で redirect-rule/ の後に指定した任意の値が、この単一のキャプチャ グループによってキャプチャされます。Any value you provide in the request URL after redirect-rule/ is captured by this single capture group.

置換文字列では、キャプチャされたグループがドル記号 ($) を使用して文字列に挿入され、その後にキャプチャのシーケンス番号が続きます。In the replacement string, captured groups are injected into the string with the dollar sign ($) followed by the sequence number of the capture. 最初のキャプチャ グループ値は、$1 で取得され、2 番目は $2 で取得され、これらは正規表現内のキャプチャ グループの順序で続行されます。The first capture group value is obtained with $1, the second with $2, and they continue in sequence for the capture groups in your regex. サンプル アプリでは、リダイレクト ルールの正規表現内に 1 つのキャプチャ グループだけがあるので、置換文字列に 1 つの挿入されたグループ ($1) だけがあります。There's only one captured group in the redirect rule regex in the sample app, so there's only one injected group in the replacement string, which is $1. ルールが適用されるときに、URL /redirected/1234/5678 になります。When the rule is applied, the URL becomes /redirected/1234/5678.

セキュリティで保護されたエンドポイントへの URL リダイレクトURL redirect to a secure endpoint

HTTP 要求を、同じホストとパスに HTTPS プロトコルを使用してリダイレクトするには、AddRedirectToHttps を使用します。Use AddRedirectToHttps to redirect HTTP requests to the same host and path using the HTTPS protocol. 状態コードが指定されていない場合、ミドルウェアは既定で "302 - 検出" に設定します。If the status code isn't supplied, the middleware defaults to 302 - Found. ポートが指定されていない場合は、次のようになります。If the port isn't supplied:

  • ミドルウェアの既定値 null に設定されます。The middleware defaults to null.
  • スキームは https (HTTPS プロトコル) に変更されて、クライアントはポート 443 でリソースにアクセスします。The scheme changes to https (HTTPS protocol), and the client accesses the resource on port 443.

次の例では、状態コードを "301 - 完全な移動" に設定し、ポートを 5001 に変更する方法を示します。The following example shows how to set the status code to 301 - Moved Permanently and change the port to 5001.

public void Configure(IApplicationBuilder app)
{
    var options = new RewriteOptions()
        .AddRedirectToHttps(301, 5001);

    app.UseRewriter(options);
}

セキュリティで保護されていない要求を、セキュリティで保護された HTTPS プロトコル (ポート 443) を使用して同じホストとパスにリダイレクトするには、AddRedirectToHttpsPermanent を使用します。Use AddRedirectToHttpsPermanent to redirect insecure requests to the same host and path with secure HTTPS protocol on port 443. ミドルウェアは状態コードを "301 -完全な移動" に設定します。The middleware sets the status code to 301 - Moved Permanently.

public void Configure(IApplicationBuilder app)
{
    var options = new RewriteOptions()
        .AddRedirectToHttpsPermanent();

    app.UseRewriter(options);
}

注意

リダイレクト規則を追加せずにセキュリティで保護されたエンドポイントにリダイレクトするときは、HTTPS リダイレクト ミドルウェアを使用することをお勧めします。When redirecting to a secure endpoint without the requirement for additional redirect rules, we recommend using HTTPS Redirection Middleware. 詳細については、「HTTPS の適用」のトピックをご覧ください。For more information, see the Enforce HTTPS topic.

サンプル アプリは、AddRedirectToHttps または AddRedirectToHttpsPermanent の使用方法の例を示すことができます。The sample app is capable of demonstrating how to use AddRedirectToHttps or AddRedirectToHttpsPermanent. 拡張メソッドを RewriteOptions に追加します。Add the extension method to the RewriteOptions. 任意の URL でセキュリティ保護されていない要求をアプリに対して行います。Make an insecure request to the app at any URL. 自己署名証明書が信頼できないことを示すブラウザーのセキュリティ警告を消去するか、証明書を信頼する例外を作成します。Dismiss the browser security warning that the self-signed certificate is untrusted or create an exception to trust the certificate.

AddRedirectToHttps(301, 5001): http://localhost:5000/secure を使用する元の要求Original Request using AddRedirectToHttps(301, 5001): http://localhost:5000/secure

要求および応答を追跡する開発者ツールを備えたブラウザー ウィンドウ

AddRedirectToHttpsPermanent: http://localhost:5000/secure を使用する元の要求Original Request using AddRedirectToHttpsPermanent: http://localhost:5000/secure

要求および応答を追跡する開発者ツールを備えたブラウザー ウィンドウ

URL 書き換えURL rewrite

URL 書き換えのルールを作成するには、AddRewrite を使用します。Use AddRewrite to create a rule for rewriting URLs. 最初のパラメーターには、着信 URL のパスに一致する正規表現が含まれています。The first parameter contains the regex for matching on the incoming URL path. 2 番目のパラメーターは、置換文字列です。The second parameter is the replacement string. 3 番目のパラメーター skipRemainingRules: {true|false} は、現在のルールが適用される場合に追加の書き換えルールをスキップするかどうかをミドルウェアに示します。The third parameter, skipRemainingRules: {true|false}, indicates to the middleware whether or not to skip additional rewrite rules if the current rule is applied.

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/5678Original Request: /rewrite-rule/1234/5678

要求および応答を追跡する開発者ツールを備えたブラウザー ウィンドウ

式の先頭にあるキャレット (^) は、URL パスの先頭からマッチングが開始されることを意味します。The carat (^) at the beginning of the expression means that matching starts at the beginning of the URL path.

前のリダイレクト ルール redirect-rule/(.*) の例では、正規表現の先頭にキャレット (^) がありません。In the earlier example with the redirect rule, redirect-rule/(.*), there's no carat (^) at the start of the regex. したがって、パスの redirect-rule/ の前にどのような文字があっても一致します。Therefore, any characters may precede redirect-rule/ in the path for a successful match.

パスPath 一致したものMatch
/redirect-rule/1234/5678 はいYes
/my-cool-redirect-rule/1234/5678 はいYes
/anotherredirect-rule/1234/5678 はいYes

書き換えルール ^rewrite-rule/(\d+)/(\d+) は、rewrite-rule/ で始まる場合のみパスと一致します。The rewrite rule, ^rewrite-rule/(\d+)/(\d+), only matches paths if they start with rewrite-rule/. 次の表では、一致の違いに注意してください。In the following table, note the difference in matching.

パスPath 一致したものMatch
/rewrite-rule/1234/5678 はいYes
/my-cool-rewrite-rule/1234/5678 いいえNo
/anotherrewrite-rule/1234/5678 いいえNo

式の ^rewrite-rule/ に続く部分に、2 つのキャプチャ グループ (\d+)/(\d+) があります。Following the ^rewrite-rule/ portion of the expression, there are two capture groups, (\d+)/(\d+). \d は、1 桁 (数字) に一致することを示します。The \d signifies match a digit (number). プラス記号 (+) は、直前の 1 つ以上の文字に一致することを意味します。The plus sign (+) means match one or more of the preceding character. そのため、URL は、数字とその後に続くスラッシュ、さらにその後に続く別の数字を含んでいる必要があります。Therefore, the URL must contain a number followed by a forward-slash followed by another number. これらのキャプチャ グループが $1 および $2 として書き換えられた URL に挿入されます。These capture groups are injected into the rewritten URL as $1 and $2. 書き換えルールの置換文字列は、クエリ文字列にキャプチャされたグループを配置します。The rewrite rule replacement string places the captured groups into the query string. /rewrite-rule/1234/5678 の要求されたパスは、/rewritten?var1=1234&var2=5678 でリソースを取得するように書き換えられます。The requested path of /rewrite-rule/1234/5678 is rewritten to obtain the resource at /rewritten?var1=1234&var2=5678. クエリ文字列が元の要求に存在する場合、URL が書き換えられるときに保持されます。If a query string is present on the original request, it's preserved when the URL is rewritten.

リソースを取得するためのサーバーへのラウンドトリップはありません。There's no round trip to the server to obtain the resource. リソースが存在する場合は、取得され、200 - OK 状態コードと共にクライアントに返されます。If the resource exists, it's fetched and returned to the client with a 200 - OK status code. クライアントはリダイレクトされていないため、ブラウザーのアドレス バーの URL は変更されません。Because the client isn't redirected, the URL in the browser's address bar doesn't change. クライアントは、URL の書き換え操作がサーバーで発生したことを検出できません。Clients can't detect that a URL rewrite operation occurred on the server.

注意

式内の照合ルールは計算量が多く、アプリの応答時間が長くなるので、可能な限り skipRemainingRules: true を使用します。Use skipRemainingRules: true whenever possible because matching rules is computationally expensive and increases app response time. 最も高速なアプリの応答を実現するには以下のようにします。For the fastest app response:

  • 一致する頻度が最も多いルールから一致頻度が最も少ないルールへの順番で書き換えルールを並べ替えます。Order rewrite rules from the most frequently matched rule to the least frequently matched rule.
  • 一致が発生し、追加の処理が必要ないときに残りのルールの処理をスキップします。Skip the processing of the remaining rules when a match occurs and no additional rule processing is required.

Apache mod_rewriteApache mod_rewrite

AddApacheModRewrite を使用して Apache mod_rewrite ルールを適用します。Apply Apache mod_rewrite rules with AddApacheModRewrite. ルール ファイルがアプリと共に展開されていることを確認します。Make sure that the rules file is deployed with the app. mod_rewrite ルールの情報と例については、「Apache mod_rewrite」を参照してください。For more information and examples of mod_rewrite rules, see Apache mod_rewrite.

ApacheModRewrite.txt ルール ファイルからルールを読み取るには、StreamReader を使用します。A StreamReader is used to read the rules from the ApacheModRewrite.txt rules file:

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 にリダイレクトします。The sample app redirects requests from /apache-mod-rules-redirect/(.\*) to /redirected?id=$1. 応答の状態コードは "302 -検出" です。The response status code is 302 - Found.

# Rewrite path with additional sub directory
RewriteRule ^/apache-mod-rules-redirect/(.*) /redirected?id=$1 [L,R=302]

元の要求: /apache-mod-rules-redirect/1234Original Request: /apache-mod-rules-redirect/1234

要求および応答を追跡する開発者ツールを備えたブラウザー ウィンドウ

ミドルウェアは、次の Apache mod_rewrite サーバー変数をサポートします。The middleware supports the following Apache mod_rewrite server variables:

  • CONN_REMOTE_ADDRCONN_REMOTE_ADDR
  • HTTP_ACCEPTHTTP_ACCEPT
  • HTTP_CONNECTIONHTTP_CONNECTION
  • HTTP_COOKIEHTTP_COOKIE
  • HTTP_FORWARDEDHTTP_FORWARDED
  • HTTP_HOSTHTTP_HOST
  • HTTP_REFERERHTTP_REFERER
  • HTTP_USER_AGENTHTTP_USER_AGENT
  • HTTPSHTTPS
  • IPV6IPV6
  • QUERY_STRINGQUERY_STRING
  • REMOTE_ADDRREMOTE_ADDR
  • REMOTE_PORTREMOTE_PORT
  • REQUEST_FILENAMEREQUEST_FILENAME
  • REQUEST_METHODREQUEST_METHOD
  • REQUEST_SCHEMEREQUEST_SCHEME
  • REQUEST_URIREQUEST_URI
  • SCRIPT_FILENAMESCRIPT_FILENAME
  • SERVER_ADDRSERVER_ADDR
  • SERVER_PORTSERVER_PORT
  • SERVER_PROTOCOLSERVER_PROTOCOL
  • TIMETIME
  • TIME_DAYTIME_DAY
  • TIME_HOURTIME_HOUR
  • TIME_MINTIME_MIN
  • TIME_MONTIME_MON
  • TIME_SECTIME_SEC
  • TIME_WDAYTIME_WDAY
  • TIME_YEARTIME_YEAR

IIS URL リライト モジュールのルールIIS URL Rewrite Module rules

IIS URL リライト モジュールに適用される同じルール セットを使用するには、AddIISUrlRewrite を使用します。To use the same rule set that applies to the IIS URL Rewrite Module, use AddIISUrlRewrite. ルール ファイルがアプリと共に展開されていることを確認します。Make sure that the rules file is deployed with the app. Windows Server IIS で実行されているときにミドルウェアでアプリの web.config ファイルを使用するように指定しないでください。Don't direct the middleware to use the app's web.config file when running on Windows Server IIS. IIS を使用する場合、IIS リライト モジュールとの競合を避けるため、これらのルールをアプリの web.config の外部に保存する必要があります。With IIS, these rules should be stored outside of the app's web.config file in order to avoid conflicts with the IIS Rewrite module. IIS URL リライト モジュールのルールの詳細と例については、「Using Url Rewrite Module 2.0」(URL リライト モジュール 2.0 の使用 ) と「URL Rewrite Module Configuration Reference」(URL リライト モジュール構成リファレンス) を参照してください。For more information and examples of IIS URL Rewrite Module rules, see Using Url Rewrite Module 2.0 and URL Rewrite Module Configuration Reference.

IISUrlRewrite.xml ルール ファイルからルールを読み取るには、StreamReader を使用します。A StreamReader is used to read the rules from the IISUrlRewrite.xml rules file:

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 に書き換えます。The sample app rewrites requests from /iis-rules-rewrite/(.*) to /rewritten?id=$1. 応答は、200 - OK 状態コードでクライアントに送信されます。The response is sent to the client with a 200 - OK status code.

<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/1234Original Request: /iis-rules-rewrite/1234

要求および応答を追跡する開発者ツールを備えたブラウザー ウィンドウ

望ましくない方法でアプリに影響するように構成されたサーバー レベル ルールを使用するアクティブな IIS リライト モジュールがある場合は、アプリに対して IIS リライト モジュールを無効にできます。If you have an active IIS Rewrite Module with server-level rules configured that would impact your app in undesirable ways, you can disable the IIS Rewrite Module for an app. 詳細については、「Disabling IIS modules」 (IIS モジュールの無効化) を参照してください。For more information, see Disabling IIS modules.

サポートされていない機能Unsupported features

ASP.NET Core 2.x でリリースされたミドルウェアは、次の IIS URL リライト モジュールの機能をサポートしていません。The middleware released with ASP.NET Core 2.x doesn't support the following IIS URL Rewrite Module features:

  • 送信ルールOutbound Rules
  • カスタム サーバー変数Custom Server Variables
  • ワイルドカードWildcards
  • LogRewrittenUrlLogRewrittenUrl

サポートされるサーバー変数Supported server variables

ミドルウェアは、次の IIS URL リライト モジュール サーバー変数をサポートします。The middleware supports the following IIS URL Rewrite Module server variables:

  • CONTENT_LENGTHCONTENT_LENGTH
  • CONTENT_TYPECONTENT_TYPE
  • HTTP_ACCEPTHTTP_ACCEPT
  • HTTP_CONNECTIONHTTP_CONNECTION
  • HTTP_COOKIEHTTP_COOKIE
  • HTTP_HOSTHTTP_HOST
  • HTTP_REFERERHTTP_REFERER
  • HTTP_URLHTTP_URL
  • HTTP_USER_AGENTHTTP_USER_AGENT
  • HTTPSHTTPS
  • LOCAL_ADDRLOCAL_ADDR
  • QUERY_STRINGQUERY_STRING
  • REMOTE_ADDRREMOTE_ADDR
  • REMOTE_PORTREMOTE_PORT
  • REQUEST_FILENAMEREQUEST_FILENAME
  • REQUEST_URIREQUEST_URI

注意

PhysicalFileProvider を介して IFileProvider を取得することもできます。You can also obtain an IFileProvider via a PhysicalFileProvider. このアプローチは、書き換えルール ファイルの場所に関する大きな柔軟性を提供する場合があります。This approach may provide greater flexibility for the location of your rewrite rules files. 書き換えルール ファイルを指定したパスでサーバーに導入されていることを確認してください。Make sure that your rewrite rules files are deployed to the server at the path you provide.

PhysicalFileProvider fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());

メソッド ベースのルールMethod-based rule

メソッド内で独自のルール ロジックを実装するには、Add を使用します。Use Add to implement your own rule logic in a method. AddRewriteContext を公開し、メソッドで HttpContext を使用できるようにします。Add exposes the RewriteContext, which makes available the HttpContext for use in your method. RewriteContext.Result は、追加のパイプライン処理の実行方法を決定します。The RewriteContext.Result determines how additional pipeline processing is handled. 次の表で説明する RuleResult フィールドのいずれかに値を設定します。Set the value to one of the RuleResult fields described in the following table.

コンテキストの書き換えの結果Rewrite context result アクションAction
RuleResult.ContinueRules (既定値)RuleResult.ContinueRules (default) ルールの適用を続けます。Continue applying rules.
RuleResult.EndResponse ルールの適用を停止し、応答を送信します。Stop applying rules and send the response.
RuleResult.SkipRemainingRules ルールの適用を停止し、次のミドルウェアにコンテキストを送信します。Stop applying rules and send the context to the next middleware.
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 で終了するパスの要求をリダイレクトするメソッドの例を示します。The sample app demonstrates a method that redirects requests for paths that end with .xml. /file.xml に対して要求が行われた場合、要求は /xmlfiles/file.xml にリダイレクトされます。If a request is made for /file.xml, the request is redirected to /xmlfiles/file.xml. 状態コードは "301 - 完全な移動" に設定されます。The status code is set to 301 - Moved Permanently. ブラウザーが /xmlfiles/file.xml に対する新しい要求を行うと、静的ファイル ミドルウェアはクライアントに wwwroot/xmlfiles フォルダーからファイルを提供します。When the browser makes a new request for /xmlfiles/file.xml, Static File Middleware serves the file to the client from the wwwroot/xmlfiles folder. リダイレクトの場合は、応答の状態コードを明示的に設定します。For a redirect, explicitly set the status code of the response. それ以外の場合は、200 - OK 状態コードが返され、クライアントでのリダイレクトは発生しません。Otherwise, a 200 - OK status code is returned, and the redirect doesn't occur on the client.

RewriteRules.cs: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 = StatusCodes.Status301MovedPermanently;
        context.Result = RuleResult.EndResponse;
        response.Headers[HeaderNames.Location] = 
            "/xmlfiles" + request.Path + request.QueryString;
    }
}

このアプローチでは、要求を書き換えることもできます。This approach can also rewrite requests. サンプル アプリでは、wwwroot フォルダーから file.txt テキスト ファイルを提供するためにテキスト ファイル要求のパスを書き換える処理が示されています。The sample app demonstrates rewriting the path for any text file request to serve the file.txt text file from the wwwroot folder. 静的ファイル ミドルウェアでは、更新された要求パスに基づいてファイルが提供されます。Static File Middleware serves the file based on the updated request path:

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: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-based rule

IRule インターフェイスを実装するクラス内のルール ロジックを使用するには、Add を使用します。Use Add to use rule logic in a class that implements the IRule interface. IRule では、メソッド ベースのルール アプローチを使用する場合より高い柔軟性が提供されます。IRule provides greater flexibility over using the method-based rule approach. 実装クラスには、ApplyRule メソッドに対してパラメーターを渡すことができるコンストラクターを含めることができます。Your implementation class may include a constructor that allows you can pass in parameters for the ApplyRule method.

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}"));
}

サンプル アプリの extensionnewPath のパラメーターの値は、いくつかの条件を満たすかチェックされます。The values of the parameters in the sample app for the extension and the newPath are checked to meet several conditions. extension は、値を含んでいる必要があり、値は .png.jpg、または .gif でなければなりません。The extension must contain a value, and the value must be .png, .jpg, or .gif. newPath が有効ではない場合、ArgumentException がスローされます。If the newPath isn't valid, an ArgumentException is thrown. image.png に対して行われた要求は、/png-images/image.png にリダイレクトされます。If a request is made for image.png, the request is redirected to /png-images/image.png. image.jpg に対して行われた要求は、/jpg-images/image.jpg にリダイレクトされます。If a request is made for image.jpg, the request is redirected to /jpg-images/image.jpg. 状態コードは "301 - 完全な移動" に設定され、context.Result はルールの処理を停止して応答を送信するように設定されます。The status code is set to 301 - Moved Permanently, and the context.Result is set to stop processing rules and send the response.

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 = StatusCodes.Status301MovedPermanently;
            context.Result = RuleResult.EndResponse;
            response.Headers[HeaderNames.Location] = 
                _newPath + request.Path + request.QueryString;
        }
    }
}

元の要求: /image.pngOriginal Request: /image.png

image.png の要求および応答を追跡する開発者ツールを備えたブラウザー ウィンドウ

元の要求: /image.jpgOriginal Request: /image.jpg

image.jpg の要求および応答を追跡する開発者ツールを備えたブラウザー ウィンドウ

正規表現の例Regex examples

GoalGoal 正規表現文字列とRegex String &
一致の例Match Example
置換文字列とReplacement String &
出力の例Output Example
クエリ文字列内のパスを書き換えるRewrite path into querystring ^path/(.*)/(.*)
/path/abc/123
path?var1=$1&var2=$2
/path?var1=abc&var2=123
末尾のスラッシュを除去するStrip trailing slash (.*)/$
/path/
$1
/path
末尾のスラッシュを強制するEnforce trailing slash (.*[^/])$
/path
$1/
/path/
特定の要求を書き換えを回避するAvoid rewriting specific requests ^(.*)(?<!\.axd)$ または ^(?!.*\.axd$)(.*)$^(.*)(?<!\.axd)$ or ^(?!.*\.axd$)(.*)$
はい: /resource.htmYes: /resource.htm
いいえ: /resource.axdNo: /resource.axd
rewritten/$1
/rewritten/resource.htm
/resource.axd
URL セグメントを再配置するRearrange URL segments path/(.*)/(.*)/(.*)
path/1/2/3
path/$3/$2/$1
path/3/2/1
URL セグメントを置き換えるReplace a URL segment ^(.*)/segment2/(.*)
/segment1/segment2/segment3
$1/replaced/$2
/segment1/replaced/segment3

その他の技術情報Additional resources