Intergiciel (middleware) de réécriture d’URL dans ASP.NET CoreURL Rewriting Middleware in ASP.NET Core

Par Luke Latham et Mikael MengistuBy Luke Latham and Mikael Mengistu

Pour obtenir la version 1.1 de cette rubrique, téléchargez URL Rewriting Middleware in ASP.NET Core (version 1.1, PDF).For the 1.1 version of this topic, download URL Rewriting Middleware in ASP.NET Core (version 1.1, PDF).

Ce document présente la réécriture d’URL avec des instructions sur la façon d’utiliser l’intergiciel (middleware) de réécriture d’URL dans les applications ASP.NET Core.This document introduces URL rewriting with instructions on how to use URL Rewriting Middleware in ASP.NET Core apps.

La réécriture d’URL consiste à modifier des URL de requête en fonction d’une ou de plusieurs règles prédéfinies.URL rewriting is the act of modifying request URLs based on one or more predefined rules. La réécriture d’URL crée une abstraction entre les emplacements des ressources et leurs adresses pour que les emplacements et les adresses ne soient pas étroitement liés.URL rewriting creates an abstraction between resource locations and their addresses so that the locations and addresses aren't tightly linked. La réécriture d’URL est utile dans plusieurs scénarios pour :URL rewriting is valuable in several scenarios to:

  • Déplacer ou remplacer de façon temporaire ou permanente les ressources d’un serveur, tout en conservant des localisateurs stables pour ces ressources.Move or replace server resources temporarily or permanently and maintain stable locators for those resources.
  • Diviser le traitement des requêtes entre différentes applications ou entre différentes parties d’une même application.Split request processing across different apps or across areas of one app.
  • Supprimer, ajouter ou réorganiser les segments d’URL sur des requêtes entrantes.Remove, add, or reorganize URL segments on incoming requests.
  • Optimiser les URL publiques pour l’optimisation du référencement d’un site auprès d’un moteur de recherche (SEO).Optimize public URLs for Search Engine Optimization (SEO).
  • Permettre l’utilisation des URL publiques conviviales pour aider les visiteurs à prédire le contenu retourné en demandant une ressource.Permit the use of friendly public URLs to help visitors predict the content returned by requesting a resource.
  • Rediriger des requêtes non sécurisées vers des points de terminaison sécurisés.Redirect insecure requests to secure endpoints.
  • Empêcher les liaisons à chaud, où un site externe utilise une ressource statique hébergée sur un autre site en liant la ressource dans son propre contenu.Prevent hotlinking, where an external site uses a hosted static asset on another site by linking the asset into its own content.

Notes

La réécriture d’URL peut réduire les performances d’une application.URL rewriting can reduce the performance of an app. Quand c’est possible, limitez le nombre et la complexité des règles.Where feasible, limit the number and complexity of rules.

Affichez ou téléchargez l’exemple de code (procédure de téléchargement)View or download sample code (how to download)

Redirection d’URL et réécriture d’URLURL redirect and URL rewrite

La différence de formulation entre la redirection d’URL et la réécriture d’URL est subtile, mais elle a des implications importantes sur la fourniture de ressources aux clients.The difference in wording between URL redirect and URL rewrite is subtle but has important implications for providing resources to clients. L’intergiciel de réécriture d’URL d’ASP.NET Core est capables de répondre aux besoins des deux.ASP.NET Core's URL Rewriting Middleware is capable of meeting the need for both.

Une redirection d’URL implique une opération côté client, où le client est invité à accéder à une ressource à une autre adresse que celle demandée à l’origine.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. Ceci nécessite un aller-retour avec le serveur.This requires a round trip to the server. L’URL de redirection retournée au client s’affiche dans la barre d’adresse du navigateur quand le client effectue une nouvelle requête pour la ressource.The redirect URL returned to the client appears in the browser's address bar when the client makes a new request for the resource.

