POSTing data to netty with Apache HttpClient

2019-08-18 05:08发布

问题:

I'm trying to use Apache HttpClient (the fluent API) to POST data to a netty server.

I've tried a few variations, I'll put two here:

1.

Client:

Request.Post(uri).bodyString("content value", ContentType.TEXT_PLAIN).useExpectContinue().execute().returnContent().asString();

Server:

final HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(new DefaultHttpDataFactory(false), req);              
System.out.println(decoder.getBodyHttpDatas().size());

Calling getBodyHttpDatas() throws a:

io.netty.handler.codec.http.multipart.HttpPostRequestDecoder$NotEnoughDataDecoderException

2.

Client:

Request.Post(uri).bodyForm(new BasicNameValuePair("value", "content value")).useExpectContinue().execute().returnContent().asString();

Server:

final HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(new DefaultHttpDataFactory(false), req);
final InterfaceHttpData data1 = decoder.getBodyHttpData("value");

while (decoder.hasNext()) {
    final InterfaceHttpData data = decoder.next();
    if (data != null) {
        try {
            Attribute attribute = (Attribute) data;
            System.out.println(attribute.getValue());
        } finally {
            data.release();
        }
    }
}

This doesn't print any output - decoder.hasNext() is false.

回答1:

To solve the problem you either need to offer() all chunks (HttpContent) of a message to HttpPostRequestDecoder before calling getBodyHttpDatas(), or alternatively you can just add the HttpObjectAggregator handler right before your handler to the channel's pipeline. If you do so, HttpObjectAggregator will collect all chunks for you and produce a single FullHttpRequest in place of multiple chunks. Passing FullHttpRequest instead of an ordinary HttpRequest to HttpPostRequestDecoder's constructor eliminates need to offer() chunks.

So you just need to pipeline.addLast(new HttpObjectAggregator(1048576)) before adding your handler. For example:

public class YourServerInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    public void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(new HttpServerCodec());
        pipeline.addLast(new HttpObjectAggregator(1048576));
        pipeline.addLast(new YourServerHandler());
    }
}

1048576 here is the maximum length of the aggregated content. You are free to pass another value.



标签: java http netty