Created
October 22, 2018 18:42
-
-
Save SFEley/56936dcc8052cddc88933566ee9d7a93 to your computer and use it in GitHub Desktop.
LambdaHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.List; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.OutputStream; | |
import java.io.ByteArrayOutputStream; | |
import java.io.File; | |
import java.nio.file.Paths; | |
import com.amazonaws.services.lambda.runtime.RequestStreamHandler; | |
import com.amazonaws.services.lambda.runtime.Context; | |
import org.jruby.embed.ScriptingContainer; | |
import org.jruby.embed.LocalVariableBehavior; | |
import org.jruby.embed.LocalContextScope; | |
import org.jruby.embed.PathType; | |
import org.jruby.CompatVersion; | |
import org.jruby.RubyInstanceConfig.CompileMode; | |
public class LambdaHandler implements RequestStreamHandler { | |
public interface Handleable { | |
String handle(String input); | |
} | |
private static final ScriptingContainer rubyRuntime; | |
public final Handleable rubyHandler; | |
static { | |
rubyRuntime = new ScriptingContainer(LocalContextScope.SINGLETHREAD, LocalVariableBehavior.PERSISTENT); | |
rubyRuntime.setCompatVersion(CompatVersion.RUBY2_0); | |
rubyRuntime.setCompileMode(CompileMode.JIT); | |
// Add Ruby file location to front of load path | |
// List<String> loadPaths = rubyRuntime.getLoadPaths(); | |
// loadPaths.add(0, rubyLoadPath); | |
// rubyRuntime.setLoadPaths(loadPaths); | |
} | |
// No Ruby handler name given; we have to infer it from the environment or | |
// use the default "Handler" | |
public LambdaHandler() { | |
this(getHandlerNameFromEnv()); | |
} | |
public LambdaHandler(String handlerName) { | |
String handlerRequire = getRubyRequireName("handlers", handlerName); | |
System.out.println("handlerName: " + handlerName); | |
System.out.println("handlerRequire: " + handlerRequire); | |
rubyRuntime.runScriptlet("require 'java'"); | |
rubyRuntime.runScriptlet(String.format("require '%s'", handlerRequire)); // rubyRuntime.runScriptlet("STDOUT.puts $LOAD_PATH"); | |
// rubyRuntime.runScriptlet(PathType.CLASSPATH, handlerFilename); | |
Object handlerObject = rubyRuntime.runScriptlet(handlerName + ".new"); | |
rubyHandler = rubyRuntime.getInstance(handlerObject, Handleable.class); | |
} | |
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) | |
throws IOException { | |
String input = readFromInputStream(inputStream); | |
String output = rubyHandler.handle(input); | |
outputStream.write(output.getBytes("UTF-8")); | |
outputStream.close(); | |
} | |
// Determines which Ruby handler to run, using either the HANDLER_NAME | |
// environment variable or the named Lambda function, testing for the | |
// existence of a Ruby script in src/main/ruby/handlers that matches. | |
private static String getHandlerNameFromEnv() { | |
String candidate; | |
candidate = System.getenv("HANDLER_NAME"); | |
if (candidate != null) return candidate; | |
candidate = System.getenv("AWS_LAMBDA_FUNCTION_NAME"); | |
if (candidate != null) return candidate; | |
candidate = "Handler"; | |
return candidate; | |
} | |
private String getRubyRequireName(String subPath, String className) { | |
String snakecase = className.replaceAll("(.)(\\p{Upper})", "$1_$2").toLowerCase(); | |
return Paths.get(subPath, snakecase).toString(); | |
} | |
// https://stackoverflow.com/a/35446009 | |
private String readFromInputStream(InputStream inputStream) throws IOException { | |
ByteArrayOutputStream result = new ByteArrayOutputStream(); | |
byte[] buffer = new byte[1024]; | |
int length; | |
while ((length = inputStream.read(buffer)) != -1) { | |
result.write(buffer, 0, length); | |
} | |
return result.toString("UTF-8"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment