3

生のHTTPPOSTリクエストを作成しようとしています。ただし、実際にサーバーに接続してメッセージを送信したくありません。

私は、HttpPostオブジェクトを作成し、エンティティを設定して、作成されたはずのメッセージを取得できることを期待して、ApacheHTTPライブラリを調べてきました。これまでのところ、エンティティをダンプすることはできますが、サーバー側に表示されるリクエスト全体をダンプすることはできません。

何か案は?もちろん、ホイールを作り直すだけではありません。

解決

ShyJの応答を静的クラスのペアにリファクタリングしましたが、元の応答は問題なく機能します。2つのクラスは次のとおりです。

public static final class LoopbackPostMethod extends PostMethod {
    private static final String STATUS_LINE = "HTTP/1.1 200 OK";

    @Override
    protected void readResponse(HttpState state, HttpConnection conn) throws IOException, HttpException {
        statusLine = new StatusLine (STATUS_LINE);
    }
}

public static final class LoopbackHttpConnection extends HttpConnection {
    private static final String HOST = "127.0.0.1";
    private static final int PORT = 80;

    private final OutputStream fOutputStream;

    public LoopbackHttpConnection(OutputStream outputStream) {
        super(HOST, PORT);
        fOutputStream = outputStream;
    }

    @Override
    public void flushRequestOutputStream() throws IOException { /* do nothing */ }

    @Override
    public OutputStream getRequestOutputStream() throws IOException, IllegalStateException {
        return fOutputStream;
    }

    @Override
    public void write(byte[] data) throws IOException, IllegalStateException {
        fOutputStream.write(data);
    }
}

例として、私が自分の実装に使用しているファクトリメソッドを次に示します。

private ByteBuffer createHttpRequest(ByteBuffer data) throws HttpException, IOException {
    LoopbackPostMethod postMethod = new LoopbackPostMethod();
    final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    postMethod.setRequestEntity(new ByteArrayRequestEntity(data.array()));
    postMethod.execute(new HttpState(), new LoopbackHttpConnection(outputStream));
    byte[] bytes = outputStream.toByteArray();
    ByteBuffer buffer = ByteBuffer.allocate(bytes.length);
    buffer.put(bytes);
    return buffer;
}
4

3 に答える 3

4

これは、http-clientといくつかのメソッドを偽造することで達成できます。3.1のバージョンを使用しましたhttp-client

このコード:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.apache.commons.httpclient.HttpConnection;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.StatusLine;
import org.apache.commons.httpclient.methods.PostMethod;

public class Main {
    public static void main(String[] args) throws Exception {
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PostMethod method = new PostMethod () {
            @Override
            protected void readResponse(HttpState state, HttpConnection conn)
                    throws IOException, HttpException {
                statusLine = new StatusLine ("HTTP/1.1 200 OK");
            }
        };
        method.addParameter("aa", "b");

        method.execute(new HttpState (), new HttpConnection("http://www.google.abc/hi", 80) {

            @Override
            public void flushRequestOutputStream() throws IOException {
            }

            @Override
            public OutputStream getRequestOutputStream() throws IOException,
                    IllegalStateException {
                return baos;
            }

            @Override
            public void write(byte[] data) throws IOException,
                    IllegalStateException {
                baos.write(data);
            }

        });

        final String postBody = new String (baos.toByteArray());

        System.out.println(postBody);
    }
}

戻ります

POST / HTTP/1.1
User-Agent: Jakarta Commons-HttpClient/3.1
Host: http://www.google.abc/hi
Content-Length: 4
Content-Type: application/x-www-form-urlencoded

aa=b
于 2012-11-21T23:26:05.000 に答える
1

私が行うことは、1つ以上のHttpClientのインターフェイスを実装し、no-op実装を使用することです。

ClientConnectionManagerAbstractHttpClient、たとえば、任意の接続を見てください。

于 2012-11-21T21:57:56.657 に答える
1

HttpClient4.xを使用

    private static String toRawHttp(HttpUriRequest request) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        HttpTransportMetricsImpl outTransportMetrics = new HttpTransportMetricsImpl();
        SessionOutputBufferImpl buffer = new SessionOutputBufferImpl(outTransportMetrics, 1);
        HttpMessageWriter<HttpRequest> defaultHttpRequestWriter = DefaultHttpRequestWriterFactory.INSTANCE.create(buffer);
        DefaultHttpRequestWriterFactory writerFactory = new DefaultHttpRequestWriterFactory(null) {
            @Override
            public HttpMessageWriter<HttpRequest> create(SessionOutputBuffer buffer) {
                return defaultHttpRequestWriter;
            }
        };
        buffer.bind(baos);

        ConnectionConfig config = ConnectionConfig.DEFAULT;
        DefaultBHttpClientConnection connection = new DefaultBHttpClientConnection(config.getBufferSize(),
                                                                                   config.getFragmentSizeHint(),
                                                                                   ConnSupport.createDecoder(config),
                                                                                   ConnSupport.createEncoder(config),
                                                                                   config.getMessageConstraints(),
                                                                                   null,
                                                                                   null,
                                                                                   writerFactory,
                                                                                   null) {
            @Override
            protected void ensureOpen() {
                //using writerFactory buffer instead of socket
            }

            @Override
            protected OutputStream createOutputStream(long len, SessionOutputBuffer outbuffer) {
                if (len == ContentLengthStrategy.CHUNKED) {
                    return new ChunkedOutputStream(2048, buffer);
                } else if (len == ContentLengthStrategy.IDENTITY) {
                    return new IdentityOutputStream(buffer);
                } else {
                    return new ContentLengthOutputStream(buffer, len);
                }
            }
        };

        CloseableHttpClient client = HttpClients.custom()
                                                .setRequestExecutor(new HttpRequestExecutor() {

                                                    @Override
                                                    protected HttpResponse doSendRequest(HttpRequest request, HttpClientConnection conn, HttpContext context) throws IOException, HttpException {
                                                        // inject fake connection
                                                        return super.doSendRequest(request, connection, context);
                                                    }

                                                    @Override
                                                    protected HttpResponse doReceiveResponse(HttpRequest request, HttpClientConnection conn, HttpContext context) {
                                                        return new BasicHttpResponse(request.getProtocolVersion(), 200, "OK");
                                                    }
                                                })
                                                .build();
        client.execute(request);
        return new String(baos.toByteArray());
    }

使用:

 RequestBuilder builder = RequestBuilder.post(requestModel.getUrl()).addHeader("X-Hello","Word");
 System.out.println(toRawHttp(builder.build()));

印刷します:

POST /ff HTTP/1.1
X-Hello: Word
Host: localhost:8080
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.8 (Java/1.8.0_161)
Accept-Encoding: gzip,deflate


于 2019-05-26T14:49:49.233 に答える