Faire une requête HTTP simple en Java

Faire une requête HTTP simple en Java

1. Vue d'ensemble

Dans ce rapide tutoriel, nous allons présenter unway of performing HTTP requests in Java - en utilisant la classe Java intégréeHttpUrlConnection.

Lectures complémentaires:

Un guide pour les cookies HTTP en Java

Un guide rapide et pratique sur les cookies HTTP en Java

Read more

Exploration du nouveau client HTTP dans Java 9 et 11

Découvrez la nouvelle API HttpClient de Java 9 qui offre une grande flexibilité et des fonctionnalités puissantes.

Read more

Serveurs Web et d'applications pour Java

Une liste rapide des serveurs Web et d'applications disponibles en Java.

Read more

2. HttpUrlConnection

La classeHttpUrlConnection nous permet deperform basic HTTP requests without the use of any additional libraries. Toutes les classes nécessaires sont contenues dans le packagejava.net.

Les inconvénients de l'utilisation de cette méthode sont quethe code can be more cumbersome than other HTTP libraries, and it does not provide more advanced functionalities such as dedicated methods for adding headers or authentication.

3. Créer une demande

A HttpUrlConnection instance is created by using the openConnection() method of the URL class. Notez que cette méthode crée uniquement un objet de connexion, mais n'établit pas encore la connexion.

La classeHttpUrlConnection est utilisée pour tous les types de requêtes en définissant l'attributrequestMethod sur l'une des valeurs: GET, POST, HEAD, OPTIONS, PUT, DELETE, TRACE.

Créons une connexion à une URL donnée à l'aide de la méthode GET:

URL url = new URL("http://example.com");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");

4. Ajout de paramètres de demande

Si nous voulons ajouter des paramètres à une requête, nous devons définir la propriétédoOutput surtrue, puis écrire unString de la formeparam1=value¶m2=value dans leOutputStream de l'instanceHttpUrlConnection:

Map parameters = new HashMap<>();
parameters.put("param1", "val");

con.setDoOutput(true);
DataOutputStream out = new DataOutputStream(con.getOutputStream());
out.writeBytes(ParameterStringBuilder.getParamsString(parameters));
out.flush();
out.close();

Pour faciliter la transformation desparameter Map, nous avons écrit une classe d'utilité appeléeParameterStringBuilder contenant une méthode statiquegetParamsString() qui transforme unMap en unString du format requis:

public class ParameterStringBuilder {
    public static String getParamsString(Map params)
      throws UnsupportedEncodingException{
        StringBuilder result = new StringBuilder();

        for (Map.Entry entry : params.entrySet()) {
          result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
          result.append("=");
          result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
          result.append("&");
        }

        String resultString = result.toString();
        return resultString.length() > 0
          ? resultString.substring(0, resultString.length() - 1)
          : resultString;
    }
}

5. Définition des en-têtes de demande

L'ajout d'en-têtes à une requête peut être réalisé en utilisant la méthodesetRequestProperty():

con.setRequestProperty("Content-Type", "application/json");

Pour lire la valeur d'un en-tête à partir d'une connexion, nous pouvons utiliser la méthodegetHeaderField():

String contentType = con.getHeaderField("Content-Type");

6. Configuration des délais d'expiration

La classeHttpUrlConnection autorisesetting the connect and read timeouts. Ces valeurs définissent l'intervalle de temps nécessaire pour que la connexion au serveur soit établie ou que les données soient disponibles pour la lecture.

Pour définir les valeurs de délai d'expiration, nous pouvons utiliser les méthodessetConnectTimeout() etsetReadTimeout():

con.setConnectTimeout(5000);
con.setReadTimeout(5000);

Dans l'exemple ci-dessus, nous avons défini les deux valeurs de délai d'attente sur 5 secondes.

7. Gestion des cookies

Le packagejava.net contient des classes qui facilitent l'utilisation des cookies tels queCookieManager etHttpCookie.

Tout d'abord, pourread the cookies from a response, nous pouvons récupérer la valeur de l'en-têteSet-Cookie et l'analyser en une liste d'objetsHttpCookie:

String cookiesHeader = con.getHeaderField("Set-Cookie");
List cookies = HttpCookie.parse(cookiesHeader);

Ensuite, nous allonsadd the cookies to the cookie store:

cookies.forEach(cookie -> cookieManager.getCookieStore().add(null, cookie));

Vérifions si un cookie appeléusername est présent, et sinon, nous l’ajouterons au magasin de cookies avec la valeur "john":

Optional usernameCookie = cookies.stream()
  .findAny().filter(cookie -> cookie.getName().equals("username"));
