Skip to content

Instantly share code, notes, and snippets.

@SFEley
Created October 22, 2018 18:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SFEley/56936dcc8052cddc88933566ee9d7a93 to your computer and use it in GitHub Desktop.
Save SFEley/56936dcc8052cddc88933566ee9d7a93 to your computer and use it in GitHub Desktop.
LambdaHandler.java
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