Come funziona RewriteBase in .htaccess


227

L'ho visto in alcuni .htaccessesempi

RewriteBase /

Sembra essere in qualche modo simile nella funzionalità <base href="">dell'HTML.

Credo che possa anteporre automaticamente il suo valore all'inizio delle RewriteRuleistruzioni (possibilmente quelle senza una barra iniziale)?

Non sono riuscito a farlo funzionare correttamente. Penso che il suo utilizzo possa rivelarsi molto utile per la portabilità del sito, poiché spesso ho un server di sviluppo diverso da quello di produzione. Il mio metodo attuale mi lascia eliminare parti dalle mie RewriteRuledichiarazioni.

Qualcuno può spiegarmi brevemente come implementarlo?

Grazie



RewriteBase funziona solo nella directory o nel contesto .htaccess ... fare riferimento al contesto per il link @SalmanPK fornito.
Eddie B,

1
Vedi questa risposta per una buona descrizione. stackoverflow.com/a/2137593/292060
goodeye

1
Si tratta di una più approfondita risposta: stackoverflow.com/a/21348047/632951
Pacerier

Questa è una risposta 1-line: stackoverflow.com/a/46541685/632951
Pacerier

Risposte:


102

Con parole mie, dopo aver letto i documenti e sperimentato:

È possibile utilizzare RewriteBaseper fornire una base per le riscritture. Considera questo

# invoke rewrite engine
    RewriteEngine On
    RewriteBase /~new/

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

Questa è una vera regola che ho usato per garantire che gli URL abbiano una barra finale. Questo convertirà

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

per

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

Avendo il RewriteBaselì, fai in modo che il relativo percorso venga fuori dal RewriteBaseparametro.


10
"Vieni fuori dal parametro RewriteBase" - intendevi il parametro rewriteRule? :)
Kissaki

1
Voglio chiarire alcuni dettagli su htaccess. ReWriteBase lo imposta per tutte le regole in htaccess seguendo la sua dichiarazione? c'è un modo per disinserirlo, può essere resettato?
Damon,

3
@Kissaki: No, $1corrisponde al modello RewriteRule tra parentesi, ma il percorso relativo per la sostituzione viene fuori dal parametro RewriteBase. Quindi, la sostituzione risultante è /~new/$1/.
Mr White

3
@Damon: vedi questa domanda relativa a più RewriteBasedirettive. In breve, non puoi averne più di una - penso che l' ultima RewriteBase direttiva vince e influisca sull'intero file .htaccess.
Mr White

24
-1; questa risposta sembra aver aiutato gli altri, ma per me è totalmente opaca. Avrei potuto immaginare che "Si può utilizzare RewriteBaseper fornire una base per le vostre riscrive" - che è praticamente solo un riarrangiamento delle parole - ma non ho idea di cosa una "base" è in questo contesto, né come il significato del l'esempio che hai dato sarebbe diverso se la RewriteBaselinea fosse rimossa. Vado al manuale vado ...
Mark Amery il

89

RewriteBaseviene applicato solo al target di una regola di riscrittura relativa .

  • Utilizzando RewriteBase in questo modo ...

    RewriteBase /folder/
    RewriteRule a\.html b.html
    
  • è essenzialmente lo stesso di ...

    RewriteRule a\.html /folder/b.html
    
  • Ma quando il file .htaccess è dentro, /folder/anche questo punta allo stesso target:

    RewriteRule a\.html b.html
    

Sebbene i documenti implichino sempre l'utilizzo di a RewriteBase, Apache di solito lo rileva correttamente per i percorsi in DocumentRoot a meno che:

  • Stai usando le Aliasdirettive

  • Stai utilizzando le regole di riscrittura di .htaccess per eseguire reindirizzamenti HTTP (piuttosto che solo la riscrittura silenziosa) su URL relativi

In questi casi, potrebbe essere necessario specificare RewriteBase.

Tuttavia, poiché si tratta di una direttiva confusa, in genere è meglio semplicemente specificare URI assoluti (ovvero "relativi alla radice") nei target di riscrittura. Altri sviluppatori che leggono le tue regole li afferreranno più facilmente.



Citando qui l'eccellente risposta approfondita di Jon Lin :

In un file htaccess, mod_rewrite funziona in modo simile a a <Directory>o <Location>container. e il RewriteBaseè usato per fornire una base di percorso relativa.

