Middleware pro přepis adres URL v ASP.NET Core

Mikael Mengistu

Tento dokument přináší přepis adres URL s pokyny, jak používat middleware pro přepis adres URL v ASP.NET Core aplikacích.

Přepsání adresy URL je úprava adres URL požadavků na základě jednoho nebo více předdefinovaných pravidel. Přepsání adresy URL vytváří abstrakci mezi umístěními prostředků a jejich adresami, aby umístění a adresy nejsou úzce propojeny. Přepis adres URL je užitečný v několika scénářích:

  • Dočasně nebo trvale přesuňte nebo nahraďte prostředky serveru a udržujte pro tyto prostředky stabilní lokátory.
  • Rozdělte zpracování požadavků napříč různými aplikacemi nebo oblastmi jedné aplikace.
  • Odeberte, přidejte nebo reorganizujte segmenty adresy URL u příchozích požadavků.
  • Optimalizace veřejných adres URL pro optimalizaci vyhledávacího webu (SEO)
  • Povolte používání popisné veřejné adresy URL, které návštěvníkům pomůžou předpovědět obsah vrácený žádostí o prostředek.
  • Přesměrovat nezabezpečené požadavky na zabezpečené koncové body.
  • Znemožnit hotlinking, kdy externí web používá hostovaný statický prostředek na jiné lokalitě propojením assetu s vlastním obsahem.

Poznámka

Přepsání adresy URL může snížit výkon aplikace. Tam, kde je to možné, omezte počet a složitost pravidel.

Zobrazení nebo stažení ukázkového kódu (stažení)

Přesměrování adresy URL a přepsání adresy URL

Rozdíl ve formulaci mezi přesměrováním adresy URL a přepsáním adresy URL je drobný, ale má důležité důsledky pro poskytování prostředků klientům. ASP.NET Core adresu URL middlewaru dokáže zadat, jak je potřeba.

Přesměrování adresy URL zahrnuje operaci na straně klienta, kde má klient pokyn, aby přistupoval k prostředku na jiné adrese, než si původně vyžádal klient. To vyžaduje zpáteční cestu k serveru. Adresa URL pro přesměrování vrácená klientovi se zobrazí v adresní řádku prohlížeče, když klient vytvoří nový požadavek na prostředek.

Pokud je přesměrován na , server odpoví, že klient by měl získat prostředek na pomocí stavového kódu, který označuje, že přesměrování /resource je dočasné nebo /different-resource /different-resource trvalé.

Koncový bod služby WebAPI se na serveru dočasně změnil z verze 1 (v1) na verzi 2 (v2). Klient do služby zažádá v cestě verze 1 /v1/api. Server odešle zpět odpověď 302 (Nalezeno) s novou dočasnou cestou pro službu ve verzi 2 /v2/api. Klient provede druhý požadavek na službu na adrese URL přesměrování. Server odpoví stavový kódem 200 (OK).

Při přesměrování požadavků na jinou adresu URL určete, jestli je přesměrování trvalé nebo dočasné, zadáním stavového kódu s odpovědí:

  • Stavový kód 301 – Přesunuto Trvale se používá tam, kde má prostředek novou trvalou adresu URL a vy chcete klientovi instruovat, aby všechny budoucí požadavky na prostředek používaly novou adresu URL. Klient může po přijetí stavového kódu 301 odpověď ukládat do mezipaměti a opakovaně používat.

  • Stavový kód 302 – Našel se tam, kde je přesměrování dočasné nebo se obecně může změnit. Stavový kód 302 indikuje klientovi, že nemá adresu URL ukládat a používat ji v budoucnu.

Další informace o stavových kódech najdete v dokumentu RFC 2616: Definice stavového kódu.

Přepsání adresy URL je operace na straně serveru, která poskytuje prostředek z jiné adresy prostředku, než si vyžádal klient. Přepsání adresy URL nevyžaduje zpáteční cestu k serveru. Přepsané adresy URL se klientovi nevrátily a nezobrazí se v adresní řádku prohlížeče.

Pokud /resource se přepíše /different-resource na , server interně načte a vrátí prostředek na /different-resource adrese .

I když klient může být schopen načíst prostředek na přepsané adrese URL, klient není informován, že prostředek existuje na přepsané adrese URL, když vytvoří svůj požadavek a obdrží odpověď.

Koncový bod služby WebAPI se na serveru změnil z verze 1 (v1) na verzi 2 (v2). Klient do služby zažádá v cestě verze 1 /v1/api. Adresa URL požadavku se přepíše pro přístup ke službě na cestě verze 2 /v2/api. Služba odpoví klientovi pomocí stavového kódu 200 (OK).

Ukázková aplikace pro přepis adres URL

Funkce middlewaru pro přepis adres URL můžete prozkoumat pomocí ukázkové aplikace. Aplikace použije pravidla přesměrování a přepsání a pro několik scénářů zobrazí přesměrovanou nebo přepsanou adresu URL.

Kdy použít middleware pro přepis adres URL

Middleware pro přepis adres URL použijte, když nemůžete použít následující přístupy:

Middleware použijte také v případě, že je aplikace hostovaná naHTTP.sys (dříve WebListener).

Hlavní důvody použití serverových technologií pro přepis adres URL ve službě IIS, Apache a Nginx jsou:

  • Middleware nepodporuje všechny funkce těchto modulů.

    Některé funkce serverových modulů nefungují s ASP.NET Core projekty, jako jsou například omezení a modulu IsFile IsDirectory IIS Rewrite. V těchto scénářích místo toho použijte middleware.

  • Výkon middlewaru se pravděpodobně neshoduje s výkonem modulů.

    Srovnávací testy jsou jediným způsobem, jak si být jistí, který přístup snižuje výkon nejvíce nebo pokud je snížený výkon zanedbatelný.

