chrome-aws-lambda
chrome-aws-lambda copied to clipboard
[BUG] chromium.font() doesn't work in lambda containers
Environment
chrome-aws-lambdaVersion: 10.1.0puppeteer/puppeteer-coreVersion: 10.1.0- OS: Linux (
public.ecr.aws/lambda/nodejs:14docker container) - Node.js Version: v14.17.4
- Lambda / GCF Runtime: Lambda container
Expected Behavior
After calling chromium.font(...) in Lambda container, Chrome should use that font.
Current Behavior
Chrome doesn't use the font.
Steps to Reproduce
-
Start the docker container with the current directory bind-mounted to /tmp/out to get the PDF out of the container:
docker run -it --rm --init --mount "type=bind,src=$(pwd),dst=/tmp/out" --entrypoint bash public.ecr.aws/lambda/nodejs:14 -
Run these commands inside the container:
npm init -y
npm install [email protected] [email protected]
curl -o ScheherazadeNew.zip 'https://fonts.google.com/download?family=Scheherazade%20New'
yum install -y unzip
unzip ScheherazadeNew.zip
- Paste the below code to index.js (using
cat >index.jsfor example):
const chromium = require('chrome-aws-lambda');
exports.handler = async (event, context, callback) => {
let browser = null;
try {
await chromium.font('ScheherazadeNew-Bold.ttf');
await chromium.font('ScheherazadeNew-Regular.ttf');
browser = await chromium.puppeteer.launch({
args: chromium.args,
defaultViewport: chromium.defaultViewport,
executablePath: await chromium.executablePath,
headless: chromium.headless,
ignoreHTTPSErrors: true,
});
let page = await browser.newPage();
await await page.setContent('<h1 style="font: \'Scheherazade New\'">تجربة</h1>');
await page.pdf({ path: '/tmp/out/test.pdf' });
} catch (error) {
return callback(error);
} finally {
if (browser !== null) {
await browser.close();
}
}
return callback(null, {});
};
- Run the AWS Lambda Runtime Interface Emulator in the background, and invoke the lambda function:
/lambda-entrypoint.sh index.handler &
# Wait a few seconds for the server to start
curl 'http://localhost:8080/2015-03-31/functions/function/invocations' --data-binary '{}'
- Open
test.pdfwhich will be written to the current directory outside the container. It will show square boxes instead of Arabic characters rendered inScheherazade Newfont.
Possible Solution
I believe it's caused by this line:
https://github.com/alixaxel/chrome-aws-lambda/blob/f9d5a9f/source/index.ts#L46
It symlinks the fonts to $HOME/.fonts, but $HOME/.fonts is not in the /tmp/aws/fonts.conf file:
bash-4.2# cat /tmp/aws/fonts.conf | grep dir
<dir>/tmp/aws/.fonts</dir>
<dir>/tmp/.fonts</dir>
<dir>/opt/.fonts</dir>
It only works in plain (non-container) Lambda because $HOME is not set, so it symlinks to /tmp/.fonts instead:
https://github.com/alixaxel/chrome-aws-lambda/blob/f9d5a9f/source/index.ts#L32-L34
Suggested fixes:
1- Either add <dir>~/.fonts</dir> to /tmp/aws/fonts.conf.
2- Or always symlink the fonts to /tmp/.fonts regardless of $HOME.
I prefer the first option, but I couldn't contribute a PR because I couldn't find the source for bin/aws.tar.br or how it's generated.
It seems like /tmp/aws/fonts.conf is no longer available in AWS lambda environment. So, the following two lines are causing the problem
https://github.com/alixaxel/chrome-aws-lambda/blob/f9d5a9ff0282ef8e172a29d6d077efc468ca3c76/source/index.ts#L12
https://github.com/alixaxel/chrome-aws-lambda/blob/f9d5a9ff0282ef8e172a29d6d077efc468ca3c76/source/index.ts#L46
as lambda tries to search fonts in /tmp/aws whereas fonts are loaded in /tmp/.fonts.
Setting process.env.FONTCONFIG_PATH=/tmp/.fonts and loading fonts using await chromium.font(path_to_custom_font.ttf) worked for me.