Skip to content

Commit

Permalink
HTTP 100-Continue handling arranged
Browse files Browse the repository at this point in the history
Signed-off-by: Maxim Nesen <maxim.nesen@oracle.com>
  • Loading branch information
senivam committed Sep 24, 2020
1 parent 5417a87 commit 3b1d207
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -406,16 +406,16 @@ public final class ClientProperties {
public static final String REQUEST_ENTITY_PROCESSING = "jersey.config.client.request.entity.processing";

/**
* Registers 100-Continue value for Expect header processing to be set in HttpUrlConnector (default Jersey
* connector)
* Allows for HTTP Expect:100-Continue being handled by the HttpUrlConnector (default Jersey
* connector).
*
* @since 2.32
*/
public static final String EXPECT_100_CONTINUE = "jersey.config.client.request.expect.100.continue.processing";

/**
* Property for threshold size for content length after which Expect:100-Continue header would be applied
* before the main request
* before the main request.
*
* @since 2.32
*/
Expand All @@ -424,11 +424,11 @@ public final class ClientProperties {

/**
* Default threshold size (64kb) after which which Expect:100-Continue header would be applied before
* the main request
* the main request.
*
* @since 2.32
*/
public static final Long DEFAULT_EXPECT_100_CONTINUE_THRESHOLD_SIZE = 64000L;
public static final Long DEFAULT_EXPECT_100_CONTINUE_THRESHOLD_SIZE = 65536L;

private ClientProperties() {
// prevents instantiation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,30 @@ public class Expect100ContinueFeature implements Feature {
public Expect100ContinueFeature() {
this(ClientProperties.DEFAULT_EXPECT_100_CONTINUE_THRESHOLD_SIZE);
}
public Expect100ContinueFeature(long thresholdSize) {

private Expect100ContinueFeature(long thresholdSize) {
this.thresholdSize = thresholdSize;
}

/**
* Creates Expect100ContinueFeature with custom (not default) threshold size for content length.
*
* @param thresholdSize size of threshold
* @return Expect100Continue Feature
*/
public static Expect100ContinueFeature withCustomThreshold(long thresholdSize) {
return new Expect100ContinueFeature(thresholdSize);
}

/**
* Creates Expect100Continue Feature with default threshold size
*
* @return Expect100Continue Feature
*/
public static Expect100ContinueFeature basic() {
return new Expect100ContinueFeature();
}

@Override
public boolean configure(FeatureContext configurableContext) {
if (configurableContext.getConfiguration().getProperty(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,14 +333,8 @@ private ClientResponse _apply(final ClientRequest request) throws IOException {
if (entity != null) {
RequestEntityProcessing entityProcessing = request.resolveProperty(
ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.class);
final Long expectContinueSizeThreshold = ClientProperties.getValue(
request.getConfiguration().getProperties(),
ClientProperties.EXPECT_100_CONTINUE_THRESHOLD_SIZE,
ClientProperties.DEFAULT_EXPECT_100_CONTINUE_THRESHOLD_SIZE, Long.class);

final long length = request.getLengthLong();
final boolean allowStreaming = length > expectContinueSizeThreshold
|| entityProcessing == RequestEntityProcessing.CHUNKED;

if (entityProcessing == null || entityProcessing != RequestEntityProcessing.BUFFERED) {
if (fixLengthStreaming && length > 0) {
Expand All @@ -358,7 +352,7 @@ private ClientResponse _apply(final ClientRequest request) throws IOException {
}
}

processExpect100Continue(request, uc, allowStreaming);
processExpect100Continue(request, uc, length, entityProcessing);

request.setStreamProvider(contentLength -> {
setOutboundHeaders(request.getStringHeaders(), uc);
Expand Down Expand Up @@ -536,10 +530,18 @@ public Object run() throws NoSuchFieldException,
}
}

private void processExpect100Continue(ClientRequest request, HttpURLConnection uc, boolean allowStreaming) {
private void processExpect100Continue(ClientRequest request, HttpURLConnection uc,
long length, RequestEntityProcessing entityProcessing) {

final Boolean expectContinueActivated = ClientProperties.getValue(request.getConfiguration().getProperties(),
ClientProperties.EXPECT_100_CONTINUE, Boolean.class);
final Long expectContinueSizeThreshold = ClientProperties.getValue(
request.getConfiguration().getProperties(),
ClientProperties.EXPECT_100_CONTINUE_THRESHOLD_SIZE,
ClientProperties.DEFAULT_EXPECT_100_CONTINUE_THRESHOLD_SIZE, Long.class);

final boolean allowStreaming = length > expectContinueSizeThreshold
|| entityProcessing == RequestEntityProcessing.CHUNKED;

if (!Boolean.TRUE.equals(expectContinueActivated)
|| !("POST".equals(uc.getRequestMethod()) || "PUT".equals(uc.getRequestMethod()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
public class Expect100ContinueTest extends JerseyTest {

private static final String RESOURCE_PATH = "expect";
private static final String ENTITY_STRING = "1234567890123456789012345678901234567890123456789012"
+ "3456789012345678901234567890";


@Path(RESOURCE_PATH)
public static class Expect100ContinueResource {
Expand Down Expand Up @@ -73,52 +76,50 @@ protected void configureClient(ClientConfig config) {

@Test
public void testExpect100Continue() {
final Response response = target(RESOURCE_PATH).request().post(Entity.text("123456789012345678901234"
+ "56789012345678901234567890123456789012345678901234567890"));
final Response response = target(RESOURCE_PATH).request().post(Entity.text(ENTITY_STRING));
assertEquals("Expected 200", 200, response.getStatus()); //no Expect header sent - responce OK
}

@Test
public void testExpect100ContinueChunked() {
final Response response = target(RESOURCE_PATH).register(new Expect100ContinueFeature())
final Response response = target(RESOURCE_PATH).register(Expect100ContinueFeature.basic())
.property(ClientProperties.REQUEST_ENTITY_PROCESSING,
RequestEntityProcessing.CHUNKED).request().post(Entity.text("123456789012345678901234"
+ "56789012345678901234567890123456789012345678901234567890"));
RequestEntityProcessing.CHUNKED).request().post(Entity.text(ENTITY_STRING));
assertEquals("Expected 204", 204, response.getStatus()); //Expect header sent - No Content response
}

@Test
public void testExpect100ContinueBuffered() {
final Response response = target(RESOURCE_PATH).register(new Expect100ContinueFeature())
final Response response = target(RESOURCE_PATH).register(Expect100ContinueFeature.basic())
.property(ClientProperties.REQUEST_ENTITY_PROCESSING,
RequestEntityProcessing.BUFFERED).request().header(HttpHeaders.CONTENT_LENGTH, 65000L)
.post(Entity.text("12345678901234567890123456789012345678901234567890123456789012345678901234567890"));
RequestEntityProcessing.BUFFERED).request().header(HttpHeaders.CONTENT_LENGTH, 67000L)
.post(Entity.text(ENTITY_STRING));
assertEquals("Expected 204", 204, response.getStatus()); //Expect header sent - No Content response
}

@Test
public void testExpect100ContinueCustomLength() {
final Response response = target(RESOURCE_PATH).register(new Expect100ContinueFeature(100L))
final Response response = target(RESOURCE_PATH).register(Expect100ContinueFeature.withCustomThreshold(100L))
.request().header(HttpHeaders.CONTENT_LENGTH, 101L)
.post(Entity.text("12345678901234567890123456789012345678901234567890123456789012345678901234567890"));
.post(Entity.text(ENTITY_STRING));
assertEquals("Expected 204", 204, response.getStatus()); //Expect header sent - No Content response
}

@Test
public void testExpect100ContinueCustomLengthWrong() {
final Response response = target(RESOURCE_PATH).register(new Expect100ContinueFeature(100L))
final Response response = target(RESOURCE_PATH).register(Expect100ContinueFeature.withCustomThreshold(100L))
.request().header(HttpHeaders.CONTENT_LENGTH, 99L)
.post(Entity.text("12345678901234567890123456789012345678901234567890123456789012345678901234567890"));
assertEquals("Expected 200", 200, response.getStatus()); //Expect header sent - No Content response
.post(Entity.text(ENTITY_STRING));
assertEquals("Expected 200", 200, response.getStatus()); //Expect header NOT sent - low request size
}

@Test
public void testExpect100ContinueCustomLengthProperty() {
final Response response = target(RESOURCE_PATH)
.property(ClientProperties.EXPECT_100_CONTINUE_THRESHOLD_SIZE, 555L)
.register(new Expect100ContinueFeature())
.register(Expect100ContinueFeature.basic())
.request().header(HttpHeaders.CONTENT_LENGTH, 666L)
.post(Entity.text("12345678901234567890123456789012345678901234567890123456789012345678901234567890"));
.post(Entity.text(ENTITY_STRING));
assertEquals("Expected 204", 204, response.getStatus()); //Expect header sent - No Content response
}

Expand All @@ -128,7 +129,7 @@ public void testExpect100ContinueRegisterViaCustomProperty() {
.property(ClientProperties.EXPECT_100_CONTINUE_THRESHOLD_SIZE, 43L)
.property(ClientProperties.EXPECT_100_CONTINUE, Boolean.TRUE)
.request().header(HttpHeaders.CONTENT_LENGTH, 44L)
.post(Entity.text("12345678901234567890123456789012345678901234567890123456789012345678901234567890"));
.post(Entity.text(ENTITY_STRING));
assertEquals("Expected 204", 204, response.getStatus()); //Expect header sent - No Content response
}
}

0 comments on commit 3b1d207

Please sign in to comment.