Java版AWS Lambda Cognito自定义消息触发器InvalidLambdaResponseException排查
解决Cognito自定义消息Lambda触发器的InvalidLambdaResponseException问题
我帮你排查了下这个问题,核心原因其实藏在你提供的CloudWatch日志里——输出的JSON字符串中包含了多余的换行符,导致Cognito无法正确解析Lambda的响应,才抛出了InvalidLambdaResponseException和“Unrecognizable lambda output”的错误。
先看你的日志:不管是初始输出还是调整后的后置日志,像userPoolId、userName、clientId这些字段的值后面都带有换行(比如userPoolId": "***** "),这些换行是从原始输入里带进来的,而你的代码直接把这些带换行的字段原样序列化输出了。Cognito对Lambda返回的JSON格式要求非常严格,这种隐性的换行符会破坏JSON的结构解析。
解决方案:清理字段中的换行和空白字符
你需要在处理输入JSON的时候,把所有字符串类型字段首尾的换行、空白字符都去掉,再生成响应输出。修改后的handler代码如下:
import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.LambdaLogger; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.StandardCharsets; public class CustomMessageHandler implements RequestStreamHandler { private final ObjectMapper mapper = new ObjectMapper(); @Override public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { LambdaLogger logger = context.getLogger(); JsonNode json = mapper.readTree(input); ObjectNode mutableJson = (ObjectNode) json; // 清理所有带换行的字段,去除首尾空白和换行符 trimStringField(mutableJson, "userPoolId"); trimStringField(mutableJson, "userName"); trimStringField(mutableJson.with("callerContext"), "clientId"); ObjectNode userAttributes = mutableJson.with("request").with("userAttributes"); trimStringField(userAttributes, "sub"); trimStringField(userAttributes, "given_name"); trimStringField(userAttributes, "custom:team_id"); // 设置自定义消息内容 mutableJson.with("response") .put("smsMessage", "TEST {####}") .put("emailMessage", "TEST {####}") .put("emailSubject", "TEST subject"); // 序列化输出,确保格式严格 try (Writer w = new OutputStreamWriter(output, StandardCharsets.UTF_8)) { mapper.writeValue(w, mutableJson); } logger.log("最终输出JSON: " + mapper.writeValueAsString(mutableJson)); } // 工具方法:清理ObjectNode中的字符串字段 private void trimStringField(ObjectNode node, String fieldName) { if (node.has(fieldName) && node.get(fieldName).isTextual()) { node.put(fieldName, node.get(fieldName).asText().trim()); } } }
为什么这样能解决问题?
AWS Cognito的Lambda触发器对响应JSON的格式要求非常严格,任何不符合标准JSON规范的内容(比如字符串中未转义的换行、多余空白)都会导致解析失败。你的原始代码直接将输入中带换行的字段序列化输出,这些换行符在JSON字符串中是不允许的(除非用\n转义,但这里是实际的换行,不是转义字符),所以Cognito无法识别这个响应。
通过trim()方法去除字段值首尾的换行和空白后,输出的JSON就是严格符合规范的格式,Cognito就能正常解析了。
内容的提问来源于stack exchange,提问作者HDubz
相关产品推荐
相关产品推荐