if (usernameCookie == null) {
    cookieManager.getCookieStore().add(null, new HttpCookie("username", "john"));
}

Enfin, àadd the cookies to the request, nous devons définir l'en-têteCookie, après la fermeture et la réouverture de la connexion:

con.disconnect();
con = (HttpURLConnection) url.openConnection();

con.setRequestProperty("Cookie",
  StringUtils.join(cookieManager.getCookieStore().getCookies(), ";"));

8. Gestion des redirections

On peutenable or disable automatically following redirects for a specific connection en utilisant la méthodesetInstanceFollowRedirects() avec le paramètretrue oufalse:

con.setInstanceFollowRedirects(false);

Il est également possible deenable or disable automatic redirect for all connections:

HttpUrlConnection.setFollowRedirects(false);

Par défaut, le comportement est activé.

Lorsqu'une requête retourne un code d'état 301 ou 302, indiquant une redirection, nous pouvons récupérer l'en-têteLocation et créer une nouvelle requête vers la nouvelle URL:

if (status == HttpURLConnection.HTTP_MOVED_TEMP
  || status == HttpURLConnection.HTTP_MOVED_PERM) {
    String location = con.getHeaderField("Location");
    URL newUrl = new URL(location);
    con = (HttpURLConnection) newUrl.openConnection();
}

9. Lire la réponse

La lecture de la réponse à la requête peut être effectuée parparsing the InputStream of the HttpUrlConnection instance.

Pour exécuter la requête, nous pouvons utiliser les méthodesgetResponseCode(), connect(), getInputStream() ougetOutputStream():

int status = con.getResponseCode();

Enfin, lisons la réponse de la requête et placez-la dans une chaînecontent:

BufferedReader in = new BufferedReader(
  new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer content = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    content.append(inputLine);
}
in.close();

Pourclose the connection, nous pouvons utiliser la méthodedisconnect():

con.disconnect();

10. Lecture de la réponse aux demandes échouées

Si la demande échoue, essayer de lire lesInputStream de l'instanceHttpUrlConnection ne fonctionnera pas. Au lieu de cela,we can consume the stream provided by HttpUrlConnection.getErrorStream().

Nous pouvons décider quelsInputStream utiliser en comparant le code d'état HTTP:

int status = con.getResponseCode();

Reader streamReader = null;

if (status > 299) {
    streamReader = new InputStreamReader(con.getErrorStream());
} else {
    streamReader = new InputStreamReader(con.getInputStream());
}

Et enfin, on peut lire lesstreamReader de la même manière que la section précédente.

11. Construire la réponse complète

Il n’est pas possible d’obtenir la représentation complète de la réponse à l’aide de l’instanceHttpUrlConnection .

Cependant,we can build it using some of the methods that the HttpUrlConnection instance offers:

public class FullResponseBuilder {
    public static String getFullResponse(HttpURLConnection con) throws IOException {
        StringBuilder fullResponseBuilder = new StringBuilder();

        // read status and message

        // read headers

        // read response content

        return fullResponseBuilder.toString();
    }
}

Ici, nous lisons les parties des réponses, y compris le code d'état, le message d'état et les en-têtes, et les ajoutons à une instanceStringBuilder.

Tout d'abord, ajoutons les informations sur l'état de la réponse:

fullResponseBuilder.append(con.getResponseCode())
  .append(" ")
  .append(con.getResponseMessage())
  .append("\n");

Next, we’ll get the headers using getHeaderFields()and ajoutez chacun d'eux à nosStringBuilder au format HeaderName:HeaderValues:

con.getHeaderFields().entrySet().stream()
  .filter(entry -> entry.getKey() != null)
  .forEach(entry -> {
      fullResponseBuilder.append(entry.getKey()).append(": ");
      List headerValues = entry.getValue();
      Iterator it = headerValues.iterator();
      if (it.hasNext()) {
          fullResponseBuilder.append(it.next());
          while (it.hasNext()) {
              fullResponseBuilder.append(", ").append(it.next());
          }
      }
      fullResponseBuilder.append("\n");
});

Finally, we’ll read the response content comme nous l'avons fait précédemment et ajoutez-le.

Notez que la méthodegetFullResponse validera si la requête a réussi ou non afin de décider si elle doit utilisercon.getInputStream() oucon.getErrorStream() pour récupérer le contenu de la requête.

12. Conclusion

Dans cet article, nous avons montré comment nous pouvons effectuer des requêtes HTTP à l'aide de la classeHttpUrlConnection. Le code source complet des exemples peut être trouvéover on GitHub.