Penulisan Ulang URL Middleware di ASP.NET Core

Oleh Kirk Larkin dan Rick Anderson

Artikel ini memperkenalkan penulisan ulang URL dengan instruksi tentang cara menggunakan URL Menulis Ulang Middleware di aplikasi ASP.NET Core.

Penulisan ulang URL adalah tindakan memodifikasi URL permintaan berdasarkan satu atau beberapa aturan yang telah ditentukan sebelumnya. Penulisan ulang URL membuat abstraksi antara lokasi sumber daya dan alamatnya sehingga lokasi dan alamat tidak ditautkan dengan erat. Penulisan ulang URL sangat berharga dalam beberapa skenario untuk:

  • Pindahkan atau ganti sumber daya server untuk sementara atau permanen dan pertahankan pencari lokasi yang stabil untuk sumber daya tersebut.
  • Memisahkan pemrosesan permintaan di berbagai aplikasi atau di seluruh area satu aplikasi.
  • Menghapus, menambahkan, atau mengatur ulang segmen URL pada permintaan masuk.
  • Optimalkan URL publik untuk Pengoptimalan Mesin Pencari (SEO).
  • Izinkan penggunaan URL publik yang ramah untuk membantu pengunjung memprediksi konten yang dikembalikan dengan meminta sumber daya.
  • Alihkan permintaan yang tidak aman ke titik akhir yang aman.
  • Cegah hotlinking, di mana situs eksternal menggunakan aset statis yang dihosting di situs lain dengan menautkan aset ke kontennya sendiri.

Penulisan ulang URL dapat mengurangi performa aplikasi. Batasi jumlah dan kompleksitas aturan.

Pengalihan URL dan regenerasi URL

Perbedaan kata antara pengalihan URL dan penulisan ulang URL halus tetapi memiliki implikasi penting untuk menyediakan sumber daya kepada klien. ASP.NET Penulisan Ulang URL Core Middleware mampu memenuhi kebutuhan keduanya.

Pengalihan URL melibatkan operasi sisi klien, di mana klien diinstruksikan untuk mengakses sumber daya di alamat yang berbeda dari klien yang awalnya diminta. Ini memerlukan perjalanan pulang pergi ke server. URL pengalihan yang dikembalikan ke klien muncul di bilah alamat browser saat klien membuat permintaan baru untuk sumber daya.

Jika /resource dialihkanke /different-resource, server merespons bahwa klien harus mendapatkan sumber daya di /different-resource dengan kode status yang menunjukkan bahwa pengalihan bersifat sementara atau permanen.

A WebAPI service endpoint has been temporarily changed from version 1 (v1) to version 2 (v2) on the server. A client makes a request to the service at the version 1 path /v1/api. The server sends back a 302 (Found) response with the new, temporary path for the service at version 2 /v2/api. The client makes a second request to the service at the redirect URL. The server responds with a 200 (OK) status code.

Saat mengalihkan permintaan ke URL yang berbeda, tunjukkan apakah pengalihan bersifat permanen atau sementara dengan menentukan kode status dengan respons:

  • Kode 301 - Moved Permanently status digunakan di mana sumber daya memiliki URL permanen baru dan bahwa semua permintaan di masa mendatang untuk sumber daya harus menggunakan URL baru. Klien dapat menyimpan dan menggunakan kembali respons saat kode status 301 diterima.

  • Kode 302 - Found status digunakan di mana pengalihan bersifat sementara atau umumnya dapat berubah. Kode status 302 menunjukkan kepada klien untuk tidak menyimpan URL dan menggunakannya di masa mendatang.

Untuk informasi selengkapnya tentang kode status, lihat RFC 9110: Definisi Kode Status.

Penulisan ulang URL adalah operasi sisi server yang menyediakan sumber daya dari alamat sumber daya yang berbeda dari yang diminta klien. Menulis ulang URL tidak memerlukan perjalanan pulang pergi ke server. URL yang ditulis ulang tidak dikembalikan ke klien dan tidak muncul di bilah alamat browser.

Jika /resource ditulis ulang ke /different-resource, server secara internal mengambil dan mengembalikan sumber daya di /different-resource.

Meskipun klien mungkin dapat mengambil sumber daya di URL yang ditulis ulang, klien tidak diberi tahu bahwa sumber daya ada di URL yang ditulis ulang saat membuat permintaannya dan menerima respons.

A WebAPI service endpoint has been changed from version 1 (v1) to version 2 (v2) on the server. A client makes a request to the service at the version 1 path /v1/api. The request URL is rewritten to access the service at the version 2 path /v2/api. The service responds to the client with a 200 (OK) status code.

Aplikasi sampel penulisan ulang URL

Jelajahi fitur URL Menulis Ulang Middleware dengan aplikasi sampel. Aplikasi ini menerapkan aturan pengalihan dan penulisan ulang dan menunjukkan URL yang dialihkan atau ditulis ulang untuk beberapa skenario.

Kapan menggunakan middleware penulisan ulang URL

Gunakan MIDDLEware Penulisan Ulang URL saat pendekatan berikut tidak memuaskan:

Gunakan MIDDLEWARE penulisan ulang URL saat aplikasi dihosting di server HTTP.sys.

Alasan utama untuk menggunakan teknologi penulisan ulang URL berbasis server di IIS, Apache, dan Nginx adalah:

  • Middleware tidak mendukung fitur lengkap modul ini.

    Beberapa fitur modul server tidak berfungsi dengan proyek ASP.NET Core, seperti IsFile batasan dan IsDirectory modul Penulisan Ulang IIS. Dalam skenario ini, gunakan middleware sebagai gantinya.

  • Performa middleware mungkin tidak cocok dengan modul.

    Tolok ukur adalah satu-satunya cara untuk mengetahui dengan kepastian pendekatan mana yang paling banyak menurunkan performa atau jika performa yang terdegradasi dapat diabaikan.

Ekstensi dan opsi

Buat aturan penulisan ulang dan pengalihan URL dengan membuat instans kelas RewriteOptions dengan metode ekstensi untuk setiap aturan penulisan ulang. Rantai beberapa aturan dalam urutan yang harus diproses. RewriteOptions diteruskan ke URL Menulis Ulang Middleware saat ditambahkan ke alur permintaan dengan 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();

Dalam kode sebelumnya, MethodRules adalah kelas yang ditentukan pengguna. Lihat RewriteRules.cs di artikel ini untuk informasi selengkapnya.

Mengalihkan non-www ke www

Tiga opsi mengizinkan aplikasi untuk mengalihkan permintaan non-kewwwwww:

Pengalihan URL

Gunakan AddRedirect untuk mengalihkan permintaan. Parameter pertama berisi ekspresi reguler .NET (Regex) untuk pencocokan pada jalur URL masuk. Parameter kedua adalah string pengganti. Parameter ketiga, jika ada, menentukan kode status. Jika kode status tidak ditentukan, kode status default ke 302 - Ditemukan, yang menunjukkan bahwa sumber daya untuk sementara dipindahkan atau diganti.

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();

Di browser dengan alat pengembang diaktifkan, buat permintaan ke aplikasi sampel dengan jalur /redirect-rule/1234/5678. Ekspresi reguler cocok dengan jalur permintaan pada redirect-rule/(.*), dan jalur diganti dengan /redirected/1234/5678. URL pengalihan dikirim kembali ke klien dengan kode status 302 - Ditemukan . Browser membuat permintaan baru di URL pengalihan, yang muncul di bilah alamat browser. Karena tidak ada aturan dalam aplikasi sampel yang cocok pada URL pengalihan:

  • Permintaan kedua menerima respons 200 - OK dari aplikasi.
  • Isi respons menunjukkan URL pengalihan.

Perjalanan pulang pergi dilakukan ke server saat URL dialihkan.

Peringatan

Berhati-hatilah saat membuat aturan pengalihan. Aturan pengalihan dievaluasi pada setiap permintaan ke aplikasi, termasuk setelah pengalihan. Sangat mudah untuk secara tidak sengaja membuat perulangan pengalihan tak terbatas .