Ad esempio, supponiamo di avere questa struttura di cartelle:

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

Quindi puoi accedere a:

  • http://example.com/ (radice)
  • http://example.com/subdir1 (Subdir1)
  • http://example.com/subdir2 (Subdir2)
  • http://example.com/subdir2/subsubdir (Subsubdir)

L'URI che viene inviato tramite a RewriteRuleè relativo alla directory contenente il file htaccess. Quindi se hai:

RewriteRule ^(.*)$ - 
  • Nel root htaccess, e la richiesta è /a/b/c/d, quindi l'URI acquisito ( $1) è a/b/c/d.
  • Se la regola è attiva subdir2e la richiesta è /subdir2/e/f/gquindi l'URI acquisito è e/f/g.
  • Se la regola è in subsubdire la richiesta lo è /subdir2/subsubdir/x/y/z, l'URI acquisito lo è x/y/z.

La directory in cui si trova la regola ha quella parte rimossa dall'URI. La base di riscrittura non ha alcun effetto su questo, questo è semplicemente come funziona per directory.

Che la base riscrittura fa fare, è fornire una base di URL-path ( non una base file-path) per tutti i percorsi relativi nella destinazione della regola . Quindi dire che hai questa regola:

RewriteRule ^foo$ bar.php [L]

La bar.phpè un percorso relativo, al contrario di:

RewriteRule ^foo$ /bar.php [L]

dove il /bar.phpè un percorso assoluto. Il percorso assoluto sarà sempre il "root" (nella struttura di directory sopra). Ciò significa che indipendentemente dal fatto che la regola sia in "root", "subdir1", "subsubdir", ecc., Il /bar.phppercorso viene sempre mappato http://example.com/bar.php.

Ma l'altra regola, con il relativo percorso, si basa sulla directory in cui si trova la regola. Quindi se

RewriteRule ^foo$ bar.php [L]

è nella "radice" e vai a http://example.com/foo, vieni servito http://example.com/bar.php. Ma se quella regola si trova nella directory "subdir1" e vai a http://example.com/subdir1/foo, vieni servito http://example.com/subdir1/bar.php. ecc. A volte questo funziona e talvolta no, come dice la documentazione, dovrebbe essere richiesto per percorsi relativi, ma il più delle volte sembra funzionare. Tranne quando stai reindirizzando (usando la Rbandiera, o implicitamente perché hai http://hostnel bersaglio della tua regola). Ciò significa che questa regola:

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

se è nella directory "subdir2", e si va a http://example.com/subdir2/foo, mod_rewrite sarà confondere il percorso relativo come file-percorso invece di un URL-path e per la Rbandiera, si finirà per ottenere reindirizzato a qualcosa come: http://example.com/var/www/localhost/htdocs/subdir1. Che ovviamente non è quello che vuoi.

È qui che RewriteBaseentra in gioco. La direttiva dice a mod_rewrite cosa aggiungere all'inizio di ogni percorso relativo. Quindi se ho:

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

in "subsubdir", http://example.com/subdir2/subsubdir/fooeffettivamente mi servirà http://example.com/blah/bar.php. Il "bar.php" viene aggiunto alla fine della base. In pratica, questo esempio di solito non è quello che vuoi, perché non puoi avere più basi nello stesso contenitore di directory o file htaccess.

Nella maggior parte dei casi, viene utilizzato in questo modo:

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

dove quelle regole sarebbero nella directory "subdir1" e

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

sarebbe nella directory "subsubdir".

Questo in parte ti consente di rendere portatili le tue regole, in modo da poterle rilasciare in qualsiasi directory e devi solo cambiare la base invece di un mucchio di regole. Ad esempio se avessi:

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

tale che http://example.com/subdir1/fooservirà http://example.com/subdir1/bar.phpecc. E dire che hai deciso di spostare tutti quei file e regole nella directory "subsubdir". Invece di cambiare ogni istanza di /subdir1/a/subdir2/subsubdir/ , avresti potuto avere una base:

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

E poi quando hai bisogno di spostare quei file e le regole in un'altra directory, basta cambiare la base:

RewriteBase /subdir2/subsubdir/

e basta.