Balíček

Middleware pro přepis adres URL poskytuje balíček Microsoft.AspNetCore.Rewrite, který je implicitně součástí ASP.NET Core aplikací.

Rozšíření a možnosti

Vytvořte pravidla přepisování adres URL a přesměrování vytvořením instance třídy RewriteOptions s metodami rozšíření pro každé pravidlo přepsání. Zřetězte několik pravidel v pořadí, ve které je chcete zpracovat. Se předá do middlewaru pro přepis adresy URL při jeho přidání do RewriteOptions kanálu požadavku pomocí 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}"));
}

Přesměrování jiné společnosti než www na www

Tři možnosti umožňují aplikaci přesměrovat jiné požadavky www než www na :

Přesměrování adresy URL

Slouží AddRedirect k přesměrování požadavků. První parametr obsahuje regulární výraz pro porovnávání na cestě příchozí adresy URL. Druhý parametr je náhradní řetězec. Třetí parametr, pokud je k dispozici, určuje stavový kód. Pokud nezadáte stavový kód, stavový kód se ve výchozím nastavení změní na 302 – Nalezeno, což značí, že se prostředek dočasně přesunul nebo nahradil.

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

V prohlížeči s povolenými vývojářských nástrojů vytvořte požadavek na ukázkovou aplikaci s cestou /redirect-rule/1234/5678 . Regulární výraz odpovídá cestě požadavku na a cesta redirect-rule/(.*) se nahradí za /redirected/1234/5678 . Adresa URL přesměrování se odesílá zpět klientovi se stavový kódem 302 – Nalezeno. Prohlížeč vytvoří nový požadavek na adrese URL přesměrování, která se zobrazí v adresní řádku prohlížeče. Vzhledem k tomu, že se v adrese URL pro přesměrování neshodují žádná pravidla v ukázkové aplikaci:

  • Druhý požadavek obdrží z aplikace odpověď 200 – OK.
  • Text odpovědi ukazuje adresu URL přesměrování.

Při přesměrování adresy URL se na server provádí zpáteční cesta.

Upozornění

Při navazování pravidel přesměrování buďte opatrní. Pravidla přesměrování se vyhodnocují při každém požadavku do aplikace, a to i po přesměrování. Je snadné náhodně vytvořit smyčku nekonečného přesměrování.

Původní žádost: /redirect-rule/1234/5678

Okno prohlížeče s Vývojářské nástroje sledování požadavků a odpovědí

Část výrazu obsažená v závorkách se nazývá skupina zachycení. Tečka ( . ) výrazu znamená, že odpovídá libovolnému znaku. Hvězdička ( * ) označuje shodu s předchozím znakem nulakrát nebo vícekrát. Poslední dva segmenty cesty adresy URL jsou proto 1234/5678 zachyceny skupinou zachycení (.*) . Jakákoli hodnota zadaná v adrese URL požadavku po redirect-rule/ zachycení se zachytí touto jedinou skupinou zachycení.

V řetězci pro nahrazení se zachycené skupiny vloženého do řetězce se znakem dolaru ( ) následovaného pořadovou $ číslem zachycení. První hodnota skupiny zachycení se získá pomocí , druhou s a pokračují v sekvenci pro skupiny zachycení $1 $2 ve vašem regulárním výrazu. Regulární výraz pravidla přesměrování v ukázkové aplikaci obsahuje jenom jednu zachycenou skupinu, takže v náhradním řetězci je jenom jedna vložená skupina, která je $1 . Po použití pravidla se adresa URL bude nacházet /redirected/1234/5678 .

Přesměrování adresy URL na zabezpečený koncový bod

Slouží AddRedirectToHttps k přesměrování požadavků HTTP na stejného hostitele a cestu pomocí protokolu HTTPS. Pokud kód stavu není zadaný, použije se ve výchozím nastavení middleware 302 – Nalezeno. Pokud port není dodán:

  • Ve výchozím nastavení se používá middleware null .
  • Schéma se změní na https (protokol HTTPS) a klient přistupuje k prostředku na portu 443.

Následující příklad ukazuje, jak nastavit stavový kód na 301 – trvale přesunuto a změnit port na 5001.

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

    app.UseRewriter(options);
}

Použijte AddRedirectToHttpsPermanent k přesměrování nezabezpečených požadavků na stejného hostitele a cestu s protokolem Secure https na portu 443. Middleware nastaví stavový kód na 301 – trvale přesunuto.

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

    app.UseRewriter(options);
}

Poznámka

Při přesměrování na zabezpečený koncový bod bez požadavku na další pravidla přesměrování doporučujeme použít middleware pro přesměrování protokolu HTTPS. Další informace najdete v tématu věnovaném vykonání protokolu HTTPS .

Ukázková aplikace dokáže demonstrovat, jak používat AddRedirectToHttps nebo AddRedirectToHttpsPermanent . Přidejte metodu rozšíření do RewriteOptions . Vytvořte nezabezpečenou žádost o aplikaci na libovolné adrese URL. Zrušte upozornění zabezpečení prohlížeče, že certifikát podepsaný svým držitelem je nedůvěryhodný, nebo vytvořte výjimku pro důvěřování certifikátu.

Původní požadavek s použitím AddRedirectToHttps(301, 5001) : http://localhost:5000/secure

Okno prohlížeče s Vývojářské nástroje sledování požadavků a odpovědí

Původní požadavek s použitím AddRedirectToHttpsPermanent : http://localhost:5000/secure

Okno prohlížeče s Vývojářské nástroje sledování požadavků a odpovědí