Bagian dari ekspresi yang terkandung dalam tanda kurung disebut grup pengambilan. Titik (.) ekspresi berarti cocok dengan karakter apa pun. Tanda bintang (*) menunjukkan kecocokan nol karakter sebelumnya atau lebih kali. Oleh karena itu, dua segmen jalur terakhir URL, 1234/5678, ditangkap oleh grup (.*)pengambilan . Nilai apa pun yang disediakan dalam URL permintaan setelah redirect-rule/ diambil oleh grup penangkapan tunggal ini.

Dalam string pengganti, grup yang diambil disuntikkan ke dalam string dengan tanda dolar ($) diikuti dengan nomor urut pengambilan. Nilai grup pengambilan pertama diperoleh dengan $1, yang kedua dengan $2, dan mereka melanjutkan secara berurutan untuk grup pengambilan dalam ekspresi reguler. Hanya ada satu grup yang diambil dalam regex aturan pengalihan di redirect-rule/(.*), sehingga hanya ada satu grup yang disuntikkan dalam string pengganti, yaitu $1. Saat aturan diterapkan, URL menjadi /redirected/1234/5678.

Coba /redirect-rule/1234/5678 dengan alat browser pada tab jaringan.

Pengalihan URL ke titik akhir yang aman

Gunakan AddRedirectToHttps untuk mengalihkan permintaan HTTP ke host dan jalur yang sama menggunakan protokol HTTPS. Jika kode status tidak disediakan, middleware default ke 302 - Ditemukan. Jika port tidak disediakan:

  • Middleware default ke null.
  • Skema berubah menjadi https (protokol HTTPS), dan klien mengakses sumber daya pada port 443.

Contoh berikut menunjukkan cara mengatur kode status ke 301 - Moved Permanently dan mengubah port ke port HTTPS yang digunakan oleh Kestrel pada localhost. Dalam produksi, port HTTPS diatur ke 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();

Gunakan AddRedirectToHttpsPermanent untuk mengalihkan permintaan yang tidak aman ke host dan jalur yang sama dengan protokol HTTPS aman pada port 443. Middleware mengatur kode status ke 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();

Catatan

Saat mengalihkan ke titik akhir yang aman tanpa persyaratan untuk aturan pengalihan tambahan, sebaiknya gunakan Middleware Pengalihan HTTPS. Untuk informasi selengkapnya, lihat Memberlakukan HTTPS.

Aplikasi sampel menunjukkan cara menggunakan AddRedirectToHttps atau AddRedirectToHttpsPermanent. Buat permintaan HTTP yang tidak aman ke aplikasi di http://redirect6.azurewebsites.net/iis-rules-rewrite/xyz. Saat menguji pengalihan HTTP ke HTTPS dengan localhost:

  • Gunakan URL HTTP, yang memiliki port yang berbeda dari URL HTTPS. URL HTTP ada dalam Properties/launchSettings.json file.
  • Menghapus s dari https://localhost/{port} gagal karena localhost tidak merespons pada HTTP ke port HTTPS.

Gambar berikut menunjukkan gambar alat browser F12 dari permintaan untuk http://redirect6.azurewebsites.net/iis-rules-rewrite/xyz menggunakan kode sebelumnya:

Browser window with developer tools tracking the requests and responses: Add redirect to HTTPS

Penulisan ulang URL

Gunakan AddRewrite untuk membuat aturan untuk menulis ulang URL. Parameter pertama berisi ekspresi reguler untuk pencocokan pada jalur URL masuk. Parameter kedua adalah string pengganti. Parameter ketiga, skipRemainingRules: {true|false}, menunjukkan kepada middleware apakah akan melewati aturan penulisan ulang tambahan atau tidak jika aturan saat ini diterapkan.

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();

Coba permintaan ke https://redirect6.azurewebsites.net/rewrite-rule/1234/5678

Tanda sisipan (^) di awal ekspresi berarti bahwa pencocokan dimulai di awal jalur URL.

Dalam contoh sebelumnya dengan aturan pengalihan, redirect-rule/(.*), tidak ada tanda sisipan (^) di awal ekspresi reguler. Oleh karena itu, setiap karakter dapat mendahului redirect-rule/ di jalur untuk kecocokan yang berhasil.

Jalur Cocokkan
/redirect-rule/1234/5678 Ya
/my-cool-redirect-rule/1234/5678 Ya
/anotherredirect-rule/1234/5678 Ya

Aturan penulisan ulang, ^rewrite-rule/(\d+)/(\d+), hanya cocok dengan jalur jika dimulai dengan rewrite-rule/. Dalam tabel berikut, perhatikan perbedaan dalam pencocokan.

Jalur Cocokkan
/rewrite-rule/1234/5678 Ya
/my-cool-rewrite-rule/1234/5678 No
/anotherrewrite-rule/1234/5678 Tidak

^rewrite-rule/ Setelah bagian ekspresi, ada dua grup pengambilan, (\d+)/(\d+). Menandakan \dcocok dengan digit (angka). Tanda plus (+) berarti cocok dengan satu atau beberapa karakter sebelumnya. Oleh karena itu, URL harus berisi angka yang diikuti dengan garis miring diikuti dengan angka lain. Grup penangkapan ini disuntikkan ke DALAM URL yang ditulis ulang sebagai $1 dan $2. String penggantian aturan penulisan ulang menempatkan grup yang diambil ke dalam string kueri. Jalur /rewrite-rule/1234/5678 yang diminta ditulis ulang untuk mengembalikan sumber daya di /rewritten?var1=1234&var2=5678. Jika string kueri ada pada permintaan asli, string tersebut dipertahankan saat URL ditulis ulang.

Tidak ada perjalanan pulang pergi ke server untuk mengembalikan sumber daya. Jika sumber daya ada, sumber daya diambil dan dikembalikan ke klien dengan kode status 200 - OK . Karena klien tidak dialihkan, URL di bilah alamat browser tidak berubah. Klien tidak dapat mendeteksi bahwa operasi penulisan ulang URL terjadi di server.

Tips performa untuk penulisan ulang dan pengalihan URL

Untuk respons tercepat:

  • Aturan penulisan ulang pesanan dari aturan yang paling sering cocok dengan aturan yang paling jarang dicocokkan.
  • Gunakan skipRemainingRules: true jika memungkinkan karena aturan yang cocok secara komputasi mahal dan meningkatkan waktu respons aplikasi. Lewati pemrosesan aturan yang tersisa ketika kecocokan terjadi dan tidak diperlukan pemrosesan aturan tambahan.

Peringatan

Pengguna berbahaya dapat memberikan input yang mahal untuk diproses hingga RegularExpressions menyebabkan serangan Denial-of-Service. ASP.NET API kerangka kerja Core yang menggunakan RegularExpressions batas waktu. Misalnya, kelas RedirectRule dan RewriteRule keduanya melewati batas waktu satu detik.

Apache mod_rewrite

Terapkan aturan Apache mod_rewrite dengan AddApacheModRewrite. Pastikan file aturan disebarkan dengan aplikasi. Untuk informasi selengkapnya dan contoh aturan mod_rewrite, lihat Apache mod_rewrite.

StreamReader digunakan untuk membaca aturan dari file aturan 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();

Aplikasi sampel mengalihkan permintaan dari /apache-mod-rules-redirect/(.\*) ke /redirected?id=$1. Kode status respons adalah 302 - Ditemukan.

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

Coba permintaan ke https://redirect6.azurewebsites.net/apache-mod-rules-redirect/1234

Middleware Apache mendukung variabel server apache mod_rewrite berikut:

  • 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

Aturan Modul Penulisan Ulang URL IIS

Untuk menggunakan seperangkat aturan yang sama yang berlaku untuk Modul Penulisan Ulang URL IIS, gunakan AddIISUrlRewrite. Pastikan file aturan disebarkan dengan aplikasi. Jangan arahkan middleware untuk menggunakan file web.config aplikasi saat berjalan di Windows Server IIS. Dengan IIS, aturan ini harus disimpan di luar file web.config aplikasi untuk menghindari konflik dengan modul Penulisan Ulang IIS. Untuk informasi selengkapnya dan contoh aturan Modul Penulisan Ulang URL IIS, lihat Menggunakan Modul Penulisan Ulang Url 2.0 dan Referensi Konfigurasi Modul Penulisan Ulang URL.

