获取将从HttpGet发送的原始HTTP请求消息?

时间:2014-08-11 11:27:55

标签: java apache-commons-httpclient apache-httpcomponents

如何在Apache http组件v4.3.5中获取完整的原始HTTP请求消息。 我设法只获得解析后的响应。

public String get(String uri) {
    try (CloseableHttpClient httpclient = HttpClients.createDefault(); CloseableHttpResponse response1 = httpclient.execute(new HttpGet(uri))) {
        HttpEntity entity = response1.getEntity();
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        entity.writeTo(byteArrayOutputStream);
        return new String(byteArrayOutputStream.toByteArray());
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

有类似的answer but for the old 3.1 version of apache commons-http v3.1。我怎么做v4.3.5?

1 个答案:

答案 0 :(得分:1)

让它像这样工作。不是最优雅,因为流被复制到内存,但适用于我的用例。

public class TestHttpClient {
    public String get(String uri) {
        StreamRecorder streamRecorder = new StreamRecorder();
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", new ListeningSocketFactory(streamRecorder))
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        try (CloseableHttpClient httpclient = HttpClients.custom().setConnectionManager(connManager).build(); CloseableHttpResponse response1 = httpclient.execute(new HttpGet(uri))) {
            HttpEntity entity = response1.getEntity();
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            entity.writeTo(byteArrayOutputStream);
            return new String(streamRecorder.getRecordedStreamAsCharArray());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        String s = new TestHttpClient().get("http://onet.pl");
        System.out.println("---------------------\n" +
                "RESULT:\n" +
                "---------------------" +
                "\n" + s.substring(0, Math.min(s.length(), 200)));
    }
}

public class ListeningSocketFactory extends PlainConnectionSocketFactory {
    private final CopyInputStream.InputStreamListener streamListener;

    public ListeningSocketFactory(StreamRecorder streamListener) {
        this.streamListener = streamListener;
    }

    @Override
    public Socket createSocket(HttpContext context) throws IOException {
        return new SocketWithInputStreamListener(streamListener);
    }

}

class StreamRecorder implements CopyInputStream.InputStreamListener {
    private final List<Integer> streamCopy = new ArrayList<>(1000);

    @Override
    public synchronized void processByte(int readByte) {
        streamCopy.add(readByte);
    }

    public synchronized char[] getRecordedStreamAsCharArray() {
        char[] result = new char[streamCopy.size()];
        for (int i = 0; i < streamCopy.size(); i++) {
            result[i] = (char) i;
        }
        return result;
    }
}


public class CopyInputStream extends FilterInputStream {
    private final InputStreamListener streamListener;

    CopyInputStream(InputStream in, InputStreamListener streamListener) {
        super(in);
        this.streamListener = streamListener;
    }

    @Override
    public int read() throws IOException {
        int readByte = super.read();
        processByte(readByte);
        return readByte;
    }

    @Override
    public int read(byte[] buffer, int offset, int count) throws IOException {
        int readBytes = super.read(buffer, offset, count);
        processBytes(buffer, offset, readBytes);
        return readBytes;
    }

    private void processBytes(byte[] buffer, int offset, int readBytes) {
        for (int i = 0; i < readBytes; i++) {
            processByte(buffer[i + offset]);
        }
    }

    private void processByte(int readByte) {
        streamListener.processByte(readByte);
    }

    interface InputStreamListener {
        void processByte(int readByte);
    }
}