Přepsání adresy URL

Slouží AddRewrite k vytvoření pravidla pro přepis adres URL. První parametr obsahuje regulární výraz pro porovnání na cestě příchozích adres URL. Druhým parametrem je náhradní řetězec. Třetí parametr, skipRemainingRules: {true|false} označuje middleware bez ohledu na to, zda má přeskočit další pravidla přepsání, pokud je použito aktuální pravidlo.

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

Původní požadavek: /rewrite-rule/1234/5678

Okno prohlížeče se Vývojářské nástroje sledování žádosti a odpovědi

Kosočtverce ( ^ ) na začátku výrazu znamená, že shoda začíná na začátku cesty URL.

V předchozím příkladu s pravidlem přesměrování redirect-rule/(.*) není ^ na začátku regulárního výrazu k dispozici žádná kosočtverce (). Proto jakékoli znaky mohou předcházet redirect-rule/ v cestě k úspěšné shodě.

Cesta Shoda
/redirect-rule/1234/5678 Yes
/my-cool-redirect-rule/1234/5678 Yes
/anotherredirect-rule/1234/5678 Yes

Pravidlo přepsaného zápisu ^rewrite-rule/(\d+)/(\d+) odpovídá pouze cestám, pokud začínají na rewrite-rule/ . V následující tabulce si všimněte rozdílu v porovnání.

Cesta Shoda
/rewrite-rule/1234/5678 Yes
/my-cool-rewrite-rule/1234/5678 No
/anotherrewrite-rule/1234/5678 No

Po ^rewrite-rule/ části výrazu jsou k dispozici dvě skupiny zachycení, (\d+)/(\d+) . \dZnačí shodu s číslicí (číslem). Znaménko plus ( + ) znamená, že se shoduje s jedním nebo více předcházejícím znakem. Proto musí adresa URL obsahovat číslo následované lomítkem, za kterým následuje jiné číslo. Tyto skupiny zachycení jsou vloženy do přepsané adresy URL jako $1 a $2 . Náhradní řetězec pravidla přepsaní umístí zachycené skupiny do řetězce dotazu. Požadovaná cesta k /rewrite-rule/1234/5678 je přepsána za účelem získání prostředku v /rewritten?var1=1234&var2=5678 . Pokud se v původním požadavku nachází řetězec dotazu, bude při přepisování adresy URL zachován.

K získání prostředku neexistuje žádná Přenosová cesta k serveru. Pokud prostředek existuje, načte se a vrátí do klienta s kódem stavu 200-OK . Vzhledem k tomu, že klient není přesměrován, adresa URL v adresním řádku prohlížeče se nezmění. Klienti nerozpoznají, že na serveru došlo k operaci přepsání adresy URL.

Poznámka

skipRemainingRules: trueKdykoli je to možné, protože vyhovující pravidla jsou výpočetně náročná a zvyšují dobu odezvy aplikace. Pro nejrychlejší aplikační odpověď:

  • Seřazení pravidel přepisu z nejčastěji spárovaného pravidla na nejméně často spárované pravidlo.
  • Pokud dojde ke shodě a není vyžadováno žádné další zpracování pravidla, přeskočte zpracování zbývajících pravidel.

Mod_rewrite Apache

Použijte pravidla mod_rewrite Apache s AddApacheModRewrite . Ujistěte se, že je soubor pravidel nasazený spolu s aplikací. Další informace a příklady pravidel mod_rewrite najdete v tématu Apache mod_rewrite.

StreamReaderPoužívá se ke čtení pravidel ze souboru pravidel 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}"));
}

Ukázková aplikace přesměrovává požadavky od /apache-mod-rules-redirect/(.\*) do /redirected?id=$1 . Stavový kód odpovědi je 302 – Nalezeno.

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

Původní požadavek: /apache-mod-rules-redirect/1234

Okno prohlížeče s Vývojářské nástroje sledování požadavků a odpovědí

Middleware podporuje následující proměnné serveru Apache mod_rewrite:

  • CONN_REMOTE_ADDR
  • HTTP_ACCEPT
  • HTTP_CONNECTION
  • HTTP_COOKIE
  • HTTP_FORWARDED
  • HTTP_HOST
  • HTTP_REFERER
  • HTTP_USER_AGENT
  • HTTPS
  • PROTOKOLŮ
  • QUERY_STRING
  • REMOTE_ADDR
  • REMOTE_PORT
  • REQUEST_FILENAME
  • REQUEST_METHOD
  • REQUEST_SCHEME
  • REQUEST_URI
  • SCRIPT_FILENAME
  • SERVER_ADDR
  • SERVER_PORT
  • SERVER_PROTOCOL
  • ČAS
  • TIME_DAY
  • TIME_HOUR
  • TIME_MIN
  • TIME_MON
  • TIME_SEC
  • TIME_WDAY
  • TIME_YEAR

Pravidla pro přepsání adresy URL služby IIS

Pokud chcete použít stejnou sadu pravidel, která se vztahuje na modul IIS URL Rewrite, použijte AddIISUrlRewrite . Ujistěte se, že je soubor pravidel nasazený s aplikací. Při spouštění ve službě IIS Windows Server nesměrovat middleware, abyweb.configsoubor aplikace. Se službou IIS by se tato pravidla měla ukládat mimo soubor web.config, aby nedocházelo ke konfliktům s modulem iis rewrite. Další informace a příklady pravidel modulu pro přepis adres URL služby IIS najdete v tématu Using Url Rewrite Module 2.0 and URL Rewrite Module Configuration Reference.

Se StreamReader používá ke čtení pravidel ze souboru IISUrlRewrite.xml pravidel:

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