StreamReader digunakan untuk membaca aturan dari IISUrlRewrite.xml file aturan:

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();

Aplikasi sampel menulis ulang permintaan dari /iis-rules-rewrite/(.*) ke /rewritten?id=$1. Respons dikirim ke klien dengan kode status 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>

Coba permintaan ke https://redirect6.azurewebsites.net/iis-rules-rewrite/xyz

Aplikasi yang memiliki Modul Penulisan Ulang IIS aktif dengan aturan tingkat server yang dikonfigurasi yang memengaruhi aplikasi dengan cara yang tidak diinginkan:

  • Pertimbangkan untuk menonaktifkan Modul Penulisan Ulang IIS untuk aplikasi.
  • Untuk informasi selengkapnya, lihat Menonaktifkan modul IIS.

Fitur yang tidak didukung

Middleware tidak mendukung fitur Modul Penulisan Ulang URL IIS berikut:

  • Aturan Keluar
  • Variabel Server Kustom
  • Wildcard
  • LogRewrittenUrl

Variabel server yang didukung

Middleware mendukung variabel server Modul Penulisan Ulang URL IIS berikut:

  • 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 dapat diperoleh melalui PhysicalFileProvider. Pendekatan ini dapat memberikan fleksibilitas yang lebih besar untuk lokasi file aturan penulisan ulang. Pastikan bahwa file aturan penulisan ulang disebarkan ke server di jalur yang disediakan.

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

Aturan berbasis metode

Gunakan Add untuk menerapkan logika aturan kustom dalam metode . AddRewriteContextmengekspos , yang menyediakan HttpContext untuk digunakan dalam metode pengalihan. Properti RewriteContext.Result menentukan bagaimana pemrosesan alur tambahan ditangani. Atur nilai ke salah satu bidang yang RuleResult dijelaskan dalam tabel berikut ini.

Menulis ulang hasil konteks Perbuatan
RuleResult.ContinueRules (default) Lanjutkan menerapkan aturan.
RuleResult.EndResponse Berhenti menerapkan aturan dan kirim respons.
RuleResult.SkipRemainingRules Berhenti menerapkan aturan dan kirim konteks ke middleware berikutnya.
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();

Aplikasi sampel menunjukkan metode yang mengalihkan permintaan untuk jalur yang diakhir dengan .xml. Ketika permintaan dibuat untuk /file.xml:

  • Permintaan dialihkan ke /xmlfiles/file.xml
  • Kode status diatur ke 301 - Moved Permanently. Ketika browser membuat permintaan baru untuk /xmlfiles/file.xml, Middleware File Statis melayani file ke klien dari folder wwwroot/xmlfiles . Untuk pengalihan, atur kode status respons secara eksplisit. Jika tidak, kode status 200 - OK dikembalikan, dan pengalihan tidak terjadi pada klien.

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

Pendekatan ini juga dapat menulis ulang permintaan. Aplikasi sampel menunjukkan penulisan ulang jalur untuk setiap permintaan file teks untuk melayani file teks file.txt dari folder wwwroot . Middleware File Statis melayani file berdasarkan jalur permintaan yang diperbarui:

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

Aturan berbasis IRule

Gunakan Add untuk menggunakan logika aturan di kelas yang mengimplementasikan IRule antarmuka. IRule memberikan fleksibilitas yang lebih besar daripada menggunakan pendekatan aturan berbasis metode. Kelas implementasi dapat mencakup konstruktor yang memungkinkan meneruskan parameter untuk metode .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();

Nilai parameter di aplikasi sampel untuk extension dan newPath diperiksa untuk memenuhi beberapa kondisi. extension harus berisi nilai, dan nilainya harus .png, , .jpgatau .gif. newPath Jika tidak valid, maka ArgumentException akan dilemparkan. Jika permintaan dibuat untuk image.png, permintaan dialihkan ke /png-images/image.png. Jika permintaan dibuat untuk image.jpg, permintaan dialihkan ke /jpg-images/image.jpg. Kode status diatur ke 301 - Moved Permanently, dan context.Result diatur untuk menghentikan aturan pemrosesan dan mengirim respons.

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

Coba:

  • Permintaan PNG: https://redirect6.azurewebsites.net/image.png
  • Permintaan JPG: https://redirect6.azurewebsites.net/image.jpg

Contoh regex

Goal String Regex &
Contoh Kecocokan
String Penggantian &
Contoh Output
Menulis ulang jalur ke dalam querystring ^path/(.*)/(.*)
/path/abc/123
path?var1=$1&var2=$2
/path?var1=abc&var2=123
Garis miring berikutnya ^path2/(.*)/$
/path2/xyz/
$1
/path2/xyz
Terapkan garis miring berikutnya ^path3/(.*[^/])$
/path3/xyz
$1/
/path3/xyz/
Hindari menulis ulang permintaan tertentu ^(.*)(?<!\.axd)$ Atau
^(?!.*\.axd$)(.*)$
Ya: /path4/resource.htm
Tidak: /path4/resource.axd
rewritten/$1
/rewritten/resource.htm
/resource.axd
Menyusun ulang segmen URL path5/(.*)/(.*)/(.*)
path5/1/2/3
path5/$3/$2/$1
path5/3/2/1
Mengganti segmen URL ^path6/(.*)/segment2/(.*)
^path6/segment1/segment2/segment3
path6/$1/replaced/$2
/path6/segment1/replaced/segment3

Tautan dalam tabel sebelumnya menggunakan kode berikut yang disebarkan ke 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();

Di sebagian besar sampel ekspresi reguler sebelumnya, harfiah path digunakan untuk membuat aturan penulisan ulang unik yang dapat diuji untuk sampel yang disebarkan. Biasanya ekspresi reguler tidak akan menyertakan path. Misalnya, lihat tabel contoh ekspresi reguler ini.

Dokumen ini memperkenalkan penulisan ulang URL dengan instruksi tentang cara menggunakan URL Menulis Ulang Middleware di aplikasi ASP.NET Core.

Penulisan ulang URL adalah tindakan memodifikasi URL permintaan berdasarkan satu atau beberapa aturan yang telah ditentukan sebelumnya. Penulisan ulang URL membuat abstraksi antara lokasi sumber daya dan alamatnya sehingga lokasi dan alamat tidak ditautkan dengan erat. Penulisan ulang URL sangat berharga dalam beberapa skenario untuk:

  • Pindahkan atau ganti sumber daya server untuk sementara atau permanen dan pertahankan pencari lokasi yang stabil untuk sumber daya tersebut.
  • Memisahkan pemrosesan permintaan di berbagai aplikasi atau di seluruh area satu aplikasi.
  • Menghapus, menambahkan, atau mengatur ulang segmen URL pada permintaan masuk.
  • Optimalkan URL publik untuk Pengoptimalan Mesin Pencari (SEO).
  • Izinkan penggunaan URL publik yang ramah untuk membantu pengunjung memprediksi konten yang dikembalikan dengan meminta sumber daya.
  • Alihkan permintaan yang tidak aman ke titik akhir yang aman.
  • Cegah hotlinking, di mana situs eksternal menggunakan aset statis yang dihosting di situs lain dengan menautkan aset ke kontennya sendiri.

Catatan

Penulisan ulang URL dapat mengurangi performa aplikasi. Jika memungkinkan, batasi jumlah dan kompleksitas aturan.

Melihat atau mengunduh kode sampel (cara mengunduh)

Pengalihan URL dan regenerasi URL

Perbedaan kata antara pengalihan URL dan penulisan ulang URL halus tetapi memiliki implikasi penting untuk menyediakan sumber daya kepada klien. ASP.NET Penulisan Ulang URL Core Middleware mampu memenuhi kebutuhan keduanya.

Pengalihan URL melibatkan operasi sisi klien, di mana klien diinstruksikan untuk mengakses sumber daya di alamat yang berbeda dari klien yang awalnya diminta. Ini memerlukan perjalanan pulang pergi ke server. URL pengalihan yang dikembalikan ke klien muncul di bilah alamat browser saat klien membuat permintaan baru untuk sumber daya.