Si /resource est redirigée vers /different-resource, le serveur répond que le client doit obtenir la ressource à l’emplacement /different-resource avec un code d’état indiquant que la redirection est temporaire ou permanente.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.

Un point de terminaison de service WebAPI a été changé temporairement de la version 1 (v1) à la version 2 (v2) sur le serveur.

Lors de la redirection des requêtes vers une URL différente, indiquez si la redirection est permanente ou temporaire en spécifiant le code d’état avec la réponse :When redirecting requests to a different URL, indicate whether the redirect is permanent or temporary by specifying the status code with the response:

  • Le code d’état 301 - Déplacé de façon permanente est utilisé quand la ressource a une nouvelle URL permanente et que vous voulez indiquer au client que toutes les requêtes futures pour la ressource doivent utiliser la nouvelle 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. Le client peut mettre en cache et réutiliser la réponse quand un code d’état 301 est reçu.The client may cache and reuse the response when a 301 status code is received.

  • Le code d’état 302 - Trouvé est utilisé quand la redirection est temporaire ou généralement susceptible d’être modifiée.The 302 - Found status code is used where the redirection is temporary or generally subject to change. Le code d’état 302 indique au client de ne pas stocker l’URL et de ne plus l’utiliser.The 302 status code indicates to the client not to store the URL and use it in the future.

Pour plus d’informations sur les codes d’état, consultez RFC 2616 : Status Code Definitions.For more information on status codes, see RFC 2616: Status Code Definitions.

Une réécriture d’URL est une opération côté serveur qui fournit une ressource à partir d’une adresse de ressource différente de celle demandée par le client.A URL rewrite is a server-side operation that provides a resource from a different resource address than the client requested. La réécriture d’URL ne nécessite pas d’aller-retour avec le serveur.Rewriting a URL doesn't require a round trip to the server. L’URL réécrite n’est pas retournée au client et n’apparaît pas dans la barre d’adresse du navigateur.The rewritten URL isn't returned to the client and doesn't appear in the browser's address bar.

Si /resource est réécrite en /different-resource, le serveur récupère la ressource en interne à l’emplacement /different-resource.If /resource is rewritten to /different-resource, the server internally fetches and returns the resource at /different-resource.

Même si le client peut récupérer la ressource à l’URL réécrite, il n’est pas informé que la ressource existe à l’URL réécrite quand il fait sa requête et reçoit la réponse.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.

Un point de terminaison de service WebAPI a été changé de la version 1 (v1) à la version 2 (v2) sur le serveur.

Exemple d’application de réécriture d’URLURL rewriting sample app

Vous pouvez explorer les fonctionnalités du middleware de réécriture d’URL avec l’exemple d’application.You can explore the features of the URL Rewriting Middleware with the sample app. L’application applique des règles de redirection et de réécriture, et montre l’URL redirigée ou réécrite pour plusieurs scénarios.The app applies redirect and rewrite rules and shows the redirected or rewritten URL for several scenarios.

Quand utiliser l’intergiciel (middleware) de réécriture d’URLWhen to use URL Rewriting Middleware

Utilisez le middleware de réécriture d’URL quand vous ne pouvez pas utiliser les approches suivantes :Use URL Rewriting Middleware when you're unable to use the following approaches:

Utilisez aussi le middleware quand l’application est hébergée sur le serveur HTTP.sys (anciennement appelé WebListener).Also, use the middleware when the app is hosted on HTTP.sys server (formerly called WebListener).

Les principales raisons d’utiliser les technologies de réécriture d’URL basée sur le serveur dans IIS, Apache et Nginx sont les suivantes :The main reasons to use the server-based URL rewriting technologies in IIS, Apache, and Nginx are:

  • Le middleware ne prend pas en charge toutes les fonctionnalités de ces modules.The middleware doesn't support the full features of these modules.

    Certaines des fonctionnalités des modules serveur ne fonctionnent pas avec les projets ASP.NET Core, comme les contraintes IsFile et IsDirectory du module Réécriture IIS.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. Dans ces scénarios, utilisez plutôt l’intergiciel.In these scenarios, use the middleware instead.

  • Les performances du middleware ne correspondent probablement pas à celles des modules.The performance of the middleware probably doesn't match that of the modules.

    Mener des tests de performances est la seule façon de savoir exactement quelle approche dégrade le plus les performances ou si la dégradation des performances est négligeable.Benchmarking is the only way to know for sure which approach degrades performance the most or if degraded performance is negligible.

