HTTP Client – Requisições GET e POST com API JAVA

Neste turorial iremos utilizar o API HTTP Client presente no pacote java.net.http. Dando continuidade ao nosso tema de protocolo de comunicação HTTP, iremos utilizar a linguagem de programação Java para criar requisições HTTP.

English version: Click

Os demais artigos sobre o tema estão listados ao final deste artigo.

HTTP Client

A API HTTP Client possui quatro classes associadas: HttpClient, HttpRequest, HttpResponse e WebSocket.

Podemos intuir o papel de cada classe apenas pelo seu nome. Neste exemplo serão apresentados códigos de envio de requisições a sites existentes na internet.

Dessa forma, estaremos utilizando as classes HttpClient e HttpRequest.

Abaixo, estão listadas as interfaces e classes Java a API.

interfaces e classes Java a API
interfaces e classes Java a API
interfaces e classes Java a API 2
interfaces e classes Java a API 2

A operação do HTTP Client é definido pelas versões do protocolo HTTP – HyperText Transfer Protocol, 2.0 e 1.1 – artigo do site sobre HTTP.

Relembrando, as mensagens HTTP são do tipo response e request. Dessa forma, iremos aplicar o conhecimento com requests utilizando os métodos GET e POST.

Por que apenas estes métodos, se há tantos? Então, apesar de haver diversos métodos com funções distintas os mais utilizados são os supracitados.

Na verdade, o método GET concentra a maior porcentagem de requisições HTTP.

Livros Indicados:

E-Books de Redes e Segurança

Começando a programar

Abra sua IDE e crie um projeto Java, vá em arquivo novo projeto. Neste tutorial, estaremos utilizando a IDE Intellij.

Contudo, os mesmos passos são aplicados a qualquer outra IDE. Podendo haver variações na interface.

Uma vez que tenha selecionado novo projeto, uma janela similar a abaixo aparecerá. Selecione Java e a versão do JDK que será utilizada.

Ok, agora criaremos as classes para efetuar a requisição. Primeiro, vamos pensar sobre o assunto…

Precisamos de um cliente para efetuar a requisição, assim como a url de destino. Então, os passos para criar nosso primeiro programa são:

  • Criar o cliente HTTP
  • Criar a requisição e definir seus parâmetros
  • Enviar a solicitação a url destino
  • Imprimir o conteúdo da mensagem response em tela

Como serão utilizados dois exemplos, criaremos duas classes em nosso projeto. A primeira denominada getRequest e a segunda postRequest.

Na imagem abaixo, definimos nossas classes dentro do pacote com.httpexamples. O nome do pacote é definido por você.

Contudo, o ideal é que ele represente bem seu programa.

HTTP Client – Get Request

Vamos começar pelo primeiro exemplo. Relembrando, o método GET solicita ao servior os objetos web relacionados a um determinado recurso (ou url).

A própria página em si é um objeto web. Para relembrar conceitos teóricos de HTTP acesso o “Protocolo HTTP – Como funciona?“.

Então definiremos a url alvo de nossas requisições GET HTTP.

public static final String URL_GET = "http://httpbin.org/get";

Esta url está sendo definida como uma constante do tipo string.

Utilizamos os modificadores de acesso para definir que a constante pode ser utilizada dentro do programa como public; mantendo o seu valor para qualquer uso dela com static; e não permitindo modificações através do final.

Cliente HTTP

Ok, agora iremos definir as configurações do cliente.

Para isso, utilizaremos o método newHttpClient que retorna um cliente HTTP com as configuração padrão. A configuração padrão inclui:

“o método de solicitação “GET”, uma preferência de HTTP / 2, uma política de redirecionamento de NUNCA, o seletor de proxy padrão e o contexto SSL padrão.”

// cliente HTTP
HttpClient client = HttpClient.newHttpClient();

Criando a requisição

// criar a requisição
HttpRequest request = HttpRequest.newBuilder()
          .GET()
          .timeout(Duration.ofSeconds(10))
          .uri(URI.create(URL_GET))
          .build();

Note que criamos uma variável do tipo HttpRequest. Nesta variável iremos definir os parâmetros de nossa requisição.

Observe que definir o método GET(), o time out da mensagem, a URL de destino. Dessa forma, para construir a requisiação finalizamos com .build();

Enviando a requisição

Uma vez que a requisição foi criada, a mesma deve ser enviada.

Dessa forma, nossa var client (do tipo HttClient) irá enviar através do método send() a requisição criada anteriormente.

// enviando uma solicitação

HttpResponse<String> response = client.send(request,HttpResponse.BodyHandlers.ofString());

Devemos prover dois parâmetros para o método send.

O primeiro, a requisição que será enviada, o segundo trata-se de um BodyHandlers. Neste caso, será tratada como string.

Esse método ainda bloqueia o programa enquanto ocorre o envio da requisição e consequentemente o recebimento do response.

Para criar um envio assíncro utilize o método sendAsync(HttpRequest, BodyHandler).

Toda a informação recebida, decorrente do envio da mensagem HTTP será armazenada na variável response do tipo HttpReponse.

Neste caso, estamos definindo o formato do conteúdo como String.

Imprimindo conteúdo recebido

Para verificar o conteúdo basta printar os atributos relacionados ao response. Aqui estamos imprimindo na tela o status code e o campo do pacote HTTP.

//imprimir o conteúdo recebido
System.out.println(response.statusCode());
System.out.println(response.body());

Após construir o programa e rodar, uma janela similar a presente abaixo deverá ser exibida em sua tela.

