Preciso de ajuda para criar um redirecionamento, estou tentando substituir tudo -
para +
, mas ambos são caracteres especiais e também quero fazer isso apenas quando a URL contiver ?s=
.
Isto é um exemplo
example.com/?s=i-need-to-rewrite-this-url
example.com/?s=i+need+to+rewrite+this+url
Isso é o que eu tenho, já tentei usar ()
ou ""
não deu certo
RewriteEngine on
RewriteRule ^?s=(.*)\-(.*)$ ?s=$1\+$2 [L,R=301]
Agradeço qualquer ajuda. Obrigado.
Não há nada particularmente "especial" sobre esses personagens. Pelo menos, não no contexto em que serão usados. O
-
(hífen) é um especificador de intervalo quando usado dentro de uma classe de caractere regex, caso contrário, é apenas um hífen e é seguro usar não codificado na parte da string de consulta da URL (não precisamos usá -lo em uma classe de caractere regex). O+
(mais) é um quantificador regex, mas não precisamos usá-lo em um regex, apenas na string de substituição (2º argumento para aRewriteRule
diretiva, que não é um regex). O é um espaço+
codificadoquando usado na parte da string de consulta do URL - que eu acho que você conhece e é por isso que você precisa redirecionar a solicitação (embora, como isso faz parte de um valor de parâmetro de URL, também é curioso porque isso não pode ser resolvido em a aplicação).Uma coisa a ser observada, no entanto, é que, como
+
é um espaço codificado em URL , precisamos usar o sinalizadorNE
(noescape
) naRewriteRule
diretiva para evitar que mod_rewrite da URL codifique o+
as%2B
(um literal+
) na resposta de redirecionamento. (O mesmo vale para quaisquer outros caracteres codificados em % que possamos capturar doQUERY_STRING
- esta variável de servidor não é decodificada em %.)O
RewriteRule
padrão (primeiro argumento) corresponde apenas ao caminho da URL, não à string de consulta. Portanto, umaRewriteRule
diretiva sozinha nunca corresponderá à string de consulta. A propósito,?
é um caractere regex especial (0 ou 1 quantificador do token anterior) e^
(o token anterior) não é quantificável, portanto, ficaria surpreso se isso fosse compilado (resultando em um erro interno do servidor 500). Um literal?
em um regex precisa ter uma barra invertida de escape.Como mencionado acima, o
NE
sinalizador seria necessário aqui. E o+
não precisa ser escapado com barra invertida na string de substituição , pois não possui nenhum significado especial aqui (não é um regex). Além disso, devido à string de substituição relativa (ou seja,?s=$1\+$2
), a menos que você tenhaRewriteBase
definido, isso resultaria em um redirecionamento malformado.Para corresponder à string de consulta, você precisa de uma condição adicional (
RewriteCond
diretiva) e corresponder àQUERY_STRING
variável do servidor. Então, como primeira tentativa, você poderia fazer algo assim:Observe que as referências anteriores
%1
e%2
(em oposição a$1
, etc.) contêm os valores capturados da diretiva CondPattern (RewriteCond
diretiva) anterior, em vez doRewriteRule
padrão (que, nesse caso, corresponde apenas à string vazia).(NB: você deve sempre testar primeiro com redirecionamentos 302 - temporários - para evitar possíveis problemas de cache e certifique-se de que todos os caches intermediários sejam limpos antes do teste.)
Estou assumindo
s
que é o único parâmetro de URL. Com a regra acima, quaisquer outros parâmetros de URL a seguir serão descartados.NO ENTANTO , o acima é muito ineficiente, pois aciona um redirecionamento externo para cada instância de
-
. Portanto, seu exemplo de/?s=i-need-to-rewrite-this-url
acionaria 5 redirecionamentos.Solução
Em vez do acima, você deve substituir recursivamente todos menos um
-
internamente e apenas acionar o redirecionamento externo (e substituir o último-
) depois que todos-
forem substituídos. Para isso, precisamos de uma reescrita adicional para realizar as substituições internas. Por exemplo:A primeira condição que verifica o regex
^s=([^&]*-[^&]*){2}
simplesmente determina que há pelo menos 2 hífens no valor dos
parâmetro de URL. (Caso contrário, a regra é ignorada e vai direto para a segunda regra/redirecionamento.) A segunda condição captura as partes relevantes da string de consulta em torno do último-
, que são usadas no seguinteRewriteRule
.O
N
sinalizador faz com que o mecanismo de reescrita seja reiniciado imediatamente. O20
define um limite para o número de iterações (Apache 2.4+) - portanto, estou assumindo não mais que 20+1 hífens (o último hífen é substituído na segunda regra/redirecionamento).Como sabemos que haverá no máximo 1 hífen restante no parâmetro de URL quando a segunda regra for processada, adicionei o hífen à classe de caractere regex como uma otimização , para evitar retrocessos desnecessários.
Futuro
Há uma
replace
função vindo para Apache expressions , que (como o nome sugere) permite que você pesquise/substitua caracteres em uma string, mas não acho que isso tenha sido lançado ainda nas últimas compilações públicas. Mas isso potencialmente permitiria que você fizesse algo como o seguinte em uma única regra: