Existe-t-il un moyen d'obtenir l'en-tête HTTP de réponse brute?Obtention d'en-têtes de réponse HTTP bruts
La méthode getHeaderField()
ne fonctionne pas pour moi, car le serveur crache plusieurs 'Set-Cookie' et certains d'entre eux sont perdus.
Existe-t-il un moyen d'obtenir l'en-tête HTTP de réponse brute?Obtention d'en-têtes de réponse HTTP bruts
La méthode getHeaderField()
ne fonctionne pas pour moi, car le serveur crache plusieurs 'Set-Cookie' et certains d'entre eux sont perdus.
La méthode
getHeaderField()
ne fonctionne pas pour moi
Vous vous demandez dans le contexte de java.net.URLConnection
, est-il? Non, l'obtention des en-têtes de réponse HTTP bruts n'est pas possible avec URLconnection
. Vous devrez revenir à la programmation de bas niveau Socket. Voici un SSCCE, il suffit de le copier et le coller.
package com.stackoverflow.q2307291;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
public class Test {
public static void main(String[] args) throws IOException {
String hostname = "stackoverflow.com";
int port = 80;
Socket socket = null;
PrintWriter writer = null;
BufferedReader reader = null;
try {
socket = new Socket(hostname, port);
writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
writer.println("GET/HTTP/1.1");
writer.println("Host: " + hostname);
writer.println("Accept: */*");
writer.println("User-Agent: Java"); // Be honest.
writer.println(""); // Important, else the server will expect that there's more into the request.
writer.flush();
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
for (String line; (line = reader.readLine()) != null;) {
if (line.isEmpty()) break; // Stop when headers are completed. We're not interested in all the HTML.
System.out.println(line);
}
} finally {
if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) {}
if (writer != null) { writer.close(); }
if (socket != null) try { socket.close(); } catch (IOException logOrIgnore) {}
}
}
}
Pour éviter SO surcharge par tout le monde essaie cet extrait, voici comment la sortie ressemblera:
HTTP/1.1 200 OK Cache-Control: private Content-Type: text/html; charset=utf-8 Expires: Sun, 21 Feb 2010 20:39:08 GMT Server: Microsoft-IIS/7.5 Date: Sun, 21 Feb 2010 20:39:07 GMT Connection: close Content-Length: 208969
Pour en savoir plus sur l'envoi de requêtes HTTP la voie de bas niveau, lisez le HTTP specification.
Toutefois, vous souhaiterez probablement utiliser la méthode getHeaderFields()
à la place pour récupérer un en-tête avec plusieurs valeurs. Le getHeaderField()
renvoie uniquement la dernière valeur, selon le document API lié.
List<String> cookies = connection.getHeaderFields().get("Set-Cookie");
Heys dites-vous que 'java.net.URLConnection' est construit sur ces méthodes? – Pacerier
"L'obtention des en-têtes de réponse HTTP bruts n'est pas possible avec' URLConnection' "? Que retourne 'getHeaderField (int)'? – erickson
@erickson: il analyse les en-têtes de réponse brutes et renvoie la valeur de l'en-tête sur l'index donné. Il ne renvoie pas les en-têtes de réponse bruts exactement comme indiqué dans la citation dans ma réponse. Je crois que vous interprétez mal dans le contexte de cette question. Avez-vous d'ailleurs lu l'indice 'getHeaderFields()' au bas de ma réponse? Btw: Je n'ai pas downvote votre réponse :) – BalusC
Le plus simple est d'utiliser la méthode getHeaderFields()
de URLConnection
. Voici un code qui fait quelque chose d'équivalent.
static String[] getHeaders(HttpURLConnection con, String header) {
List<String> values = new ArrayList<String>();
int idx = (con.getHeaderFieldKey(0) == null) ? 1 : 0;
while (true) {
String key = con.getHeaderFieldKey(idx);
if (key == null)
break;
if (header.equalsIgnoreCase(key))
values.add(con.getHeaderField(idx));
++idx;
}
return values.toArray(new String[values.size()]);
}
Cette réponse est incorrecte? – Pacerier
@Pacerier L'avez vous essayé? Qu'avez-vous trouvé être incorrect? – erickson
Je reçois des en-têtes 'Set-Cookie' vides. Deux ou trois d'entre eux, selon ce que l'autre partie envoie. Les autres en-têtes fonctionnent bien. Le problème ne semble pas se situer dans l'impression car 'connection.getRequestProperties()' indique 'Set-Cookies = [,]'. Les cookies sont 'sécurisés; HTTPOnly', mais cela ne devrait pas avoir d'importance en Java. Étrange, n'est-ce pas? – maaartinus
Pas exactement 'brute' mais concise:
for (Map.Entry<String, List<String>> k : myHttpURLConnection.getHeaderFields().entrySet()) {
System.out.println(k.toString());
}
Si vous vous inquiétez que certains des en-têtes OBTIENNENT utilisation perdus:
for (Map.Entry<String, List<String>> k : myHttpURLConnection.getHeaderFields().entrySet()) {
for (String v : k.getValue()){
System.out.println(k.getKey() + ":" + v);
}
}
PS: Mieux vaut tard que jamais. :)
Je n'ai pas testé votre exemple, mais je pense que getHeaderFields renvoie une seule valeur pour un champ. Cela conduit à des problèmes, si vous obtenez plusieurs champs avec un nom égal, par exemple "Set-Cookies" est l'un d'entre eux. – p4553d
@ p4553d - C'est pourquoi entrySet renvoie une liste
En retard à la fête, mais voici la solution la plus simple. Implémentez simplement CookieStore. (Ou utiliser l'implémentation par défaut et laissez-le prendre soin d'ajouter les cookies pour vos appels.)
http://docs.oracle.com/javase/7/docs/api/java/net/CookieStore.html
Définissez votre magasin cookie en tant que gestionnaire de cookies par défaut
CookieManager cookieManager = new CookieManager(new MyCookieStore(), CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(cookieManager);
Et chaque nouveau cookie vous apparaîtra dans add() dans votre CookieStore. J'ai eu le même problème avec les paramètres étant écrasés en ayant le même nom "Set-Cookie" dans une seule demande, et maintenant je reçois à la fois le cookie et le sessionId.
Il semble que vous utilisiez une bibliothèque comme Apache HTTP Client? Serait utile d'indiquer que si oui, puisque je suppose que vous demandez si cette bibliothèque particulière a une telle méthode. –
Serait utile, mais je pense qu'il n'utilise pas le client apache mais la bibliothèque standard Java: http://docs.oracle.com/javase/6/docs/api/java/net/URLConnection.html#getHeaderField(java.lang. Chaîne) – thermz