Middleware de reescritura de URL en ASP.NET Core
Nota:
Esta no es la versión más reciente de este artículo. Para la versión actual, consulte la versión .NET 8 de este artículo.
Advertencia
Esta versión de ASP.NET Core ya no se admite. Para obtener más información, consulte la Directiva de soporte técnico de .NET y .NET Core. Para la versión actual, consulte la versión .NET 8 de este artículo.
Importante
Esta información hace referencia a un producto en versión preliminar, el cual puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.
Para la versión actual, consulte la versión .NET 8 de este artículo.
Por Kirk Larkin y Rick Anderson
En este artículo se ofrece una introducción a la reescritura de URL e instrucciones sobre cómo usar el middleware de reescritura de URL en aplicaciones ASP.NET Core.
La reescritura de URL consiste en modificar varias URL de solicitud basadas en una o varias reglas predefinidas. La reescritura de URL crea una abstracción entre las ubicaciones de recursos y sus direcciones para que las ubicaciones y las direcciones no estén estrechamente vinculadas. La reescritura de URL es útil en varios escenarios para:
- Mover o reemplazar recursos del servidor de forma temporal o permanente a la vez que se mantienen localizadores estables para esos recursos.
- Dividir el procesamiento de solicitudes entre otras aplicaciones o entre áreas de una aplicación.
- Quitar, agregar o reorganizar segmentos de dirección URL en solicitudes entrantes.
- Optimizar direcciones URL públicas para la optimización del motor de búsqueda (SEO).
- Permitir el uso de direcciones URL públicas descriptivas para ayudar a los visitantes a predecir el contenido devuelto mediante la solicitud de un recurso.
- Redirigir solicitudes no seguras a puntos de conexión seguros.
- Evitar la vinculación activa, en la que un sitio externo usa un recurso estático hospedado en otro sitio mediante la vinculación del recurso a su propio contenido.
La reescritura de URL puede reducir el rendimiento de una aplicación. Limite el número y la complejidad de las reglas.
Redireccionamiento y reescritura de URL
La diferencia entre los términos redirección de URL y reescritura de URL es sutil, pero tiene importantes implicaciones para proporcionar recursos a los clientes. El middleware de reescritura de URL de ASP.NET Core es capaz de satisfacer las necesidades de ambos.
Una redirección de URL implica una operación del lado cliente, donde al cliente se le indica que acceda a un recurso en una dirección distinta a la que ha solicitado originalmente. Esto requiere un recorrido de ida y vuelta al servidor. La URL de redireccionamiento que se devuelve al cliente aparece en la barra de direcciones del explorador cuando el cliente realiza una nueva solicitud para el recurso.
Si /resource
se redirige a /different-resource
, el servidor responde que el cliente debe obtener el recurso en /different-resource
con un código de estado que indica que la redirección es temporal o permanente.
Al redirigir las solicitudes a otra dirección URL, se indica si la redirección es permanente o temporal mediante la especificación del código de estado con la respuesta:
El código de estado
301 - Moved Permanently
se usa cuando el recurso tiene una nueva dirección URL permanente y todas las solicitudes futuras para el recurso deben usar la nueva dirección URL. El cliente puede almacenar en caché la respuesta cuando se recibe un código de estado 301.El código de estado
302 - Found
se usa cuando el redireccionamiento es temporal o en general está sujeto a cambios. El código de estado 302 indica al cliente que no almacene la dirección URL y la use en el futuro.
Para más información sobre los códigos de estado, consulte RFC 9110: definiciones de código de estado.
La reescritura de URL es una operación del lado servidor que proporciona un recurso desde una dirección de recursos distinta a la que el cliente ha solicitado. La reescritura de una dirección URL no requiere un recorrido de ida y vuelta al servidor. La dirección URL reescrita no se devuelve al cliente y no aparece en la barra de direcciones del explorador.
Si /resource
se reescribe como /different-resource
, el servidor la obtiene internamente y devuelve el recurso en /different-resource
.
Aunque es posible que el cliente pueda recuperar el recurso en la dirección URL reescrita, no se le informa de que el recurso existe en la dirección URL reescrita cuando realiza su solicitud y recibe la respuesta.
Aplicación de ejemplo de reescritura de URL
Explore las características del middleware de reescritura de URL con la aplicación de ejemplo. La aplicación emplea las reglas de redireccionamiento y reescritura, y muestra la URL redirigida o reescrita para varios escenarios.
Cuándo usar el middleware de reescritura de URL
Use el middleware de reescritura de URL cuando no pueda usar los enfoques siguientes:
- Módulo de reescritura de URL con IIS en Windows Server
- Módulo mod_rewrite de Apache en el servidor Apache
- Reescritura de URL en Nginx
Utilice el middleware de reescritura de URL cuando la aplicación esté hospedada en el servidor HTTP.sys.
Las principales razones para usar la tecnologías de reescritura de URL basadas en servidor en IIS, Apache y Nginx son las siguientes:
El middleware no es compatible con todas las características de estos módulos.
Algunas de las características de los módulos de servidor no funcionan con proyectos de ASP.NET Core, como las restricciones
IsFile
yIsDirectory
del módulo de reescritura de IIS. En estos casos, es mejor usar el middleware.El rendimiento del middleware probablemente no coincida con el de los módulos.
La única manera de saber con certeza con qué enfoque el rendimiento disminuye más, o si la disminución de este es insignificante, es mediante una comparación.
Extensión y opciones
Establezca las reglas de reescritura y redirección de URL mediante la creación de una instancia de la clase RewriteOptions con métodos de extensión para cada una de las reglas de reescritura. Encadene varias reglas en el orden en que se deben procesar. Las RewriteOptions
se pasan al middleware de reescritura de URL cuando se agrega a la canalización de solicitudes con 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();
En el código anterior, MethodRules
es una clase definida por el usuario. Consulte RewriteRules.cs
este artículo para obtener más información.
Redirigir solicitudes que distintas de www a www
Hay tres opciones que permiten a la aplicación redirigir solicitudes distintas de www
a www
:
AddRedirectToWwwPermanent: redirige permanentemente la solicitud al subdominio
www
si la solicitud es distinta dewww
. Se redirige con un código de estado Status308PermanentRedirect.AddRedirectToWww: redirige la solicitud al subdominio
www
si la solicitud de entrada es distinta dewww
. Se redirige con un código de estado Status307TemporaryRedirect. Una sobrecarga permite proporcionar el código de estado para la respuesta. Use un campo de la clase StatusCodes para una asignación de código de estado.
Redirección de URL
Use AddRedirect para redirigir las solicitudes. El primer parámetro contiene la expresión regular de .NET (Regex) para hacer coincidir la ruta de acceso de la URL entrante. El segundo parámetro es la cadena de reemplazo. El tercer parámetro, si está presente, especifica el código de estado. Si no se especifica el código de estado, el valor predeterminado es 302 - Encontrado, lo que indica que el recurso se ha movido o reemplazado temporalmente.
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();
En un explorador con herramientas de desarrollo habilitadas, realice una solicitud a la aplicación de ejemplo con la ruta de acceso /redirect-rule/1234/5678
. La expresión regular coincide con la ruta de acceso de la solicitud en redirect-rule/(.*)
y la ruta de acceso se reemplaza por /redirected/1234/5678
. La dirección URL de redireccionamiento se devuelve al cliente con un código de estado 302 - Encontrado. El explorador realiza una solicitud nueva en la URL de redireccionamiento, que aparece en la barra de direcciones del explorador. Como ninguna de las reglas de la aplicación de ejemplo coincide con la dirección URL de redireccionamiento:
- La segunda solicitud recibe una respuesta 200: correcto de la aplicación.
- En el cuerpo de la respuesta se muestra la dirección URL de redireccionamiento.
Se realiza un recorrido de ida y vuelta al servidor cuando se redirige una dirección URL.
Advertencia
Tenga cuidado al establecer las reglas de redirección. Las reglas de redirección se evalúan en cada solicitud enviada a la aplicación, incluso después de una redirección. Es fácil crear por error un bucle de redirecciones infinitas.
La parte de la expresión incluida entre paréntesis se denomina grupo de capturas. El punto (.
) de la expresión significa buscar cualquier carácter. El asterisco (*
) indica buscar el carácter precedente cero o más veces. Por tanto, el grupo de capturas (.*)
busca los dos últimos segmentos de la ruta de acceso de la URL, 1234/5678
. Cualquier valor que se proporcione en la URL de la solicitud después de redirect-rule/
se captura por este grupo de capturas único.
En la cadena de reemplazo, se insertan los grupos capturados en la cadena con el signo de dólar ($
) seguido del número de secuencia de la captura. Se obtiene el valor del primer grupo de capturas con $1
, el segundo con $2
, y así siguen en secuencia para los grupos de capturas de la expresión regular. Solo hay un grupo capturado en la expresión regular de la regla de redirección de redirect-rule/(.*)
, por lo que solo hay un grupo insertado en la cadena de reemplazo, que es $1
. Cuando se aplica la regla, la URL se convierte en /redirected/1234/5678
.
Pruebe /redirect-rule/1234/5678
con las herramientas del explorador en la pestaña de red.
Redirección de URL a un punto de conexión segura
Use AddRedirectToHttps para redirigir las solicitudes HTTP al mismo host y ruta de acceso mediante el protocolo HTTPS. Si no se proporciona el código de estado, el middleware muestra de forma predeterminada 302 - Encontrado. Si no se proporciona el puerto:
- El middleware tiene como valor predeterminado
null
. - El esquema cambia a
https
(protocolo HTTPS), y el cliente accede al recurso en el puerto 443.
En el ejemplo siguiente se muestra cómo establecer el código de estado en 301 - Moved Permanently
y cambiar el puerto al puerto HTTPS utilizado por Kestrel en localhost. En producción, el puerto HTTPS se establece en 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();
Use AddRedirectToHttpsPermanent para redirigir las solicitudes no seguras al mismo host y ruta de acceso mediante el protocolo HTTPS seguro en el puerto 443. El middleware establece el código de estado en 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();
Nota
Al redirigir a un punto de conexión seguro sin la necesidad de reglas de redirección adicionales, se recomienda usar el Middleware de redirección de HTTPS. Para más información, vea Aplicación de HTTPS.
En esta aplicación de ejemplo se muestra cómo usar AddRedirectToHttps
o AddRedirectToHttpsPermanent
. Realice una solicitud HTTP poco segura a la aplicación en http://redirect6.azurewebsites.net/iis-rules-rewrite/xyz
. Al probar el redireccionamiento de HTTP a HTTPS con localhost:
- Use la dirección URL HTTP, que tiene un puerto diferente de la dirección URL HTTPS. La dirección URL HTTP está en el archivo
Properties/launchSettings.json
. - Se produce un error al quitar
s
dehttps://localhost/{port}
porque localhost no responde en HTTP al puerto HTTPS.
En la imagen siguiente se muestra la imagen de las herramientas del explorador F12 de una solicitud a http://redirect6.azurewebsites.net/iis-rules-rewrite/xyz
con el código anterior:
Reescritura de URL
Use AddRewrite para crear una regla para reescribir URL. El primer parámetro contiene la expresión regular para buscar coincidencias en la ruta de dirección de URL entrante. El segundo parámetro es la cadena de reemplazo. El tercer parámetro, skipRemainingRules: {true|false}
, indica al middleware si al aplicar la regla actual tiene que omitir o no alguna regla de redirección adicional.
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();
Prueba de la solicitud a https://redirect6.azurewebsites.net/rewrite-rule/1234/5678
El acento circunflejo (^
) al principio de la expresión significa que la búsqueda de coincidencias empieza al principio de la ruta de dirección URL.
En el ejemplo anterior de la regla de redireccionamiento (redirect-rule/(.*)
), no hay ningún acento circunflejo (^
) al principio de la expresión regular. Por tanto, cualquier carácter puede preceder a redirect-rule/
en la ruta de acceso para que la coincidencia sea correcta.
Ruta de acceso | Coincidir con |
---|---|
/redirect-rule/1234/5678 |
Sí |
/my-cool-redirect-rule/1234/5678 |
Sí |
/anotherredirect-rule/1234/5678 |
Sí |
La regla de reescritura, ^rewrite-rule/(\d+)/(\d+)
, solo encuentra rutas de acceso que empiezan con rewrite-rule/
. En la tabla siguiente, observe la diferencia de coincidencia.
Ruta de acceso | Coincidir con |
---|---|
/rewrite-rule/1234/5678 |
Sí |
/my-cool-rewrite-rule/1234/5678 |
No |
/anotherrewrite-rule/1234/5678 |
No |
Después de la parte ^rewrite-rule/
de la expresión, hay dos grupos de captura, (\d+)/(\d+)
. \d
significa buscar un dígito (número) . El signo más (+
) significa buscar uno o más de los caracteres anteriores. Por tanto, la URL debe contener un número seguido de una barra diagonal, seguida de otro número. Estos grupos de capturas se insertan en la URL de reescritura como $1
y $2
. La cadena de reemplazo de la regla de reescritura coloca los grupos capturados en la cadena de consulta. La ruta de acceso solicitada /rewrite-rule/1234/5678
se reescribe para obtener el recurso en /rewritten?var1=1234&var2=5678
. Si una cadena de consulta está presente en la solicitud original, se conserva cuando se reescribe la dirección URL.
No hay ningún recorrido de ida y vuelta al servidor para devolver el recurso. Si el recurso existe, se captura y se devuelve al cliente con un código de estado 200 - Correcto. Como el cliente no se redirige, la dirección URL no cambia en la barra de direcciones del explorador. Los clientes no pueden detectar que se ha producido una operación de reescritura de URL en el servidor.
Sugerencias de rendimiento para la reescritura y redireccionamiento de direcciones URL
Para obtener la respuesta más rápida de la aplicación:
- Ordene las reglas de reescritura desde la que coincida con más frecuencia a la que coincida con menos frecuencia.
- Use
skipRemainingRules: true
siempre que sea posible, ya que las reglas de coincidencia consumen muchos recursos y aumentan el tiempo de respuesta de aplicación. Omita el procesamiento de las reglas restantes cuando se produzca una coincidencia; no es necesario ningún procesamiento de reglas adicional.
Advertencia
Un usuario malintencionado puede proporcionar una entrada costosa de procesar a RegularExpressions
y provocar un ataque por denegación de servicio. Las API del marco ASP.NET Core en las que se usa RegularExpressions
pasan un tiempo de expiración. Por ejemplo, las clases RedirectRule y RewriteRule pasan un tiempo de espera de un segundo.
mod_rewrite de Apache
Aplique reglas mod_rewrite de Apache con AddApacheModRewrite. Asegúrese de que el archivo de reglas se implementa con la aplicación. Para obtener más información y ejemplos de reglas mod_rewrite, vea Apache mod_rewrite (mod_rewrite de Apache).
Se usa StreamReader para leer las reglas del archivo de reglas 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();
La aplicación de ejemplo redirige las solicitudes de /apache-mod-rules-redirect/(.\*)
a /redirected?id=$1
. El código de estado de la respuesta es 302: Encontrado.
# Rewrite path with additional sub directory
RewriteRule ^/apache-mod-rules-redirect/(.*) /redirected?id=$1 [L,R=302]
Prueba de la solicitud a https://redirect6.azurewebsites.net/apache-mod-rules-redirect/1234
El middleware Apache admite las siguientes variables de servidor mod_rewrite de Apache:
- CONN_REMOTE_ADDR
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_FORWARDED
- HTTP_HOST
- HTTP_REFERER
- HTTP_USER_AGENT
- HTTPS
- IPV6
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_METHOD
- REQUEST_SCHEME
- REQUEST_URI
- SCRIPT_FILENAME
- SERVER_ADDR
- SERVER_PORT
- SERVER_PROTOCOL
- TIME
- TIME_DAY
- TIME_HOUR
- TIME_MIN
- TIME_MON
- TIME_SEC
- TIME_WDAY
- TIME_YEAR
Reglas del Módulo URL Rewrite para IIS
Para usar el mismo conjunto de reglas que se aplica al módulo URL Rewrite para IIS, use AddIISUrlRewrite. Asegúrese de que el archivo de reglas se implementa con la aplicación. No dirija el middleware para que use el archivo web.config de la aplicación cuando se ejecute en Windows Server IIS. Con IIS, estas reglas se deben almacenar fuera del archivo web.config de la aplicación para evitar conflictos con el Módulo URL Rewrite para IIS. Para obtener más información y ejemplos de reglas del Módulo URL Rewrite para IIS, vea Using Url Rewrite Module 2.0 (Uso del Módulo URL Rewrite 2.0) y URL Rewrite Module Configuration Reference (Referencia de configuración del Módulo URL Rewrite).
Se usa StreamReader para leer las reglas del archivo de reglas 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();
La aplicación de ejemplo reescribe las solicitudes de /iis-rules-rewrite/(.*)
a /rewritten?id=$1
. La respuesta se envía al cliente con un código de estado 200 - Correcto.
<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>
Prueba de la solicitud a https://redirect6.azurewebsites.net/iis-rules-rewrite/xyz
Aplicaciones que tienen un módulo de reescritura de IIS activo con reglas de nivel de servidor configuradas que afectan a la aplicación de maneras no deseadas:
- Considere la posibilidad de deshabilitar el módulo de reescritura de IIS para la aplicación.
- Para más información, vea Disabling IIS modules (Deshabilitación de módulos de IIS).
Características no admitidas
El middleware no admite las siguientes características de Módulo URL Rewrite para IIS:
- Reglas de salida
- Variables de servidor personalizadas
- Caracteres comodín
- LogRewrittenUrl
Variables de servidor compatibles
El middleware admite las siguientes variables de servidor del Módulo URL Rewrite para IIS:
- CONTENT_LENGTH
- CONTENT_TYPE
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_HOST
- HTTP_REFERER
- HTTP_URL
- HTTP_USER_AGENT
- HTTPS
- LOCAL_ADDR
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_URI
IFileProvider puede obtenerse a través de PhysicalFileProvider. Con este enfoque logrará mayor flexibilidad para la ubicación de los archivos de reglas de reescritura. Asegúrese de que los archivos de reglas de reescritura se implementan en el servidor en la ruta de acceso que proporcione.
var fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
Regla basada en métodos
Use Add para implementar la lógica de la regla personalizada en un método. Add
expone el elemento RewriteContext, lo que hace que HttpContext esté disponible para usarlo en métodos de redireccionamiento. La propiedad RewriteContext.Result determina cómo se administra el procesamiento adicional en la canalización. Establezca el valor en uno de los campos RuleResult que se describen en la tabla siguiente.
Volver a escribir el resultado del contexto | Acción |
---|---|
RuleResult.ContinueRules (valor predeterminado) |
Continuar aplicando las reglas. |
RuleResult.EndResponse |
Dejar de aplicar las reglas y enviar la respuesta. |
RuleResult.SkipRemainingRules |
Dejar de aplicar las reglas y enviar el contexto al middleware siguiente. |
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();
La aplicación de ejemplo muestra un método que redirige las solicitudes para las rutas de acceso que terminen con .xml
. Cuando se realiza una solicitud a /file.xml
:
- La solicitud se redirige a
/xmlfiles/file.xml
. - El código de estado se establece en
301 - Moved Permanently
. Cuando el explorador realiza una solicitud nueva a/xmlfiles/file.xml
, el middleware de archivos estáticos sirve el archivo al cliente desde la carpeta wwwroot/xmlfiles. Para un redireccionamiento, debe establecer de forma explícita el código de estado de la respuesta. En caso contrario, se devuelve un código de estado 200: correcto y no se produce el redireccionamiento en el cliente.
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;
}
}
Este enfoque también permite volver a escribir las solicitudes. En la aplicación de ejemplo se muestra cómo volver a escribir la ruta de acceso para cualquier solicitud de archivo de texto para proporcionar el archivo de texto file.txt desde la carpeta wwwroot. El middleware de archivos estáticos proporciona el archivo en función de la ruta de acceso de la solicitud actualizada:
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";
}
}
Regla basada en IRule
Utilice Add para usar la lógica de reglas en una clase que implemente la interfaz IRule. IRule
proporciona mayor flexibilidad que si se usa el enfoque de reglas basadas en métodos. La clase de implementación puede incluir un constructor que permita pasar parámetros para el método 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();
Se comprueba que los valores de los parámetros en la aplicación de ejemplo para extension
y newPath
cumplen ciertas condiciones. extension
debe contener un valor, que debe ser .png
, .jpg
o .gif
. Si newPath
no es válido, se genera ArgumentException . Si se realiza una solicitud de image.png
, la solicitud se redirige a /png-images/image.png
. Si se realiza una solicitud de image.jpg
, la solicitud se redirige a /jpg-images/image.jpg
. El código de estado se establece en 301 - Moved Permanently
, y context.Result
se establece para detener el procesamiento de las reglas y enviar la respuesta.
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;
}
}
}
Pruebe lo siguiente:
- Solicitud PNG:
https://redirect6.azurewebsites.net/image.png
- Solicitud JPG:
https://redirect6.azurewebsites.net/image.jpg
Ejemplos de expresiones regulares
Objetivo | Cadena de expresión regular & Ejemplo de coincidencia |
Cadena de reemplazo & Ejemplo de resultado |
---|---|---|
Ruta de acceso de reescritura en la cadena de consulta | ^path/(.*)/(.*) /path/abc/123 |
path?var1=$1&var2=$2 /path?var1=abc&var2=123 |
Quitar barra diagonal final | ^path2/(.*)/$ /path2/xyz/ |
$1 /path2/xyz |
Exigir barra diagonal final | ^path3/(.*[^/])$ /path3/xyz |
$1/ /path3/xyz/ |
Evitar reescritura de solicitudes específicas | ^(.*)(?<!\.axd)$ , o bien ^(?!.*\.axd$)(.*)$ Sí: /path4/resource.htm No: /path4/resource.axd |
rewritten/$1 /rewritten/resource.htm /resource.axd |
Reorganizar los segmentos de URL | path5/(.*)/(.*)/(.*) path5/1/2/3 |
path5/$3/$2/$1 path5/3/2/1 |
Reemplazar un segmento de URL | ^path6/(.*)/segment2/(.*) ^path6/segment1/segment2/segment3 |
path6/$1/replaced/$2 /path6/segment1/replaced/segment3 |
Los vínculos de la tabla anterior usan el código siguiente implementado en 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();
En la mayoría de los ejemplos de expresiones regulares anteriores, el literal path
se usa para crear reglas únicas de reescritura que se pueden probar para el ejemplo implementado. Normalmente, la expresión regular no incluiría path
. Por ejemplo, consulte esta tabla de ejemplos de expresiones regulares.
En este documento se ofrece una introducción a la reescritura de URL e instrucciones sobre cómo usar el middleware de reescritura de URL en aplicaciones ASP.NET Core.
La reescritura de URL consiste en modificar varias URL de solicitud basadas en una o varias reglas predefinidas. La reescritura de URL crea una abstracción entre las ubicaciones de recursos y sus direcciones para que las ubicaciones y las direcciones no estén estrechamente vinculadas. La reescritura de URL es útil en varios escenarios para:
- Mover o reemplazar recursos del servidor de forma temporal o permanente a la vez que se mantienen localizadores estables para esos recursos.
- Dividir el procesamiento de solicitudes entre otras aplicaciones o entre áreas de una aplicación.
- Quitar, agregar o reorganizar segmentos de dirección URL en solicitudes entrantes.
- Optimizar direcciones URL públicas para la optimización del motor de búsqueda (SEO).
- Permitir el uso de direcciones URL públicas descriptivas para ayudar a los visitantes a predecir el contenido devuelto mediante la solicitud de un recurso.
- Redirigir solicitudes no seguras a puntos de conexión seguros.
- Evitar la vinculación activa, en la que un sitio externo usa un recurso estático hospedado en otro sitio mediante la vinculación del recurso a su propio contenido.
Nota
La reescritura de URL puede reducir el rendimiento de una aplicación. Cuando sea factible, limite el número y la complejidad de las reglas.
Vea o descargue el código de ejemplo (cómo descargarlo)
Redireccionamiento y reescritura de URL
La diferencia entre los términos redirección de URL y reescritura de URL es sutil, pero tiene importantes implicaciones para proporcionar recursos a los clientes. El middleware de reescritura de URL de ASP.NET Core es capaz de satisfacer las necesidades de ambos.
Una redirección de URL implica una operación del lado cliente, donde al cliente se le indica que acceda a un recurso en una dirección distinta a la que ha solicitado originalmente. Esto requiere un recorrido de ida y vuelta al servidor. La URL de redireccionamiento que se devuelve al cliente aparece en la barra de direcciones del explorador cuando el cliente realiza una nueva solicitud para el recurso.
Si /resource
se redirige a /different-resource
, el servidor responde que el cliente debe obtener el recurso en /different-resource
con un código de estado que indica que la redirección es temporal o permanente.
Al redirigir las solicitudes a otra dirección URL, se indica si la redirección es permanente o temporal mediante la especificación del código de estado con la respuesta:
El código de estado
301 - Moved Permanently
se usa cuando el recurso tiene una nueva dirección URL permanente y se quiere indicar al cliente que todas las solicitudes futuras para el recurso deben usar la nueva dirección URL. El cliente puede almacenar en caché la respuesta cuando se recibe un código de estado 301.El código de estado 302: encontrado se usa cuando el redireccionamiento es temporal o en general está sujeto a cambios. El código de estado 302 indica al cliente que no almacene la dirección URL y la use en el futuro.
Para más información sobre los códigos de estado, consulte RFC 9110: definiciones de código de estado.
La reescritura de URL es una operación del lado servidor que proporciona un recurso desde una dirección de recursos distinta a la que el cliente ha solicitado. La reescritura de una dirección URL no requiere un recorrido de ida y vuelta al servidor. La dirección URL reescrita no se devuelve al cliente y no aparece en la barra de direcciones del explorador.
Si /resource
se reescribe como /different-resource
, el servidor la obtiene internamente y devuelve el recurso en /different-resource
.
Aunque es posible que el cliente pueda recuperar el recurso en la dirección URL reescrita, no se le informa de que el recurso existe en la dirección URL reescrita cuando realiza su solicitud y recibe la respuesta.
Aplicación de ejemplo de reescritura de URL
Puede explorar las características del middleware de reescritura de URL con la aplicación de ejemplo. La aplicación emplea las reglas de redireccionamiento y reescritura, y muestra la URL redirigida o reescrita para varios escenarios.
Cuándo usar el middleware de reescritura de URL
Use el middleware de reescritura de URL cuando no pueda usar los enfoques siguientes:
- Módulo de reescritura de URL con IIS en Windows Server
- Módulo mod_rewrite de Apache en el servidor Apache
- Reescritura de URL en Nginx
Utilice el middleware de reescritura de URL cuando la aplicación esté hospedada en el servidor HTTP.sys.
Las principales razones para usar la tecnologías de reescritura de URL basadas en servidor en IIS, Apache y Nginx son las siguientes:
El middleware no es compatible con todas las características de estos módulos.
Algunas de las características de los módulos de servidor no funcionan con proyectos de ASP.NET Core, como las restricciones
IsFile
yIsDirectory
del módulo de reescritura de IIS. En estos casos, es mejor usar el middleware.El rendimiento del middleware probablemente no coincida con el de los módulos.
La única manera de saber con certeza con qué enfoque el rendimiento disminuye más, o si la disminución de este es insignificante, es mediante una comparación.
Package
El middleware de reescritura de URL está disponible en el paquete Microsoft.AspNetCore.Rewrite, incluido implícitamente en las aplicaciones ASP.NET Core.
Extensión y opciones
Establezca las reglas de reescritura y redirección de URL mediante la creación de una instancia de la clase RewriteOptions con métodos de extensión para cada una de las reglas de reescritura. Encadene varias reglas en el orden que quiera procesarlas. Las RewriteOptions
se pasan al middleware de reescritura de URL cuando se agrega a la canalización de solicitudes con 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}"));
}
Redirigir solicitudes que distintas de www a www
Hay tres opciones que permiten a la aplicación redirigir solicitudes distintas de www
a www
:
AddRedirectToWwwPermanent: redirige permanentemente la solicitud al subdominio
www
si la solicitud es distinta dewww
. Se redirige con un código de estado Status308PermanentRedirect.AddRedirectToWww: redirige la solicitud al subdominio
www
si la solicitud de entrada es distinta dewww
. Se redirige con un código de estado Status307TemporaryRedirect. Una sobrecarga permite proporcionar el código de estado para la respuesta. Use un campo de la clase StatusCodes para una asignación de código de estado.
Redirección de URL
Use AddRedirect para redirigir las solicitudes. El primer parámetro contiene la expresión regular para hacer coincidir la ruta de acceso de la URL entrante. El segundo parámetro es la cadena de reemplazo. El tercer parámetro, si está presente, especifica el código de estado. Si no se especifica el código de estado, el valor predeterminado es 302 - Encontrado, lo que indica que el recurso se ha movido o reemplazado temporalmente.
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}"));
}
En un explorador con herramientas de desarrollo habilitadas, realice una solicitud a la aplicación de ejemplo con la ruta de acceso /redirect-rule/1234/5678
. La expresión regular coincide con la ruta de acceso de la solicitud en redirect-rule/(.*)
y la ruta de acceso se reemplaza con /redirected/1234/5678
. La dirección URL de redireccionamiento se devuelve al cliente con un código de estado 302 - Encontrado. El explorador realiza una solicitud nueva en la URL de redireccionamiento, que aparece en la barra de direcciones del explorador. Como ninguna de las reglas de la aplicación de ejemplo coincide con la dirección URL de redireccionamiento:
- La segunda solicitud recibe una respuesta 200: correcto de la aplicación.
- En el cuerpo de la respuesta se muestra la dirección URL de redireccionamiento.
Se realiza un recorrido de ida y vuelta al servidor cuando se redirige una dirección URL.
Advertencia
Tenga cuidado al establecer las reglas de redirección. Las reglas de redirección se evalúan en cada solicitud enviada a la aplicación, incluso después de una redirección. Es fácil crear por error un bucle de redirecciones infinitas.
Solicitud original: /redirect-rule/1234/5678
La parte de la expresión incluida entre paréntesis se denomina grupo de capturas. El punto (.
) de la expresión significa buscar cualquier carácter. El asterisco (*
) indica buscar el carácter precedente cero o más veces. Por tanto, el grupo de capturas (.*)
busca los dos últimos segmentos de la ruta de acceso de la URL, 1234/5678
. Cualquier valor que se proporcione en la URL de la solicitud después de redirect-rule/
es capturado por este grupo de capturas único.
En la cadena de reemplazo, se insertan los grupos capturados en la cadena con el signo de dólar ($
) seguido del número de secuencia de la captura. Se obtiene el valor del primer grupo de capturas con $1
, el segundo con $2
, y así siguen en secuencia para los grupos de capturas de la expresión regular. Solo hay un grupo capturado en la expresión regular de la regla de redirección de la aplicación de ejemplo, por lo que solo hay un grupo insertado en la cadena de reemplazo, que es $1
. Cuando se aplica la regla, la URL se convierte en /redirected/1234/5678
.
Redirección de URL a un punto de conexión segura
Use AddRedirectToHttps para redirigir las solicitudes HTTP al mismo host y ruta de acceso mediante el protocolo HTTPS. Si no se proporciona el código de estado, el middleware muestra de forma predeterminada 302 - Encontrado. Si no se proporciona el puerto:
- El middleware tiene como valor predeterminado
null
. - El esquema cambia a
https
(protocolo HTTPS), y el cliente accede al recurso en el puerto 443.
En el ejemplo siguiente se muestra cómo establecer el código de estado en 301 - Moved Permanently
y cambiar el puerto a 5001.
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttps(301, 5001);
app.UseRewriter(options);
}
Use AddRedirectToHttpsPermanent para redirigir las solicitudes no seguras al mismo host y ruta de acceso mediante el protocolo HTTPS seguro en el puerto 443. El middleware establece el código de estado en 301 - Moved Permanently
.
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent();
app.UseRewriter(options);
}
Nota
Al redirigir a un punto de conexión seguro sin la necesidad de reglas de redirección adicionales, se recomienda usar el Middleware de redirección de HTTPS. Para más información, vea el tema Aplicación de HTTPS.
La aplicación de ejemplo es capaz de mostrar cómo usar AddRedirectToHttps
o AddRedirectToHttpsPermanent
. Agregue el método de extensión a RewriteOptions
. Realice una solicitud poco segura a la aplicación en cualquier URL. Descarte la advertencia de seguridad del explorador que indica que el certificado autofirmado no es de confianza o cree una excepción para confiar en el certificado en cuestión.
Solicitud original mediante AddRedirectToHttps(301, 5001)
: http://localhost:5000/secure
Solicitud original mediante AddRedirectToHttpsPermanent
: http://localhost:5000/secure
Reescritura de URL
Use AddRewrite para crear una regla para reescribir URL. El primer parámetro contiene la expresión regular para buscar coincidencias en la ruta de dirección de URL entrante. El segundo parámetro es la cadena de reemplazo. El tercer parámetro, skipRemainingRules: {true|false}
, indica al middleware si al aplicar la regla actual tiene que omitir o no alguna regla de redirección adicional.
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}"));
}
Solicitud original: /rewrite-rule/1234/5678
El acento circunflejo (^
) al principio de la expresión significa que la búsqueda de coincidencias empieza al principio de la ruta de dirección URL.
En el ejemplo anterior de la regla de redireccionamiento (redirect-rule/(.*)
), no hay ningún acento circunflejo (^
) al principio de la expresión regular. Por tanto, cualquier carácter puede preceder a redirect-rule/
en la ruta de acceso para que la coincidencia sea correcta.
Ruta de acceso | Coincidir con |
---|---|
/redirect-rule/1234/5678 |
Sí |
/my-cool-redirect-rule/1234/5678 |
Sí |
/anotherredirect-rule/1234/5678 |
Sí |
La regla de reescritura, ^rewrite-rule/(\d+)/(\d+)
, solo encuentra rutas de acceso que empiezan con rewrite-rule/
. En la tabla siguiente, observe la diferencia de coincidencia.
Ruta de acceso | Coincidir con |
---|---|
/rewrite-rule/1234/5678 |
Sí |
/my-cool-rewrite-rule/1234/5678 |
No |
/anotherrewrite-rule/1234/5678 |
No |
Después de la parte ^rewrite-rule/
de la expresión, hay dos grupos de captura, (\d+)/(\d+)
. \d
significa buscar un dígito (número) . El signo más (+
) significa buscar uno o más de los caracteres anteriores. Por tanto, la URL debe contener un número seguido de una barra diagonal, seguida de otro número. Estos grupos de capturas se insertan en la URL de reescritura como $1
y $2
. La cadena de reemplazo de la regla de reescritura coloca los grupos capturados en la cadena de consulta. La ruta de acceso solicitada de /rewrite-rule/1234/5678
se reescribe para obtener el recurso en /rewritten?var1=1234&var2=5678
. Si una cadena de consulta está presente en la solicitud original, se conserva cuando se reescribe la dirección URL.
No hay ningún recorrido de ida y vuelta al servidor para obtener el recurso. Si el recurso existe, se captura y se devuelve al cliente con un código de estado 200 - Correcto. Como el cliente no se redirige, la dirección URL no cambia en la barra de direcciones del explorador. Los clientes no pueden detectar que se ha producido una operación de reescritura de URL en el servidor.
Nota
Use skipRemainingRules: true
siempre que sea posible, ya que las reglas de coincidencia consumen muchos recursos y aumentan el tiempo de respuesta de aplicación. Para obtener la respuesta más rápida de la aplicación:
- Ordene las reglas de reescritura desde la que coincida con más frecuencia a la que coincida con menos frecuencia.
- Omita el procesamiento de las reglas restantes cuando se produzca una coincidencia; no es necesario ningún procesamiento de reglas adicional.
mod_rewrite de Apache
Aplique reglas mod_rewrite de Apache con AddApacheModRewrite. Asegúrese de que el archivo de reglas se implementa con la aplicación. Para obtener más información y ejemplos de reglas mod_rewrite, vea Apache mod_rewrite (mod_rewrite de Apache).
Se usa StreamReader para leer las reglas del archivo de reglas 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}"));
}
La aplicación de ejemplo redirige las solicitudes de /apache-mod-rules-redirect/(.\*)
a /redirected?id=$1
. El código de estado de la respuesta es 302: Encontrado.
# Rewrite path with additional sub directory
RewriteRule ^/apache-mod-rules-redirect/(.*) /redirected?id=$1 [L,R=302]
Solicitud original: /apache-mod-rules-redirect/1234
El middleware admite las siguientes variables de servidor mod_rewrite de Apache:
- CONN_REMOTE_ADDR
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_FORWARDED
- HTTP_HOST
- HTTP_REFERER
- HTTP_USER_AGENT
- HTTPS
- IPV6
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_METHOD
- REQUEST_SCHEME
- REQUEST_URI
- SCRIPT_FILENAME
- SERVER_ADDR
- SERVER_PORT
- SERVER_PROTOCOL
- TIME
- TIME_DAY
- TIME_HOUR
- TIME_MIN
- TIME_MON
- TIME_SEC
- TIME_WDAY
- TIME_YEAR
Reglas del Módulo URL Rewrite para IIS
Para usar el mismo conjunto de reglas que se aplica al módulo URL Rewrite para IIS, use AddIISUrlRewrite. Asegúrese de que el archivo de reglas se implementa con la aplicación. No dirija el middleware para que use el archivo web.config de la aplicación cuando se ejecute en Windows Server IIS. Con IIS, estas reglas se deben almacenar fuera del archivo web.config de la aplicación para evitar conflictos con el Módulo URL Rewrite para IIS. Para obtener más información y ejemplos de reglas del Módulo URL Rewrite para IIS, vea Using Url Rewrite Module 2.0 (Uso del Módulo URL Rewrite 2.0) y URL Rewrite Module Configuration Reference (Referencia de configuración del Módulo URL Rewrite).
Se usa StreamReader para leer las reglas del archivo de reglas 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}"));
}
La aplicación de ejemplo reescribe las solicitudes de /iis-rules-rewrite/(.*)
a /rewritten?id=$1
. La respuesta se envía al cliente con un código de estado 200 - Correcto.
<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>
Solicitud original: /iis-rules-rewrite/1234
Si tiene un Módulo URL Rewrite para IIS activo con reglas configuradas en el nivel de servidor que podrían afectar a la aplicación de manera no deseada, puede deshabilitar el Módulo URL Rewrite para IIS para una aplicación. Para más información, vea Disabling IIS modules (Deshabilitación de módulos de IIS).
Características no admitidas
El middleware no admite las siguientes características de Módulo URL Rewrite para IIS:
- Reglas de salida
- Variables de servidor personalizadas
- Caracteres comodín
- LogRewrittenUrl
Variables de servidor compatibles
El middleware admite las siguientes variables de servidor del Módulo URL Rewrite para IIS:
- 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
Nota
También puede obtener IFileProvider a través de PhysicalFileProvider. Con este enfoque logrará mayor flexibilidad para la ubicación de los archivos de reglas de reescritura. Asegúrese de que los archivos de reglas de reescritura se implementan en el servidor en la ruta de acceso que proporcione.
PhysicalFileProvider fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
Regla basada en métodos
Use Add para implementar su propia lógica de la regla en un método. Add
expone el elemento RewriteContext, lo que hace que HttpContext esté disponible para usarlo en el método. RewriteContext.Result determina cómo se administra el procesamiento adicional en la canalización. Establezca el valor en uno de los campos RuleResult que se describen en la tabla siguiente.
Volver a escribir el resultado del contexto | Acción |
---|---|
RuleResult.ContinueRules (valor predeterminado) |
Continuar aplicando las reglas. |
RuleResult.EndResponse |
Dejar de aplicar las reglas y enviar la respuesta. |
RuleResult.SkipRemainingRules |
Dejar de aplicar las reglas y enviar el contexto al middleware siguiente. |
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}"));
}
La aplicación de ejemplo muestra un método que redirige las solicitudes para las rutas de acceso que terminen con .xml
. Si se realiza una solicitud de /file.xml
, la solicitud se redirige a /xmlfiles/file.xml
. El código de estado se establece en 301 - Moved Permanently
. Cuando el explorador realiza una solicitud nueva a /xmlfiles/file.xml
, el middleware de archivos estáticos sirve el archivo al cliente desde la carpeta wwwroot/xmlfiles. Para un redireccionamiento, debe establecer de forma explícita el código de estado de la respuesta. En caso contrario, se devuelve un código de estado 200: correcto y no se produce el redireccionamiento en el cliente.
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;
}
}
Este enfoque también permite volver a escribir las solicitudes. En la aplicación de ejemplo se muestra cómo volver a escribir la ruta de acceso para cualquier solicitud de archivo de texto para proporcionar el archivo de texto file.txt desde la carpeta wwwroot. El middleware de archivos estáticos proporciona el archivo en función de la ruta de acceso de la solicitud actualizada:
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";
}
}
Regla basada en IRule
Utilice Add para usar la lógica de reglas en una clase que implemente la interfaz IRule. IRule
proporciona mayor flexibilidad que si se usa el enfoque de reglas basadas en métodos. La clase de implementación puede incluir un constructor que permita pasar parámetros para el método 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}"));
}
Se comprueba que los valores de los parámetros en la aplicación de ejemplo para extension
y newPath
cumplen ciertas condiciones. extension
debe contener un valor, que debe ser .png
, .jpg
o .gif. Si newPath
no es válido, se genera ArgumentException . Si se realiza una solicitud de image.png
, la solicitud se redirige a /png-images/image.png
. Si se realiza una solicitud de image.jpg
, la solicitud se redirige a /jpg-images/image.jpg
. El código de estado se establece en 301 - Moved Permanently
, y context.Result
se establece para detener el procesamiento de las reglas y enviar la respuesta.
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;
}
}
}
Solicitud original: /image.png
Solicitud original: /image.jpg
Ejemplos de expresiones regulares
Objetivo | Cadena de expresión regular & Ejemplo de coincidencia |
Cadena de reemplazo & Ejemplo de resultado |
---|---|---|
Ruta de acceso de reescritura en la cadena de consulta | ^path/(.*)/(.*) /path/abc/123 |
path?var1=$1&var2=$2 /path?var1=abc&var2=123 |
Quitar barra diagonal final | (.*)/$ /path/ |
$1 /path |
Exigir barra diagonal final | (.*[^/])$ /path |
$1/ /path/ |
Evitar reescritura de solicitudes específicas | ^(.*)(?<!\.axd)$ o ^(?!.*\.axd$)(.*)$ Sí: /resource.htm No: /resource.axd |
rewritten/$1 /rewritten/resource.htm /resource.axd |
Reorganizar los segmentos de URL | path/(.*)/(.*)/(.*) path/1/2/3 |
path/$3/$2/$1 path/3/2/1 |
Reemplazar un segmento de URL | ^(.*)/segment2/(.*) /segment1/segment2/segment3 |
$1/replaced/$2 /segment1/replaced/segment3 |
En este documento se ofrece una introducción a la reescritura de URL e instrucciones sobre cómo usar el middleware de reescritura de URL en aplicaciones ASP.NET Core.
La reescritura de URL consiste en modificar varias URL de solicitud basadas en una o varias reglas predefinidas. La reescritura de URL crea una abstracción entre las ubicaciones de recursos y sus direcciones para que las ubicaciones y las direcciones no estén estrechamente vinculadas. La reescritura de URL es útil en varios escenarios para:
- Mover o reemplazar recursos del servidor de forma temporal o permanente a la vez que se mantienen localizadores estables para esos recursos.
- Dividir el procesamiento de solicitudes entre otras aplicaciones o entre áreas de una aplicación.
- Quitar, agregar o reorganizar segmentos de dirección URL en solicitudes entrantes.
- Optimizar direcciones URL públicas para la optimización del motor de búsqueda (SEO).
- Permitir el uso de direcciones URL públicas descriptivas para ayudar a los visitantes a predecir el contenido devuelto mediante la solicitud de un recurso.
- Redirigir solicitudes no seguras a puntos de conexión seguros.
- Evitar la vinculación activa, en la que un sitio externo usa un recurso estático hospedado en otro sitio mediante la vinculación del recurso a su propio contenido.
Nota
La reescritura de URL puede reducir el rendimiento de una aplicación. Cuando sea factible, limite el número y la complejidad de las reglas.
Vea o descargue el código de ejemplo (cómo descargarlo)
Redireccionamiento y reescritura de URL
La diferencia entre los términos redirección de URL y reescritura de URL es sutil, pero tiene importantes implicaciones para proporcionar recursos a los clientes. El middleware de reescritura de URL de ASP.NET Core es capaz de satisfacer las necesidades de ambos.
Una redirección de URL implica una operación del lado cliente, donde al cliente se le indica que acceda a un recurso en una dirección distinta a la que ha solicitado originalmente. Esto requiere un recorrido de ida y vuelta al servidor. La URL de redireccionamiento que se devuelve al cliente aparece en la barra de direcciones del explorador cuando el cliente realiza una nueva solicitud para el recurso.
Si /resource
se redirige a /different-resource
, el servidor responde que el cliente debe obtener el recurso en /different-resource
con un código de estado que indica que la redirección es temporal o permanente.
Al redirigir las solicitudes a otra dirección URL, se indica si la redirección es permanente o temporal mediante la especificación del código de estado con la respuesta:
El código de estado
301 - Moved Permanently
se usa cuando el recurso tiene una nueva dirección URL permanente y se quiere indicar al cliente que todas las solicitudes futuras para el recurso deben usar la nueva dirección URL. El cliente puede almacenar en caché la respuesta cuando se recibe un código de estado 301.El código de estado 302: encontrado se usa cuando el redireccionamiento es temporal o en general está sujeto a cambios. El código de estado 302 indica al cliente que no almacene la dirección URL y la use en el futuro.
Para más información sobre los códigos de estado, consulte RFC 9110: definiciones de código de estado.
La reescritura de URL es una operación del lado servidor que proporciona un recurso desde una dirección de recursos distinta a la que el cliente ha solicitado. La reescritura de una dirección URL no requiere un recorrido de ida y vuelta al servidor. La dirección URL reescrita no se devuelve al cliente y no aparece en la barra de direcciones del explorador.
Si /resource
se reescribe como /different-resource
, el servidor la obtiene internamente y devuelve el recurso en /different-resource
.
Aunque es posible que el cliente pueda recuperar el recurso en la dirección URL reescrita, no se le informa de que el recurso existe en la dirección URL reescrita cuando realiza su solicitud y recibe la respuesta.
Aplicación de ejemplo de reescritura de URL
Puede explorar las características del middleware de reescritura de URL con la aplicación de ejemplo. La aplicación emplea las reglas de redireccionamiento y reescritura, y muestra la URL redirigida o reescrita para varios escenarios.
Cuándo usar el middleware de reescritura de URL
Use el middleware de reescritura de URL cuando no pueda usar los enfoques siguientes:
- Módulo de reescritura de URL con IIS en Windows Server
- Módulo mod_rewrite de Apache en el servidor Apache
- Reescritura de URL en Nginx
Además, use el middleware cuando la aplicación se hospede en el servidor HTTP.sys (anteriormente denominado WebListener).
Las principales razones para usar la tecnologías de reescritura de URL basadas en servidor en IIS, Apache y Nginx son las siguientes:
El middleware no es compatible con todas las características de estos módulos.
Algunas de las características de los módulos de servidor no funcionan con proyectos de ASP.NET Core, como las restricciones
IsFile
yIsDirectory
del módulo de reescritura de IIS. En estos casos, es mejor usar el middleware.El rendimiento del middleware probablemente no coincida con el de los módulos.
La única manera de saber con certeza con qué enfoque el rendimiento disminuye más, o si la disminución de este es insignificante, es mediante una comparación.
Package
Para incluir el middleware en el proyecto, agregue una referencia de paquete al metapaquete Microsoft.AspNetCore.App del archivo de proyecto, que contiene el paquete Microsoft.AspNetCore.Rewrite.
Si no se usa el metapaquete Microsoft.AspNetCore.App
, agregue una referencia de proyecto al paquete Microsoft.AspNetCore.Rewrite
.
Extensión y opciones
Establezca las reglas de reescritura y redirección de URL mediante la creación de una instancia de la clase RewriteOptions con métodos de extensión para cada una de las reglas de reescritura. Encadene varias reglas en el orden que quiera procesarlas. Las RewriteOptions
se pasan al middleware de reescritura de URL cuando se agrega a la canalización de solicitudes con 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}"));
}
Redirigir solicitudes que distintas de www a www
Hay tres opciones que permiten a la aplicación redirigir solicitudes distintas de www
a www
:
AddRedirectToWwwPermanent: redirige permanentemente la solicitud al subdominio
www
si la solicitud es distinta dewww
. Se redirige con un código de estado Status308PermanentRedirect.AddRedirectToWww: redirige la solicitud al subdominio
www
si la solicitud de entrada es distinta dewww
. Se redirige con un código de estado Status307TemporaryRedirect. Una sobrecarga permite proporcionar el código de estado para la respuesta. Use un campo de la clase StatusCodes para una asignación de código de estado.
Redirección de URL
Use AddRedirect para redirigir las solicitudes. El primer parámetro contiene la expresión regular para hacer coincidir la ruta de acceso de la URL entrante. El segundo parámetro es la cadena de reemplazo. El tercer parámetro, si está presente, especifica el código de estado. Si no se especifica el código de estado, el valor predeterminado es 302 - Encontrado, lo que indica que el recurso se ha movido o reemplazado temporalmente.
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}"));
}
En un explorador con herramientas de desarrollo habilitadas, realice una solicitud a la aplicación de ejemplo con la ruta de acceso /redirect-rule/1234/5678
. La expresión regular coincide con la ruta de acceso de la solicitud en redirect-rule/(.*)
y la ruta de acceso se reemplaza con /redirected/1234/5678
. La dirección URL de redireccionamiento se devuelve al cliente con un código de estado 302 - Encontrado. El explorador realiza una solicitud nueva en la URL de redireccionamiento, que aparece en la barra de direcciones del explorador. Como ninguna de las reglas de la aplicación de ejemplo coincide con la dirección URL de redireccionamiento:
- La segunda solicitud recibe una respuesta 200: correcto de la aplicación.
- En el cuerpo de la respuesta se muestra la dirección URL de redireccionamiento.
Se realiza un recorrido de ida y vuelta al servidor cuando se redirige una dirección URL.
Advertencia
Tenga cuidado al establecer las reglas de redirección. Las reglas de redirección se evalúan en cada solicitud enviada a la aplicación, incluso después de una redirección. Es fácil crear por error un bucle de redirecciones infinitas.
Solicitud original: /redirect-rule/1234/5678
La parte de la expresión incluida entre paréntesis se denomina grupo de capturas. El punto (.
) de la expresión significa buscar cualquier carácter. El asterisco (*
) indica buscar el carácter precedente cero o más veces. Por tanto, el grupo de capturas (.*)
busca los dos últimos segmentos de la ruta de acceso de la URL, 1234/5678
. Cualquier valor que se proporcione en la URL de la solicitud después de redirect-rule/
es capturado por este grupo de capturas único.
En la cadena de reemplazo, se insertan los grupos capturados en la cadena con el signo de dólar ($
) seguido del número de secuencia de la captura. Se obtiene el valor del primer grupo de capturas con $1
, el segundo con $2
, y así siguen en secuencia para los grupos de capturas de la expresión regular. Solo hay un grupo capturado en la expresión regular de la regla de redirección de la aplicación de ejemplo, por lo que solo hay un grupo insertado en la cadena de reemplazo, que es $1
. Cuando se aplica la regla, la URL se convierte en /redirected/1234/5678
.
Redirección de URL a un punto de conexión segura
Use AddRedirectToHttps para redirigir las solicitudes HTTP al mismo host y ruta de acceso mediante el protocolo HTTPS. Si no se proporciona el código de estado, el middleware muestra de forma predeterminada 302 - Encontrado. Si no se proporciona el puerto:
- El middleware tiene como valor predeterminado
null
. - El esquema cambia a
https
(protocolo HTTPS), y el cliente accede al recurso en el puerto 443.
En el ejemplo siguiente se muestra cómo establecer el código de estado en 301 - Moved Permanently
y cambiar el puerto a 5001.
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttps(301, 5001);
app.UseRewriter(options);
}
Use AddRedirectToHttpsPermanent para redirigir las solicitudes no seguras al mismo host y ruta de acceso mediante el protocolo HTTPS seguro en el puerto 443. El middleware establece el código de estado en 301 - Moved Permanently
.
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent();
app.UseRewriter(options);
}
Nota
Al redirigir a un punto de conexión seguro sin la necesidad de reglas de redirección adicionales, se recomienda usar el Middleware de redirección de HTTPS. Para más información, vea el tema Aplicación de HTTPS.
La aplicación de ejemplo es capaz de mostrar cómo usar AddRedirectToHttps
o AddRedirectToHttpsPermanent
. Agregue el método de extensión a RewriteOptions
. Realice una solicitud poco segura a la aplicación en cualquier URL. Descarte la advertencia de seguridad del explorador que indica que el certificado autofirmado no es de confianza o cree una excepción para confiar en el certificado en cuestión.
Solicitud original mediante AddRedirectToHttps(301, 5001)
: http://localhost:5000/secure
Solicitud original mediante AddRedirectToHttpsPermanent
: http://localhost:5000/secure
Reescritura de URL
Use AddRewrite para crear una regla para reescribir URL. El primer parámetro contiene la expresión regular para buscar coincidencias en la ruta de dirección de URL entrante. El segundo parámetro es la cadena de reemplazo. El tercer parámetro, skipRemainingRules: {true|false}
, indica al middleware si al aplicar la regla actual tiene que omitir o no alguna regla de redirección adicional.
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}"));
}
Solicitud original: /rewrite-rule/1234/5678
El acento circunflejo (^
) al principio de la expresión significa que la búsqueda de coincidencias empieza al principio de la ruta de dirección URL.
En el ejemplo anterior de la regla de redireccionamiento (redirect-rule/(.*)
), no hay ningún acento circunflejo (^
) al principio de la expresión regular. Por tanto, cualquier carácter puede preceder a redirect-rule/
en la ruta de acceso para que la coincidencia sea correcta.
Ruta de acceso | Coincidir con |
---|---|
/redirect-rule/1234/5678 |
Sí |
/my-cool-redirect-rule/1234/5678 |
Sí |
/anotherredirect-rule/1234/5678 |
Sí |
La regla de reescritura, ^rewrite-rule/(\d+)/(\d+)
, solo encuentra rutas de acceso que empiezan con rewrite-rule/
. En la tabla siguiente, observe la diferencia de coincidencia.
Ruta de acceso | Coincidir con |
---|---|
/rewrite-rule/1234/5678 |
Sí |
/my-cool-rewrite-rule/1234/5678 |
No |
/anotherrewrite-rule/1234/5678 |
No |
Después de la parte ^rewrite-rule/
de la expresión, hay dos grupos de captura, (\d+)/(\d+)
. \d
significa buscar un dígito (número) . El signo más (+
) significa buscar uno o más de los caracteres anteriores. Por tanto, la URL debe contener un número seguido de una barra diagonal, seguida de otro número. Estos grupos de capturas se insertan en la URL de reescritura como $1
y $2
. La cadena de reemplazo de la regla de reescritura coloca los grupos capturados en la cadena de consulta. La ruta de acceso solicitada de /rewrite-rule/1234/5678
se reescribe para obtener el recurso en /rewritten?var1=1234&var2=5678
. Si una cadena de consulta está presente en la solicitud original, se conserva cuando se reescribe la dirección URL.
No hay ningún recorrido de ida y vuelta al servidor para obtener el recurso. Si el recurso existe, se captura y se devuelve al cliente con un código de estado 200 - Correcto. Como el cliente no se redirige, la dirección URL no cambia en la barra de direcciones del explorador. Los clientes no pueden detectar que se ha producido una operación de reescritura de URL en el servidor.
Nota
Use skipRemainingRules: true
siempre que sea posible, ya que las reglas de coincidencia consumen muchos recursos y aumentan el tiempo de respuesta de aplicación. Para obtener la respuesta más rápida de la aplicación:
- Ordene las reglas de reescritura desde la que coincida con más frecuencia a la que coincida con menos frecuencia.
- Omita el procesamiento de las reglas restantes cuando se produzca una coincidencia; no es necesario ningún procesamiento de reglas adicional.
mod_rewrite de Apache
Aplique reglas mod_rewrite de Apache con AddApacheModRewrite. Asegúrese de que el archivo de reglas se implementa con la aplicación. Para obtener más información y ejemplos de reglas mod_rewrite, vea Apache mod_rewrite (mod_rewrite de Apache).
Se usa StreamReader para leer las reglas del archivo de reglas 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}"));
}
La aplicación de ejemplo redirige las solicitudes de /apache-mod-rules-redirect/(.\*)
a /redirected?id=$1
. El código de estado de la respuesta es 302: Encontrado.
# Rewrite path with additional sub directory
RewriteRule ^/apache-mod-rules-redirect/(.*) /redirected?id=$1 [L,R=302]
Solicitud original: /apache-mod-rules-redirect/1234
El middleware admite las siguientes variables de servidor mod_rewrite de Apache:
- CONN_REMOTE_ADDR
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_FORWARDED
- HTTP_HOST
- HTTP_REFERER
- HTTP_USER_AGENT
- HTTPS
- IPV6
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_METHOD
- REQUEST_SCHEME
- REQUEST_URI
- SCRIPT_FILENAME
- SERVER_ADDR
- SERVER_PORT
- SERVER_PROTOCOL
- TIME
- TIME_DAY
- TIME_HOUR
- TIME_MIN
- TIME_MON
- TIME_SEC
- TIME_WDAY
- TIME_YEAR
Reglas del Módulo URL Rewrite para IIS
Para usar el mismo conjunto de reglas que se aplica al módulo URL Rewrite para IIS, use AddIISUrlRewrite. Asegúrese de que el archivo de reglas se implementa con la aplicación. No dirija el middleware para que use el archivo web.config de la aplicación cuando se ejecute en Windows Server IIS. Con IIS, estas reglas se deben almacenar fuera del archivo web.config de la aplicación para evitar conflictos con el Módulo URL Rewrite para IIS. Para obtener más información y ejemplos de reglas del Módulo URL Rewrite para IIS, vea Using Url Rewrite Module 2.0 (Uso del Módulo URL Rewrite 2.0) y URL Rewrite Module Configuration Reference (Referencia de configuración del Módulo URL Rewrite).
Se usa StreamReader para leer las reglas del archivo de reglas 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}"));
}
La aplicación de ejemplo reescribe las solicitudes de /iis-rules-rewrite/(.*)
a /rewritten?id=$1
. La respuesta se envía al cliente con un código de estado 200 - Correcto.
<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>
Solicitud original: /iis-rules-rewrite/1234
Si tiene un Módulo URL Rewrite para IIS activo con reglas configuradas en el nivel de servidor que podrían afectar a la aplicación de manera no deseada, puede deshabilitar el Módulo URL Rewrite para IIS para una aplicación. Para más información, vea Disabling IIS modules (Deshabilitación de módulos de IIS).
Características no admitidas
El middleware publicado con ASP.NET Core 2.x no admite las siguientes características de Módulo URL Rewrite para IIS:
- Reglas de salida
- Variables de servidor personalizadas
- Caracteres comodín
- LogRewrittenUrl
Variables de servidor compatibles
El middleware admite las siguientes variables de servidor del Módulo URL Rewrite para IIS:
- 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
Nota
También puede obtener IFileProvider a través de PhysicalFileProvider. Con este enfoque logrará mayor flexibilidad para la ubicación de los archivos de reglas de reescritura. Asegúrese de que los archivos de reglas de reescritura se implementan en el servidor en la ruta de acceso que proporcione.
PhysicalFileProvider fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
Regla basada en métodos
Use Add para implementar su propia lógica de la regla en un método. Add
expone el elemento RewriteContext, lo que hace que HttpContext esté disponible para usarlo en el método. RewriteContext.Result determina cómo se administra el procesamiento adicional en la canalización. Establezca el valor en uno de los campos RuleResult que se describen en la tabla siguiente.
Volver a escribir el resultado del contexto | Acción |
---|---|
RuleResult.ContinueRules (valor predeterminado) |
Continuar aplicando las reglas. |
RuleResult.EndResponse |
Dejar de aplicar las reglas y enviar la respuesta. |
RuleResult.SkipRemainingRules |
Dejar de aplicar las reglas y enviar el contexto al middleware siguiente. |
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}"));
}
La aplicación de ejemplo muestra un método que redirige las solicitudes para las rutas de acceso que terminen con .xml
. Si se realiza una solicitud de /file.xml
, la solicitud se redirige a /xmlfiles/file.xml
. El código de estado se establece en 301 - Moved Permanently
. Cuando el explorador realiza una solicitud nueva a /xmlfiles/file.xml
, el middleware de archivos estáticos sirve el archivo al cliente desde la carpeta wwwroot/xmlfiles. Para un redireccionamiento, debe establecer de forma explícita el código de estado de la respuesta. En caso contrario, se devuelve un código de estado 200: correcto y no se produce el redireccionamiento en el cliente.
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;
}
}
Este enfoque también permite volver a escribir las solicitudes. En la aplicación de ejemplo se muestra cómo volver a escribir la ruta de acceso para cualquier solicitud de archivo de texto para proporcionar el archivo de texto file.txt desde la carpeta wwwroot. El middleware de archivos estáticos proporciona el archivo en función de la ruta de acceso de la solicitud actualizada:
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";
}
}
Regla basada en IRule
Utilice Add para usar la lógica de reglas en una clase que implemente la interfaz IRule. IRule
proporciona mayor flexibilidad que si se usa el enfoque de reglas basadas en métodos. La clase de implementación puede incluir un constructor que permita pasar parámetros para el método 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}"));
}
Se comprueba que los valores de los parámetros en la aplicación de ejemplo para extension
y newPath
cumplen ciertas condiciones. extension
debe contener un valor, que debe ser .png
, .jpg
o .gif. Si newPath
no es válido, se genera ArgumentException . Si se realiza una solicitud de image.png
, la solicitud se redirige a /png-images/image.png
. Si se realiza una solicitud de image.jpg
, la solicitud se redirige a /jpg-images/image.jpg
. El código de estado se establece en 301 - Moved Permanently
, y context.Result
se establece para detener el procesamiento de las reglas y enviar la respuesta.
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;
}
}
}
Solicitud original: /image.png
Solicitud original: /image.jpg
Ejemplos de expresiones regulares
Objetivo | Cadena de expresión regular & Ejemplo de coincidencia |
Cadena de reemplazo & Ejemplo de resultado |
---|---|---|
Ruta de acceso de reescritura en la cadena de consulta | ^path/(.*)/(.*) /path/abc/123 |
path?var1=$1&var2=$2 /path?var1=abc&var2=123 |
Quitar barra diagonal final | (.*)/$ /path/ |
$1 /path |
Exigir barra diagonal final | (.*[^/])$ /path |
$1/ /path/ |
Evitar reescritura de solicitudes específicas | ^(.*)(?<!\.axd)$ o ^(?!.*\.axd$)(.*)$ Sí: /resource.htm No: /resource.axd |
rewritten/$1 /rewritten/resource.htm /resource.axd |
Reorganizar los segmentos de URL | path/(.*)/(.*)/(.*) path/1/2/3 |
path/$3/$2/$1 path/3/2/1 |
Reemplazar un segmento de URL | ^(.*)/segment2/(.*) /segment1/segment2/segment3 |
$1/replaced/$2 /segment1/replaced/segment3 |
Recursos adicionales
- Vea o descargue el código de ejemplo (cómo descargarlo)
- Origen RewriteMiddleware en GitHub
- Inicio de la aplicación en ASP.NET Core
- Middleware de ASP.NET Core
- Expresiones regulares en .NET
- Lenguaje de expresiones regulares: referencia rápida
- Apache mod_rewrite (mod_rewrite de Apache)
- Using Url Rewrite Module 2.0 (for IIS) (Uso del Módulo URL Rewrite 2.0 para IIS)
- URL Rewrite Module Configuration Reference (Referencia de configuración del Módulo URL Rewrite)
- Cómo simplificar la estructura de direcciones URL
- 10 URL Rewriting Tips and Tricks (10 trucos y consejos para reescritura de URL)
- To slash or not to slash (Usar la barra diagonal o no)