Question Comment utiliser java.net.URLConnection pour déclencher et gérer les requêtes HTTP


Utilisation de java.net.URLConnection est demandé à peu près souvent ici, et le Oracle tutoriel est aussi concis à ce sujet.

Ce tutoriel montre essentiellement comment lancer une requête GET et lire la réponse. Il n'explique pas comment l'utiliser, entre autres, pour effectuer une requête POST, définir des en-têtes de requête, lire des en-têtes de réponse, gérer des cookies, soumettre un formulaire HTML, télécharger un fichier, etc.

Alors, comment puis-je utiliser java.net.URLConnection tirer et gérer les requêtes HTTP "avancées"?


1759


origine


Réponses:


D'abord un avertissement: les extraits de code affichés sont tous des exemples de base. Vous aurez besoin de gérer trivial IOExceptionle sable RuntimeExceptions aime NullPointerException, ArrayIndexOutOfBoundsException et vous consorts.


En train de préparer

Nous devons d'abord connaître au moins l'URL et le jeu de caractères. Les paramètres sont facultatifs et dépendent des exigences fonctionnelles.

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));

Les paramètres de requête doivent être dans name=value format et être concaténés par &. Vous auriez normalement aussi URL-encoder les paramètres de requête avec le jeu de caractères spécifié en utilisant URLEncoder#encode().

le String#format() est juste pour la commodité. Je préfère quand j'aurais besoin de l'opérateur de concaténation String + plus de deux fois.


Firing a HTTP GET requête avec (optionnellement) des paramètres de requête

C'est une tâche triviale. C'est la méthode de requête par défaut.

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

Toute chaîne de requête doit être concaténée à l'URL en utilisant ?. le Accept-Charset L'en-tête peut indiquer au serveur le codage des paramètres. Si vous n'envoyez aucune chaîne de requête, vous pouvez laisser le Accept-Charset En-tête Si vous n'avez pas besoin de définir d'en-têtes, vous pouvez même utiliser le URL#openStream() méthode de raccourci.

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

De toute façon, si l'autre côté est un HttpServletpuis son doGet() méthode sera appelée et les paramètres seront disponibles par HttpServletRequest#getParameter().

À des fins de test, vous pouvez imprimer le corps de la réponse sur stdout comme suit:

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

Firing a HTTP POST demande avec paramètres de requête

Réglage de la URLConnection#setDoOutput() à true implicite définit la méthode de demande à POST. Le HTTP POST standard sous forme de formulaires Web est de type application/x-www-form-urlencoded dans lequel la chaîne de requête est écrite dans le corps de la requête.

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();
// ...

Remarque: chaque fois que vous souhaitez soumettre un formulaire HTML par programmation, n'oubliez pas de prendre la name=value paires de tout <input type="hidden"> éléments dans la chaîne de requête et bien sûr aussi le name=value paire de <input type="submit"> élément que vous souhaitez "appuyer" par programmation (parce que c'est habituellement utilisé du côté serveur pour distinguer si un bouton a été pressé et si oui, lequel).

Vous pouvez également lancer le obtenu URLConnection à HttpURLConnection et utilise son HttpURLConnection#setRequestMethod() au lieu. Mais si vous essayez d'utiliser la connexion pour la sortie, vous devez toujours définir URLConnection#setDoOutput() à true.

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

De toute façon, si l'autre côté est un HttpServletpuis son doPost() méthode sera appelée et les paramètres seront disponibles par HttpServletRequest#getParameter().


En train de déclencher la requête HTTP

Vous pouvez déclencher la requête HTTP explicitement avec URLConnection#connect(), mais la requête sera automatiquement déclenchée à la demande lorsque vous souhaitez obtenir des informations sur la réponse HTTP, comme le corps de la réponse en utilisant URLConnection#getInputStream()etc. Les exemples ci-dessus font exactement cela, de sorte que le connect() l'appel est en fait superflu.


Collecte des informations de réponse HTTP

  1. Statut de réponse HTTP:

    Tu as besoin d'un HttpURLConnection ici. Jetez-le en premier si nécessaire.

    int status = httpConnection.getResponseCode();
    
  2. En-têtes de réponse HTTP:

    for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) {
        System.out.println(header.getKey() + "=" + header.getValue());
    }
    
  3. Codage de réponse HTTP:

    Quand le Content-Type contient un charset paramètre, le corps de la réponse est probablement basé sur le texte et nous aimerions traiter le corps de la réponse avec le codage de caractères spécifié côté serveur.

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

Maintenir la session

La session côté serveur est généralement soutenue par un cookie. Certains formulaires Web exigent que vous soyez connecté et / ou que vous soyez suivi par une session. Vous pouvez utiliser le CookieHandler API pour conserver les cookies Vous devez préparer un CookieManager avec un CookiePolicy de ACCEPT_ALL avant d'envoyer toutes les demandes 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();
// ...

Notez que ceci est connu pour ne pas toujours fonctionner correctement dans toutes les circonstances. Si cela échoue pour vous, le mieux est de rassembler et de définir manuellement les en-têtes des cookies. Vous devez essentiellement tout attraper Set-Cookie en-têtes de la réponse de la connexion ou le premier GET demander et passer ensuite à travers les demandes suivantes.

