Cómo usar java.net.URLConnection para abrir y manejar solicitudes HTTP

El uso de java.net.URLConnection se realiza con bastante frecuencia aquí, y el tutorial de Oracle es demasiado conciso al respecto.

Ese tutorial básicamente solo muestra cómo activar una solicitud GET y leer la respuesta. No explica en ningún lugar cómo usarlo para, entre otros, realizar una solicitud POST, establecer encabezados de solicitud, leer encabezados de respuesta, tratar con cookies, enviar un formulario HTML, cargar un archivo, etc.

Entonces, ¿cómo puedo usar java.net.URLConnection para activar y manejar solicitudes HTTP “avanzadas”?

Primero, un descargo de responsabilidad de antemano: los fragmentos de código publicados son todos ejemplos básicos. Necesitarás manejar IOException s triviales y RuntimeException como NullPointerException , ArrayIndexOutOfBoundsException y ArrayIndexOutOfBoundsException tú mismo.


Preparando

Primero necesitamos saber al menos la URL y el juego de caracteres. Los parámetros son opcionales y dependen de los requisitos funcionales.

 String url = "http://example.com"; String charset = "UTF-8"; // Or in Java 7 and later, use the constant: java.nio.charset.StandardCharsets.UTF_8.name() String param1 = "value1"; String param2 = "value2"; // ... String query = String.format("param1=%s&param2=%s", URLEncoder.encode(param1, charset), URLEncoder.encode(param2, charset)); 

Los parámetros de consulta deben estar en formato name=value y estar concatenados por & . Normalmente, también codificará por URL los parámetros de consulta con el URLEncoder#encode() caracteres especificado utilizando URLEncoder#encode() .

El String#format() es solo por conveniencia. Lo prefiero cuando necesito el operador de concatenación String + más de dos veces.


Disparar una solicitud HTTP GET con (opcionalmente) parámetros de consulta

Es una tarea trivial. Es el método de solicitud predeterminado.

 URLConnection connection = new URL(url + "?" + query).openConnection(); connection.setRequestProperty("Accept-Charset", charset); InputStream response = connection.getInputStream(); // ... 

Cualquier cadena de consulta debe concatenarse a la URL usando ? . El encabezado Accept-Charset puede Accept-Charset al servidor en qué encoding están los parámetros. Si no envía ninguna cadena de consulta, puede dejar el encabezado Accept-Charset . Si no necesita establecer ningún encabezado, incluso puede usar el método abreviado URL#openStream() .

 InputStream response = new URL(url).openStream(); // ... 

De cualquier manera, si el otro lado es un HttpServlet , entonces se doGet() su método doGet() y los parámetros estarán disponibles por HttpServletRequest#getParameter() .

Para propósitos de prueba, puede imprimir el cuerpo de la respuesta a stdout de la siguiente manera:

 try (Scanner scanner = new Scanner(response)) { String responseBody = scanner.useDelimiter("\\A").next(); System.out.println(responseBody); } 

Disparar una solicitud HTTP POST con parámetros de consulta

Establecer el URLConnection#setDoOutput() en true establece implícitamente el método de solicitud en POST. El HTTP POST estándar como lo hacen los formularios web es del tipo application/x-www-form-urlencoded en el que la cadena de consulta se escribe en el cuerpo de la solicitud.

 URLConnection connection = new URL(url).openConnection(); connection.setDoOutput(true); // Triggers POST. connection.setRequestProperty("Accept-Charset", charset); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset); try (OutputStream output = connection.getOutputStream()) { output.write(query.getBytes(charset)); } InputStream response = connection.getInputStream(); // ... 

Nota: siempre que desee enviar un formulario HTML mediante progtwigción, no olvide tomar los pares name=value de cualquier elemento en la cadena de consulta y, por supuesto, también el par name=value de el elemento que desea “presionar” programáticamente (porque generalmente se usa en el servidor para distinguir si se presionó un botón y, de ser así, cuál).

También puede convertir el URLConnection obtenido en HttpURLConnection y utilizar su HttpURLConnection#setRequestMethod() lugar. Pero si intenta usar la conexión para la salida, aún necesita establecer URLConnection#setDoOutput() en true .

 HttpURLConnection httpConnection = (HttpURLConnection) new URL(url).openConnection(); httpConnection.setRequestMethod("POST"); // ... 

De cualquier manera, si el otro lado es un HttpServlet , entonces se doPost() su método doPost() y los parámetros estarán disponibles por HttpServletRequest#getParameter() .