Ukázková aplikace přepíše požadavky z /iis-rules-rewrite/(.*) na /rewritten?id=$1 . Odpověď se klientovi odesílá se stavový kódem 200 – OK.

<rewrite>
  <rules>
    <rule name="Rewrite segment to id querystring" stopProcessing="true">
      <match url="^iis-rules-rewrite/(.*)$" />
      <action type="Rewrite" url="rewritten?id={R:1}" appendQueryString="false"/>
    </rule>
  </rules>
</rewrite>

Původní žádost: /iis-rules-rewrite/1234

Okno prohlížeče s Vývojářské nástroje, které sleduje požadavek a odpověď

Pokud máte aktivní modul iis rewrite s nakonfigurovaným pravidly na úrovni serveru, která by nežádoucím způsobem ovlivnila vaši aplikaci, můžete pro aplikaci zakázat modul IIS Rewrite Module. Další informace najdete v tématu Zakázání modulů služby IIS.

Nepodporované funkce

Middleware nepodporuje následující funkce modulu IIS URL Rewrite Module:

  • Pravidla pro odchozí provoz
  • Vlastní proměnné serveru
  • Zástupné znaky
  • LogRewrittenUrl

Podporované proměnné serveru

Middleware podporuje následující proměnné serveru IIS URL Rewrite Module:

  • 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

Poznámka

Můžete také získat IFileProvider prostřednictvím PhysicalFileProvider . Tento přístup může poskytovat větší flexibilitu pro umístění souborů pravidel přepsání. Ujistěte se, že jsou vaše soubory pravidel přepsání nasazené na server v cestě, kterou poskytnete.

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

Pravidlo založené na metodě

K Add implementaci vlastní logiky pravidla v metodě použijte . Add zpřístupňuje RewriteContext , který zpřístupňuje HttpContext pro použití v metodě . RewriteContext.Result určuje, jak se zpracovává další zpracování kanálu. Nastavte hodnotu na jedno z RuleResult polí popsaných v následující tabulce.

Výsledek přepsání kontextu Akce
RuleResult.ContinueRules (výchozí) Pokračujte v používání pravidel.
RuleResult.EndResponse Zastavte používání pravidel a odešlete odpověď.
RuleResult.SkipRemainingRules Zastavte používání pravidel a odešlete kontext do dalšího middlewaru.
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}"));
}

Ukázková aplikace ukazuje metodu, která přesměruje požadavky na cesty končící.xml. Pokud je požadavek proveden /file.xml pro , požadavek se přesměruje na /xmlfiles/file.xml . Stavový kód je nastavený na hodnotu 301 – Přesunuto trvale. Když prohlížeč vytvoří nový požadavek na /xmlfiles/file.xml, middleware static file předá soubor klientovi ze složky wwwroot/xmlfiles. Pro přesměrování explicitně nastavte stavový kód odpovědi. V opačném případě se vrátí stavový kód 200 – OK a k přesměrování nedojde v klientovi.

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

Tento přístup může také přepsat požadavky. Ukázková aplikace předvede přepsání cesty pro všechny požadavky na textový soubor, abyfile.txt textový soubor ze složky wwwroot. Middleware static file slouží k zpracování souboru na základě aktualizované cesty požadavku:

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

Pravidlo založené na pravidle IRule

Používá Add se k použití logiky pravidla ve třídě, která implementuje rozhraní IRule . IRule nabízí větší flexibilitu při používání přístupu založeného na metodě. Implementační třída může obsahovat konstruktor, který umožňuje předat parametry metody 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}"));
}

Hodnoty parametrů v ukázkové aplikaci pro a jsou extension newPath zkontrolovány, aby splňovaly několik podmínek. Musí obsahovat hodnotu a hodnota musí být extension.png, .jpg nebo .gif. ** Pokud newPath není platná, vyvolá ArgumentException se . Pokud je požadavek na image.png, požadavek se přesměruje na /png-images/image.png . Pokud je požadavek na image.jpg, požadavek se přesměruje na /jpg-images/image.jpg . Stavový kód je nastavený na hodnotu 301 – Přesunuto trvale a je nastavený tak, aby zastavil pravidla zpracování context.Result a odesílal odpověď.

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

Původní žádost: /image.png

Okno prohlížeče s Vývojářské nástroje, které sleduje požadavky a odpovědi pro image.png

Původní žádost: /image.jpg

Okno prohlížeče s Vývojářské nástroje, které sleduje požadavky a odpovědi pro image.jpg

Příklady regulárních výrazů

Cíl Regex String &
Příklad shody
Náhradní řetězec &
Příklad výstupu
Přepsání cesty na řetězec dotazu ^path/(.*)/(.*)
/path/abc/123
path?var1=$1&var2=$2
/path?var1=abc&var2=123
Prokládaní koncového lomítka (.*)/$
/path/
$1
/path
Vynucení koncového lomítka (.*[^/])$
/path
$1/
/path/
Vyhněte se přepisování konkrétních požadavků ^(.*)(?<!\.axd)$ nebo ^(?!.*\.axd$)(.*)$
Ano: /resource.htm
Ne: /resource.axd
rewritten/$1
/rewritten/resource.htm
/resource.axd
Změna uspořádání segmentů adres URL path/(.*)/(.*)/(.*)
path/1/2/3
path/$3/$2/$1
path/3/2/1
Nahrazení segmentu adresy URL ^(.*)/segment2/(.*)
/segment1/segment2/segment3
$1/replaced/$2
/segment1/replaced/segment3

Tento dokument přináší přepis adres URL s pokyny, jak používat middleware pro přepis adres URL v ASP.NET Core aplikacích.