Jika /resource dialihkanke /different-resource, server merespons bahwa klien harus mendapatkan sumber daya di /different-resource dengan kode status yang menunjukkan bahwa pengalihan bersifat sementara atau permanen.

A WebAPI service endpoint has been temporarily changed from version 1 (v1) to version 2 (v2) on the server. A client makes a request to the service at the version 1 path /v1/api. The server sends back a 302 (Found) response with the new, temporary path for the service at version 2 /v2/api. The client makes a second request to the service at the redirect URL. The server responds with a 200 (OK) status code.

Saat mengalihkan permintaan ke URL yang berbeda, tunjukkan apakah pengalihan bersifat permanen atau sementara dengan menentukan kode status dengan respons:

  • Kode 301 - Moved Permanently status digunakan di mana sumber daya memiliki URL permanen baru dan Anda ingin menginstruksikan klien bahwa semua permintaan sumber daya di masa mendatang harus menggunakan URL baru. Klien dapat menyimpan dan menggunakan kembali respons saat kode status 301 diterima.

  • Kode status 302 - Ditemukan digunakan di mana pengalihan bersifat sementara atau umumnya dapat berubah. Kode status 302 menunjukkan kepada klien untuk tidak menyimpan URL dan menggunakannya di masa mendatang.

Untuk informasi selengkapnya tentang kode status, lihat RFC 9110: Definisi Kode Status.

Penulisan ulang URL adalah operasi sisi server yang menyediakan sumber daya dari alamat sumber daya yang berbeda dari yang diminta klien. Menulis ulang URL tidak memerlukan perjalanan pulang pergi ke server. URL yang ditulis ulang tidak dikembalikan ke klien dan tidak muncul di bilah alamat browser.

Jika /resource ditulis ulang ke /different-resource, server secara internal mengambil dan mengembalikan sumber daya di /different-resource.

Meskipun klien mungkin dapat mengambil sumber daya di URL yang ditulis ulang, klien tidak diberi tahu bahwa sumber daya ada di URL yang ditulis ulang saat membuat permintaannya dan menerima respons.

A WebAPI service endpoint has been changed from version 1 (v1) to version 2 (v2) on the server. A client makes a request to the service at the version 1 path /v1/api. The request URL is rewritten to access the service at the version 2 path /v2/api. The service responds to the client with a 200 (OK) status code.

Aplikasi sampel penulisan ulang URL

Anda dapat menjelajahi fitur MIDDLEware Penulisan Ulang URL dengan aplikasi sampel. Aplikasi ini menerapkan aturan pengalihan dan penulisan ulang dan menunjukkan URL yang dialihkan atau ditulis ulang untuk beberapa skenario.

Kapan menggunakan middleware penulisan ulang URL

Gunakan Middleware Penulisan Ulang URL saat Anda tidak dapat menggunakan pendekatan berikut:

Gunakan MIDDLEWARE penulisan ulang URL saat aplikasi dihosting di server HTTP.sys.

Alasan utama untuk menggunakan teknologi penulisan ulang URL berbasis server di IIS, Apache, dan Nginx adalah:

  • Middleware tidak mendukung fitur lengkap modul ini.

    Beberapa fitur modul server tidak berfungsi dengan proyek ASP.NET Core, seperti IsFile batasan dan IsDirectory modul Penulisan Ulang IIS. Dalam skenario ini, gunakan middleware sebagai gantinya.

  • Performa middleware mungkin tidak cocok dengan modul.

    Tolok ukur adalah satu-satunya cara untuk mengetahui dengan pasti pendekatan mana yang paling banyak menurunkan performa atau jika performa yang terdegradasi dapat diabaikan.

Paket

Url Penulisan Ulang Middleware disediakan oleh paket Microsoft.AspNetCore.Rewrite , yang secara implisit disertakan dalam aplikasi ASP.NET Core.

Ekstensi dan opsi

Buat aturan penulisan ulang dan pengalihan URL dengan membuat instans kelas RewriteOptions dengan metode ekstensi untuk setiap aturan penulisan ulang Anda. Rantai beberapa aturan dalam urutan yang Anda inginkan untuk diproses. RewriteOptions diteruskan ke URL Menulis Ulang Middleware saat ditambahkan ke alur permintaan dengan 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}"));
}

Mengalihkan non-www ke www

Tiga opsi mengizinkan aplikasi untuk mengalihkan permintaan non-kewwwwww:

Pengalihan URL

Gunakan AddRedirect untuk mengalihkan permintaan. Parameter pertama berisi Regex Anda untuk pencocokan pada jalur URL masuk. Parameter kedua adalah string pengganti. Parameter ketiga, jika ada, menentukan kode status. Jika Anda tidak menentukan kode status, kode status default ke 302 - Ditemukan, yang menunjukkan bahwa sumber daya untuk sementara dipindahkan atau diganti.

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

Di browser dengan alat pengembang diaktifkan, buat permintaan ke aplikasi sampel dengan jalur /redirect-rule/1234/5678. Regex cocok dengan jalur permintaan pada redirect-rule/(.*), dan jalur diganti dengan /redirected/1234/5678. URL pengalihan dikirim kembali ke klien dengan kode status 302 - Ditemukan . Browser membuat permintaan baru di URL pengalihan, yang muncul di bilah alamat browser. Karena tidak ada aturan dalam aplikasi sampel yang cocok pada URL pengalihan:

  • Permintaan kedua menerima respons 200 - OK dari aplikasi.
  • Isi respons menunjukkan URL pengalihan.

Perjalanan pulang pergi dilakukan ke server saat URL dialihkan.

Peringatan

Berhati-hatilah saat membuat aturan pengalihan. Aturan pengalihan dievaluasi pada setiap permintaan ke aplikasi, termasuk setelah pengalihan. Sangat mudah untuk secara tidak sengaja membuat perulangan pengalihan tak terbatas.

Permintaan Asli: /redirect-rule/1234/5678

Browser window with developer tools tracking the requests and responses: Add redirect

Bagian dari ekspresi yang terkandung dalam tanda kurung disebut grup pengambilan. Titik (.) ekspresi berarti cocok dengan karakter apa pun. Tanda bintang (*) menunjukkan kecocokan nol karakter sebelumnya atau lebih kali. Oleh karena itu, dua segmen jalur terakhir URL, 1234/5678, ditangkap oleh grup (.*)pengambilan . Nilai apa pun yang Anda berikan dalam URL permintaan setelah redirect-rule/ diambil oleh grup tangkapan tunggal ini.

Dalam string pengganti, grup yang diambil disuntikkan ke dalam string dengan tanda dolar ($) diikuti dengan nomor urut pengambilan. Nilai grup pengambilan pertama diperoleh dengan $1, yang kedua dengan $2, dan mereka melanjutkan secara berurutan untuk grup pengambilan di regex Anda. Hanya ada satu grup yang diambil dalam regex aturan pengalihan di aplikasi sampel, jadi hanya ada satu grup yang disuntikkan dalam string pengganti, yaitu $1. Saat aturan diterapkan, URL menjadi /redirected/1234/5678.

Pengalihan URL ke titik akhir yang aman

Gunakan AddRedirectToHttps untuk mengalihkan permintaan HTTP ke host dan jalur yang sama menggunakan protokol HTTPS. Jika kode status tidak disediakan, middleware default ke 302 - Ditemukan. Jika port tidak disediakan:

  • Middleware default ke null.
  • Skema berubah menjadi https (protokol HTTPS), dan klien mengakses sumber daya pada port 443.

Contoh berikut menunjukkan cara mengatur kode status ke 301 - Moved Permanently dan mengubah port menjadi 5001.

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

    app.UseRewriter(options);
}

Gunakan AddRedirectToHttpsPermanent untuk mengalihkan permintaan yang tidak aman ke host dan jalur yang sama dengan protokol HTTPS aman pada port 443. Middleware mengatur kode status ke 301 - Moved Permanently.

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

    app.UseRewriter(options);
}

Catatan

Saat mengalihkan ke titik akhir yang aman tanpa persyaratan untuk aturan pengalihan tambahan, sebaiknya gunakan Middleware Pengalihan HTTPS. Untuk informasi selengkapnya, lihat topik Terlaksanakan HTTPS .

