Frage Wie man mit java.net.URLConnection HTTP-Anfragen auslöst und verarbeitet


Gebrauch von java.net.URLConnection wird hier ziemlich oft gefragt, und die Oracle-Tutorial ist auch Prägnant darüber.

Dieses Tutorial zeigt im Grunde nur, wie man eine GET-Anfrage auslöst und die Antwort liest. Es wird nirgends erklärt, wie man es unter anderem zum Ausführen einer POST-Anfrage, zum Setzen von Anforderungsheadern, zum Lesen von Antwortheadern, zum Umgang mit Cookies, zum Senden eines HTML-Formulars, zum Hochladen einer Datei usw. verwendet.

Also, wie kann ich verwenden java.net.URLConnection feuern und behandeln "erweiterte" HTTP-Anfragen?


1759


Ursprung


Antworten:


Zuerst ein Haftungsausschluss: Die geposteten Code-Snippets sind alles Beispiele. Sie müssen mit Trivial umgehen IOExceptions und RuntimeExceptions wie NullPointerException, ArrayIndexOutOfBoundsException und dich selbst umarmen.


Vorbereitung

Wir müssen zuerst mindestens die URL und den Zeichensatz kennen. Die Parameter sind optional und hängen von den funktionalen Anforderungen ab.

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

Die Abfrageparameter müssen in sein name=value formatieren und verkettet werden durch &. Das würdest du normalerweise auch URL-Codierung die Abfrageparameter mit dem angegebenen Zeichensatz mit URLEncoder#encode().

Das String#format() ist nur für die Bequemlichkeit. Ich bevorzuge es, wenn ich den String-Verkettungsoperator benötigen würde + mehr als zweimal.


Feuern a HTTP GET Anfrage mit (optional) Abfrageparametern

Es ist eine triviale Aufgabe. Es ist die Standardanforderungsmethode.

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

Jede Abfragezeichenfolge sollte mit der URL verkettet werden ?. Das Accept-Charset Header kann den Server anweisen, in welcher Kodierung die Parameter enthalten sind. Wenn Sie keine Abfragezeichenfolge senden, können Sie das Feld verlassen Accept-Charset Kopf weg. Wenn Sie keine Header festlegen müssen, können Sie auch die verwenden URL#openStream() Verknüpfungsmethode.

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

In jedem Fall, wenn die andere Seite eine ist HttpServlet, dann ist es doGet() Methode wird aufgerufen und die Parameter sind verfügbar von HttpServletRequest#getParameter().

Zu Testzwecken können Sie den Antworttext wie folgt ausdrucken:

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

Feuern a HTTP-POST Anfrage mit Abfrageparametern

Einstellen der URLConnection#setDoOutput() zu true legt die Request-Methode implizit auf POST fest. Der Standard-HTTP-POST als Webformular ist vom Typ application/x-www-form-urlencoded wobei die Abfragezeichenfolge in den Anfragetext geschrieben wird.

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

Hinweis: Wenn Sie ein HTML - Formular programmatisch übermitteln möchten, vergessen Sie nicht, das name=value Paare von irgendwelchen <input type="hidden"> Elemente in die Abfragezeichenfolge und natürlich auch die name=value Paar der <input type="submit"> Element, das Sie programmgesteuert "drücken" möchten (weil das normalerweise auf der Serverseite verwendet wird, um zu unterscheiden, ob eine Schaltfläche gedrückt wurde und wenn ja, welche).

Sie können das erhaltene auch übertragen URLConnection zu HttpURLConnection und benutze es HttpURLConnection#setRequestMethod() stattdessen. Aber wenn Sie versuchen, die Verbindung für die Ausgabe zu verwenden, müssen Sie noch festlegen URLConnection#setDoOutput() zu true.

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

In jedem Fall, wenn die andere Seite eine ist HttpServlet, dann ist es doPost() Methode wird aufgerufen und die Parameter sind verfügbar von HttpServletRequest#getParameter().


Tatsächlich feuern die HTTP-Anfrage

Sie können die HTTP-Anfrage explizit mit auslösen URLConnection#connect(), aber die Anforderung wird automatisch bei Bedarf ausgelöst, wenn Sie Informationen über die HTTP-Antwort erhalten möchten, z. B. den verwendeten Antworttext URLConnection#getInputStream()und so weiter. Die obigen Beispiele tun genau das, also die connect() Ein Anruf ist in der Tat überflüssig.


Sammeln von HTTP-Antwortinformationen

  1. HTTP-Antwortstatus:

    Du brauchst ein HttpURLConnection Hier. Wirf es zuerst, wenn es nötig ist.

    int status = httpConnection.getResponseCode();
    
  2. HTTP-Antwortheader:

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

    Wenn das Content-Type enthält ein charset Parameter, dann ist der Antworttext wahrscheinlich textbasiert und wir möchten den Antworttext dann mit der serverseitig angegebenen Zeichencodierung verarbeiten.

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