Přepsání adresy URL je úprava adres URL požadavků na základě jednoho nebo více předdefinovaných pravidel. Přepsání adresy URL vytváří abstrakci mezi umístěními prostředků a jejich adresami, aby umístění a adresy nejsou úzce propojeny. Přepis adres URL je užitečný v několika scénářích:

  • Dočasně nebo trvale přesuňte nebo nahraďte prostředky serveru a udržujte pro tyto prostředky stabilní lokátory.
  • Rozdělte zpracování požadavků napříč různými aplikacemi nebo oblastmi jedné aplikace.
  • Odeberte, přidejte nebo reorganizujte segmenty adresy URL u příchozích požadavků.
  • Optimalizace veřejných adres URL pro optimalizaci vyhledávacího webu (SEO)
  • Povolte používání popisné veřejné adresy URL, které návštěvníkům pomůžou předpovědět obsah vrácený žádostí o prostředek.
  • Přesměrovat nezabezpečené požadavky na zabezpečené koncové body.
  • Znemožnit hotlinking, kdy externí web používá hostovaný statický prostředek na jiné lokalitě propojením assetu s vlastním obsahem.

Poznámka

Přepsání adresy URL může snížit výkon aplikace. Tam, kde je to možné, omezte počet a složitost pravidel.

Zobrazení nebo stažení ukázkového kódu (stažení)

Přesměrování adresy URL a přepsání adresy URL

Rozdíl ve formulaci mezi přesměrováním adresy URL a přepsáním adresy URL je drobný, ale má důležité důsledky pro poskytování prostředků klientům. ASP.NET Core adresu URL middlewaru dokáže zadat, jak je potřeba.

Přesměrování adresy URL zahrnuje operaci na straně klienta, kde má klient pokyn, aby přistupoval k prostředku na jiné adrese, než si původně vyžádal klient. To vyžaduje zpáteční cestu k serveru. Adresa URL pro přesměrování vrácená klientovi se zobrazí v adresní řádku prohlížeče, když klient vytvoří nový požadavek na prostředek.

Pokud je přesměrován na , server odpoví, že klient by měl získat prostředek na pomocí stavového kódu, který označuje, že přesměrování /resource je dočasné nebo /different-resource /different-resource trvalé.

Koncový bod služby WebAPI se na serveru dočasně změnil z verze 1 (v1) na verzi 2 (v2). Klient do služby zažádá v cestě verze 1 /v1/api. Server odešle zpět odpověď 302 (Nalezeno) s novou dočasnou cestou pro službu ve verzi 2 /v2/api. Klient provede druhý požadavek na službu na adrese URL přesměrování. Server odpoví stavový kódem 200 (OK).

Při přesměrování požadavků na jinou adresu URL určete, jestli je přesměrování trvalé nebo dočasné, zadáním stavového kódu s odpovědí:

  • Stavový kód 301 – Přesunuto Trvale se používá tam, kde má prostředek novou trvalou adresu URL a vy chcete klientovi instruovat, aby všechny budoucí požadavky na prostředek používaly novou adresu URL. Klient může po přijetí stavového kódu 301 odpověď ukládat do mezipaměti a opakovaně používat.

  • Stavový kód 302 – Našel se tam, kde je přesměrování dočasné nebo se obecně může změnit. Stavový kód 302 indikuje klientovi, že nemá adresu URL ukládat a používat ji v budoucnu.

Další informace o stavových kódech najdete v dokumentu RFC 2616: Definice stavového kódu.

Přepsání adresy URL je operace na straně serveru, která poskytuje prostředek z jiné adresy prostředku, než si vyžádal klient. Přepsání adresy URL nevyžaduje zpáteční cestu k serveru. Přepsané adresy URL se klientovi nevrátily a nezobrazí se v adresní řádku prohlížeče.

Pokud /resource se přepíše /different-resource na , server interně načte a vrátí prostředek na /different-resource adrese .

I když klient může být schopen načíst prostředek na přepsané adrese URL, klient není informován, že prostředek existuje na přepsané adrese URL, když vytvoří svůj požadavek a obdrží odpověď.

Koncový bod služby WebAPI se na serveru změnil z verze 1 (v1) na verzi 2 (v2). Klient do služby zažádá v cestě verze 1 /v1/api. Adresa URL požadavku se přepíše pro přístup ke službě na cestě verze 2 /v2/api. Služba odpoví klientovi pomocí stavového kódu 200 (OK).

Ukázková aplikace pro přepis adres URL

Funkce middlewaru pro přepis adres URL můžete prozkoumat pomocí ukázkové aplikace. Aplikace použije pravidla přesměrování a přepsání a pro několik scénářů zobrazí přesměrovanou nebo přepsanou adresu URL.

Kdy použít middleware pro přepis adres URL

Middleware pro přepis adres URL použijte, když nemůžete použít následující přístupy:

Middleware použijte také v případě, že je aplikace hostovaná naHTTP.sys (dříve WebListener).

Hlavní důvody použití serverových technologií pro přepis adres URL ve službě IIS, Apache a Nginx jsou:

  • Middleware nepodporuje všechny funkce těchto modulů.

    Některé funkce serverových modulů nefungují s projekty ASP.NET Core, jako jsou například omezení a modulu IsFile IsDirectory IIS Rewrite. V těchto scénářích místo toho použijte middleware.

  • Výkon middlewaru se pravděpodobně neshoduje s výkonem modulů.

    Srovnávací testy jsou jediným způsobem, jak si být jistí, který přístup snižuje výkon nejvíce nebo pokud je snížený výkon zanedbatelný.

Balíček

