C贸mo enviar solicitudes HTTP en Java

    Introducci贸n

    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 por Internet tal como la conocemos.

    Se utiliza para transferir documentos 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 enviando solicitudes de ciertos documentos, ya sean documentos HTML (devueltos como las p谩ginas que vemos) o los hipermedia (im谩genes, videos, etc.) que se sirven 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 verse as铆:

    GET /tag/java/ HTTP/1.1
    Host: Pharos.sh.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 Pharos.sh.com/tag/java/ utilizando HTTP versi贸n 1.1.

    Lo que el servidor deber铆a responder 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=.Pharos.sh.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 隆recibiremos una p谩gina!

    junto al HTTP/1.1 200 OK c贸digo de estado que hemos recibido como respuesta, hay varios 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 200 OK lo que 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 solicitud o sintaxis incorrecta. Junto a 茅l, hay 400 Bad Request, 401 Unauthorized y 403 Forbidden. Estos c贸digos de estado son los m谩s comunes y hay una amplia variedad de ellos.
    • 5xx: Cualquier estado que comience con ‘5’ indica un error del servidor.

    los lista completa de c贸digos de estado HTTP es bastante largo, aunque no es mala idea repasarlo.

    Env铆o de solicitudes con HttpURLConnection

    HttpURLConnection es la clase principal de Java para manejar solicitudes y respuestas HTTP.

    Utilizando HttpURLConnection est谩 perfectamente bien para solicitudes HTTP simples, aunque si desea agregar m谩s f谩cilmente cosas como encabezados o autenticaci贸n, le resultar谩 m谩s f谩cil confiar en otras bibliotecas como Apache Commons.

    La forma m谩s sencilla de instanciar el HttpURLConnection el objeto est谩 usando el URL objeto:

    URL url = new URL("https://www.Pharos.sh.com");
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    

    Tipos de solicitud

    Ahora que nuestro HttpURLConnection existe una instancia, 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.

    Solicitar par谩metros

    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, normalmente se nos ocurre una forma de emparejar estos valores. A veces, las personas definen sus propias clases para mantener estos valores, aunque una simple HashMap lo 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:

    • Genere el par谩metro en un formato similar a una cadena. Estaremos usando StringBuilder ya que es ideal para la concatenaci贸n que realizaremos
    • Utilizar el URLEncoder clase para codificar nuestros par谩metros
    • Convierta los datos en bytes, como nuestro DataOutputStream que dispara la solicitud espera una matriz de tipo byte

    Nota: Si no est谩 seguro de por qu茅 necesitamos codificar nuestra URL, es porque ciertos caracteres pueden tener un significado especial dentro de las URL. Personajes como “/”, “.”, “#”y “?” puede alterar la solicitud, por lo que, si est谩n presentes, debemos codificarlos de una manera que no afecte la forma en que se interpreta la URL.

    Implementemos 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.

    Solicitar encabezados

    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 HttpURLConnection ofertas est谩 estableciendo tiempos muertos. Podemos definir intervalos de tiempo de espera para leer o conectarse:

    connection.setConnectTimeout(10000);
    connection.setReadTimeout(10000);
    

    Los intervalos, como de costumbre, se definen en milisegundos.

    Entonces, por ejemplo, la conexi贸n expirar谩 si no se puede establecer 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 configurada, 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 postDataBytes en nuestra solicitud POST, que es una matriz de bytes. Consulte la demostraci贸n a continuaci贸n para obtener m谩s detalles sobre c贸mo generar esto.

    OBTENER Solicitud

    Una vez que enviamos una solicitud POST, normalmente querr铆amos 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 del connection en este 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

    As铆 es como una aplicaci贸n muy simple generar铆a una solicitud POST, la enviar铆a y luego leer铆a 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();
        }
    }
    

    Ejecutar este fragmento de c贸digo seguramente produce 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

    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 manejar solicitudes y respuestas HTTP.

    Utilizando HttpURLConnection est谩 perfectamente bien para solicitudes HTTP simples, aunque si desea crear solicitudes HTTP m谩s complejas con encabezados o autenticaci贸n, tendr谩 una experiencia mucho m谩s simple con bibliotecas como Apache Commons.

     

    Etiquetas:

    Deja una respuesta

    Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *