Bagaimana cara kerja RewriteBase di .htaccess

227

Saya telah melihat ini dalam beberapa .htaccesscontoh

RewriteBase /

Tampaknya fungsionalitasnya agak mirip dengan <base href="">HTML.

Saya percaya mungkin secara otomatis menambahkan nilainya ke awal RewriteRulepernyataan (mungkin yang tanpa garis miring)?

Saya tidak bisa membuatnya berfungsi dengan baik. Saya pikir itu digunakan bisa sangat berguna untuk portabilitas situs, karena saya sering memiliki server pengembangan yang berbeda dengan yang produksi. Metode saya saat ini membuat saya menghapus bagian dari RewriteRulepernyataan saya .

Adakah yang bisa menjelaskan kepada saya secara singkat bagaimana menerapkannya?

Terima kasih

alex
sumber
RewriteBase hanya berfungsi di direktori atau konteks .htaccess ... lihat konteks untuk tautan yang diberikan oleh @SalmanPK.
Eddie B
1
Lihat jawaban ini untuk deskripsi yang bagus. stackoverflow.com/a/2137593/292060
selamat tinggal
1
Ini adalah jawaban yang lebih mendalam: stackoverflow.com/a/21348047/632951
Pacerier
Ini adalah jawaban 1-baris: stackoverflow.com/a/46541685/632951
Pacerier

Jawaban:

102

Dengan kata-kata saya sendiri, setelah membaca dokumen dan bereksperimen:

Anda dapat menggunakan RewriteBaseuntuk menyediakan basis untuk penulisan ulang Anda. Pertimbangkan ini

# invoke rewrite engine
    RewriteEngine On
    RewriteBase /~new/

# add trailing slash if missing
    rewriteRule ^(([a-z0-9\-]+/)*[a-z0-9\-]+)$ $1/ [NC,R=301,L]

Ini adalah aturan nyata yang saya gunakan untuk memastikan bahwa URL memiliki garis miring. Ini akan dikonversi

http://www.example.com/~new/page

untuk

http://www.example.com/~new/page/

Dengan memiliki di RewriteBasesana, Anda membuat jalur relatif keluar dari RewriteBaseparameter.

alex
sumber
10
“Lepas parameter RewriteBase” - maksud Anda parameter rewriteRule? :)
Kissaki
1
Saya ingin menjernihkan beberapa perincian tentang htaccess .. apakah ReWriteBase menyetelnya untuk semua aturan di htaccess mengikuti deklarasi apa? apakah ada cara untuk menghapusnya, dapatkah diatur ulang?
Damon
3
@Kissaki: Tidak, $1cocok dengan pola RewriteRule yang ditulis dalam kurung, tetapi jalur relatif untuk substitusi berasal dari parameter RewriteBase. Jadi, substitusi yang dihasilkan adalah /~new/$1/.
MrWhite
3
@Damon: Lihat pertanyaan ini mengenai banyak RewriteBasearahan. Singkatnya, Anda tidak dapat memiliki lebih dari satu - saya pikir arahan terakhir yang RewriteBase menang, dan memengaruhi keseluruhan file .htaccess.
MrWhite
24
-1; jawaban ini tampaknya telah membantu orang lain, tetapi sama sekali tidak jelas bagi saya. Aku bisa menduga bahwa "Anda dapat menggunakan RewriteBaseuntuk menyediakan dasar untuk penulisan ulang Anda" - itu cukup banyak hanya penyusunan kembali kata-kata - tapi saya tidak tahu apa "dasar" adalah dalam konteks ini, atau bagaimana arti dari contoh yang Anda berikan akan berbeda jika RewriteBasegaris dihapus. Pergi ke manual saya pergi ...
Mark Amery
89

RewriteBasehanya diterapkan pada sasaran dari kerabat aturan penulisan ulang.

  • Menggunakan RewriteBase seperti ini ...

    RewriteBase /folder/
    RewriteRule a\.html b.html
    
  • pada dasarnya sama dengan ...

    RewriteRule a\.html /folder/b.html
    
  • Tetapi ketika file .htaccess ada di dalam /folder/maka ini juga menunjuk ke target yang sama:

    RewriteRule a\.html b.html
    

