From 53eec48ffd4cb2a15f54617129272a00f93eb50f Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 10 Nov 2014 14:14:02 -0500 Subject: [PATCH] Fix HttpUrlConnection DELETE without body The following commit allowed HTTP DELETE with body: https://github.com/spring-projects/spring-framework/commit/584b831bb9390a49c791d180d023e3a585203215 However it broke buffered requests even without a body since JDK 1.6 and 1.7 do not support calls to getOutputStream with HTTP DELETE. This commit set the doOutput flag back to false if the actual buffered body is 0 length. Issue: SPR-12361 --- .../client/SimpleBufferingAsyncClientHttpRequest.java | 4 ++++ .../http/client/SimpleBufferingClientHttpRequest.java | 6 ++++++ .../client/BufferedSimpleHttpRequestFactoryTests.java | 11 +++++++++++ 3 files changed, 21 insertions(+) diff --git a/spring-web/src/main/java/org/springframework/http/client/SimpleBufferingAsyncClientHttpRequest.java b/spring-web/src/main/java/org/springframework/http/client/SimpleBufferingAsyncClientHttpRequest.java index e9594e2864..336cf4f239 100644 --- a/spring-web/src/main/java/org/springframework/http/client/SimpleBufferingAsyncClientHttpRequest.java +++ b/spring-web/src/main/java/org/springframework/http/client/SimpleBufferingAsyncClientHttpRequest.java @@ -78,6 +78,10 @@ final class SimpleBufferingAsyncClientHttpRequest extends AbstractBufferingAsync @Override public ClientHttpResponse call() throws Exception { SimpleBufferingClientHttpRequest.addHeaders(connection, headers); + // JDK < 1.8 doesn't support getOutputStream with HTTP DELETE + if (HttpMethod.DELETE.equals(getMethod()) && bufferedOutput.length == 0) { + connection.setDoOutput(false); + } if (connection.getDoOutput() && outputStreaming) { connection.setFixedLengthStreamingMode(bufferedOutput.length); } diff --git a/spring-web/src/main/java/org/springframework/http/client/SimpleBufferingClientHttpRequest.java b/spring-web/src/main/java/org/springframework/http/client/SimpleBufferingClientHttpRequest.java index 6f7531255d..0247ef6cf8 100644 --- a/spring-web/src/main/java/org/springframework/http/client/SimpleBufferingClientHttpRequest.java +++ b/spring-web/src/main/java/org/springframework/http/client/SimpleBufferingClientHttpRequest.java @@ -26,6 +26,7 @@ import java.util.Map; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.util.FileCopyUtils; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; /** @@ -69,6 +70,11 @@ final class SimpleBufferingClientHttpRequest extends AbstractBufferingClientHttp protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException { addHeaders(this.connection, headers); + // JDK < 1.8 doesn't support getOutputStream with HTTP DELETE + if (HttpMethod.DELETE.equals(getMethod()) && bufferedOutput.length == 0) { + this.connection.setDoOutput(false); + } + if (this.connection.getDoOutput() && this.outputStreaming) { this.connection.setFixedLengthStreamingMode(bufferedOutput.length); } diff --git a/spring-web/src/test/java/org/springframework/http/client/BufferedSimpleHttpRequestFactoryTests.java b/spring-web/src/test/java/org/springframework/http/client/BufferedSimpleHttpRequestFactoryTests.java index 0bb1c30b03..d240be912b 100644 --- a/spring-web/src/test/java/org/springframework/http/client/BufferedSimpleHttpRequestFactoryTests.java +++ b/spring-web/src/test/java/org/springframework/http/client/BufferedSimpleHttpRequestFactoryTests.java @@ -18,9 +18,12 @@ package org.springframework.http.client; import static org.junit.Assert.assertEquals; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.ProtocolException; +import java.net.URI; import java.net.URL; import org.junit.Test; @@ -56,6 +59,14 @@ public class BufferedSimpleHttpRequestFactoryTests extends AbstractHttpRequestFa testRequestBodyAllowed(uri, "DELETE", true); } + @Test + public void deleteWithoutBodyDoesNotRaiseException() throws Exception { + HttpURLConnection connection = new TestHttpURLConnection(new URL("http://example.com")); + ((SimpleClientHttpRequestFactory) this.factory).prepareConnection(connection, "DELETE"); + SimpleBufferingClientHttpRequest request = new SimpleBufferingClientHttpRequest(connection, false); + request.execute(); + } + private void testRequestBodyAllowed(URL uri, String httpMethod, boolean allowed) throws IOException { HttpURLConnection connection = new TestHttpURLConnection(uri); ((SimpleClientHttpRequestFactory) this.factory).prepareConnection(connection, httpMethod);