Com códigos em HTML e PHP podemos ver algumas diferenças básicas entre os métodos POST e GET quando submetemos um formulário HTTP/HTTPS.
Basicamente o que se sabe é que o GET envia os parâmetros como string da requisição HTTP sendo que os mesmos aparecem no URI (Uniform Resource Identifier - Identificador Uniforme de Recurso, grosso modo, aquela sequência de caracteres que se digita na barra de endereços do navegador).
O POST encapsula os parâmetros junto ao corpo da requisição HTTP(S) não podendo serem visualizados.
Para fins de entendimento, "Solicitação" é o URI, é a sequência completa de caracteres e "Requisição" é a Request-URI. A Request-URI está dentro do URI e a query string está dentro da Request-URI.
No exemplo abaixo o URI é a linha inteira:
https://www.vivaolinux.com.br/busca/?cx=partner-pub-3535276187000580%3A4725058203&cof=FORID%3A10&ie=ISO-8859-1&q=Buckminster
A Request-URI é a parte:
/busca/?cx=partner-pub-3535276187000580%3A4725058203&cof=FORID%3A10&ie=ISO-8859-1&q=Buckminster
A query string é a parte após o sinal de interrogação:
cx=partner-pub-3535276187000580%3A4725058203&cof=FORID%3A10&ie=ISO-8859-1&q=Buckminster
Na RFC 9110 de 2022, a mais atual sobre o protocolo HTTP, link nas referências, na seção "18.2. Method Registration", encontramos todos os métodos de requisição, mas nos deteremos no POST e no GET:
"O método POST é usado para solicitar que o servidor de destino aceite a entidade incluída na solicitação como novo subordinado do recurso identificado pela Request-URI na Request-Line.
O POST foi projetado para permitir um método uniforme para cobrir as seguintes funções:
- Anotação de recursos existentes;
- Publicar uma mensagem em um quadro de avisos, grupo de notícias, lista de discussão ou grupo similar de artigos;
- Fornecer um bloco de dados, como o resultado do envio de um formulário, para um processo de tratamento de dados;
- Estendendo um banco de dados através de uma operação de acréscimo.
O método GET significa recuperar qualquer informação (na forma de uma entidade) identificada pela Request-URI.
Se a Request-URI se referir a um processo de produção de dados, são os dados produzidos que devem ser retornados como a entidade na resposta e não o texto fonte do processo, a menos que esse texto seja a saída do processo."
O POST é geralmente utilizado para enviar dados para o servidor, para atualizar ou criar um novo recurso.
Uma solicitação POST geralmente é enviada por meio de um formulário HTML e resulta em uma alteração no servidor.
O Google utiliza bastante o GET na sua busca, pois as informações não contém senhas e/ou outros dados que devam ser confidenciais, aliás, essa é uma diferença básica entre GET e POST, além do que o GET é mais rápido e isso faz uma grande diferença para o Google que lida com um volume gigantesco de dados.
Deve-se usar o GET em praticamente toda requisição que não envolva informações confidenciais que não devam aparecer na barra de endereços (URI).
A query string é aquela parte do URI que vem depois de um ponto de interrogação seguida de uma sequência de caracteres e contém pares de chave-valor.
Para fins de entendimento, "Solicitação" é o URI, é a sequência completa de caracteres e "Requisição" é a Request-URI. A Request-URI está dentro do URI e a query string está dentro da Request-URI.
Por enviar os dados no cabeçalho da requisição o GET tem um limite máximo de dados a serem enviados, geralmente esse limite é definido pelo número de caracteres da string de requisição, alguns afirmam que o limite é 255 caracteres, outros que o limite do GET é 1024, outros dizem que é 2048, porém, esse limite varia de acordo com as configurações da linguagem utilizada, do servidor web utilizado (Apache, Nginx, IIS, etc), contudo, se tentarmos passar uma grande quantidade de informações via GET algumas partes podem ser perdidas no caminho, lembrando que o GET só aceita caracteres ASCII, grosso modo, somente texto.
TESTE EM NAVEGADORES
Copiando o conteúdo de um arquivo texto com caracteres aleatórios, usando Notepadqq no
Linux, Notepad++ no Windows e no macOS o editor de texto padrão do Mac, fui colando na barra de endereços do Edge, do Chrome, do Firefox, do Ópera e do Safari (macOS), sendo que aumentava o conteúdo do arquivo na medida que o navegador aceitava o conteúdo aumentado.
Depois copiava da barra de endereços e colava em um arquivo em branco para ver a quantidade de caracteres exibidos.
Talvez esses números variam de acordo com o sistema operacional e outros fatores como a codificação do servidor, etc, porém, as configurações estando nos padrões, a variação será de poucos caracteres podendo ser desconsiderada para este teste.
OS testes foram feitos em dois lugares diferentes com bandas de internet diferentes e sistemas operacionais diferentes.
O Edge aceitou 62.877 caracteres, mas ao solicitar (dar enter) exibiu a mensagem "404. That's an error The requested URL ... was not found on this server.", o que é óbvio.
O Chrome a mesma coisa.
O Ópera aceitou 26.934 caracteres e ao solicitar (dar enter) apresentava a mensagem "404.. not found", o que é óbvio, e foi o único que travou quando ultrapassava o limite, sendo que ao colar com o limite excedido na barra de endereços travava e voltava com a mensagem "O Ópera se recuperou de uma falha...", ou seja, nem deixava colar e quando estava dentro do limite apresentava a mensagem de erro 400 "... malformed or illegal request".
O Safari apresentava a mensagem "O Safari não pode abrir a página", o que é óbvio.
O Safari exibe na barra de endereços 6.370 caracteres, porém, aceita 253.864 caracteres (ou mais).
Os limites que encontrei são os seguintes:
- Edge: aceita 62.877 caracteres, exibe 10.104;
- Chrome: aceita 62.877 caracteres, exibe 10.115;
- Firefox: 61.960 caracteres, exibe 31.733;
- Ópera: 26.934 caracteres, exibe 10.231;
- Safari: 253.864 caracteres (o Safari provavelmente aceita mais caracteres, pois parei de testar nesse limite), exibe 6.370.
Com exceção do Ópera, quando excedia o limite apresentavam a mensagem de erro 413, por exemplo, no Chrome:
413. That's an error.
Your client issued a request that was too large. That's all we know.
Deixo bem claro que esses limites não representam exatamente os limites do GET, pois tem outros fatores envolvidos, mas dão uma boa idéia.
Para fins de informação, nesta mesma RFC 9110 na seção "18.3. Status Code Registration" (link nas referências) tem todos os códigos 1XX, 2XX, 3XX, 4XX e 5XX.
A RFC 9110 de 2022, "HTTP Semantics", não especifica nenhum requisito para o comprimento do URI.
"5.4. Field Limits
HTTP does not place a predefined limit on the length of each field line, field value, or on the length of a header or trailer section as a whole, as described in Section 2. Various ad hoc limitations on individual lengths are found in practice, often depending on the specific field's semantics.
A server that receives a request header field line, field value, or set of fields larger than it wishes to process MUST respond with an appropriate 4xx (Client Error) status code. Ignoring such header fields would increase the server's vulnerability to request smuggling attacks (Section 11.2 of [HTTP/1.1]).
A client MAY discard or truncate received field lines that are larger than the client wishes to process if the field semantics are such that the dropped value(s) can be safely ignored without changing the message framing or response semantics.
Na seção 4.1, diz:
"É RECOMENDADO que todos os remetentes e destinatários suportem, no mínimo, URIs com comprimento de 8.000 octetos em elementos de protocolo. Observe que isso implica que algumas estruturas e representações on-wire (por exemplo, a linha de solicitação em HTTP/1.1) serão necessariamente maiores em alguns casos."
Está bem claro que o tamanho do URI e, por conseguinte, da Request-URI, é limitado pelo navegador e/ou pelo servidor web utilizado, sendo que não pode ser diferente.
Sugestões que posso dar:
Caso você for um programador, usar URIs extremamente longos geralmente são um erro. Mantendo os URIs com menos de 2.000 caracteres, funcionará em praticamente qualquer combinação de software cliente e servidor.
Com GET o tamanho máximo da solicitação depende do lado do servidor e também do lado do cliente (no caso, o navegador). Use 2.000 caracteres ou menos para o GET; caso necessitar aumentar esse limite e tenha que usar o GET, aumente para um máximo de 8.000 caracteres, como sugerido na RFC (8.000 octetos), lembrando que 1 Byte tem oito bits (um octeto) e para formar um caractere é necessário 1 Byte, então 8.000 octetos são 8.000 mil caracteres.
Porém, para solicitações maiores de 2.000 caracteres prefira usar o POST.
Tanto com GET quanto com POST, geralmente quando o URI é muito longo o servidor responde com um erro "413 Entity Too Large" e a solicitação falha.
Essa resposta do servidor é preferível a encurtar o URI, porque os resultados do encurtamento do URI são imprevisíveis, então é melhor que a solicitação falhe.
Antigamente, alguns servidores e navegadores da Web não conseguiam truncar ou ignorar URIs longos resultando em situações perigosas de "buffer overflow", sendo que eram usados para inserir código executável resultando em uma falha de segurança que poderia ser explorada para malwares.
Hoje em dia, os principais navegadores e servidores estão seguros contra esses ataques óbvios - embora falhas de segurança mais sutis sejam frequentemente descobertas e, geralmente, prontamente corrigidas.
E, como vimos nos testes, o tamanho permitido de caracteres na barra de endereços nos navegadores é bastante generoso.
Por POST o limite padrão na maioria dos servidores geralmente é 4GB, então não tem muito com o que se preocupar. No form coloque <... method="post" enctype="multipart/form-data"> caso o formulário tiver arquivos para upload ou somente method="post" deixando no padrão "application/x-www-form-urlencoded" que é quando se omite a tag enctype.
Caso for aceitar uploads de vídeos, por exemplo, ou arquivos ISOs ou arquivos de qualquer tipo maiores do que 4GB então você deve usar POST e deve ajustar as configurações do servidor.
Alguns navegadores limitam o comprimento do URI por motivos práticos e para evitar causar problemas de negação de serviço na comunicação entre processos.
Caso exceder o comprimento máximo da solicitação, ela será truncada fora do limite pelo servidor web ou navegador sem qualquer aviso, sendo que alguns servidores retornarão com o código de resposta 414.
O servidor web Apache, por exemplo, limita por padrão em 4.000 caracteres.
Dependendo do navegador, quando exceder o limite a página exibe um erro ou não exibe mais o URI.
Pode-se aumentar o tamanho da requisição GET, mas, para tanto, terá de mexer nas configurações da linguagem utilizada, do servidor web (Apache, Nginx, IIS, etc) e no código fonte deverá ser configurado e/ou burlado o limite imposto pelo navegador.
Lembrando que o tamanho do URI é uma coisa e o tamanho da Request-URI é outra. A Request-URI é uma parte do URI.
Lembrando que é melhor chamar de URI e não de URL quando nos referimos ao que é digitado na barra de endereços do navegador, apesar de que todo mundo chama de URL.
Com POST, podemos enviar quantidades de dados maiores, como imagens. Em teoria uma requisição POST é ilimitada, sendo necessária uma conexão paralela para envio das informações. Geralmente o tamanho máximo padrão configurado são 4GB para requisições HTTP.
Em questão de segurança, a maneira correta de garantir segurança é utilizar HTTPS e atualizar para a versão 2 do HTTP (HTTP/2), pois tanto o POST quanto o GET tecnicamente oferecem o mesmo grau de segurança se não levarmos em conta a peça entre a cadeira e o teclado.
O GET é mais rápido do que o POST.
O método GET também é mais útil quando se recarrega ou abre uma página para pegar informações que se precisa deixar visíveis na tela, como, por exemplo, em um formulário pré-preenchido.
A requisição GET pode ser armazenada em cache, a POST não, o que significa que quando você quiser que sua página seja favoritada no navegador, utilize o GET; com POST, obviamente, a página será favoritada também, mas o navegador não guardará no cache.
O POST utiliza o método Heap para passar as variáveis de formulário.
O GET utiliza o método Stack para passar as variáveis de formulário.
"Se você está solicitando uma imagem no código ou se precisa de um URL com mais de 2.000 caracteres, é necessário enviar sua solicitação de imagem usando HTTP POST. O servidor de infográficos é compatível com solicitações HTTP POST de até 16K."
Referência:
Solicitações POST | Infographics | Google for Developers
Na seção "Conclusão" tem um compilado do artigo.
Vamos aos códigos na próxima seção.