#PhantomJS or Puppeter in AppWrite Functions

22 messages · Page 1 of 1 (latest)

compact monolith
#

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

deft cape
#

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

compact monolith
#

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

faint ravine
compact monolith
#

Great. I'l wait and externalize the puppeter functions for the moment 🙂

faint ravine
compact monolith
#

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

faint ravine
compact monolith
#

Yes

faint ravine
# compact monolith

I would probably write this to storage rather than returning the buffer in case it's too big and gets truncated

compact monolith
#

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