Português (Brasil)

Ferramentas de desenvolvedor · Codificador e decodificador URL

WHATWG URL Padrão vs RFC 3986: por que navegadores e bibliotecas discordam

· Fundo

codificação de URL padrões ferramentas de desenvolvedor

Divergência de navegador e biblioteca na análise de URL
Ilustração vetorial original ToolAcre

Existem duas definições vivas de URL e elas discordam propositalmente. Esta postagem explica por que WHATWG escreveu seu próprio padrão, onde os dois diferem na codificação e análise, e qual deles seu código segue.

O URL que uma biblioteca estrita rejeita e o navegador carrega alegremente - uma string, dois veredictos

Uma string com uma barra invertida em JavaScript pode ser interpretada facilmente pelo seu navegador como parte do caminho URL. A mesma string chega ao back-end da biblioteca Python e se recusa a analisá-la porque barras invertidas não são permitidas. Um URL, dois resultados diferentes. Nenhum dos dois está errado – eles seguem padrões diferentes. O padrão WHATWG descreve o que os navegadores realmente fazem com URLs do mundo real, incluindo como eles lidam com entradas malformadas. RFC 3986 define uma gramática formal com a qual os URLs devem idealmente estar em conformidade. Muitas bibliotecas de back-end construídas em RFC 3986 aplicam essa gramática estritamente e rejeitam qualquer coisa fora dela.

Essa divergência é importante quando você move dados entre ambientes. Uma aceitação do navegador URL pode falhar na validação em uma ferramenta de back-end. Entender qual padrão seu código implementa evita a depuração de problemas fantasmas – URLs funcionando bem em um lugar, mas falhando misteriosamente em outro lugar sem motivo aparente.

Por que o WHATWG recomeçou — descrevendo o que os navegadores realmente fazem com entradas malformadas, em vez do que é válido

O Grupo de Trabalho WHATWG foi formado em 2004 para padronizar como os navegadores realmente lidam com URLs na prática, em vez de definir regras formais mais rígidas que os navegadores não seguiriam. RFC 2396 descreveu uma especificação gramatical formal, mas os navegadores na prática nunca a seguiram exatamente e corretamente. Os navegadores do mundo real desenvolveram regras práticas para tolerar espaços, lidar com caracteres de escape e recuperar entradas malformadas que o RFC não previu ou esperava.

RFC 3986 chegou em 2005 com gramática formal para URLs bem formados e requisitos rígidos. Os navegadores implementam WHATWG; bibliotecas de back-end geralmente implementam RFC 3986.

Conjuntos de codificação versus caracteres reservados — como as listas por componente do padrão URL se relacionam com as categorias de RFC 3986

RFC 3986 divide os caracteres em três categorias: reservados, não reservados e tudo o mais que deve ser codificado. Caracteres reservados como dois pontos, barra, ponto de interrogação e hash têm significado estrutural em URLs. Caracteres não reservados são letras, dígitos, hífen, sublinhado, ponto final e til; estes são sempre seguros. Todo o resto é codificado em porcentagem como bytes. O padrão fornece uma regra clara: saiba a qual categoria seu personagem pertence.

O padrão WHATWG URL adota uma abordagem baseada em componentes. Especifica diferentes regras de codificação para esquema, autoridade, caminho, consulta e fragmento separadamente, em vez de usar categorias globais. Um E comercial pode ser codificado em um caminho, mas deixado sozinho em uma string de consulta. Um espaço é sempre codificado, mas a representação exata varia de acordo com o contexto. Este design por componente corresponde muito melhor ao comportamento do navegador, mas requer saber qual parte do URL você está codificando.

Tolerância a erros: espaços, barras invertidas e tabulações — entradas que um padrão rejeita e o outro repara

Os espaços devem se tornar %20 em ambos os padrões, mas os navegadores convertem silenciosamente espaços literais. Barras invertidas são proibidas por ambos os padrões, mas alguns navegadores as tratam como separadores de caminho. Tabulações, novas linhas e caracteres de controle são proibidos. WHATWG especifica o comportamento tolerante do analisador: converta-o ou ignore-o.

