Skip to content

Commit 2d184d9

Browse files
authored
Merge pull request #38 from awslabs/servlet-improvements
Addressing issues #34, #35, and #37
2 parents 9d16cff + 54104b4 commit 2d184d9

File tree

35 files changed

+719
-101
lines changed

35 files changed

+719
-101
lines changed

aws-serverless-java-container-core/pom.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,15 @@
6565
<version>1.10.19</version>
6666
<scope>test</scope>
6767
</dependency>
68+
69+
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpmime -->
70+
<dependency>
71+
<groupId>org.apache.httpcomponents</groupId>
72+
<artifactId>httpmime</artifactId>
73+
<version>4.5.3</version>
74+
<scope>test</scope>
75+
</dependency>
76+
6877
</dependencies>
6978

7079
</project>

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

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
package com.amazonaws.serverless.proxy.internal;
1414

1515

16+
import com.amazonaws.serverless.proxy.internal.model.ContainerConfig;
1617
import com.amazonaws.services.lambda.runtime.Context;
1718

1819
import javax.ws.rs.core.SecurityContext;
@@ -36,6 +37,7 @@ public abstract class LambdaContainerHandler<RequestType, ResponseType, Containe
3637

3738
public static final String SERVER_INFO = "aws-serverless-java-container";
3839

40+
3941
//-------------------------------------------------------------
4042
// Variables - Private
4143
//-------------------------------------------------------------
@@ -45,6 +47,15 @@ public abstract class LambdaContainerHandler<RequestType, ResponseType, Containe
4547
private SecurityContextWriter<RequestType> securityContextWriter;
4648
private ExceptionHandler<ResponseType> exceptionHandler;
4749

50+
protected Context lambdaContext;
51+
52+
53+
//-------------------------------------------------------------
54+
// Variables - Private - Static
55+
//-------------------------------------------------------------
56+
57+
private static ContainerConfig config = ContainerConfig.defaultConfig();
58+
4859