PackagePackage

Pour inclure le middleware dans votre projet, ajoutez une référence de package au métapackage Microsoft.AspNetCore.App dans le fichier projet, qui contient le package 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.

Quand vous n’utilisez pas le métapackage Microsoft.AspNetCore.App, ajoutez une référence de projet au package Microsoft.AspNetCore.Rewrite.When not using the Microsoft.AspNetCore.App metapackage, add a project reference to the Microsoft.AspNetCore.Rewrite package.

Extension et optionsExtension and options

Établissez des règles de réécriture et de redirection d’URL en créant une instance de la classe RewriteOptions avec des méthodes d’extension pour chacune de vos règles de réécriture.Establish URL rewrite and redirect rules by creating an instance of the RewriteOptions class with extension methods for each of your rewrite rules. Chaînez plusieurs règles dans l’ordre dans lequel vous voulez qu’elles soient traitées.Chain multiple rules in the order that you would like them processed. Les RewriteOptions sont passées dans le middleware de réécriture d’URL quand il est ajouté au pipeline de requête avec UseRewriter :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}"));
}

Redirection de demandes non-www en demandes wwwRedirect non-www to www

Trois options permettent à l’application de rediriger des demandes non-www en demandes www :Three options permit the app to redirect non-www requests to www:

Redirection d’URLURL redirect

Utilisez AddRedirect pour rediriger des requêtes.Use AddRedirect to redirect requests. Le premier paramètre contient votre expression régulière pour la mise en correspondance sur le chemin de l’URL entrante.The first parameter contains your regex for matching on the path of the incoming URL. Le deuxième paramètre est la chaîne de remplacement.The second parameter is the replacement string. Le troisième paramètre, le cas échéant, spécifie le code d’état.The third parameter, if present, specifies the status code. Si vous ne spécifiez pas le code d’état, sa valeur par défaut est 302 - Trouvé, ce qui indique que la ressource est temporairement déplacée ou remplacée.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}"));
}

Dans un navigateur dans lequel les outils de développement sont activés, effectuez une requête à l’exemple d’application avec le chemin /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. L’expression régulière établit une correspondance avec le chemin de la requête sur redirect-rule/(.*), et le chemin est remplacé par /redirected/1234/5678.The regex matches the request path on redirect-rule/(.*), and the path is replaced with /redirected/1234/5678. L’URL de redirection est renvoyée au client avec le code d’état 302 - Trouvé.The redirect URL is sent back to the client with a 302 - Found status code. Le navigateur effectue une nouvelle requête à l’URL de redirection, qui apparaît dans la barre d’adresse du navigateur.The browser makes a new request at the redirect URL, which appears in the browser's address bar. Comme aucune règle de l’exemple d’application ne correspond sur l’URL de redirection :Since no rules in the sample app match on the redirect URL:

  • La deuxième requête reçoit une réponse 200 - OK de l’application.The second request receives a 200 - OK response from the app.
  • Le corps de la réponse montre l’URL de redirection.The body of the response shows the redirect URL.

Un aller-retour est effectué avec le serveur quand une URL est redirigée.A round trip is made to the server when a URL is redirected.

Avertissement

Soyez prudent lors de l’établissement de règles de redirection.Be cautious when establishing redirect rules. Les règles de redirection sont évaluées à chaque requête effectuée à l’application, notamment après une redirection.Redirect rules are evaluated on every request to the app, including after a redirect. Il est facile de créer accidentellement une boucle de redirections infinies.It's easy to accidentally create a loop of infinite redirects.

