Caracteres permitidos em um URL

Alguém sabe a lista completa de caracteres que podem ser usados ​​dentro de um GET sem serem codificados? No momento estou usando AZ az e 0-9 … mas estou procurando descobrir a lista completa.

Eu também estou interessado em saber se há uma especificação lançada para a próxima adição de chinês, url árabe (como, obviamente, que terá um grande impacto sobre a minha pergunta)

De especificação RFC 1738 :

Portanto, somente alfanuméricos, os caracteres especiais ” $-_.+!*'(), ” E caracteres reservados usados ​​para seus fins reservados podem ser usados ​​sem codificação em um URL.

EDIT: Como @Jukka K. Korpela corretamente aponta, este RFC foi atualizado pela RFC 3986 . Isso ampliou e esclareceu os caracteres válidos para o host, infelizmente não é facilmente copiado e colado, mas farei o melhor possível.

Na primeira ordem correspondente:

 host = IP-literal / IPv4address / reg-name IP-literal = "[" ( IPv6address / IPvFuture ) "]" IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) IPv6address = 6( h16 ":" ) ls32 / "::" 5( h16 ":" ) ls32 / [ h16 ] "::" 4( h16 ":" ) ls32 / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32 / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32 / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32 / [ *4( h16 ":" ) h16 ] "::" ls32 / [ *5( h16 ":" ) h16 ] "::" h16 / [ *6( h16 ":" ) h16 ] "::" ls32 = ( h16 ":" h16 ) / IPv4address ; least-significant 32 bits of address h16 = 1*4HEXDIG ; 16 bits of address represented in hexadecimal IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet dec-octet = DIGIT ; 0-9 / %x31-39 DIGIT ; 10-99 / "1" 2DIGIT ; 100-199 / "2" %x30-34 DIGIT ; 200-249 / "25" %x30-35 ; 250-255 reg-name = *( unreserved / pct-encoded / sub-delims ) unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" < ---This seems like a practical shortcut, most closely resembling original answer reserved = gen-delims / sub-delims gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" pct-encoded = "%" HEXDIG HEXDIG 

Os caracteres permitidos em um URI são reservados ou não reservados (ou um caractere de porcentagem como parte de uma codificação percentual)

http://en.wikipedia.org/wiki/Percent-encoding#Types_of_URI_characters

diz que estes são os caracteres não reservados da RFC 3986 (seção 2.3), bem como os caracteres reservados (seg 2.2), se eles precisarem manter seu significado especial. E também um caractere de porcentagem como parte de uma codificação percentual.

A lista completa dos 66 caracteres não reservados está em RFC3986, aqui: http://tools.ietf.org/html/rfc3986#section-2.3

Este é qualquer caractere no seguinte conjunto:

 [A-Za-z0-9_.-~] 

Daqui

Portanto, somente alfanuméricos, os caracteres especiais $-_.+!*'(), E caracteres reservados usados ​​para seus fins reservados podem ser usados ​​sem codificação em um URL.

Eu testei solicitando meu site (apache) com todos os caracteres disponíveis no teclado alemão como parâmetro de URL:

 http://example.com/?^1234567890ß´qwertzuiopü+asdfghjklöä#YXCVBNM;:_²³{[]}\|µ@€~ 

Estes não foram codificados:

 ^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,.-!/()=?`*;:_{}[]\|~ 

Não codificado após o urlencode() :

 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_ 

Não codificado após rawurlencode() :

 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_~ 

Nota: Antes do PHP 5.3.0 rawurlencode() codificado ~ por causa do RFC 1738 . Mas isso foi substituído pelo RFC 3986, então é seguro usá-lo agora. Mas eu não entendo porque por exemplo {} são codificados através de rawurlencode() porque eles não são mencionados no RFC 3986.

Um teste adicional que fiz foi sobre a vinculação automática em textos de email. Eu testei o Mozilla Thunderbird, aol.com, outlook.com, gmail.com, gmx.de e yahoo.de e eles totalmente vincularam URLs contendo esses caracteres:

 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_~+#,%&=*;:@ 

Claro que o ? estava ligado também, mas apenas se fosse usado uma vez.

Algumas pessoas agora sugerem usar apenas os caracteres rawurlencode() , mas você já ouviu falar que alguém teve problemas para abrir esses sites?

Asterisco
http://wayback.archive.org/web/*/http://google.com

Cólon
https://en.wikipedia.org/wiki/Wikipedia:About

Mais
https://plus.google.com/+google

No sinal, dois pontos, vírgula e ponto de exclamação
https: //www.google.com/maps/place/USA/@36.2218457, …

Por causa disso, esses caracteres devem ser usados ​​sem codificação sem problemas. Claro que você não deve usar &; por causa de seqüências de codificação como & . O mesmo motivo é válido para % como costumava codificar caracteres em geral. E = como atribui um valor a um nome de parâmetro.

Finalmente eu diria que é ok usar estes não codificados:

 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_~!+,*:@ 

Mas se você espera URLs gerados aleatoriamente, você não deve usar .! , porque esses marcam o final de uma frase e alguns aplicativos de e-mail não vinculam automaticamente o último caractere da URL. Exemplo:

 Visit http://example.com/foo=bar! ! 

Estes estão listados no RFC3986 . Veja o ABNF coletado para o URI para ver o que é permitido onde e o regex para análise / validação.

A próxima mudança é para nomes de domínio chinês, árabe e não URIs. Os URIs internacionalizados são chamados de IRIs e estão definidos no RFC 3987 . No entanto, tendo dito que eu recomendaria não fazer isso sozinho, mas contando com uma biblioteca existente e testada, pois há muitas opções de codificação / decodificação de URI e o que é considerado seguro por especificação, versus o que é seguro pelo uso real (navegadores) .

RFC3986 define dois conjuntos de caracteres que você pode usar em um URI:

  • Caracteres Reservados :/?#[]@!$&'()*+,;=

    reserved = gen-delims / sub-delims

    gen-delims = “:” / “/” / “?” / “#” / “[” / “]” / “@”

    sub-delims = “!” / “$” / “&” / “‘” / “(” / “)” / “*” / “+” / “,” / “;” / “=”

    O objective dos caracteres reservados é fornecer um conjunto de caracteres delimitadores que sejam distinguíveis de outros dados em um URI. URIs que diferem na substituição de um caractere reservado por seu octeto codificado por cento correspondente não são equivalentes.

  • Personagens não reservados : A-Za-z0-9-_.~

    unreserved = ALPHA / DIGIT / “-” / “.” / “_” / “~”

    Caracteres que são permitidos em um URI, mas não têm uma finalidade reservada, são chamados de não reservados.