Skip to content

Commit cb20e88

Browse files
committed
Revert "Fix ApacheHttpClient's handling of request bodies on DELETE, GET, HEAD & OPTIONS requests (#5704)"
This reverts commit b2fcb7e.
1 parent b19b9d3 commit cb20e88

File tree

6 files changed

+45
-105
lines changed

6 files changed

+45
-105
lines changed

Diff for: .changes/2.29.26.json

+6
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@
109109
"category": "Redshift Serverless",
110110
"contributor": "",
111111
"description": "Adds support for the ListManagedWorkgroups API to get an overview of existing managed workgroups."
112+
},
113+
{
114+
"type": "bugfix",
115+
"category": "AWS SDK for Java v2",
116+
"contributor": "",
117+
"description": "Reverted PR https://github.com/aws/aws-sdk-java-v2/pull/5704 that attached the request body entity to all HTTP methods because it caused regression issues for some services."
112118
}
113119
]
114120
}

Diff for: CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@
7272
- ### Features
7373
- Adds support for the ListManagedWorkgroups API to get an overview of existing managed workgroups.
7474

75+
## __AWS SDK for Java v2__
76+
- ### Bugfixes
77+
- Reverted PR https://github.com/aws/aws-sdk-java-v2/pull/5704 that attached the request body entity to all HTTP methods because it caused regression issues for some services.
78+
7579
# __2.29.25__ __2024-12-02__
7680
## __AWS End User Messaging Social__
7781
- ### Features

Diff for: http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/internal/impl/ApacheHttpRequestFactory.java

