Cómo enviar solicitudes HTTP en Java

Introducción

El Protocolo de transferencia de hipertexto (HTTP) es un protocolo de capa de aplicación que, sin exagerar, es prácticamente la columna vertebral de la navegación en Internet, tal como la conocemos.
Se utiliza para transferir documentos de hipermedia entre el cliente y el servidor y es una parte esencial de cada aplicación web, incluidas las API que utilizan la arquitectura REST.
Permite que el navegador se comunique con el servidor mediante el envío de solicitudes de ciertos documentos, ya sean documentos HTML (devueltos como las páginas que vemos) o hipermedia (imágenes, videos, etc.) que se muestran en las páginas.

¿Cómo funciona HTTP?

Cuando decidimos visitar un sitio web, lo que sucede detrás de las cortinas es que nuestra computadora genera y envía una solicitud al servidor en el que está alojado el sitio web.
Una solicitud HTTP podría ser algo como esto:
GET /tag/java/ HTTP/1.1  
Host: stackabuse.com  
Accept: */*  
User-Agent: Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion  
Aquí, solicitamos que el servidor devuelva la página bajo la URL stackabuse.com/tag/java/usando HTTP versión 1.1.
Lo que debe responder el servidor es algo como esto:
HTTP/1.1 200 OK  
Date: Fri, 01 Feb 2019 22:07:06 GMT  
Content-Type: text/html; charset=utf-8  
Transfer-Encoding: chunked  
Connection: keep-alive  
Set-Cookie: __cfduid=dd40ff971a6cefddc4855e028541f79581549051234; expires=Sat, 01-Feb-20 22:07:06 GMT; path=/; domain=.stackabuse.com; HttpOnly; Secure  
...
Seguido por el cuerpo de respuesta :
<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title>java - Page 1 - Stack Abuse</title>
    <meta name="description" content="" />
    <meta name="keywords" content="">

<!-- rest of the page -->  
El cuerpo de la respuesta se procesará en nuestro navegador y nos recibe una página.
stackabuse_java
Además del HTTP/1.1 200 OKcódigo de estado que hemos recibido como respuesta, hay muchos otros que probablemente haya encontrado en su vida diaria:
  • 1xx : cualquier estado que comience con '1' es un estado informativo . La solicitud se recibe y se está procesando.
  • 2xx : cualquier estado que comience con '2' significa que la solicitud fue exitosa . La mayoría de las veces es lo 200 OKque simplemente significa que todo salió bien.
  • 3xx : cualquier estado que comience con '3' significa que el usuario debe ser redirigido para finalizar la acción.
  • 4xx : cualquier estado que comience con '4' indica un error del cliente . El más notorio es 404 Not Found, generalmente debido a una mala solicitud o sintaxis. Junto a él, hay 400 Bad Request401 Unauthorized403 ForbiddenEstos códigos de estado son los más comunes y hay una amplia gama de ellos.
  • 5xx : cualquier estado que comience con '5' indica un error del servidor .
La lista completa de códigos de estado HTTP es bastante larga, aunque no es una mala idea revisarla.

Enviando solicitudes con HttpURLConnection

HttpURLConnection es la clase principal de Java para manejar solicitudes y respuestas HTTP.
El uso HttpURLConnectionestá perfectamente bien para solicitudes HTTP simples, aunque si desea agregar más fácilmente elementos como encabezados o autenticación, le resultará más fácil confiar en otras bibliotecas como Apache Commons.
La forma más sencilla de crear una instancia del HttpURLConnectionobjeto es utilizar el URLobjeto:
URL url = new URL("https://www.stackabuse.com");  
HttpURLConnection connection = (HttpURLConnection) url.openConnection();  

Tipos de solicitud

Ahora que nuestra HttpURLConnectioninstancia existe, podemos definir un tipo de solicitud HTTP para ella:
// For a GET request
connection.setRequestMethod("GET");

// For a POST request
connection.setRequestMethod("POST");

// For a HEAD request
connection.setRequestMethod("HEAD");

// For a OPTIONS request
connection.setRequestMethod("OPTIONS");

// For a PUT request
connection.setRequestMethod("PUT");

// For a DELETE request
connection.setRequestMethod("DELETE");

// For a TRACE request
connection.setRequestMethod("TRACE");  
Sin embargo, en la mayoría de los casos solo usará GET , POST y DELETE .

Parámetros de solicitud

En algunos casos, nos gustaría enviar una solicitud HTTP con ciertos parámetros de consulta, como www.youtube.com/watch?v=dQw4w9WgXcQ.
Para lograr esto, generalmente se nos ocurre una manera de emparejar estos valores. A veces, las personas definen sus propias clases para mantener estos valores, aunque un simple HashMaplo hará bien:
Map<String, String> params = new HashMap<>();  
params.put("v", "dQw4w9WgXcQ");  
Ahora que tenemos nuestros parámetros asignados, necesitamos hacer un par de cosas para prepararlos para nuestra solicitud:
  • Genera el parámetro en un formato de tipo cadena. Lo usaremos StringBuilderya que es ideal para la concatenación que realizaremos
  • Utilice la clase URLEncoder para codificar nuestros parámetros
  • Convierta los datos en bytes, ya DataOutputStreamque nuestro que activa la solicitud espera una matriz de tipobyte
Nota : si no está seguro por qué necesitamos codificar nuestra URL, es porque ciertos caracteres pueden tener un significado especial dentro de las URL. Caracteres como "/", ".", "#" Y "?" puede alterar la solicitud, por lo que si están presentes debemos codificarlos de manera que no afecte la forma en que se interpreta la URL.
Vamos a implementar los elementos de la lista:
// Instantiate a requestData object to store our data
StringBuilder requestData = new StringBuilder();

for (Map.Entry<String, String> param : params.entrySet()) {  
    if (requestData.length() != 0) {
        requestData.append('&');
    }
    // Encode the parameter based on the parameter map we've defined
    // and append the values from the map to form a single parameter
    requestData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
    requestData.append('=');
    requestData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
}

// Convert the requestData into bytes 
byte[] requestDataByes = requestData.toString().getBytes("UTF-8");  
Y así, nuestro parámetro está listo para ser utilizado en la solicitud.

Encabezados de solicitud

Si desea agregar un encabezado a una solicitud, es tan fácil como:
connection.setRequestProperty("Content-Type", "application/json");  
connection.setRequestProperty("Content-Length", String.valueOf(requestDataBytes.length));  
Y si desea leer un encabezado de una solicitud:
String contentType = connection.getHeaderField("Content-Type");  

Tiempos de espera

Otra característica que HttpURLConnectionofrece es establecer tiempos de espera . Podemos definir intervalos de tiempo de espera para leer o conectar:
connection.setConnectTimeout(10000);  
connection.setReadTimeout(10000);  
Los intervalos se definen, como es habitual, en milisegundos.
Entonces, por ejemplo, la conexión expirará si no puede establecerse en 10 segundos. Del mismo modo, también se agotará el tiempo de espera si no se pueden leer los datos de la conexión en 10 segundos.

Solicitud POST

Con nuestra solicitud preparada, podemos continuar y disparar la solicitud POST :
// Set the doOutput flag to true
connection.setDoOutput(true);

// Get the output stream of the connection instance
// and add the parameter to the request
try (DataOutputStream writer = new DataOutputStream(connection.getOutputStream())) {  
    writer.write(postDataBytes);

    // Always flush and close
    writer.flush();
    writer.close();
}
Aquí estamos enviando postDataBytesnuestra solicitud POST , que es una matriz de bytes. Echa un vistazo a la demostración a continuación para obtener más detalles sobre cómo generar esto.

Solicitud GET

Una vez que enviamos una solicitud POST , normalmente queremos hacer algo para (o al menos ver) la respuesta.
Las solicitudes GET solo están destinadas a recuperar datos, así que sigamos adelante y obtengamos una respuesta:
// To store our response
StringBuilder content;

// Get the input stream of the connection
try (BufferedReader input = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {  
    String line;
    content = new StringBuilder();
    while ((line = input.readLine()) != null) {
        // Append each line of the response and separate them
        content.append(line);
        content.append(System.lineSeparator());
    }
} finally {
    connection.disconnect();
}

// Output the content to the console
System.out.println(content.toString());  
Podemos extraer muchos tipos diferentes de información desde connectioneste punto:
// Returns the value of the content-type header field
connection.getContentType();

// Returns an unmodifiable Map of the header fields
connection.getHeaderFields();

// Gets the status code from an HTTP response message
connection.getResponseCode();

// Gets the HTTP response message returned along with the response code from a server
connection.getResponseMessage();

// Returns the error stream if the connection failed but the server sent useful data nonetheless
connection.getErrorStream();

// ...etc

Manifestación

Aquí es cómo una aplicación muy simple generaría una solicitud POST , la enviará y luego leerá la respuesta:
public static void main(String[] args) throws MalformedURLException, ProtocolException, IOException {  
    URL url = new URL("https://www.youtube.com");
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();

    connection.setRequestMethod("POST");
    Map<String, String> params = new HashMap<>();
    params.put("v", "dQw4w9WgXcQ");

    StringBuilder postData = new StringBuilder();
    for (Map.Entry<String, String> param : params.entrySet()) {
        if (postData.length() != 0) {
            postData.append('&');
        }
        postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
        postData.append('=');
        postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
    }

    byte[] postDataBytes = postData.toString().getBytes("UTF-8");
    connection.setDoOutput(true);
    try (DataOutputStream writer = new DataOutputStream(connection.getOutputStream())) {
        writer.write(postDataBytes);
        writer.flush();
        writer.close();

        StringBuilder content;

        try (BufferedReader in = new BufferedReader(
                new InputStreamReader(connection.getInputStream()))) {
        String line;
        content = new StringBuilder();
           while ((line = in.readLine()) != null) {
                content.append(line);
                content.append(System.lineSeparator());
            }
        }
        System.out.println(content.toString());
    } finally {
        connection.disconnect();
    }
}
La ejecución de este fragmento de código seguramente proporciona el código fuente de la página que especificamos para obtener:
<!DOCTYPE html>  
<html lang="sr" data-cast-api-enabled="true">  
<head>  
<!-- rest of the page -->  

Conclusión

El Protocolo de transferencia de hipertexto (HTTP) es un protocolo de capa de aplicación que, sin exagerar, es un componente muy grande y crítico para las aplicaciones de Internet.
HttpURLConnection es la clase principal de Java para el manejo de solicitudes y respuestas HTTP.
El uso HttpURLConnectiones perfectamente adecuado para solicitudes HTTP simples, aunque si desea crear solicitudes HTTP más complejas con encabezados o autenticación, tendrá una experiencia mucho más sencilla con bibliotecas como Apache Commons.

Acerca de: Programator

Somos Instinto Programador

0 comentarios:

Publicar un comentario

Dejanos tu comentario para seguir mejorando!

Con tecnología de Blogger.