// Gather all cookies on the first request.
URLConnection connection = new URL(url).openConnection();
List<String> 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]);
}
// ...

le split(";", 2)[0] est là pour se débarrasser des attributs de cookie qui ne sont pas pertinents pour le côté du serveur comme expires, path, etc. Vous pouvez également utiliser cookie.substring(0, cookie.indexOf(';')) au lieu de split().


Mode de diffusion

le HttpURLConnection sera par défaut le tampon du tout demande au corps avant de l'envoyer, que vous ayez défini une longueur de contenu fixe connection.setRequestProperty("Content-Length", contentLength);. Cela peut causer OutOfMemoryExceptions chaque fois que vous envoyez simultanément de grandes requêtes POST (par exemple, en téléchargeant des fichiers). Pour éviter cela, vous souhaitez définir le HttpURLConnection#setFixedLengthStreamingMode().

httpConnection.setFixedLengthStreamingMode(contentLength);

Mais si la longueur du contenu n'est pas connue à l'avance, alors vous pouvez utiliser le mode de diffusion en bloc partagé en réglant le HttpURLConnection#setChunkedStreamingMode() en conséquence. Cela va définir le HTTP Transfer-Encoding en-tête de chunked ce qui forcera le corps de la requête à être envoyé en morceaux. L'exemple ci-dessous enverra le corps en morceaux de 1 Ko.

httpConnection.setChunkedStreamingMode(1024);

Agent utilisateur

Cela peut arriver une requête renvoie une réponse inattendue, alors qu'elle fonctionne correctement avec un véritable navigateur Web. Le côté serveur bloque probablement les demandes basées sur User-Agent en-tête de requête. le URLConnection sera réglé par défaut à Java/1.6.0_19 où la dernière partie est évidemment la version JRE. Vous pouvez remplacer ceci comme suit:

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.

Utilisez la chaîne User-Agent à partir d'un navigateur récent.


La gestion des erreurs

Si le code de réponse HTTP est 4nn (Erreur client) ou 5nn (Erreur du serveur), alors vous pouvez lire le HttpURLConnection#getErrorStream() pour voir si le serveur a envoyé des informations d'erreur utiles.

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

Si le code de réponse HTTP est -1, alors quelque chose s'est mal passé avec la gestion des connexions et des réponses. le HttpURLConnection la mise en œuvre est dans les anciens JRE quelque peu boguée avec le maintien des connexions en vie. Vous voudrez peut-être l'éteindre en réglant http.keepAlive propriété du système à false. Vous pouvez le faire par programme au début de votre application en:

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

Téléchargement de fichiers

Vous utiliseriez normalement multipart/form-data codage pour le contenu POST mixte (données binaires et caractères). Le codage est décrit plus en détail dans 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 l'autre côté est un HttpServletpuis son doPost() méthode sera appelée et les pièces seront disponibles par HttpServletRequest#getPart() (notez, ainsi ne pas  getParameter() etc!). le getPart() La méthode est relativement nouvelle, elle est introduite dans Servlet 3.0 (Glassfish 3, Tomcat 7, etc). Avant Servlet 3.0, votre meilleur choix est d'utiliser Apache Commons FileUpload analyser un multipart/form-data demande. Regarde aussi cette réponse pour des exemples des approches FileUpload et Servelt 3.0.


Traiter avec des sites HTTPS non approuvés ou mal configurés

Parfois, vous devez connecter une URL HTTPS, peut-être parce que vous écrivez un scraper Web. Dans ce cas, vous pouvez probablement faire face à javax.net.ssl.SSLException: Not trusted server certificate sur certains sites HTTPS qui ne conservent pas leurs certificats SSL à jour, ou java.security.cert.CertificateException: No subject alternative DNS name matching [hostname] found ou javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name sur certains sites HTTPS mal configurés.

Le temps unique suivant static initialiseur dans votre classe de grattoir web devrait faire HttpsURLConnection plus indulgents vis-à-vis de ces sites HTTPS et donc ne plus jeter ces exceptions.

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);
    }
}

Derniers mots

le Apache HttpComponents HttpClient est beaucoup plus pratique dans tout cela :)


Analyse et extraction HTML

Si tout ce que vous voulez est l'analyse et l'extraction de données à partir de HTML, alors mieux utiliser un analyseur HTML comme Jsoup


2525



Lorsque vous travaillez avec HTTP, il est presque toujours plus utile de se référer à HttpURLConnection plutôt que la classe de base URLConnection (depuis URLConnection est un cours abstrait quand vous demandez URLConnection.openConnection() sur une URL HTTP, c'est ce que vous obtiendrez de toute façon).

Alors vous pouvez au lieu de compter sur URLConnection#setDoOutput(true) implicitement définir la méthode de demande à POSTER plutôt faire httpURLConnection.setRequestMethod("POST") que certains pourraient trouver plus naturel (et qui vous permet également de spécifier d'autres méthodes de requête telles que METTRE, EFFACER, ...).

Il fournit également des constantes HTTP utiles pour vous permettre de:

int responseCode = httpURLConnection.getResponseCode();

if (responseCode == HttpURLConnection.HTTP_OK) {

84



Inspiré par ceci et d'autres questions sur SO, j'ai créé une source ouverte minimale basic-http-client qui incarne la plupart des techniques trouvées ici.

google-http-java-client est également une excellente ressource open source.


49



Il y a 2 options que vous pouvez aller avec HTTP URL Hits: GET / POST

GET Demande: -

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()));

