Example Live View avatar
Example Live View

Pricing

Pay per usage

Go to Store
Example Live View

Example Live View

Developed by

Apify

Maintained by Apify

This example demonstrates how to use web server in actor as communication channel with outer world. Read more at Apify docs https://docs.apify.com/actors/running#container-web-server

5.0 (4)

Pricing

Pay per usage

4

Monthly users

2

Last modified

10 months ago

Dockerfile

1# This is a template for a Dockerfile used to run acts in Actor system.
2# The base image name below is set during the act build, based on user settings.
3# IMPORTANT: The base image must set a correct working directory, such as /usr/src/app or /home/user
4FROM apify/actor-node-chrome
5
6# Second, copy just package.json and package-lock.json since it should be
7# the only file that affects "npm install" in the next step, to speed up the build
8COPY package*.json ./
9
10# Install NPM packages, skip optional and development dependencies to
11# keep the image small. Avoid logging too much and print the dependency
12# tree for debugging
13RUN npm --quiet set progress=false \
14 && npm install --only=prod --no-optional \
15 && echo "Installed NPM packages:" \
16 && (npm list --all || true) \
17 && echo "Node.js version:" \
18 && node --version \
19 && echo "NPM version:" \
20 && npm --version
21
22# Copy source code to container
23# Do this in the last step, to have fast build if only the source code changed
24COPY --chown=myuser:myuser . ./
25
26# NOTE: The CMD is already defined by the base image.
27# Uncomment this for local node inspector debugging:
28# CMD [ "node", "--inspect=0.0.0.0:9229", "main.js" ]

package.json

1{
2    "name": "apify-project",
3    "version": "0.0.1",
4    "description": "",
5    "author": "It's not you it's me",
6    "license": "ISC",
7    "dependencies": {
8        "apify": "0.22.4",
9        "express": "latest",
10        "body-parser": "latest"
11    },
12    "scripts": {
13        "start": "node main.js"
14    }
15}

main.js

1const Apify = require('apify');
2const express = require('express')
3const bodyParser = require('body-parser');
4
5// Create ExpressJS app and configure body parsers that will allow us to receive form submissions.
6const app = express()
7app.use(bodyParser.json());
8app.use(bodyParser.urlencoded({ extended: true }));
9
10//  Now we need to read following environment variables: 
11// - APIFY_CONTAINER_PORT  contains a port number where we must start server 
12// - APIFY_CONTAINER_URL  contains a URL under which we can access the container
13// - APIFY_DEFAULT_KEY_VALUE_STORE_ID is simply ID of default key-value store of this 
14//   actor where we can store screenshots
15const {
16    APIFY_CONTAINER_PORT,
17    APIFY_CONTAINER_URL,
18    APIFY_DEFAULT_KEY_VALUE_STORE_ID,
19} = process.env;
20
21// Create an array of the processed URLs where n-th URL has its screenshot stored under the 
22// key [n].jpg in key-value store:
23const processedUrls = [];
24
25// Root path displays a HTML form to submit new URL and thumbnails of processed URLs:
26app.get('/', (req, res) => {
27    let listItems = '';
28
29    // For each of the processed
30    processedUrls.forEach((url, index) => {
31        const imageUrl = `https://api.apify.com/v2/key-value-stores/${APIFY_DEFAULT_KEY_VALUE_STORE_ID}/records/${index}.jpg`;
32
33        listItems += `<li>
34    <a href="${imageUrl}" target="_blank">
35        <img src="${imageUrl}" width="300px" />
36        <br />
37        ${url}
38    </a>
39</li>`;
40    });
41
42    const pageHtml = `
43<html>
44    <head><title>Example</title></head>
45    <body>
46        <form method="POST" action="${APIFY_CONTAINER_URL}/add-url">
47            URL: <input type="text" name="url" placeholder="http://example.com" />
48            <input type="submit" value="Add" />
49            <hr />
50            <ul>${listItems}</ul>
51        </form>
52    </body>
53</html>`;
54
55    res.send(pageHtml);
56});
57
58// POST route allowing us to submit new URLs. After URL is processed
59// it redirects user back to root path.
60app.post('/add-url', async (req, res) => {
61    const { url } = req.body;
62    console.log(`Got new URL: ${url}`);
63
64    // Start chrome browser and open new page ...
65    const browser = await Apify.launchPuppeteer();
66    const page = await browser.newPage();
67
68    // ... go to our URL and grab a screenshot ...
69    await page.goto(url);
70    const screenshot = await page.screenshot({ type: 'jpeg' });
71
72    // ... close browser ...
73    await page.close();
74    await browser.close(); 
75
76    // ... save sreenshot to key-value store and add URL to processedUrls.
77    await Apify.setValue(`${processedUrls.length}.jpg`, screenshot, { contentType: 'image/jpeg' });
78    processedUrls.push(url);
79
80    res.redirect('/');
81});
82
83// Start the webserver.
84app.listen(APIFY_CONTAINER_PORT, () => {
85    console.log(`Application is listening at URL ${APIFY_CONTAINER_URL}.`);
86});

Pricing

Pricing model

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage.