ASP.NET Core에서 URL 재작성 미들웨어URL Rewriting Middleware in ASP.NET Core

작성자: Luke LathamMikael MengistuBy Luke Latham and 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 재작성은 하나 이상의 미리 정의된 규칙을 기반으로 하는 요청 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.
  • 여러 앱 또는 한 앱의 여러 영역 간에 요청 처리를 분리합니다.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을 표시합니다.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 재작성 모듈의 IsFileIsDirectory 제약 조건과 같은 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.

패키지Package

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. RewriteOptionsUseRewriter를 사용하여 요청 파이프라인에 추가될 때 URL 재작성 미들웨어에 전달됩니다.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로 리디렉션하도록 허용합니다.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. 두 번째 매개 변수는 대체 문자열입니다.The second parameter is the replacement string. 필요한 경우 세 번째 매개 변수로 상태 코드를 지정할 수 있습니다.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:

  • 두 번째 요청에서 앱의 200 - 정상 응답을 받습니다.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

요청 및 응답을 추적하는 개발자 도구가 있는 브라우저 창

표현식에서 괄호로 둘러쌓인 부분을 캡처 그룹(Capture Group) 이라고 합니다.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의 마지막 두 세그먼트, 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로 얻을 수 있으며, 이는 정규식에 포함된 캡처 그룹에 대해 순차적으로 계속됩니다.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 하나뿐입니다.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

AddRedirectToHttps를 사용하여 HTTPS 프로토콜을 통해 HTTP 요청을 동일한 호스트 및 경로로 리디렉션할 수 있습니다.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);
}

AddRedirectToHttpsPermanent를 사용하여 443 포트의 HTTPS 프로토콜을 통해 안전하지 않은 요청을 동일한 호스트 및 경로로 리디렉션합니다.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/secureOriginal Request using AddRedirectToHttps(301, 5001): http://localhost:5000/secure

요청 및 응답을 추적하는 개발자 도구가 있는 브라우저 창

AddRedirectToHttpsPermanent에 대한 원본 요청: http://localhost:5000/secureOriginal 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. 두 번째 매개 변수는 대체 문자열입니다.The second parameter is the replacement string. 세 번째 매개 변수, 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/ 부분 뒤에는 계속해서 두 개의 캡처 그룹, (\d+)/(\d+)이 위치해 있습니다.Following the ^rewrite-rule/ portion of the expression, there are two capture groups, (\d+)/(\d+). 여기서 \d숫자 하나와 일치함을 뜻합니다.The \d signifies match a digit (number). 그리고 더하기 기호(+)는 앞의 문자와 한 번 이상 일치함을 나타냅니다.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 - 정상 상태 코드와 함께 클라이언트에 반환합니다.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.

StreamReaderApacheModRewrite.txt 규칙 파일에서 규칙을 읽는 데 사용됩니다.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 재작성 모듈 규칙에 대한 보다 자세한 내용 및 예제는 URL 재작성 모듈 2.0 사용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.

StreamReaderIISUrlRewrite.xml 규칙 파일에서 규칙을 읽는 데 사용됩니다.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 - 정상 상태 코드와 함께 클라이언트에 전송됩니다.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. 보다 자세한 내용은 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. Add는 메서드에서 사용할 HttpContext를 사용할 수 있게 하는 RewriteContext를 공개합니다.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.

RewriteContext.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 - 정상 상태 코드가 반환되고 클라이언트에서 리디렉션이 수행되지 않습니다.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

Add를 사용하여 IRule 인터페이스를 구현하는 클래스에서 규칙 논리를 사용합니다.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 재작성은 하나 이상의 미리 정의된 규칙을 기반으로 하는 요청 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.
  • 여러 앱 또는 한 앱의 여러 영역 간에 요청 처리를 분리합니다.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을 표시합니다.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 재작성 모듈의 IsFileIsDirectory 제약 조건과 같은 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.

패키지Package

프로젝트에 미들웨어를 포함시키려면 Microsoft.AspNetCore.Rewrite 패키지가 포함된 프로젝트 파일의 Microsoft.AspNetCore.App 메타패키지에 패키지 참조를 추가합니다.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. RewriteOptionsUseRewriter를 사용하여 요청 파이프라인에 추가될 때 URL 재작성 미들웨어에 전달됩니다.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로 리디렉션하도록 허용합니다.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. 두 번째 매개 변수는 대체 문자열입니다.The second parameter is the replacement string. 필요한 경우 세 번째 매개 변수로 상태 코드를 지정할 수 있습니다.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:

  • 두 번째 요청에서 앱의 200 - 정상 응답을 받습니다.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

요청 및 응답을 추적하는 개발자 도구가 있는 브라우저 창

표현식에서 괄호로 둘러쌓인 부분을 캡처 그룹(Capture Group) 이라고 합니다.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의 마지막 두 세그먼트, 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로 얻을 수 있으며, 이는 정규식에 포함된 캡처 그룹에 대해 순차적으로 계속됩니다.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 하나뿐입니다.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

AddRedirectToHttps를 사용하여 HTTPS 프로토콜을 통해 HTTP 요청을 동일한 호스트 및 경로로 리디렉션할 수 있습니다.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);
}

AddRedirectToHttpsPermanent를 사용하여 443 포트의 HTTPS 프로토콜을 통해 안전하지 않은 요청을 동일한 호스트 및 경로로 리디렉션합니다.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/secureOriginal Request using AddRedirectToHttps(301, 5001): http://localhost:5000/secure

요청 및 응답을 추적하는 개발자 도구가 있는 브라우저 창

AddRedirectToHttpsPermanent에 대한 원본 요청: http://localhost:5000/secureOriginal 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. 두 번째 매개 변수는 대체 문자열입니다.The second parameter is the replacement string. 세 번째 매개 변수, 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/ 부분 뒤에는 계속해서 두 개의 캡처 그룹, (\d+)/(\d+)이 위치해 있습니다.Following the ^rewrite-rule/ portion of the expression, there are two capture groups, (\d+)/(\d+). 여기서 \d숫자 하나와 일치함을 뜻합니다.The \d signifies match a digit (number). 그리고 더하기 기호(+)는 앞의 문자와 한 번 이상 일치함을 나타냅니다.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 - 정상 상태 코드와 함께 클라이언트에 반환합니다.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.

StreamReaderApacheModRewrite.txt 규칙 파일에서 규칙을 읽는 데 사용됩니다.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 재작성 모듈 규칙에 대한 보다 자세한 내용 및 예제는 URL 재작성 모듈 2.0 사용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.

StreamReaderIISUrlRewrite.xml 규칙 파일에서 규칙을 읽는 데 사용됩니다.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 - 정상 상태 코드와 함께 클라이언트에 전송됩니다.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. 보다 자세한 내용은 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. Add는 메서드에서 사용할 HttpContext를 사용할 수 있게 하는 RewriteContext를 공개합니다.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.

RewriteContext.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 - 정상 상태 코드가 반환되고 클라이언트에서 리디렉션이 수행되지 않습니다.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

Add를 사용하여 IRule 인터페이스를 구현하는 클래스에서 규칙 논리를 사용합니다.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