Intergiciel (middleware) de réécriture d’URL dans ASP.NET Core
Remarque
Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 8 de cet article.
Avertissement
Cette version d’ASP.NET Core n’est plus prise en charge. Pour plus d’informations, consultez la Stratégie de prise en charge de .NET et .NET Core. Pour la version actuelle, consultez la version .NET 8 de cet article.
Important
Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.
Pour la version actuelle, consultez la version .NET 8 de cet article.
Par Kirk Larkin et Rick Anderson
Cet article 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.
La réécriture d’URL consiste à modifier des URL de requête en fonction d’une ou de plusieurs règles prédéfinies. 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. La réécriture d’URL est utile dans plusieurs scénarios pour :
- Déplacer ou remplacer de façon temporaire ou permanente les ressources d’un serveur, tout en conservant des localisateurs stables pour ces ressources.
- Diviser le traitement des requêtes entre différentes applications ou entre différentes parties d’une même application.
- Supprimer, ajouter ou réorganiser les segments d’URL sur des requêtes entrantes.
- Optimiser les URL publiques pour l’optimisation du référencement d’un site auprès d’un moteur de recherche (SEO).
- Permettre l’utilisation des URL publiques conviviales pour aider les visiteurs à prédire le contenu retourné en demandant une ressource.
- Rediriger des requêtes non sécurisées vers des points de terminaison sécurisés.
- 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.
La réécriture d’URL peut réduire les performances d’une application. Limitez le nombre et la complexité des règles.
Redirection d’URL et réécriture d’URL
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. L’intergiciel de réécriture d’URL d’ASP.NET Core est capables de répondre aux besoins des deux.
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. Ceci nécessite un aller-retour avec le serveur. 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.
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.
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 :
Le code d’état
301 - Moved Permanently
est utilisé quand la ressource a une nouvelle URL permanente et que toutes les requêtes futures pour la ressource doivent utiliser la nouvelle URL. Le client peut mettre en cache et réutiliser la réponse quand un code d’état 301 est reçu.Le code d’état
302 - Found
est utilisé quand la redirection est temporaire ou généralement susceptible d’être modifiée. Le code d’état 302 indique au client de ne pas stocker l’URL et de ne plus l’utiliser.
Pour plus d’informations sur les codes d’état, consultez RFC 9110: 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. La réécriture d’URL ne nécessite pas d’aller-retour avec le serveur. L’URL réécrite n’est pas retournée au client et n’apparaît pas dans la barre d’adresse du navigateur.
Si /resource
est réécrite en /different-resource
, le serveur récupère la ressource en interne à l’emplacement /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.
Exemple d’application de réécriture d’URL
Explorez les fonctionnalités de l’intergiciel de réécriture d’URL avec l’exemple d’application. 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.
Quand utiliser l’intergiciel (middleware) de réécriture d’URL
Utilisez l’intergiciel de réécriture d’URL lorsque les approches suivantes ne sont pas satisfaisantes :
- Module de réécriture d’URL avec IIS sur Windows Server
- Module mod_rewrite Apache sur Apache Server
- URL de réécriture sur Nginx
Utilisez l’intergiciel de réécriture d’URL lorsque l’application est hébergée sur un serveur HTTP.sys.
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 :
Le middleware ne prend pas en charge toutes les fonctionnalités de ces modules.
Certaines des fonctionnalités des modules serveur ne fonctionnent pas avec les projets ASP.NET Core, comme les contraintes
IsFile
etIsDirectory
du module Réécriture IIS. Dans ces scénarios, utilisez plutôt l’intergiciel.Les performances du middleware ne correspondent probablement pas à celles des 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.
Extension et 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 des règles de réécriture. Chaînez plusieurs règles dans l’ordre dans lequel elles doivent être traitées. Les RewriteOptions
sont passées dans le middleware de réécriture d’URL quand il est ajouté au pipeline de requête avec UseRewriter :
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Dans le code précédent, MethodRules
est une classe définie par l’utilisateur. Pour plus d’informations, consultez RewriteRules.cs
dans cet article.
Redirection de demandes non-www en demandes www
Trois options permettent à l’application de rediriger des demandes non-www
en demandes www
:
AddRedirectToWwwPermanent : Redirige de façon permanente la requête vers le sous-domaine
www
si la requête n’est pas de typewww
. Redirige avec un code d’état Status308PermanentRedirect.AddRedirectToWww : Redirige la requête vers le sous-domaine
www
si la requête entrante n’est pas de typewww
. Redirige avec un code d’état Status307TemporaryRedirect. Une surcharge vous permet de fournir le code d’état pour la réponse. Utilisez un champ de la classe StatusCodes pour une affectation de code d’état.
Redirection d’URL
Utilisez AddRedirect pour rediriger des requêtes. Le premier paramètre contient l’expression régulière .NET (Regex) pour la correspondance sur le chemin d’accès de l’URL entrante. Le deuxième paramètre est la chaîne de remplacement. Le troisième paramètre, le cas échéant, spécifie le code d’état. Si le code d’état n’est pas spécifié, sa valeur par défaut est 302 - Trouvé, ce qui indique que la ressource est temporairement déplacée ou remplacée.
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
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
. 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
. L’URL de redirection est renvoyée au client avec le code d’état 302 - Trouvé. Le navigateur effectue une nouvelle requête à l’URL de redirection, qui apparaît dans la barre d’adresse du navigateur. Comme aucune règle de l’exemple d’application ne correspond sur l’URL de redirection :
- La deuxième requête reçoit une réponse 200 - OK de l’application.
- Le corps de la réponse montre l’URL de redirection.
Un aller-retour est effectué avec le serveur quand une URL est redirigée.
Avertissement
Soyez prudent lors de l’établissement de règles de redirection. Les règles de redirection sont évaluées à chaque requête effectuée à l’application, notamment après une redirection. Il est facile de créer accidentellement une boucle de redirections infinies.
La partie de l’expression entre parenthèses est appelée groupe de capture. Le point (.
) de l’expression signifie mettre en correspondance n’importe quel caractère. L’astérisque (*
) indique mettre en correspondance zéro occurrence ou plus du caractère précédent. Par conséquent, les deux derniers segments de chemin de l’URL, 1234/5678
, sont capturés par le groupe de capture (.*)
. Toute valeur fournie dans l’URL de la requête après redirect-rule/
est capturée par ce groupe de capture unique.
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. 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 l’expression régulière. Comme il n’y a qu’un seul groupe capturé dans l’expression régulière dans redirect-rule/(.*)
, un seul groupe est injecté dans la chaîne de remplacement, à savoir $1
. Quand la règle est appliquée, l’URL devient /redirected/1234/5678
.
Essayez /redirect-rule/1234/5678
avec les outils de navigateur sous l’onglet Réseau.
Redirection d’URL vers un point de terminaison sécurisé
Utilisez AddRedirectToHttps pour rediriger les requêtes HTTP vers le même hôte et le même chemin avec le protocole HTTPS. Si le code d’état n’est pas fourni, le middleware utilise par défaut 302 - Trouvé. Si le port n’est pas fourni :
- Le middleware utilise par défaut
null
. - Le schéma change en
https
(protocole HTTPS), et le client accède à la ressource sur le port 443.
L’exemple suivant montre comment définir le code d’état sur 301 - Moved Permanently
et comment remplacer le port par le port HTTPS utilisé par Kestrel sur localhost. En production, le port HTTPS est défini sur null :
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
int? localhostHTTPSport = null;
if (app.Environment.IsDevelopment())
{
localhostHTTPSport = Int32.Parse(Environment.GetEnvironmentVariable(
"ASPNETCORE_URLS")!.Split(new Char[] { ':', ';' })[2]);
}
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
// localhostHTTPport not needed for production, used only with localhost.
.AddRedirectToHttps(301, localhostHTTPSport)
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
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. L’intergiciel définit le code d’état sur 301 - Moved Permanently
.
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Remarque
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. Pour plus d’informations, consultez Appliquer le protocole HTTPS.
L’exemple d’application montre comment utiliser AddRedirectToHttps
ou AddRedirectToHttpsPermanent
. Effectuez une requête HTTP non sécurisée à l’application http://redirect6.azurewebsites.net/iis-rules-rewrite/xyz
. Lors du test de la redirection HTTP vers HTTPS avec localhost :
- Utilisez l’URL HTTP, qui a un port différent de l’URL HTTPS. L’URL HTTP se trouve dans le fichier
Properties/launchSettings.json
. - La suppression de
s
dehttps://localhost/{port}
échoue, car localhost ne répond pas sur HTTP au port HTTPS.
L’image suivante montre l’image des outils de navigateur F12 d’une requête à http://redirect6.azurewebsites.net/iis-rules-rewrite/xyz
avec le code précédent :
Réécrire URL
Utilisez AddRewrite pour créer une règle pour la réécriture d’URL. Le premier paramètre contient l’expression régulière pour la mise en correspondance sur le chemin de l’URL entrante. Le deuxième paramètre est la chaîne de remplacement. 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.
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Essayer la requête pour https://redirect6.azurewebsites.net/rewrite-rule/1234/5678
Le caret (^
) au début de l’expression signifie que la correspondance commence au début du chemin de l’URL.
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. Ainsi, n’importe quel caractère peut précéder redirect-rule/
dans le chemin pour qu’une correspondance soit établie.
Chemin d’accès | Correspond |
---|---|
/redirect-rule/1234/5678 |
Oui |
/my-cool-redirect-rule/1234/5678 |
Oui |
/anotherredirect-rule/1234/5678 |
Oui |
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/
. Dans le tableau suivant, notez la différence de correspondance.
Chemin d’accès | Correspond |
---|---|
/rewrite-rule/1234/5678 |
Oui |
/my-cool-rewrite-rule/1234/5678 |
No |
/anotherrewrite-rule/1234/5678 |
Non |
À la suite de la partie ^rewrite-rule/
de l’expression se trouvent deux groupes de capture, (\d+)/(\d+)
. \d
signifie établir une correspondance avec un chiffre (nombre). Le signe plus (+
) signifie établir une correspondance avec une ou plusieurs occurrences du caractère précédent. Par conséquent, l’URL doit contenir un nombre suivi d’une barre oblique, elle-même suivie d’un autre nombre. Ces groupes sont injectés dans l’URL réécrite sous la forme $1
et $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. Le chemin demandé /rewrite-rule/1234/5678
est réécrit pour retourner la ressource à l’emplacement /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.
Il n’y a pas d’aller-retour avec le serveur pour retourner la ressource. Si la ressource existe, elle est récupérée et retournée au client avec le code d’état 200 - OK. Comme le client n’est pas redirigé, l’URL dans la barre d’adresse du navigateur ne change pas. Les clients ne peuvent pas détecter qu’une opération de réécriture d’URL s’est produite sur le serveur.
Conseils relatifs aux performances pour la réécriture et la redirection d’URL
Pour obtenir la réponse la plus rapide :
- 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.
- 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. 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.
Avertissement
Un utilisateur malveillant peut fournir une entrée coûteuse à traiter à RegularExpressions
, provoquant une attaque par déni de service. Les API d’infrastructure ASP.NET Core qui utilisent RegularExpressions
passent un délai d’expiration. Par exemple, les classes RedirectRule et RewriteRule passent toutes deux un délai d’expiration d’une seconde.
Apache mod_rewrite
Appliquez des règles Apache mod_rewrite avec AddApacheModRewrite. Vérifiez que le fichier de règles est déployé avec l’application. Pour obtenir plus d’informations et des exemples de règles mod_rewrite, consultez Apache mod_rewrite.
Un StreamReader est utilisé pour lire les règles dans le fichier de règles ApacheModRewrite.txt :
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
L’exemple d’application redirige les requêtes de /apache-mod-rules-redirect/(.\*)
vers /redirected?id=$1
. Le code d’état de la réponse est 302 - Trouvé.
# Rewrite path with additional sub directory
RewriteRule ^/apache-mod-rules-redirect/(.*) /redirected?id=$1 [L,R=302]
Essayer la requête pour https://redirect6.azurewebsites.net/apache-mod-rules-redirect/1234
L’intergiciel Apache prend en charge les variables de serveur Apache mod_rewrite suivantes :
- CONN_REMOTE_ADDR
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_FORWARDED
- HTTP_HOST
- HTTP_REFERER
- HTTP_USER_AGENT
- HTTPS
- IPV6
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_METHOD
- REQUEST_SCHEME
- REQUEST_URI
- SCRIPT_FILENAME
- SERVER_ADDR
- SERVER_PORT
- SERVER_PROTOCOL
- TEMPS
- TIME_DAY
- TIME_HOUR
- TIME_MIN
- TIME_MON
- TIME_SEC
- TIME_WDAY
- TIME_YEAR
Règles du module de réécriture d’URL IIS
Pour utiliser le même ensemble de règles que celui qui s’applique au module de réécriture d’URL IIS, utilisez AddIISUrlRewrite. Vérifiez que le fichier de règles est déployé avec l’application. N’indiquez pas au middleware d’utiliser le fichier web.config de l’application en cas d’exécution sur 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. 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.
Un StreamReader est utilisé pour lire les règles dans le fichier de règles IISUrlRewrite.xml
:
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
L’exemple d’application réécrit les requêtes de /iis-rules-rewrite/(.*)
vers /rewritten?id=$1
. La réponse est envoyée au client avec le code d’état 200 - OK.
<rewrite>
<rules>
<rule name="Rewrite segment to id querystring" stopProcessing="true">
<match url="^iis-rules-rewrite/(.*)$" />
<action type="Rewrite" url="rewritten?id={R:1}" appendQueryString="false"/>
</rule>
</rules>
</rewrite>
Essayer la requête pour https://redirect6.azurewebsites.net/iis-rules-rewrite/xyz
Les applications qui ont un module de réécriture IIS actif avec des règles au niveau du serveur configurées affectent l’application de manière indésirable :
- Envisagez de désactiver le module de réécriture IIS pour l’application.
- Pour plus d’informations, consultez Désactivation de modules IIS.
Fonctionnalités non prises en charge
L’intergiciel ne prend pas en charge les fonctionnalités de module de réécriture d’URL IIS suivantes :
- Règles de trafic sortant
- Variables serveur personnalisées
- Caractères génériques
- LogRewrittenUrl
Variables de serveur prises en charge
L’intergiciel prend en charge les variables serveur du module de réécriture d’URL IIS suivantes :
- CONTENT_LENGTH
- CONTENT_TYPE
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_HOST
- HTTP_REFERER
- HTTP_URL
- HTTP_USER_AGENT
- HTTPS
- LOCAL_ADDR
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_URI
Vous pouvez obtenir IFileProvider via un PhysicalFileProvider. Cette approche peut fournir davantage de flexibilité pour l’emplacement des fichiers de règles de réécriture. Vérifiez que les fichiers de règles de réécriture sont déployés sur le serveur dans le chemin fourni.
var fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
Règle basée sur une méthode
Utilisez Add pour implémenter une logique de règle personnalisée dans une méthode. Add
expose RewriteContext, ce qui rend HttpContext disponible pour une utilisation dans les méthodes de redirection. La propriété RewriteContext.Result détermine la façon dont un traitement du pipeline supplémentaire est géré. Définissez la valeur sur un des champs RuleResult décrits dans le tableau suivant.
Réécrire le résultat du contexte | Action |
---|---|
RuleResult.ContinueRules (valeur par défaut) |
Continuer à appliquer les règles. |
RuleResult.EndResponse |
Cesser d’appliquer les règles et envoyer la réponse. |
RuleResult.SkipRemainingRules |
Cesser d’appliquer les règles et envoyer le contexte au middleware suivant. |
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
L’exemple d’application présente une méthode qui redirige les requêtes de chemins qui se terminent par .xml
. Quand une requête est faite à /file.xml
:
- La requête est redirigée vers
/xmlfiles/file.xml
- Le code d’état est défini sur
301 - Moved Permanently
. Quand le navigateur fait une nouvelle requête pour/xmlfiles/file.xml
, l’intergiciel de fichiers statiques délivre le fichier au client à partir du dossier wwwroot/xmlfiles. Pour une redirection, définissez explicitement le code d’état de la réponse. Sinon, un code d’état 200 - OK est retourné et la redirection ne se produit pas sur le client.
RewriteRules.cs
:
public static void RedirectXmlFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because the client is redirecting back to the same app, stop
// processing if the request has already been redirected.
if (request.Path.StartsWithSegments(new PathString("/xmlfiles")) ||
request.Path.Value==null)
{
return;
}
if (request.Path.Value.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
"/xmlfiles" + request.Path + request.QueryString;
}
}
Cette approche peut également réécrire des requêtes. 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. Le middleware de fichiers statiques délivre le fichier en fonction du chemin de requête mis à jour :
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
RewriteRules.cs
:
public static void RewriteTextFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
if (request.Path.Value != null &&
request.Path.Value.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.SkipRemainingRules;
request.Path = "/file.txt";
}
}
Règle basée sur IRule
Utilisez Add pour insérer votre propre logique de règle dans une classe qui implémente l’interface IRule. IRule
offre davantage de flexibilité par rapport à l’approche de la règle basée sur une méthode. La classe d’implémentation peut inclure un constructeur qui vous permet de passer des paramètres pour la méthode ApplyRule.
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Les valeurs des paramètres dans l’exemple d’application pour extension
et newPath
sont vérifiées afin de remplir plusieurs conditions. extension
doit contenir une valeur, laquelle doit être .png
, .jpg
ou .gif
. Si newPath
n’est pas valide, un ArgumentException est levé. Si une requête est faite pour image.png
, la requête est redirigée vers /png-images/image.png
. Si une requête est faite pour image.jpg
, la requête est redirigée vers /jpg-images/image.jpg
. Le code d’état est défini sur 301 - Moved Permanently
, et context.Result
est défini de façon à cesser le traitement des règles et envoyer la réponse.
public class RedirectImageRequests : IRule
{
private readonly string _extension;
private readonly PathString _newPath;
public RedirectImageRequests(string extension, string newPath)
{
if (string.IsNullOrEmpty(extension))
{
throw new ArgumentException(nameof(extension));
}
if (!Regex.IsMatch(extension, @"^\.(png|jpg|gif)$"))
{
throw new ArgumentException("Invalid extension", nameof(extension));
}
if (!Regex.IsMatch(newPath, @"(/[A-Za-z0-9]+)+?"))
{
throw new ArgumentException("Invalid path", nameof(newPath));
}
_extension = extension;
_newPath = new PathString(newPath);
}
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because we're redirecting back to the same app, stop
// processing if the request has already been redirected
if (request.Path.StartsWithSegments(new PathString(_newPath)) ||
request.Path.Value == null)
{
return;
}
if (request.Path.Value.EndsWith(_extension, StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
_newPath + request.Path + request.QueryString;
}
}
}
Essayez de procéder comme suit :
- Requête PNG :
https://redirect6.azurewebsites.net/image.png
- Requête JPG :
https://redirect6.azurewebsites.net/image.jpg
Exemples d’expressions régulières
Objectif | Chaîne d’expression régulière et exemple de correspondance |
Chaîne de remplacement et Exemple de sortie |
---|---|---|
Réécrire le chemin dans la chaîne de requête | ^path/(.*)/(.*) /path/abc/123 |
path?var1=$1&var2=$2 /path?var1=abc&var2=123 |
Supprimer la barre oblique finale | ^path2/(.*)/$ /path2/xyz/ |
$1 /path2/xyz |
Appliquer une barre oblique finale | ^path3/(.*[^/])$ /path3/xyz |
$1/ /path3/xyz/ |
Éviter la réécriture des requêtes spécifiques | ^(.*)(?<!\.axd)$ ou ^(?!.*\.axd$)(.*)$ Oui : /path4/resource.htm Non : /path4/resource.axd |
rewritten/$1 /rewritten/resource.htm /resource.axd |
Réorganiser les segments d’URL | path5/(.*)/(.*)/(.*) path5/1/2/3 |
path5/$3/$2/$1 path5/3/2/1 |
Remplacer un segment d’URL | ^path6/(.*)/segment2/(.*) ^path6/segment1/segment2/segment3 |
path6/$1/replaced/$2 /path6/segment1/replaced/segment3 |
Les liens du tableau précédent utilisent le code suivant déployé sur Azure :
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
// Rewrite path to QS.
.AddRewrite(@"^path/(.*)/(.*)", "path?var1=$1&var2=$2",
skipRemainingRules: true)
// Skip trailing slash.
.AddRewrite(@"^path2/(.*)/$", "path2/$1",
skipRemainingRules: true)
// Enforce trailing slash.
.AddRewrite(@"^path3/(.*[^/])$", "path3/$1/",
skipRemainingRules: true)
// Avoid rewriting specific requests.
.AddRewrite(@"^path4/(.*)(?<!\.axd)$", "rewritten/$1",
skipRemainingRules: true)
// Rearrange URL segments
.AddRewrite(@"^path5/(.*)/(.*)/(.*)", "path5/$3/$2/$1",
skipRemainingRules: true)
// Replace a URL segment
.AddRewrite(@"^path6/(.*)/segment2/(.*)", "path6/$1/replaced/$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Dans la plupart des exemples d’expressions régulières précédents, le littéral path
est utilisé pour créer des règles de réécriture testables uniques pour l’exemple déployé. En règle générale, l’expression régulière n’inclut pas path
. Par exemple, consultez le tableau des exemples d’expressions régulières.
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.
La réécriture d’URL consiste à modifier des URL de requête en fonction d’une ou de plusieurs règles prédéfinies. 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. La réécriture d’URL est utile dans plusieurs scénarios pour :
- Déplacer ou remplacer de façon temporaire ou permanente les ressources d’un serveur, tout en conservant des localisateurs stables pour ces ressources.
- Diviser le traitement des requêtes entre différentes applications ou entre différentes parties d’une même application.
- Supprimer, ajouter ou réorganiser les segments d’URL sur des requêtes entrantes.
- Optimiser les URL publiques pour l’optimisation du référencement d’un site auprès d’un moteur de recherche (SEO).
- Permettre l’utilisation des URL publiques conviviales pour aider les visiteurs à prédire le contenu retourné en demandant une ressource.
- Rediriger des requêtes non sécurisées vers des points de terminaison sécurisés.
- 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.
Remarque
La réécriture d’URL peut réduire les performances d’une application. Quand c’est possible, limitez le nombre et la complexité des règles.
Affichez ou téléchargez l’exemple de code (procédure de téléchargement)
Redirection d’URL et réécriture d’URL
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. L’intergiciel de réécriture d’URL d’ASP.NET Core est capables de répondre aux besoins des deux.
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. Ceci nécessite un aller-retour avec le serveur. 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.
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.
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 :
Le code d’état
301 - Moved Permanently
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. Le client peut mettre en cache et réutiliser la réponse quand un code d’état 301 est reçu.Le code d’état 302 - Trouvé est utilisé quand la redirection est temporaire ou généralement susceptible d’être modifiée. Le code d’état 302 indique au client de ne pas stocker l’URL et de ne plus l’utiliser.
Pour plus d’informations sur les codes d’état, consultez RFC 9110: 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. La réécriture d’URL ne nécessite pas d’aller-retour avec le serveur. L’URL réécrite n’est pas retournée au client et n’apparaît pas dans la barre d’adresse du navigateur.
Si /resource
est réécrite en /different-resource
, le serveur récupère la ressource en interne à l’emplacement /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.
Exemple d’application de réécriture d’URL
Vous pouvez explorer les fonctionnalités du middleware de réécriture d’URL avec l’exemple d’application. 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.
Quand utiliser l’intergiciel (middleware) de réécriture d’URL
Utilisez le middleware de réécriture d’URL quand vous ne pouvez pas utiliser les approches suivantes :
- Module de réécriture d’URL avec IIS sur Windows Server
- Module mod_rewrite Apache sur Apache Server
- URL de réécriture sur Nginx
Utilisez l’intergiciel de réécriture d’URL lorsque l’application est hébergée sur un serveur HTTP.sys.
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 :
Le middleware ne prend pas en charge toutes les fonctionnalités de ces modules.
Certaines des fonctionnalités des modules serveur ne fonctionnent pas avec les projets ASP.NET Core, comme les contraintes
IsFile
etIsDirectory
du module Réécriture IIS. Dans ces scénarios, utilisez plutôt l’intergiciel.Les performances du middleware ne correspondent probablement pas à celles des 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.
Package
L’intergiciel (middleware) de réécriture d’URL est fourni par le package Microsoft.AspNetCore.Rewrite, qui est implicitement inclus dans les applications ASP.NET Core.
Extension et 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. Chaînez plusieurs règles dans l’ordre dans lequel vous voulez qu’elles soient traitées. Les RewriteOptions
sont passées dans le middleware de réécriture d’URL quand il est ajouté au pipeline de requête avec 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 www
Trois options permettent à l’application de rediriger des demandes non-www
en demandes www
:
AddRedirectToWwwPermanent : Redirige de façon permanente la requête vers le sous-domaine
www
si la requête n’est pas de typewww
. Redirige avec un code d’état Status308PermanentRedirect.AddRedirectToWww : Redirige la requête vers le sous-domaine
www
si la requête entrante n’est pas de typewww
. Redirige avec un code d’état Status307TemporaryRedirect. Une surcharge vous permet de fournir le code d’état pour la réponse. Utilisez un champ de la classe StatusCodes pour une affectation de code d’état.
Redirection d’URL
Utilisez AddRedirect pour rediriger des requêtes. Le premier paramètre contient votre expression régulière pour la mise en correspondance sur le chemin de l’URL entrante. Le deuxième paramètre est la chaîne de remplacement. Le troisième paramètre, le cas échéant, spécifie le code d’état. 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.
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
. 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
. L’URL de redirection est renvoyée au client avec le code d’état 302 - Trouvé. Le navigateur effectue une nouvelle requête à l’URL de redirection, qui apparaît dans la barre d’adresse du navigateur. Comme aucune règle de l’exemple d’application ne correspond sur l’URL de redirection :
- La deuxième requête reçoit une réponse 200 - OK de l’application.
- Le corps de la réponse montre l’URL de redirection.
Un aller-retour est effectué avec le serveur quand une URL est redirigée.
Avertissement
Soyez prudent lors de l’établissement de règles de redirection. Les règles de redirection sont évaluées à chaque requête effectuée à l’application, notamment après une redirection. Il est facile de créer accidentellement une boucle de redirections infinies.
Requête d’origine : /redirect-rule/1234/5678
La partie de l’expression entre parenthèses est appelée groupe de capture. Le point (.
) de l’expression signifie mettre en correspondance n’importe quel caractère. L’astérisque (*
) indique mettre en correspondance zéro occurrence ou plus du caractère précédent. Par conséquent, les deux derniers segments de chemin de l’URL, 1234/5678
, sont capturés par le groupe de capture (.*)
. Toute valeur fournie dans l’URL de la requête après redirect-rule/
est capturée par ce groupe de capture unique.
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. 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. 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
. Quand la règle est appliquée, l’URL devient /redirected/1234/5678
.
Redirection d’URL vers un point de terminaison sécurisé
Utilisez AddRedirectToHttps pour rediriger les requêtes HTTP vers le même hôte et le même chemin avec le protocole HTTPS. Si le code d’état n’est pas fourni, le middleware utilise par défaut 302 - Trouvé. Si le port n’est pas fourni :
- Le middleware utilise par défaut
null
. - Le schéma change en
https
(protocole HTTPS), et le client accède à la ressource sur le port 443.
L’exemple suivant montre comment définir le code d’état sur 301 - Moved Permanently
et changer le port en 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. L’intergiciel définit le code d’état sur 301 - Moved Permanently
.
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent();
app.UseRewriter(options);
}
Remarque
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. Pour plus d’informations, consultez la rubrique Appliquer HTTPS.
L’exemple d’application peut montrer comment utiliser AddRedirectToHttps
ou AddRedirectToHttpsPermanent
. Ajoutez la méthode d’extension à RewriteOptions
. Effectuez une requête non sécurisée à l’application à n’importe quelle 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.
Requête d’origine utilisant AddRedirectToHttps(301, 5001)
: http://localhost:5000/secure
Requête d’origine utilisant AddRedirectToHttpsPermanent
: http://localhost:5000/secure
Réécrire URL
Utilisez AddRewrite pour créer une règle pour la réécriture d’URL. Le premier paramètre contient l’expression régulière pour la mise en correspondance sur le chemin de l’URL entrante. Le deuxième paramètre est la chaîne de remplacement. 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.
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/5678
Le caret (^
) au début de l’expression signifie que la correspondance commence au début du chemin de l’URL.
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. Ainsi, n’importe quel caractère peut précéder redirect-rule/
dans le chemin pour qu’une correspondance soit établie.
Chemin d’accès | Correspond |
---|---|
/redirect-rule/1234/5678 |
Oui |
/my-cool-redirect-rule/1234/5678 |
Oui |
/anotherredirect-rule/1234/5678 |
Oui |
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/
. Dans le tableau suivant, notez la différence de correspondance.
Chemin d’accès | Correspond |
---|---|
/rewrite-rule/1234/5678 |
Oui |
/my-cool-rewrite-rule/1234/5678 |
No |
/anotherrewrite-rule/1234/5678 |
Non |
À la suite de la partie ^rewrite-rule/
de l’expression se trouvent deux groupes de capture, (\d+)/(\d+)
. \d
signifie établir une correspondance avec un chiffre (nombre). Le signe plus (+
) signifie établir une correspondance avec une ou plusieurs occurrences du caractère précédent. Par conséquent, l’URL doit contenir un nombre suivi d’une barre oblique, elle-même suivie d’un autre nombre. Ces groupes sont injectés dans l’URL réécrite sous la forme $1
et $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. Le chemin demandé /rewrite-rule/1234/5678
est réécrit pour obtenir la ressource à l’emplacement /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.
Il n’y a pas d’aller-retour avec le serveur pour obtenir la ressource. Si la ressource existe, elle est récupérée et retournée au client avec le code d’état 200 - OK. Comme le client n’est pas redirigé, l’URL dans la barre d’adresse du navigateur ne change pas. Les clients ne peuvent pas détecter qu’une opération de réécriture d’URL s’est produite sur le serveur.
Remarque
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. Pour obtenir la réponse d’application la plus rapide :
- 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.
- 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.
Apache mod_rewrite
Appliquez des règles Apache mod_rewrite avec AddApacheModRewrite. Vérifiez que le fichier de règles est déployé avec l’application. Pour obtenir plus d’informations et des exemples de règles mod_rewrite, consultez Apache mod_rewrite.
Un StreamReader est utilisé pour lire les règles dans le fichier de règles ApacheModRewrite.txt :
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
L’exemple d’application redirige les requêtes de /apache-mod-rules-redirect/(.\*)
vers /redirected?id=$1
. Le code d’état de la réponse est 302 - Trouvé.
# 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/1234
L’intergiciel prend en charge les variables de serveur Apache mod_rewrite suivantes :
- CONN_REMOTE_ADDR
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_FORWARDED
- HTTP_HOST
- HTTP_REFERER
- HTTP_USER_AGENT
- HTTPS
- IPV6
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_METHOD
- REQUEST_SCHEME
- REQUEST_URI
- SCRIPT_FILENAME
- SERVER_ADDR
- SERVER_PORT
- SERVER_PROTOCOL
- TEMPS
- TIME_DAY
- TIME_HOUR
- TIME_MIN
- TIME_MON
- TIME_SEC
- TIME_WDAY
- TIME_YEAR
Règles du module de réécriture d’URL IIS
Pour utiliser le même ensemble de règles que celui qui s’applique au module de réécriture d’URL IIS, utilisez AddIISUrlRewrite. Vérifiez que le fichier de règles est déployé avec l’application. N’indiquez pas au middleware d’utiliser le fichier web.config de l’application en cas d’exécution sur 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. 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.
Un StreamReader est utilisé pour lire les règles dans le fichier de règles IISUrlRewrite.xml
:
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
. La réponse est envoyée au client avec le code d’état 200 - OK.
<rewrite>
<rules>
<rule name="Rewrite segment to id querystring" stopProcessing="true">
<match url="^iis-rules-rewrite/(.*)$" />
<action type="Rewrite" url="rewritten?id={R:1}" appendQueryString="false"/>
</rule>
</rules>
</rewrite>
Requête d’origine : /iis-rules-rewrite/1234
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. Pour plus d’informations, consultez Désactivation de modules IIS.
Fonctionnalités non prises en charge
L’intergiciel ne prend pas en charge les fonctionnalités de module de réécriture d’URL IIS suivantes :
- Règles de trafic sortant
- Variables serveur personnalisées
- Caractères génériques
- LogRewrittenUrl
Variables de serveur prises en charge
L’intergiciel prend en charge les variables serveur du module de réécriture d’URL IIS suivantes :
- CONTENT_LENGTH
- CONTENT_TYPE
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_HOST
- HTTP_REFERER
- HTTP_URL
- HTTP_USER_AGENT
- HTTPS
- LOCAL_ADDR
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_URI
Remarque
Vous pouvez également obtenir un IFileProvider par le biais d’un PhysicalFileProvider. Cette approche peut fournir davantage de flexibilité pour l’emplacement de vos fichiers de règles de réécriture. Vérifiez que vos fichiers de règles de réécriture sont déployés sur le serveur dans le chemin que vous fournissez.
PhysicalFileProvider fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
Règle basée sur une méthode
Utilisez Add pour implémenter votre propre logique de règle dans une méthode. Add
expose RewriteContext, ce qui rend HttpContext disponible pour une utilisation dans votre méthode. RewriteContext.Result détermine la façon dont le traitement du pipeline supplémentaire est géré. Définissez la valeur sur un des champs RuleResult décrits dans le tableau suivant.
Réécrire le résultat du contexte | Action |
---|---|
RuleResult.ContinueRules (valeur par défaut) |
Continuer à appliquer les règles. |
RuleResult.EndResponse |
Cesser d’appliquer les règles et envoyer la réponse. |
RuleResult.SkipRemainingRules |
Cesser d’appliquer les règles et envoyer le contexte au middleware suivant. |
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
. Si une requête est faite pour /file.xml
, la requête est redirigée vers /xmlfiles/file.xml
. Le code d’état est défini sur 301 - Moved Permanently
. Quand le navigateur fait une nouvelle requête pour /xmlfiles/file.xml
, l’intergiciel de fichiers statiques délivre le fichier au client à partir du dossier wwwroot/xmlfiles. Pour une redirection, définissez explicitement le code d’état de la réponse. Sinon, un code d’état 200 - OK est retourné et la redirection ne se produit pas sur le client.
RewriteRules.cs
:
public static void RedirectXmlFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because the client is redirecting back to the same app, stop
// processing if the request has already been redirected.
if (request.Path.StartsWithSegments(new PathString("/xmlfiles")))
{
return;
}
if (request.Path.Value.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
"/xmlfiles" + request.Path + request.QueryString;
}
}
Cette approche peut également réécrire des requêtes. 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. Le middleware de fichiers statiques délivre le fichier en fonction du chemin de requête mis à jour :
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
RewriteRules.cs
:
public static void RewriteTextFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
if (request.Path.Value.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.SkipRemainingRules;
request.Path = "/file.txt";
}
}
Règle basée sur IRule
Utilisez Add pour insérer votre propre logique de règle dans une classe qui implémente l’interface IRule. IRule
offre davantage de flexibilité par rapport à l’approche de la règle basée sur une méthode. Votre classe d’implémentation peut inclure un constructeur qui vous permet de passer des paramètres pour la méthode ApplyRule.
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Les valeurs des paramètres dans l’exemple d’application pour extension
et newPath
sont vérifiées afin de remplir plusieurs conditions. extension
doit contenir une valeur, laquelle doit être .png
, .jpg
ou .gif. Si newPath
n’est pas valide, un ArgumentException est levé. Si une requête est faite pour image.png
, la requête est redirigée vers /png-images/image.png
. Si une requête est faite pour image.jpg
, la requête est redirigée vers /jpg-images/image.jpg
. Le code d’état est défini sur 301 - Moved Permanently
, et context.Result
est défini de façon à cesser le traitement des règles et envoyer la réponse.
public class RedirectImageRequests : IRule
{
private readonly string _extension;
private readonly PathString _newPath;
public RedirectImageRequests(string extension, string newPath)
{
if (string.IsNullOrEmpty(extension))
{
throw new ArgumentException(nameof(extension));
}
if (!Regex.IsMatch(extension, @"^\.(png|jpg|gif)$"))
{
throw new ArgumentException("Invalid extension", nameof(extension));
}
if (!Regex.IsMatch(newPath, @"(/[A-Za-z0-9]+)+?"))
{
throw new ArgumentException("Invalid path", nameof(newPath));
}
_extension = extension;
_newPath = new PathString(newPath);
}
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because we're redirecting back to the same app, stop
// processing if the request has already been redirected
if (request.Path.StartsWithSegments(new PathString(_newPath)))
{
return;
}
if (request.Path.Value.EndsWith(_extension, StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
_newPath + request.Path + request.QueryString;
}
}
}
Requête d’origine : /image.png
Requête d’origine : /image.jpg
Exemples d’expressions régulières
Objectif | Chaîne d’expression régulière et exemple de correspondance |
Chaîne de remplacement et Exemple de sortie |
---|---|---|
Réécrire le chemin dans la chaîne de requête | ^path/(.*)/(.*) /path/abc/123 |
path?var1=$1&var2=$2 /path?var1=abc&var2=123 |
Supprimer la barre oblique finale | (.*)/$ /path/ |
$1 /path |
Appliquer une barre oblique finale | (.*[^/])$ /path |
$1/ /path/ |
Éviter la réécriture des requêtes spécifiques | ^(.*)(?<!\.axd)$ ou ^(?!.*\.axd$)(.*)$ Oui : /resource.htm Non : /resource.axd |
rewritten/$1 /rewritten/resource.htm /resource.axd |
Réorganiser les segments d’URL | path/(.*)/(.*)/(.*) path/1/2/3 |
path/$3/$2/$1 path/3/2/1 |
Remplacer un segment d’URL | ^(.*)/segment2/(.*) /segment1/segment2/segment3 |
$1/replaced/$2 /segment1/replaced/segment3 |
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.
La réécriture d’URL consiste à modifier des URL de requête en fonction d’une ou de plusieurs règles prédéfinies. 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. La réécriture d’URL est utile dans plusieurs scénarios pour :
- Déplacer ou remplacer de façon temporaire ou permanente les ressources d’un serveur, tout en conservant des localisateurs stables pour ces ressources.
- Diviser le traitement des requêtes entre différentes applications ou entre différentes parties d’une même application.
- Supprimer, ajouter ou réorganiser les segments d’URL sur des requêtes entrantes.
- Optimiser les URL publiques pour l’optimisation du référencement d’un site auprès d’un moteur de recherche (SEO).
- Permettre l’utilisation des URL publiques conviviales pour aider les visiteurs à prédire le contenu retourné en demandant une ressource.
- Rediriger des requêtes non sécurisées vers des points de terminaison sécurisés.
- 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.
Remarque
La réécriture d’URL peut réduire les performances d’une application. Quand c’est possible, limitez le nombre et la complexité des règles.
Affichez ou téléchargez l’exemple de code (procédure de téléchargement)
Redirection d’URL et réécriture d’URL
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. L’intergiciel de réécriture d’URL d’ASP.NET Core est capables de répondre aux besoins des deux.
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. Ceci nécessite un aller-retour avec le serveur. 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.
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.
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 :
Le code d’état
301 - Moved Permanently
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. Le client peut mettre en cache et réutiliser la réponse quand un code d’état 301 est reçu.Le code d’état 302 - Trouvé est utilisé quand la redirection est temporaire ou généralement susceptible d’être modifiée. Le code d’état 302 indique au client de ne pas stocker l’URL et de ne plus l’utiliser.
Pour plus d’informations sur les codes d’état, consultez RFC 9110: 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. La réécriture d’URL ne nécessite pas d’aller-retour avec le serveur. L’URL réécrite n’est pas retournée au client et n’apparaît pas dans la barre d’adresse du navigateur.
Si /resource
est réécrite en /different-resource
, le serveur récupère la ressource en interne à l’emplacement /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.
Exemple d’application de réécriture d’URL
Vous pouvez explorer les fonctionnalités du middleware de réécriture d’URL avec l’exemple d’application. 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.
Quand utiliser l’intergiciel (middleware) de réécriture d’URL
Utilisez le middleware de réécriture d’URL quand vous ne pouvez pas utiliser les approches suivantes :
- Module de réécriture d’URL avec IIS sur Windows Server
- Module mod_rewrite Apache sur Apache Server
- URL de réécriture sur Nginx
Utilisez aussi le middleware quand l’application est hébergée sur le serveur HTTP.sys (anciennement appelé 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 :
Le middleware ne prend pas en charge toutes les fonctionnalités de ces modules.
Certaines des fonctionnalités des modules serveur ne fonctionnent pas avec les projets ASP.NET Core, comme les contraintes
IsFile
etIsDirectory
du module Réécriture IIS. Dans ces scénarios, utilisez plutôt l’intergiciel.Les performances du middleware ne correspondent probablement pas à celles des 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.
Package
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.
Quand vous n’utilisez pas le métapackage Microsoft.AspNetCore.App
, ajoutez une référence de projet au package Microsoft.AspNetCore.Rewrite
.
Extension et 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. Chaînez plusieurs règles dans l’ordre dans lequel vous voulez qu’elles soient traitées. Les RewriteOptions
sont passées dans le middleware de réécriture d’URL quand il est ajouté au pipeline de requête avec 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 www
Trois options permettent à l’application de rediriger des demandes non-www
en demandes www
:
AddRedirectToWwwPermanent : Redirige de façon permanente la requête vers le sous-domaine
www
si la requête n’est pas de typewww
. Redirige avec un code d’état Status308PermanentRedirect.AddRedirectToWww : Redirige la requête vers le sous-domaine
www
si la requête entrante n’est pas de typewww
. Redirige avec un code d’état Status307TemporaryRedirect. Une surcharge vous permet de fournir le code d’état pour la réponse. Utilisez un champ de la classe StatusCodes pour une affectation de code d’état.
Redirection d’URL
Utilisez AddRedirect pour rediriger des requêtes. Le premier paramètre contient votre expression régulière pour la mise en correspondance sur le chemin de l’URL entrante. Le deuxième paramètre est la chaîne de remplacement. Le troisième paramètre, le cas échéant, spécifie le code d’état. 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.
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
. 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
. L’URL de redirection est renvoyée au client avec le code d’état 302 - Trouvé. Le navigateur effectue une nouvelle requête à l’URL de redirection, qui apparaît dans la barre d’adresse du navigateur. Comme aucune règle de l’exemple d’application ne correspond sur l’URL de redirection :
- La deuxième requête reçoit une réponse 200 - OK de l’application.
- Le corps de la réponse montre l’URL de redirection.
Un aller-retour est effectué avec le serveur quand une URL est redirigée.
Avertissement
Soyez prudent lors de l’établissement de règles de redirection. Les règles de redirection sont évaluées à chaque requête effectuée à l’application, notamment après une redirection. Il est facile de créer accidentellement une boucle de redirections infinies.
Requête d’origine : /redirect-rule/1234/5678
La partie de l’expression entre parenthèses est appelée groupe de capture. Le point (.
) de l’expression signifie mettre en correspondance n’importe quel caractère. L’astérisque (*
) indique mettre en correspondance zéro occurrence ou plus du caractère précédent. Par conséquent, les deux derniers segments de chemin de l’URL, 1234/5678
, sont capturés par le groupe de capture (.*)
. Toute valeur fournie dans l’URL de la requête après redirect-rule/
est capturée par ce groupe de capture unique.
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. 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. 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
. Quand la règle est appliquée, l’URL devient /redirected/1234/5678
.
Redirection d’URL vers un point de terminaison sécurisé
Utilisez AddRedirectToHttps pour rediriger les requêtes HTTP vers le même hôte et le même chemin avec le protocole HTTPS. Si le code d’état n’est pas fourni, le middleware utilise par défaut 302 - Trouvé. Si le port n’est pas fourni :
- Le middleware utilise par défaut
null
. - Le schéma change en
https
(protocole HTTPS), et le client accède à la ressource sur le port 443.
L’exemple suivant montre comment définir le code d’état sur 301 - Moved Permanently
et changer le port en 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. L’intergiciel définit le code d’état sur 301 - Moved Permanently
.
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent();
app.UseRewriter(options);
}
Remarque
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. Pour plus d’informations, consultez la rubrique Appliquer HTTPS.
L’exemple d’application peut montrer comment utiliser AddRedirectToHttps
ou AddRedirectToHttpsPermanent
. Ajoutez la méthode d’extension à RewriteOptions
. Effectuez une requête non sécurisée à l’application à n’importe quelle 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.
Requête d’origine utilisant AddRedirectToHttps(301, 5001)
: http://localhost:5000/secure
Requête d’origine utilisant AddRedirectToHttpsPermanent
: http://localhost:5000/secure
Réécrire URL
Utilisez AddRewrite pour créer une règle pour la réécriture d’URL. Le premier paramètre contient l’expression régulière pour la mise en correspondance sur le chemin de l’URL entrante. Le deuxième paramètre est la chaîne de remplacement. 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.
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/5678
Le caret (^
) au début de l’expression signifie que la correspondance commence au début du chemin de l’URL.
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. Ainsi, n’importe quel caractère peut précéder redirect-rule/
dans le chemin pour qu’une correspondance soit établie.
Chemin d’accès | Correspond |
---|---|
/redirect-rule/1234/5678 |
Oui |
/my-cool-redirect-rule/1234/5678 |
Oui |
/anotherredirect-rule/1234/5678 |
Oui |
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/
. Dans le tableau suivant, notez la différence de correspondance.
Chemin d’accès | Correspond |
---|---|
/rewrite-rule/1234/5678 |
Oui |
/my-cool-rewrite-rule/1234/5678 |
No |
/anotherrewrite-rule/1234/5678 |
Non |
À la suite de la partie ^rewrite-rule/
de l’expression se trouvent deux groupes de capture, (\d+)/(\d+)
. \d
signifie établir une correspondance avec un chiffre (nombre). Le signe plus (+
) signifie établir une correspondance avec une ou plusieurs occurrences du caractère précédent. Par conséquent, l’URL doit contenir un nombre suivi d’une barre oblique, elle-même suivie d’un autre nombre. Ces groupes sont injectés dans l’URL réécrite sous la forme $1
et $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. Le chemin demandé /rewrite-rule/1234/5678
est réécrit pour obtenir la ressource à l’emplacement /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.
Il n’y a pas d’aller-retour avec le serveur pour obtenir la ressource. Si la ressource existe, elle est récupérée et retournée au client avec le code d’état 200 - OK. Comme le client n’est pas redirigé, l’URL dans la barre d’adresse du navigateur ne change pas. Les clients ne peuvent pas détecter qu’une opération de réécriture d’URL s’est produite sur le serveur.
Remarque
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. Pour obtenir la réponse d’application la plus rapide :
- 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.
- 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.
Apache mod_rewrite
Appliquez des règles Apache mod_rewrite avec AddApacheModRewrite. Vérifiez que le fichier de règles est déployé avec l’application. Pour obtenir plus d’informations et des exemples de règles mod_rewrite, consultez Apache mod_rewrite.
Un StreamReader est utilisé pour lire les règles dans le fichier de règles ApacheModRewrite.txt :
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
L’exemple d’application redirige les requêtes de /apache-mod-rules-redirect/(.\*)
vers /redirected?id=$1
. Le code d’état de la réponse est 302 - Trouvé.
# 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/1234
L’intergiciel prend en charge les variables de serveur Apache mod_rewrite suivantes :
- CONN_REMOTE_ADDR
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_FORWARDED
- HTTP_HOST
- HTTP_REFERER
- HTTP_USER_AGENT
- HTTPS
- IPV6
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_METHOD
- REQUEST_SCHEME
- REQUEST_URI
- SCRIPT_FILENAME
- SERVER_ADDR
- SERVER_PORT
- SERVER_PROTOCOL
- TEMPS
- TIME_DAY
- TIME_HOUR
- TIME_MIN
- TIME_MON
- TIME_SEC
- TIME_WDAY
- TIME_YEAR
Règles du module de réécriture d’URL IIS
Pour utiliser le même ensemble de règles que celui qui s’applique au module de réécriture d’URL IIS, utilisez AddIISUrlRewrite. Vérifiez que le fichier de règles est déployé avec l’application. N’indiquez pas au middleware d’utiliser le fichier web.config de l’application en cas d’exécution sur 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. 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.
Un StreamReader est utilisé pour lire les règles dans le fichier de règles IISUrlRewrite.xml
:
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
. La réponse est envoyée au client avec le code d’état 200 - OK.
<rewrite>
<rules>
<rule name="Rewrite segment to id querystring" stopProcessing="true">
<match url="^iis-rules-rewrite/(.*)$" />
<action type="Rewrite" url="rewritten?id={R:1}" appendQueryString="false"/>
</rule>
</rules>
</rewrite>
Requête d’origine : /iis-rules-rewrite/1234
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. Pour plus d’informations, consultez Désactivation de modules IIS.
Fonctionnalités non prises en charge
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 :
- Règles de trafic sortant
- Variables serveur personnalisées
- Caractères génériques
- LogRewrittenUrl
Variables de serveur prises en charge
L’intergiciel prend en charge les variables serveur du module de réécriture d’URL IIS suivantes :
- CONTENT_LENGTH
- CONTENT_TYPE
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_HOST
- HTTP_REFERER
- HTTP_URL
- HTTP_USER_AGENT
- HTTPS
- LOCAL_ADDR
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_URI
Remarque
Vous pouvez également obtenir un IFileProvider par le biais d’un PhysicalFileProvider. Cette approche peut fournir davantage de flexibilité pour l’emplacement de vos fichiers de règles de réécriture. Vérifiez que vos fichiers de règles de réécriture sont déployés sur le serveur dans le chemin que vous fournissez.
PhysicalFileProvider fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
Règle basée sur une méthode
Utilisez Add pour implémenter votre propre logique de règle dans une méthode. Add
expose RewriteContext, ce qui rend HttpContext disponible pour une utilisation dans votre méthode. RewriteContext.Result détermine la façon dont le traitement du pipeline supplémentaire est géré. Définissez la valeur sur un des champs RuleResult décrits dans le tableau suivant.
Réécrire le résultat du contexte | Action |
---|---|
RuleResult.ContinueRules (valeur par défaut) |
Continuer à appliquer les règles. |
RuleResult.EndResponse |
Cesser d’appliquer les règles et envoyer la réponse. |
RuleResult.SkipRemainingRules |
Cesser d’appliquer les règles et envoyer le contexte au middleware suivant. |
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
. Si une requête est faite pour /file.xml
, la requête est redirigée vers /xmlfiles/file.xml
. Le code d’état est défini sur 301 - Moved Permanently
. Quand le navigateur fait une nouvelle requête pour /xmlfiles/file.xml
, l’intergiciel de fichiers statiques délivre le fichier au client à partir du dossier wwwroot/xmlfiles. Pour une redirection, définissez explicitement le code d’état de la réponse. Sinon, un code d’état 200 - OK est retourné et la redirection ne se produit pas sur le client.
RewriteRules.cs
:
public static void RedirectXmlFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because the client is redirecting back to the same app, stop
// processing if the request has already been redirected.
if (request.Path.StartsWithSegments(new PathString("/xmlfiles")))
{
return;
}
if (request.Path.Value.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
"/xmlfiles" + request.Path + request.QueryString;
}
}
Cette approche peut également réécrire des requêtes. 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. Le middleware de fichiers statiques délivre le fichier en fonction du chemin de requête mis à jour :
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
RewriteRules.cs
:
public static void RewriteTextFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
if (request.Path.Value.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.SkipRemainingRules;
request.Path = "/file.txt";
}
}
Règle basée sur IRule
Utilisez Add pour insérer votre propre logique de règle dans une classe qui implémente l’interface IRule. IRule
offre davantage de flexibilité par rapport à l’approche de la règle basée sur une méthode. Votre classe d’implémentation peut inclure un constructeur qui vous permet de passer des paramètres pour la méthode ApplyRule.
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Les valeurs des paramètres dans l’exemple d’application pour extension
et newPath
sont vérifiées afin de remplir plusieurs conditions. extension
doit contenir une valeur, laquelle doit être .png
, .jpg
ou .gif. Si newPath
n’est pas valide, un ArgumentException est levé. Si une requête est faite pour image.png
, la requête est redirigée vers /png-images/image.png
. Si une requête est faite pour image.jpg
, la requête est redirigée vers /jpg-images/image.jpg
. Le code d’état est défini sur 301 - Moved Permanently
, et context.Result
est défini de façon à cesser le traitement des règles et envoyer la réponse.
public class RedirectImageRequests : IRule
{
private readonly string _extension;
private readonly PathString _newPath;
public RedirectImageRequests(string extension, string newPath)
{
if (string.IsNullOrEmpty(extension))
{
throw new ArgumentException(nameof(extension));
}
if (!Regex.IsMatch(extension, @"^\.(png|jpg|gif)$"))
{
throw new ArgumentException("Invalid extension", nameof(extension));
}
if (!Regex.IsMatch(newPath, @"(/[A-Za-z0-9]+)+?"))
{
throw new ArgumentException("Invalid path", nameof(newPath));
}
_extension = extension;
_newPath = new PathString(newPath);
}
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because we're redirecting back to the same app, stop
// processing if the request has already been redirected
if (request.Path.StartsWithSegments(new PathString(_newPath)))
{
return;
}
if (request.Path.Value.EndsWith(_extension, StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
_newPath + request.Path + request.QueryString;
}
}
}
Requête d’origine : /image.png
Requête d’origine : /image.jpg
Exemples d’expressions régulières
Objectif | Chaîne d’expression régulière et exemple de correspondance |
Chaîne de remplacement et Exemple de sortie |
---|---|---|
Réécrire le chemin dans la chaîne de requête | ^path/(.*)/(.*) /path/abc/123 |
path?var1=$1&var2=$2 /path?var1=abc&var2=123 |
Supprimer la barre oblique finale | (.*)/$ /path/ |
$1 /path |
Appliquer une barre oblique finale | (.*[^/])$ /path |
$1/ /path/ |
Éviter la réécriture des requêtes spécifiques | ^(.*)(?<!\.axd)$ ou ^(?!.*\.axd$)(.*)$ Oui : /resource.htm Non : /resource.axd |
rewritten/$1 /rewritten/resource.htm /resource.axd |
Réorganiser les segments d’URL | path/(.*)/(.*)/(.*) path/1/2/3 |
path/$3/$2/$1 path/3/2/1 |
Remplacer un segment d’URL | ^(.*)/segment2/(.*) /segment1/segment2/segment3 |
$1/replaced/$2 /segment1/replaced/segment3 |
Ressources supplémentaires
- Affichez ou téléchargez l’exemple de code (procédure de téléchargement)
- Source de RewriteMiddleware sur GitHub
- Démarrage d’une application dans ASP.NET Core
- Intergiciel (middleware) ASP.NET Core
- Expressions régulières dans .NET
- Langage des expressions régulières - Aide-mémoire
- Apache mod_rewrite
- Utilisation du module de réécriture d’URL 2.0 (pour IIS)
- Informations de référence sur la configuration du module de réécriture d’URL
- Maintenir une structure d’URL simple
- 10 conseils et astuces pour la réécriture d’URL
- Mettre ou ne pas mettre une barre oblique