O que é válido e o que não está em uma consulta de URI?

Antecedentes (questão mais abaixo)

Eu estive pesquisando isso RFCs e perguntas sobre como tentar quebrar isso, mas eu ainda não tenho jack.

Então eu acho que nós apenas votamos na “melhor” resposta e é isso, ou?

Basicamente, isso se resume a isso.

3.4. Componente de Consulta

O componente de consulta é uma cadeia de informações a ser interpretada pelo recurso.

query = *uric

Dentro de um componente de consulta, os caracteres “;”, “/”, “?”, “:”, “@”, “&”, “=”, “+”, “,” E “$” são reservados.

A primeira coisa que me surpreende é que * úric é definido assim

uric = reserved | unreserved | escaped

reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","

Isto é, no entanto, algo esclarecido por parágrafos tais como

A class de syntax “reservada” acima se refere aos caracteres permitidos em um URI, mas que podem não ser permitidos em um componente específico da syntax genérica do URI; eles são usados ​​como delimitadores dos componentes descritos na Seção 3.

Os caracteres no conjunto “reservado” não são reservados em todos os contextos. O conjunto de caracteres realmente reservado em qualquer componente URI determinado é definido por esse componente. Em geral, um caractere é reservado se a semântica do URI for alterada se o caractere for substituído por sua codificação US-ASCII com escape.

Este último trecho parece um pouco atrasado, mas afirma claramente que o conjunto de caracteres reservados depende do contexto. Ainda 3,4 afirma que todos os caracteres reservados são reservados dentro de um componente de consulta, no entanto, as únicas coisas que mudariam a semântica aqui é escaping o ponto de interrogação (?) Como URIs não definem o conceito de uma seqüência de consulta.

Neste ponto, desisti inteiramente das RFCs, mas achei a RFC 1738 particularmente interessante.

Um URL HTTP assume o formato:

http://:/?

Dentro dos componentes e , “/”, “;”, “?” são reservados. O caractere “/” pode ser usado no HTTP para designar uma estrutura hierárquica.

Eu interpreto isso pelo menos com relação a URLs HTTP que a RFC 1738 substitui a RFC 2396. Como a consulta de URI não tem noção de uma string de consulta, a interpretação de reserved não permite que eu defina strings de consulta como estou acostumado fazendo agora.

Questão

Tudo isso começou quando eu queria passar uma lista de números junto com a solicitação de outro recurso. Eu não pensei muito sobre isso e apenas passei isso como valores separados por vírgulas. Para minha surpresa, a vírgula escapou. A consulta page.html?q=1,2,3 codificada se transformou em page.html?q=1%2C2%2C3 funciona, mas é feia e não esperava. Foi quando eu comecei a passar por RFCs.

Minha primeira pergunta é simplesmente: codificar vírgulas é realmente necessário?

Minha resposta, de acordo com a RFC 2396: sim, de acordo com a RFC 1738: não

Mais tarde, encontrei posts relacionados sobre a transmissão de listas entre solicitações. Onde a abordagem csv estava tão ruim. Isso apareceu em vez disso, (não vi isso antes).

 page.html?q=1;q=2;q=3 

Minha segunda pergunta, este é um URL válido?

Minha resposta, de acordo com a RFC 2396: não, de acordo com a RFC 1738: não (; é reservado)

Eu não tenho nenhum problema em transmitir o csv, contanto que sejam números, mas sim você corre o risco de ter que codificar e decodificar valores para frente e para trás se a vírgula de repente for necessária para outra coisa. De qualquer forma eu tentei a coisa de cadeia de consulta de ponto-e-vírgula com o ASP.NET e o resultado não era o que eu esperava.

 Default.aspx?a=1;a=2&b=1&a=3 Request.QueryString["a"] = "1;a=2,3" Request.QueryString["b"] = "1" 

Eu não consigo ver como isso difere muito de uma abordagem csv como quando eu peço “a” eu recebo uma string com vírgulas nele. O ASP.NET certamente não é uma implementação de referência, mas ainda não me decepcionou.

Mas o mais importante – minha terceira pergunta – onde está a especificação para isso? e o que você faria ou não faria?

O fato de um caractere ser reservado dentro de um componente de URL genérico não significa que ele deva ter escape quando aparecer dentro do componente ou dentro dos dados no componente. O caractere também deve ser definido como um delimitador dentro da syntax genérica ou específica do esquema, e a aparência do caractere deve estar dentro dos dados.

O padrão atual para URIs genéricos é o RFC 3986 , que tem isto para dizer:

2.2. Caracteres reservados

Os URIs incluem componentes e subcomponentes delimitados por caracteres no conjunto “reservado”. Esses caracteres são chamados de “reservados” porque podem (ou não) ser definidos como delimitadores pela syntax genérica, por cada syntax específica do esquema ou pela syntax específica da implementação de um algoritmo de desreferenciamento do URI. Se os dados de um componente de URI entrassem em conflito com o propósito de um caracter reservado como um delimitador [ênfase adicionada], os dados conflitantes devem ser codificados em porcentagem antes que o URI seja formado.

  reserved = gen-delims / sub-delims

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

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

3.3. Componente de caminho

[…]

  pchar = unreserved / pct-encoded / sub-delims / ":" / "@" 

[…]

3.4 Componente de Consulta

[…]

  consulta = * (pchar / "/" / "?") 