Aplikasi sampel mampu menunjukkan cara menggunakan AddRedirectToHttps atau AddRedirectToHttpsPermanent. Tambahkan metode ekstensi ke RewriteOptions. Buat permintaan yang tidak aman ke aplikasi di URL apa pun. Mengabaikan peringatan keamanan browser bahwa sertifikat yang ditandatangani sendiri tidak tepercaya atau membuat pengecualian untuk mempercayai sertifikat.

Permintaan Asli menggunakan AddRedirectToHttps(301, 5001): http://localhost:5000/secure

Browser window with developer tools tracking the requests and responses: Add redirect to HTTPS

Permintaan Asli menggunakan AddRedirectToHttpsPermanent: http://localhost:5000/secure

Browser window with developer tools tracking the requests and responses: Add redirect to HTTPS permanent

Penulisan ulang URL

Gunakan AddRewrite untuk membuat aturan untuk menulis ulang URL. Parameter pertama berisi regex untuk pencocokan pada jalur URL masuk. Parameter kedua adalah string pengganti. Parameter ketiga, skipRemainingRules: {true|false}, menunjukkan kepada middleware apakah akan melewati aturan penulisan ulang tambahan atau tidak jika aturan saat ini diterapkan.

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

Permintaan Asli: /rewrite-rule/1234/5678

Browser window with developer tools tracking the request and response: Add rewrite

Karat (^) di awal ekspresi berarti bahwa pencocokan dimulai di awal jalur URL.

Dalam contoh sebelumnya dengan aturan pengalihan, redirect-rule/(.*), tidak ada karat (^) di awal regex. Oleh karena itu, setiap karakter dapat mendahului redirect-rule/ di jalur untuk kecocokan yang berhasil.

Jalur Cocokkan
/redirect-rule/1234/5678 Ya
/my-cool-redirect-rule/1234/5678 Ya
/anotherredirect-rule/1234/5678 Ya

Aturan penulisan ulang, ^rewrite-rule/(\d+)/(\d+), hanya cocok dengan jalur jika dimulai dengan rewrite-rule/. Dalam tabel berikut, perhatikan perbedaan dalam pencocokan.

Jalur Cocokkan
/rewrite-rule/1234/5678 Ya
/my-cool-rewrite-rule/1234/5678 No
/anotherrewrite-rule/1234/5678 Tidak

^rewrite-rule/ Setelah bagian ekspresi, ada dua grup pengambilan, (\d+)/(\d+). Menandakan \dcocok dengan digit (angka). Tanda plus (+) berarti cocok dengan satu atau beberapa karakter sebelumnya. Oleh karena itu, URL harus berisi angka yang diikuti dengan garis miring diikuti dengan angka lain. Grup penangkapan ini disuntikkan ke DALAM URL yang ditulis ulang sebagai $1 dan $2. String penggantian aturan penulisan ulang menempatkan grup yang diambil ke dalam string kueri. Jalur /rewrite-rule/1234/5678 yang diminta ditulis ulang untuk mendapatkan sumber daya di /rewritten?var1=1234&var2=5678. Jika string kueri ada pada permintaan asli, string tersebut dipertahankan saat URL ditulis ulang.

Tidak ada perjalanan pulang pergi ke server untuk mendapatkan sumber daya. Jika sumber daya ada, sumber daya diambil dan dikembalikan ke klien dengan kode status 200 - OK . Karena klien tidak dialihkan, URL di bilah alamat browser tidak berubah. Klien tidak dapat mendeteksi bahwa operasi penulisan ulang URL terjadi di server.

Catatan

Gunakan skipRemainingRules: true jika memungkinkan karena aturan yang cocok secara komputasi mahal dan meningkatkan waktu respons aplikasi. Untuk respons aplikasi tercepat:

  • Aturan penulisan ulang pesanan dari aturan yang paling sering cocok dengan aturan yang paling jarang dicocokkan.
  • Lewati pemrosesan aturan yang tersisa ketika kecocokan terjadi dan tidak diperlukan pemrosesan aturan tambahan.

Apache mod_rewrite

Terapkan aturan Apache mod_rewrite dengan AddApacheModRewrite. Pastikan file aturan disebarkan dengan aplikasi. Untuk informasi selengkapnya dan contoh aturan mod_rewrite, lihat Apache mod_rewrite.

StreamReader digunakan untuk membaca aturan dari file aturan 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}"));
}

Aplikasi sampel mengalihkan permintaan dari /apache-mod-rules-redirect/(.\*) ke /redirected?id=$1. Kode status respons adalah 302 - Ditemukan.

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

Permintaan Asli: /apache-mod-rules-redirect/1234

Browser window with developer tools tracking the requests and responses: Add Apache mod redirect

Middleware mendukung variabel server Apache mod_rewrite berikut:

  • 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

Aturan Modul Penulisan Ulang URL IIS

Untuk menggunakan seperangkat aturan yang sama yang berlaku untuk Modul Penulisan Ulang URL IIS, gunakan AddIISUrlRewrite. Pastikan file aturan disebarkan dengan aplikasi. Jangan arahkan middleware untuk menggunakan file web.config aplikasi saat berjalan di Windows Server IIS. Dengan IIS, aturan ini harus disimpan di luar file web.config aplikasi untuk menghindari konflik dengan modul Penulisan Ulang IIS. Untuk informasi selengkapnya dan contoh aturan Modul Penulisan Ulang URL IIS, lihat Menggunakan Modul Penulisan Ulang Url 2.0 dan Referensi Konfigurasi Modul Penulisan Ulang URL.

StreamReader digunakan untuk membaca aturan dari IISUrlRewrite.xml file aturan:

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

Aplikasi sampel menulis ulang permintaan dari /iis-rules-rewrite/(.*) ke /rewritten?id=$1. Respons dikirim ke klien dengan kode status 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>

Permintaan Asli: /iis-rules-rewrite/1234

Browser window with developer tools tracking the request and response: Add IIS URL rewrite

Jika Anda memiliki Modul Penulisan Ulang IIS aktif dengan aturan tingkat server yang dikonfigurasi yang akan memengaruhi aplikasi Anda dengan cara yang tidak diinginkan, Anda dapat menonaktifkan Modul Penulisan Ulang IIS untuk aplikasi. Untuk informasi selengkapnya, lihat Menonaktifkan modul IIS.

Fitur yang tidak didukung

Middleware tidak mendukung fitur Modul Penulisan Ulang URL IIS berikut:

  • Aturan Keluar
  • Variabel Server Kustom
  • Wildcard
  • LogRewrittenUrl

Variabel server yang didukung

Middleware mendukung variabel server Modul Penulisan Ulang URL IIS berikut:

  • 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

Catatan

Anda juga dapat memperoleh IFileProvider melalui PhysicalFileProvider. Pendekatan ini dapat memberikan fleksibilitas yang lebih besar untuk lokasi file aturan penulisan ulang Anda. Pastikan file aturan penulisan ulang Anda disebarkan ke server di jalur yang Anda sediakan.

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

Aturan berbasis metode

Gunakan Add untuk menerapkan logika aturan Anda sendiri dalam metode . AddRewriteContextmengekspos , yang menyediakan HttpContext untuk digunakan dalam metode Anda. RewriteContext.Result menentukan bagaimana pemrosesan alur tambahan ditangani. Atur nilai ke salah satu bidang yang RuleResult dijelaskan dalam tabel berikut ini.

Menulis ulang hasil konteks Perbuatan
RuleResult.ContinueRules (default) Lanjutkan menerapkan aturan.
RuleResult.EndResponse Berhenti menerapkan aturan dan kirim respons.
RuleResult.SkipRemainingRules Berhenti menerapkan aturan dan kirim konteks ke middleware berikutnya.
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}"));
}

Aplikasi sampel menunjukkan metode yang mengalihkan permintaan untuk jalur yang diakhir dengan .xml. Jika permintaan dibuat untuk /file.xml, permintaan dialihkan ke /xmlfiles/file.xml. Kode status diatur ke 301 - Moved Permanently. Ketika browser membuat permintaan baru untuk /xmlfiles/file.xml, Middleware File Statis melayani file ke klien dari folder wwwroot/xmlfiles . Untuk pengalihan, atur kode status respons secara eksplisit. Jika tidak, kode status 200 - OK dikembalikan, dan pengalihan tidak terjadi pada klien.

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