+16-18
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,14 @@
2424
import org.apache.http.HttpEntity;
2525
import org.apache.http.HttpHeaders;
2626
import org.apache.http.client.config.RequestConfig;
27+
import org.apache.http.client.methods.HttpDelete;
2728
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
29+
import org.apache.http.client.methods.HttpGet;
30+
import org.apache.http.client.methods.HttpHead;
31+
import org.apache.http.client.methods.HttpOptions;
32+
import org.apache.http.client.methods.HttpPatch;
33+
import org.apache.http.client.methods.HttpPost;
34+
import org.apache.http.client.methods.HttpPut;
2835
import org.apache.http.client.methods.HttpRequestBase;
2936
import software.amazon.awssdk.annotations.SdkInternalApi;
3037
import software.amazon.awssdk.http.HttpExecuteRequest;
@@ -109,18 +116,23 @@ private void addRequestConfig(final HttpRequestBase base,
109116

110117

111118
private HttpRequestBase createApacheRequest(HttpExecuteRequest request, URI uri) {
112-
SdkHttpMethod method = request.httpRequest().method();
113-
switch (method) {
119+
switch (request.httpRequest().method()) {
114120
case HEAD:
121+
return new HttpHead(uri);
115122
case GET:
123+
return new HttpGet(uri);
116124
case DELETE:
125+
return new HttpDelete(uri);
117126
case OPTIONS:
127+
return new HttpOptions(uri);
118128
case PATCH:
129+
return wrapEntity(request, new HttpPatch(uri));
119130
case POST:
131+
return wrapEntity(request, new HttpPost(uri));
120132
case PUT:
121-
return wrapEntity(request, new HttpRequestImpl(method, uri));
133+
return wrapEntity(request, new HttpPut(uri));
122134
default:
123-
throw new RuntimeException("Unknown HTTP method name: " + method);
135+
throw new RuntimeException("Unknown HTTP method name: " + request.httpRequest().method());
124136
}
125137
}
126138

@@ -180,18 +192,4 @@ private String getHostHeaderValue(SdkHttpRequest request) {
180192
? request.host() + ":" + request.port()
181193
: request.host();
182194
}
183-
184-
private static final class HttpRequestImpl extends HttpEntityEnclosingRequestBase {
185-
private final SdkHttpMethod method;
186-
187-
private HttpRequestImpl(SdkHttpMethod method, URI uri) {
188-
this.method = method;
189-
setURI(uri);
190-
}
191-
192-
@Override
193-
public String getMethod() {
194-
return this.method.toString();
195-
}
196-
}
197195
}

Diff for: http-clients/url-connection-client/src/test/java/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClientDefaultWireMockTest.java

-21
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,11 @@
1515

1616
package software.amazon.awssdk.http.urlconnection;
1717

18-
import static org.assertj.core.api.Assertions.assertThatThrownBy;
19-
20-
import java.net.ProtocolException;
2118
import javax.net.ssl.HttpsURLConnection;
2219
import javax.net.ssl.SSLSocketFactory;
23-
import org.junit.Test;
2420
import org.junit.jupiter.api.AfterEach;
2521
import software.amazon.awssdk.http.SdkHttpClient;
2622
import software.amazon.awssdk.http.SdkHttpClientDefaultTestSuite;
27-
import software.amazon.awssdk.http.SdkHttpMethod;
2823

2924
public class UrlConnectionHttpClientDefaultWireMockTest extends SdkHttpClientDefaultTestSuite {
3025

@@ -37,20 +32,4 @@ protected SdkHttpClient createSdkHttpClient() {
3732
public void reset() {
3833
HttpsURLConnection.setDefaultSSLSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault());
3934
}
40-
41-
@Test
42-
@Override
43-
public void supportsRequestBodyOnGetRequest() throws Exception {
44-
// HttpURLConnection is hard-coded to switch GET requests with a body to POST requests, in #getOutputStream0.
45-
testForResponseCode(200, SdkHttpMethod.GET, SdkHttpMethod.POST, true);
46-
}
47-
48-
@Test
49-
@Override
50-
public void supportsRequestBodyOnPatchRequest() {
51-
// HttpURLConnection does not support PATCH requests.
52-
assertThatThrownBy(super::supportsRequestBodyOnPatchRequest)
53-
.hasRootCauseInstanceOf(ProtocolException.class)
54-
.hasRootCauseMessage("Invalid HTTP method: PATCH");
55-
}
5635
}

Diff for: test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkHttpClientDefaultTestSuite.java

+15-60
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public void supportsResponseCode200() throws Exception {
6161
@Test
6262
public void supportsResponseCode200Head() throws Exception {
6363
// HEAD is special due to closing of the connection immediately and streams are null
64-
testForResponseCode(HttpURLConnection.HTTP_FORBIDDEN, SdkHttpMethod.HEAD, false);
64+
testForResponseCode(HttpURLConnection.HTTP_FORBIDDEN, SdkHttpMethod.HEAD);
6565
}
6666

6767
@Test
@@ -76,7 +76,7 @@ public void supportsResponseCode403() throws Exception {
7676

7777
@Test
7878
public void supportsResponseCode403Head() throws Exception {
79-
testForResponseCode(HttpURLConnection.HTTP_FORBIDDEN, SdkHttpMethod.HEAD, false);
79+
testForResponseCode(HttpURLConnection.HTTP_FORBIDDEN, SdkHttpMethod.HEAD);
8080
}
8181

8282
@Test
@@ -98,87 +98,45 @@ public void supportsResponseCode500() throws Exception {
9898
public void validatesHttpsCertificateIssuer() {
9999
SdkHttpClient client = createSdkHttpClient();
100100

101-
SdkHttpFullRequest request = mockSdkRequest("https://localhost:" + mockServer.httpsPort(), SdkHttpMethod.POST, true);
101+
SdkHttpFullRequest request = mockSdkRequest("https://localhost:" + mockServer.httpsPort(), SdkHttpMethod.POST);
102102

103103
assertThatThrownBy(client.prepareRequest(HttpExecuteRequest.builder().request(request).build())::call)
104104
.isInstanceOf(SSLHandshakeException.class);
105105
}
106106

107-
@Test
108-
public void supportsRequestBodyOnGetRequest() throws Exception {
109-
testForResponseCode(200, SdkHttpMethod.GET, true);
110-
}
111-
112-
@Test
113-
public void supportsRequestBodyOnPostRequest() throws Exception {
114-
testForResponseCode(200, SdkHttpMethod.POST, true);
115-
}
116-
117-
@Test
118-
public void supportsRequestBodyOnPutRequest() throws Exception {
119-
testForResponseCode(200, SdkHttpMethod.PUT, true);
120-
}
121-
122-
@Test
123-
public void supportsRequestBodyOnDeleteRequest() throws Exception {
124-
testForResponseCode(200, SdkHttpMethod.DELETE, true);
125-
}
126-
127-
@Test
128-
public void supportsRequestBodyOnHeadRequest() throws Exception {
129-
testForResponseCode(200, SdkHttpMethod.HEAD, true);
130-
}
131-
132-
@Test
133-
public void supportsRequestBodyOnPatchRequest() throws Exception {
134-
testForResponseCode(200, SdkHttpMethod.PATCH, true);
135-
}
136-
137-
@Test
138-
public void supportsRequestBodyOnOptionsRequest() throws Exception {
139-
testForResponseCode(200, SdkHttpMethod.OPTIONS, true);
140-
}
141-
142107
private void testForResponseCode(int returnCode) throws Exception {
143-
testForResponseCode(returnCode, SdkHttpMethod.POST, true);
108+
testForResponseCode(returnCode, SdkHttpMethod.POST);
144109
}
145110

146-
protected void testForResponseCode(int returnCode, SdkHttpMethod method, boolean includeBody) throws Exception {
147-
testForResponseCode(returnCode, method, method, includeBody);
148-
}
149-
150-
protected void testForResponseCode(int returnCode,
151-
SdkHttpMethod method,
152-
SdkHttpMethod expectedMethod,
153-
boolean includeBody) throws Exception {
111+
private void testForResponseCode(int returnCode, SdkHttpMethod method) throws Exception {
154112
SdkHttpClient client = createSdkHttpClient();
155113

156114
stubForMockRequest(returnCode);
157115

158-
SdkHttpFullRequest req = mockSdkRequest("http://localhost:" + mockServer.port(), method, includeBody);
116+
SdkHttpFullRequest req = mockSdkRequest("http://localhost:" + mockServer.port(), method);
159117
HttpExecuteResponse rsp = client.prepareRequest(HttpExecuteRequest.builder()
160118
.request(req)
161119
.contentStreamProvider(req.contentStreamProvider()
162120
.orElse(null))
163121
.build())
164122
.call();
165123

166-
validateResponse(rsp, returnCode, expectedMethod, includeBody);
124+
validateResponse(rsp, returnCode, method);
167125
}
168126

169127
protected void testForResponseCodeUsingHttps(SdkHttpClient client, int returnCode) throws Exception {
170128
SdkHttpMethod sdkHttpMethod = SdkHttpMethod.POST;
171129
stubForMockRequest(returnCode);
172130

173-
SdkHttpFullRequest req = mockSdkRequest("https://localhost:" + mockServer.httpsPort(), sdkHttpMethod, true);
131+
SdkHttpFullRequest req = mockSdkRequest("https://localhost:" + mockServer.httpsPort(), sdkHttpMethod);
174132
HttpExecuteResponse rsp = client.prepareRequest(HttpExecuteRequest.builder()
175133
.request(req)
176134
.contentStreamProvider(req.contentStreamProvider()
177135
.orElse(null))
178136
.build())
179137
.call();
180138

181-
validateResponse(rsp, returnCode, sdkHttpMethod, true);
139+
validateResponse(rsp, returnCode, sdkHttpMethod);
182140
}
183141

184142
private void stubForMockRequest(int returnCode) {
@@ -193,20 +151,17 @@ private void stubForMockRequest(int returnCode) {
193151
mockServer.stubFor(any(urlPathEqualTo("/")).willReturn(responseBuilder));
194152
}
195153

196-
private void validateResponse(HttpExecuteResponse response,
197-
int returnCode,
198-
SdkHttpMethod method,
199-
boolean expectBody) throws IOException {
154+
private void validateResponse(HttpExecuteResponse response, int returnCode, SdkHttpMethod method) throws IOException {
200155
RequestMethod requestMethod = RequestMethod.fromString(method.name());
201156

202157
RequestPatternBuilder patternBuilder = RequestPatternBuilder.newRequestPattern(requestMethod, urlMatching("/"))
203158
.withHeader("Host", containing("localhost"))
204159
.withHeader("User-Agent", equalTo("hello-world!"));
205160

206-
if (expectBody) {
207-
patternBuilder.withRequestBody(equalTo("Body"));
208-
} else {
161+
if (method == SdkHttpMethod.HEAD) {
209162
patternBuilder.withRequestBody(absent());
163+
} else {
164+
patternBuilder.withRequestBody(equalTo("Body"));
210165
}
211166

212167
mockServer.verify(1, patternBuilder);
@@ -222,14 +177,14 @@ private void validateResponse(HttpExecuteResponse response,
222177
mockServer.resetMappings();
223178
}
224179

225-
private SdkHttpFullRequest mockSdkRequest(String uriString, SdkHttpMethod method, boolean includeBody) {
180+
private SdkHttpFullRequest mockSdkRequest(String uriString, SdkHttpMethod method) {
226181
URI uri = URI.create(uriString);
227182
SdkHttpFullRequest.Builder requestBuilder = SdkHttpFullRequest.builder()
228183
.uri(uri)
229184
.method(method)
230185
.putHeader("Host", uri.getHost())
231186
.putHeader("User-Agent", "hello-world!");
232-
if (includeBody) {
187+
if (method != SdkHttpMethod.HEAD) {
233188
byte[] content = "Body".getBytes(StandardCharsets.UTF_8);
234189
requestBuilder.putHeader("Content-Length", Integer.toString(content.length));
235190
requestBuilder.contentStreamProvider(() -> new ByteArrayInputStream(content));

Diff for: test/protocol-tests-core/src/main/resources/software/amazon/awssdk/protocol/suites/cases/rest-json-contenttype.json

+4-6
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,9 @@
230230
"uri": "/no-payload",
231231
"method": "GET",
232232
"headers": {
233-
"contains": {
234-
"Content-Length": "0"
235-
},
236233
"doesNotContain": [
237-
"Content-Type"
234+
"Content-Type",
235+
"Content-Length"
238236
]
239237
},
240238
"body": {
@@ -260,11 +258,11 @@
260258
"method": "GET",
261259
"headers": {
262260
"contains": {
263-
"Content-Length": "0",
264261
"x-amz-test-id": "t-12345"
265262
},
266263
"doesNotContain": [
267-
"Content-Type"
264+
"Content-Type",
265+
"Content-Length"
268266
]
269267
},
270268
"body": {

0 commit comments

Comments
 (0)