This is an automated email from the ASF dual-hosted git repository.
reta pushed a commit to branch 3.3.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git
The following commit(s) were added to refs/heads/3.3.x-fixes by this push:
new 1ffa6ae [CXF-8565] Add support for requests with no body to the netty
client transport There were several issues with the netty client transport:
1ffa6ae is described below
commit 1ffa6ae57f09675e8cce2b7fd669d1f7eda15e84
Author: Tim Ward <[email protected]>
AuthorDate: Wed Jul 21 14:47:59 2021 +0100
[CXF-8565] Add support for requests with no body to the netty client
transport
There were several issues with the netty client transport:
* Several NPE locations due to setting or removing null headers
* No call to connect when there is no OutputStream to write a body
* No call to write the request when there is no OutputStream to close
Signed-off-by: Tim Ward <[email protected]>
(cherry picked from commit fc5b8fd8689815ee3bff284b89ac8d9cb897e83b)
---
.../http/netty/client/NettyHttpConduit.java | 62 +++++++++++++++++++---
1 file changed, 54 insertions(+), 8 deletions(-)
diff --git
a/rt/transports/http-netty/netty-client/src/main/java/org/apache/cxf/transport/http/netty/client/NettyHttpConduit.java
b/rt/transports/http-netty/netty-client/src/main/java/org/apache/cxf/transport/http/netty/client/NettyHttpConduit.java
index f5d4e7a..cd358d4 100644
---
a/rt/transports/http-netty/netty-client/src/main/java/org/apache/cxf/transport/http/netty/client/NettyHttpConduit.java
+++
b/rt/transports/http-netty/netty-client/src/main/java/org/apache/cxf/transport/http/netty/client/NettyHttpConduit.java
@@ -32,6 +32,8 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.security.Principal;
import java.security.cert.Certificate;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -78,6 +80,9 @@ public class NettyHttpConduit extends
URLConnectionHTTPConduit implements BusLif
public static final String MAX_RESPONSE_CONTENT_LENGTH =
"org.apache.cxf.transport.http.netty.maxResponseContentLength";
static final Integer DEFAULT_MAX_RESPONSE_CONTENT_LENGTH = 1048576;
+ private static final Set<String> KNOWN_HTTP_VERBS_WITH_NO_CONTENT =
+ new HashSet<>(Arrays.asList(new String[]{"GET", "HEAD", "OPTIONS",
"TRACE"}));
+
final NettyHttpConduitFactory factory;
private Bootstrap bootstrap;
@@ -197,7 +202,10 @@ public class NettyHttpConduit extends
URLConnectionHTTPConduit implements BusLif
entity.createRequest(out.getOutBuffer());
// TODO need to check how to set the Chunked feature
//request.getRequest().setChunked(true);
- entity.getRequest().headers().set(Message.CONTENT_TYPE,
message.get(Message.CONTENT_TYPE));
+ Object contentType = message.get(Message.CONTENT_TYPE);
+ if (contentType != null) {
+ entity.getRequest().headers().set(Message.CONTENT_TYPE,
contentType);
+ }
return out;
}
return super.createOutputStream(message, needToCacheRequest,
isChunking, chunkThreshold);
@@ -314,7 +322,7 @@ public class NettyHttpConduit extends
URLConnectionHTTPConduit implements BusLif
synchronized (entity) {
Channel syncChannel = getChannel();
- ChannelFuture channelFuture =
syncChannel.write(entity);
+ ChannelFuture channelFuture =
syncChannel.writeAndFlush(entity);
channelFuture.addListener(listener);
outputStream.close();
}
@@ -328,6 +336,11 @@ public class NettyHttpConduit extends
URLConnectionHTTPConduit implements BusLif
wrappedStream = cachedStream;
}
}
+
+ @Override
+ protected void handleNoOutput() throws IOException {
+ connect(false);
+ }
protected TLSClientParameters findTLSClientParameters() {
TLSClientParameters clientParameters =
outMessage.get(TLSClientParameters.class);
@@ -378,11 +391,6 @@ public class NettyHttpConduit extends
URLConnectionHTTPConduit implements BusLif
connFuture.addListener(listener);
- if (!output) {
- entity.getRequest().headers().remove("Transfer-Encoding");
- entity.getRequest().headers().remove("Content-Type");
- entity.getRequest().headers().remove(null);
- }
// setup the CxfResponseCallBack
CxfResponseCallBack callBack = new CxfResponseCallBack() {
@@ -398,6 +406,29 @@ public class NettyHttpConduit extends
URLConnectionHTTPConduit implements BusLif
};
entity.setCxfResponseCallback(callBack);
+ if (!output) {
+ entity.getRequest().headers().remove("Transfer-Encoding");
+ entity.getRequest().headers().remove("Content-Type");
+
+ ChannelFutureListener writeFailureListener = new
ChannelFutureListener() {
+ @Override
+ public void operationComplete(ChannelFuture future) throws
Exception {
+ if (!future.isSuccess()) {
+ setException(future.cause());
+ }
+ }
+ };
+
+ connFuture.addListener(new ChannelFutureListener() {
+ @Override
+ public void operationComplete(ChannelFuture future)
throws Exception {
+ if (future.isSuccess()) {
+ ChannelFuture channelFuture =
future.channel().writeAndFlush(entity);
+
channelFuture.addListener(writeFailureListener);
+ }
+ }
+ });
+ }
}
@Override
@@ -434,7 +465,7 @@ public class NettyHttpConduit extends
URLConnectionHTTPConduit implements BusLif
@Override
protected void setProtocolHeaders() throws IOException {
Headers h = new Headers(outMessage);
- entity.getRequest().headers().set(Message.CONTENT_TYPE,
h.determineContentType());
+ setContentTypeHeader(h);
boolean addHeaders = MessageUtils.getContextualBoolean(outMessage,
Headers.ADD_HEADERS_PROPERTY, false);
for (Map.Entry<String, List<String>> header :
h.headerMap().entrySet()) {
@@ -460,6 +491,21 @@ public class NettyHttpConduit extends
URLConnectionHTTPConduit implements BusLif
}
}
}
+
+ private void setContentTypeHeader(Headers headers) {
+ if (outMessage.get(Message.CONTENT_TYPE) == null) {
+ // if no content type is set then check for a request body
+ Object requestMethod =
outMessage.get(Message.HTTP_REQUEST_METHOD);
+ boolean emptyRequest =
KNOWN_HTTP_VERBS_WITH_NO_CONTENT.contains(requestMethod)
+ ||
PropertyUtils.isTrue(outMessage.get(Headers.EMPTY_REQUEST_PROPERTY));
+ // If it is not an empty request then add a content type
+ if (!emptyRequest) {
+ entity.getRequest().headers().set(Message.CONTENT_TYPE,
headers.determineContentType());
+ }
+ } else {
+ entity.getRequest().headers().set(Message.CONTENT_TYPE,
headers.determineContentType());
+ }
+ }
@Override
protected void setFixedLengthStreamingMode(int i) {