4960
//-------------------------------------------------------------
5061
// Constructors
@@ -76,6 +87,19 @@ protected abstract void handleRequest(ContainerRequestType containerRequest, Con
7687
// Methods - Public
7788
//-------------------------------------------------------------
7889

90+
/**
91+
* Configures the library to strip a base path from incoming requests before passing them on to the wrapped
92+
* framework. This was added in response to issue #34 (https://github.com/awslabs/aws-serverless-java-container/issues/34).
93+
* When creating a base path mapping for custom domain names in API Gateway we want to be able to strip the base path
94+
* from the request - the underlying service may not recognize this path.
95+
* @param basePath The base path to be stripped from the request
96+
*/
97+
public void stripBasePath(String basePath) {
98+
config.setStripBasePath(true);
99+
config.setServiceBasePath(basePath);
100+
}
101+
102+
79103
/**
80104
* Proxies requests to the underlying container given the incoming Lambda request. This method returns a populated
81105
* return object for the Lambda function.
@@ -85,11 +109,12 @@ protected abstract void handleRequest(ContainerRequestType containerRequest, Con
85109
* @return A valid response type
86110
*/
87111
public ResponseType proxy(RequestType request, Context context) {
112+
lambdaContext = context;
88113
try {
89114
SecurityContext securityContext = securityContextWriter.writeSecurityContext(request, context);
90115
CountDownLatch latch = new CountDownLatch(1);
91116
ContainerResponseType containerResponse = getContainerResponse(latch);
92-
ContainerRequestType containerRequest = requestReader.readRequest(request, securityContext, context);
117+
ContainerRequestType containerRequest = requestReader.readRequest(request, securityContext, context, config);
93118

94119
handleRequest(containerRequest, containerResponse, context);
95120

@@ -98,13 +123,22 @@ public ResponseType proxy(RequestType request, Context context) {
98123
return responseWriter.writeResponse(containerResponse, context);
99124
} catch (Exception e) {
100125
context.getLogger().log("Error while handling request: " + e.getMessage());
101-
102-
/*for (StackTraceElement el : e.getStackTrace()) {
103-
context.getLogger().log(el.toString());
104-
}*/
105126
e.printStackTrace();
106127

107128
return exceptionHandler.handle(e);
108129
}
109130
}
131+
132+
133+
//-------------------------------------------------------------
134+
// Methods - Getter/Setter
135+
//-------------------------------------------------------------
136+
137+
/**
138+
* Returns the current container configuration object.
139+
* @return
140+
*/
141+
public static ContainerConfig getContainerConfig() {
142+
return config;
143+
}
110144
}

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515

1616
import com.amazonaws.serverless.exceptions.InvalidRequestEventException;
17+
import com.amazonaws.serverless.proxy.internal.model.ContainerConfig;
1718
import com.amazonaws.services.lambda.runtime.Context;
1819

1920
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -67,9 +68,36 @@ public abstract class RequestReader<RequestType, ContainerRequestType> {
6768
* @return A valid request object for the underlying container
6869
* @throws InvalidRequestEventException This exception is thrown if anything goes wrong during the creation of the request object
6970
*/
70-
protected abstract ContainerRequestType readRequest(RequestType request, SecurityContext securityContext, Context lambdaContext)
71+
protected abstract ContainerRequestType readRequest(RequestType request, SecurityContext securityContext, Context lambdaContext, ContainerConfig config)
7172
throws InvalidRequestEventException;
7273

7374

7475
protected abstract Class<? extends RequestType> getRequestClass();
76+
77+
78+
//-------------------------------------------------------------
79+
// Methods - Protected
80+
//-------------------------------------------------------------
81+
82+
/**
83+
* Strips the base path from the request path if the container configuration object requires it
84+
* @param requestPath The incoming request path
85+
* @param config The container configuration object
86+
* @return The final request path
87+
*/
88+
protected String stripBasePath(String requestPath, ContainerConfig config) {
89+
if (!config.isStripBasePath()) {
90+
return requestPath;
91+
}
92+
93+
if (requestPath.startsWith(config.getServiceBasePath())) {
94+
String newRequestPath = requestPath.replaceFirst(config.getServiceBasePath(), "");
95+
if (!newRequestPath.startsWith("/")) {
96+
newRequestPath = "/" + newRequestPath;
97+
}
98+
return newRequestPath;
99+
}
100+
101+
return requestPath;
102+
}
75103
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.amazonaws.serverless.proxy.internal.model;
2+
3+
4+
/**
5+
* Configuration paramters used by the <code>RequestReader</code> and <code>ResponseWriter</code> objects.
6+
*/
7+
public class ContainerConfig {
8+
9+
public static ContainerConfig defaultConfig() {
10+
ContainerConfig configuration = new ContainerConfig();
11+
configuration.setStripBasePath(false);
12+
13+
return configuration;
14+
}
15+
16+
//-------------------------------------------------------------
17+
// Variables - Private
18+
//-------------------------------------------------------------
19+
20+
private String serviceBasePath;
21+
private boolean stripBasePath;
22+
23+
24+
//-------------------------------------------------------------
25+
// Methods - Getter/Setter
26+
//-------------------------------------------------------------
27+
28+
public String getServiceBasePath() {
29+
return serviceBasePath;
30+
}
31+
32+
33+
public void setServiceBasePath(String serviceBasePath) {
34+
// clean up base path before setting it, we want a "/" at the beginning but not at the end.
35+
String finalBasePath = serviceBasePath;
36+
if (!finalBasePath.startsWith("/")) {
37+
finalBasePath = "/" + serviceBasePath;
38+
}
39+
if (finalBasePath.endsWith("/")) {
40+
finalBasePath = finalBasePath.substring(0, finalBasePath.length() - 1);
41+
}
42+
this.serviceBasePath = finalBasePath;
43+
}
44+
45+
46+
public boolean isStripBasePath() {
47+
return stripBasePath;
48+
}
49+
50+
51+
public void setStripBasePath(boolean stripBasePath) {
52+
this.stripBasePath = stripBasePath;
53+
}
54+
55+
56+
}

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

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,13 @@
2323
import java.io.UnsupportedEncodingException;
2424
import java.net.URLEncoder;
2525
import java.nio.charset.StandardCharsets;
26-
import java.util.*;
26+
import java.util.AbstractMap;
27+
import java.util.ArrayList;
28+
import java.util.Collections;
29+
import java.util.Enumeration;
30+
import java.util.HashMap;
31+
import java.util.List;
32+
import java.util.Map;
2733
import java.util.stream.Collectors;
2834

2935

@@ -56,6 +62,9 @@ public abstract class AwsHttpServletRequest implements HttpServletRequest {
5662

5763
private Context lambdaContext;
5864
private Map<String, Object> attributes;
65+
private ServletContext servletContext;
66+
67+
protected DispatcherType dispatcherType;
5968

6069

6170
//-------------------------------------------------------------
@@ -72,6 +81,7 @@ public abstract class AwsHttpServletRequest implements HttpServletRequest {
7281
attributes = new HashMap<>();
7382
}
7483

84+
7585
//-------------------------------------------------------------
7686
// Implementation - HttpServletRequest
7787
//-------------------------------------------------------------
@@ -119,6 +129,7 @@ public boolean isRequestedSessionIdFromURL() {
119129

120130

121131
@Override
132+
@Deprecated
122133
public boolean isRequestedSessionIdFromUrl() {
123134
return false;
124135
}
@@ -185,7 +196,7 @@ public int getLocalPort() {
185196

186197
@Override
187198
public ServletContext getServletContext() {
188-
return AwsServletContext.getInstance(lambdaContext);
199+
return servletContext;
189200
}
190201

191202

@@ -213,6 +224,19 @@ public DispatcherType getDispatcherType() {
213224
}
214225

215226

227+
//-------------------------------------------------------------
228+
// Methods - Getter/Setter
229+
//-------------------------------------------------------------
230+
231+
public void setDispatcherType(DispatcherType type) {
232+
dispatcherType = type;
233+
}
234+
235+
public void setServletContext(ServletContext context) {
236+
servletContext = context;
237+
}
238+
239+
216240
//-------------------------------------------------------------
217241
// Methods - Protected
218242
//-------------------------------------------------------------
@@ -223,7 +247,6 @@ public DispatcherType getDispatcherType() {
223247
* @return An array of Cookie objects from the header
224248
*/
225249
protected Cookie[] parseCookieHeaderValue(String headerValue) {
226-
227250
List<Map.Entry<String, String>> parsedHeaders = this.parseHeaderValue(headerValue);
228251

229252
return parsedHeaders.stream()
@@ -232,6 +255,7 @@ protected Cookie[] parseCookieHeaderValue(String headerValue) {
232255
.toArray(Cookie[]::new);
233256
}
234257

258+
235259
/**
236260
* Given a map of key/values query string parameters from API Gateway, creates a query string as it would have
237261
* been in the original url.

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ public void setStatus(int i) {
188188

189189

190190
@Override
191+
@Deprecated
191192
public void setStatus(int i, String s) {
192193
statusCode = i;
193194
statusMessage = s;

0 commit comments

Comments
 (0)