API Gateway(Rest API) の Lambda Authorizer では、Lambda のレスポンスに 指定の JSON を返す 必要があります。
Lambda Authorizer って何?って方は こちら を。
Node.js だと、こんな感じで、そのまま JSON を返せます。便利ですね。
exports.handler = async (event) => {
console.log(JSON.stringify(event, null, 4));
return {
"principalId": "1234",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": event.methodArn
}
]
}
};
};
Java の場合は、JSON では返せないですし、JSON を文字列として返してもうまくいきません。
方法としては 2 つあって、Map を使う方法と POJO クラスを使う方法です。
Map を使う方法
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class MapLambdaAuthorizer implements RequestHandler<Map<String, Object>, Map<String, Object>> {
@Override
public Map<String, Object> handleRequest(Map<String, Object> event, Context lambdaContext) {
Map<String, Object> response = new HashMap<String, Object>();
response.put("principalId", "1234");
Map<String, Object> policyDocument = new HashMap<String, Object>();
policyDocument.put("Version", "2012-10-17");
Map<String, String> statement = new HashMap<>();
statement.put("Action", "execute-api:Invoke");
statement.put("Effect", "Allow");
statement.put("Resource", (String) event.get("methodArn"));
policyDocument.put("Statement", Arrays.asList(statement));
response.put("policyDocument", policyDocument);
Map<String, String> context = new HashMap<String, String>();
context.put("now", new Date().toString());
response.put("context", context);
return response;
}
}
POJO を使う方法
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class PojoLambdaAuthorizer implements RequestHandler<Map<String, Object>, AuthorizerResponse> {
@Override
public AuthorizerResponse handleRequest(Map<String, Object> event, Context lambdaContext) {
AuthorizerResponse response = new AuthorizerResponse();
response.setPrincipalId("1234");
Map<String, Object> policyDocument = new HashMap<>();
policyDocument.put("Version", "2012-10-17");
Map<String, String> statement = new HashMap<>();
statement.put("Action", "execute-api:Invoke");
statement.put("Effect", "Allow");
statement.put("Resource", (String) event.get("methodArn"));
policyDocument.put("Statement", Arrays.asList(statement));
response.setPolicyDocument(policyDocument);
Map<String, String> context = new HashMap<>();
context.put("now", new Date().toString());
response.setContext(context);
return response;
}
}
import java.util.Map;
public class AuthorizerResponse {
private String principalId;
public void setPrincipalId(String principalId) {
this.principalId = principalId;
}
public String getPrincipalId() {
return this.principalId;
}
private Map<String, Object> policyDocument;
public void setPolicyDocument(Map<String, Object> policyDocument) {
this.policyDocument = policyDocument;
}
public Map<String, Object> getPolicyDocument() {
return this.policyDocument;
}
private Map<String, String> context;
public Map<String, String> getContext() {
return context;
}
public void setContext(Map<String, String> context) {
this.context = context;
}
}
POJO にするなら、
policyDocument.put("Version", "2012-10-17");
statement.put("Action", "execute-api:Invoke");
とかも POJO にしないと気持ち悪いところですが、POJO にした場合に API Gateway に返される JSON のキー名が小文字始まり(version、action)になってしまい、うまく解釈してくれませんでした。
まとめ
JSON がそんなに大きくないので、Map 方式の方が読みやすくていいと思います。
Source Code