como reescrever '% 25' no url

4

O software do meu website substitui caracteres de espaço por "+" no URL. Um link adequado seria semelhante a " link 'por exemplo.

Alguns sites têm links para esse artigo, mas, de alguma forma, o editor incorporado não pode lidar com a codificação, então o que eu vejo nos arquivos de log do httpd é realmente

GET /display/INFO/How%2525252bto%2525252breattach%2525252ba%2525252bdisk%2525252bto%2525252bXenServer

que, claro, leva a um erro 404. Parece que o caractere '+' é codificado como '% 2b' e, em seguida, o caractere '%' é codificado como '% 25' - várias vezes.

Como existem muitas referências a diferentes páginas de sites diferentes, gostaria de reescrever o URL para que os visitantes recebam a página correta.

Aqui está minha tentativa que não funciona:

RewriteRule ^(.*)%25(.*)$ $1%$2 [R=301]

O que é suposto fazer é: levar tudo antes da string% 25 e depois de tudo, concatencie essas strings com um '%' entre elas e, em seguida, redirecione.

Com o exemplo de URL de entrada, a regra deve ser reescrita para

/display/INFO/How%25252bto%2525252breattach%2525252ba%2525252bdisk%2525252bto%2525252bXenServer

seguido por um redirecionamento, então ele deve ser reescrito para

/display/INFO/How%252bto%2525252breattach%2525252ba%2525252bdisk%2525252bto%2525252bXenServer

e novamente para

/display/INFO/How%2bto%2525252breattach%2525252ba%2525252bdisk%2525252bto%2525252bXenServer

e assim por diante. Finalmente, depois de muitos redirecionamentos eu deveria ter saído

/display/INFO/How%2bto%2breattach%2ba%2bdisk%2bto%2bXenServer

que é um URL válido equivalente a / display / INFO / How + to + recolocar + a + disk + em + XenServer.

Meu problema é que a expressão não corresponde a todos, por isso nem mesmo substitui uma única ocorrência de% 25.

Eu entendo que há um limite no número de redirecionamentos e realmente devo usar o sinalizador [N], no entanto, nem sequer consigo o primeiro passo correto.

@Ben Lee: obrigado pela sua resposta detalhada. Agora passei várias horas nesse problema. Aqui está o que eu descobri:

  1. Qualquer string '% 25' na URL é convertida em '%' antes de mod_rewrite Vê isso. Portanto, o RewriteRule ^ (. )% 25 (. ) $ não corresponde a '% 25' em o URL, na verdade corresponde a '% 2525'.

  2. A presença de uma barra invertida não faz diferença. Parece que o sinal '%' não é interpretado como uma referência anterior no meu caso, talvez porque não há nenhuma instrução RewriteCond antes. Mas é provavelmente melhor usá-lo, só para ter certeza.

  3. A linha que tem [L, R = 301] está incorreta. Ele tentará redirecionar para cada correspondência de% 2b, mas há um limite de redirecionamentos permitidos e falhará se houver mais.

Aqui estão as linhas do mod_rewrite que estou usando:

RewriteRule ^(.*)\%25(.*\%25.*)$ $1%$2 [N]
RewriteRule ^(.*)\%25(.*)$ $1%$2 [R=301,L]

RewriteRule ^(.*)\%2b(.*\%2b.*)$ $1+$2 [N]
RewriteRule ^(.*)\%2b(.*)$ $1+$2 [R=301,L]

A terceira linha substituirá todas as seqüências, exceto uma% 2b, por um caractere '+'. Quando houver apenas uma seqüência% 2b restante, a quarta linha corresponderá, forçando um redirecionamento.

A primeira e a segunda linha são basicamente as mesmas, mas com uma seqüência de% 25. É necessário ter uma regra com um sinalizador [R] para cada sequência de caracteres possível, porque também estou usando mod_proxy / mod_jk e o redirecionamento garantirá que o URL resultante seja alimentado para cada módulo novamente. Caso contrário, o httpd tentaria buscar o url do disco, o que falharia no meu caso.

    
por nn4l 08.04.2012 / 14:33

1 resposta

3

Esta é a regra original, com [L] adicionado para denotar "last":

RewriteRule ^(.*)%25(.*)$ $1%$2 [L,R=301]

Depois disso, há alguns problemas aqui. Primeiro, sinais de porcentagem em padrões RewriteRule têm um significado especial; eles denotam o início de uma referência de volta a um RewriteCond . Você pode contornar isso escapando deles (usando uma barra invertida):

RewriteRule ^(.*)\%25(.*)$ $1%$2 [L,R=301]

Em segundo lugar, quando você insere um % em para a substituição, ele não passa a tratar isso como parte de uma peça uri-codificada. Isso se traduz em um sinal de porcentagem literal. No URL original que você está recebendo, o primeiro %25" é convertido em um sinal de porcentagem literal também. Assim, a regra acima resultará em literal %25 s ou literal %2b na URL, em vez de resolver em % ou + . Então você tem que resolver isso manualmente.

RewriteRule ^(.*)\%25(.*)$ $1%$2
RewriteRule ^(.*)\%2b(.*)$ $1+$2 [L,R=301]

Por fim, como você não tem apenas um único 25 após o % inicial, mas potencialmente muitos, use [N] para indicar "próximo". Isso significa basicamente "iniciar o processo desde o início, mas usar meu novo URL como entrada". Então, isso lidará com qualquer número de 25 s após o percentual:

RewriteRule ^(.*)\%25(.*)$ $1%$2 [N]
RewriteRule ^(.*)\%2b(.*)$ $1+$2 [L,R=301]

Nota: Isso deve funcionar se você estiver configurando sua regra nas configurações regulares do apache. Se você estiver configurando como .htaccess , as barras iniciais serão omitidas da sequência verificada na regex, e nesse caso você terá que adicioná-las novamente:

RewriteRule ^(.*)\%25(.*)$ /$1%$2 [N]
RewriteRule ^(.*)\%2b(.*)$ /$1+$2 [L,R=301]

UPDATE : Eu não tenho a habilidade de testar agora, mas olhando para os documentos, acabei de ver uma opção NE para "no escape" que faz com que as porcentagens funcionem como codificação regular marcadores no resultado. Se bem entendi, isso significa que a regra pode ser simplificada para isso:

RewriteRule ^(.*)\%25(.*)$ $1%$2 [NE,N,L,R=301]

Mas, novamente, isso não foi testado e, na verdade, nunca usei o NE , então posso estar interpretando mal. Se você testar isso e achar que funciona, avise-me e removerei este UPDATE e corrija a resposta acima para incluir essa versão mais simples.

    
por 12.04.2012 / 00:51