Tente algo como o seguinte, em vez no arquivo raiz .htaccess
:
RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(site1|site2|site3)/?(.*) /$1/public/$2 [L]
Isso segmenta qualquer URL que inicie /site1
, /site2
ou /site3
(observe que em .htaccess
o padrão exclui o prefixo de barra). Em seguida, reescreve internamente a solicitação de /site1/<whatever>
para /site1/public/<whatever>
usando as referências anteriores $1
e $2
. A barra opcional no padrão RewriteRule
garante que ela também corresponderá a uma solicitação para o subdiretório bare, excluindo a barra final, por exemplo. /site1
, em vez de permitir que mod_dir emita primeiro um redirecionamento para /site1/
.
Para reescrever qualquer diretório raiz (não apenas limitando a site1
, site2
, etc.), altere a diretiva RewriteRule
para ler:
RewriteRule ^([^/]+)/?(.*) /$1/public/$2 [L]
A regex [^/]+
corresponde apenas ao primeiro segmento do caminho, ou seja, tudo excluindo a primeira barra.
A diretiva RewriteCond
que verifica a variável de ambiente REDIRECT_STATUS
garante que não obtenhamos um loop de regravação. REDIRECT_STATUS
não é definido quando o script é chamado pela primeira vez, mas definido para o status HTTP na primeira reescrita (ou estado de erro).
#RewriteRule /(.?)/ /$1/public/ [L]
Alguns problemas com sua diretiva original ...
-
.?
captura apenas um único caractere - o que você tornou opcional. -
/(.?)/
seria correspondido em qualquer lugar no URL solicitado (não no início). Mas note que você não pode igualar a primeira barra no início do caminho da URL em um contexto de diretório.htaccess
/ (como mencionado acima). - Você não está capturando o restante do caminho da URL, portanto, isso só seria reescrito na raiz do documento, independentemente de qual URL foi solicitado.
- Isso acionaria um loop de reescrita. (Resultando em um erro interno do servidor 500.)