Meskipun dokumen selalu menunjukkan penggunaan RewriteBase, Apache biasanya mendeteksi dengan benar untuk jalur di bawah DocumentRoot kecuali:

  • Anda menggunakan Aliasarahan

  • Anda menggunakan aturan penulisan ulang .htaccess untuk melakukan pengalihan HTTP (bukan hanya penulisan ulang diam) ke URL relatif

Dalam kasus ini, Anda mungkin menemukan bahwa Anda perlu menentukan RewriteBase.

Namun, karena ini adalah arahan yang membingungkan, biasanya lebih baik untuk menentukan URI absolut (alias 'relatif') dalam target penulisan ulang Anda. Pengembang lain yang membaca aturan Anda akan memahami ini dengan lebih mudah.



Mengutip dari jawaban mendalam yang sangat baik dari Jon Lin di sini :

Dalam file htaccess, mod_rewrite bekerja mirip dengan <Directory>atau <Location>wadah. dan RewriteBasedigunakan untuk menyediakan basis path relatif.

Misalnya, Anda memiliki struktur folder ini:

DocumentRoot
|-- subdir1
`-- subdir2
    `-- subsubdir

Jadi Anda dapat mengakses:

  • http://example.com/ (akar)
  • http://example.com/subdir1 (subdir1)
  • http://example.com/subdir2 (subdir2)
  • http://example.com/subdir2/subsubdir (subsubdir)

URI yang dikirimkan melalui a RewriteRuleadalah relatif ke direktori yang berisi file htaccess. Jadi, jika Anda memiliki:

RewriteRule ^(.*)$ - 
  • Di root htaccess, dan permintaannya adalah /a/b/c/d, maka URI yang ditangkap ( $1) adalah a/b/c/d.
  • Jika aturannya ada subdir2dan permintaannya /subdir2/e/f/gmaka URI yang ditangkap adalah e/f/g.
  • Jika aturannya ada di subsubdir, dan permintaannya adalah /subdir2/subsubdir/x/y/z, maka URI yang ditangkap adalah x/y/z.

Direktori tempat aturan berada memiliki bagian yang dilepaskan dari URI. Basis penulisan ulang tidak memengaruhi hal ini, ini hanyalah cara kerja per-direktori.

Apa dasar menulis ulang tidak lakukan, adalah memberikan dasar URL-jalan ( bukan basis berkas-jalan) untuk setiap path relatif dalam sasaran aturan ini . Jadi katakan Anda memiliki aturan ini:

RewriteRule ^foo$ bar.php [L]

Ini bar.phpadalah jalur relatif, berlawanan dengan:

RewriteRule ^foo$ /bar.php [L]

di mana itu /bar.phpadalah jalur absolut. Path absolut akan selalu menjadi "root" (dalam struktur direktori di atas). Itu berarti bahwa terlepas dari apakah aturannya ada di "root", "subdir1", "subsubdir", dll. /bar.phpPath selalu dipetakan ke http://example.com/bar.php.

Tetapi aturan lainnya, dengan jalur relatif, ini didasarkan pada direktori tempat aturan itu berada. Jadi jika

RewriteRule ^foo$ bar.php [L]

ada di "root" dan Anda pergi ke http://example.com/foo, Anda dilayani http://example.com/bar.php. Tetapi jika aturan itu ada di direktori "subdir1", dan Anda pergi ke http://example.com/subdir1/foo, Anda dilayani http://example.com/subdir1/bar.php. dll. Ini kadang-kadang berfungsi dan kadang tidak, seperti yang dikatakan dalam dokumentasi, itu diperlukan untuk jalur relatif, tetapi sebagian besar waktu tampaknya berfungsi. Kecuali ketika Anda mengarahkan ulang (menggunakan Rbendera, atau secara implisit karena Anda miliki http://hostdalam target aturan Anda). Itu berarti aturan ini:

RewriteRule ^foo$ bar.php [L,R]

