web-dev-qa-db-ja.com

生のHTTP応答ヘッダーを取得する

生の応答httpヘッダーを取得する方法はありますか?

サーバーが複数の「Set-Cookie」を吐き出し、それらのいくつかが失われるため、getHeaderField()メソッドは機能しません。

10
p4553d

getHeaderField()メソッドが機能しません

_Java.net.URLConnection_ のコンテキストでこれを求めていますね?いいえ、URLconnectionでは生のHTTP応答ヘッダーを取得できません。低レベルにフォールバックする必要があります Socket プログラミング。これが [〜#〜] sscce [〜#〜] です。コピーして 'n'貼り付け 'n'実行してください。

_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) {} 
        }
    }

}
_

SOこのスニペットを試すすべての人によって過負荷になるのを避けるために、出力は次のようになります。

 HTTP/1.1 200 OK 
 Cache-Control:private 
 Content-Type:text/html; charset = utf-8 
有効期限:2010年2月21日日曜日20:39:08 GMT 
サーバー:Microsoft-IIS/7.5 
日付:2010年2月21日日曜日20:39 :07 GMT 
接続:閉じる
コンテンツの長さ:208969 

低レベルの方法でHTTPリクエストを送信する方法の詳細については、 HTTP仕様 をお読みください。

ただし、複数の値を持つヘッダーを取得する代わりに、 getHeaderFields() メソッドを使用することをお勧めします。 getHeaderField() つまり、リンクされたAPIドキュメントに従って、最後の値のみを返します。

_List<String> cookies = connection.getHeaderFields().get("Set-Cookie");
_
33
BalusC

正確には「生」ではありませんが、簡潔です。

for (Map.Entry<String, List<String>> k : myHttpURLConnection.getHeaderFields().entrySet()) {
    System.out.println(k.toString());
}

一部のヘッダーが使用できなくなることが心配な場合:

for (Map.Entry<String, List<String>> k : myHttpURLConnection.getHeaderFields().entrySet()) {
    for (String v : k.getValue()){
         System.out.println(k.getKey() + ":" + v);
    }
}

PS:決して遅くなるよりはましだ。 :)

6
ostergaard

簡単な方法は、URLConnectionの-​​ getHeaderFields() メソッドを使用することです。これは、同等のことを行うコードです。

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()]);
}
2
erickson

パーティーに遅れましたが、これが最も簡単な解決策です。 CookieStoreを実装するだけです。 (または、デフォルトの実装を使用して、後続の呼び出しにCookieを追加するようにします。)

http://docs.Oracle.com/javase/7/docs/api/Java/net/CookieStore.html

CookieストアをデフォルトのCookieマネージャーとして設定します

CookieManager cookieManager = new CookieManager(new MyCookieStore(), CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(cookieManager);

そして、すべての新しいCookieは、CookieStoreのadd()に表示されます。 1回のリクエストで同じ名前の「Set-Cookie」を使用してパラメータが上書きされるという同じ問題が発生しましたが、CookieとsessionIdの両方を取得するようになりました。

1
accordionfolder