Caracteres permitidos em um URL

190

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.

Também estou interessado em saber se há uma especificação liberada para a próxima adição de URLs em chinês e árabe (como obviamente isso terá um grande impacto na minha pergunta)

Marca
fonte
5
Os caracteres permitidos em um URI ou são reservados !*'();:@&=+$,/?#[]ou sem reservas A-Za-z0-9_.~-(ou um carácter de percentagem %, como parte de um por cento de codificação)
Mikl
1
No MySQL, eu uso isso REGEXP '[^]A-Za-z0-9_.~!*''();:@&=+$,/?#[%-]+'para encontrar URL com caracteres incorretos. Talvez seja útil para outra pessoa também.
Mikl 30/05
@ Mikl: Essa coisa dificilmente parece uma expressão regular.
Jens Mander

Respostas:

181

Da especificação RFC 1738 :

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

EDIT: Como aponta corretamente @Jukka K. Korpela, esta RFC foi atualizada pela RFC 3986 . Isso expandiu e esclareceu os caracteres válidos para o host, infelizmente não é fácil copiar e colar, mas farei o meu melhor.

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
Myles
fonte
5
A barra @Tim é um caractere reservado, portanto, se estiver sendo usada para seu fim reservado (delineando caminhos, delineamento de protocolo ...), não será necessário escapar. Caso contrário, ele faz.
Myles
4
Regras de sintaxe genéricas de RFC 1738 foram tornados obsoletos em 1998.
Jukka K. Korpela
3
@ Styles, STD 66 (= RFC 3986) é mencionado em outras respostas. Se o conteúdo das respostas está correto é uma questão diferente; Acho que nenhuma das respostas descreve corretamente a lista completa.
Jukka K. Korpela 08/03
4
E você pode adicionar uma lista de A-Za-z0-9_.-~caracteres não reservados e reservados no início desta resposta. !*'();:@&=+$,/?#[]Ele pode economizar tempo para as pessoas
Mikl
2
@basZero Sinto muito que você tenha achado confuso, mas a resposta completa não é simples. A resposta para sua pergunta é não, pois é um caractere reservado, conforme indicado por:reserved = gen-delims / sub-delims gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
Myles
42

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

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

diz que esses são caracteres não reservados para o RFC 3986 (seção 2.3) e caracteres reservados (seção 2.2), caso precisem manter seu significado especial. E também um caractere de porcentagem como parte de uma codificação de porcentagem.

Âmbar
fonte
7
Embora esse link possa responder à pergunta, é melhor incluir aqui as partes essenciais da resposta e fornecer o link para referência. As respostas somente para links podem se tornar inválidas se a página vinculada for alterada.
jaestevan
@jaestevan Citação do documento vinculado:The characters allowed in a URI are either reserved or unreserved (or a percent character as part of a percent-encoding)
Mikl
26

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

Este é qualquer caractere no seguinte conjunto de expressões regulares:

[A-Za-z0-9_.\-~]
slacy
fonte
2
Você pode usar aqueles reservados também.
Qwerty
O obsoleto RFC1738 listado {}^\~e backtickcomo inseguro. E o RFC3986 lista \ como não seguro por causa do sistema de arquivos. Isso significa que também {}^pode ser usado.
mgutt
Então, se você está tentando, digamos, encontrar o final de um URL dentro de uma string (o que eu sou), seria melhor seguir os padrões obsoletos na resposta aceita ... Se você estiver validando os URLs, deve use o conjunto de caracteres nesta resposta.
ashleedawg
Cuidado, você escreveu isso como uma classe de caractere de expressão regular. Certifique-se para escapar da -ou colocá-lo no início ou no final da classe de personagem, porque [.-~]na verdade, contém todos os caracteres ASCII de 46 a 126.
kwl
19

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

http://example.com/?^1234567890ß´qwertzuiopü+asdfghjklöä#<yxcvbnm,.-°!"§$%&/()=? `QWERTZUIOPÜ*ASDFGHJKLÖÄ\'>YXCVBNM;:_²³{[]}\|µ@€~

Estes não foram codificados:

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

Não codificado após urlencode():

0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_

Não codificado após rawurlencode():

0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_~

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

Um teste adicional que fiz foi referente à vinculação automática em textos de correio. Testei o Mozilla Thunderbird, aol.com, outlook.com, gmail.com, gmx.de e yahoo.de e eles vincularam completamente os URLs contendo esses caracteres:

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

É claro que o ?link também estava vinculado, mas apenas se fosse usado uma vez.

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

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

Colon
https://en.wikipedia.org/wiki/Wikipedia:About

Além disso,
https://plus.google.com/+google

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

Por esse motivo, esses caracteres devem ser utilizáveis ​​sem codificação sem problemas. Claro que você não deve usar &;por causa de sequências de codificação como &amp;. O mesmo motivo é válido %, pois costumava codificar caracteres em geral. E =como atribui um valor ao nome de um parâmetro.

Finalmente, eu diria que não há problema em usar estes não codificados:

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

Mas se você espera URLs gerados aleatoriamente, não deve usá-lo .!, porque eles marcam o final de uma frase e alguns aplicativos de email não vinculam automaticamente o último caractere do URL. Exemplo:

Visit http://example.com/foo=bar! !
mgutt
fonte
Abordagem prática - bom trabalho. Estava procurando pela última lista sua - o +sinal especialmente :-D
Oliver
12

A partir daqui

Portanto, apenas alfanuméricos, caracteres especiais $-_.+!*'(), e caracteres reservados usados ​​para fins reservados podem ser usados ​​não codificados em um URL.

AdaTheDev
fonte
7

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

McDowell
fonte
5

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

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

    reservado = delimitações genéricas / sublimites

    gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"

    sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

    O objetivo 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 pelo seu octeto codificado em porcentagem correspondente não são equivalentes.

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

    não reservado = ALPHA / DIGIT / "-" / "." / "_" / "~"

    Os caracteres permitidos em um URI, mas que não têm um objetivo reservado, são chamados de não reservados.

Cyker
fonte
3

A próxima mudança é para nomes de domínio em árabe e chinês, não URIs. Os URIs internacionalizados são chamados IRIs e são definidos na RFC 3987 . No entanto, tendo dito que eu recomendaria não fazer isso sozinho, contando com uma biblioteca já testada, já que existem 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) .

dajobe
fonte
0

Se você deseja dar um tipo especial de experiência aos usuários, pode usar pushStateuma variedade de caracteres para o URL do navegador:

insira a descrição da imagem aqui

var u="";var tt=168;
for(var i=0; i< 250;i++){
 var x = i+250*tt;
console.log(x);
 var c = String.fromCharCode(x);
 u+=c; 
}
history.pushState({},"",250*tt+u);
Sombrio
fonte