Skip to content

Commit

Permalink
add support for openwhisk web actions; #20
Browse files Browse the repository at this point in the history
  • Loading branch information
bbilger committed Jun 21, 2017
1 parent 4fe9f76 commit e146708
Show file tree
Hide file tree
Showing 47 changed files with 2,930 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,12 @@
*/
package com.jrestless.aws.gateway.io;

import java.io.IOException;
import java.util.Base64;

import javax.annotation.Priority;
import javax.ws.rs.Priorities;
import javax.ws.rs.ext.ReaderInterceptor;
import javax.ws.rs.ext.ReaderInterceptorContext;

import com.jrestless.core.interceptor.ConditionalBase64ReadInterceptor;

/**
* Read interceptor that decodes the response from base64 if the property
* {@link GatewayBinaryReadInterceptor#PROPERTY_BASE_64_ENCODED_REQUEST
Expand Down Expand Up @@ -50,16 +48,13 @@
*/
// make sure this gets invoked before any encoding ReaderInterceptor
@Priority(Priorities.ENTITY_CODER - GatewayBinaryReadInterceptor.PRIORITY_OFFSET)
public class GatewayBinaryReadInterceptor implements ReaderInterceptor {
public class GatewayBinaryReadInterceptor extends ConditionalBase64ReadInterceptor {

public static final String PROPERTY_BASE_64_ENCODED_REQUEST = "base64EncodedAwsApiGatewayRequest";
static final int PRIORITY_OFFSET = 100;

@Override
public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException {
if (Boolean.TRUE.equals(context.getProperty(PROPERTY_BASE_64_ENCODED_REQUEST))) {
context.setInputStream(Base64.getDecoder().wrap(context.getInputStream()));
}
return context.proceed();
protected boolean isBase64(ReaderInterceptorContext context) {
return Boolean.TRUE.equals(context.getProperty(PROPERTY_BASE_64_ENCODED_REQUEST));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,12 @@
*/
package com.jrestless.aws.gateway.io;

import java.io.IOException;
import java.util.Base64;

import javax.annotation.Priority;
import javax.ws.rs.Priorities;
import javax.ws.rs.ext.WriterInterceptor;
import javax.ws.rs.ext.WriterInterceptorContext;

import com.jrestless.core.interceptor.ConditionalBase64WriteInterceptor;


/**
* Write interceptor that encodes the response in base64 if the first
Expand All @@ -45,16 +43,12 @@
*/
// make sure this gets invoked after any encoding WriteInterceptor
@Priority(Priorities.ENTITY_CODER - GatewayBinaryWriteInterceptor.PRIORITY_OFFSET)
public class GatewayBinaryWriteInterceptor implements WriterInterceptor {
public class GatewayBinaryWriteInterceptor extends ConditionalBase64WriteInterceptor {

static final int PRIORITY_OFFSET = 100;

@Override
public void aroundWriteTo(WriterInterceptorContext context) throws IOException {
Object headerValue = context.getHeaders().getFirst(GatewayBinaryResponseFilter.HEADER_BINARY_RESPONSE);
if (Boolean.TRUE.equals(headerValue)) {
context.setOutputStream(Base64.getEncoder().wrap(context.getOutputStream()));
}
context.proceed();
protected boolean isBase64(WriterInterceptorContext context) {
return Boolean.TRUE.equals(context.getHeaders().getFirst(GatewayBinaryResponseFilter.HEADER_BINARY_RESPONSE));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,10 @@ public void delegateRequest_ValidRequestAndNoReferencesGiven_ShouldNotFailOnRequ
requestScopedInitializer.initialize(serviceLocator);
}



@SuppressWarnings({ "unchecked", "rawtypes" })
@SuppressWarnings("unchecked")
private RequestScopedInitializer getSetRequestScopedInitializer(Context context, GatewayRequest request) {
GatewayRequestAndLambdaContext reqAndContext = new GatewayRequestAndLambdaContext(request, context);
ArgumentCaptor<Consumer> containerEnhancerCaptor = ArgumentCaptor.forClass(Consumer.class);
ArgumentCaptor<Consumer<ContainerRequest>> containerEnhancerCaptor = ArgumentCaptor.forClass(Consumer.class);
gatewayHandler.delegateRequest(reqAndContext);
verify(container).handleRequest(any(), any(), any(), containerEnhancerCaptor.capture());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
import com.jrestless.aws.security.CognitoUserPoolAuthorizerPrincipal;
import com.jrestless.aws.security.CustomAuthorizerPrincipal;
import com.jrestless.core.container.dpi.InstanceBinder;
import com.jrestless.test.IOUtils;

public class GatewayRequestObjectHandlerIntTest {

Expand Down Expand Up @@ -247,7 +248,7 @@ public void testBinaryBase64EncodingWithContentEncoding() throws IOException {
assertTrue(response.isIsBase64Encoded());
byte[] bytes = Base64.getDecoder().decode(response.getBody());
InputStream unzipStream = new GZIPInputStream(new ByteArrayInputStream(bytes));
assertEquals("test", new String(toBytes(unzipStream)));
assertEquals("test", IOUtils.toString(unzipStream));
assertNotNull(response.getHeaders().get(HttpHeaders.CONTENT_ENCODING));
}

Expand All @@ -265,17 +266,6 @@ public void testNonBinaryNonBase64EncodingWithContentEncoding() throws IOExcepti
assertNull(response.getHeaders().get(HttpHeaders.CONTENT_ENCODING));
}

private byte[] toBytes(InputStream is) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[1024];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
return buffer.toByteArray();
}

private void testBase64Encoding(String resoruce) {
DefaultGatewayRequest request = new DefaultGatewayRequestBuilder()
.httpMethod("GET")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;

Expand All @@ -21,7 +19,10 @@
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;

public class GatewayBinaryResponseFilterIntTest {
import com.jrestless.test.DynamicJerseyTestRunner;
import com.jrestless.test.IOUtils;

public class GatewayBinaryResponseFilterIntTest extends DynamicJerseyTestRunner {

@Test
public void testBinaryZippedWhenZippingRequested() throws Exception {
Expand All @@ -35,7 +36,7 @@ public void testBinaryZippedWhenZippingRequested() throws Exception {
assertNotNull(response.getHeaderString(HttpHeaders.CONTENT_ENCODING));
assertNotNull(response.getHeaderString(GatewayBinaryResponseFilter.HEADER_BINARY_RESPONSE));
InputStream unzipStream = new GZIPInputStream(response.readEntity(InputStream.class));
assertEquals("binary", new String(toBytes(unzipStream)));
assertEquals("binary", IOUtils.toString(unzipStream));
});
}

Expand Down Expand Up @@ -94,7 +95,7 @@ public void testNonBinaryZippedWhenZippingRequestedAndNotBinaryCompressionOnly()
assertNotNull(response.getHeaderString(HttpHeaders.CONTENT_ENCODING));
assertNotNull(response.getHeaderString(GatewayBinaryResponseFilter.HEADER_BINARY_RESPONSE));
InputStream unzipStream = new GZIPInputStream(response.readEntity(InputStream.class));
assertEquals("non-binary", new String(toBytes(unzipStream)));
assertEquals("non-binary", new String(IOUtils.toBytes(unzipStream)));
});
}

Expand All @@ -112,23 +113,6 @@ public void testNonBinaryNotZippedWhenNoZippingRequestedAndNotBinaryCompressionO
});
}

private void runJerseyTest(JerseyTest jerseyTest, ThrowingConsumer<JerseyTest> test) throws Exception {
try {
try {
jerseyTest.setUp();
} catch (Exception e) {
throw new RuntimeException(e);
}
test.accept(jerseyTest);
} finally {
try {
jerseyTest.tearDown();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}


private JerseyTest createJerseyTest(Boolean binaryCompressionOnly) {
return new JerseyTest() {
Expand All @@ -148,17 +132,6 @@ protected Application configure() {
};
}

private byte[] toBytes(InputStream is) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[1024];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
return buffer.toByteArray();
}

@Path("/")
public static class TestResource {
@GET
Expand All @@ -172,9 +145,4 @@ public Response getNonBinary() {
return Response.ok("non-binary").build();
}
}

@FunctionalInterface
private static interface ThrowingConsumer<T> {
void accept(T in) throws Exception;
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
package com.jrestless.aws.service.client;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.Collections;

import org.junit.Before;
import org.junit.Test;

import com.jrestless.aws.service.client.AbstractFeignLambdaServiceClient;
import com.jrestless.aws.service.io.ServiceRequest;
import com.jrestless.aws.service.io.ServiceResponse;
import com.jrestless.test.IOUtils;

public class AbstractFeignLambdaServiceClientTest {

Expand Down Expand Up @@ -105,7 +102,7 @@ public void execute_ResponseBodyGiven_ShouldRespondWithBody() throws IOException
FeignLambdaClientImpl client = new FeignLambdaClientImpl(serviceResponse);
when(serviceResponse.getBody()).thenReturn("some body");
feign.Response response = client.execute(feignRequest, null);
assertArrayEquals("some body".getBytes(), toBytes(response.body().asInputStream()));
assertEquals("some body", IOUtils.toString(response.body().asInputStream()));
}

@Test
Expand Down Expand Up @@ -170,17 +167,6 @@ public void execute_OptionsGiven_ShouldPassOptionsToInternalExec() throws IOExce
assertEquals(null, client.getFeignRequestOptions());
}

private byte[] toBytes(InputStream is) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[1024];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
return buffer.toByteArray();
}

private static class FeignLambdaClientImpl extends AbstractFeignLambdaServiceClient {
private ServiceResponse response;
private ServiceRequest serviceRequest;
Expand Down
5 changes: 4 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ subprojects {
junit: 'junit:junit:4.12',
mockito_core: 'org.mockito:mockito-core:2.2.0',
guava_testlib: 'com.google.guava:guava-testlib:18.0',
jsonassert: 'org.skyscreamer:jsonassert:1.3.0'
jsonassert: 'org.skyscreamer:jsonassert:1.3.0',
gson: 'com.google.code.gson:gson:2.8.1'
]

checkstyle {
Expand Down Expand Up @@ -178,6 +179,8 @@ dependencies {
compile project(":aws:service:jrestless-aws-service-handler")
compile project(":aws:service:jrestless-aws-service-feign-client")
compile project(":aws:sns:jrestless-aws-sns-handler")
compile project(":openwhisk:core:jrestless-openwhisk-core")
compile project(":openwhisk:webaction:jrestless-openwhisk-webaction-handler")
compile project(":test:jrestless-test")
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2017 Bjoern Bilger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jrestless.core.interceptor;

import java.io.IOException;
import java.util.Base64;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.ext.ReaderInterceptor;
import javax.ws.rs.ext.ReaderInterceptorContext;

/**
* Wraps the {@link ReaderInterceptorContext context's} input stream with a
* base64 decoder (RFC4648; not URL-safe) if {@link #isBase64(ReaderInterceptorContext)}
* returns true.
*
* @author Bjoern Bilger
*
*/
public abstract class ConditionalBase64ReadInterceptor implements ReaderInterceptor {

@Override
public final Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
if (isBase64(context)) {
context.setInputStream(Base64.getDecoder().wrap(context.getInputStream()));
}
return context.proceed();
}

/**
* Returns true if the {@link ReaderInterceptorContext context's}
* input stream should be wrapped by a base64 decoder.
*
* @param context
* the response context
* @return {@code true} in case the context's input stream must be wrapped
* by a base64 encoder; {@code false} otherwise
*/
protected abstract boolean isBase64(ReaderInterceptorContext context);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2017 Bjoern Bilger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jrestless.core.interceptor;

import java.io.IOException;
import java.util.Base64;

import javax.ws.rs.ext.WriterInterceptor;
import javax.ws.rs.ext.WriterInterceptorContext;

/**
* Wraps the {@link WriterInterceptorContext context's} output stream with a
* base64 encoder (RFC4648; not URL-safe) if {@link #isBase64(WriterInterceptorContext)}
* returns true.
*
* @author Bjoern Bilger
*
*/
public abstract class ConditionalBase64WriteInterceptor implements WriterInterceptor {

@Override
public final void aroundWriteTo(WriterInterceptorContext context) throws IOException {
if (isBase64(context)) {
context.setOutputStream(Base64.getEncoder().wrap(context.getOutputStream()));
}
context.proceed();
}

/**
* Returns true if the {@link WriterInterceptorContext context's}
* output stream should be wrapped by a base64 encoder.
*
* @param context
* the response context
* @return {@code true} in case the context's output stream must be wrapped
* by a base64 encoder; {@code false} otherwise
*/
protected abstract boolean isBase64(WriterInterceptorContext context);
}
Loading

0 comments on commit e146708

Please sign in to comment.