Pendekatan ini juga dapat menulis ulang permintaan. Aplikasi sampel menunjukkan penulisan ulang jalur untuk setiap permintaan file teks untuk melayani file teks file.txt dari folder wwwroot . Middleware File Statis melayani file berdasarkan jalur permintaan yang diperbarui:

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

Aturan berbasis IRule

Gunakan Add untuk menggunakan logika aturan di kelas yang mengimplementasikan IRule antarmuka. IRule memberikan fleksibilitas yang lebih besar daripada menggunakan pendekatan aturan berbasis metode. Kelas implementasi Anda dapat mencakup konstruktor yang memungkinkan Anda dapat meneruskan parameter untuk metode tersebut 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}"));
}

Nilai parameter di aplikasi sampel untuk extension dan newPath diperiksa untuk memenuhi beberapa kondisi. extension harus berisi nilai, dan nilainya harus .png, , .jpgatau .gif. newPath Jika tidak valid, maka ArgumentException akan dilemparkan. Jika permintaan dibuat untuk image.png, permintaan dialihkan ke /png-images/image.png. Jika permintaan dibuat untuk image.jpg, permintaan dialihkan ke /jpg-images/image.jpg. Kode status diatur ke 301 - Moved Permanently, dan context.Result diatur untuk menghentikan aturan pemrosesan dan mengirim respons.

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

Permintaan Asli: /image.png

Browser window with developer tools tracking the requests and responses for image.png

Permintaan Asli: /image.jpg

Browser window with developer tools tracking the requests and responses for image.jpg

Contoh regex

Goal String Regex &
Contoh Kecocokan
String Penggantian &
Contoh Output
Menulis ulang jalur ke dalam querystring ^path/(.*)/(.*)
/path/abc/123
path?var1=$1&var2=$2
/path?var1=abc&var2=123
Garis miring berikutnya (.*)/$
/path/
$1
/path
Terapkan garis miring berikutnya (.*[^/])$
/path
$1/
/path/
Hindari menulis ulang permintaan tertentu ^(.*)(?<!\.axd)$ atau ^(?!.*\.axd$)(.*)$
Ya: /resource.htm
Tidak: /resource.axd
rewritten/$1
/rewritten/resource.htm
/resource.axd
Menyusun ulang segmen URL path/(.*)/(.*)/(.*)
path/1/2/3
path/$3/$2/$1
path/3/2/1
Mengganti segmen URL ^(.*)/segment2/(.*)
/segment1/segment2/segment3
$1/replaced/$2
/segment1/replaced/segment3

Dokumen ini memperkenalkan penulisan ulang URL dengan instruksi tentang cara menggunakan URL Menulis Ulang Middleware di aplikasi ASP.NET Core.

Penulisan ulang URL adalah tindakan memodifikasi URL permintaan berdasarkan satu atau beberapa aturan yang telah ditentukan sebelumnya. Penulisan ulang URL membuat abstraksi antara lokasi sumber daya dan alamatnya sehingga lokasi dan alamat tidak ditautkan dengan erat. Penulisan ulang URL sangat berharga dalam beberapa skenario untuk:

  • Pindahkan atau ganti sumber daya server untuk sementara atau permanen dan pertahankan pencari lokasi yang stabil untuk sumber daya tersebut.
  • Memisahkan pemrosesan permintaan di berbagai aplikasi atau di seluruh area satu aplikasi.
  • Menghapus, menambahkan, atau mengatur ulang segmen URL pada permintaan masuk.
  • Optimalkan URL publik untuk Pengoptimalan Mesin Pencari (SEO).
  • Izinkan penggunaan URL publik yang ramah untuk membantu pengunjung memprediksi konten yang dikembalikan dengan meminta sumber daya.
  • Alihkan permintaan yang tidak aman ke titik akhir yang aman.
  • Cegah hotlinking, di mana situs eksternal menggunakan aset statis yang dihosting di situs lain dengan menautkan aset ke kontennya sendiri.

Catatan

Penulisan ulang URL dapat mengurangi performa aplikasi. Jika memungkinkan, batasi jumlah dan kompleksitas aturan.

Melihat atau mengunduh kode sampel (cara mengunduh)

Pengalihan URL dan regenerasi URL

Perbedaan kata antara pengalihan URL dan penulisan ulang URL halus tetapi memiliki implikasi penting untuk menyediakan sumber daya kepada klien. ASP.NET Penulisan Ulang URL Core Middleware mampu memenuhi kebutuhan keduanya.

Pengalihan URL melibatkan operasi sisi klien, di mana klien diinstruksikan untuk mengakses sumber daya di alamat yang berbeda dari klien yang awalnya diminta. Ini memerlukan perjalanan pulang pergi ke server. URL pengalihan yang dikembalikan ke klien muncul di bilah alamat browser saat klien membuat permintaan baru untuk sumber daya.

Jika /resource dialihkanke /different-resource, server merespons bahwa klien harus mendapatkan sumber daya di /different-resource dengan kode status yang menunjukkan bahwa pengalihan bersifat sementara atau permanen.

A WebAPI service endpoint has been temporarily changed from version 1 (v1) to version 2 (v2) on the server. A client makes a request to the service at the version 1 path /v1/api. The server sends back a 302 (Found) response with the new, temporary path for the service at version 2 /v2/api. The client makes a second request to the service at the redirect URL. The server responds with a 200 (OK) status code.

Saat mengalihkan permintaan ke URL yang berbeda, tunjukkan apakah pengalihan bersifat permanen atau sementara dengan menentukan kode status dengan respons:

  • Kode 301 - Moved Permanently status digunakan di mana sumber daya memiliki URL permanen baru dan Anda ingin menginstruksikan klien bahwa semua permintaan sumber daya di masa mendatang harus menggunakan URL baru. Klien dapat menyimpan dan menggunakan kembali respons saat kode status 301 diterima.

  • Kode status 302 - Ditemukan digunakan di mana pengalihan bersifat sementara atau umumnya dapat berubah. Kode status 302 menunjukkan kepada klien untuk tidak menyimpan URL dan menggunakannya di masa mendatang.

Untuk informasi selengkapnya tentang kode status, lihat RFC 9110: Definisi Kode Status.

Penulisan ulang URL adalah operasi sisi server yang menyediakan sumber daya dari alamat sumber daya yang berbeda dari yang diminta klien. Menulis ulang URL tidak memerlukan perjalanan pulang pergi ke server. URL yang ditulis ulang tidak dikembalikan ke klien dan tidak muncul di bilah alamat browser.

Jika /resource ditulis ulang ke /different-resource, server secara internal mengambil dan mengembalikan sumber daya di /different-resource.

Meskipun klien mungkin dapat mengambil sumber daya di URL yang ditulis ulang, klien tidak diberi tahu bahwa sumber daya ada di URL yang ditulis ulang saat membuat permintaannya dan menerima respons.

A WebAPI service endpoint has been changed from version 1 (v1) to version 2 (v2) on the server. A client makes a request to the service at the version 1 path /v1/api. The request URL is rewritten to access the service at the version 2 path /v2/api. The service responds to the client with a 200 (OK) status code.

Aplikasi sampel penulisan ulang URL

Anda dapat menjelajahi fitur MIDDLEware Penulisan Ulang URL dengan aplikasi sampel. Aplikasi ini menerapkan aturan pengalihan dan penulisan ulang dan menunjukkan URL yang dialihkan atau ditulis ulang untuk beberapa skenario.

Kapan menggunakan MIDDLEware Penulisan Ulang URL

Gunakan Middleware Penulisan Ulang URL saat Anda tidak dapat menggunakan pendekatan berikut:

Selain itu, gunakan middleware saat aplikasi dihosting di server HTTP.sys (sebelumnya disebut WebListener).

