Se eu quiser criar um URL usando uma variável, tenho duas opções para codificar a string. urlencode()
e rawurlencode()
.
Quais são exatamente as diferenças e qual é a preferida?
php
urlencode
url-encoding
Gary Willoughby
fonte
fonte
rawurlencode
. Você raramente se depara com um sistema que engasga quando determinados espaços são codificados como%20
, enquanto sistemas que engasgam com espaços codificados como+
são mais comuns.Respostas:
Vai depender do seu propósito. Se a interoperabilidade com outros sistemas é importante, parece que o código de código bruto é o caminho a seguir. A única exceção são os sistemas legados que esperam que a string de consulta siga o estilo de codificação de formulário dos espaços codificados como + em vez de% 20 (nesse caso, você precisa do código de URL).
O rawurlencode segue o RFC 1738 anterior ao PHP 5.3.0 e o RFC 3986 posteriormente (consulte http://us2.php.net/manual/en/function.rawurlencode.php )
Nota no RFC 3986 vs 1738. O rawurlencode antes do php 5.3 codificava o caractere til (
~
) de acordo com o RFC 1738. No PHP 5.3, no entanto, o rawurlencode segue o RFC 3986, que não requer codificação de caracteres til.O urlencode codifica os espaços como sinais de adição (não
%20
como feito no rawurlencode) (consulte http://us2.php.net/manual/en/function.urlencode.php )Isso corresponde à definição para application / x-www-form-urlencoded na RFC 1866 .
Leitura adicional:
Você também pode querer assistir à discussão em http://bytes.com/groups/php/5624-urlencode-vs-rawurlencode .
Além disso, o RFC 2396 vale a pena dar uma olhada. O RFC 2396 define a sintaxe válida do URI. A parte principal em que estamos interessados é do 3.4 Query Component:
Como você pode ver,
+
é um caractere reservado na string de consulta e, portanto, precisaria ser codificado de acordo com a RFC 3986 (como no rawurlencode).fonte
A prova está no código fonte do PHP.
Vou levá-lo através de um processo rápido de como descobrir esse tipo de coisa por conta própria no futuro a qualquer momento que você quiser. Tenha paciência comigo, haverá muito código-fonte C em que você pode ler (eu explico). Se você deseja atualizar um pouco de C, um bom lugar para começar é o nosso SO wiki .
Faça o download da fonte (ou use http://lxr.php.net/ para navegar online), grep todos os arquivos para o nome da função, você encontrará algo como isto:
PHP 5.3.6 (mais recente no momento da escrita) descreve as duas funções em seu código nativo C no arquivo url.c .
RawUrlEncode ()
UrlEncode ()
Ok, então o que há de diferente aqui?
Ambos estão essencialmente chamando duas funções internas diferentes, respectivamente: php_raw_url_encode e php_url_encode
Então vá procurar essas funções!
Vamos olhar para php_raw_url_encode
E, claro, php_url_encode:
Um conhecimento rápido antes de avançar, EBCDIC é outro conjunto de caracteres , semelhante ao ASCII, mas um concorrente total. O PHP tenta lidar com ambos. Mas basicamente, isso significa que o byte EBCDIC 0x4c não é o
L
ASCII, na verdade é um<
. Tenho certeza que você vê a confusão aqui.Ambas as funções gerenciam o EBCDIC se o servidor da web o definiu.
Além disso, ambos usam uma pesquisa de caracteres chars (tipo de cadeia de caracteres)
hexchars
para obter alguns valores; a matriz é descrita da seguinte forma:Além disso, as funções são realmente diferentes, e eu vou explicá-las em ASCII e EBCDIC.
Diferenças em ASCII:
URLENCODE:
+
sinal à string de saída.isalnum(c)
), e também não é e_
,-
ou.
caractere, emitimos um%
sinal para a posição 0 da matriz, fazemos uma matriz procurar nahexchars
matriz uma procura poros_toascii
matriz ( uma matriz do Apache que converte char para código hexadecimal) para a chave dec
(o caractere presente), então deslocamos bit a bit para a direita em 4, atribuímos esse valor ao caractere 1 e à posição 2 atribuímos a mesma pesquisa, exceto que executamos um lógico e para ver se o valor é 15 (0xF) e retorne 1 nesse caso ou 0 caso contrário. No final, você terminará com algo codificado._-.
caracteres, gera exatamente o que é.RAWURLENCODE:
Nota: Muitos programadores provavelmente nunca viram um loop for iterar dessa maneira, é um tanto hackiano e não a convenção padrão usada com a maioria dos loops for, preste atenção, ele atribui
x
ey
verifica a saída aolen
atingir 0 e incrementa ambosx
ey
. Eu sei, não é o que você esperaria, mas é um código válido.str
._-.
caracteres, e se não for, fazemos quase a mesma atribuição que com URLENCODE onde ele realiza pesquisas, no entanto, incrementamos de maneira diferente, usando emy++
vez deto[1]
, isso ocorre porque o as strings estão sendo construídas de maneiras diferentes, mas atingem o mesmo objetivo no final.\0
byte.Diferenças:
\0
byte à cadeia de caracteres, RawUrlEncode (isso pode ser um ponto discutível)Basicamente, iteram de maneira diferente, atribui-se um sinal de + no evento ASCII 20.
Diferenças no EBCDIC:
URLENCODE:
0
, com exceção de ser um.
ou-
, OR menor queA
mas maior que char9
, OR maior queZ
e menor quea
mas não a_
. OU maior quez
(sim, EBCDIC está meio bagunçado para trabalhar). Se corresponder a qualquer um desses, faça uma pesquisa semelhante à encontrada na versão ASCII (apenas não requer uma pesquisa em os_toascii).RAWURLENCODE:
z
, exclui~
da codificação de URL.\0
byte à string antes de retornar.Grande resumo
~
que o UrlEncode não faz ( esse é um problema relatado ). Vale a pena notar que ASCII e EBCDIC 0x20 são ambos espaços.+
, RawUrlEncode cria um espaço%20
através de pesquisas de matriz.Isenção de responsabilidade: não toquei em C há anos e não vejo o EBCDIC há muito tempo. Se eu estiver errado em algum lugar, me avise.
Implementações sugeridas
Com base em tudo isso, rawurlencode é o caminho a seguir na maioria das vezes. Como você vê na resposta de Jonathan Fingland, fique com ela na maioria dos casos. Ele lida com o esquema moderno de componentes de URI, onde como urlencode faz as coisas da maneira antiga, onde + significava "espaço".
Se você estiver tentando converter entre o formato antigo e os novos, certifique-se de que seu código não aconteça e transforme algo que é um sinal + decodificado em um espaço por meio de codificação dupla acidental ou cenários semelhantes de "ops" espaço / 20% / + problema.
Se você estiver trabalhando em um sistema mais antigo com software mais antigo que não prefere o novo formato, fique com o código de URL, no entanto, acredito que% 20 será realmente compatível com versões anteriores, pois no antigo padrão% 20 funcionou, simplesmente não era preferido. Dê uma chance se quiser brincar, deixe-nos saber como funcionou para você.
Basicamente, você deve ficar com o raw, a menos que seu sistema EBCDIC realmente o odeie. A maioria dos programadores nunca encontrará o EBCDIC em qualquer sistema criado após o ano de 2000, talvez até 1990 (isso é bom, mas ainda é provável na minha opinião).
fonte
rendimentos
enquanto
rendimentos
A diferença é o
asd%20asd
vsasd+asd
urlencode difere do RFC 1738, codificando espaços, em
+
vez de%20
fonte
Um motivo prático para escolher um sobre o outro é se você usará o resultado em outro ambiente, por exemplo, JavaScript.
No PHP,
urlencode('test 1')
retorna'test+1'
enquantorawurlencode('test 1')
retorna'test%201'
como resultado.Mas se você precisa de "decodificar" isso em JavaScript usando decodeURI () função, em seguida,
decodeURI("test+1")
irá dar-lhe"test+1"
enquantodecodeURI("test%201")
lhe dará"test 1"
como resultado.Em outras palavras, o espaço ("") codificado pelo urlencode para mais ("+") no PHP não será decodificado adequadamente pelo decodeURI no JavaScript.
Nesses casos, a função PHP rawurlencode deve ser usada.
fonte
json_encode
eJSON.parse
para esse fim.Acredito que os espaços devem ser codificados como:
%20
quando usado dentro do componente do caminho da URL+
quando usado dentro do componente da string de consulta da URL ou dos dados do formulário (consulte 17.13.4 Tipos de conteúdo do formulário )O exemplo a seguir mostra o uso correto de
rawurlencode
eurlencode
:Resultado:
O que acontece se você codificar o caminho e consultar os componentes da cadeia de caracteres ao contrário? Para o seguinte exemplo:
latest+songs
vez delatest songs
q
conterálady gaga
fonte
q
conterálady gaga
" O que mais ele conteria? O parâmetro queryq
parece ter o mesmo valor passado para a$_GET
matriz, independentemente do usorawurlencode
ouurlencode
no PHP 5.2+. No entanto,urlencode
codifica noapplication/x-www-form-urlencoded
formato que é padrão para solicitações GET, então eu vou com sua abordagem. +1+
e%20
são decodificados como espaço quando usados em seqüências de caracteres de consulta.A diferença está nos valores de retorno, ou seja:
urlencode () :
rawurlencode () :
Os dois são muito semelhantes, mas o último (rawurlencode) substituirá espaços por um '%' e dois dígitos hexadecimais, o que é adequado para codificar senhas ou outras, em que um '+' não é, por exemplo:
fonte
1. Quais são exatamente as diferenças e
A única diferença está na maneira como os espaços são tratados:
urlencode - com base na implementação herdada converte espaços em +
rawurlencode - com base no RFC 1738 converte espaços para% 20
O motivo da diferença é porque + é reservado e válido (não codificado) em URLs.
2. qual é o preferido?
Justo, tenho uma estratégia simples que sigo ao tomar essas decisões, que compartilharei com você na esperança de que possa ajudar.
Eu acho que foi a especificação HTTP / 1.1 RFC 2616 que pediu " aplicativos tolerantes "
Quando confrontada com perguntas como essas, a melhor estratégia é sempre consumir o máximo possível e produzir o que é compatível com os padrões.
Portanto, meu conselho é usar
rawurlencode
para produzir seqüências codificadas em conformidade com os padrões RFC 1738 eurldecode
ser compatível com versões anteriores e acomodar qualquer coisa que você possa encontrar para consumir.Agora você pode apenas aceitar minha palavra, mas vamos provar que devemos ...
Parece que o PHP tinha exatamente isso em mente, mesmo que eu nunca tenha encontrado alguém que se recuse a nenhum dos dois formatos, não consigo pensar em uma estratégia melhor para adotar como sua estratégia defacto, pode?
nJoy!
fonte
fonte
Espaços codificados como
%20
vs.+
A maior razão que eu vi usar
rawurlencode()
na maioria dos casos é porqueurlencode
codifica os espaços de texto como+
(sinais de mais), onde osrawurlencode
codifica como os mais comuns%20
:Vi especificamente determinados pontos de extremidade da API que aceitam consultas de texto codificado que esperam ver
%20
por um espaço e, como resultado, falham se um sinal de adição for usado. Obviamente, isso difere entre implementações de API e sua milhagem pode variar.fonte
Acredito que urlencode é para parâmetros de consulta, enquanto o rawurlencode é para os segmentos de caminho. Isso se deve principalmente aos
%20
segmentos de caminho e+
aos parâmetros de consulta. Veja esta resposta que fala sobre os espaços: Quando codificar o espaço para mais (+) ou% 20?No entanto,
%20
agora também funciona nos parâmetros de consulta, e é por isso que o rawurlencode é sempre mais seguro. No entanto, o sinal de mais tende a ser usado onde a experiência do usuário de edição e legibilidade dos parâmetros de consulta são importantes.Observe que isso significa
rawurldecode
que não decodifica+
em espaços ( http://au2.php.net/manual/en/function.rawurldecode.php ). É por isso que o $ _GET é sempre passado automaticamente atravésurldecode
, o que significa que+
e%20
ambos são decodificados em espaços.Se você deseja que a codificação e a decodificação sejam consistentes entre entradas e saídas e optou por sempre usar
+
e não%20
para parâmetros de consulta, issourlencode
é bom para parâmetros de consulta (chave e valor).A conclusão é:
Segmentos de caminho - sempre use rawurlencode / rawurldecode
Parâmetros de consulta - para decodificar sempre use urldecode (feito automaticamente), para codificação, tanto rawurlencode quanto urlencode estão corretos, basta escolher um que seja consistente, especialmente ao comparar URLs.
fonte
simple * rawurlencode o caminho - o caminho é a parte antes do "?" - espaços devem ser codificados como% 20 * urlencode a string de consulta - String de consulta é a parte após o "?" -spaces são melhor codificados como "+" = rawurlencode é mais compatível geralmente
fonte