Pokud chcete do projektu zahrnout middleware, přidejte do souboru projektu odkaz na balíček Microsoft.AspNetCore.App metapackage, který obsahuje balíček Microsoft.AspNetCore.Rewrite.

Pokud balíčky Microsoft.AspNetCore.App metapackage používat balíčky, přidejte do balíčku odkaz na Microsoft.AspNetCore.Rewrite projekt.

Rozšíření a možnosti

Vytvořte pravidla přepisování adres URL a přesměrování vytvořením instance třídy RewriteOptions s metodami rozšíření pro každé pravidlo přepsání. Zřetězte několik pravidel v pořadí, ve které je chcete zpracovat. Se předá do middlewaru pro přepis adresy URL při jeho přidání do RewriteOptions kanálu požadavku pomocí 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}"));
}

Přesměrování jiné společnosti než www na www

Tři možnosti umožňují aplikaci přesměrovat jiné požadavky www než www na :

Přesměrování adresy URL

Slouží AddRedirect k přesměrování požadavků. První parametr obsahuje regulární výraz pro porovnávání na cestě příchozí adresy URL. Druhý parametr je náhradní řetězec. Třetí parametr, pokud je k dispozici, určuje stavový kód. Pokud nezadáte stavový kód, stavový kód se ve výchozím nastavení změní na 302 – Nalezeno, což značí, že se prostředek dočasně přesunul nebo nahradil.

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

V prohlížeči s povolenými vývojářských nástrojů vytvořte požadavek na ukázkovou aplikaci s cestou /redirect-rule/1234/5678 . Regulární výraz odpovídá cestě požadavku na a cesta redirect-rule/(.*) se nahradí za /redirected/1234/5678 . Adresa URL přesměrování se odesílá zpět klientovi se stavový kódem 302 – Nalezeno. Prohlížeč vytvoří nový požadavek na adrese URL přesměrování, která se zobrazí v adresní řádku prohlížeče. Vzhledem k tomu, že se v adrese URL pro přesměrování neshodují žádná pravidla v ukázkové aplikaci:

  • Druhý požadavek obdrží z aplikace odpověď 200 – OK.
  • Text odpovědi ukazuje adresu URL přesměrování.

Při přesměrování adresy URL se na server provádí zpáteční cesta.

Upozornění

Při navazování pravidel přesměrování buďte opatrní. Pravidla přesměrování se vyhodnocují při každém požadavku do aplikace, a to i po přesměrování. Je snadné náhodně vytvořit smyčku nekonečného přesměrování.

Původní žádost: /redirect-rule/1234/5678

Okno prohlížeče s Vývojářské nástroje sledování požadavků a odpovědí

Část výrazu obsažená v závorkách se nazývá skupina zachycení. Tečka ( . ) výrazu znamená, že odpovídá libovolnému znaku. Hvězdička ( * ) označuje shodu s předchozím znakem nulakrát nebo vícekrát. Poslední dva segmenty cesty adresy URL jsou proto 1234/5678 zachyceny skupinou zachycení (.*) . Jakákoli hodnota zadaná v adrese URL požadavku po redirect-rule/ zachycení se zachytí touto jedinou skupinou zachycení.

V řetězci pro nahrazení se zachycené skupiny vloženého do řetězce se znakem dolaru ( ) následovaného pořadovou $ číslem zachycení. První hodnota skupiny zachycení se získá pomocí , druhou s a pokračují v sekvenci pro skupiny zachycení $1 $2 ve vašem regulárním výrazu. V regulárním výrazu pravidla přesměrování v ukázkové aplikaci je pouze jedna zachycená skupina, takže v řetězci pro nahrazení existuje pouze jedna injektovaná skupina, což je $1 . Po použití pravidla se adresa URL změní na /redirected/1234/5678 .

Přesměrování adresy URL na zabezpečený koncový bod

Slouží AddRedirectToHttps k přesměrování požadavků HTTP na stejného hostitele a cestu pomocí protokolu HTTPS. Pokud stavový kód není zadaný, middleware má výchozí hodnotu 302 – Nalezeno. Pokud port není zadaný:

  • Middleware má výchozí hodnotu null .
  • Schéma se změní na (protokol HTTPS) a klient přistupuje k https prostředku na portu 443.

Následující příklad ukazuje, jak nastavit stavový kód na 301 – Přesunuto trvale a změnit port na 5001.

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

    app.UseRewriter(options);
}

Slouží k přesměrování nezabezpečených požadavků na stejného hostitele a cestu se zabezpečeným AddRedirectToHttpsPermanent protokolem HTTPS na portu 443. Middleware nastaví stavový kód na 301 – Přesunuto Trvale.

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

    app.UseRewriter(options);
}

Poznámka

Při přesměrování na zabezpečený koncový bod bez požadavku na další pravidla přesměrování doporučujeme použít middleware pro přesměrování HTTPS. Další informace najdete v tématu Vynucení HTTPS.

Ukázková aplikace dokáže předvede použití nebo AddRedirectToHttps AddRedirectToHttpsPermanent . Přidejte metodu rozšíření do RewriteOptions . Vytvořte nezabezpečenou žádost o aplikaci na libovolné adrese URL. Zrušte upozornění zabezpečení prohlížeče, že certifikát podepsaný svým držitelem je nedůvěryhodný, nebo vytvořte výjimku pro důvěřování certifikátu.

Původní požadavek s použitím AddRedirectToHttps(301, 5001) : http://localhost:5000/secure

Okno prohlížeče s Vývojářské nástroje sledování požadavků a odpovědí

Původní požadavek s použitím AddRedirectToHttpsPermanent : http://localhost:5000/secure