Requête d’origine : /redirect-rule/1234/5678Original Request: /redirect-rule/1234/5678

Fenêtre de navigateur avec les requêtes et les réponses suivies par les Outils de développement

La partie de l’expression entre parenthèses est appelée groupe de capture.The part of the expression contained within parentheses is called a capture group. Le point (.) de l’expression signifie mettre en correspondance n’importe quel caractère.The dot (.) of the expression means match any character. L’astérisque (*) indique mettre en correspondance zéro occurrence ou plus du caractère précédent.The asterisk (*) indicates match the preceding character zero or more times. Par conséquent, les deux derniers segments de chemin de l’URL, 1234/5678, sont capturés par le groupe de capture (.*).Therefore, the last two path segments of the URL, 1234/5678, are captured by capture group (.*). Toute valeur fournie dans l’URL de la requête après redirect-rule/ est capturée par ce groupe de capture unique.Any value you provide in the request URL after redirect-rule/ is captured by this single capture group.

Dans la chaîne de remplacement, les groupes capturés sont injectés dans la chaîne avec le signe dollar ($) suivi du numéro de séquence de la capture.In the replacement string, captured groups are injected into the string with the dollar sign ($) followed by the sequence number of the capture. La valeur du premier groupe de capture est obtenue avec $1, la deuxième avec $2, et ainsi de suite en séquence pour les groupes de capture de votre expression régulière.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. Comme il n’y a qu’un seul groupe capturé dans l’expression régulière de la règle de redirection de l’exemple d’application, un seul groupe est injecté dans la chaîne de remplacement, à savoir $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. Quand la règle est appliquée, l’URL devient /redirected/1234/5678.When the rule is applied, the URL becomes /redirected/1234/5678.

Redirection d’URL vers un point de terminaison sécuriséURL redirect to a secure endpoint

Utilisez AddRedirectToHttps pour rediriger les requêtes HTTP vers le même hôte et le même chemin avec le protocole HTTPS.Use AddRedirectToHttps to redirect HTTP requests to the same host and path using the HTTPS protocol. Si le code d’état n’est pas fourni, le middleware utilise par défaut 302 - Trouvé.If the status code isn't supplied, the middleware defaults to 302 - Found. Si le port n’est pas fourni :If the port isn't supplied:

  • Le middleware utilise par défaut null.The middleware defaults to null.
  • Le schéma change en https (protocole HTTPS), et le client accède à la ressource sur le port 443.The scheme changes to https (HTTPS protocol), and the client accesses the resource on port 443.

L’exemple suivant montre comment définir le code d’état sur 301 - Déplacé de façon permanente et changer le port en 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);
}

Utilisez AddRedirectToHttpsPermanent pour rediriger les requêtes non sécurisées vers le même hôte et le même chemin avec le protocole HTTPS sécurisé sur le port 443.Use AddRedirectToHttpsPermanent to redirect insecure requests to the same host and path with secure HTTPS protocol on port 443. Le middleware définit le code d’état sur 301 - Déplacé de façon permanente.The middleware sets the status code to 301 - Moved Permanently.

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

    app.UseRewriter(options);
}

Notes

Si vous effectuez une redirection vers un point de terminaison sécurisé et que vous n’avez pas besoin de règles de redirection supplémentaires, nous vous recommandons d’utiliser le middleware de redirection HTTPS.When redirecting to a secure endpoint without the requirement for additional redirect rules, we recommend using HTTPS Redirection Middleware. Pour plus d’informations, consultez la rubrique Appliquer HTTPS.For more information, see the Enforce HTTPS topic.

