web-dev-qa-db-fra.com

Comment utiliser Java.net.URLConnection pour déclencher et gérer des requêtes HTTP

L'utilisation de Java.net.URLConnection est posée assez souvent ici, et le tutoriel Oracle est aussi concis à ce sujet.

Fondamentalement, ce tutoriel montre uniquement comment déclencher une requête GET et lire la réponse. Cela n'explique nulle part comment l'utiliser pour effectuer, entre autres, une demande POST, définir des en-têtes de demande, lire des en-têtes de réponse, gérer les cookies, envoyer un formulaire HTML, télécharger un fichier, etc.

Alors, comment puis-je utiliser _Java.net.URLConnection_ pour déclencher et gérer les requêtes HTTP "avancées"?

1884
BalusC

Tout d'abord, une clause de non-responsabilité: les extraits de code publiés sont tous des exemples élémentaires. Vous aurez besoin de manipuler des IOExceptions et des RuntimeExceptions triviaux comme NullPointerException, ArrayIndexOutOfBoundsException et vous complice.


En train de préparer

Nous devons d’abord connaître au moins l’URL et le charset. 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 au format name=value et être concaténés par &. Normalement, vous devez également encoder les paramètres de la requête avec le jeu de caractères spécifié à l'aide de URLEncoder#encode() .

La String#format() est juste pour votre commodité. Je le préfère lorsque j'ai besoin de l'opérateur de concaténation de chaînes + plus de deux fois.


Lancer une requête HTTP GET avec (éventuellement) 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 à l'aide de ?. L'en-tête Accept-Charset peut indiquer au serveur le codage des paramètres. Si vous n'envoyez aucune chaîne de requête, vous pouvez laisser l'en-tête Accept-Charset. Si vous n'avez pas besoin de définir d'en-tête, vous pouvez même utiliser la méthode de raccourci URL#openStream() .

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

Quoi qu'il en soit, si l'autre côté est un HttpServlet , sa méthode doGet() 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);
}

Envoi d'une requête HTTP POST avec des paramètres de requête

La définition de URLConnection#setDoOutput() sur true définit implicitement la méthode de requête sur POST. Comme le font les formulaires Web, HTTP POST _ 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: lorsque vous souhaitez soumettre un formulaire HTML par programme, n'oubliez pas de prendre les paires name=value de tous les éléments <input type="hidden"> dans la chaîne de requête et, bien sûr, également la paire name=value de l'élément <input type="submit"> que vous souhaitez "appuyer, "par programmation (car cela a généralement été utilisé côté serveur pour distinguer si un bouton a été enfoncé et, le cas échéant, lequel).

Vous pouvez également convertir le résultat obtenu URLConnection en HttpURLConnection et utiliser sa fonction HttpURLConnection#setRequestMethod() . Mais si vous essayez d'utiliser la connexion pour la sortie, vous devez toujours définir URLConnection#setDoOutput() sur true.

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

Quoi qu'il en soit, si l'autre côté est un HttpServlet , sa méthode doPost() sera appelée et les paramètres seront disponibles par HttpServletRequest#getParameter() .


Activer la requête HTTP

Vous pouvez déclencher explicitement la requête HTTP 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, telles que le corps de la réponse utilisant URLConnection#getInputStream() et ainsi de suite. C'est exactement ce que font les exemples ci-dessus, donc l'appel connect() est en réalité superflu.


Collecte des informations de réponse HTTP

  1. État de la réponse HTTP :

    Vous avez besoin d'un HttpURLConnection ici. Jetez-le d'abord 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 la réponse HTTP :

    Lorsque le Content-Type contient un paramètre charset, le corps de la réponse est probablement basé sur du 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 accompagnée d'un cookie. Certains formulaires Web nécessitent que vous soyez connecté et/ou suivi par une session. Vous pouvez utiliser l'API CookieHandler 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 cela 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 de cookie. Vous devez essentiellement extraire tous les en-têtes Set-Cookie de la réponse de la connexion ou de la première demande GET, puis les transmettre aux 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]);
}
// ...

La split(";", 2)[0] permet de supprimer les attributs de cookie non pertinents pour le serveur, tels que expires, path, etc. Sinon, vous pouvez également utiliser cookie.substring(0, cookie.indexOf(';')) au lieu de split().


Mode de streaming

Le HttpURLConnection met par défaut en mémoire tampon le corps de la requête entière avant de l'envoyer, que vous ayez défini vous-même une longueur de contenu fixe à l'aide de connection.setRequestProperty("Content-Length", contentLength);. Cela peut entraîner OutOfMemoryException chaque fois que vous envoyez simultanément de grandes demandes POST (par exemple, le téléchargement de fichiers). Pour éviter cela, vous souhaitez définir la HttpURLConnection#setFixedLengthStreamingMode() .

httpConnection.setFixedLengthStreamingMode(contentLength);

Mais si la longueur du contenu n’est pas vraiment connue au préalable, vous pouvez utiliser le mode de diffusion en bloc en définissant la fonction HttpURLConnection#setChunkedStreamingMode() en conséquence. Cela définira l'en-tête HTTP Transfer-Encoding sur 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

Il peut arriver qu'une demande renvoie une réponse inattendue, alors que cela fonctionne correctement avec un navigateur Web réel . Le côté serveur bloque probablement les demandes en fonction de l'en-tête de demande User-Agent . URLConnection le définira par défaut sur Java/1.6.0_19 où la dernière partie est évidemment la version de 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 d'un navigateur récent .


La gestion des erreurs