Caracteres não ASCII como é ou 中 devem ser codificados por porcentagem usando a codificação UTF-8. RFC 3986 na verdade não especifica a etapa de codificação de caracteres em si; ele assume que existem bytes, mas não diz como obtê-los do texto. O padrão WHATWG requer explicitamente UTF-8: transforme a string em UTF-8 bytes primeiro e depois codifique-os por cento. Ambos os padrões alcançam o mesmo resultado de codificação, mas partem de diferentes suposições subjacentes e não são explícitos sobre as mesmas coisas.

Exemplo resolvido: analisando um URL com uma barra invertida e um espaço em ambos os modelos - as saídas comparadas

Veja a string de exemplo "https://example.com/café\ search". Um navegador encontra a barra invertida e a vê como um caractere de caminho; ele vê o espaço e o codifica para %20, produzindo algo como https://example.com/café%5C%20search. Um analisador RFC 3986 rejeita todo o URL imediatamente porque barras invertidas são proibidas e espaços são proibidos. O navegador continua a análise; o analisador estrito para completamente. Tente outro exemplo: "https://user@example.com:80/path?q=a&b=c". Ambos os padrões identificam claramente as informações do usuário, host, porta, caminho e consulta. Eles concordam completamente com este URL estruturado. A discordância acontece apenas em entradas incomuns ou malformadas.

Abra o codificador e decodificador URL e compare o modo RFC 3986 com o comportamento do navegador. Cole uma string com espaços, barras invertidas ou outros casos extremos. A ferramenta mostra exatamente como cada padrão transforma a mesma entrada de maneira diferente. Você vê imediatamente qual é mais rígido e o que cada um faz.

Qual deles seu ambiente usa — navegadores e Node seguem o padrão URL; muitas bibliotecas de servidor seguem o RFC, descrito geralmente

Nos navegadores, JavaScript usa o padrão WHATWG URL por padrão. O URL API implementa isso exatamente. Node.js também usa WHATWG. Bibliotecas Python tendem a implementar RFC 3986; urllib segue de perto. As bibliotecas Java variam; java.net.URL tende para RFC 3986. A caixa de URL do Rust segue WHATWG. A rede/url de Go é influenciada por WHATWG. Este é um padrão geral, não uma regra absoluta.

Quando você cria URLs programaticamente e eles se movem entre o navegador e o back-end, escolha um padrão e siga-o. Use URL API do navegador para WHATWG. Se a sua biblioteca de back-end for mais rígida, não será uma contradição, mas uma escolha de design.

O que isso não cobre: ​​análise de nome de host, literais IPv6 e processamento de IDNA

A análise de nome de host envolve IDNA, punycode e regras de registrador que vão além da análise completa de URL. Endereços IPv6, esquemas especiais como mailto: ou data: e componentes vazios são tópicos separados, distintos da codificação percentual completamente. Os limites de comprimento de domínio e a validade do nome de host variam de acordo com o registrador e não são relevantes para esta discussão. Também excluídas: referências relativas e regras de análise específicas do esquema. Esta postagem se concentra apenas na codificação e análise de diferenças.

Esta discussão concentra-se nas diferenças de codificação e análise que distinguem esses padrões. A exclusão de regras de nome de host, regras DNS e comportamento específico do esquema evita confusão sobre regras de codificação percentual.

Conclusão: o mesmo URL é válido em um mundo e um erro em outro - como o codificador e decodificador URL fornece a codificação RFC 3986 simples para que você possa ver o que o navegador normalizou

A mesma string URL pode ser válida em um padrão e inválida em outro. Ambos estão corretos dentro de seus próprios objetivos de design. Ao codificar componentes URL programaticamente, use a ferramenta certa para seu ambiente. WHATWG descreve o que os navegadores realmente fazem; RFC 3986 define gramática formal. O codificador e decodificador URL mostra regras RFC 3986 junto com o comportamento do navegador para que você possa ver as diferenças exatas e escolher qual se adapta à sua situação.

Os problemas aparecem com mais frequência quando os URLs ultrapassam os limites do navegador ao back-end. Compreender esta diferença significa lidar com essa travessia intencionalmente e não acidentalmente ou por engano.