jika itu dalam "subdir2" direktori, dan Anda pergi ke http://example.com/subdir2/foo, mod_rewrite akan kesalahan path relatif sebagai file-jalan bukannya URL-jalan dan karena Rbendera, Anda akan berakhir mendapatkan diarahkan ke sesuatu seperti: http://example.com/var/www/localhost/htdocs/subdir1. Yang jelas bukan yang Anda inginkan.

Di sinilah RewriteBasemasuk. Arahan memberitahu mod_rewrite apa yang harus ditambahkan ke awal setiap jalur relatif. Jadi jika saya punya:

RewriteBase /blah/
RewriteRule ^foo$ bar.php [L]

di "subsubdir", http://example.com/subdir2/subsubdir/fooakan benar-benar melayani saya http://example.com/blah/bar.php. "Bar.php" ditambahkan ke ujung pangkalan. Dalam praktiknya, contoh ini biasanya bukan yang Anda inginkan, karena Anda tidak dapat memiliki banyak pangkalan di wadah direktori atau file htaccess yang sama.

Dalam kebanyakan kasus, digunakan seperti ini:

RewriteBase /subdir1/
RewriteRule ^foo$ bar.php [L]

di mana aturan itu berada di direktori "subdir1" dan

RewriteBase /subdir2/subsubdir/
RewriteRule ^foo$ bar.php [L]

akan berada di direktori "subsubdir".

Ini sebagian memungkinkan Anda untuk membuat aturan Anda portabel, sehingga Anda dapat menjatuhkannya di direktori mana pun dan hanya perlu mengubah basis alih-alih sekelompok aturan. Misalnya jika Anda memiliki:

RewriteEngine On
RewriteRule ^foo$ /subdir1/bar.php [L]
RewriteRule ^blah1$ /subdir1/blah.php?id=1 [L]
RewriteRule ^blah2$ /subdir1/blah2.php [L]
...

sehingga http://example.com/subdir1/fooakan melayani http://example.com/subdir1/bar.phpdll. Dan katakanlah Anda memutuskan untuk memindahkan semua file dan aturan itu ke direktori "subsubdir". Alih-alih mengubah setiap instance /subdir1/menjadi /subdir2/subsubdir/, Anda bisa saja memiliki basis:

RewriteEngine On
RewriteBase /subdir1/
RewriteRule ^foo$ bar.php [L]
RewriteRule ^blah1$ blah.php?id=1 [L]
RewriteRule ^blah2$ blah2.php [L]
...

Dan kemudian ketika Anda perlu memindahkan file-file itu dan aturan-aturannya ke direktori lain, ubah saja basisnya:

RewriteBase /subdir2/subsubdir/

dan hanya itu.

Simon Timur
sumber
Bagi saya, saya ketinggalan RewriteEngine On. Tidak perlu pada 1and1 misalnya tetapi diperlukan di server khusus saya.
Portekoi
41

AFAIK, RewriteBase hanya digunakan untuk memperbaiki kasus-kasus di mana mod_rewrite berjalan dalam .htaccessfile yang bukan di root situs dan ia menebak jalur web yang salah (sebagai lawan jalur sistem file) untuk folder yang digunakan. Jadi jika Anda memiliki RewriteRule dalam .htaccess di folder yang dapat http://example.com/myfolderAnda gunakan:

RewriteBase myfolder

Jika mod_rewrite tidak berfungsi dengan benar.

Mencoba menggunakannya untuk mencapai sesuatu yang tidak biasa, daripada memperbaiki masalah ini kedengarannya seperti resep untuk menjadi sangat bingung.

rjmunro
sumber
2
Apakah harus diakhiri dengan garis miring?
Pacerier
@self, No. Tested, dan sub-dijelaskan di sini: stackoverflow.com/a/11443194/632951
Pacerier
23

RewriteBase hanya berguna dalam situasi di mana Anda hanya dapat meletakkan .htaccess di root situs Anda. Jika tidak, Anda mungkin lebih baik menempatkan file .htaccess Anda yang berbeda di berbagai direktori situs Anda dan sepenuhnya menghilangkan arahan RewriteBase.

Akhir-akhir ini, untuk situs yang kompleks, saya telah mengeluarkannya, karena itu membuat penerapan file dari pengujian untuk hidup hanya satu langkah lebih rumit.