L’exemple d’application peut montrer comment utiliser AddRedirectToHttps ou AddRedirectToHttpsPermanent.The sample app is capable of demonstrating how to use AddRedirectToHttps or AddRedirectToHttpsPermanent. Ajoutez la méthode d’extension à RewriteOptions.Add the extension method to the RewriteOptions. Effectuez une requête non sécurisée à l’application à n’importe quelle URL.Make an insecure request to the app at any URL. Ignorez l’avertissement de sécurité du navigateur indiquant que le certificat auto-signé n’est pas approuvé ou créez une exception pour approuver le certificat.Dismiss the browser security warning that the self-signed certificate is untrusted or create an exception to trust the certificate.

Requête d’origine utilisant AddRedirectToHttps(301, 5001) : http://localhost:5000/secureOriginal Request using AddRedirectToHttps(301, 5001): http://localhost:5000/secure

Fenêtre de navigateur avec les requêtes et les réponses suivies par les Outils de développement

Requête d’origine utilisant AddRedirectToHttpsPermanent : http://localhost:5000/secureOriginal Request using AddRedirectToHttpsPermanent: http://localhost:5000/secure

Fenêtre de navigateur avec les requêtes et les réponses suivies par les Outils de développement

Réécriture d’URLURL rewrite

Utilisez AddRewrite pour créer une règle pour la réécriture d’URL.Use AddRewrite to create a rule for rewriting URLs. Le premier paramètre contient l’expression régulière pour la mise en correspondance sur le chemin de l’URL entrante.The first parameter contains the regex for matching on the incoming URL path. Le deuxième paramètre est la chaîne de remplacement.The second parameter is the replacement string. Le troisième paramètre, skipRemainingRules: {true|false}, indique à l’intergiciel d’ignorer, ou non, les règles de réécriture supplémentaires si la règle actuelle est appliquée.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}"));
}

Requête d’origine : /rewrite-rule/1234/5678Original Request: /rewrite-rule/1234/5678

Fenêtre de navigateur avec la requête et la réponse suivies par les Outils de développement

Le caret (^) au début de l’expression signifie que la correspondance commence au début du chemin de l’URL.The carat (^) at the beginning of the expression means that matching starts at the beginning of the URL path.

Dans l’exemple précédent avec la règle de redirection, redirect-rule/(.*), il n’existe pas de caret (^) au début de l’expression régulière.In the earlier example with the redirect rule, redirect-rule/(.*), there's no carat (^) at the start of the regex. Ainsi, n’importe quel caractère peut précéder redirect-rule/ dans le chemin pour qu’une correspondance soit établie.Therefore, any characters may precede redirect-rule/ in the path for a successful match.

Chemin d’accèsPath Faire correspondre àMatch
/redirect-rule/1234/5678 OuiYes
/my-cool-redirect-rule/1234/5678 OuiYes
/anotherredirect-rule/1234/5678 OuiYes

La règle de réécriture, ^rewrite-rule/(\d+)/(\d+), établit une correspondance uniquement avec des chemins d’accès s’ils commencent par rewrite-rule/.The rewrite rule, ^rewrite-rule/(\d+)/(\d+), only matches paths if they start with rewrite-rule/. Dans le tableau suivant, notez la différence de correspondance.In the following table, note the difference in matching.

Chemin d’accèsPath Faire correspondre àMatch
/rewrite-rule/1234/5678 OuiYes
/my-cool-rewrite-rule/1234/5678 NonNo
/anotherrewrite-rule/1234/5678 NonNo

À la suite de la partie ^rewrite-rule/ de l’expression se trouvent deux groupes de capture, (\d+)/(\d+).Following the ^rewrite-rule/ portion of the expression, there are two capture groups, (\d+)/(\d+). \d signifie établir une correspondance avec un chiffre (nombre).The \d signifies match a digit (number). Le signe plus (+) signifie établir une correspondance avec une ou plusieurs occurrences du caractère précédent.The plus sign (+) means match one or more of the preceding character. Par conséquent, l’URL doit contenir un nombre suivi d’une barre oblique, elle-même suivie d’un autre nombre.Therefore, the URL must contain a number followed by a forward-slash followed by another number. Ces groupes sont injectés dans l’URL réécrite sous la forme $1 et $2.These capture groups are injected into the rewritten URL as $1 and $2. La chaîne de remplacement de la règle de réécriture place les groupes capturés dans la chaîne de requête.The rewrite rule replacement string places the captured groups into the query string. Le chemin demandé /rewrite-rule/1234/5678 est réécrit pour obtenir la ressource à l’emplacement /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. Si une chaîne de requête est présente dans la requête d’origine, elle est conservée lors de la réécriture de l’URL.If a query string is present on the original request, it's preserved when the URL is rewritten.