Okno prohlížeče s Vývojářské nástroje sledování požadavků a odpovědí

Přepsání adresy URL

Slouží AddRewrite k vytvoření pravidla pro přepis adres URL. První parametr obsahuje regulární výraz pro porovnání na cestě příchozích adres URL. Druhým parametrem je náhradní řetězec. Třetí parametr, skipRemainingRules: {true|false} označuje middleware bez ohledu na to, zda má přeskočit další pravidla přepsání, pokud je použito aktuální pravidlo.

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

Původní požadavek: /rewrite-rule/1234/5678

Okno prohlížeče se Vývojářské nástroje sledování žádosti a odpovědi

Kosočtverce ( ^ ) na začátku výrazu znamená, že shoda začíná na začátku cesty URL.

V předchozím příkladu s pravidlem přesměrování redirect-rule/(.*) není ^ na začátku regulárního výrazu k dispozici žádná kosočtverce (). Proto jakékoli znaky mohou předcházet redirect-rule/ v cestě k úspěšné shodě.

Cesta Shoda
/redirect-rule/1234/5678 Yes
/my-cool-redirect-rule/1234/5678 Yes
/anotherredirect-rule/1234/5678 Yes

Pravidlo přepsaného zápisu ^rewrite-rule/(\d+)/(\d+) odpovídá pouze cestám, pokud začínají na rewrite-rule/ . V následující tabulce si všimněte rozdílu v porovnání.

Cesta Shoda
/rewrite-rule/1234/5678 Yes
/my-cool-rewrite-rule/1234/5678 No
/anotherrewrite-rule/1234/5678 No

Po ^rewrite-rule/ části výrazu jsou k dispozici dvě skupiny zachycení, (\d+)/(\d+) . \dZnačí shodu s číslicí (číslem). Znaménko plus ( + ) znamená, že se shoduje s jedním nebo více předcházejícím znakem. Proto musí adresa URL obsahovat číslo následované lomítkem, za kterým následuje jiné číslo. Tyto skupiny zachycení jsou vloženy do přepsané adresy URL jako $1 a $2 . Náhradní řetězec pravidla přepsaní umístí zachycené skupiny do řetězce dotazu. Požadovaná cesta k /rewrite-rule/1234/5678 je přepsána za účelem získání prostředku v /rewritten?var1=1234&var2=5678 . Pokud se v původním požadavku nachází řetězec dotazu, bude při přepisování adresy URL zachován.

K získání prostředku neexistuje žádná Přenosová cesta k serveru. Pokud prostředek existuje, načte se a vrátí do klienta s kódem stavu 200-OK . Vzhledem k tomu, že klient není přesměrován, adresa URL v adresním řádku prohlížeče se nezmění. Klienti nerozpoznají, že na serveru došlo k operaci přepsání adresy URL.

Poznámka

skipRemainingRules: trueKdykoli je to možné, protože vyhovující pravidla jsou výpočetně náročná a zvyšují dobu odezvy aplikace. Pro nejrychlejší aplikační odpověď:

  • Seřazení pravidel přepisu z nejčastěji spárovaného pravidla na nejméně často spárované pravidlo.
  • Pokud dojde ke shodě a není vyžadováno žádné další zpracování pravidla, přeskočte zpracování zbývajících pravidel.

Mod_rewrite Apache

Použijte pravidla mod_rewrite Apache s AddApacheModRewrite . Ujistěte se, že je soubor pravidel nasazený spolu s aplikací. Další informace a příklady pravidel mod_rewrite najdete v tématu Apache mod_rewrite.

StreamReaderPoužívá se ke čtení pravidel ze souboru pravidel 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}"));
}

Ukázková aplikace přesměrovává požadavky od /apache-mod-rules-redirect/(.\*) do /redirected?id=$1 . Stavový kód odpovědi je 302 – Nalezeno.

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

Původní požadavek: /apache-mod-rules-redirect/1234

Okno prohlížeče s Vývojářské nástroje sledování požadavků a odpovědí

Middleware podporuje následující proměnné serveru Apache mod_rewrite:

  • CONN_REMOTE_ADDR
  • HTTP_ACCEPT
  • HTTP_CONNECTION
  • HTTP_COOKIE
  • HTTP_FORWARDED
  • HTTP_HOST
  • HTTP_REFERER
  • HTTP_USER_AGENT
  • HTTPS
  • PROTOKOLŮ
  • QUERY_STRING
  • REMOTE_ADDR
  • REMOTE_PORT
  • REQUEST_FILENAME
  • REQUEST_METHOD
  • REQUEST_SCHEME
  • REQUEST_URI
  • SCRIPT_FILENAME
  • SERVER_ADDR
  • SERVER_PORT
  • SERVER_PROTOCOL
  • ČAS
  • TIME_DAY
  • TIME_HOUR
  • TIME_MIN
  • TIME_MON
  • TIME_SEC
  • TIME_WDAY
  • TIME_YEAR

Pravidla pro přepsání adresy URL služby IIS

Pokud chcete použít stejnou sadu pravidel, která se vztahuje na modul IIS URL Rewrite, použijte AddIISUrlRewrite . Ujistěte se, že je soubor pravidel nasazený spolu s aplikací. nesměrujte middleware na použití web.config souboru aplikace při spuštění v Windows Server IIS. V případě služby IIS by tato pravidla měla být uložena mimo soubor web.config aplikace, aby nedocházelo ke konfliktům s modulem PŘEPISU služby IIS. Další informace a příklady pravidel pro přepis adres URL služby IIS najdete v tématu použití odkazu na modul pro přepis adres url 2,0 a odkaz na konfiguraci modulu přepisu adresyURL.

