Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@
</dependencies>
</dependencyManagement>
<dependencies>
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.14</version>
</dependency>
<!-- https://mvnrepository.com/artifact/software.amazon.cloudformation/aws-cloudformation-resource-schema -->
<dependency>
<groupId>software.amazon.cloudformation</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,8 @@ public void handleRequest(final InputStream inputStream, final OutputStream outp
throw new TerminalException("No request object received");
}

String input = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
String input = this.serializer.decompress(IOUtils.toString(inputStream, StandardCharsets.UTF_8));

JSONObject rawInput = new JSONObject(new JSONTokener(input));

// deserialize incoming payload to modelled request
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*/
package software.amazon.cloudformation.resource;

import com.amazonaws.util.IOUtils;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
Expand All @@ -22,14 +23,24 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import org.apache.commons.codec.binary.Base64;
import software.amazon.cloudformation.proxy.aws.AWSServiceSerdeModule;

public class Serializer {

public static final String COMPRESSED = "compressed";
Comment thread
ammokhov marked this conversation as resolved.
Outdated
private static final ObjectMapper OBJECT_MAPPER;

private static final ObjectMapper STRICT_OBJECT_MAPPER;
private static final TypeReference<Map<String, String>> MAP_TYPE_REFERENCE = new TypeReference<Map<String, String>>() {
};

/**
* Configures the specified ObjectMapper with the (de)serialization behaviours
Expand Down Expand Up @@ -76,10 +87,37 @@ public <T> String serialize(final T modelObject) throws JsonProcessingException
return OBJECT_MAPPER.writeValueAsString(modelObject);
}

public <T> String compress(final String modelInput) throws IOException {
final Map<String, String> map = new HashMap<>();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Comment thread
ammokhov marked this conversation as resolved.
Outdated
GZIPOutputStream gzip = new GZIPOutputStream(byteArrayOutputStream);
gzip.write(modelInput.getBytes(StandardCharsets.UTF_8));
gzip.close();
map.put(COMPRESSED, Base64.encodeBase64String(byteArrayOutputStream.toByteArray()));
Comment thread
ammokhov marked this conversation as resolved.
Outdated
return OBJECT_MAPPER.writeValueAsString(map);
}

public <T> T deserialize(final String s, final TypeReference<T> reference) throws IOException {
return OBJECT_MAPPER.readValue(s, reference);
}

public String decompress(final String s) {
try {
final Map<String, String> map = deserialize(s, MAP_TYPE_REFERENCE);
Comment thread
ammokhov marked this conversation as resolved.
Outdated

if (!map.containsKey(COMPRESSED)) {
return s;
}

final byte[] bytes = Base64.decodeBase64(map.get(COMPRESSED));
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
Comment thread
ammokhov marked this conversation as resolved.
Outdated
GZIPInputStream gzipInputStream = new GZIPInputStream(byteArrayInputStream);
return new String(IOUtils.toByteArray(gzipInputStream), StandardCharsets.UTF_8);
} catch (IOException e) {
return s;
Comment thread
ammokhov marked this conversation as resolved.
Outdated
}
}

public <T> T deserializeStrict(final String s, final TypeReference<T> reference) throws IOException {
return STRICT_OBJECT_MAPPER.readValue(s, reference);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*/
package software.amazon.cloudformation.scheduler;

import com.fasterxml.jackson.core.JsonProcessingException;
import java.io.IOException;
import java.util.Objects;
import java.util.UUID;
import lombok.Data;
Expand Down Expand Up @@ -101,14 +101,15 @@ public <ResourceT, CallbackT> void rescheduleAfterMinutes(final String functionA
String jsonRequest;
try {
// expect return type to be non-null
jsonRequest = serializer.serialize(handlerRequest);
} catch (JsonProcessingException e) {
jsonRequest = serializer.compress(serializer.serialize(handlerRequest));
} catch (IOException e) {
throw new TerminalException("Unable to serialize the request for callback", e);
}
this.log(String.format("Scheduling re-invoke at %s (%s)%n", cronRule, rescheduleId));

PutRuleRequest putRuleRequest = PutRuleRequest.builder().name(ruleName).scheduleExpression(cronRule)
.state(RuleState.ENABLED).build();

this.client.putRule(putRuleRequest);

Target target = Target.builder().arn(functionArn).id(targetId).input(jsonRequest).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import org.json.JSONObject;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
Expand Down Expand Up @@ -148,7 +148,7 @@ public void test_cleanupCloudWatchEventsWithErrorDeletingRule() {
}

@Test
public void test_rescheduleAfterMinutes_1MinuteFloor() {
public void test_rescheduleAfterMinutes_1MinuteFloor() throws IOException {
final CloudWatchEventsProvider provider = mock(CloudWatchEventsProvider.class);
final CloudWatchEventsClient client = getCloudWatchEvents();
when(provider.get()).thenReturn(client);
Expand All @@ -166,8 +166,9 @@ public void test_rescheduleAfterMinutes_1MinuteFloor() {
verify(requestContext, times(1)).setCloudWatchEventsRuleName(startsWith("reinvoke-handler-"));
verify(requestContext, times(1)).setCloudWatchEventsTargetId(startsWith("reinvoke-target-"));

final List<TargetMatcher> targetMatchers = Arrays
.asList(new TargetMatcher(FUNCTION_ARN, "reinvoke-target-", new JSONObject(request).toString()));
final List<TargetMatcher> targetMatchers = Collections.singletonList(
new TargetMatcher(FUNCTION_ARN, "reinvoke-target-", serializer.compress(serializer.serialize(request))));

verify(client, times(1))
.putTargets(argThat(new PutTargetsRequestMatcher("reinvoke-handler-", new TargetsListMatcher(targetMatchers))));
verify(client, times(1))
Expand Down