Il n’y a pas d’aller-retour avec le serveur pour obtenir la ressource.There's no round trip to the server to obtain the resource. Si la ressource existe, elle est récupérée et retournée au client avec le code d’état 200 - OK.If the resource exists, it's fetched and returned to the client with a 200 - OK status code. Comme le client n’est pas redirigé, l’URL dans la barre d’adresse du navigateur ne change pas.Because the client isn't redirected, the URL in the browser's address bar doesn't change. Les clients ne peuvent pas détecter qu’une opération de réécriture d’URL s’est produite sur le serveur.Clients can't detect that a URL rewrite operation occurred on the server.

Notes

Quand c’est possible, utilisez skipRemainingRules: true, car la mise en correspondance de règles est un processus gourmand en ressources qui augmente le temps de réponse de l’application.Use skipRemainingRules: true whenever possible because matching rules is computationally expensive and increases app response time. Pour obtenir la réponse d’application la plus rapide :For the fastest app response:

  • Classez vos règles de réécriture en partant de la règle la plus souvent mise en correspondance jusqu’à la règle la moins souvent mise en correspondance.Order rewrite rules from the most frequently matched rule to the least frequently matched rule.
  • Ignorez le traitement des règles restantes quand une correspondance est trouvée et qu’aucun traitement de règle supplémentaire n’est nécessaire.Skip the processing of the remaining rules when a match occurs and no additional rule processing is required.

Apache mod_rewriteApache mod_rewrite

Appliquez des règles Apache mod_rewrite avec AddApacheModRewrite.Apply Apache mod_rewrite rules with AddApacheModRewrite. Vérifiez que le fichier de règles est déployé avec l’application.Make sure that the rules file is deployed with the app. Pour obtenir plus d’informations et des exemples de règles mod_rewrite, consultez Apache mod_rewrite.For more information and examples of mod_rewrite rules, see Apache mod_rewrite.

Un StreamReader est utilisé pour lire les règles dans le fichier de règles ApacheModRewrite.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}"));
}

L’exemple d’application redirige les requêtes de /apache-mod-rules-redirect/(.\*) vers /redirected?id=$1.The sample app redirects requests from /apache-mod-rules-redirect/(.\*) to /redirected?id=$1. Le code d’état de la réponse est 302 - Trouvé.The response status code is 302 - Found.

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

Requête d’origine : /apache-mod-rules-redirect/1234Original Request: /apache-mod-rules-redirect/1234

Fenêtre de navigateur avec les requêtes et les réponses suivies par les Outils de développement

L’intergiciel prend en charge les variables de serveur Apache mod_rewrite suivantes :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

Règles du module de réécriture d’URL IISIIS URL Rewrite Module rules

Pour utiliser le même ensemble de règles que celui qui s’applique au module de réécriture d’URL IIS, utilisez AddIISUrlRewrite.To use the same rule set that applies to the IIS URL Rewrite Module, use AddIISUrlRewrite. Vérifiez que le fichier de règles est déployé avec l’application.Make sure that the rules file is deployed with the app. N’indiquez pas au middleware d’utiliser le fichier web.config de l’application en cas d’exécution sur Windows Server IIS.Don't direct the middleware to use the app's web.config file when running on Windows Server IIS. Avec IIS, ces règles doivent être stockées en dehors du fichier web.config de l’application pour éviter les conflits avec le module de réécriture IIS.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. Pour obtenir plus d’informations et des exemples de règles du module de réécriture d’URL IIS, consultez Utilisation du module de réécriture d’URL 2.0 et Informations de référence sur la configuration du module de réécriture d’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.