StreamReaderPoužívá se ke čtení pravidel ze souboru pravidel 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}"));
}

Ukázková aplikace přepíše požadavky od /iis-rules-rewrite/(.*) do /rewritten?id=$1 . Odpověď se pošle klientovi s kódem stavu 200-OK .

<rewrite>
  <rules>
    <rule name="Rewrite segment to id querystring" stopProcessing="true">
      <match url="^iis-rules-rewrite/(.*)$" />
      <action type="Rewrite" url="rewritten?id={R:1}" appendQueryString="false"/>
    </rule>
  </rules>
</rewrite>

Původní požadavek: /iis-rules-rewrite/1234

Okno prohlížeče se Vývojářské nástroje sledování žádosti a odpovědi

Pokud máte aktivní modul pro přepis služby IIS s nakonfigurovanými pravidly na úrovni serveru, který by ovlivnil vaši aplikaci nežádoucím způsobem, můžete pro aplikaci zakázat modul IIS Rewrite. Další informace najdete v tématu zakázání modulů IIS.

Nepodporované funkce

middleware vydaná ASP.NET Core 2. x nepodporuje následující funkce modulu pro přepis adres URL služby IIS:

  • Pravidla pro odchozí provoz
  • Vlastní proměnné serveru
  • Zástupné znaky
  • LogRewrittenUrl

Podporované proměnné serveru

Middleware podporuje následující proměnné serveru pro přepis adres URL služby 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

Poznámka

Můžete také získat IFileProvider prostřednictvím PhysicalFileProvider . Tento přístup může poskytovat větší flexibilitu pro umístění souborů pravidel přepisu. Ujistěte se, že jsou v cestě, kterou zadáte, nasazené soubory pravidel přepisu na server.

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

Pravidlo založené na metodách

Použijte Add k implementaci logiky vlastního pravidla v metodě. Add zpřístupňuje RewriteContext , který zpřístupňuje HttpContext metodu pro použití v metodě. RewriteContext. Result určuje, jak se zpracovává další zpracování kanálu. Nastavte hodnotu na jedno z RuleResult polí popsaných v následující tabulce.

Výsledek kontextu přepsání Akce
RuleResult.ContinueRules výchozí Pokračovat v používání pravidel.
RuleResult.EndResponse Zastavení použití pravidel a odeslání odpovědi.
RuleResult.SkipRemainingRules Zastavení použití pravidel a odeslání kontextu do dalšího middlewaru.
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}"));
}

Ukázková aplikace ukazuje metodu, která přesměrovává požadavky na cesty, které končí na .xml. Pokud je žádost určena pro /file.xml , je požadavek přesměrován na /xmlfiles/file.xml . Stavový kód je nastaven na 301 – trvale přesunuto. Když prohlížeč vytvoří nový požadavek na /xmlfiles/file.xml, soubor middleware statických souborů obsluhuje soubor do klienta ze složky wwwroot/xmlfiles . Pro přesměrování explicitně nastavte stavový kód odpovědi. V opačném případě se vrátí stavový kód 200-OK a na klientovi se neobjeví přesměrování.

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

Tento přístup může také přezapisovat požadavky. Ukázková aplikace ukazuje přepis cesty k libovolné žádosti o textový soubor, aby sloužila file.txt textový soubor ze složky wwwroot . Middleware statických souborů zachovává soubor na základě aktualizované cesty požadavku:

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

Pravidlo založené na IRule

Použijte Add k použití logiky pravidla ve třídě, která implementuje IRule rozhraní. IRule poskytuje větší flexibilitu při použití pravidla založeného na metodách. Vaše třída implementace může obsahovat konstruktor, který umožňuje předat parametry pro ApplyRule metodu.

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

Hodnoty parametrů v ukázkové aplikaci pro extension a newPath jsou zkontrolovány, aby splňovaly několik podmínek. extensionMusí obsahovat hodnotu a hodnota musí být .png, .jpg nebo .gif. Pokud newPath není platná, ArgumentException je vyvolána výjimka. Pokud se pro image.png požadavek provede, požadavek se přesměruje na /png-images/image.png . Pokud se pro image.jpg požadavek provede, požadavek se přesměruje na /jpg-images/image.jpg . Stavový kód je nastaven na 301 – trvale přesunuto a context.Result je nastavené na zastavení zpracování pravidel a odeslání odpovědi.

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

Původní požadavek: /image.png

Okno prohlížeče s Vývojářské nástroje sledování požadavků a odpovědí pro image.png

Původní požadavek: /image.jpg

Okno prohlížeče s Vývojářské nástroje sledování požadavků a odpovědí pro image.jpg

Příklady Regex

Cíl & řetězce regulárního výrazu
Příklad shody
& řetězce nahrazení
Příklad výstupu
Přepište cestu do řetězce dotazu. ^path/(.*)/(.*)
/path/abc/123
path?var1=$1&var2=$2
/path?var1=abc&var2=123
Koncové lomítko pruhu (.*)/$
/path/
$1
/path
Vymáhat koncové lomítko (.*[^/])$
/path
$1/
/path/
Vyhnout se přepisu konkrétních požadavků ^(.*)(?<!\.axd)$ nebo ^(?!.*\.axd$)(.*)$
Ano: /resource.htm
Ne: /resource.axd
rewritten/$1
/rewritten/resource.htm
/resource.axd
Změna uspořádání segmentů adresy URL path/(.*)/(.*)/(.*)
path/1/2/3
path/$3/$2/$1
path/3/2/1
Nahradit segment adresy URL ^(.*)/segment2/(.*)
/segment1/segment2/segment3
$1/replaced/$2
/segment1/replaced/segment3

Další zdroje informací