> Aparte: As diretivas que você postou criariam um loop de reescrita em qualquer instalação padrão do Apache, então talvez você tenha outras diretivas ou uma configuração diferente que você não esteja revelando na sua pergunta? De qualquer forma, ignorando isso por enquanto, já que você não parece estar tendo um problema como esse.
I don't know how to get the wrong URI used before redirecting to
example.com/e404
...
Mas você precisa obter essas informações antes "redirecionando"? No PHP você pode simplesmente verificar o $_SERVER['REQUEST_URI']
superglobal para obter esta informação (o URL que resultou no 404). No entanto, observe que isso contém o prefixo da barra e a string de consulta (se houver), que o parâmetro page
URL não conteria de outra forma.
Além disso, apenas para esclarecer a terminologia, isso não é estritamente um "redirecionamento" para example.com/e404
. Um "redirecionamento" implica um redirecionamento HTTP externo. O Apache emite uma
Um dos possíveis problemas com o seu código é que a resposta 404 é veiculada de uma forma bastante aproximada:
- Se
file.css
não existir, o Apache acionará uma subrequição interna para/e404
(isso desencadeia outra rodada de processamento ...) - Como
/e404
não termina em uma das extensões de arquivo declaradas, ela é novamente reescrita em?page=e404
(presumivelmenteindex.php
?).
Devido à (desnecessária) segunda reescrita, outras variáveis de servidor, como REDIRECT_URL
e REDIRECT_QUERY_STRING
(que também são passadas para o PHP $_SERVER
superglobal) não são definidas como esperado. Normalmente, eles seriam definidos como "URI errado" (ou seja, a URL solicitada que acionou o 404), mas, em vez disso, contêm detalhes do próprio documento de erro.
Você deve fazer o acima em uma etapa e evitar a segunda reescrita. Por exemplo (assumindo que index.php
é o arquivo que manipula o pedido), o documento de erro deve ser definido para o resultado final desejado:
ErrorDocument 404 /index.php?page=e404
Incidentalmente, você não precisa necessariamente passar explicitamente o "status de erro" HTTP (ou seja, e404
) na URL, pois isso está disponível em $_SERVER['REDIRECT_STATUS']
superglobal do PHP.
RewriteRule ^(.*)$ ?page=$1 [NC,L,QSA]
Eu assumi que você está reescrevendo para index.php
(o DirectoryIndex registrado)? Em vez de voltar atrás para deixar o mod_dir emitir uma sub-requisição adicional para o DirectoryIndex, você deve ser explícito e incluir o arquivo para o qual você está reescrevendo na substituição . Por exemplo:
RewriteRule ^(.*)$ index.php?page=$1 [QSA,L]
(A NC
bandeira é supérflua aqui.)
I don't know how to get the wrong URI used before redirecting to
example.com/e404
...
Recuando para abordar sua consulta inicial novamente (como um exercício acadêmico ). Você pode fazer isso no Apache 2.4.13+ (embora eu não ache que você precise ). No Apache 2.4.13+ você pode criar um ErrorDocument dinâmico usando expressões do Apache.
Por exemplo, para passar explicitamente o URL-path que causou o erro 404 na URL do próprio documento de erro, você pode fazer algo como o seguinte:
ErrorDocument 404 /index.php?page=%{escape:%{REQUEST_URI}}&error=404
O parâmetro de URL page
, em seguida, contém o caminho da URL (que inclui o prefixo da barra, ao contrário da sua reescrita que o exclui). Um parâmetro adicional de error
URL envia o status HTTP (embora, como mencionado acima, isso não seja estritamente necessário).