Un StreamReader est utilisé pour lire les règles dans le fichier de règles IISUrlRewrite.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}"));
}

L’exemple d’application réécrit les requêtes de /iis-rules-rewrite/(.*) vers /rewritten?id=$1.The sample app rewrites requests from /iis-rules-rewrite/(.*) to /rewritten?id=$1. La réponse est envoyée au client avec le code d’état 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>

Requête d’origine : /iis-rules-rewrite/1234Original Request: /iis-rules-rewrite/1234

Fenêtre de navigateur avec la requête et la réponse suivies par les Outils de développement

Si vous avez un module de réécriture IIS actif pour lequel des règles au niveau du serveur qui affecteraient de façon non souhaitée votre application sont configurées, vous pouvez le désactiver pour une application.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. Pour plus d’informations, consultez Désactivation de modules IIS.For more information, see Disabling IIS modules.

Fonctionnalités non prises en chargeUnsupported features

L’intergiciel intégré à ASP.NET Core 2.x ne prend pas en charge les fonctionnalités de module de réécriture d’URL IIS suivantes :The middleware released with ASP.NET Core 2.x doesn't support the following IIS URL Rewrite Module features:

  • Règles de trafic sortantOutbound Rules
  • Variables serveur personnaliséesCustom Server Variables
  • Caractères génériquesWildcards
  • LogRewrittenUrlLogRewrittenUrl

Variables serveur prises en chargeSupported server variables

L’intergiciel prend en charge les variables serveur du module de réécriture d’URL IIS suivantes :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

Notes

Vous pouvez également obtenir un IFileProvider par le biais d’un PhysicalFileProvider.You can also obtain an IFileProvider via a PhysicalFileProvider. Cette approche peut fournir davantage de flexibilité pour l’emplacement de vos fichiers de règles de réécriture.This approach may provide greater flexibility for the location of your rewrite rules files. Vérifiez que vos fichiers de règles de réécriture sont déployés sur le serveur dans le chemin que vous fournissez.Make sure that your rewrite rules files are deployed to the server at the path you provide.

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

Règle basée sur une méthodeMethod-based rule

Utilisez Add pour implémenter votre propre logique de règle dans une méthode.Use Add to implement your own rule logic in a method. Add expose RewriteContext, ce qui rend HttpContext disponible pour une utilisation dans votre méthode.Add exposes the RewriteContext, which makes available the HttpContext for use in your method. RewriteContext.Result détermine la façon dont le traitement du pipeline supplémentaire est géré.The RewriteContext.Result determines how additional pipeline processing is handled. Définissez la valeur sur un des champs RuleResult décrits dans le tableau suivant.Set the value to one of the RuleResult fields described in the following table.

RewriteContext.Result ActionAction
RuleResult.ContinueRules (valeur par défaut)RuleResult.ContinueRules (default) Continuer à appliquer les règles.Continue applying rules.
RuleResult.EndResponse Cesser d’appliquer les règles et envoyer la réponse.Stop applying rules and send the response.
RuleResult.SkipRemainingRules Cesser d’appliquer les règles et envoyer le contexte au middleware suivant.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}"));
}

L’exemple d’application présente une méthode qui redirige les requêtes de chemins qui se terminent par .xml.The sample app demonstrates a method that redirects requests for paths that end with .xml. Si une requête est faite pour /file.xml, la requête est redirigée vers /xmlfiles/file.xml.If a request is made for /file.xml, the request is redirected to /xmlfiles/file.xml. Le code d’état est défini sur 301 - Déplacé de façon permanente.The status code is set to 301 - Moved Permanently. Quand le navigateur fait une nouvelle requête pour /xmlfiles/file.xml, le middleware de fichiers statiques délivre le fichier au client à partir du dossier 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. Pour une redirection, définissez explicitement le code d’état de la réponse.For a redirect, explicitly set the status code of the response. Sinon, un code d’état 200 - OK est retourné et la redirection ne se produit pas sur le client.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;
    }
}