Alasan utama untuk menggunakan teknologi penulisan ulang URL berbasis server di IIS, Apache, dan Nginx adalah:

  • Middleware tidak mendukung fitur lengkap modul ini.

    Beberapa fitur modul server tidak berfungsi dengan proyek ASP.NET Core, seperti IsFile batasan dan IsDirectory modul Penulisan Ulang IIS. Dalam skenario ini, gunakan middleware sebagai gantinya.

  • Performa middleware mungkin tidak cocok dengan modul.

    Tolok ukur adalah satu-satunya cara untuk mengetahui dengan pasti pendekatan mana yang paling banyak menurunkan performa atau jika performa yang terdegradasi dapat diabaikan.

Paket

Untuk menyertakan middleware dalam proyek Anda, tambahkan referensi paket ke metapackage Microsoft.AspNetCore.App dalam file proyek, yang berisi paket Microsoft.AspNetCore.Rewrite .

Saat tidak menggunakan Microsoft.AspNetCore.App metapackage, tambahkan referensi proyek ke Microsoft.AspNetCore.Rewrite paket.

Ekstensi dan opsi

Buat aturan penulisan ulang dan pengalihan URL dengan membuat instans kelas RewriteOptions dengan metode ekstensi untuk setiap aturan penulisan ulang Anda. Rantai beberapa aturan dalam urutan yang Anda inginkan untuk diproses. RewriteOptions diteruskan ke URL Menulis Ulang Middleware saat ditambahkan ke alur permintaan dengan 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}"));
}

Mengalihkan non-www ke www

Tiga opsi mengizinkan aplikasi untuk mengalihkan permintaan non-kewwwwww:

Pengalihan URL

Gunakan AddRedirect untuk mengalihkan permintaan. Parameter pertama berisi regex Anda untuk pencocokan pada jalur URL masuk. Parameter kedua adalah string pengganti. Parameter ketiga, jika ada, menentukan kode status. Jika Anda tidak menentukan kode status, kode status default ke 302 - Ditemukan, yang menunjukkan bahwa sumber daya untuk sementara dipindahkan atau diganti.

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

Di browser dengan alat pengembang diaktifkan, buat permintaan ke aplikasi sampel dengan jalur /redirect-rule/1234/5678. Regex cocok dengan jalur permintaan pada redirect-rule/(.*), dan jalur diganti dengan /redirected/1234/5678. URL pengalihan dikirim kembali ke klien dengan kode status 302 - Ditemukan . Browser membuat permintaan baru di URL pengalihan, yang muncul di bilah alamat browser. Karena tidak ada aturan dalam aplikasi sampel yang cocok pada URL pengalihan:

  • Permintaan kedua menerima respons 200 - OK dari aplikasi.
  • Isi respons menunjukkan URL pengalihan.

Perjalanan pulang pergi dilakukan ke server saat URL dialihkan.

Peringatan

Berhati-hatilah saat membuat aturan pengalihan. Aturan pengalihan dievaluasi pada setiap permintaan ke aplikasi, termasuk setelah pengalihan. Sangat mudah untuk secara tidak sengaja membuat perulangan pengalihan tak terbatas.

Permintaan Asli: /redirect-rule/1234/5678

Add redirect: Browser window with developer tools tracking the requests and responses

Bagian dari ekspresi yang terkandung dalam tanda kurung disebut grup pengambilan. Titik (.) ekspresi berarti cocok dengan karakter apa pun. Tanda bintang (*) menunjukkan kecocokan nol karakter sebelumnya atau lebih kali. Oleh karena itu, dua segmen jalur terakhir URL, 1234/5678, ditangkap oleh grup (.*)pengambilan . Nilai apa pun yang Anda berikan dalam URL permintaan setelah redirect-rule/ diambil oleh grup tangkapan tunggal ini.

Dalam string pengganti, grup yang diambil disuntikkan ke dalam string dengan tanda dolar ($) diikuti dengan nomor urut pengambilan. Nilai grup pengambilan pertama diperoleh dengan $1, yang kedua dengan $2, dan mereka melanjutkan secara berurutan untuk grup pengambilan di regex Anda. Hanya ada satu grup yang diambil dalam regex aturan pengalihan di aplikasi sampel, jadi hanya ada satu grup yang disuntikkan dalam string pengganti, yaitu $1. Saat aturan diterapkan, URL menjadi /redirected/1234/5678.

Pengalihan URL ke titik akhir yang aman

Gunakan AddRedirectToHttps untuk mengalihkan permintaan HTTP ke host dan jalur yang sama menggunakan protokol HTTPS. Jika kode status tidak disediakan, middleware default ke 302 - Ditemukan. Jika port tidak disediakan:

  • Middleware default ke null.
  • Skema berubah menjadi https (protokol HTTPS), dan klien mengakses sumber daya pada port 443.

Contoh berikut menunjukkan cara mengatur kode status ke 301 - Moved Permanently dan mengubah port menjadi 5001.

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

    app.UseRewriter(options);
}

Gunakan AddRedirectToHttpsPermanent untuk mengalihkan permintaan yang tidak aman ke host dan jalur yang sama dengan protokol HTTPS aman pada port 443. Middleware mengatur kode status ke 301 - Moved Permanently.

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

    app.UseRewriter(options);
}

Catatan

Saat mengalihkan ke titik akhir yang aman tanpa persyaratan untuk aturan pengalihan tambahan, sebaiknya gunakan Middleware Pengalihan HTTPS. Untuk informasi selengkapnya, lihat topik Terlaksanakan HTTPS .

Aplikasi sampel mampu menunjukkan cara menggunakan AddRedirectToHttps atau AddRedirectToHttpsPermanent. Tambahkan metode ekstensi ke RewriteOptions. Buat permintaan yang tidak aman ke aplikasi di URL apa pun. Mengabaikan peringatan keamanan browser bahwa sertifikat yang ditandatangani sendiri tidak tepercaya atau membuat pengecualian untuk mempercayai sertifikat.

Permintaan Asli menggunakan AddRedirectToHttps(301, 5001): http://localhost:5000/secure

Add redirect to HTTPS: Browser window with developer tools tracking the requests and responses

Permintaan Asli menggunakan AddRedirectToHttpsPermanent: http://localhost:5000/secure

Add redirect to HTTPS permanent: Browser window with developer tools tracking the requests and responses

Penulisan ulang URL

Gunakan AddRewrite untuk membuat aturan untuk menulis ulang URL. Parameter pertama berisi regex untuk pencocokan pada jalur URL masuk. Parameter kedua adalah string pengganti. Parameter ketiga, skipRemainingRules: {true|false}, menunjukkan kepada middleware apakah akan melewati aturan penulisan ulang tambahan atau tidak jika aturan saat ini diterapkan.

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

Permintaan Asli: /rewrite-rule/1234/5678

Add rewrite: Browser window with developer tools tracking the request and response

Karat (^) di awal ekspresi berarti bahwa pencocokan dimulai di awal jalur URL.

Dalam contoh sebelumnya dengan aturan pengalihan, redirect-rule/(.*), tidak ada karat (^) di awal regex. Oleh karena itu, setiap karakter dapat mendahului redirect-rule/ di jalur untuk kecocokan yang berhasil.

Jalur Cocokkan
/redirect-rule/1234/5678 Ya
/my-cool-redirect-rule/1234/5678 Ya
/anotherredirect-rule/1234/5678 Ya

Aturan penulisan ulang, ^rewrite-rule/(\d+)/(\d+), hanya cocok dengan jalur jika dimulai dengan rewrite-rule/. Dalam tabel berikut, perhatikan perbedaan dalam pencocokan.

Jalur Cocokkan
/rewrite-rule/1234/5678 Ya
/my-cool-rewrite-rule/1234/5678 No
/anotherrewrite-rule/1234/5678 Tidak

^rewrite-rule/ Setelah bagian ekspresi, ada dua grup pengambilan, (\d+)/(\d+). Menandakan \dcocok dengan digit (angka). Tanda plus (+) berarti cocok dengan satu atau beberapa karakter sebelumnya. Oleh karena itu, URL harus berisi angka yang diikuti dengan garis miring diikuti dengan angka lain. Grup penangkapan ini disuntikkan ke DALAM URL yang ditulis ulang sebagai $1 dan $2. String penggantian aturan penulisan ulang menempatkan grup yang diambil ke dalam string kueri. Jalur /rewrite-rule/1234/5678 yang diminta ditulis ulang untuk mendapatkan sumber daya di /rewritten?var1=1234&var2=5678. Jika string kueri ada pada permintaan asli, string tersebut dipertahankan saat URL ditulis ulang.