Aufrechterhaltung der Sitzung

Die serverseitige Sitzung wird normalerweise von einem Cookie unterstützt. Bei einigen Webformularen müssen Sie angemeldet und / oder von einer Sitzung überwacht werden. Du kannst den ... benutzen CookieHandler API zum Verwalten von Cookies. Sie müssen ein vorbereiten CookieManager mit einem CookiePolicy von ACCEPT_ALL vor dem Senden aller HTTP-Anfragen.

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

Beachten Sie, dass dies unter allen Umständen nicht immer ordnungsgemäß funktioniert. Wenn es für Sie fehlschlägt, ist es am besten, die Cookie-Header manuell zu sammeln und festzulegen. Sie müssen im Grunde alle greifen Set-Cookie Header aus der Antwort der Anmeldung oder der ersten GET Anfrage und dann weiterleiten durch die nachfolgenden Anfragen.

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

Das split(";", 2)[0] gibt es Cookie-Attribute loszuwerden, die für die Serverseite irrelevant sind expires, pathusw. Alternativ könntest du auch verwenden cookie.substring(0, cookie.indexOf(';')) Anstatt von split().


Streaming-Modus

Das HttpURLConnection wird standardmäßig den Puffer puffern ganz Anfrage Körper vor dem eigentlichen Senden, unabhängig davon, ob Sie eine feste Inhaltslänge selbst mit festgelegt haben connection.setRequestProperty("Content-Length", contentLength);. Dies kann verursachen OutOfMemoryExceptions, wenn Sie gleichzeitig große POST-Anfragen senden (z. B. Dateien hochladen). Um dies zu vermeiden, möchten Sie die HttpURLConnection#setFixedLengthStreamingMode().

httpConnection.setFixedLengthStreamingMode(contentLength);

Aber wenn die Länge des Inhalts vorher nicht bekannt ist, können Sie den Chunked - Streaming - Modus nutzen, indem Sie den HttpURLConnection#setChunkedStreamingMode() entsprechend. Dies wird das HTTP setzen Transfer-Encoding Kopfzeile zu chunked Dadurch wird erzwungen, dass der Anfragetext in Blöcken gesendet wird. Das folgende Beispiel sendet den Körper in Blöcken von 1 KB.

httpConnection.setChunkedStreamingMode(1024);

User-Agent

Das kann passieren Eine Anfrage gibt eine unerwartete Antwort zurück, während sie mit einem echten Webbrowser funktioniert. Die Serverseite blockiert wahrscheinlich Anfragen basierend auf der User-Agent Anforderungsheader Das URLConnection wird standardmäßig auf eingestellt Java/1.6.0_19 wo der letzte Teil offensichtlich die JRE-Version ist. Sie können dies wie folgt überschreiben:

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.

Verwenden Sie die User-Agent-Zeichenfolge aus einem neuer Browser.


Fehlerbehandlung

Wenn der HTTP-Antwortcode lautet 4nn (Client Fehler) oder 5nn (Serverfehler), dann möchten Sie vielleicht die HttpURLConnection#getErrorStream() um zu sehen, ob der Server irgendwelche nützlichen Fehlerinformationen gesendet hat.

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

Wenn der HTTP-Antwortcode -1 ist, ist bei der Verarbeitung der Verbindung und der Antwort ein Fehler aufgetreten. Das HttpURLConnection Die Implementierung ist in älteren JREs etwas fehlerhaft und hält die Verbindungen am Leben. Vielleicht möchten Sie es ausschalten, indem Sie die Option http.keepAlive Systemeigenschaft zu false. Sie können dies programmatisch am Anfang Ihrer Anwendung tun, indem Sie:

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

Hochladen von Dateien

Sie würden normalerweise verwenden multipart/form-data Codierung für gemischten POST-Inhalt (Binär- und Zeichendaten). Die Kodierung wird detaillierter in beschrieben 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();
}

Wenn die andere Seite ein ist HttpServlet, dann ist es doPost() Methode wird aufgerufen und die Teile werden von verfügbar sein HttpServletRequest#getPart() (beachte so nicht  getParameter() und so weiter!). Das getPart() Methode ist jedoch relativ neu, es ist in Servlet 3.0 (Glassfish 3, Tomcat 7, etc.) eingeführt. Vor Servlet 3.0 ist Ihre beste Wahl zu verwenden Apache Commons FileUpload a multipart/form-data anfordern. Siehe auch diese Antwort Beispiele für beide Ansätze von FileUpload und Servelt 3.0.


