Skip to content

Commit 31a53c3

Browse files
committed
Added ability to set a default charset for Content-Type header when a request doesn't explicitly specify one. This addresses issue #175
1 parent cf0577f commit 31a53c3

File tree

3 files changed

+105
-0
lines changed

3 files changed

+105
-0
lines changed

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414

1515
import com.amazonaws.serverless.exceptions.InvalidRequestEventException;
1616
import com.amazonaws.serverless.proxy.RequestReader;
17+
import com.amazonaws.serverless.proxy.internal.LambdaContainerHandler;
1718
import com.amazonaws.serverless.proxy.model.AwsProxyRequest;
1819
import com.amazonaws.serverless.proxy.model.ContainerConfig;
1920
import com.amazonaws.services.lambda.runtime.Context;
2021

22+
import javax.ws.rs.core.HttpHeaders;
2123
import javax.ws.rs.core.SecurityContext;
2224

2325
/**
@@ -34,6 +36,11 @@ public class AwsProxyHttpServletRequestReader extends RequestReader<AwsProxyRequ
3436
public AwsProxyHttpServletRequest readRequest(AwsProxyRequest request, SecurityContext securityContext, Context lambdaContext, ContainerConfig config)
3537
throws InvalidRequestEventException {
3638
request.setPath(stripBasePath(request.getPath(), config));
39+
if (request.getMultiValueHeaders().getFirst(HttpHeaders.CONTENT_TYPE) != null) {
40+
String contentType = request.getMultiValueHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
41+
// put single as we always expect to have one and only one content type in a request.
42+
request.getMultiValueHeaders().putSingle(HttpHeaders.CONTENT_TYPE, getContentTypeWithCharset(contentType, config));
43+
}
3744
AwsProxyHttpServletRequest servletRequest = new AwsProxyHttpServletRequest(request, lambdaContext, securityContext, config);
3845
servletRequest.setAttribute(API_GATEWAY_CONTEXT_PROPERTY, request.getRequestContext());
3946
servletRequest.setAttribute(API_GATEWAY_STAGE_VARS_PROPERTY, request.getStageVariables());
@@ -52,4 +59,26 @@ public AwsProxyHttpServletRequest readRequest(AwsProxyRequest request, SecurityC
5259
protected Class<? extends AwsProxyRequest> getRequestClass() {
5360
return AwsProxyRequest.class;
5461
}
62+
63+
//-------------------------------------------------------------
64+
// Methods - Private
65+
//-------------------------------------------------------------
66+
67+
private String getContentTypeWithCharset(String headerValue, ContainerConfig config) {
68+
if (headerValue == null || "".equals(headerValue.trim())) {
69+
return headerValue;
70+
}
71+
72+
if (headerValue.contains("charset=")) {
73+
return headerValue;
74+
}
75+
76+
String newValue = headerValue;
77+
if (!headerValue.trim().endsWith(";")) {
78+
newValue += "; ";
79+
}
80+
81+
newValue += "charset=" + config.getDefaultContentCharset();
82+
return newValue;
83+
}
5584
}

aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/model/ContainerConfig.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
*/
1414
public class ContainerConfig {
1515
public static final String DEFAULT_URI_ENCODING = "UTF-8";
16+
public static final String DEFAULT_CONTENT_CHARSET = "ISO-8859-1";
1617
private static final List<String> DEFAULT_FILE_PATHS = new ArrayList<String>() {{ add("/tmp"); add("/var/task"); }};
1718

1819
public static ContainerConfig defaultConfig() {
@@ -24,6 +25,7 @@ public static ContainerConfig defaultConfig() {
2425
configuration.setValidFilePaths(DEFAULT_FILE_PATHS);
2526
configuration.setQueryStringCaseSensitive(false);
2627
configuration.addBinaryContentTypes("application/octet-stream", "image/jpeg", "image/png", "image/gif");
28+
configuration.setDefaultContentCharset(DEFAULT_CONTENT_CHARSET);
2729

2830
return configuration;
2931
}
@@ -35,6 +37,7 @@ public static ContainerConfig defaultConfig() {
3537
private String serviceBasePath;
3638
private boolean stripBasePath;
3739
private String uriEncoding;
40+
private String defaultContentCharset;
3841
private boolean consolidateSetCookieHeaders;
3942
private boolean useStageAsServletContext;
4043
private List<String> validFilePaths;
@@ -248,4 +251,25 @@ public void addBinaryContentTypes(String... contentTypes) {
248251
public boolean isBinaryContentType(String contentType) {
249252
return contentType != null && binaryContentTypes.contains(contentType.trim());
250253
}
254+
255+
256+
/**
257+
* Returns the name of the default charset appended to the <code>Content-Type</code> header if no charset is specified by the request. The
258+
* default value of this is <code>ISO-8859-1</code>.
259+
* @return The name of the default charset for the Content-Type header
260+
*/
261+
public String getDefaultContentCharset() {
262+
return defaultContentCharset;
263+
}
264+
265+
266+
/**
267+
* Sets the default charset value for the <code>Content-Type</code> header if no charset is specified with a request. The default value of this
268+
* is <code>ISO-8859-1</code>. If a request specifies a <code>Content-Type</code> header without a <code>charset</code> property, the value of
269+
* this field is automatically appended to the header.
270+
* @param defaultContentCharset The name of the charset for the content type header.
271+
*/
272+
public void setDefaultContentCharset(String defaultContentCharset) {
273+
this.defaultContentCharset = defaultContentCharset;
274+
}
251275
}

aws-serverless-java-container-core/src/test/java/com/amazonaws/serverless/proxy/internal/servlet/AwsProxyHttpServletRequestReaderTest.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33

44
import com.amazonaws.serverless.exceptions.InvalidRequestEventException;
5+
import com.amazonaws.serverless.proxy.internal.LambdaContainerHandler;
56
import com.amazonaws.serverless.proxy.model.AwsProxyRequest;
67
import com.amazonaws.serverless.proxy.model.ContainerConfig;
78
import com.amazonaws.serverless.proxy.internal.testutils.AwsProxyRequestBuilder;
89
import com.amazonaws.services.lambda.runtime.Context;
910
import org.junit.Test;
1011

1112
import javax.servlet.http.HttpServletRequest;
13+
import javax.ws.rs.core.HttpHeaders;
1214
import javax.ws.rs.core.SecurityContext;
1315
import java.lang.reflect.Method;
1416

@@ -57,4 +59,54 @@ public void readRequest_urlDecode_expectDecodedPath() {
5759
}
5860

5961
}
62+
63+
@Test
64+
public void readRequest_contentCharset_doesNotOverrideRequestCharset() {
65+
String requestCharset = "application/json; charset=UTF-8";
66+
AwsProxyRequest request = new AwsProxyRequestBuilder(ENCODED_REQUEST_PATH, "GET").header(HttpHeaders.CONTENT_TYPE, requestCharset).build();
67+
try {
68+
HttpServletRequest servletRequest = reader.readRequest(request, null, null, ContainerConfig.defaultConfig());
69+
assertNotNull(servletRequest);
70+
assertNotNull(servletRequest.getHeader(HttpHeaders.CONTENT_TYPE));
71+
assertEquals(requestCharset, servletRequest.getHeader(HttpHeaders.CONTENT_TYPE));
72+
assertEquals("UTF-8", servletRequest.getCharacterEncoding());
73+
} catch (InvalidRequestEventException e) {
74+
e.printStackTrace();
75+
fail("Could not read request");
76+
}
77+
}
78+
79+
@Test
80+
public void readRequest_contentCharset_setsDefaultCharsetWhenNotSpecified() {
81+
String requestCharset = "application/json";
82+
AwsProxyRequest request = new AwsProxyRequestBuilder(ENCODED_REQUEST_PATH, "GET").header(HttpHeaders.CONTENT_TYPE, requestCharset).build();
83+
try {
84+
HttpServletRequest servletRequest = reader.readRequest(request, null, null, ContainerConfig.defaultConfig());
85+
assertNotNull(servletRequest);
86+
assertNotNull(servletRequest.getHeader(HttpHeaders.CONTENT_TYPE));
87+
String contentAndCharset = requestCharset + "; charset=" + LambdaContainerHandler.getContainerConfig().getDefaultContentCharset();
88+
assertEquals(contentAndCharset, servletRequest.getHeader(HttpHeaders.CONTENT_TYPE));
89+
assertEquals(LambdaContainerHandler.getContainerConfig().getDefaultContentCharset(), servletRequest.getCharacterEncoding());
90+
} catch (InvalidRequestEventException e) {
91+
e.printStackTrace();
92+
fail("Could not read request");
93+
}
94+
}
95+
96+
@Test
97+
public void readRequest_contentCharset_appendsCharsetToComplextContentType() {
98+
String contentType = "multipart/form-data; boundary=something";
99+
AwsProxyRequest request = new AwsProxyRequestBuilder(ENCODED_REQUEST_PATH, "GET").header(HttpHeaders.CONTENT_TYPE, contentType).build();
100+
try {
101+
HttpServletRequest servletRequest = reader.readRequest(request, null, null, ContainerConfig.defaultConfig());
102+
assertNotNull(servletRequest);
103+
assertNotNull(servletRequest.getHeader(HttpHeaders.CONTENT_TYPE));
104+
String contentAndCharset = contentType + "; charset=" + LambdaContainerHandler.getContainerConfig().getDefaultContentCharset();
105+
assertEquals(contentAndCharset, servletRequest.getHeader(HttpHeaders.CONTENT_TYPE));
106+
assertEquals(LambdaContainerHandler.getContainerConfig().getDefaultContentCharset(), servletRequest.getCharacterEncoding());
107+
} catch (InvalidRequestEventException e) {
108+
e.printStackTrace();
109+
fail("Could not read request");
110+
}
111+
}
60112
}

0 commit comments

Comments
 (0)