I am invoking a AWS Lambda function from the AWS API Gateway. The returned JSON needs to be zipped since it sometimes became too big (body size too large etc). However, I have some issues getting the response through the API Gateway. This is my Java code:
@Override
public JSONObject handleRequest(Object input, Context context) {
String json_string = "";
try {
Gson gson = new Gson();
json_string = gson.toJson(input, LinkedHashMap.class);
} catch (ClassCastException ex) {
json_string = (String) input;
}
GenerateJson generateJson = new GenerateJson ();
String body = "";
try {
JSONParser parser = new JSONParser();
Object jsonObj = parser.parse(json_string);
JSONObject matchesobj = (JSONObject) jsonObj;
if (matchesobj.containsKey("body")) {
body = (String) matchesobj.get("body");
} else {
JSONObject error = new JSONObject();
error.put("error", "No body with Base64 data in Request.");
System.out.println(error.toJSONString());
return error;
}
} catch (ParseException ex) {
ex.printStackTrace();
}
byte[] decodedBytes = Base64.getDecoder().decode(body);
String decodedString = new String(decodedBytes);
// System.out.println(decodedString);
JSONObject json = generateJson .getJson(decodedString, "", 2);
JSONObject returnObject = new JSONObject();
JSONObject headers = new JSONObject();
returnObject.put("statusCode", 205);
returnObject.put("isBase64Encoded", true);
// returnObject.put("Content-Encoding", "gzip");
returnObject.put("headers", headers);
returnObject.put("body", compressStringAndReturnBase64(json.toString()));
return (returnObject);
}
public static String compressStringAndReturnBase64(String srcTxt) {
ByteArrayOutputStream rstBao = new ByteArrayOutputStream();
GZIPOutputStream zos;
try {
zos = new GZIPOutputStream(rstBao);
zos.write(srcTxt.getBytes());
IOUtils.closeQuietly(zos);
byte[] bytes = rstBao.toByteArray();
String base64comp = Base64.getEncoder().encodeToString(bytes);
System.out.println("Json String is " + srcTxt.toString().getBytes().length + " compressed " + bytes.length + " compressed Base64 " + base64comp.getBytes().length);
return base64comp;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
I've checked the Base64 output and that seems to work fine (pasted it in https://www.base64decode.org/). In addition, when I check with Postman, I get a binary blob which can be unpacked with 7-zip if I save the response to something that ends with .gz.
Under settings, the API Gateway Binary Media Types has been set to / But I'd like to have the client "see" that it is GZIPped and decode it on the fly. However, when I add the line
returnObject.put("Content-Encoding", "gzip");
I get {"message": "Internal server error"} and in the AWS API logs: Execution failed due to configuration error: Malformed Lambda proxy response
The Lambda logs are fine, so it did execute successfully, just wasn't able to be returned.
I am thinking I need some more tweaking on the API Gateway side, any ideas?
public class XXXX implements ........
What interface are you implementing? - ᴛʜᴇᴘᴀᴛᴇʟContent-Encoding
belongs insideheaders
, not as a top level key inreturnObject
. It appears you are building a malformed response by putting this in the wrong place. - Michael - sqlbot