Cette approche peut également réécrire des requêtes.This approach can also rewrite requests. L’exemple d’application montre la réécriture du chemin pour toute requête demandant de délivrer le fichier texte file.txt à partir du dossier wwwroot.The sample app demonstrates rewriting the path for any text file request to serve the file.txt text file from the wwwroot folder. Le middleware de fichiers statiques délivre le fichier en fonction du chemin de requête mis à jour :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";
    }
}

Règle basée sur IRuleIRule-based rule

Utilisez Add pour insérer votre propre logique de règle dans une classe qui implémente l’interface IRule.Use Add to use rule logic in a class that implements the IRule interface. IRule offre davantage de flexibilité par rapport à l’approche de la règle basée sur une méthode.IRule provides greater flexibility over using the method-based rule approach. Votre classe d’implémentation peut inclure un constructeur qui vous permet de passer des paramètres pour la méthode 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}"));
}

Les valeurs des paramètres dans l’exemple d’application pour extension et newPath sont vérifiées afin de remplir plusieurs conditions.The values of the parameters in the sample app for the extension and the newPath are checked to meet several conditions. extension doit contenir une valeur, laquelle doit être .png, .jpg ou .gif.The extension must contain a value, and the value must be .png, .jpg, or .gif. Si newPath n’est pas valide, un ArgumentException est levé.If the newPath isn't valid, an ArgumentException is thrown. Si une requête est faite pour image.png, la requête est redirigée vers /png-images/image.png.If a request is made for image.png, the request is redirected to /png-images/image.png. Si une requête est faite pour image.jpg, la requête est redirigée vers /jpg-images/image.jpg.If a request is made for image.jpg, the request is redirected to /jpg-images/image.jpg. Le code d’état est défini sur 301 - Déplacé de façon permanente, et context.Result est défini de façon à cesser le traitement des règles et envoyer la réponse.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;
        }
    }
}

Requête d’origine : /image.pngOriginal Request: /image.png

Fenêtre de navigateur avec les requêtes et les réponses suivies par les Outils de développement pour image.png

Requête d’origine : /image.jpgOriginal Request: /image.jpg

Fenêtre de navigateur avec les requêtes et les réponses suivies par les Outils de développement pour image.jpg

Exemples d’expressions régulièresRegex examples

GoalGoal Chaîne d’expression régulière etRegex String &
exemple de correspondanceMatch Example
Chaîne de remplacement etReplacement String &
exemple de sortieOutput Example
Réécrire le chemin dans la chaîne de requêteRewrite path into querystring ^path/(.*)/(.*)
/path/abc/123
path?var1=$1&var2=$2
/path?var1=abc&var2=123
Supprimer la barre oblique finaleStrip trailing slash (.*)/$
/path/
$1
/path
Appliquer une barre oblique finaleEnforce trailing slash (.*[^/])$
/path
$1/
/path/
Éviter la réécriture des requêtes spécifiquesAvoid rewriting specific requests ^(.*)(?<!\.axd)$ ou ^(?!.*\.axd$)(.*)$^(.*)(?<!\.axd)$ or ^(?!.*\.axd$)(.*)$
Oui : /resource.htmYes: /resource.htm
Non : /resource.axdNo: /resource.axd
rewritten/$1
/rewritten/resource.htm
/resource.axd
Réorganiser les segments d’URLRearrange URL segments path/(.*)/(.*)/(.*)
path/1/2/3
path/$3/$2/$1
path/3/2/1
Remplacer un segment d’URLReplace a URL segment ^(.*)/segment2/(.*)
/segment1/segment2/segment3
$1/replaced/$2
/segment1/replaced/segment3

Ressources supplémentairesAdditional resources