Perceba que o status code é o 200, ou seja, 200 OK (requisição respondida com sucesso).

Posteriormente, o payload da mensagem e impresso em tela.

Podemos observar algumas propriedades da mensagem, como: tamanho do conteúdo, host, agente que realizou a requisição, o IP público e url.

Pronto, você acabou de criar sua primeira requisição em Java com HTTP Client. O código completo está no github.

HTTP Client – POST Request

Partindo para o segundo exemplo, utilizaremos uma requisição com método POST. Relembrando, o método POST submete o conteúdo do payload ao servidor.

Esse tipo de método é mandatório, o que significa que o servidor é obrigado a tratar o conteúdo do pacote.

Definindo url e payload

Você perceberá que não são todos os sites que aceitam as requisições POST. No decorrer do artigo explicarei melhor o assunto.

Continuando, definiremos a url alvo de nossas requisições POST HTTP.

public static final String URL_POST = "http://httpbin.org/forms/post";

Como estamos lidando com método POST, devemos enviar algum conteúdo no payload da mensagem.

Neste caso, iremos enviar um documento no formato JSON. Nele estão contidas informações para preenchimento de um formulário.

O conteúdo desse arquivo está exposto na figura abaixo.

 public static final String FILE_JSON = "/home/jm/IdeaProjects/HttpExample/pedido.json";

No código em Java a definição das duas constantes permanecem como segue.

HTTP Client

Uma vez definidas as urls, iremos prosseguir o conforme exemplo anterior. Primeiramente criamos o cliente através do método newHttpClient().

 // cliente HTTP
 HttpClient client = HttpClient.newHttpClient();

POST Request

O próximo passo será criar a requisição com método POST inserido.

Aqui aparece a diferença principal na definição de parâmetros, o payload. Diferentemente de mensagens com método GET, o métod POST precisa enviar algo em seu payload.

O motivo é justamente a função do método, submeter ao servidor algum conteúdo que deverá ser tratado.

// criar a requisição
HttpRequest request = HttpRequest.newBuilder()
         .POST(HttpRequest.BodyPublishers.ofFile(Path.of(FILE_JSON)))
         .timeout(Duration.ofSeconds(10))
         .uri(URI.create(URL_POST))
         .build();

Através do método BodyPublisher.ofFile enviamos o conteúdo a partir de um arquivo. Dessa forma, utilizados Path.of ara definir qual arquivo será utilizado.

Como o arquivo está no memso diretório não há necessidade de especificar todo o caminho.

Similarmente ao primeiro exemplo, definimos apenas as features timeout, e a url.

Enviando o request

No exemplo anterior realizarmos uma comunicação síncrona. Isso significa que bloqueamos o programa enquanto não recebemos a resposta.

Neste caso, estamos lidando com uma comunicação assíncrona. Por que isso? O servidor preciso receber e processar o conteúdo antes de responder.

Dessa forma, o código fica como descrito abaixo:

client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
        .thenApply(HttpResponse::body)
        .thenAccept(System.out::println)
        .join();

Novamente utilizaremos o BodyHandlers, definindo que a resposta deve ser tratada como String.

Então a resposta deve ser aplicada como corpo da mensagem (thenApply(HttpResponse::body).

Assim, ela poderá ser impressa em tela. Esse são os parâmetros da Request. Uma vez que os parâmetros foram definidos setamos o .join() para estabelecer a conexão.

O resultado deste programa segue abaixo.

Resultado da requisição Post

Vamos olhar mais de perto… O status code da mensagem está descrito como 405 Method Not Allowed.

Você lembra que comentei da obrigatóriedade do servidor tratar o conteúdo do payload.

Eu poderia ter adicionado qualquer tipo de conteúdo, desde imagem, arquivos, ou até mesmo programas maliciosos como Trojans.

Pensando melhor, um servidor que permita esse tipo de solicitação possui uma vulnerabilidade.

OK… Mas como o lado do servidor define qual solicitação ele irá bloquear? Uma das informações dentro de pacotes HTTP está associada ao agente requisitor da ação.

Analisando o resultado

Vamos adicionar uma linha ao nosso código para verificar essa questão.

A variável request possui métodos atrelados a classe que ela pertence.

Dessa forma, podemos imprimir o status code, uri, ou outro parâmetro associado a ela. Neste caso, o que nos interessa é o bodyPublisher().

O BodyPublisher irá retornar o agente que realizou a requisição HTTP. Assim, na imagem a seguir podemos verificar que o agente esta especificado como:

Optional[jdk.internal.net.http.RequestPublishers$FilePublisher@31ef45e3]

Caso o formulário seja preenchido pela interface web, o agente está associado a ela. Isso significa que só poderam ser anexados tipos de dados permitidos pela API web.

Dessa forma, temos um ambiente controlado que não permite envio de arquivos duvidosos.

Em nosso exemplo podemos perceber que o agente trata-se de um jdk (Java), utilizando a API net.http para realizar a requisição.

Portanto, como o servidor não permite outra interação, via POST, com outro agente além da web a requisição é recusada.

Como seria um caso prático com o POST, precisariamos de acesso a um servidor web que permite solicitações via agente Java.

Você pode implementar ou procurar na internet algum com esse quesito. Contudo, como informei isso irá acarretar em vulnerabilidade.

Sendo assim, a probabilidade de encontrar tal site é baixa.

Código completo

Abaixo estão os programas com o código completo utilizados no tutorial.

Juliana Mascarenhas

Data Scientist and Master in Computer Modeling by LNCC.
Computer Engineer

Artigos relacionados

Simplificando Redes nas redes sociais