-
Notifications
You must be signed in to change notification settings - Fork 375
Description
By default the Netty Connector uses CHUNKED transfer encoding. This is fine in many cases but sometimes it is required to use a request that contains a "Content-Length" header, for example Azure Blob Storage requires this.
Changing to BUFFERED mode can be done either by setting the "RequestEntityProcessing.BUFFERED" property or by specifying a "Content-Length" header. But both these triggers a bug which will create a "read timeout" in every other request. So request 2, 4, 6 and so on will hang until the configured read timeout is reached. It looks like the "Channel" ends up in an incorrect state. At least POST and PUT are affected.
This issue can be found in all the latest versions of the connector ("2.47", "3.1.11" and "4.0.0").
This can be replicated using the following:
POM
<dependency> <groupId>org.glassfish.jersey.connectors</groupId> <artifactId>jersey-netty-connector</artifactId> <version>2.47</version> </dependency>
Code
`
package com.test;
// Same issue for "jakarta.ws.rs.client" package
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.Invocation.Builder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.client.ClientProperties;
import org.glassfish.jersey.client.RequestEntityProcessing;
import org.glassfish.jersey.netty.connector.NettyConnectorProvider;
public class App {
private static Client client = null;
// Initializes the client on first request
public static Client getClient() {
if (client == null) {
client = ClientBuilder.newBuilder()
.property(ClientProperties.CONNECTOR_PROVIDER, NettyConnectorProvider.class.getName())
.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.BUFFERED)
.build();
}
return client;
}
private static String executeRequest(final String url, final String body) {
// Create the request
WebTarget target = getClient().target(url);
Builder builder = target.request();
// builder.header("Content-Length", body.getBytes(StandardCharsets.UTF_8).length); // Setting this doesn't resolve the issue
Invocation invocation = builder.build("POST", Entity.entity(body, "application/json"));
// Invoke the request
try (Response response = invocation.invoke()) {
return response.hasEntity() ? response.readEntity(String.class) : null;
}
}
public static void main(String[] args) {
final String url = "https://echo.free.beeceptor.com/";
final String body = "{}";
System.out.println(executeRequest(url, body));
System.out.println(executeRequest(url, body));
}
}
`