Skip to content

Commit 4f7bc3f

Browse files
committed
CharacterEncoding fix in AwsProxyHttpServletRequest
Fix to address issue #5. Also added a unit test for the fix in the spring support repo.
1 parent f0accf1 commit 4f7bc3f

File tree

2 files changed

+71
-3
lines changed

2 files changed

+71
-3
lines changed

aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/servlet/AwsProxyHttpServletRequest.java

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ public class AwsProxyHttpServletRequest
7979
private static final String FORM_DATA_SEPARATOR = "&";
8080
private static final String DEFAULT_CHARACTER_ENCODING = "UTF-8";
8181
private static final String HEADER_DATE_FORMAT = "EEE, d MMM yyyy HH:mm:ss z";
82+
private static final String ENCODING_VALUE_KEY = "charset";
8283

8384
// We need this to pickup the protocol from the CloudFront header since Lambda doesn't receive this
8485
// information from anywhere else
@@ -382,15 +383,60 @@ public Enumeration<String> getAttributeNames() {
382383

383384
@Override
384385
public String getCharacterEncoding() {
385-
return getHeaderCaseInsensitive(HttpHeaders.ACCEPT_ENCODING);
386+
// we only look at content-type because content-encoding should only be used for
387+
// "binary" requests such as gzip/deflate.
388+
String contentTypeHeader = getHeaderCaseInsensitive(HttpHeaders.CONTENT_TYPE);
389+
if (contentTypeHeader == null) {
390+
return null;
391+
}
392+
393+
String[] contentTypeValues = contentTypeHeader.split(HEADER_VALUE_SEPARATOR);
394+
if (contentTypeValues.length <= 1) {
395+
return null;
396+
}
397+
398+
for (String contentTypeValue : contentTypeValues) {
399+
if (contentTypeValue.trim().startsWith(ENCODING_VALUE_KEY)) {
400+
String[] encodingValues = contentTypeValue.split(HEADER_KEY_VALUE_SEPARATOR);
401+
if (encodingValues.length <= 1) {
402+
return null;
403+
}
404+
return encodingValues[1];
405+
}
406+
}
407+
return null;
386408
}
387409

388410

389411
@Override
390412
public void setCharacterEncoding(String s) throws UnsupportedEncodingException {
391-
request.getHeaders().put(HttpHeaders.ACCEPT_ENCODING, s);
392-
}
413+
String currentContentType = request.getHeaders().get(HttpHeaders.CONTENT_TYPE);
414+
if (currentContentType == null) {
415+
request.getHeaders().put(
416+
HttpHeaders.CONTENT_TYPE,
417+
HEADER_VALUE_SEPARATOR + " " + ENCODING_VALUE_KEY + HEADER_KEY_VALUE_SEPARATOR + s);
418+
return;
419+
}
420+
421+
if (currentContentType.contains(HEADER_VALUE_SEPARATOR)) {
422+
String[] contentTypeValues = currentContentType.split(HEADER_VALUE_SEPARATOR);
423+
String contentType = contentTypeValues[0];
424+
425+
for (String contentTypeValue : contentTypeValues) {
426+
if (contentTypeValue.trim().startsWith(ENCODING_VALUE_KEY)) {
427+
contentType += HEADER_VALUE_SEPARATOR + " " + ENCODING_VALUE_KEY + HEADER_KEY_VALUE_SEPARATOR + s;
428+
} else {
429+
contentType += HEADER_VALUE_SEPARATOR + " " + contentTypeValue;
430+
}
431+
}
393432

433+
request.getHeaders().put(HttpHeaders.CONTENT_TYPE, contentType);
434+
} else {
435+
request.getHeaders().put(
436+
HttpHeaders.CONTENT_TYPE,
437+
currentContentType + HEADER_VALUE_SEPARATOR + " " + ENCODING_VALUE_KEY + HEADER_KEY_VALUE_SEPARATOR + s);
438+
}
439+
}
394440

395441
@Override
396442
public int getContentLength() {

aws-serverless-java-container-spring/src/test/java/com/amazonaws/serverless/proxy/spring/SpringAwsProxyTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
2020
import org.springframework.test.context.web.WebAppConfiguration;
2121

22+
import javax.ws.rs.core.HttpHeaders;
23+
import javax.ws.rs.core.MediaType;
2224
import java.io.IOException;
2325
import java.util.UUID;
2426

@@ -165,6 +167,26 @@ public void base64_binaryResponse_base64Encoding() {
165167
assertTrue(Base64.isBase64(response.getBody()));
166168
}
167169

170+
@Test
171+
public void servletRequestEncoding_acceptEncoding_okStatusCode() {
172+
SingleValueModel singleValueModel = new SingleValueModel();
173+
singleValueModel.setValue(CUSTOM_HEADER_VALUE);
174+
AwsProxyRequest request = null;
175+
try {
176+
request = new AwsProxyRequestBuilder("/echo/json-body", "POST")
177+
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
178+
.header(HttpHeaders.ACCEPT_ENCODING, "gzip, deflate")
179+
.queryString("status", "200")
180+
.body(objectMapper.writeValueAsString(singleValueModel))
181+
.build();
182+
} catch (JsonProcessingException e) {
183+
fail("Could not serialize object to JSON");
184+
}
185+
186+
AwsProxyResponse output = handler.proxy(request, lambdaContext);
187+
assertEquals(200, output.getStatusCode());
188+
}
189+
168190
private void validateMapResponseModel(AwsProxyResponse output) {
169191
try {
170192
MapResponseModel response = objectMapper.readValue(output.getBody(), MapResponseModel.class);

0 commit comments

Comments
 (0)