Per me, mi sono perso RewriteEngine On. Non è necessario ad esempio 1and1, ma è necessario sul mio server dedicato.
Portekoi,

41

AFAIK, RewriteBase viene utilizzato solo per correggere i casi in cui mod_rewrite è in esecuzione in un .htaccessfile non alla radice di un sito e indovina il percorso Web errato (al contrario del percorso del file system) per la cartella in cui è in esecuzione. Quindi se si dispone di un RewriteRule in un .htaccess in una cartella mappata su di http://example.com/myfolderte puoi usare:

RewriteBase myfolder

Se mod_rewrite non funziona correttamente.

Cercare di usarlo per ottenere qualcosa di insolito, piuttosto che risolvere questo problema, sembra una ricetta molto confusa.


2
Deve finire con una barra finale?
Pacerier,

@self, n Provato, e sub-spiegato qui: stackoverflow.com/a/11443194/632951
Pacerier

23

RewriteBase è utile solo in situazioni in cui puoi solo inserire un .htaccess nella radice del tuo sito. Altrimenti, è meglio collocare i diversi file .htaccess in diverse directory del sito e omettere completamente la direttiva RewriteBase.

Ultimamente, per siti complessi, li ho eliminati perché rende complicata la distribuzione di file dai test per rendere ancora più semplice un passaggio.


22
Sebbene questo possa essere un buon consiglio, questa non è affatto una risposta alla domanda. Dovrebbe quindi essere stato un commento alla domanda, non aver ricevuto (altrettanti) voti e sicuramente non accettato come "risposta".
Kissaki

3
"meglio posizionare i tuoi diversi file .htaccess in directory diverse" - Non sono sicuro che questo sia un buon consiglio? La presenza di file .htaccess sparsi in tutto il sito può rendere il debug / la manutenzione un incubo. Avrei detto che era preferibile avere un file .htaccess nella radice del tuo sito.
MrWhite,

1
@ w3d C'è anche una questione di tempistica: ogni volta che si accede a una sottodirectory, vengono analizzati più file .htaccess (dalla radice alla sottodirectory corrente). Avere molti file potrebbe ridurre la velocità della risposta globale alla richiesta, al contrario di un singolo file nella radice, anche se contiene molte regole ..
Erenor Paz

19

Quando sviluppo, è su un dominio diverso all'interno di una cartella. Quando prendo un sito dal vivo, quella cartella non esiste più. L'uso di RewriteBase mi consente di utilizzare lo stesso file .htaccess in entrambi gli ambienti.

Quando dal vivo:

RewriteBase /
# RewriteBase /dev_folder/

Durante lo sviluppo:

# RewriteBase /
RewriteBase /dev_folder/

4
Sono sicuro che non funzionerà sempre. Che cosa succede se ad esempio %{REQUEST_URI}in una RewriteConddirettiva?
MrWhite,

1
@ user1669830, Se hai un solo RewriteRule, si potrebbe aver appena aggiunto la base al RewriteRule stackoverflow.com/a/46541685/632951
Pacerier

18

La spiegazione più chiara che ho trovato non era negli attuali documenti apache 2.4, ma nella versione 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

Come funziona? Per voi hacker apache, questo documento 2.0 continua fornendo "informazioni dettagliate sulle fasi di elaborazione interne".

Lezione imparata: anche se dobbiamo conoscere le "attuali", le gemme si possono trovare negli annali.


3

Questo comando può impostare esplicitamente l'URL di base per le riscritture. Se desideri iniziare nella radice del tuo dominio, includi la seguente riga prima di RewriteRule:

RewriteBase /

2

Credo che questo estratto della documentazione di Apache integri bene le risposte precedenti:

Questa direttiva è richiesta quando si utilizza un percorso relativo in una sostituzione in un contesto per directory (htaccess) a meno che non sia vera una delle seguenti condizioni:

  • La richiesta originale e la sostituzione sono sotto DocumentRoot (al contrario di raggiungibili con altri mezzi, come Alias).

  • Il percorso del filesystem nella directory contenente RewriteRule, suffisso dalla relativa sostituzione è valido anche come percorso URL sul server (questo è raro).

Come accennato in precedenza, in altri contesti, è utile solo ridurre la regola. Inoltre, come già accennato in precedenza, è possibile ottenere lo stesso risultato posizionando il file htaccess nella sottodirectory.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.