【问题标题】:Get the full, raw HTTP request message that would be sent from an HttpPost获取将从 HttpPost 发送的完整的原始 HTTP 请求消息
【发布时间】:2012-11-21 21:17:09
【问题描述】:

我正在尝试构建原始 HTTP POST 请求。但是,我不想实际连接到服务器并发送消息。

我一直在研究 Apache HTTP 库,希望我可以创建一个 HttpPost 对象,设置实体,然后获取它会创建的消息。到目前为止,我可以转储实体,但不能转储整个请求,因为它会出现在服务器端。

有什么想法吗?当然,除了重新创建轮子。

解决方案

我将 ShyJ 的响应重构为一对静态类,但原始响应运行良好。这是两个类:

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;
}

【问题讨论】:

    标签: java apache http post


    【解决方案1】:

    使用 HttpClient 4.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
    
    
    

    【讨论】:

      【解决方案2】:

      这可以通过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
      

      【讨论】:

        【解决方案3】:

        我要做的是实现一个或多个 HttpClient 的接口,并使用我的无操作实现。

        查看ClientConnectionManagerAbstractHttpClient,例如。任何连接。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-16
          • 1970-01-01
          • 1970-01-01
          • 2014-11-15
          • 1970-01-01
          • 2018-08-07
          • 2023-03-24
          • 2019-12-11
          相关资源
          最近更新 更多