W3docs

Java HttpURLConnection

Realiza solicitudes HTTP en Java con la API heredada HttpURLConnection.

HttpURLConnection es la subclase de URLConnection con conocimiento de HTTP. Cuando llamas a openConnection() sobre una URL http: o https:, el objeto que obtienes de vuelta es un HttpURLConnection — conviértelo con cast para acceder a las funciones específicas de HTTP: configurar el método de la solicitud, leer el código de estado y obtener el flujo de error separado. Es el cliente HTTP original del JDK, disponible desde Java 1.1.

Este capítulo cubre cómo hacer el cast de la conexión y elegir un método, enviar un cuerpo de solicitud, el código de estado y los dos flujos de respuesta (la trampa clásica del flujo de error), y un ejemplo completo de un ciclo POST que puedes ejecutar.

Nota moderna: para código nuevo, prefiere java.net.http.HttpClient — es más limpio, soporta HTTP/2 y maneja la asincronía. HttpURLConnection sigue estando en todas partes en bases de código antiguas, por lo que vale la pena conocerlo bien.

Cast y elección del método

URL url = URI.create("http://example.com/api").toURL();
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");                       // GET is the default
conn.setRequestProperty("Content-Type", "application/json");
conn.setConnectTimeout(2000);
conn.setReadTimeout(2000);

setRequestMethod acepta "GET", "POST", "PUT", "DELETE", etc. Añade encabezados de solicitud con setRequestProperty.

Envío de un cuerpo de solicitud

Para enviar un cuerpo debes activarlo con setDoOutput(true) (lo que también hace que el método predeterminado sea POST), y luego escribir en el flujo de salida:

conn.setDoOutput(true);
try (OutputStream os = conn.getOutputStream()) {
    os.write(payload.getBytes(StandardCharsets.UTF_8));
}

Código de estado y los dos flujos

La característica HTTP definitoria es el código de estado, y la trampa que se deriva de ella:

int code = conn.getResponseCode();          // triggers the request
InputStream body = (code >= 200 && code < 400)
        ? conn.getInputStream()             // success body
        : conn.getErrorStream();            // error body (4xx/5xx)

getInputStream() lanza IOException en una respuesta 4xx/5xx. El cuerpo de error vive en un flujo diferente, getErrorStream(). Olvidar esto es el bug clásico de HttpURLConnection: una respuesta de error falla en lugar de permitirte leer la explicación del servidor. Siempre evalúa primero getResponseCode(). Termina con conn.disconnect().

Un ejemplo completo: un ciclo POST

Este programa ejecuta un servidor de loopback que devuelve el cuerpo de la solicitud con un 201 Created, luego realiza un POST mediante HttpURLConnection: configura el método, escribe un cuerpo, lee el estado y elige el flujo correcto.

java— editable, runs on the server

Lo que se puede extraer de la ejecución:

  • Hacer el cast de URLConnection a HttpURLConnection desbloqueó la capa HTTP: setRequestMethod("POST"), getResponseCode() y getResponseMessage() solo existen en la subclase. Para una URL http: el objeto realmente es un HttpURLConnection, por lo que el cast siempre tiene éxito.
  • Enviar un cuerpo requirió setDoOutput(true) antes de escribir en getOutputStream(). Sin esa llamada la conexión permanece de solo lectura y la escritura falla — activar la salida es el interruptor que convierte un GET en una solicitud con cuerpo.
  • getResponseCode() devolvió 201 y es lo que realmente disparó la solicitud al servidor. El código de estado es lo primero que hay que leer, porque la siguiente decisión — qué flujo leer — depende de él.
  • El ejemplo ramificó entre getInputStream() y getErrorStream(). Aquí 201 es éxito, por lo que el flujo de entrada llevó el cuerpo del eco, pero en una respuesta 4xx/5xx getInputStream() habría lanzado y el mensaje del servidor solo sería accesible mediante getErrorStream(). Esa bifurcación es el flanco más afilado de la API.
  • El flujo requirió más de cinco llamadas de configuración para un solo POST, y disconnect() para limpiar. Esa verbosidad — flujos manuales, la trampa del flujo de error, sin asincronía integrada — es exactamente la razón por la que existe HttpClient.

Cuándo usar HttpURLConnection

Recurre a HttpURLConnection cuando estés en un JDK más antiguo (anterior a Java 11), cuando una biblioteca o base de código ya esté estandarizada en él, o cuando quieras evitar agregar cualquier dependencia adicional para una sola llamada sencilla. Para cualquier cosa nueva y no trivial — reutilización de conexiones, HTTP/2, asincronía u objetos de solicitud/respuesta más limpios — prefiere el moderno HttpClient. Si solo necesitas leer desde una URL sin control específico de HTTP, las clases URL y URLConnection son suficientes.

Práctica

Práctica
Un cliente realiza un PUT con 'HttpURLConnection'. Cuando el servidor devuelve '400 Bad Request', el código falla con una 'IOException' en 'conn.getInputStream()' en lugar de registrar el mensaje de error del servidor. ¿Cuál es la solución correcta?
Un cliente realiza un PUT con 'HttpURLConnection'. Cuando el servidor devuelve '400 Bad Request', el código falla con una 'IOException' en 'conn.getInputStream()' en lugar de registrar el mensaje de error del servidor. ¿Cuál es la solución correcta?
Was this page helpful?