Umgang mit nicht vertrauenswürdigen oder falsch konfigurierten HTTPS-Sites

Manchmal müssen Sie eine HTTPS-URL verbinden, vielleicht weil Sie einen Web-Scraper schreiben. In diesem Fall können Sie wahrscheinlich mit einem javax.net.ssl.SSLException: Not trusted server certificate auf einigen HTTPS-Sites, die ihre SSL-Zertifikate nicht auf dem neuesten Stand halten, oder a java.security.cert.CertificateException: No subject alternative DNS name matching [hostname] found oder javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name auf einigen falsch konfigurierten HTTPS-Sites.

Der folgende einmalige Durchlauf static Initialisierer in Ihrer Web-Scraper-Klasse sollte machen HttpsURLConnection Diese HTTPS-Sites werden weniger streng behandelt und diese Ausnahmen werden nicht mehr ausgelöst.

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

Letzte Worte

Das Apache HttpComponents HttpClient ist viel bequemer in diesem alles :)


Parsen und Extrahieren von HTML

Wenn Sie nur Daten aus HTML analysieren und extrahieren möchten, verwenden Sie besser einen HTML-Parser wie Jsoup


2525



Bei der Arbeit mit HTTP ist es fast immer sinnvoller, sich darauf zu beziehen HttpURLConnection eher als die Basisklasse URLConnection (schon seit URLConnection ist eine abstrakte Klasse, wenn Sie darum bitten URLConnection.openConnection() auf einer HTTP-URL, die Sie sowieso erhalten werden).

Dann können Sie sich darauf verlassen URLConnection#setDoOutput(true) implizit setzen Sie die Anfrage-Methode auf POST stattdessen tun httpURLConnection.setRequestMethod("POST") was einige natürlicher finden könnten (und die Ihnen auch erlaubt, andere Anfrage - Methoden wie STELLEN, LÖSCHEN, ...).

Es bietet auch nützliche HTTP-Konstanten, so dass Sie Folgendes tun können:

int responseCode = httpURLConnection.getResponseCode();

if (responseCode == HttpURLConnection.HTTP_OK) {

84



Inspiriert von diesen und anderen Fragen zu SO habe ich eine minimale Open Source geschaffen Basis-HTTP-Client das verkörpert die meisten der hier gefundenen Techniken.

Google-HTTP-Java-Client ist auch eine großartige Open-Source-Ressource.


49



Es gibt 2 Optionen, die Sie mit HTTP-URL-Hits aufrufen können: GET / POST

GET Anfrage: -

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-Anfrage: -

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



Ich schlage vor, Sie schauen sich den Code an Kevinsawicki / http-Anfrage, es ist im Grunde ein Wrapper oben auf HttpUrlConnection Es bietet eine viel einfachere API für den Fall, dass Sie nur die Anfragen sofort machen möchten oder Sie können sich die Quellen ansehen (es ist nicht zu groß), um einen Blick darauf zu werfen, wie Verbindungen gehandhabt werden.

Beispiel: Machen Sie a GET Anfrage mit Inhaltstyp application/json und einige Abfrageparameter:

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



Diese Antwort hat mich sehr inspiriert.

Ich bin oft auf Projekten, wo ich etwas HTTP tun muss, und ich möchte vielleicht nicht viele Abhängigkeiten von Drittanbietern einbringen (die andere hereinbringen und so weiter, usw.)

Ich fing an, meine eigenen Dienstprogramme zu schreiben, basierend auf einigen dieser Konversation (nicht wo getan):

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 {

Dann gibt es nur eine Reihe oder statische Methoden.

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

Dann post ...

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

Nun, Sie bekommen die Idee ....

Hier sind die 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);


}

Den Rest finden Sie hier:

https://github.com/RichardHightower/boon

Mein Ziel ist es, die allgemeinen Dinge, die man tun möchte, etwas einfacher zu machen als ...


19



Aktualisieren

Der neue HTTP-Client wurde mit Java 9 ausgeliefert, aber als Teil eines   Incubator-Modul benannt jdk.incubator.httpclient. Inkubatormodule sind   ein Mittel, um nicht-finale APIs in die Hände von Entwicklern zu geben, während die   APIs werden in der Zukunft entweder fertiggestellt oder entfernt   Freisetzung.

In Java 9 können Sie eine senden GET Anfrage wie:

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

Dann können Sie die zurückgegebenen überprüfen HttpResponse:

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

Da dieser neue HTTP-Client in ist java.httpclient  jdk.incubator.httpclient Modul sollten Sie diese Abhängigkeit in Ihrem module-info.java Datei:

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

15