Thomas Hunter II
sumber
22
Meskipun ini mungkin saran yang bagus, ini sama sekali bukan jawaban untuk pertanyaan itu. Dengan demikian seharusnya komentar untuk pertanyaan, tidak menerima (sebanyak) upvotes dan jelas tidak diterima sebagai "jawaban".
Kissaki
3
"lebih baik menempatkan file .htaccess Anda yang berbeda di direktori yang berbeda" - Saya tidak yakin ini saran yang bagus? Memiliki file .htaccess yang tersebar di seluruh situs Anda dapat menjadikan debugging / pemeliharaan menjadi mimpi buruk. Saya akan mengatakan itu lebih baik untuk memiliki satu file .htaccess di root situs Anda.
MrWhite
1
@ w3d Ada juga masalah waktu: setiap kali subdirektori diakses, banyak file .htaccess diurai (dari root ke subdirektori saat ini). Memiliki banyak file dapat menurunkan kecepatan jawaban keseluruhan untuk permintaan tersebut, dibandingkan dengan satu file di root, bahkan jika itu berisi banyak aturan ..
Erenor Paz
19

Ketika saya mengembangkan, itu pada domain yang berbeda di dalam folder. Ketika saya mengambil situs secara langsung, folder itu tidak ada lagi. Menggunakan RewriteBase memungkinkan saya menggunakan file .htaccess yang sama di kedua lingkungan.

Ketika hidup:

RewriteBase /
# RewriteBase /dev_folder/

Ketika berkembang:

# RewriteBase /
RewriteBase /dev_folder/
pengguna1669830
sumber
4
Saya yakin ini tidak akan selalu berhasil. Bagaimana jika Anda digunakan %{REQUEST_URI}dalam RewriteConddirektif misalnya?
MrWhite
1
@ user1669830, Jika Anda hanya memiliki satu rewriterule, Anda bisa saja menambahkan pangkalan ke stackoverflow.com/riter
a46541685
18

Penjelasan paling jelas yang saya temukan tidak ada di dokumen apache 2.4 saat ini, tetapi dalam versi 2.0 .

#  /abc/def/.htaccess -- per-dir config file for directory /abc/def
#  Remember: /abc/def is the physical path of /xyz, i.e., the server
#            has a 'Alias /xyz /abc/def' directive e.g.

RewriteEngine On

#  let the server know that we were reached via /xyz and not
#  via the physical path prefix /abc/def
RewriteBase   /xyz

Bagaimana cara kerjanya? Bagi Anda apache hacker, 2.0 doc ini berlanjut untuk memberikan "informasi terperinci tentang langkah-langkah pemrosesan internal."

Hal yang dipelajari: Meskipun kita harus terbiasa dengan "saat ini," permata dapat ditemukan dalam sejarah.

DWB
sumber
3

Perintah ini dapat secara eksplisit mengatur URL dasar untuk penulisan ulang Anda. Jika Anda ingin memulai di root domain Anda, Anda akan menyertakan baris berikut sebelum RewriteRule Anda:

RewriteBase /
Sandeep Goyal
sumber
2

Saya percaya kutipan ini dari dokumentasi Apache, melengkapi dengan baik jawaban sebelumnya:

Arahan ini diperlukan ketika Anda menggunakan jalur relatif dalam substitusi dalam konteks per-direktori (htaccess) kecuali salah satu dari kondisi berikut ini benar:

  • Permintaan asli, dan substitusi, berada di bawah DocumentRoot (sebagai lawan dapat dijangkau dengan cara lain, seperti Alias).

  • Jalur sistem file ke direktori yang berisi RewriteRule, yang diakhiri dengan substitusi relatif juga valid sebagai jalur URL di server (ini jarang terjadi).

Seperti yang disebutkan sebelumnya, dalam konteks lain, hanya berguna untuk membuat aturan Anda lebih pendek. Selain itu, juga seperti yang disebutkan sebelumnya, Anda dapat mencapai hal yang sama dengan menempatkan file htaccess di subdirektori.

alex
sumber