I followed this guide on https://medium.com/@bruce_39084/setting-up-prince-on-aws-lambda-and-api-gateway-4d524dcb035b but I want to just pass in a url instead of a html file. so I made some changes to the index.js and installed axios. I also used the latest prince lambda package as opposed to the 13.5 included in the guide.
var execFile = require('child_process').exec;
const axios = require('axios');
function tinyMultipartParser(data) {
// assume first line is boundary
const lines = data.split("\r\n");
const output = [];
let in_body = false;
lines.forEach(line => {
output.push(line.trim());
})
return output.join("\n");
}
exports.handler = async (event, context, done) => {
if (!event || !event.body) { return done(new Error("No data.")); }
let body = event.body;
if (event.isBase64Encoded) {
body = Buffer.from(body, "base64").toString("ascii");
}
const response = await axios.get(body);
body = response.data;
const baseUrl = 'https://embed.notMyRealDomain.com'; // Replace with actual base URL
// Replace relative URLs with absolute URLs
body = body.replace(/href="([^"]+)"/g, (match, relativeURL) => {
const absoluteURL = new URL(relativeURL, baseUrl).toString();
return `href="${absoluteURL}"`;
});
body = body.replace(/src="([^"]+)"/g, (match, relativeURL) => {
const absoluteURL = new URL(relativeURL, baseUrl).toString();
return `src="${absoluteURL}"`;
});
let html = tinyMultipartParser(body);
let child = execFile("./prince", ["-", "-o", "-"], function (err, stdout, stderr) {
if (err) { throw new Error(err);}
if (err === null && (m = stderr.toString().match(/prince:\s+error:\s+([^\n]+)/))) {
throw new Error(m[1]);
}
done(null, {
"isBase64Encoded": true,
"statusCode": 200,
"headers": { "Content-Type": "application/pdf" },
"body": stdout.toString("base64")
});
});
child.stdin.write(html);
child.stdin.end();
};
I got it to the point where the "html" variable right before it does exec on prince on both the html-file version and in the pass-in-a-url version the html variable is IDENTICAL but it only works on the html file version and errors in my pass in a url version. Through some searching it says the write EPIPE error happens when the client disconnects before the function is completed. That makes sense because when i dump the response in the client i just get "null" instead of what it usually says when there is an error but in cloud watch I get the write EPIPE error. I tried some things I found online about making it wait so and so seconds for a promise but that didn't seem to work at all.