En realidad disparando la solicitud HTTP

Puede activar la solicitud HTTP explícitamente con URLConnection#connect() , pero la solicitud se activará automáticamente cuando desee obtener información sobre la respuesta HTTP, como el cuerpo de la respuesta utilizando URLConnection#getInputStream() y así sucesivamente. Los ejemplos anteriores hacen exactamente eso, por lo que la llamada a connect() es de hecho superflua.


Recostackción de información de respuesta HTTP

  1. Estado de respuesta HTTP :

    Necesitas una HttpURLConnection aquí. Echalo primero si es necesario.

     int status = httpConnection.getResponseCode(); 
  2. Encabezados de respuesta HTTP :

     for (Entry> header : connection.getHeaderFields().entrySet()) { System.out.println(header.getKey() + "=" + header.getValue()); } 
  3. Codificación de respuesta HTTP :

    Cuando Content-Type contiene un parámetro de charset , entonces el cuerpo de la respuesta probablemente se base en texto y nos gustaría procesar el cuerpo de la respuesta con la encoding de caracteres especificada en el lado del servidor.

     String contentType = connection.getHeaderField("Content-Type"); String charset = null; for (String param : contentType.replace(" ", "").split(";")) { if (param.startsWith("charset=")) { charset = param.split("=", 2)[1]; break; } } if (charset != null) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(response, charset))) { for (String line; (line = reader.readLine()) != null;) { // ... System.out.println(line) ? } } } else { // It's likely binary content, use InputStream/OutputStream. } 

Mantenimiento de la sesión

La sesión del servidor generalmente está respaldada por una cookie. Algunos formularios web requieren que haya iniciado sesión y / o que una sesión los rastree. Puede usar la API de CookieHandler para mantener las cookies. CookiePolicy preparar un CookieManager con una CookiePolicy de ACCEPT_ALL antes de enviar todas las solicitudes HTTP.

 // First set the default cookie manager. CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL)); // All the following subsequent URLConnections will use the same cookie manager. URLConnection connection = new URL(url).openConnection(); // ... connection = new URL(url).openConnection(); // ... connection = new URL(url).openConnection(); // ... 

Tenga en cuenta que esto se sabe que no siempre funciona correctamente en todas las circunstancias. Si falla para usted, lo mejor es recostackr manualmente y establecer los encabezados de las cookies. Básicamente, es necesario tomar todos Set-Cookie encabezados Set-Cookie de la respuesta del inicio de sesión o la primera solicitud GET y luego pasar esto a través de las solicitudes posteriores.

 // Gather all cookies on the first request. URLConnection connection = new URL(url).openConnection(); List cookies = connection.getHeaderFields().get("Set-Cookie"); // ... // Then use the same cookies on all subsequent requests. connection = new URL(url).openConnection(); for (String cookie : cookies) { connection.addRequestProperty("Cookie", cookie.split(";", 2)[0]); } // ... 

La split(";", 2)[0] está ahí para deshacerse de los atributos de cookie que son irrelevantes para el lado del servidor como expires , path , etc. Alternativamente, también podría usar cookie.substring(0, cookie.indexOf(';')) lugar de split() .


Modo de transmisión

El HttpURLConnection almacenará de forma predeterminada el cuerpo completo de la solicitud antes de enviarlo, independientemente de si ha establecido usted mismo una longitud de contenido fija utilizando connection.setRequestProperty("Content-Length", contentLength); . Esto puede causar OutOfMemoryException s cuando envía al mismo tiempo grandes solicitudes POST (por ejemplo, carga de archivos). Para evitar esto, le gustaría configurar el HttpURLConnection#setFixedLengthStreamingMode() .

 httpConnection.setFixedLengthStreamingMode(contentLength); 

Pero si la longitud del contenido realmente no se conoce de antemano, puede hacer uso del modo de transmisión fragmentada configurando HttpURLConnection#setChunkedStreamingMode() consecuencia. Esto configurará el encabezado HTTP Transfer-Encoding para chunked lo que obligará al cuerpo de la solicitud a enviarse en fragmentos. El siguiente ejemplo enviará el cuerpo en pedazos de 1 KB.

 httpConnection.setChunkedStreamingMode(1024); 

Agente de usuario

Puede suceder que una solicitud devuelva una respuesta inesperada, mientras que funciona bien con un navegador web real . El lado del servidor probablemente esté bloqueando las solicitudes según el encabezado de solicitud del User-Agent . El URLConnection lo configurará por defecto en Java/1.6.0_19 donde la última parte es obviamente la versión de JRE. Puede anular esto de la siguiente manera:

 connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"); // Do as if you're using Chrome 41 on Windows 7. 

Use la cadena User-Agent desde un navegador reciente .


Manejo de errores

Si el código de respuesta HTTP es 4nn (Error del cliente) o 5nn (Error del servidor), puede leer HttpURLConnection#getErrorStream() para ver si el servidor ha enviado información de error útil.

 InputStream error = ((HttpURLConnection) connection).getErrorStream(); 

Si el código de respuesta HTTP es -1, entonces algo salió mal con la conexión y el manejo de la respuesta. La implementación de HttpURLConnection está en JREs más antiguos con errores para mantener las conexiones activas. Es posible que desee desactivarlo estableciendo la propiedad del sistema http.keepAlive en false . Puede hacer esto programáticamente al comienzo de su aplicación al:

 System.setProperty("http.keepAlive", "false"); 

Subiendo archivos

Normalmente usaría encoding multipart/form-data para contenido mixto POST (datos binarios y caracteres). La encoding se describe con más detalle en RFC2388 .

 String param = "value"; File textFile = new File("/path/to/file.txt"); File binaryFile = new File("/path/to/file.bin"); String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value. String CRLF = "\r\n"; // Line separator required by multipart/form-data. URLConnection connection = new URL(url).openConnection(); connection.setDoOutput(true); connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); try ( OutputStream output = connection.getOutputStream(); PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, charset), true); ) { // Send normal param. writer.append("--" + boundary).append(CRLF); writer.append("Content-Disposition: form-data; name=\"param\"").append(CRLF); writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF); writer.append(CRLF).append(param).append(CRLF).flush(); // Send text file. writer.append("--" + boundary).append(CRLF); writer.append("Content-Disposition: form-data; name=\"textFile\"; filename=\"" + textFile.getName() + "\"").append(CRLF); writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF); // Text file itself must be saved in this charset! writer.append(CRLF).flush(); Files.copy(textFile.toPath(), output); output.flush(); // Important before continuing with writer! writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary. // Send binary file. writer.append("--" + boundary).append(CRLF); writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + binaryFile.getName() + "\"").append(CRLF); writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(binaryFile.getName())).append(CRLF); writer.append("Content-Transfer-Encoding: binary").append(CRLF); writer.append(CRLF).flush(); Files.copy(binaryFile.toPath(), output); output.flush(); // Important before continuing with writer! writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary. // End of multipart/form-data. writer.append("--" + boundary + "--").append(CRLF).flush(); } 

Si el otro lado es un HttpServlet , entonces se doPost() su método doPost() y las partes estarán disponibles por HttpServletRequest#getPart() (nota, por lo tanto, no getParameter() y así sucesivamente!). El método getPart() es relativamente nuevo, pero se introdujo en Servlet 3.0 (Glassfish 3, Tomcat 7, etc.). Antes de Servlet 3.0, su mejor opción es utilizar Apache Commons FileUpload para analizar una solicitud multipart/form-data . Consulte también esta respuesta para ver ejemplos de los enfoques FileUpload y Servelt 3.0.


Tratar con sitios HTTPS desconfiados o no confiables

En ocasiones, debe conectar una URL HTTPS, tal vez porque está escribiendo un raspador web. En ese caso, es probable que se enfrente a javax.net.ssl.SSLException: Not trusted server certificate en algunos sitios HTTPS que no mantiene sus certificados SSL actualizados, o una java.security.cert.CertificateException: No subject alternative DNS name matching [hostname] found o javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name en algunos sitios HTTPS mal configurados.

El siguiente inicializador static ejecución única en su clase de raspador web debería hacer que HttpsURLConnection más indulgente con esos sitios HTTPS y, por lo tanto, no arroje esas excepciones.

 static { TrustManager[] trustAllCertificates = new TrustManager[] { new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return null; // Not relevant. } @Override public void checkClientTrusted(X509Certificate[] certs, String authType) { // Do nothing. Just allow them all. } @Override public void checkServerTrusted(X509Certificate[] certs, String authType) { // Do nothing. Just allow them all. } } }; HostnameVerifier trustAllHostnames = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; // Just allow them all. } }; try { System.setProperty("jsse.enableSNIExtension", "false"); SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCertificates, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier(trustAllHostnames); } catch (GeneralSecurityException e) { throw new ExceptionInInitializerError(e); } } 

Ultimas palabras

El HttpClients de Apache HttpComponents es mucho más conveniente en todo esto 🙂

  • Tutorial de HttpClient
  • Ejemplos de HttpClient

Analizando y extrayendo HTML

Si todo lo que quiere es analizar y extraer datos de HTML, mejor utilice un analizador HTML como Jsoup

  • ¿Cuáles son los pros / contras de los principales analizadores de HTML en Java?
  • Cómo escanear y extraer una página web en Java

Cuando se trabaja con HTTP, es casi siempre más útil referirse a HttpURLConnection lugar de a la clase base URLConnection (ya que URLConnection es una clase abstracta cuando se solicita URLConnection.openConnection() en una URL HTTP que de todos modos obtendrá de vuelta).

Luego, en lugar de confiar en URLConnection#setDoOutput(true) para establecer implícitamente el método de solicitud en POST, en su lugar, haga httpURLConnection.setRequestMethod("POST") que algunos pueden considerar más natural (y que también le permite especificar otros métodos de solicitud, como PUT , DELETE , …).

También proporciona constantes HTTP útiles para que pueda hacer:

 int responseCode = httpURLConnection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { 

Inspirados por esta y otras preguntas sobre SO, he creado un cliente HTTP básico de código abierto mínimo que incorpora la mayoría de las técnicas que se encuentran aquí.

google-http-java-client también es un excelente recurso de código abierto.

Hay 2 opciones que puede elegir con HTTP Hits de URL: GET / POST

Solicitud GET: –

 HttpURLConnection.setFollowRedirects(true); // defaults to true String url = "https://name_of_the_url"; URL request_url = new URL(url); HttpURLConnection http_conn = (HttpURLConnection)request_url.openConnection(); http_conn.setConnectTimeout(100000); http_conn.setReadTimeout(100000); http_conn.setInstanceFollowRedirects(true); System.out.println(String.valueOf(http_conn.getResponseCode())); 

Solicitud POST: –

 HttpURLConnection.setFollowRedirects(true); // defaults to true String url = "https://name_of_the_url" URL request_url = new URL(url); HttpURLConnection http_conn = (HttpURLConnection)request_url.openConnection(); http_conn.setConnectTimeout(100000); http_conn.setReadTimeout(100000); http_conn.setInstanceFollowRedirects(true); http_conn.setDoOutput(true); PrintWriter out = new PrintWriter(http_conn.getOutputStream()); if (urlparameter != null) { out.println(urlparameter); } out.close(); out = null; System.out.println(String.valueOf(http_conn.getResponseCode())); 

Le sugiero que eche un vistazo al código en kevinsawicki / http-request , básicamente es un contenedor sobre HttpUrlConnection que proporciona una API mucho más simple en caso de que quiera hacer las solicitudes ahora o puede echar un vistazo a las fonts (no es demasiado grande) para ver cómo se manejan las conexiones.

Ejemplo: hacer una solicitud GET con el tipo de contenido application/json y algunos parámetros de consulta:

 // GET http://google.com?q=baseball%20gloves&size=100 String response = HttpRequest.get("http://google.com", true, "q", "baseball gloves", "size", 100) .accept("application/json") .body(); System.out.println("Response was: " + response); 

También estaba muy inspirado por esta respuesta.

A menudo estoy en proyectos donde necesito hacer algo de HTTP, y es posible que no quiera incorporar muchas dependencias de terceros (que traen otras, etc., etc.)

Empecé a escribir mis propias utilidades basadas en algunas de estas conversaciones (no en ninguna parte):

 package org.boon.utils; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.Map; import static org.boon.utils.IO.read; public class HTTP { 

Entonces solo hay un montón o métodos estáticos.

 public static String get( final String url) { Exceptions.tryIt(() -> { URLConnection connection; connection = doGet(url, null, null, null); return extractResponseString(connection); }); return null; } public static String getWithHeaders( final String url, final Map headers) { URLConnection connection; try { connection = doGet(url, headers, null, null); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String getWithContentType( final String url, final Map headers, String contentType) { URLConnection connection; try { connection = doGet(url, headers, contentType, null); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String getWithCharSet( final String url, final Map headers, String contentType, String charSet) { URLConnection connection; try { connection = doGet(url, headers, contentType, charSet); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } 

Luego publica …

 public static String postBody( final String url, final String body) { URLConnection connection; try { connection = doPost(url, null, "text/plain", null, body); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String postBodyWithHeaders( final String url, final Map headers, final String body) { URLConnection connection; try { connection = doPost(url, headers, "text/plain", null, body); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String postBodyWithContentType( final String url, final Map headers, final String contentType, final String body) { URLConnection connection; try { connection = doPost(url, headers, contentType, null, body); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String postBodyWithCharset( final String url, final Map headers, final String contentType, final String charSet, final String body) { URLConnection connection; try { connection = doPost(url, headers, contentType, charSet, body); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } private static URLConnection doPost(String url, Map headers, String contentType, String charset, String body ) throws IOException { URLConnection connection;/* Handle output. */ connection = new URL(url).openConnection(); connection.setDoOutput(true); manageContentTypeHeaders(contentType, charset, connection); manageHeaders(headers, connection); IO.write(connection.getOutputStream(), body, IO.CHARSET); return connection; } private static void manageHeaders(Map headers, URLConnection connection) { if (headers != null) { for (Map.Entry entry : headers.entrySet()) { connection.setRequestProperty(entry.getKey(), entry.getValue().toString()); } } } private static void manageContentTypeHeaders(String contentType, String charset, URLConnection connection) { connection.setRequestProperty("Accept-Charset", charset == null ? IO.CHARSET : charset); if (contentType!=null && !contentType.isEmpty()) { connection.setRequestProperty("Content-Type", contentType); } } private static URLConnection doGet(String url, Map headers, String contentType, String charset) throws IOException { URLConnection connection;/* Handle output. */ connection = new URL(url).openConnection(); manageContentTypeHeaders(contentType, charset, connection); manageHeaders(headers, connection); return connection; } private static String extractResponseString(URLConnection connection) throws IOException { /* Handle input. */ HttpURLConnection http = (HttpURLConnection)connection; int status = http.getResponseCode(); String charset = getCharset(connection.getHeaderField("Content-Type")); if (status==200) { return readResponseBody(http, charset); } else { return readErrorResponseBody(http, status, charset); } } private static String readErrorResponseBody(HttpURLConnection http, int status, String charset) { InputStream errorStream = http.getErrorStream(); if ( errorStream!=null ) { String error = charset== null ? read( errorStream ) : read( errorStream, charset ); throw new RuntimeException("STATUS CODE =" + status + "\n\n" + error); } else { throw new RuntimeException("STATUS CODE =" + status); } } private static String readResponseBody(HttpURLConnection http, String charset) throws IOException { if (charset != null) { return read(http.getInputStream(), charset); } else { return read(http.getInputStream()); } } private static String getCharset(String contentType) { if (contentType==null) { return null; } String charset = null; for (String param : contentType.replace(" ", "").split(";")) { if (param.startsWith("charset=")) { charset = param.split("=", 2)[1]; break; } } charset = charset == null ? IO.CHARSET : charset; return charset; } 

Bueno, ya captas la idea….

Aquí están las pruebas:

 static class MyHandler implements HttpHandler { public void handle(HttpExchange t) throws IOException { InputStream requestBody = t.getRequestBody(); String body = IO.read(requestBody); Headers requestHeaders = t.getRequestHeaders(); body = body + "\n" + copy(requestHeaders).toString(); t.sendResponseHeaders(200, body.length()); OutputStream os = t.getResponseBody(); os.write(body.getBytes()); os.close(); } } @Test public void testHappy() throws Exception { HttpServer server = HttpServer.create(new InetSocketAddress(9212), 0); server.createContext("/test", new MyHandler()); server.setExecutor(null); // creates a default executor server.start(); Thread.sleep(10); Map headers = map("foo", "bar", "fun", "sun"); String response = HTTP.postBodyWithContentType("http://localhost:9212/test", headers, "text/plain", "hi mom"); System.out.println(response); assertTrue(response.contains("hi mom")); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.postBodyWithCharset("http://localhost:9212/test", headers, "text/plain", "UTF-8", "hi mom"); System.out.println(response); assertTrue(response.contains("hi mom")); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.postBodyWithHeaders("http://localhost:9212/test", headers, "hi mom"); System.out.println(response); assertTrue(response.contains("hi mom")); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.get("http://localhost:9212/test"); System.out.println(response); response = HTTP.getWithHeaders("http://localhost:9212/test", headers); System.out.println(response); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.getWithContentType("http://localhost:9212/test", headers, "text/plain"); System.out.println(response); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.getWithCharSet("http://localhost:9212/test", headers, "text/plain", "UTF-8"); System.out.println(response); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); Thread.sleep(10); server.stop(0); } @Test public void testPostBody() throws Exception { HttpServer server = HttpServer.create(new InetSocketAddress(9220), 0); server.createContext("/test", new MyHandler()); server.setExecutor(null); // creates a default executor server.start(); Thread.sleep(10); Map headers = map("foo", "bar", "fun", "sun"); String response = HTTP.postBody("http://localhost:9220/test", "hi mom"); assertTrue(response.contains("hi mom")); Thread.sleep(10); server.stop(0); } @Test(expected = RuntimeException.class) public void testSad() throws Exception { HttpServer server = HttpServer.create(new InetSocketAddress(9213), 0); server.createContext("/test", new MyHandler()); server.setExecutor(null); // creates a default executor server.start(); Thread.sleep(10); Map headers = map("foo", "bar", "fun", "sun"); String response = HTTP.postBodyWithContentType("http://localhost:9213/foo", headers, "text/plain", "hi mom"); System.out.println(response); assertTrue(response.contains("hi mom")); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); Thread.sleep(10); server.stop(0); } 

Puedes encontrar el rest aqui:

https://github.com/RichardHightower/boon

Mi objective es proporcionar las cosas comunes que uno querría hacer de una manera un poco más fácil que …

Actualizar

El nuevo cliente HTTP incluido con Java 9 pero como parte de un módulo de incubadora denominado jdk.incubator.httpclient . Los módulos de incubadora son un medio para poner las API que no son finales en manos de los desarrolladores, mientras que las API avanzan hacia la finalización o eliminación en una versión futura.

En Java 9, puede enviar una solicitud GET como:

 // GET HttpResponse response = HttpRequest .create(new URI("http://www.stackoverflow.com")) .headers("Foo", "foovalue", "Bar", "barvalue") .GET() .response(); 

Luego puede examinar la HttpResponse :

 int statusCode = response.statusCode(); String responseBody = response.body(HttpResponse.asString()); 

Dado que este nuevo cliente HTTP está en java.httpclient jdk.incubator.httpclient module, debe declarar esta dependencia en su archivo module-info.java :

 module com.foo.bar { requires jdk.incubator.httpclient; } 

Inicialmente fui engañado por este artículo que favorece a HttpClient .

Más tarde me he dado cuenta de que HttpURLConnection se va a quedar de este artículo

Según el blog de Google :

El cliente Apache HTTP tiene menos errores en Eclair y Froyo. Es la mejor opción para estos lanzamientos. Para Gingerbread, HttpURLConnection es la mejor opción. Su API simple y su pequeño tamaño lo hacen ideal para Android.

La compresión transparente y el almacenamiento en caché de respuesta reducen el uso de la red, mejoran la velocidad y ahorran batería. Las nuevas aplicaciones deben usar HttpURLConnection; es donde gastaremos nuestra energía en el futuro.

Después de leer este artículo y algunas otras preguntas de stack over flow, estoy convencido de que HttpURLConnection se mantendrá durante más tiempo.

Algunas de las preguntas de SE que favorecen HttpURLConnections :

En Android, realice una solicitud POST con datos de formularios codificados en URL sin utilizar UrlEncodedFormEntity

HttpPost funciona en el proyecto de Java, no en Android

También puede usar JdkRequest desde jcabi-http (soy desarrollador), que hace todo este trabajo por usted, decorando HttpURLConnection, disparando solicitudes HTTP y analizando respuestas, por ejemplo:

 String html = new JdkRequest("http://www.google.com").fetch().body(); 

Consulte esta publicación en el blog para obtener más información: http://www.yegor256.com/2014/04/11/jcabi-http-intro.html

También está OkHttp , que es un cliente HTTP que es eficiente por defecto:

  • La compatibilidad con HTTP / 2 permite que todas las solicitudes al mismo host compartan un socket.
  • La agrupación de conexiones reduce la latencia de las solicitudes (si HTTP / 2 no está disponible).
  • El GZIP transparente reduce el tamaño de las descargas.
  • El caché de respuesta evita la red completamente para solicitudes repetidas.

Primero crea una instancia de OkHttpClient :

 OkHttpClient client = new OkHttpClient(); 

Luego, prepara tu solicitud GET :

 Request request = new Request.Builder() .url(url) .build(); 

finalmente, use OkHttpClient para enviar la Request preparada:

 Response response = client.newCall(request).execute(); 

Para más detalles, puede consultar la documentación de OkHttp

si está utilizando http get, por favor elimine esta línea

 urlConnection.setDoOutput(true);