Hi all,
Is there a way to be able to run puppeter or phantomjs in appwrite functions?
When testing my function locally, both with puppeter and with the html-pdf extension that phantomjs uses, it works fine, but when I run it inside a function, it throws me an error.
An example of errors:
Phantomjs
Error: spawn /usr/code-start/node_modules/phantomjs-prebuilt/lib/phantom/bin/phantomjs ENOENT
at Process.ChildProcess._handle.onexit (node:internal/child_process:282:19)
at onErrorNT (node:internal/child_process:480:16)
at processTicksAndRejections (node:internal/process/task_queues:83:21)
Puppeter
Error: Could not find Chromium (rev. 1108766). This can occur if either
1. you did not perform an installation before running the script (e.g. `npm install`) or
2. your cache path is incorrectly configured (which is: /root/.cache/puppeteer).
For (2), check out our guide on configuring puppeteer at https://pptr.dev/guides/configuration.
at ChromeLauncher.resolveExecutablePath (/usr/code-start/node_modules/puppeteer-core/lib/cjs/puppeteer/node/ProductLauncher.js:127:27)
at ChromeLauncher.executablePath (/usr/code-start/node_modules/puppeteer-core/lib/cjs/puppeteer/node/ChromeLauncher.js:207:25)
at ChromeLauncher.launch (/usr/code-start/node_modules/puppeteer-core/lib/cjs/puppeteer/node/ChromeLauncher.js:93:37)
at async /usr/code-start/dist/models/invoice.js:174:33
Thanks in advance
did you deploy the function as a fresh new function, or just an updated build to an existing function?
I suggest you delete the function, and deploy a fresh build from the appwrite cli
it seems like it's a simple dependency issue, and a fresh deploy should fix it
It is an existing function but I think the problem is that puppeter and phantom are not supported in the docker image that appwrite uses
Yes, correct. There are OS level dependencies required which isn't supported in Appwrite functions. Here's the related issue: https://github.com/appwrite/appwrite/issues/1037. This might be achievable in the next version of our functions
Great. I'l wait and externalize the puppeter functions for the moment 🙂
You might be able to hack together a solution if you include the os level dependencies in the uploaded code and reference them somehow. 🤷♂️
I used docker with dokku instance and create a Dockerfile like this:
FROM node:lts-alpine
WORKDIR /app
RUN apk update && apk add --no-cache nmap && \
echo @edge http://nl.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories && \
echo @edge http://nl.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories && \
apk update && \
apk add --no-cache \
chromium \
harfbuzz \
"freetype>2.8" \
ttf-freefont \
nss
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
COPY package*.json ./
RUN npm install
COPY . .
CMD ["npm", "start"]
With this Procfile web: node index.js
And this is my script:
const express = require('express')
const bodyParser = require('body-parser')
const puppeter = require('puppeteer')
const app = express()
app.use(bodyParser.urlencoded({ extended: true }))
app.post('/', async (req, res) => {
try {
const html = req.body.html
// Create a browser instance
const browser = await puppeter.launch({
headless: true,
executablePath: '/usr/bin/chromium-browser',
args: [
'--disable-gpu',
'--disable-setuid-sandbox',
'--no-sandbox',
'--no-zygote',
],
})
// Create a new page
const page = await browser.newPage()
await page.setContent(html, {
waitUntil: 'networkidle0',
})
const pdfBuffer = await page.pdf({
format: 'A4',
// path: `${__dirname}/../invoice.pdf`,
printBackground: true,
})
res.status(200).json({ file: pdfBuffer })
await browser.close()
} catch (error) {
console.error(error)
res.status(500).json({ error: error.message })
}
})
app.listen(5000, function () {})
With all this I have managed to build a simple web service that through a provided html generates a pdf and sends the buffer in response to my appwrite function
I hope someone can be of help
Now, my appwrite function return a file buffer
And this is hosted separate from Appwrite? And the appwrite function calls this service?
Yes
I would probably write this to storage rather than returning the buffer in case it's too big and gets truncated
Yeah but in my case my backend who calls appwrite function manage the storage
I plan to use appwrite functions as microservices and be able to run universal functions from different projects
In this case, the function renders a pdf invoice based on some parameters provided
Recommended threads
- HTTP POST to function returning "No Appw...
Hi everyone, I’m running into an issue with my self-hosted Appwrite instance. I’ve set up my environment variables (APPWRITE_FUNCTION_PROJECT_ID, APPWRITE_FUNC...
- Can't add dart 3.5 runtime
Modified the `.env` to enable dart 3.5 runtime on my self-hosted instance but still can't find the runtime when creating a new function. I manually pulled the i...
- How to verify an user using AppWrite Fun...
I have seen similar questions but none whose solutions serve me. I have a function to verify a user with their secret and their id: https://blahblah.appwrite.gl...