For others in a similar situation - you would like to return a zip file / image anything other than JSON really here is what you need to do.
Firstly lambda wont let you stream directly from fme because it tries to chunk the data and then the API gateway can't put it back properly such then when it encodes to binary it fails (most of the time). So the work around I found was basically to save whatever file it is to S3, then pick it up in lambda and sent it to API Gateway.
The lambda code needs to change to something like:
console.log("Lambda Function working");
var AWS = require("aws-sdk");
var https = require('https');
var querystring = require('querystring');
var host = 'xxx';
var path = '/fmedatastreaming/APIrepository/';
var S3Key = 'xx';
var S3SecretKey = 'xx';
var isJSON = false;
var isZIP = false;
var makeRequestToFME = function (httpMethod, event, callback) {
var qs = querystring.stringify(event.params.querystring);
var token = querystring.stringify(event["stage-variables"]);
var statusCode;
var parsed;
var fmeResponse = '';
var parsedResponse;
var options = {
hostname: host,
port: 443,
path: path + event.workspace + '?' + qs + '&' + token ,
timeout: 20000,
method: httpMethod
};
console.log("Options", options);
var req = https.request(options, function (response) {
response.on('error', function (d) {
console.log("FME Error", d);
if (callback) {
callback({
statusCode: response.statusCode
});
}
});
response.on('data', function (returnData) {
console.log("Headers", response.headers);
if (response.headers['content-type'] === 'application/json') {
isJSON = true;
fmeResponse += returnData;
}
if (response.headers['content-type'] === 'application/zip') {
isZIP = true;
fmeResponse += returnData;
}
});
response.on('end', function (d) {
console.log('FME Response end', fmeResponse);
parsed = JSON.parse(fmeResponse);
if ( parsed != null && (parsed.status !== undefined && parsed.filename !== undefined)){
isZIP = true;
}
if (isZIP){
if (fmeResponse==='') {
if (callback) {
callback({
body: { "status": response.statusCode, "message": response.statusMessage },
statusCode: response.statusCode,
statusMessage: response.statusMessage
});
}
}
else {
console.log('FME Response end', fmeResponse);
parsed = JSON.parse(fmeResponse);
if (callback) {
callback({
body: parsed.filename,
statusCode: parsed.status,
statusMessage: 'Reply from FME '+parsed.status
});
}
}
}
else if (isJSON){
parsed = JSON.parse(fmeResponse);
if (parsed.status) {
//Use status code defined in JSON
statusCode = parsed.status;
} else {
//Default to HTTP status code returned by request
statusCode = response.statusCode;
}
if (callback) {
callback({
body: parsed,
statusCode: statusCode,
statusMessage: response.statusMessage
});
}
}
});
console.log("End makeFMERequest", response);
return response;
});
console.log("Request gone");
req.end();
};
exports.handler = (event, context, callback) => {
try {
var httpMethod = event.context["http-method"];
makeRequestToFME(httpMethod, event, function (response) {
console.log('makeFMERequest done', response);
if (response.body != null && response.statusCode === 'ok') {
var s3 = new AWS.S3({ region: "us-east-1", accessKeyId: S3Key, secretAccessKey: S3SecretKey });
s3.getObject({
Bucket: 'xxxxx',
Key: 'DOWNLOAD/' + response.body
}, function (err, data) {
if (err) {
console.log("S3", err);
callback(err);
}
else {
console.log("ZIP", data.Body);
callback(null, data.Body.toString('base64'));
}
});
}
else {
console.log('context failed', response);
return context.fail(JSON.stringify(response.body));
}
});
}
catch (e) {
console.log('try catch', e);
context.fail(e);
}
};
And in the API Gateway, under settings and Binary Media Types add the MIME type e.g. application/zip
Then in the method response add content-type

and in the integration response pull it into binary and update the header mappings as below

Then when making the curl request - in say Postman be sure to request the data in the header as content-type / application-zip.
I hope this helps someone, AWS Gateway and lambda integration is quite a tricky piece, FME is the easiest bit.
Cheers
Oliver