1 pontos por GN⁺ 5 시간 전 | 1 comentários | Compartilhar no WhatsApp
  • Chris Morgan decidiu bloquear completamente strings de consulta não autorizadas em seu site, e a implementação atual está no Caddyfile
  • Ele não quer que parâmetros de rastreamento como ?ref=example.com sejam anexados às URLs, e considera que, se necessário, basta olhar o cabeçalho Referer
  • Ele considera que UTM parameters como ?utm_source=example&utm_*&c.* são para uso do proprietário do site, e não para serem anexados por terceiros
  • Atualmente o site não usa strings de consulta de forma alguma, e, se passar a usar no futuro, pretende permitir apenas parâmetros conhecidos
  • A URL final escolhida foi /no-query-strings, e /%3F não foi adotada por causa de problemas com a reescrita try_files do Caddy

Bloqueio de strings de consulta não autorizadas

  • Chris Morgan decidiu bloquear completamente strings de consulta não autorizadas em seu site
  • Ele não quer que parâmetros de rastreamento como ?ref=example.com sejam anexados às suas URLs, e considera que, se necessário, basta olhar o cabeçalho Referer
  • Ele considera que UTM parameters como ?utm_source=example&utm_*&c.* são para uso do proprietário do site, e não para serem anexados por terceiros
  • Atualmente este site não usa strings de consulta de forma alguma, e, se passar a usar no futuro, pretende permitir apenas parâmetros conhecidos
  • No passado, ele usava URLs de invalidação de cache como ?t=… e ?h=… na URL da folha de estilo, mas concluiu que tudo bem se esse tipo de requisição quebrar
  • Esse bloqueio está atualmente implementado no Caddyfile

Processo de escolha da URL

  • Plano de usar /?

    • No início, a tentação de publicar esta página em https://chrismorgan.info/? era grande
    • Por ser a forma de caminho vazio e consulta vazia, ela quebraria várias suposições comuns porém equivocadas e poderia colocar algumas ferramentas em dificuldade
    • O curl parecia remover indevidamente o ponto de interrogação final na linha de comando, e ele não testou o uso por bibliotecas
    • No fim, decidiu respeitar o conceito de caminho e ser mais generoso com as pessoas, especialmente porque já considerava estar forçando o Caddy em direções desconfortáveis o suficiente
  • Plano de usar /%3F

    • O plano seguinte era publicar em /%3F, onde o caminho seria ? e não haveria consulta
    • Porém, havia um problema no Caddy que o impedia de lidar com isso quando a reescrita try_files estava envolvida
    • A issue relacionada é try_files quebra caminhos contendo caracteres como ? e %
  • Escolha final

    • A URL final foi definida como /no-query-strings
    • /? ou /%3F talvez ainda venham a ser usados depois para algum outro propósito relacionado a strings de consulta