Si le code de réponse HTTP est 4nn (erreur du client) ou 5nn (erreur du serveur), vous pouvez lire la 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, il y a eu un problème de connexion et de traitement des réponses. L'implémentation HttpURLConnection dans les anciens JRE est quelque peu boguée avec le maintien des connexions actives. Vous pouvez le désactiver en définissant la propriété système http.keepAlive sur 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 un codage pour un contenu mixte POST (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 HttpServlet , sa méthode doPost() sera appelée et les pièces seront disponibles par HttpServletRequest#getPart() (note, donc pas getParameter() et ainsi de suite!). La méthode getPart() est cependant relativement nouvelle, elle a été introduite dans Servlet 3.0 (Glassfish 3, Tomcat 7, etc.). Avant Servlet 3.0, votre meilleur choix consiste à utiliser Apache Commons FileUpload pour analyser une requête multipart/form-data. Voir aussi cette réponse pour des exemples d'approches FileUpload et Servelt 3.0.


Gestion de sites HTTPS non fiables ou mal configurés

Parfois, vous devez connecter une URL HTTPS, peut-être parce que vous écrivez un scraper Web. Dans ce cas, il est possible que vous rencontriez un javax.net.ssl.SSLException: Not trusted server certificate sur certains sites HTTPS qui ne maintient pas leurs certificats SSL à jour, ou un 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.

L’initialiseur static à exécution unique suivant de votre classe de nettoyage Web devrait rendre HttpsURLConnection plus indulgent vis-à-vis de ces sites HTTPS et ainsi ne plus lancer 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 :)


Analyser et extraire HTML

Si tout ce que vous voulez, c'est analyser et extraire des données à partir de HTML, utilisez plutôt un analyseur HTML tel que Jsoup

2654
BalusC

Lorsque vous travaillez avec HTTP, il est presque toujours plus utile de faire référence à HttpURLConnection plutôt qu'à la classe de base URLConnection (puisque URLConnection est une classe abstraite lorsque vous demandez URLConnection.openConnection() sur HTTP. URL c'est ce que vous obtiendrez quand même).

Ensuite, vous pouvez vous contenter de URLConnection#setDoOutput(true) pour définir implicitement la méthode de requête sur POST à la place faire httpURLConnection.setRequestMethod("POST") ce que certains pourraient trouver plus naturel (et qui vous permet également de spécifier d'autres méthodes de requête telles que PUT, DELETE, ...).

Il fournit également des constantes HTTP utiles pour que vous puissiez faire:

int responseCode = httpURLConnection.getResponseCode();

if (responseCode == HttpURLConnection.HTTP_OK) {
88
Paal Thorstensen

Inspiré par cette question et d’autres sur SO, j’ai créé un open source minimal basic-http-client , qui reprend la plupart des techniques décrites ici.

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

50
David Chandler

Il y a 2 options possibles avec HTTP URL Hits: GET/POST

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

POST 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);
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()));
23
Utkash Bhatt

Je vous suggère de jeter un coup d'oeil au code sur kevinsawicki/http-request , c'est fondamentalement un wrapper au-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 gros) pour voir comment les connexions sont gérées.

Exemple: Faites une demande GET avec le type de contenu application/json et des 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);
21
fernandohur

Mise à jour

Le nouveau client HTTP livré avec Java 9 mais faisant partie d'un module d'incubateur nommé jdk.incubator.httpclient. Les modules de l'incubateur sont un moyen de mettre des API non finales entre les mains des développeurs tandis que les API progressent vers la finalisation ou la suppression dans une version ultérieure.

Dans Java 9, vous pouvez envoyer une demande GET comme:

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

Ensuite, vous pouvez examiner le HttpResponse retourné:

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

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

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

Cette réponse m'a également beaucoup inspirée.

Je suis souvent sur des projets où je dois utiliser un certain HTTP et je ne souhaite peut-être pas introduire beaucoup de dépendances de tiers (qui en amènent d'autres, etc., etc.).

J'ai commencé à écrire mes propres utilitaires sur la base d'une partie de cette conversation (pas du tout terminé):

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

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 objectif est de fournir les choses communes que l'on voudrait faire un peu plus facilement, alors ...

20
RickHigh

Au début, j'ai été induit en erreur par ceci article qui favorise HttpClient.

Plus tard, je me suis rendu compte 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. HttpURLConnection est le meilleur choix pour le pain d’épice. Son API simple et sa petite taille le rendent idéal 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 pour aller de l'avant.

Après avoir lu cet article et quelques autres questions de débordement de pile, je suis convaincu que HttpURLConnection restera plus longtemps.

Certaines des questions SE favorisant HttpURLConnections:

Sous Android, effectuez une demande POST avec des données de formulaire codé par URL sans utiliser UrlEncodedFormEntity

HttpPost fonctionne dans le projet Java, pas dans Android

16
Ravindra babu

Il existe également OkHttp , qui est un client HTTP efficace par défaut:

  • La prise en charge HTTP/2 permet à toutes les demandes adressées au même hôte de partager un socket.
  • Le regroupement de connexions réduit la latence des demandes (si HTTP/2 n’est pas disponible).
  • GZIP transparent réduit la taille des téléchargements.
  • 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 demande GET:

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

enfin, utilisez OkHttpClient pour envoyer préparé Request:

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

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

14
Ali Dehghani

Vous pouvez également utiliser JdkRequest à partir de jcabi-http (je suis un développeur), qui effectue tout ce travail pour vous: décorer HttpURLConnection, lancer des requêtes HTTP et analyser les réponses, pour exemple:

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

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

13
yegor256

si vous utilisez http get s'il vous plaît supprimer cette ligne

urlConnection.setDoOutput(true);
11