Assim, vírgulas são explicitamente permitidas dentro de strings de consulta e só precisam ser escapadas em dados se esquemas específicos a definem como um delimitador. O esquema HTTP não usa a vírgula ou o ponto-e-vírgula como um delimitador nas strings de consulta, portanto, eles não precisam ser escapados. Se os navegadores seguem esse padrão é outra questão.

O uso de CSV deve funcionar bem para dados de string, basta seguir as convenções CSV padrão e citar dados ou escaping de vírgulas com barras invertidas.

Quanto ao RFC 2396, ele também permite vírgulas sem escape nas strings de consulta HTTP:

2.2. Caracteres reservados

Muitos URI incluem componentes consistindo ou delimitados por determinados caracteres especiais. Esses caracteres são chamados de “reservados”, já que seu uso dentro do componente URI é limitado ao seu propósito reservado. Se os dados de um componente de URI entrassem em conflito com a finalidade reservada, os dados conflitantes devem ter escape para formar o URI.

Como as vírgulas não têm uma finalidade reservada no esquema HTTP, elas não precisam ter escape nos dados. A nota do § 2.3 sobre caracteres reservados sendo aqueles que alteram a semântica quando codificados por percentual se aplicam apenas de maneira geral; caracteres podem ser codificados por percentual sem alterar a semântica para esquemas específicos e ainda assim serem reservados.

Para responder o que é válido em uma string de consulta, verifiquei quais caracteres especiais são substituídos pelo chrome ao fazer uma solicitação:

 Space -> %20 ! -> ! " -> %22 # -> removed, marks the end of the query string % -> % & -> & ' -> %27 ( -> ( ) -> ) * -> * + -> + (this usually means blank when received at the server, so encode if necessary) , -> , - -> - . -> . / -> / : -> : ; -> ; < -> %3C = -> = > -> %3E ? -> ? @ -> @ [ -> [ \ -> \ ] -> ] ^ -> ^ _ -> _ ` -> ` { -> { | -> | } -> } ~ -> ~ Extended ASCII (like °) -> Every character from this set is encoded 

Nota: Isso provavelmente não significa que você não deve escaping de caracteres que não foram substituídos quando você gera URIs para links. Por exemplo, recomenda-se frequentemente não usar URIs ~ por causa de problemas de compatibilidade, mas ainda é um caractere válido.

Outro exemplo seria o sinal de mais que é válido, mas geralmente tratado como codificado em branco quando um servidor o recebe como parte de uma solicitação. Assim, ele deve ser codificado, mesmo que válido, quando seu propósito é representar um sinal de adição e não um espaço.

Então, para responder o que deve ser codificado: Caracteres inválidos e caracteres que você deseja tratar literalmente, mas têm um significado especial ou podem causar problemas no servidor final.

Apenas use ?q=1+2+3

Estou respondendo aqui uma quarta questão 🙂 que não perguntou, mas tudo começou com: como faço para passar a lista de números a la valores separados por vírgulas? Parece-me que a melhor abordagem é apenas passá-los separados por espaços, onde os espaços serão codificados em forma de url para + . Funciona muito bem, desde que você saiba que os valores na lista não contêm espaços (algo que os números tendem a não include).

page.html? q = 1; q = 2; q = 3

este é um URL válido?

Sim. O ; é reservado, mas não por um RFC. O contexto que define esse componente é a definição do tipo de mídia application/x-www-form-urlencoded , que faz parte do padrão HTML (seção 17.13.4.1 ). Em particular, a nota furtiva escondida na seção B.2.2 :

Recomendamos que os implementadores de servidores HTTP e, em particular, implementadores CGI suportem o uso de “;” no lugar de “&” para salvar os autores do problema de escaping “&” caracteres dessa maneira.

Infelizmente, muitas estruturas de script populares do lado do servidor, incluindo ASP.NET, não suportam esse uso.

Gostaria de observar que page.html?q=1&q=2&q=3 é um URL válido também. Essa é uma maneira completamente legítima de expressar um array em uma string de consulta. Sua tecnologia de servidor determinará exatamente como isso é apresentado.

No ASP clássico, você verifica Response.QueryString("q").Count e, em seguida, use Response.QueryString("q")(0) (e (1) e (2)).

Note que você viu isso no seu ASP.NET também (acho que não foi intencional, mas veja):

 Default.aspx?a=1;a=2&b=1&a=3 Request.QueryString["a"] = "1;a=2,3" Request.QueryString["b"] = "1" 

Observe que o ponto-e-vírgula é ignorado, portanto, você definiu duas vezes e obteve seu valor duas vezes, separado por uma vírgula. Usando todos os e comercials Default.aspx?a=1&a=2&b=1&a=3 produzirão a como “1,2,3”. Mas tenho certeza de que há um método para obter cada elemento individual, caso os elementos contenham vírgulas. É simplesmente a propriedade padrão da QueryString não indexada que concatena os subvalores junto com os separadores por vírgula.

Eu tive o mesmo problema. A URL que estava com hiperlink era uma URL de terceiros e estava esperando uma lista de parâmetros no formato page.html?q=1,2,3 ONLY e a URL page.html?q=1%2C2%2C3 não funcionou. Consegui fazê-lo funcionar usando o javascript. Pode não ser a melhor abordagem, mas pode verificar a solução aqui, se isso ajudar alguém.

Se você está enviando os caracteres ENCODED para o arquivo FLASH / SWF , então você deve ENCODIR o personagem duas vezes !! (por causa do analisador Flash)

Intereting Posts