Demande 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()));

22



Je vous suggère de regarder le code sur kevinsawicki / http-request, c'est essentiellement un emballage sur le dessus de HttpUrlConnection il fournit une API beaucoup plus simple au cas où vous voudriez simplement faire les demandes maintenant ou vous pouvez regarder les sources (ce n'est pas trop grand) pour voir comment les connexions sont gérées.

Exemple: Faire un GET demande avec le type de contenu application/json et quelques paramètres de requête:

// 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);

20



J'ai également été très inspiré par cette réponse.

Je suis souvent sur des projets où je dois faire un peu de HTTP, et je ne veux pas apporter beaucoup de dépendances de tiers (qui en amènent d'autres et ainsi de suite, etc.)

J'ai commencé à écrire mes propres utilitaires basés sur une partie de cette conversation (pas n'importe où):

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 {

Ensuite, il y a juste un tas ou des méthodes statiques.

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<String, ? extends Object> 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<String, ? extends Object> 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<String, ? extends Object> 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;
    }
}

Puis poster ...

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<String, ? extends Object> 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<String, ? extends Object> 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<String, ? extends Object> 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<String, ? extends Object> 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<String, ? extends Object> headers, URLConnection connection) {
    if (headers != null) {
        for (Map.Entry<String, ? extends Object> 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<String, ? extends Object> 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;
}

Eh bien, vous avez l'idée ...

Voici les tests:

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<String,String> 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<String,String> 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<String,String> 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);


}

Vous pouvez trouver le reste ici:

https://github.com/RichardHightower/boon

Mon but est de fournir les choses communes que l'on voudrait faire d'une manière un peu plus facile alors ....


19



Mettre à jour

Le nouveau client HTTP livré avec Java 9 mais dans le cadre d'un   Module d'incubateur nommé jdk.incubator.httpclient. Les modules d'incubation sont   un moyen de mettre les API non-finales dans les mains des développeurs tandis que le   Les API progressent vers la finalisation ou la suppression dans un futur   Libération.

En Java 9, vous pouvez envoyer un GET demande comme:

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

Ensuite, vous pouvez examiner le retour HttpResponse:

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

Puisque ce nouveau client HTTP est en java.httpclient  jdk.incubator.httpclient module, vous devez déclarer cette dépendance dans votre module-info.java fichier:

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

15



Au départ, j'ai été induit en erreur par cette article ce qui favorise HttpClient.

Plus tard, j'ai réalisé que HttpURLConnection va rester de cette article

Selon le blog de Google:

Le client HTTP Apache a moins de bugs sur Eclair et Froyo. C'est le meilleur choix pour ces versions. Pour Gingerbread, HttpURLConnection est le meilleur choix. Son API simple et sa petite taille le rendent parfait pour Android.

La compression transparente et la mise en cache des réponses réduisent l'utilisation du réseau, améliorent la vitesse et économisent la batterie. Les nouvelles applications doivent utiliser HttpURLConnection; C'est là que nous dépenserons notre énergie à l'avenir.

Après avoir lu Cet article et d'autres questions de pile sur les flux, je suis convaincu que HttpURLConnection va rester plus longtemps.

Certaines des questions SE favorisant HttpURLConnections:

Sur Android, effectuez une requête POST avec des données de formulaire codé par URL sans utiliser UrlEncodedFormEntity

HttpPost fonctionne dans le projet Java, pas dans Android


14



Vous pouvez aussi utiliser JdkRequest de jcabi-http (Je suis un développeur), qui fait tout ce travail pour vous, en décorant HttpURLConnection, en envoyant des requêtes HTTP et en analysant des réponses, par exemple:

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

Consultez cet article de blog pour plus d'informations: http://www.yegor256.com/2014/04/11/jcabi-http-intro.html


11



Il y a aussi OkHttp, qui est un client HTTP efficace par défaut:

  • Le support HTTP / 2 permet à toutes les demandes au même hôte de partager un socket.
  • Le regroupement de connexions réduit la latence des requêtes (si HTTP / 2 n'est pas disponible).
  • GZIP transparent réduit les tailles de téléchargement.
  • La mise en cache des réponses évite complètement le réseau pour les demandes répétées.

Commencez par créer une instance de OkHttpClient:

OkHttpClient client = new OkHttpClient();

Ensuite, préparez votre GET demande:

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

enfin, utiliser OkHttpClient envoyer envoyé préparé Request:

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

Pour plus de détails, vous pouvez consulter le La documentation d'OkHttp


11



Si vous utilisez http get, supprimez cette ligne

urlConnection.setDoOutput(true);

10