diff --git a/README.md b/README.md
index 04cecb27..d4ae39eb 100644
--- a/README.md
+++ b/README.md
@@ -1,130 +1,165 @@
# AWS Lambda Java Support Libraries
-Interface definitions for Java code running on the AWS Lambda platform.
+Key libraries for running Java on the AWS Lambda platform.
For issues and questions, you can start with our [FAQ](https://aws.amazon.com/lambda/faqs/)
- and the [AWS forums](https://forums.aws.amazon.com/forum.jspa?forumID=186)
+and the AWS questions and answer site [re:Post](https://repost.aws/tags/TA5uNafDy2TpGNjidWLMSxDw/aws-lambda)
-To get started writing AWS Lambda functions in Java, check out the [official documentation](http://docs.aws.amazon.com/lambda/latest/dg/java-gs.html).
+To get started writing Lambda functions in Java, check out the official [developer guide](https://docs.aws.amazon.com/lambda/latest/dg/lambda-java.html).
-# Disclaimer of use
+For information on how to optimize your functions watch the re:Invent talk [Optimize your Java application on AWS Lambda](https://www.youtube.com/watch?v=sVJOJUD0fhQ).
-Each of the supplied packages should be used without modification. Removing
-dependencies, adding conflicting dependencies, or selectively including classes
-from the packages can result in unexpected behavior.
+## Core Java Lambda interfaces - aws-lambda-java-core
-# Release Notes
+This package defines the Lambda [Context](http://docs.aws.amazon.com/lambda/latest/dg/java-context-object.html) object
+as well as [interfaces](http://docs.aws.amazon.com/lambda/latest/dg/java-handler-using-predefined-interfaces.html) that Lambda accepts.
-Check out the per-module release notes:
-- [aws-lambda-java-core](aws-lambda-java-core/RELEASE.CHANGELOG.md)
-- [aws-lambda-java-events](aws-lambda-java-events/RELEASE.CHANGELOG.md)
-- [aws-lambda-java-events-sdk-transformer](aws-lambda-java-events-sdk-transformer/RELEASE.CHANGELOG.md)
-- [aws-lambda-java-log4j2](aws-lambda-java-log4j2/RELEASE.CHANGELOG.md)
-- [aws-lambda-java-runtime-interface-client](aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md)
-- [aws-lambda-java-serialization](aws-lambda-java-serialization/RELEASE.CHANGELOG.md)
-- [aws-lambda-java-test](aws-lambda-java-tests/RELEASE.CHANGELOG.md)
+- [Release Notes](aws-lambda-java-core/RELEASE.CHANGELOG.md)
-# Where to get packages
-___
+Example request handler
+
+```java
+public class Handler implements RequestHandler
*/
- public Map getCustom();
+ Map getCustom();
/**
* Gets environment information provided by mobile SDK, immutable.
*
*/
- public Map getEnvironment();
+ Map getEnvironment();
}
diff --git a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/CognitoIdentity.java b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/CognitoIdentity.java
index 25f3b3dd..a6588763 100644
--- a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/CognitoIdentity.java
+++ b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/CognitoIdentity.java
@@ -11,11 +11,11 @@ public interface CognitoIdentity {
* Gets the Amazon Cognito identity ID
*
*/
- public String getIdentityId();
+ String getIdentityId();
/**
* Gets the Amazon Cognito identity pool ID
*
*/
- public String getIdentityPoolId();
+ String getIdentityPoolId();
}
diff --git a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/LambdaLogger.java b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/LambdaLogger.java
index 8ff06458..ec51c4ab 100644
--- a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/LambdaLogger.java
+++ b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/LambdaLogger.java
@@ -25,12 +25,12 @@ public interface LambdaLogger {
*
* @param message A string containing the event to log.
*/
- public void log(String message);
+ void log(String message);
/**
* Logs a byte array to AWS CloudWatch Logs
* @param message byte array containing logs
*/
- public void log(byte[] message);
+ void log(byte[] message);
}
diff --git a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestHandler.java b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestHandler.java
index 406f2be3..834683f2 100644
--- a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestHandler.java
+++ b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestHandler.java
@@ -17,5 +17,5 @@ public interface RequestHandler {
* @param context The Lambda execution environment context object.
* @return The Lambda Function output
*/
- public O handleRequest(I input, Context context);
+ O handleRequest(I input, Context context);
}
diff --git a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestStreamHandler.java b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestStreamHandler.java
index d8ccf5a6..3a34adc9 100644
--- a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestStreamHandler.java
+++ b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestStreamHandler.java
@@ -18,5 +18,5 @@ public interface RequestStreamHandler {
* @param context The Lambda execution environment context object.
* @throws IOException
*/
- public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException;
+ void handleRequest(InputStream input, OutputStream output, Context context) throws IOException;
}
diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerRequestEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerRequestEvent.java
index 30a9c933..83c4979f 100644
--- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerRequestEvent.java
+++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerRequestEvent.java
@@ -63,8 +63,8 @@ public static class RequestContext implements Serializable {
private String path;
private Map queryStringParameters;
private Map> multiValueQueryStringParameters;
- private Map headers;
- private Map> multiValueHeaders;
+ private HttpHeaders headers;
+ private HttpHeaders> multiValueHeaders;
private String body;
@JsonProperty("isBase64Encoded")
private boolean isBase64Encoded;
diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerResponseEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerResponseEvent.java
index 5033fc75..8b77535d 100644
--- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerResponseEvent.java
+++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerResponseEvent.java
@@ -22,7 +22,6 @@
import java.io.Serializable;
import java.util.List;
-import java.util.Map;
/**
* Class to represent the response event to Application Load Balancer.
@@ -42,8 +41,8 @@ public class ApplicationLoadBalancerResponseEvent implements Serializable {
private String statusDescription;
@JsonProperty("isBase64Encoded")
private boolean isBase64Encoded;
- private Map headers;
- private Map> multiValueHeaders;
+ private HttpHeaders headers;
+ private HttpHeaders> multiValueHeaders;
private String body;
}
\ No newline at end of file
diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/HttpHeaders.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/HttpHeaders.java
new file mode 100644
index 00000000..6ccd89b5
--- /dev/null
+++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/HttpHeaders.java
@@ -0,0 +1,89 @@
+package com.amazonaws.services.lambda.runtime.events;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+/**
+ * Class that represents Http Headers.
+ *
+ * Http Headers are case-insensitive.
+ * Thus, requesting a header "host" will yield the same result as "Host" or "HOST"
+ */
+public class HttpHeaders implements Map {
+
+ // Headers are case insensitive (https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2)
+ private final Map map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+
+ @Override
+ public int size() {
+ return map.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return map.isEmpty();
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ return map.containsKey(key);
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ return map.containsValue(value);
+ }
+
+ @Override
+ public T get(Object key) {
+ return map.get(key);
+ }
+
+ @Override
+ public T put(String key, T value) {
+ return map.put(key, value);
+ }
+
+ @Override
+ public T remove(Object key) {
+ return map.remove(key);
+ }
+
+ @Override
+ public void putAll(Map extends String, ? extends T> m) {
+ map.putAll(m);
+ }
+
+ @Override
+ public void clear() {
+ map.clear();
+ }
+
+ @Override
+ public Set keySet() {
+ return map.keySet();
+ }
+
+ @Override
+ public Collection values() {
+ return map.values();
+ }
+
+ @Override
+ public Set> entrySet() {
+ return map.entrySet();
+ }
+
+ public static HttpHeaders mergeOrReplace(Map from) {
+ if (from == null) return null;
+ if (from instanceof HttpHeaders) return (HttpHeaders) from;
+
+ HttpHeaders out = new HttpHeaders<>();
+ if (from.isEmpty()) return out;
+
+ out.putAll(from);
+ return out;
+ }
+}
diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayCustomAuthorizerEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayCustomAuthorizerEvent.java
index a8a5eb26..26b534f6 100644
--- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayCustomAuthorizerEvent.java
+++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayCustomAuthorizerEvent.java
@@ -13,6 +13,7 @@
package com.amazonaws.services.lambda.runtime.events.apigateway;
+import com.amazonaws.services.lambda.runtime.events.HttpHeaders;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -39,7 +40,7 @@ public class APIGatewayCustomAuthorizerEvent {
private String resource;
private String path;
private String httpMethod;
- private Map headers;
+ private HttpHeaders headers;
private Map queryStringParameters;
private Map pathParameters;
private Map stageVariables;
diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayProxyRequestEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayProxyRequestEvent.java
index 92ad919c..27649afe 100644
--- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayProxyRequestEvent.java
+++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayProxyRequestEvent.java
@@ -13,6 +13,7 @@
package com.amazonaws.services.lambda.runtime.events.apigateway;
+import com.amazonaws.services.lambda.runtime.events.HttpHeaders;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -40,9 +41,9 @@ public class APIGatewayProxyRequestEvent implements Serializable {
private String httpMethod;
- private Map headers;
+ private HttpHeaders headers;
- private Map> multiValueHeaders;
+ private HttpHeaders> multiValueHeaders;
private Map queryStringParameters;
diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayProxyResponseEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayProxyResponseEvent.java
index deeae324..9fbe681b 100644
--- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayProxyResponseEvent.java
+++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayProxyResponseEvent.java
@@ -13,6 +13,7 @@
package com.amazonaws.services.lambda.runtime.events.apigateway;
+import com.amazonaws.services.lambda.runtime.events.HttpHeaders;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -35,7 +36,7 @@ public class APIGatewayProxyResponseEvent implements Serializable {
private Integer statusCode;
- private Map headers;
+ private HttpHeaders headers;
private String body;
diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayV2CustomAuthorizerEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayV2CustomAuthorizerEvent.java
index 90c24175..20201521 100644
--- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayV2CustomAuthorizerEvent.java
+++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayV2CustomAuthorizerEvent.java
@@ -13,6 +13,7 @@
package com.amazonaws.services.lambda.runtime.events.apigateway;
+import com.amazonaws.services.lambda.runtime.events.HttpHeaders;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -43,7 +44,7 @@ public class APIGatewayV2CustomAuthorizerEvent {
private String rawPath;
private String rawQueryString;
private List cookies;
- private Map headers;
+ private HttpHeaders headers;
private Map queryStringParameters;
private RequestContext requestContext;
private Map pathParameters;
diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayV2HTTPEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayV2HTTPEvent.java
index 49bee30e..33e47ce8 100644
--- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayV2HTTPEvent.java
+++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayV2HTTPEvent.java
@@ -13,6 +13,7 @@
package com.amazonaws.services.lambda.runtime.events.apigateway;
+import com.amazonaws.services.lambda.runtime.events.HttpHeaders;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -38,7 +39,7 @@ public class APIGatewayV2HTTPEvent {
private String rawPath;
private String rawQueryString;
private List cookies;
- private Map headers;
+ private HttpHeaders headers;
private Map queryStringParameters;
private Map pathParameters;
private Map stageVariables;
@@ -47,6 +48,10 @@ public class APIGatewayV2HTTPEvent {
private boolean isBase64Encoded;
private RequestContext requestContext;
+ public void setHeaders(Map headers) {
+ this.headers = HttpHeaders.mergeOrReplace(headers);
+ }
+
@AllArgsConstructor
@Builder(setterPrefix = "with")
@Data
diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayV2HTTPResponse.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayV2HTTPResponse.java
index 0ea4cac6..e4b99018 100644
--- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayV2HTTPResponse.java
+++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/apigateway/APIGatewayV2HTTPResponse.java
@@ -13,6 +13,7 @@
package com.amazonaws.services.lambda.runtime.events.apigateway;
+import com.amazonaws.services.lambda.runtime.events.HttpHeaders;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -29,10 +30,29 @@
@NoArgsConstructor
public class APIGatewayV2HTTPResponse {
private int statusCode;
- private Map headers;
- private Map> multiValueHeaders;
+ private HttpHeaders headers;
+ private HttpHeaders> multiValueHeaders;
private List cookies;
private String body;
@JsonProperty("isBase64Encoded")
private boolean isBase64Encoded;
+
+ public static APIGatewayV2HTTPResponseBuilder builder() {
+ return new APIGatewayV2HTTPResponseBuilder();
+ }
+
+ public static class APIGatewayV2HTTPResponseBuilder {
+ private HttpHeaders headers;
+ private HttpHeaders> multiValueHeaders;
+
+ public APIGatewayV2HTTPResponseBuilder withHeaders(Map headers) {
+ this.headers = HttpHeaders.mergeOrReplace(headers);
+ return this;
+ }
+
+ public APIGatewayV2HTTPResponseBuilder withMultiValueHeaders(Map> multiValueHeaders) {
+ this.multiValueHeaders = HttpHeaders.mergeOrReplace(multiValueHeaders);
+ return this;
+ }
+ }
}
diff --git a/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/HttpHeadersTest.java b/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/HttpHeadersTest.java
new file mode 100644
index 00000000..1c220159
--- /dev/null
+++ b/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/HttpHeadersTest.java
@@ -0,0 +1,151 @@
+package com.amazonaws.services.lambda.runtime.events;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.*;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class HttpHeadersTest {
+
+ @Test
+ public void testHttpHeadersCanBeInit() {
+ HttpHeaders obj = new HttpHeaders<>();
+ }
+
+ @Test
+ public void testValueCanBeAddedToHttpHeaders() {
+ HttpHeaders obj = new HttpHeaders<>();
+ obj.put("key", "value");
+ assertEquals(1, obj.size());
+ assertEquals(obj.getOrDefault("key", null), "value");
+ }
+
+ @Test
+ public void testValuesCanBeAddedToHttpHeaders() {
+ HttpHeaders obj = new HttpHeaders<>();
+ obj.put("key", "value");
+ obj.put("key2", "value2");
+ obj.put("key3", "value3");
+
+ assertEquals(3, obj.size());
+ assertEquals(obj.getOrDefault("key", null), "value");
+ assertEquals(obj.getOrDefault("key2", null), "value2");
+ assertEquals(obj.getOrDefault("key3", null), "value3");
+ }
+
+ @Test
+ public void testOverridingHttpHeadersKeysIsCaseInsensitive() {
+ HttpHeaders obj = new HttpHeaders<>();
+ obj.put("key", "value");
+ obj.put("KEY", "value2");
+ obj.put("kEy", "value3");
+
+ assertEquals(1, obj.size());
+ assertEquals(obj.getOrDefault("key", null), "value3");
+ }
+
+ @Test
+ public void testValuesCanBeRemovedFromHttpHeaders() {
+ HttpHeaders obj = new HttpHeaders<>();
+ obj.put("key", "value");
+
+
+ assertEquals(1, obj.size());
+ obj.remove("key");
+ assertEquals(Collections.emptyMap(), obj);
+ }
+
+ @Test
+ public void testContainedKeysAreContainedInHttpHeaders() {
+ HttpHeaders obj = new HttpHeaders<>();
+ obj.put("key", "value");
+
+ assertTrue(obj.containsKey("key"));
+ }
+
+ @Test
+ public void testContainedValuesAreContainedInHttpHeaders() {
+ HttpHeaders obj = new HttpHeaders<>();
+ obj.put("key", "value");
+
+ assertTrue(obj.containsValue("value"));
+ }
+
+ @Test
+ public void testPutAllWorksInHttpHeaders() {
+ HttpHeaders obj = new HttpHeaders<>();
+ obj.put("key", "value");
+ obj.put("key2", "value2");
+
+ Map otherMap = new HashMap<>();
+ otherMap.put("otherKey1", "otherVal1");
+ otherMap.put("otherKey2", "otherVal2");
+ otherMap.put("otherKey3", "otherVal3");
+
+ obj.putAll(otherMap);
+
+ assertEquals(5, obj.size());
+ assertEquals(obj.getOrDefault("key", null), "value");
+ assertEquals(obj.getOrDefault("key2", null), "value2");
+ assertEquals(obj.getOrDefault("otherKey1", null), "otherVal1");
+ assertEquals(obj.getOrDefault("otherKey2", null), "otherVal2");
+ assertEquals(obj.getOrDefault("otherKey3", null), "otherVal3");
+ }
+
+ @Test
+ public void testClearWorksInHttpHeaders() {
+ HttpHeaders obj = new HttpHeaders<>();
+ obj.put("key", "value");
+ obj.put("key2", "value2");
+
+ assertEquals(2, obj.size());
+
+ obj.clear();
+
+ assertEquals(0, obj.size());
+ }
+
+ @Test
+ public void testKeySetWorksInHttpHeaders() {
+ HttpHeaders obj = new HttpHeaders<>();
+ obj.put("key", "value");
+ obj.put("key2", "value2");
+
+ Set keySet = obj.keySet();
+
+ assertNotNull(keySet);
+ assertEquals(2, keySet.size());
+ assertTrue(keySet.stream().allMatch(k -> k.equals("key") || k.equals("key2")));
+ }
+
+ @Test
+ public void testValuesWorksInHttpHeaders() {
+ HttpHeaders obj = new HttpHeaders<>();
+ obj.put("key", "value");
+ obj.put("key2", "value2");
+
+ Collection values = obj.values();
+
+ assertNotNull(values);
+ assertEquals(2, values.size());
+ assertTrue(values.stream().allMatch(v -> v.equals("value") || v.equals("value2")));
+ }
+
+ @Test
+ public void testEntrySetWorksInHttpHeaders() {
+ HttpHeaders obj = new HttpHeaders<>();
+ obj.put("key", "value");
+ obj.put("key2", "value2");
+
+ Set> entrySet = obj.entrySet();
+
+ assertNotNull(entrySet);
+ assertEquals(2, entrySet.size());
+
+
+ assertTrue(entrySet.stream()
+ .allMatch(kvp -> (kvp.getKey().equals("key") && kvp.getValue().equals("value"))
+ || (kvp.getKey().equals("key2") && kvp.getValue().equals("value2"))));
+ }
+}
diff --git a/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/HttpHeadersUtilTest.java b/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/HttpHeadersUtilTest.java
new file mode 100644
index 00000000..bba055bd
--- /dev/null
+++ b/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/HttpHeadersUtilTest.java
@@ -0,0 +1,146 @@
+package com.amazonaws.services.lambda.runtime.events;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.*;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class HttpHeadersUtilTest {
+
+ @Test
+ public void testWhenFromObjNullThenNullReturned() {
+ Map result = HttpHeaders.mergeOrReplace(null);
+ assertNull(result);
+ }
+
+ @Test
+ public void testWhenFromObjEmptyThenEmptyHttpHeadersReturned() {
+ Map from = new HashMap<>();
+ Map result = HttpHeaders.mergeOrReplace(from);
+
+ assertNotNull(result);
+ assertInstanceOf(HttpHeaders.class, result);
+ assertEquals(Collections.emptyMap(), result);
+ }
+
+ @Test
+ public void testWhenFromObjIsHashmapThenNewHttpHeadersReturned() {
+ HashMap from = createHashMap("key", "value");
+ Map result = HttpHeaders.mergeOrReplace(from);
+
+ assertNotNull(result);
+ assertInstanceOf(HttpHeaders.class, result);
+ assertEquals(from, result);
+ }
+
+ @Test
+ public void testWhenFromObjIsHashmapMultiValueThenNewHttpHeadersReturned() {
+ HashMap from = createHashMap(
+ "key", "value",
+ "key2", "value2",
+ "key3", "value3"
+ );
+ Map result = HttpHeaders.mergeOrReplace(from);
+
+ assertNotNull(result);
+ assertInstanceOf(HttpHeaders.class, result);
+ assertEquals(from, result);
+ }
+
+ @Test
+ public void testWhenFromObjIsTreemapMultiValueThenNewHttpHeadersReturned() {
+ TreeMap from = createTreeMap(
+ "key", "value",
+ "key2", "value2",
+ "key3", "value3"
+ );
+ Map result = HttpHeaders.mergeOrReplace(from);
+
+ assertNotNull(result);
+ assertInstanceOf(HttpHeaders.class, result);
+ assertEquals(from, result);
+ }
+
+ @Test
+ public void testWhenFromObjIsDuplicatedKeyMultiValueTreeMapThenReturnedHttpHeadersContainOnlyFinalValue() {
+ TreeMap from = createTreeMap(
+ "key", "value",
+ "KEY", "value2",
+ "kEy", "value3",
+ Collections.reverseOrder()
+ );
+ Map result = HttpHeaders.mergeOrReplace(from);
+
+ assertNotNull(result);
+ assertInstanceOf(HttpHeaders.class, result);
+ assertEquals(1, result.size());
+ Map.Entry lastEntry = from.lastEntry();
+ assertEquals(result.getOrDefault(lastEntry.getKey(), null), lastEntry.getValue());
+ }
+
+ @Test
+ public void testWhenFromObjIsDuplicatedKeyMultiValueHashMapThenReturnedHttpHeadersContainOnlyOneValue() {
+ HashMap from = createHashMap(
+ "key", "value",
+ "KEY", "value2",
+ "kEy", "value3"
+ );
+ Map result = HttpHeaders.mergeOrReplace(from);
+
+ assertNotNull(result);
+ assertInstanceOf(HttpHeaders.class, result);
+ assertEquals(1, result.size());
+
+ Map.Entry entry = from.entrySet().iterator().next();
+ assertTrue(from.entrySet().stream()
+ .anyMatch(e -> entry.getKey().equals(e.getKey()) && entry.getValue().equals(e.getValue())));
+ }
+
+ @Test
+ public void testWhenFromObjAlreadyHttpHeadersThenSameInstanceReturned() {
+ Map from = new HttpHeaders<>();
+ from.put("key", "value");
+
+ Map result = HttpHeaders.mergeOrReplace(from);
+ assertSame(from, result);
+ }
+
+ @Test
+ public void testWhenFromObjAlreadyEmptyHttpHeadersThenSameInstanceReturned() {
+ Map from = new HttpHeaders<>();
+
+ Map result = HttpHeaders.mergeOrReplace(from);
+ assertSame(from, result);
+ }
+
+ private static HashMap createHashMap(String key1, T val1) {
+ HashMap map = new HashMap<>();
+ map.put(key1, val1);
+ return map;
+ }
+
+ private static HashMap createHashMap(String key1, T val1, String key2, T val2, String key3, T val3) {
+ HashMap map = new HashMap<>();
+ map.put(key1, val1);
+ map.put(key2, val2);
+ map.put(key3, val3);
+ return map;
+ }
+
+ private static TreeMap createTreeMap(String key1, T val1, String key2, T val2, String key3, T val3) {
+ TreeMap map = new TreeMap<>();
+ map.put(key1, val1);
+ map.put(key2, val2);
+ map.put(key3, val3);
+ return map;
+ }
+
+ private static TreeMap createTreeMap(String key1, T val1, String key2, T val2, String key3, T val3, java.util.Comparator ordering) {
+ TreeMap map = new TreeMap<>();
+ map.put(key1, val1);
+ map.put(key2, val2);
+ map.put(key3, val3);
+ return map;
+ }
+}
diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/CustomerClassLoader.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/CustomerClassLoader.java
index 3932547d..ee554c14 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/CustomerClassLoader.java
+++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/CustomerClassLoader.java
@@ -3,6 +3,7 @@
package com.amazonaws.services.lambda.runtime.api.client;
import java.io.File;
+import java.io.FilenameFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
@@ -18,6 +19,18 @@ class CustomerClassLoader extends URLClassLoader {
* does not depend on the underlying filesystem.
*/
private final static Comparator LEXICAL_SORT_ORDER = Comparator.comparing(String::toString);
+ private final static FilenameFilter JAR_FILE_NAME_FILTER = new FilenameFilter() {
+
+ @Override
+ public boolean accept(File dir, String name) {
+ int offset = name.length() - 4;
+ if (offset <= 0) { /* must be at least A.jar */
+ return false;
+ } else {
+ return name.startsWith(".jar", offset);
+ }
+ }
+ };
CustomerClassLoader(String taskRoot, String optRoot, ClassLoader parent) throws IOException {
super(getUrls(taskRoot, optRoot), parent);
@@ -36,15 +49,14 @@ private static void appendJars(File dir, List result) throws MalformedURLEx
if (!dir.isDirectory()) {
return;
}
- String[] names = dir.list();
+ String[] names = dir.list(CustomerClassLoader.JAR_FILE_NAME_FILTER);
if (names == null) {
return;
}
Arrays.sort(names, CustomerClassLoader.LEXICAL_SORT_ORDER);
- for(String path : names) {
- if(path.endsWith(".jar")) {
- result.add(newURL(dir, path));
- }
+
+ for (String path : names) {
+ result.add(newURL(dir, path));
}
}
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh b/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
index e404d56a..872f3c7a 100755
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
@@ -6,7 +6,7 @@ set -euo pipefail
SRC_DIR=$(dirname "$0")
DST_DIR=${1}
MULTI_ARCH=${2}
-CURL_VERSION=7.83.0
+CURL_VERSION=7.84.0
# Not using associative arrays to maintain bash 3 compatibility with building on MacOS
# MacOS ships with bash 3 and associative arrays require bash 4+
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/curl-7.83.0.tar.gz b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/curl-7.83.0.tar.gz
deleted file mode 100644
index 3d8e0775..00000000
Binary files a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/curl-7.83.0.tar.gz and /dev/null differ
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/curl-7.84.0.tar.gz b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/curl-7.84.0.tar.gz
new file mode 100644
index 00000000..2c084061
Binary files /dev/null and b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/curl-7.84.0.tar.gz differ
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/codebuild_build.sh b/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/codebuild_build.sh
index e177edb8..2a6ffa97 100755
--- a/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/codebuild_build.sh
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/codebuild_build.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# This file is copied from https://github.com/aws/aws-codebuild-docker-images/blob/f0912e4b16e427da35351fc102f0f56f4ceb938a/local_builds/codebuild_build.sh
+# This file is copied from https://github.com/aws/aws-codebuild-docker-images/blob/282c6634e8c83c2a9841719b09aabfced3461981/local_builds/codebuild_build.sh
function allOSRealPath() {
if isOSWindows
@@ -36,6 +36,7 @@ function usage {
echo " -a Used to specify an artifact output directory."
echo "Options:"
echo " -l IMAGE Used to override the default local agent image."
+ echo " -r Used to specify a report output directory."
echo " -s Used to specify source information. Defaults to the current working directory for primary source."
echo " * First (-s) is for primary source"
echo " * Use additional (-s) in : format for secondary source"
@@ -61,10 +62,11 @@ awsconfig_flag=false
mount_src_dir_flag=false
docker_privileged_mode_flag=false
-while getopts "cmdi:a:s:b:e:l:p:h" opt; do
+while getopts "cmdi:a:r:s:b:e:l:p:h" opt; do
case $opt in
i ) image_flag=true; image_name=$OPTARG;;
a ) artifact_flag=true; artifact_dir=$OPTARG;;
+ r ) report_dir=$OPTARG;;
b ) buildspec=$OPTARG;;
c ) awsconfig_flag=true;;
m ) mount_src_dir_flag=true;;
@@ -106,6 +108,11 @@ fi
docker_command+="\"IMAGE_NAME=$image_name\" -e \
\"ARTIFACTS=$(allOSRealPath "$artifact_dir")\""
+if [ -n "$report_dir" ]
+then
+ docker_command+=" -e \"REPORTS=$(allOSRealPath "$report_dir")\""
+fi
+
if [ -z "$source_dirs" ]
then
docker_command+=" -e \"SOURCE=$(allOSRealPath "$PWD")\""
@@ -176,7 +183,12 @@ else
docker_command+=" -e \"INITIATOR=$USER\""
fi
-docker_command+=" public.ecr.aws/codebuild/local-builds:latest"
+if [ -n "$local_agent_image" ]
+then
+ docker_command+=" $local_agent_image"
+else
+ docker_command+=" public.ecr.aws/codebuild/local-builds:latest"
+fi
# Note we do not expose the AWS_SECRET_ACCESS_KEY or the AWS_SESSION_TOKEN
exposed_command=$docker_command
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/test_one.sh b/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/test_one.sh
index 838c0ae7..ba49e826 100755
--- a/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/test_one.sh
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/test_one.sh
@@ -18,6 +18,15 @@ function usage {
>&2 echo " env Additional environment variables file."
}
+# codebuild/local-builds images are not multi-architectural
+function get_local_agent_image() {
+ if [[ "$(arch)" == "aarch64" ]]; then
+ echo "public.ecr.aws/codebuild/local-builds:aarch64"
+ else
+ echo "public.ecr.aws/codebuild/local-builds:latest"
+ fi
+}
+
main() {
if (( $# != 5 && $# != 6)); then
>&2 echo "Invalid number of parameters."
@@ -48,7 +57,7 @@ main() {
echo "RUNTIME_VERSION=$RUNTIME_VERSION"
echo "PLATFORM=$PLATFORM"
} >> "$ENVFILE"
-
+
ARTIFACTS_DIR="$CODEBUILD_TEMP_DIR/artifacts"
mkdir -p "$ARTIFACTS_DIR"
# Run CodeBuild local agent.
@@ -57,7 +66,8 @@ main() {
-a "$ARTIFACTS_DIR" \
-e "$ENVFILE" \
-b "$BUILDSPEC_YML" \
- -s "$(dirname $PWD)"
+ -s "$(dirname $PWD)" \
+ -l "$(get_local_agent_image)"
}
main "$@"
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.alpine.yml b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.alpine.yml
index fe1c4e98..4f8caf39 100644
--- a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.alpine.yml
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.alpine.yml
@@ -79,49 +79,7 @@ phases:
--build-arg DISTRO_VERSION="${DISTRO_VERSION}"
build:
commands:
- - set -x
- - echo "Running Image ${IMAGE_TAG}"
- - docker network create "${OS_DISTRIBUTION}-network"
- - >
- docker run \
- --detach \
- --name "${OS_DISTRIBUTION}-app" \
- --network "${OS_DISTRIBUTION}-network" \
- --entrypoint="" \
- "${IMAGE_TAG}" \
- sh -c "/usr/bin/${RIE} ${JAVA_BINARY_LOCATION} -jar ./HelloWorld-1.0.jar helloworld.App"
- - sleep 2
- - >
- docker run \
- --name "${OS_DISTRIBUTION}-tester" \
- --env "TARGET=${OS_DISTRIBUTION}-app" \
- --network "${OS_DISTRIBUTION}-network" \
- --entrypoint="" \
- "${IMAGE_TAG}" \
- sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10'
- - actual="$(docker logs --tail 1 "${OS_DISTRIBUTION}-tester" | xargs)"
- - expected='success'
- - |
- echo "Response: ${actual}"
- if [[ "$actual" != "$expected" ]]; then
- echo "fail! runtime: $RUNTIME - expected output $expected - got $actual"
- exit -1
- fi
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/run_invocation_test.sh
finally:
- - |
- echo "---------Container Logs: ${OS_DISTRIBUTION}-app----------"
- echo
- docker logs "${OS_DISTRIBUTION}-app" || true
- echo
- echo "---------------------------------------------------"
- echo "--------Container Logs: ${OS_DISTRIBUTION}-tester--------"
- echo
- docker logs "${OS_DISTRIBUTION}-tester" || true
- echo
- echo "---------------------------------------------------"
- - echo "Cleaning up..."
- - docker stop "${OS_DISTRIBUTION}-app" || true
- - docker rm --force "${OS_DISTRIBUTION}-app" || true
- - docker stop "${OS_DISTRIBUTION}-tester" || true
- - docker rm --force "${OS_DISTRIBUTION}-tester" || true
- - docker network rm "${OS_DISTRIBUTION}-network" || true
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/fetch_test_container_logs.sh
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/clean_up.sh
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazoncorretto.yml b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazoncorretto.yml
index 17a0c48f..fd45aabb 100644
--- a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazoncorretto.yml
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazoncorretto.yml
@@ -75,49 +75,7 @@ phases:
--build-arg DISTRO_VERSION="${DISTRO_VERSION}"
build:
commands:
- - set -x
- - echo "Running Image ${IMAGE_TAG}"
- - docker network create "${OS_DISTRIBUTION}-network"
- - >
- docker run \
- --detach \
- --name "${OS_DISTRIBUTION}-app" \
- --network "${OS_DISTRIBUTION}-network" \
- --entrypoint="" \
- "${IMAGE_TAG}" \
- sh -c "/usr/bin/${RIE} ${JAVA_BINARY_LOCATION} -jar ./HelloWorld-1.0.jar helloworld.App"
- - sleep 2
- - >
- docker run \
- --name "${OS_DISTRIBUTION}-tester" \
- --env "TARGET=${OS_DISTRIBUTION}-app" \
- --network "${OS_DISTRIBUTION}-network" \
- --entrypoint="" \
- "${IMAGE_TAG}" \
- sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10'
- - actual="$(docker logs --tail 1 "${OS_DISTRIBUTION}-tester" | xargs)"
- - expected='success'
- - |
- echo "Response: ${actual}"
- if [[ "$actual" != "$expected" ]]; then
- echo "fail! runtime: $RUNTIME - expected output $expected - got $actual"
- exit -1
- fi
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/run_invocation_test.sh
finally:
- - |
- echo "---------Container Logs: ${OS_DISTRIBUTION}-app----------"
- echo
- docker logs "${OS_DISTRIBUTION}-app" || true
- echo
- echo "---------------------------------------------------"
- echo "--------Container Logs: ${OS_DISTRIBUTION}-tester--------"
- echo
- docker logs "${OS_DISTRIBUTION}-tester" || true
- echo
- echo "---------------------------------------------------"
- - echo "Cleaning up..."
- - docker stop "${OS_DISTRIBUTION}-app" || true
- - docker rm --force "${OS_DISTRIBUTION}-app" || true
- - docker stop "${OS_DISTRIBUTION}-tester" || true
- - docker rm --force "${OS_DISTRIBUTION}-tester" || true
- - docker network rm "${OS_DISTRIBUTION}-network" || true
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/fetch_test_container_logs.sh
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/clean_up.sh
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazonlinux.1.yml b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazonlinux.1.yml
index 9eafb6de..197e9724 100644
--- a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazonlinux.1.yml
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazonlinux.1.yml
@@ -61,49 +61,7 @@ phases:
--build-arg DISTRO_VERSION="${DISTRO_VERSION}"
build:
commands:
- - set -x
- - echo "Running Image ${IMAGE_TAG}"
- - docker network create "${OS_DISTRIBUTION}-network"
- - >
- docker run \
- --detach \
- --name "${OS_DISTRIBUTION}-app" \
- --network "${OS_DISTRIBUTION}-network" \
- --entrypoint="" \
- "${IMAGE_TAG}" \
- sh -c "/usr/bin/${RIE} ${JAVA_BINARY_LOCATION} -jar ./HelloWorld-1.0.jar helloworld.App"
- - sleep 2
- - >
- docker run \
- --name "${OS_DISTRIBUTION}-tester" \
- --env "TARGET=${OS_DISTRIBUTION}-app" \
- --network "${OS_DISTRIBUTION}-network" \
- --entrypoint="" \
- "${IMAGE_TAG}" \
- sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10'
- - actual="$(docker logs --tail 1 "${OS_DISTRIBUTION}-tester" | xargs)"
- - expected='success'
- - |
- echo "Response: ${actual}"
- if [[ "$actual" != "$expected" ]]; then
- echo "fail! runtime: $RUNTIME - expected output $expected - got $actual"
- exit -1
- fi
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/run_invocation_test.sh
finally:
- - |
- echo "---------Container Logs: ${OS_DISTRIBUTION}-app----------"
- echo
- docker logs "${OS_DISTRIBUTION}-app" || true
- echo
- echo "---------------------------------------------------"
- echo "--------Container Logs: ${OS_DISTRIBUTION}-tester--------"
- echo
- docker logs "${OS_DISTRIBUTION}-tester" || true
- echo
- echo "---------------------------------------------------"
- - echo "Cleaning up..."
- - docker stop "${OS_DISTRIBUTION}-app" || true
- - docker rm --force "${OS_DISTRIBUTION}-app" || true
- - docker stop "${OS_DISTRIBUTION}-tester" || true
- - docker rm --force "${OS_DISTRIBUTION}-tester" || true
- - docker network rm "${OS_DISTRIBUTION}-network" || true
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/fetch_test_container_logs.sh
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/clean_up.sh
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazonlinux.2.yml b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazonlinux.2.yml
index cdd02073..75b816e8 100644
--- a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazonlinux.2.yml
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazonlinux.2.yml
@@ -74,49 +74,7 @@ phases:
--build-arg DISTRO_VERSION="${DISTRO_VERSION}"
build:
commands:
- - set -x
- - echo "Running Image ${IMAGE_TAG}"
- - docker network create "${OS_DISTRIBUTION}-network"
- - >
- docker run \
- --detach \
- --name "${OS_DISTRIBUTION}-app" \
- --network "${OS_DISTRIBUTION}-network" \
- --entrypoint="" \
- "${IMAGE_TAG}" \
- sh -c "/usr/bin/${RIE} ${JAVA_BINARY_LOCATION} -jar ./HelloWorld-1.0.jar helloworld.App"
- - sleep 2
- - >
- docker run \
- --name "${OS_DISTRIBUTION}-tester" \
- --env "TARGET=${OS_DISTRIBUTION}-app" \
- --network "${OS_DISTRIBUTION}-network" \
- --entrypoint="" \
- "${IMAGE_TAG}" \
- sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10'
- - actual="$(docker logs --tail 1 "${OS_DISTRIBUTION}-tester" | xargs)"
- - expected='success'
- - |
- echo "Response: ${actual}"
- if [[ "$actual" != "$expected" ]]; then
- echo "fail! runtime: $RUNTIME - expected output $expected - got $actual"
- exit -1
- fi
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/run_invocation_test.sh
finally:
- - |
- echo "---------Container Logs: ${OS_DISTRIBUTION}-app----------"
- echo
- docker logs "${OS_DISTRIBUTION}-app" || true
- echo
- echo "---------------------------------------------------"
- echo "--------Container Logs: ${OS_DISTRIBUTION}-tester--------"
- echo
- docker logs "${OS_DISTRIBUTION}-tester" || true
- echo
- echo "---------------------------------------------------"
- - echo "Cleaning up..."
- - docker stop "${OS_DISTRIBUTION}-app" || true
- - docker rm --force "${OS_DISTRIBUTION}-app" || true
- - docker stop "${OS_DISTRIBUTION}-tester" || true
- - docker rm --force "${OS_DISTRIBUTION}-tester" || true
- - docker network rm "${OS_DISTRIBUTION}-network" || true
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/fetch_test_container_logs.sh
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/clean_up.sh
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.centos.yml b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.centos.yml
index 307b3280..d718c264 100644
--- a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.centos.yml
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.centos.yml
@@ -74,49 +74,7 @@ phases:
--build-arg DISTRO_VERSION="${DISTRO_VERSION}"
build:
commands:
- - set -x
- - echo "Running Image ${IMAGE_TAG}"
- - docker network create "${OS_DISTRIBUTION}-network"
- - >
- docker run \
- --detach \
- --name "${OS_DISTRIBUTION}-app" \
- --network "${OS_DISTRIBUTION}-network" \
- --entrypoint="" \
- "${IMAGE_TAG}" \
- sh -c "/usr/bin/${RIE} ${JAVA_BINARY_LOCATION} -jar ./HelloWorld-1.0.jar helloworld.App"
- - sleep 2
- - >
- docker run \
- --name "${OS_DISTRIBUTION}-tester" \
- --env "TARGET=${OS_DISTRIBUTION}-app" \
- --network "${OS_DISTRIBUTION}-network" \
- --entrypoint="" \
- "${IMAGE_TAG}" \
- sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10'
- - actual="$(docker logs --tail 1 "${OS_DISTRIBUTION}-tester" | xargs)"
- - expected='success'
- - |
- echo "Response: ${actual}"
- if [[ "$actual" != "$expected" ]]; then
- echo "fail! runtime: $RUNTIME - expected output $expected - got $actual"
- exit -1
- fi
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/run_invocation_test.sh
finally:
- - |
- echo "---------Container Logs: ${OS_DISTRIBUTION}-app----------"
- echo
- docker logs "${OS_DISTRIBUTION}-app" || true
- echo
- echo "---------------------------------------------------"
- echo "--------Container Logs: ${OS_DISTRIBUTION}-tester--------"
- echo
- docker logs "${OS_DISTRIBUTION}-tester" || true
- echo
- echo "---------------------------------------------------"
- - echo "Cleaning up..."
- - docker stop "${OS_DISTRIBUTION}-app" || true
- - docker rm --force "${OS_DISTRIBUTION}-app" || true
- - docker stop "${OS_DISTRIBUTION}-tester" || true
- - docker rm --force "${OS_DISTRIBUTION}-tester" || true
- - docker network rm "${OS_DISTRIBUTION}-network" || true
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/fetch_test_container_logs.sh
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/clean_up.sh
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.debian.yml b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.debian.yml
index 7c088810..d2772fbf 100644
--- a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.debian.yml
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.debian.yml
@@ -78,49 +78,7 @@ phases:
--build-arg DISTRO_VERSION="${DISTRO_VERSION}"
build:
commands:
- - set -x
- - echo "Running Image ${IMAGE_TAG}"
- - docker network create "${OS_DISTRIBUTION}-network"
- - >
- docker run \
- --detach \
- --name "${OS_DISTRIBUTION}-app" \
- --network "${OS_DISTRIBUTION}-network" \
- --entrypoint="" \
- "${IMAGE_TAG}" \
- sh -c "/usr/bin/${RIE} ${JAVA_BINARY_LOCATION} -jar ./HelloWorld-1.0.jar helloworld.App"
- - sleep 2
- - >
- docker run \
- --name "${OS_DISTRIBUTION}-tester" \
- --env "TARGET=${OS_DISTRIBUTION}-app" \
- --network "${OS_DISTRIBUTION}-network" \
- --entrypoint="" \
- "${IMAGE_TAG}" \
- sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10'
- - actual="$(docker logs --tail 1 "${OS_DISTRIBUTION}-tester" | xargs)"
- - expected='success'
- - |
- echo "Response: ${actual}"
- if [[ "$actual" != "$expected" ]]; then
- echo "fail! runtime: $RUNTIME - expected output $expected - got $actual"
- exit -1
- fi
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/run_invocation_test.sh
finally:
- - |
- echo "---------Container Logs: ${OS_DISTRIBUTION}-app----------"
- echo
- docker logs "${OS_DISTRIBUTION}-app" || true
- echo
- echo "---------------------------------------------------"
- echo "--------Container Logs: ${OS_DISTRIBUTION}-tester--------"
- echo
- docker logs "${OS_DISTRIBUTION}-tester" || true
- echo
- echo "---------------------------------------------------"
- - echo "Cleaning up..."
- - docker stop "${OS_DISTRIBUTION}-app" || true
- - docker rm --force "${OS_DISTRIBUTION}-app" || true
- - docker stop "${OS_DISTRIBUTION}-tester" || true
- - docker rm --force "${OS_DISTRIBUTION}-tester" || true
- - docker network rm "${OS_DISTRIBUTION}-network" || true
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/fetch_test_container_logs.sh
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/clean_up.sh
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.ubuntu.yml b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.ubuntu.yml
index 7be6274f..2a90017b 100644
--- a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.ubuntu.yml
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.ubuntu.yml
@@ -80,49 +80,7 @@ phases:
--build-arg DISTRO_VERSION="${DISTRO_VERSION}"
build:
commands:
- - set -x
- - echo "Running Image ${IMAGE_TAG}"
- - docker network create "${OS_DISTRIBUTION}-network"
- - >
- docker run \
- --detach \
- --name "${OS_DISTRIBUTION}-app" \
- --network "${OS_DISTRIBUTION}-network" \
- --entrypoint="" \
- "${IMAGE_TAG}" \
- sh -c "/usr/bin/${RIE} ${JAVA_BINARY_LOCATION} -jar ./HelloWorld-1.0.jar helloworld.App"
- - sleep 2
- - >
- docker run \
- --name "${OS_DISTRIBUTION}-tester" \
- --env "TARGET=${OS_DISTRIBUTION}-app" \
- --network "${OS_DISTRIBUTION}-network" \
- --entrypoint="" \
- "${IMAGE_TAG}" \
- sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10'
- - actual="$(docker logs --tail 1 "${OS_DISTRIBUTION}-tester" | xargs)"
- - expected='success'
- - |
- echo "Response: ${actual}"
- if [[ "$actual" != "$expected" ]]; then
- echo "fail! runtime: $RUNTIME - expected output $expected - got $actual"
- exit -1
- fi
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/run_invocation_test.sh
finally:
- - |
- echo "---------Container Logs: ${OS_DISTRIBUTION}-app----------"
- echo
- docker logs "${OS_DISTRIBUTION}-app" || true
- echo
- echo "---------------------------------------------------"
- echo "--------Container Logs: ${OS_DISTRIBUTION}-tester--------"
- echo
- docker logs "${OS_DISTRIBUTION}-tester" || true
- echo
- echo "---------------------------------------------------"
- - echo "Cleaning up..."
- - docker stop "${OS_DISTRIBUTION}-app" || true
- - docker rm --force "${OS_DISTRIBUTION}-app" || true
- - docker stop "${OS_DISTRIBUTION}-tester" || true
- - docker rm --force "${OS_DISTRIBUTION}-tester" || true
- - docker network rm "${OS_DISTRIBUTION}-network" || true
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/fetch_test_container_logs.sh
+ - aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/clean_up.sh
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/clean_up.sh b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/clean_up.sh
new file mode 100755
index 00000000..236fa7b2
--- /dev/null
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/clean_up.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+# Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+
+set -euo pipefail
+
+echo "Cleaning up..."
+docker stop "${OS_DISTRIBUTION}-app" || true
+docker rm --force "${OS_DISTRIBUTION}-app" || true
+docker stop "${OS_DISTRIBUTION}-tester" || true
+docker rm --force "${OS_DISTRIBUTION}-tester" || true
+docker network rm "${OS_DISTRIBUTION}-network" || true
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/fetch_test_container_logs.sh b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/fetch_test_container_logs.sh
new file mode 100755
index 00000000..4bc809dc
--- /dev/null
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/fetch_test_container_logs.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+# Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+
+set -euo pipefail
+
+echo "---------Container Logs: ${OS_DISTRIBUTION}-app----------"
+echo
+docker logs "${OS_DISTRIBUTION}-app" || true
+echo
+echo "---------------------------------------------------"
+echo "--------Container Logs: ${OS_DISTRIBUTION}-tester--------"
+echo
+docker logs "${OS_DISTRIBUTION}-tester" || true
+echo
+echo "---------------------------------------------------"
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/run_invocation_test.sh b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/run_invocation_test.sh
new file mode 100755
index 00000000..f5ebf068
--- /dev/null
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/scripts/run_invocation_test.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+# Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+
+set -euxo pipefail
+
+echo "Running Image ${IMAGE_TAG}"
+docker network create "${OS_DISTRIBUTION}-network"
+
+function_jar="./HelloWorld-1.0.jar"
+function_handler="helloworld.App"
+docker run \
+ --detach \
+ --name "${OS_DISTRIBUTION}-app" \
+ --network "${OS_DISTRIBUTION}-network" \
+ --entrypoint="" \
+ --platform="${PLATFORM}" \
+ "${IMAGE_TAG}" \
+ sh -c "/usr/bin/${RIE} ${JAVA_BINARY_LOCATION} -jar ${function_jar} ${function_handler}"
+sleep 2
+
+# running on arm64 hosts with x86_64 being emulated takes significantly more time than any other combination
+if [[ "$(arch)" == "aarch64" ]] && [[ "${PLATFORM}" == "linux/amd64" ]]; then
+ declare -i time_out=150
+else
+ declare -i time_out=10
+fi
+
+docker run \
+ --name "${OS_DISTRIBUTION}-tester" \
+ --env "TARGET=${OS_DISTRIBUTION}-app" \
+ --env "MAX_TIME=${time_out}" \
+ --network "${OS_DISTRIBUTION}-network" \
+ --entrypoint="" \
+ --platform="${PLATFORM}" \
+ "${IMAGE_TAG}" \
+ sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time ${MAX_TIME}'
+actual="$(docker logs --tail 1 "${OS_DISTRIBUTION}-tester" | xargs)"
+expected='success'
+echo "Response: ${actual}"
+if [[ "${actual}" != "${expected}" ]]; then
+ echo "fail! runtime: ${RUNTIME} - expected output ${expected} - got ${actual}"
+ exit 1
+fi
diff --git a/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/EventLoaderTest.java b/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/EventLoaderTest.java
index 47a9c52c..56879552 100644
--- a/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/EventLoaderTest.java
+++ b/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/EventLoaderTest.java
@@ -12,11 +12,9 @@
import org.junit.jupiter.api.Test;
import java.time.Instant;
-import java.util.Date;
import java.util.List;
import java.util.Map;
-import static java.time.Instant.ofEpochSecond;
import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.Assertions.from;
@@ -86,8 +84,8 @@ public void testLoadKafkaEvent() {
KafkaEvent.KafkaEventRecord record = event.getRecords().get("mytopic-01").get(0);
assertThat(record.getValue()).decodedAsBase64().asString().isEqualTo("Hello from Kafka !!");
-
- String headerValue = new String(record.getHeaders().get(0).get("headerKey"));
+
+ String headerValue = new String(record.getHeaders().get(0).get("headerKey"));
assertThat(headerValue).isEqualTo("headerValue");
}
diff --git a/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/HeadersTest.java b/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/HeadersTest.java
new file mode 100644
index 00000000..a326d22e
--- /dev/null
+++ b/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/HeadersTest.java
@@ -0,0 +1,56 @@
+package com.amazonaws.services.lambda.runtime.tests;
+
+import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent;
+import com.amazonaws.services.lambda.runtime.events.apigateway.APIGatewayCustomAuthorizerEvent;
+import com.amazonaws.services.lambda.runtime.events.apigateway.APIGatewayProxyRequestEvent;
+import com.amazonaws.services.lambda.runtime.events.apigateway.APIGatewayV2CustomAuthorizerEvent;
+import com.amazonaws.services.lambda.runtime.events.apigateway.APIGatewayV2HTTPEvent;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class HeadersTest {
+
+ @Test
+ public void testHeadersApiGatewayRestEvent() {
+ APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_rest_event.json");
+
+ assertThat(event.getHeaders().get("Header1")).isEqualTo("value1");
+ assertThat(event.getHeaders().get("header1")).isEqualTo("value1");
+ assertThat(event.getMultiValueHeaders().get("header1")).contains("value1", "value11");
+ assertThat(event.getMultiValueHeaders().get("Header1")).contains("value1", "value11");
+ assertThat(event.getHeaders()).hasSize(2);
+ }
+
+ @Test
+ public void testHeadersApiGatewayHttpEvent() {
+ APIGatewayV2HTTPEvent event = EventLoader.loadApiGatewayHttpEvent("apigw_http_event.json");
+
+ assertThat(event.getHeaders().get("Header1")).isEqualTo("value1");
+ assertThat(event.getHeaders().get("header1")).isEqualTo("value1");
+ }
+
+ @Test
+ public void testHeadersAPIGatewayCustomAuthorizerEvent() {
+ APIGatewayCustomAuthorizerEvent event = EventLoader.loadAPIGatewayCustomAuthorizerEvent("apigw_auth.json");
+
+ assertThat(event.getHeaders().get("Accept")).isEqualTo("application/json");
+ assertThat(event.getHeaders().get("accept")).isEqualTo("application/json");
+ }
+
+ @Test
+ public void testHeadersAPIGatewayV2CustomAuthorizerEvent() {
+ APIGatewayV2CustomAuthorizerEvent event = EventLoader.loadAPIGatewayV2CustomAuthorizerEvent("apigw_auth_v2.json");
+
+ assertThat(event.getHeaders().get("Header1")).isEqualTo("Value1");
+ assertThat(event.getHeaders().get("header1")).isEqualTo("Value1");
+ }
+
+ @Test
+ public void testHeadersApplicationLoadBalancerRequestEvent() {
+ ApplicationLoadBalancerRequestEvent event = EventLoader.loadApplicationLoadBalancerRequestEvent("elb_event.json");
+
+ assertThat(event.getHeaders().get("Accept")).isEqualTo("application/json");
+ assertThat(event.getHeaders().get("accept")).isEqualTo("application/json");
+ }
+}
diff --git a/aws-lambda-java-tests/src/test/resources/apigw_auth.json b/aws-lambda-java-tests/src/test/resources/apigw_auth.json
index eb73956e..bfe2d112 100644
--- a/aws-lambda-java-tests/src/test/resources/apigw_auth.json
+++ b/aws-lambda-java-tests/src/test/resources/apigw_auth.json
@@ -10,6 +10,7 @@
"headers": {
"X-AMZ-Date": "20170718T062915Z",
"Accept": "*/*",
+ "accept": "application/json",
"HeaderAuth1": "headerValue1",
"CloudFront-Viewer-Country": "US",
"CloudFront-Forwarded-Proto": "https",
diff --git a/aws-lambda-java-tests/src/test/resources/apigw_auth_v2.json b/aws-lambda-java-tests/src/test/resources/apigw_auth_v2.json
index a603763e..70024f22 100644
--- a/aws-lambda-java-tests/src/test/resources/apigw_auth_v2.json
+++ b/aws-lambda-java-tests/src/test/resources/apigw_auth_v2.json
@@ -8,8 +8,9 @@
"rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value",
"cookies": [ "cookie1", "cookie2" ],
"headers": {
- "Header1": "value1",
- "Header2": "value2"
+ "header1": "value1",
+ "Header2": "value2",
+ "Header1": "Value1"
},
"queryStringParameters": { "parameter1": "value1,value2", "parameter2": "value" },
"requestContext": {
diff --git a/aws-lambda-java-tests/src/test/resources/apigw_http_event.json b/aws-lambda-java-tests/src/test/resources/apigw_http_event.json
index 88f4e5b4..43c7e4b3 100644
--- a/aws-lambda-java-tests/src/test/resources/apigw_http_event.json
+++ b/aws-lambda-java-tests/src/test/resources/apigw_http_event.json
@@ -8,8 +8,9 @@
"cookie2"
],
"headers": {
- "Header1": "value1",
- "Header2": "value1,value2"
+ "Header1": "Value1",
+ "Header2": "value1,value2",
+ "header1": "value1"
},
"queryStringParameters": {
"parameter1": "value1,value2",
diff --git a/aws-lambda-java-tests/src/test/resources/apigw_rest_event.json b/aws-lambda-java-tests/src/test/resources/apigw_rest_event.json
index 28f10c22..e7907d58 100644
--- a/aws-lambda-java-tests/src/test/resources/apigw_rest_event.json
+++ b/aws-lambda-java-tests/src/test/resources/apigw_rest_event.json
@@ -4,8 +4,9 @@
"path": "/my/path",
"httpMethod": "GET",
"headers": {
- "Header1": "value1",
- "Header2": "value2"
+ "Header1": "Value1",
+ "Header2": "value2",
+ "header1": "value1"
},
"multiValueHeaders": {
"Header1": [
@@ -14,6 +15,10 @@
"Header2": [
"value1",
"value2"
+ ],
+ "header1": [
+ "value1",
+ "value11"
]
},
"queryStringParameters": {
diff --git a/aws-lambda-java-tests/src/test/resources/elb_event.json b/aws-lambda-java-tests/src/test/resources/elb_event.json
index 23f599f4..59e314b7 100644
--- a/aws-lambda-java-tests/src/test/resources/elb_event.json
+++ b/aws-lambda-java-tests/src/test/resources/elb_event.json
@@ -9,6 +9,7 @@
"queryStringParameters": {},
"headers": {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
+ "Accept": "application/json",
"accept-encoding": "gzip",
"accept-language": "en-US,en;q=0.5",
"connection": "keep-alive",