Skip to content

Commit 7d4b8c1

Browse files
committed
Add node20 to store
Signed-off-by: Alex Ellis (OpenFaaS Ltd) <[email protected]>
1 parent 7297fce commit 7d4b8c1

File tree

9 files changed

+262
-2
lines changed

9 files changed

+262
-2
lines changed

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ This repository contains the Classic OpenFaaS templates, but many more are avail
1818
| node16 | NodeJS | 16 | Alpine Linux | of-watchdog | [NodeJS template](https://github.com/openfaas/templates/tree/master/template/node16)
1919
| node17 | NodeJS | 17 | Alpine Linux | of-watchdog | [NodeJS template](https://github.com/openfaas/templates/tree/master/template/node17)
2020
| node18 | NodeJS | 18 | Alpine Linux | of-watchdog | [NodeJS template](https://github.com/openfaas/templates/tree/master/template/node18)
21+
| node18 | NodeJS | 20 | Alpine Linux | of-watchdog | [NodeJS template](https://github.com/openfaas/templates/tree/master/template/node20)
2122
| bun-express | Bun | 1.0 | Alpine Linux | of-watchdog | [NodeJS template](https://github.com/openfaas/templates/tree/master/template/bun-express)
22-
| node | NodeJS | 12 | Alpine Linux | classic | [NodeJS template](https://github.com/openfaas/templates/tree/master/template/node)
23+
| node | NodeJS | 20 | Alpine Linux | classic | [NodeJS template](https://github.com/openfaas/templates/tree/master/template/node)
2324
| python3 | Python | 3 | Alpine Linux | classic | [Python 3 template](https://github.com/openfaas/templates/tree/master/template/python3)
2425
| python3-debian | Python | 3 | Debian Linux | classic | [Python 3 Debian template](https://github.com/openfaas/templates/tree/master/template/python3-debian)
2526
| python | Python | 2.7 | Alpine Linux | classic | [Python 2.7 template](https://github.com/openfaas/templates/tree/master/template/python)

template/node/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
FROM --platform=${TARGETPLATFORM:-linux/amd64} ghcr.io/openfaas/classic-watchdog:0.2.3 as watchdog
2-
FROM --platform=${TARGETPLATFORM:-linux/amd64} node:12-alpine as ship
2+
FROM --platform=${TARGETPLATFORM:-linux/amd64} node:20-alpine as ship
33

44
ARG TARGETPLATFORM
55
ARG BUILDPLATFORM

template/node20/.dockerignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*/node_modules

template/node20/Dockerfile

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
FROM --platform=${TARGETPLATFORM:-linux/amd64} ghcr.io/openfaas/of-watchdog:0.9.15 as watchdog
2+
FROM --platform=${TARGETPLATFORM:-linux/amd64} node:20-alpine as ship
3+
4+
ARG TARGETPLATFORM
5+
ARG BUILDPLATFORM
6+
7+
COPY --from=watchdog /fwatchdog /usr/bin/fwatchdog
8+
RUN chmod +x /usr/bin/fwatchdog
9+
10+
RUN apk --no-cache add curl ca-certificates \
11+
&& addgroup -S app && adduser -S -g app app
12+
13+
# Turn down the verbosity to default level.
14+
ENV NPM_CONFIG_LOGLEVEL warn
15+
16+
RUN chmod 777 /tmp
17+
18+
USER app
19+
20+
RUN mkdir -p /home/app/function
21+
22+
# Entrypoint
23+
WORKDIR /home/app
24+
COPY --chown=app:app package.json ./
25+
26+
# This ordering means the npm installation is cached for the outer function handler.
27+
RUN npm i
28+
29+
# Copy outer function handler
30+
COPY --chown=app:app index.js ./
31+
32+
# COPY function node packages and install, adding this as a separate
33+
# entry allows caching of npm install
34+
35+
WORKDIR /home/app/function
36+
COPY --chown=app:app function/*.json ./
37+
38+
RUN npm i
39+
40+
# COPY function files and folders
41+
COPY --chown=app:app function/ ./
42+
43+
# Run any tests that may be available
44+
RUN npm test
45+
46+
# Set correct permissions to use non root user
47+
WORKDIR /home/app/
48+
49+
ENV cgi_headers="true"
50+
ENV fprocess="node index.js"
51+
ENV mode="http"
52+
ENV upstream_url="http://127.0.0.1:3000"
53+
54+
ENV exec_timeout="10s"
55+
ENV write_timeout="15s"
56+
ENV read_timeout="15s"
57+
58+
ENV prefix_logs="false"
59+
60+
HEALTHCHECK --interval=3s CMD [ -e /tmp/.lock ] || exit 1
61+
62+
CMD ["fwatchdog"]

template/node20/function/handler.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use strict'
2+
3+
module.exports = async (event, context) => {
4+
const result = {
5+
'body': JSON.stringify(event.body),
6+
'content-type': event.headers["content-type"]
7+
}
8+
9+
return context
10+
.status(200)
11+
.succeed(result)
12+
}

template/node20/function/package.json

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "openfaas-function",
3+
"version": "1.0.0",
4+
"description": "OpenFaaS Function",
5+
"main": "handler.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 0"
8+
},
9+
"keywords": [],
10+
"author": "OpenFaaS Ltd",
11+
"license": "MIT"
12+
}

template/node20/index.js

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Copyright (c) Alex Ellis 2021. All rights reserved.
2+
// Copyright (c) OpenFaaS Author(s) 2021. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4+
5+
"use strict"
6+
7+
const express = require('express')
8+
const app = express()
9+
const handler = require('./function/handler');
10+
const bodyParser = require('body-parser')
11+
12+
const defaultMaxSize = '100kb' // body-parser default
13+
14+
app.disable('x-powered-by');
15+
16+
const rawLimit = process.env.MAX_RAW_SIZE || defaultMaxSize
17+
const jsonLimit = process.env.MAX_JSON_SIZE || defaultMaxSize
18+
19+
app.use(function addDefaultContentType(req, res, next) {
20+
// When no content-type is given, the body element is set to
21+
// nil, and has been a source of contention for new users.
22+
23+
if(!req.headers['content-type']) {
24+
req.headers['content-type'] = "text/plain"
25+
}
26+
next()
27+
})
28+
29+
if (process.env.RAW_BODY === 'true') {
30+
app.use(bodyParser.raw({ type: '*/*' , limit: rawLimit }))
31+
} else {
32+
app.use(bodyParser.text({ type : "text/*" }));
33+
app.use(bodyParser.json({ limit: jsonLimit}));
34+
app.use(bodyParser.urlencoded({ extended: true }));
35+
}
36+
37+
const isArray = (a) => {
38+
return (!!a) && (a.constructor === Array);
39+
};
40+
41+
const isObject = (a) => {
42+
return (!!a) && (a.constructor === Object);
43+
};
44+
45+
class FunctionEvent {
46+
constructor(req) {
47+
this.body = req.body;
48+
this.headers = req.headers;
49+
this.method = req.method;
50+
this.query = req.query;
51+
this.path = req.path;
52+
}
53+
}
54+
55+
class FunctionContext {
56+
constructor(cb) {
57+
this.statusCode = 200;
58+
this.cb = cb;
59+
this.headerValues = {};
60+
this.cbCalled = 0;
61+
}
62+
63+
status(statusCode) {
64+
if(!statusCode) {
65+
return this.statusCode;
66+
}
67+
68+
this.statusCode = statusCode;
69+
return this;
70+
}
71+
72+
headers(value) {
73+
if(!value) {
74+
return this.headerValues;
75+
}
76+
77+
this.headerValues = value;
78+
return this;
79+
}
80+
81+
succeed(value) {
82+
let err;
83+
this.cbCalled++;
84+
this.cb(err, value);
85+
}
86+
87+
fail(value) {
88+
let message;
89+
if(this.status() == "200") {
90+
this.status(500)
91+
}
92+
93+
this.cbCalled++;
94+
this.cb(value, message);
95+
}
96+
}
97+
98+
const middleware = async (req, res) => {
99+
const cb = (err, functionResult) => {
100+
if (err) {
101+
console.error(err);
102+
103+
return res.status(fnContext.status())
104+
.send(err.toString ? err.toString() : err);
105+
}
106+
107+
if(isArray(functionResult) || isObject(functionResult)) {
108+
res.set(fnContext.headers())
109+
.status(fnContext.status()).send(JSON.stringify(functionResult));
110+
} else {
111+
res.set(fnContext.headers())
112+
.status(fnContext.status())
113+
.send(functionResult);
114+
}
115+
};
116+
117+
const fnEvent = new FunctionEvent(req);
118+
const fnContext = new FunctionContext(cb);
119+
120+
Promise.resolve(handler(fnEvent, fnContext, cb))
121+
.then(res => {
122+
if(!fnContext.cbCalled) {
123+
fnContext.succeed(res);
124+
}
125+
})
126+
.catch(e => {
127+
cb(e);
128+
});
129+
};
130+
131+
app.post('/*', middleware);
132+
app.get('/*', middleware);
133+
app.patch('/*', middleware);
134+
app.put('/*', middleware);
135+
app.delete('/*', middleware);
136+
app.options('/*', middleware);
137+
138+
const port = process.env.http_port || 3000;
139+
140+
app.listen(port, () => {
141+
console.log(`node18 listening on port: ${port}`)
142+
});
143+
144+

template/node20/package.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "openfaas-node18",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no tests specified\" && exit 0"
8+
},
9+
"keywords": [],
10+
"author": "OpenFaaS Ltd",
11+
"license": "MIT",
12+
"dependencies": {
13+
"body-parser": "^1.18.2",
14+
"express": "^4.16.2"
15+
}
16+
}

template/node20/template.yml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
language: node20
2+
fprocess: node index.js
3+
welcome_message: |
4+
You have created a new function which uses Node.js 20 and the OpenFaaS
5+
of-watchdog which gives greater control over HTTP responses.
6+
7+
npm i --save can be used to add third-party packages like request or cheerio
8+
npm documentation: https://docs.npmjs.com/
9+
10+
Unit tests are run at build time via "npm run", edit package.json to specify
11+
how you want to execute them.
12+

0 commit comments

Comments
 (0)