É comum a dúvida, para quem tem de desenvolver aplicações web, saber qual é a diferença entre um pedido POST e um pedido GET. E mais importante que isso, qual deveremos utilizar dentro de um formulário de html.
Toda a gente sabe que para enviar dados para o servidor de HTTP se devem de utilizar pedidos POST e para recolher dados do servidor pedidos GET. É esta a mantra.
A diferença reside somente na forma como são enviados os dados para o servidor. Nos pedidos GET a informação é codificada no URL. Enquanto que num método POST a informação é enviada de uma forma mais escondida, no próprio pedido http do browser.
Esta é uma das razões pela qual este método é desencorajado, dado que permite o chamado shoulder surfing. Além disto, algumas codificações de caracteres obrigam, de qualquer forma, a utilizar o método POST.
De acordo com a especificação, os métodos GET devem ser apenas usados para operações que não mudem o estado da aplicação, ou que de outra forma induzam mudanças no sistema. Por exemplo uma query a uma base de dados, é um candidato ideal ao uso deste método.
Isto faz sentido dado que se o utilizador andar para trás na sua história de navegação, ou carregar 'F5' para refrescar a página, nenhum mal deve daí advir dado que o método GET não gera nenhum aviso da parte do browser quando refrescamos a página. Enquanto que se usarmos um método POST e fizermos o mesmo, o browser tem obrigação de avisar o utilizador que vamos voltar a submeter a informação do formulário para o servidor. É claro que, numa aplicação web, devemos certificar-nos que mesmo quando recebemos formulários via métodos POST se verifica se estamos perante uma entrada repetida, ou não.
Se usarmos um sniffer para observar o trafego quando fazemos um pedido via método GET, obtemos qualquer coisa como:
Pedido da página: http://localhost:8000/teste/?variavel1&variavel2=asdasdasd
GET /teste/?variavel1&variavel2=asdasdasd HTTP/1.1 User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.6 (like Gecko) (Kubuntu) Accept: text/html, image/jpeg, image/png, text/*, image/*, */* Accept-Encoding: x-gzip, x-deflate, gzip, deflate Accept-Charset: utf-8, utf-8;q=0.5, *;q=0.5 Accept-Language: en Host: 127.0.0.1:8000 Cookie: sessionid=df82fcf23695423d8bae5bee88a337bb Connection: Keep-Alive
A resposta do servidor é uma página normal:
HTTP/1.0 200 OK Date: Mon, 15 Oct 2007 11:30:03 GMT Server: WSGIServer/0.1 Python/2.5.1 vary: Cookie content-type: text/html; charset=utf-8 [snip...]
Um pedido POST aparece:
POST /formedit/id_4/ HTTP/1.1 User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.6 (like Gecko) (Kubuntu) Referer: http://127.0.0.1:8000/formedit/id_4/ Pragma: no-cache Cache-control: no-cache Accept: text/html, image/jpeg, image/png, text/*, image/*, */* Accept-Encoding: x-gzip, x-deflate, gzip, deflate Accept-Charset: utf-8, utf-8;q=0.5, *;q=0.5 Accept-Language: en Host: 127.0.0.1:8000 Cookie: sessionid=df82fcf23695423d8bae5bee88a337bb Content-Type: application/x-www-form-urlencoded Connection: Keep-Alive Content-Length: 38 mail_address=uytiu%403423423.cv&age=3
Os dados foram codificados no próprio pedido neste caso a variável mail_address e age.
A resposta do servidor vem, neste caso:
HTTP/1.0 302 FOUND Date: Mon, 15 Oct 2007 11:35:13 GMT Server: WSGIServer/0.1 Python/2.5.1 content-type: text/html; charset=utf-8 location: http://127.0.0.1:8000/teste/
Isto é uma directiva de redirecionamento para a página do exemplo do método GET.
É claro que do lado do servidor estes pedidos são tratados de forma diferente, a forma como se tratam estes pedidos já depende do toolkit que estivermos a utilizar.