1 comentários

 
GN⁺ 5 시간 전
Comentários do Hacker News
  • Fiquei curioso com isso e fui reler os padrões W3C de HTML e URL; para minha surpresa, o formato de query string não tem uma definição específica além de percent-encoding
    Dá para confundir query string com query string “form-urlencoded”[0], mas isso é apenas um dos formatos interoperáveis. Em geral, query string é uma string arbitrária com percent-encoding[1] que vem depois do ? na URL, e é mais uma propriedade do objeto URL do HTML que pode ser usada para gerar a resposta
    O objeto URLSearchParams é o resultado de analisar a query string com um parser form-urlencoded, mas isso é só uma camada de interoperabilidade para JavaScript
    Sinceramente, antes de olhar o padrão eu estava pronto para discordar, mas o padrão é bem claro. Responder com 404 a uma query string inesperada também pode ser apropriado. A query string faz parte da API de URL tanto quanto o caminho, e a maioria concordaria que acrescentar uma string arbitrária ao caminho não é uma boa ideia e é um comportamento indefinido
    [0]: https://url.spec.whatwg.org/#application/x-www-form-urlencod...
    [1]: https://url.spec.whatwg.org/#url-class

    • Antigamente era bem comum CMS ou fóruns terem só um index.php e fazerem todo o roteamento pela query string
      Claro, era no formato form-urlencoded, as pessoas também não eram bárbaras. Então apareciam URLs como index.php?p=home, index.php?p=shop ou index.php?action=showthread&forum=42&thread=17976. Numa estrutura dessas, fica imediatamente óbvio que 404 é a resposta certa para parâmetros de query desconhecidos
      Na prática, muitos sites ainda funcionam assim, só que escondidos atrás de algumas regras de reescrita do Apache/nginx por causa de SEO
    • Sim, URL não tem tanta semântica assim. Caminho claramente parece destinado a dados hierárquicos e query a dados não hierárquicos, há convenções fortes e algumas bibliotecas até apoiam ou impõem isso, mas não existem regras de verdade
      No fim, URL é só uma string que o servidor decide como processar
      O mais engraçado nessa discussão é se preocupar com os efeitos colaterais de responder com 404 enquanto se esquece completamente por quanto tempo os caminhos foram sem sentido na história da web. Agora o caminho venceu. Quase ninguém mais começa do zero com URLs tipo /item?id=…. Que bom!
    • Acho que um 400 genérico seria melhor. Não é que a página não foi encontrada, e sim que foi enviada uma requisição não permitida
      A leitura é “corrija a requisição e tente de novo”, e é assim que eu uso nas APIs que ofereço. Prefiro isso a 406 porque não é um problema que eu não consiga processar. Se alguém tentou quebrar a coisa acrescentando algo na query string ou não montou a requisição como manda a documentação, a responsabilidade é de quem fez a requisição
    • A proposta No-Vary-Search permite especificar quais partes da query são relevantes
      https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/...
      Por exemplo, do ponto de vista de cache, url?a=b&c=d pode ser considerado equivalente a url?c=d&a=b
    • Padrão é só um comportamento amplamente aceito que alguém escreveu em algum lugar
      Há muitas convenções que nunca foram documentadas como padrão formal, mas que quebram um monte de coisa se você não seguir, e também há muitos “padrões” que, se levados ao pé da letra, fazem você parecer bobo
      No caso do texto original, quem quebra é só quem está tentando visitar aquele site, e provavelmente a pessoa vai apertar voltar no navegador e seguir a vida. Cabe ao autor decidir se aceita esse nível de dano. Só que o fato de algum padrão não proibir algo não significa que isso seja permitido por definição, e o contrário também vale: se o padrão proíbe, isso não se torna automaticamente inadmissível
  • Pelo que entendi, o autor parece irritado porque outros sites colocam uma query string como ?ref=origin.com nos links para o site dele
    Não entendo que benefício isso traz para o site de origem nem que prejuízo causa ao site do autor
    Os dois lados desse comportamento me parecem completamente confusos
    Quando se roda uma campanha de anúncios, entendo que o Google queira anexar query strings UTM para rastrear de qual campanha o usuário veio. Aí há uma relação de cooperação entre origem e destino. Mas aqui a origem está acrescentando algo sem motivo aparente. Por quê?

    • Do ponto de vista do site de origem, isso é marketing. O autor vê na query string ref que um tráfego considerável está vindo de xyz.com e pode pensar em anunciar lá ou fazer alguma parceria
      Sinceramente, isso é bem útil para sites de nicho/startups. Já estive dos dois lados de conversas iniciadas por esse tipo de dado em analytics: uma vez eu entrei em contato ao ver o tráfego de referência, em outra um site para o qual eu havia linkado entrou em contato comigo. Nas duas situações terminou em parcerias benéficas para ambos
      Entendo até certo ponto a discussão sobre privacidade, mas isso não fornece mais informação do que o cabeçalho padrão Referer. Só fica muito mais visível se você usa ferramentas de analytics como Simple Analytics ou Plausible
    • Em geral sou contra rastreamento. Rastreamento normalmente vai contra os interesses do indivíduo
      Acrescentar query string é algo frequentemente usado para rastreamento. Só o fato de existirem recursos como “copy clean link” do Firefox ou a Enhanced Tracking Protection, que remove preventivamente alguns parâmetros UTM, já mostra que muita gente não quer isso
      Alguns sites participam de bom grado do sistema que eu chamaria casualmente de “economia do rastreamento”, porque o destinatário pode ver nos logs que muita gente veio daquele site e agir de uma forma que beneficie esse site
      Rejeitar query strings é um protesto simples contra esse sistema
    • Se um site popular adiciona esse parâmetro, o site de destino pode descobrir facilmente quem está enviando tráfego, e isso pode servir de base para patrocínios ou acordos de afiliados
  • Pela descrição, “um pequeno console web descentralizado, auto-hospedado, que permite aos visitantes explorar sites e páginas interessantes recomendados por uma comunidade de operadores de sites pessoais independentes”, antigamente isso era chamado de Webring. Só que não era tão pomposo
    Um dos problemas que tive ao desenvolver um framework de aplicações open source foi que hospedagens usando FastCGI não respeitavam o cabeçalho Auth, então eu era forçado a passar o token pela query. Era péssimo, porque ao copiar e colar o endereço da web o token frequentemente ia junto. Talvez isso já tenha sido corrigido hoje
    Em backends sob meu controle e que não precisam ser públicos para todo mundo, eu uso cabeçalhos

    • Você escreveu o framework de aplicações open source com fcgi-app, então quer dizer que, por exemplo, o Apache quebrava o cabeçalho Auth?
      Fiquei curioso se você pode explicar melhor essa parte. Tecnicamente, parece que você está dizendo que o registro PARAM não entregava o valor esperado
  • Ele disse: “Então neste site decidi tentar uma proibição abrangente: nada de query strings não aprovadas”, mas o site dele aparentemente retorna 414 quando a requisição inclui query string, e acho que essa foi uma escolha errada
    Se esse protesto é para defender o usuário, por que punir justamente o usuário, que em princípio não tinha controle sobre aquela string?
    Não seria melhor usar isso como um sinal para mostrar ao usuário como ele mesmo pode tomar essa decisão, por exemplo com ferramentas do navegador?

    • “Você pode alegar que estou abusando de 414 URI Too Long. Minha resposta é: assim fica mais engraçado. As outras opções que considerei foram:
      400 Bad Request, um código genérico de erro do cliente, correto, mas sem graça
      402 Payment Required, sinceramente eu estaria aberto a aceitar pagamento para fazer uma determinada URL com query string funcionar
      404 Not Found, mas isso gera efeitos colaterais com muita facilidade e não transmite a sensação de ‘o formato da requisição está errado’ que eu quero
      303 See Other sem cabeçalho Location. Hoje é extremamente raro, mas é legítimo. Pelo menos no RFC 2616 era (“The different URI SHOULD be given by the Location field in the response”). Mas no 7231 e no 9110 isso mudou para uma formulação que pressupõe a presença do cabeçalho Location (“… as indicated by a URI in the Location header field”). Já 301, 302, 307 e 308 dizem que “the server SHOULD generate a Location header field”. De qualquer forma, ainda considero um See Other sem cabeçalho Location perfeitamente aceitável. Mas URI Too Long era mais engraçado”
      https://chrismorgan.info/no-query-strings?foo
    • Faz muito tempo, então posso estar lembrando errado, mas acho que houve uma versão de páginas de servidor PLSQL que retornava 500 quando você passava query strings desconhecidas
  • Quando ele diz “Você pode alegar que estou abusando de 414 URI Too Long. Minha resposta é: assim fica mais engraçado. As outras opções que considerei…” dá para considerar outra opção: 418 I'm a teapot. Bules normalmente também não suportam query strings

    • Simplesmente 400 “Bad Request” ou 403 “Forbidden” também parecem escolhas defensáveis. É estranho não existir um código de resposta de erro específico para parâmetros de URI
      Há várias opções que parecem adequadas, mas olhando de perto não são: 406 “Not Acceptable” é baseada em cabeçalhos de negociação de conteúdo; 409 “Conflict” é em grande parte voltada a requisições WebDAV; 411, 422 e 431 também são para condições específicas que não têm relação com isso
      Erros da faixa 300 ou 500 também são inadequados. Isso não é realocação nem falha do lado do servidor, e sim problema na requisição do cliente
      O bule ou o URI longo demais parecem os melhores candidatos
    • Claro que suportam. Por exemplo, você pode passar a linha por cima para consultar o nível de água do bule, ou enrolá-la em volta do bule para consultar a circunferência
    • Mas eu não sou um bule. Eu odeio chá
  • Pelo tom deste texto e do texto do Chris, parece que incluir esses parâmetros de query é algo prejudicial, mas eu não entendo como exatamente isso prejudica
    Entendo que pode quebrar algumas URLs, e só isso já é motivo suficiente para não fazer. Ainda assim parece um incômodo pequeno. Alguém pode explicar?

    • Há três perspectivas
      Pela ótica do purismo técnico, modificar uma URL é tecnicamente incorreto, mesmo que por convenção isso seja aceito. URL deve ser tratada basicamente como um valor opaco
      Pela ótica social, é rastreamento, e as threads irmãs de comentários já explicam bem isso, então não vou repetir
      Pela ótica do ruído, isso contribui para esconder aquilo com que o usuário deveria se importar e torna a URL tão difícil e complexa que pessoas comuns deixam de prestar atenção nela
    • Ler sobre os problemas relacionados ao cabeçalho HTTP Referer ajuda a entender por que as pessoas não gostam disso: https://en.wikipedia.org/wiki/HTTP_referer
      Há muitos motivos para você não querer que um site saiba onde você estava antes de chegar até ele. Na prática, é compartilhar seu histórico de navegação com o site que você está visitando
      Por isso o cabeçalho HTTP Referer recebeu muitas atualizações, incluindo restrições sobre quando ele é enviado e recursos para desativá-lo completamente
      Acrescentar a mesma informação como parâmetro de URL contorna essas regras existentes e os mecanismos de recusa. Basta usar o padrão
    • Não há motivo nenhum. É só descartar essa informação
      É uma postura absurdamente extrema, e não explica direito como isso levaria a uma web melhor
    • O interessante é que nenhum desses sites parece ter busca, sendo que busca é um importante recurso de acessibilidade e um caso de uso claro e legítimo para query strings
    • Há alguns motivos. O usuário não consentiu com o rastreamento, e esses parâmetros de query são informações de rastreamento. Além disso, o administrador do site pode não querer que o tráfego de entrada seja rastreado
      O segundo ponto pode ser mais difícil de entender, mas no meu caso eu nunca quero que meus logs tenham informações que possam prejudicar os usuários
      Pessoalmente, odeio quando vou copiar um link para mandar por mensagem e ele vem com um código de rastreamento duas vezes maior que a URL original. Aí eu tenho que apagar tudo manualmente ou deixar a pessoa que recebeu se perguntando o que são aqueles caracteres aleatórios ocupando a tela inteira
      Isso viola a privacidade do usuário, piora a experiência de uso e, acima de tudo, ninguém pediu por isso
  • Como a fonte original ainda não tinha sido discutida no HN, coloquei esse link (https://chrismorgan.info/no-query-strings) no topo e movi o link para o texto-resposta (https://susam.net/no-query-strings.html) para a descrição superior
    Os dois são bons, mas me parece justo dar prioridade ao original

  • Por aqui, a maioria dos sites que ainda usa queries GET é operada por governos locais, em sites de arrecadação de impostos, e eles vão passando variáveis de um lado para o outro depois do login
    Na verdade, me irrita muito mais um parser de roteamento que faz exatamente a mesma coisa que uma requisição GET, mas finge ser uma URL de verdade

  • Query strings são úteis. É o caso de busca de arquivos ou outros tipos de arquivos dinâmicos, mas não deveriam ser anexadas a URLs que não esperam query strings
    Por isso acho correto rejeitar requisições com coisas como UTM anexadas
    Se a query string não era esperada mas está presente, 404 parece a resposta mais sensata, e 400 também pode ser apropriado