Tidak ada perjalanan pulang pergi ke server untuk mendapatkan sumber daya. Jika sumber daya ada, sumber daya diambil dan dikembalikan ke klien dengan kode status 200 - OK . Karena klien tidak dialihkan, URL di bilah alamat browser tidak berubah. Klien tidak dapat mendeteksi bahwa operasi penulisan ulang URL terjadi di server.

Catatan

Gunakan skipRemainingRules: true jika memungkinkan karena aturan yang cocok secara komputasi mahal dan meningkatkan waktu respons aplikasi. Untuk respons aplikasi tercepat:

  • Aturan penulisan ulang pesanan dari aturan yang paling sering cocok dengan aturan yang paling jarang dicocokkan.
  • Lewati pemrosesan aturan yang tersisa ketika kecocokan terjadi dan tidak diperlukan pemrosesan aturan tambahan.

Apache mod_rewrite

Terapkan aturan Apache mod_rewrite dengan AddApacheModRewrite. Pastikan file aturan disebarkan dengan aplikasi. Untuk informasi selengkapnya dan contoh aturan mod_rewrite, lihat Apache mod_rewrite.

StreamReader digunakan untuk membaca aturan dari file aturan 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}"));
}

Aplikasi sampel mengalihkan permintaan dari /apache-mod-rules-redirect/(.\*) ke /redirected?id=$1. Kode status respons adalah 302 - Ditemukan.

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

Permintaan Asli: /apache-mod-rules-redirect/1234

Add Apache mod redirect: Browser window with developer tools tracking the requests and responses

Middleware mendukung variabel server Apache mod_rewrite berikut:

  • 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

Aturan Modul Penulisan Ulang URL IIS

Untuk menggunakan seperangkat aturan yang sama yang berlaku untuk Modul Penulisan Ulang URL IIS, gunakan AddIISUrlRewrite. Pastikan file aturan disebarkan dengan aplikasi. Jangan arahkan middleware untuk menggunakan file web.config aplikasi saat berjalan di Windows Server IIS. Dengan IIS, aturan ini harus disimpan di luar file web.config aplikasi untuk menghindari konflik dengan modul Penulisan Ulang IIS. Untuk informasi selengkapnya dan contoh aturan Modul Penulisan Ulang URL IIS, lihat Menggunakan Modul Penulisan Ulang Url 2.0 dan Referensi Konfigurasi Modul Penulisan Ulang URL.

StreamReader digunakan untuk membaca aturan dari IISUrlRewrite.xml file aturan:

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

Aplikasi sampel menulis ulang permintaan dari /iis-rules-rewrite/(.*) ke /rewritten?id=$1. Respons dikirim ke klien dengan kode status 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>

Permintaan Asli: /iis-rules-rewrite/1234

Add IIS URL rewrite: Browser window with developer tools tracking the request and response

Jika Anda memiliki Modul Penulisan Ulang IIS aktif dengan aturan tingkat server yang dikonfigurasi yang akan memengaruhi aplikasi Anda dengan cara yang tidak diinginkan, Anda dapat menonaktifkan Modul Penulisan Ulang IIS untuk aplikasi. Untuk informasi selengkapnya, lihat Menonaktifkan modul IIS.

Fitur yang tidak didukung

Middleware yang dirilis dengan ASP.NET Core 2.x tidak mendukung fitur Modul Penulisan Ulang URL IIS berikut:

  • Aturan Keluar
  • Variabel Server Kustom
  • Wildcard
  • LogRewrittenUrl

Variabel server yang didukung

Middleware mendukung variabel server Modul Penulisan Ulang URL IIS berikut:

  • 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

Catatan

Anda juga dapat memperoleh IFileProvider melalui PhysicalFileProvider. Pendekatan ini dapat memberikan fleksibilitas yang lebih besar untuk lokasi file aturan penulisan ulang Anda. Pastikan file aturan penulisan ulang Anda disebarkan ke server di jalur yang Anda sediakan.

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

Aturan berbasis metode

Gunakan Add untuk menerapkan logika aturan Anda sendiri dalam metode . AddRewriteContextmengekspos , yang menyediakan HttpContext untuk digunakan dalam metode Anda. RewriteContext.Result menentukan bagaimana pemrosesan alur tambahan ditangani. Atur nilai ke salah satu bidang yang RuleResult dijelaskan dalam tabel berikut ini.

Menulis ulang hasil konteks Perbuatan
RuleResult.ContinueRules (default) Lanjutkan menerapkan aturan.
RuleResult.EndResponse Berhenti menerapkan aturan dan kirim respons.
RuleResult.SkipRemainingRules Berhenti menerapkan aturan dan kirim konteks ke middleware berikutnya.
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}"));
}

Aplikasi sampel menunjukkan metode yang mengalihkan permintaan untuk jalur yang diakhir dengan .xml. Jika permintaan dibuat untuk /file.xml, permintaan dialihkan ke /xmlfiles/file.xml. Kode status diatur ke 301 - Moved Permanently. Ketika browser membuat permintaan baru untuk /xmlfiles/file.xml, Middleware File Statis melayani file ke klien dari folder wwwroot/xmlfiles . Untuk pengalihan, atur kode status respons secara eksplisit. Jika tidak, kode status 200 - OK dikembalikan, dan pengalihan tidak terjadi pada klien.

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

Pendekatan ini juga dapat menulis ulang permintaan. Aplikasi sampel menunjukkan penulisan ulang jalur untuk setiap permintaan file teks untuk melayani file teks file.txt dari folder wwwroot . Middleware File Statis melayani file berdasarkan jalur permintaan yang diperbarui:

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

Aturan berbasis IRule

Gunakan Add untuk menggunakan logika aturan di kelas yang mengimplementasikan IRule antarmuka. IRule memberikan fleksibilitas yang lebih besar daripada menggunakan pendekatan aturan berbasis metode. Kelas implementasi Anda dapat mencakup konstruktor yang memungkinkan Anda dapat meneruskan parameter untuk metode tersebut 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}"));
}

Nilai parameter di aplikasi sampel untuk extension dan newPath diperiksa untuk memenuhi beberapa kondisi. extension harus berisi nilai, dan nilainya harus .png, , .jpgatau .gif. newPath Jika tidak valid, maka ArgumentException akan dilemparkan. Jika permintaan dibuat untuk image.png, permintaan dialihkan ke /png-images/image.png. Jika permintaan dibuat untuk image.jpg, permintaan dialihkan ke /jpg-images/image.jpg. Kode status diatur ke 301 - Moved Permanently, dan context.Result diatur untuk menghentikan aturan pemrosesan dan mengirim respons.

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

Permintaan Asli: /image.png

For image.png: Browser window with developer tools tracking the requests and responses

Permintaan Asli: /image.jpg

For image.jpg: Browser window with developer tools tracking the requests and responses

Contoh regex

Goal String Regex &
Contoh Kecocokan
String Penggantian &
Contoh Output
Menulis ulang jalur ke dalam querystring ^path/(.*)/(.*)
/path/abc/123
path?var1=$1&var2=$2
/path?var1=abc&var2=123
Garis miring berikutnya (.*)/$
/path/
$1
/path
Terapkan garis miring berikutnya (.*[^/])$
/path
$1/
/path/
Hindari menulis ulang permintaan tertentu ^(.*)(?<!\.axd)$ atau ^(?!.*\.axd$)(.*)$
Ya: /resource.htm
Tidak: /resource.axd
rewritten/$1
/rewritten/resource.htm
/resource.axd
Menyusun ulang segmen URL path/(.*)/(.*)/(.*)
path/1/2/3
path/$3/$2/$1
path/3/2/1
Mengganti segmen URL ^(.*)/segment2/(.*)
/segment1/segment2/segment3
$1/replaced/$2
/segment1/replaced/segment3

Sumber daya tambahan