mirror of https://github.com/knative/func.git
src(templates)!: modify the nodejs event template to accept a cloudevent (#356)
* Simplify the nodejs events template Pretty-printing the contents of the event and its envelope for each request. This is handy when invoked as a Knative event sink as some sources, e.g. Kafka, ignore the response body. Co-authored-by: Lance Ball <lball@redhat.com> * Expect the event parameter to be the entire CloudEvent This will require a change to the faas-js-runtime, but at least the template won't need to change when that's released * Update nodejs guide to reflect 2nd arg's type is CloudEvent * Templates now using faas-js-runtime 0.7.1 Co-authored-by: Lance Ball <lball@redhat.com>
This commit is contained in:
parent
f62303b091
commit
caf0659900
|
@ -86,20 +86,27 @@ If you prefer another, that's no problem. Just remove the `tape` dependency from
|
|||
|
||||
## Function reference
|
||||
|
||||
Boson Node.js functions have very few restrictions. You can add any required dependencies
|
||||
in `package.json`, and you may include additional local JavaScript files. The only real
|
||||
requirements are that your project contain an `index.js` file which exports a single function.
|
||||
In this section, we will look in a little more detail at how Boson functions are invoked,
|
||||
and what APIs are available to you as a developer.
|
||||
Boson Node.js functions have very few restrictions. You can add any
|
||||
required dependencies in `package.json`, and you may include
|
||||
additional local JavaScript files. The only real requirements are that
|
||||
your project contain an `index.js` file which exports a single
|
||||
function. In this section, we will look in a little more detail at
|
||||
how Boson functions are invoked, and what APIs are available to you as
|
||||
a developer.
|
||||
|
||||
### Invocation parameters
|
||||
|
||||
When using the `func` CLI to create a function project, you may choose to generate a project
|
||||
that responds to a `CloudEvent` or simple HTTP. `CloudEvents` in Knative are transported over
|
||||
HTTP as a `POST` request, so in many ways, the two types of functions are very much the same.
|
||||
They each will listen and respond to incoming HTTP events.
|
||||
When using the `func` CLI to create a function project, you may choose
|
||||
to generate a project that responds to a `CloudEvent` or simple
|
||||
HTTP. `CloudEvents` in Knative are transported over HTTP as a `POST`
|
||||
request, so in many ways, the two types of functions are very much the
|
||||
same. They each will listen and respond to incoming HTTP events.
|
||||
|
||||
When an incoming request is received, your function will be invoked with a `Context` object as the first parameter. If the incoming request is a `CloudEvent`, any data associated with the `CloudEvent` is extracted from the event and provided as a second parameter. For example, a `CloudEvent` is received which contains a JSON string such as this in its data property,
|
||||
When an incoming request is received, your function will be invoked
|
||||
with a `Context` object as the first parameter. If the incoming
|
||||
request is a `CloudEvent`, it will be provided as the second
|
||||
parameter. For example, a `CloudEvent` is received which contains a
|
||||
JSON string such as this in its data property,
|
||||
|
||||
```json
|
||||
{
|
||||
|
@ -108,12 +115,12 @@ When an incoming request is received, your function will be invoked with a `Cont
|
|||
}
|
||||
```
|
||||
|
||||
When invoked, the second parameter to the function, after the `Context` object, will be
|
||||
a JavaScript object having `customerId` and `productId` properties. The function
|
||||
signature might look like this, with the `data` parameter having these properties.
|
||||
So to log that string from your function, you might do this:
|
||||
|
||||
```js
|
||||
function processPurchase(context, data)
|
||||
function handle(context, event) {
|
||||
console.log(JSON.stringify(event.data, null, 2));
|
||||
}
|
||||
```
|
||||
### Return Values
|
||||
Functions may return any valid JavaScript type, or nothing at all. When a
|
||||
|
@ -126,7 +133,10 @@ the returned values are extracted and sent with the response.
|
|||
|
||||
#### Example
|
||||
```js
|
||||
function processCustomer(context, customer) {
|
||||
function handle(context, event) {
|
||||
return processCustomer(event.data)
|
||||
}
|
||||
function processCustomer(customer) {
|
||||
// process customer and return a new CloudEvent
|
||||
return new CloudEvent({
|
||||
source: 'customer.processor',
|
||||
|
@ -142,7 +152,7 @@ extracted and sent with the response to the caller.
|
|||
|
||||
#### Example
|
||||
```js
|
||||
function processCustomer(context, customer) {
|
||||
function processCustomer(customer) {
|
||||
// process customer and return custom headers
|
||||
// the response will be '204 No content'
|
||||
return { headers: { customerid: customer.id } };
|
||||
|
@ -155,7 +165,7 @@ Developers may set the response code returned to the caller by adding a
|
|||
|
||||
#### Example
|
||||
```js
|
||||
function processCustomer(context, customer) {
|
||||
function processCustomer(customer) {
|
||||
// process customer
|
||||
if (customer.restricted) {
|
||||
return { statusCode: 451 }
|
||||
|
@ -167,7 +177,7 @@ This also works with `Error` objects thrown from the function.
|
|||
|
||||
#### Example
|
||||
```js
|
||||
function processCustomer(context, customer) {
|
||||
function processCustomer(customer) {
|
||||
// process customer
|
||||
if (customer.restricted) {
|
||||
const err = new Error(‘Unavailable for legal reasons’);
|
||||
|
@ -193,7 +203,7 @@ The log adheres to the Pino logging API (https://getpino.io/#/docs/api).
|
|||
|
||||
#### Example
|
||||
```js
|
||||
Function myFunction(context) {
|
||||
Function handle(context) {
|
||||
context.log.info(“Processing customer”);
|
||||
}
|
||||
```
|
||||
|
@ -216,7 +226,7 @@ attributes are also found on the context object itself.
|
|||
|
||||
#### Example
|
||||
```js
|
||||
Function myFunction(context) {
|
||||
Function handle(context) {
|
||||
// Log the 'name' query parameter
|
||||
context.log.info(context.query.name);
|
||||
// Query parameters also are attached to the context
|
||||
|
@ -242,7 +252,7 @@ be parsed so that the attributes are directly available.
|
|||
|
||||
#### Example
|
||||
```js
|
||||
Function myFunction(context) {
|
||||
Function handle(context) {
|
||||
// log the incoming request body's 'hello' parameter
|
||||
context.log.info(context.body.hello);
|
||||
}
|
||||
|
@ -264,7 +274,7 @@ Returns the HTTP request headers as an object.
|
|||
|
||||
#### Example
|
||||
```js
|
||||
Function myFunction(context) {
|
||||
Function handle(context) {
|
||||
context.log.info(context.headers[custom-header]);
|
||||
}
|
||||
```
|
||||
|
@ -309,10 +319,10 @@ A function which accepts a data value and returns a CloudEvent.
|
|||
#### Example
|
||||
```js
|
||||
// Expects to receive a CloudEvent with customer data
|
||||
function processCustomer(context, customer) {
|
||||
function handle(context, event) {
|
||||
// process the customer
|
||||
const processed = processCustomer(customer);
|
||||
return context.cloudEventResponse(customer);
|
||||
const processed = processCustomer(event.data);
|
||||
return context.cloudEventResponse(processed);
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
# Node.js Cloud Events Function
|
||||
|
||||
Welcome to your new Node.js function project! The boilerplate function code can
|
||||
be found in [`index.js`](./index.js). This function is meant to respond
|
||||
exclusively to [Cloud Events](https://cloudevents.io/), but you can remove the
|
||||
check for this in the function and it will respond just fine to plain vanilla
|
||||
incoming HTTP requests. Additionally, this example function is written
|
||||
asynchronously, returning a `Promise`. If your function does not perform any
|
||||
asynchronous execution, you can safely remove the `async` keyword from the
|
||||
function, and return raw values instead of a `Promise`.
|
||||
Welcome to your new Node.js function project! The boilerplate function
|
||||
code can be found in [`index.js`](./index.js). This function is meant
|
||||
to respond to [Cloud Events](https://cloudevents.io/).
|
||||
|
||||
## Local execution
|
||||
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
const { CloudEvent, HTTP } = require('cloudevents');
|
||||
|
||||
/**
|
||||
* An example function that responds to incoming CloudEvents over HTTP. For example,
|
||||
* from the Knative event Broker. Try invoking with a request such as this.
|
||||
* A function that responds to incoming CloudEvents over HTTP from,
|
||||
* for example, a Knative event Source, Channel or Broker.
|
||||
*
|
||||
* If running via 'npm run local', it can be invoked like so:
|
||||
*
|
||||
* curl -X POST -d '{"name": "Tiger", "customerId": "0123456789"}' \
|
||||
* -H'Content-type: application/json' \
|
||||
|
@ -13,37 +15,22 @@ const { CloudEvent, HTTP } = require('cloudevents');
|
|||
* -H'Ce-specversion: 1.0' \
|
||||
* http://localhost:8080
|
||||
*
|
||||
* The event data is extracted from the incoming event and provided as the first
|
||||
* parameter to the function. The CloudEvent object itself may be accessed via the
|
||||
* context parameter, For example:
|
||||
*
|
||||
* const incomingEvent = context.cloudevent;
|
||||
*
|
||||
* @param {Context} context the invocation context
|
||||
* @param {Object} user the CloudEvent data. If the data content type is application/json
|
||||
* this will be converted to an Object via JSON.parse()
|
||||
* @param {Object} event the CloudEvent
|
||||
*/
|
||||
function verifyUser(context, user) {
|
||||
if (!context.cloudevent) {
|
||||
return {
|
||||
message: 'No cloud event received'
|
||||
};
|
||||
}
|
||||
function handle(context, event) {
|
||||
|
||||
context.log.info('Processing user', user);
|
||||
context.log.info(`CloudEvent received: ${context.cloudevent.toString()}`);
|
||||
context.log.info("context");
|
||||
console.log(JSON.stringify(context, null, 2));
|
||||
|
||||
context.log.info("event");
|
||||
console.log(JSON.stringify(event, null, 2));
|
||||
|
||||
user = verify(user);
|
||||
return HTTP.binary(new CloudEvent({
|
||||
source: 'function.verifyUser',
|
||||
type: 'user:verified',
|
||||
data: user
|
||||
source: 'event.handler',
|
||||
type: 'echo',
|
||||
data: event
|
||||
}));
|
||||
};
|
||||
|
||||
function verify(user) {
|
||||
// do something with the user
|
||||
return user;
|
||||
}
|
||||
|
||||
module.exports = verifyUser;
|
||||
module.exports = handle;
|
||||
|
|
|
@ -178,9 +178,9 @@
|
|||
}
|
||||
},
|
||||
"avvio": {
|
||||
"version": "7.2.1",
|
||||
"resolved": "https://registry.npmjs.org/avvio/-/avvio-7.2.1.tgz",
|
||||
"integrity": "sha512-b+gox68dqD6c3S3t+bZBKN6rYbVWdwpN12sHQLFTiacDT2rcq7fm07Ww+IKt/AvAkyCIe1f5ArP1bC/vAlx97A==",
|
||||
"version": "7.2.2",
|
||||
"resolved": "https://registry.npmjs.org/avvio/-/avvio-7.2.2.tgz",
|
||||
"integrity": "sha512-XW2CMCmZaCmCCsIaJaLKxAzPwF37fXi1KGxNOvedOpeisLdmxZnblGc3hpHWYnlP+KOUxZsazh43WXNHgXpbqw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"archy": "^1.0.0",
|
||||
|
@ -356,9 +356,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
||||
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
|
||||
"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
|
@ -704,13 +704,13 @@
|
|||
"dev": true
|
||||
},
|
||||
"faas-js-runtime": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/faas-js-runtime/-/faas-js-runtime-0.6.0.tgz",
|
||||
"integrity": "sha512-p4D8sRw7PArjlD02C9V8m42FBOs79qdqVP/BgWUX6pRIY2pJ6Vd6qTqZ99uBQqjb5HZJfACEcbFtWnUz9RE2Bw==",
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/faas-js-runtime/-/faas-js-runtime-0.7.1.tgz",
|
||||
"integrity": "sha512-BrIP4UtdCOOmCaX/oEpFOP24RIbikaCBQ8Iiaf6Zn54++nkTIvy6HyXzu+35sx4sQdB4w8G4uPFAzOphUQjbJA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^4.1.0",
|
||||
"cloudevents": "^4.0.0",
|
||||
"cloudevents": "^4.0.2",
|
||||
"commander": "^6.1.0",
|
||||
"death": "^1.1.0",
|
||||
"fastify": "^3.3.0",
|
||||
|
@ -719,9 +719,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"cloudevents": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cloudevents/-/cloudevents-4.0.1.tgz",
|
||||
"integrity": "sha512-6Q0jwDOuDbBw9FS31YPggS+baB7/Lv44i6Hp7rMaivAQFdPrMZkdmchONwrKMamLD16myEeb7HNvx+NDqdU57Q==",
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/cloudevents/-/cloudevents-4.0.2.tgz",
|
||||
"integrity": "sha512-tIgdbZApPVT81PAOhmUcq8INkppmWeAsMAjp2EFmMoYc7Uez1B62m6AddxG9oVIUXyALWdATtzEeaSMhC83c/g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "~6.12.3",
|
||||
|
@ -747,9 +747,9 @@
|
|||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
|
||||
},
|
||||
"fast-json-stringify": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.5.4.tgz",
|
||||
"integrity": "sha512-fu74X0fRzQqADX6LFJ+5lSal1+j/QmX4oWrDnrfVAXV4qT6PwyymZmhGa/1SWgouOmf0tBJzZrHZPLymO00Lxg==",
|
||||
"version": "2.7.5",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.7.5.tgz",
|
||||
"integrity": "sha512-VClYNkPo7tyZr0BMrRWraDMTJwjH6dIaHc/b/BiA4Z2MpxpKZBu45akYVb0dOVwQbF22zUMmhdg1WjrUjzAN2g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.11.0",
|
||||
|
@ -759,9 +759,9 @@
|
|||
}
|
||||
},
|
||||
"fast-redact": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.0.tgz",
|
||||
"integrity": "sha512-a/S/Hp6aoIjx7EmugtzLqXmcNsyFszqbt6qQ99BdG61QjBZF6shNis0BYR6TsZOQ1twYc0FN2Xdhwwbv6+KD0w==",
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.1.tgz",
|
||||
"integrity": "sha512-kYpn4Y/valC9MdrISg47tZOpYBNoTXKgT9GYXFpHN/jYFs+lFkPoisY+LcBODdKVMY96ATzvzsWv+ES/4Kmufw==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-safe-stringify": {
|
||||
|
@ -771,9 +771,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"fastify": {
|
||||
"version": "3.14.2",
|
||||
"resolved": "https://registry.npmjs.org/fastify/-/fastify-3.14.2.tgz",
|
||||
"integrity": "sha512-/PY//7gJnGxLQORaRHCEW148vpFKFpBIQNz1Yo/DxbHuk5EQqK2comzyE2ug8FSEldDX8nleapTshl0m78Px2w==",
|
||||
"version": "3.15.1",
|
||||
"resolved": "https://registry.npmjs.org/fastify/-/fastify-3.15.1.tgz",
|
||||
"integrity": "sha512-QZBGrSOwcR+IJF5OwYTZ5662wEd68SqC6sG4aMu0GncKbYlG9GF88EF2PzN2HfXCCD9K0d/+ZNowuF8S893mOg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@fastify/proxy-addr": "^3.0.0",
|
||||
|
@ -795,9 +795,9 @@
|
|||
}
|
||||
},
|
||||
"fastify-error": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/fastify-error/-/fastify-error-0.3.0.tgz",
|
||||
"integrity": "sha512-Jm2LMTB5rsJqlS1+cmgqqM9tTs0UrlgYR7TvDT3ZgXsUI5ib1NjQlqZHf+tDK5tVPdFGwyq02wAoJtyYIRSiFA==",
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/fastify-error/-/fastify-error-0.3.1.tgz",
|
||||
"integrity": "sha512-oCfpcsDndgnDVgiI7bwFKAun2dO+4h84vBlkWsWnz/OUK9Reff5UFoFl241xTiLeHWX/vU9zkDVXqYUxjOwHcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"fastify-warning": {
|
||||
|
@ -1557,16 +1557,16 @@
|
|||
"dev": true
|
||||
},
|
||||
"pino": {
|
||||
"version": "6.11.2",
|
||||
"resolved": "https://registry.npmjs.org/pino/-/pino-6.11.2.tgz",
|
||||
"integrity": "sha512-bmzxwbrIPxQUlAuMkF4PWVErUGERU4z37HazlhflKFg08crsNE3fACGN6gPwg5xtKOK47Ux5cZm8YCuLV4wWJg==",
|
||||
"version": "6.11.3",
|
||||
"resolved": "https://registry.npmjs.org/pino/-/pino-6.11.3.tgz",
|
||||
"integrity": "sha512-drPtqkkSf0ufx2gaea3TryFiBHdNIdXKf5LN0hTM82SXI4xVIve2wLwNg92e1MT6m3jASLu6VO7eGY6+mmGeyw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-redact": "^3.0.0",
|
||||
"fast-safe-stringify": "^2.0.7",
|
||||
"flatstr": "^1.0.12",
|
||||
"pino-std-serializers": "^3.1.0",
|
||||
"quick-format-unescaped": "4.0.1",
|
||||
"quick-format-unescaped": "^4.0.3",
|
||||
"sonic-boom": "^1.0.2"
|
||||
}
|
||||
},
|
||||
|
@ -1643,9 +1643,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"quick-format-unescaped": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.1.tgz",
|
||||
"integrity": "sha512-RyYpQ6Q5/drsJyOhrWHYMWTedvjTIat+FTwv0K4yoUxzvekw2aRHMQJLlnvt8UantkZg2++bEzD9EdxXqkWf4A==",
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.3.tgz",
|
||||
"integrity": "sha512-MaL/oqh02mhEo5m5J2rwsVL23Iw2PEaGVHgT2vFt8AAsr0lfvQA5dpXo9TPu0rz7tSBdUPgkbam0j/fj5ZM8yg==",
|
||||
"dev": true
|
||||
},
|
||||
"rc": {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
"debug": "nodemon --inspect ./node_modules/faas-js-runtime/bin/cli.js ./index.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"faas-js-runtime": "0.6.0",
|
||||
"faas-js-runtime": "0.7.1",
|
||||
"nodemon": "^2.0.4",
|
||||
"supertest": "^4.0.2",
|
||||
"tape": "^4.13.0"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
const { CloudEvent } = require('cloudevents');
|
||||
const runtime = require('faas-js-runtime');
|
||||
const { start } = require('faas-js-runtime');
|
||||
const request = require('supertest');
|
||||
|
||||
const func = require('..');
|
||||
|
@ -19,26 +19,26 @@ const data = {
|
|||
}
|
||||
|
||||
test('Integration: handles a valid event', t => {
|
||||
runtime(func, server => {
|
||||
t.plan(5);
|
||||
request(server)
|
||||
.post('/')
|
||||
.send(data)
|
||||
.set(Spec.id, '01234')
|
||||
.set(Spec.source, '/test')
|
||||
.set(Spec.type, 'com.example.cloudevents.test')
|
||||
.set(Spec.version, '1.0')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, result) => {
|
||||
t.error(err, 'No error');
|
||||
t.ok(result);
|
||||
t.deepEqual(result.body, data);
|
||||
t.equal(result.headers['ce-type'], 'user:verified');
|
||||
t.equal(result.headers['ce-source'], 'function.verifyUser');
|
||||
t.end();
|
||||
server.close();
|
||||
});
|
||||
}, { log: false });
|
||||
start(func)
|
||||
.then(server => {
|
||||
t.plan(5);
|
||||
request(server)
|
||||
.post('/')
|
||||
.send(data)
|
||||
.set(Spec.id, '01234')
|
||||
.set(Spec.source, '/test')
|
||||
.set(Spec.type, 'com.example.cloudevents.test')
|
||||
.set(Spec.version, '1.0')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, result) => {
|
||||
t.error(err, 'No error');
|
||||
t.ok(result);
|
||||
t.deepEqual(result.body.data, data);
|
||||
t.equal(result.headers['ce-type'], 'echo');
|
||||
t.equal(result.headers['ce-source'], 'event.handler');
|
||||
t.end();
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ test('Unit: handles a valid event', t => {
|
|||
const result = func(mockContext, data);
|
||||
t.ok(result);
|
||||
t.equal(result.body, data);
|
||||
t.equal(result.headers['ce-type'], 'user:verified');
|
||||
t.equal(result.headers['ce-source'], 'function.verifyUser');
|
||||
t.equal(result.headers['ce-type'], 'echo');
|
||||
t.equal(result.headers['ce-source'], 'event.handler');
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ function handlePost(context) {
|
|||
*/
|
||||
function invoke(context) {
|
||||
context.log.info(`Handling HTTP ${context.httpVersion} request`);
|
||||
console.log(JSON.stringify(context, null, 2));
|
||||
if (context.method === 'POST') {
|
||||
return handlePost(context);
|
||||
} else if (context.method === 'GET') {
|
||||
|
@ -51,4 +52,4 @@ function invokeDestructured({ name }) {
|
|||
return `Hello ${name}!`;
|
||||
}
|
||||
|
||||
module.exports = invoke;
|
||||
module.exports = invoke;
|
||||
|
|
|
@ -201,9 +201,9 @@
|
|||
}
|
||||
},
|
||||
"avvio": {
|
||||
"version": "7.2.1",
|
||||
"resolved": "https://registry.npmjs.org/avvio/-/avvio-7.2.1.tgz",
|
||||
"integrity": "sha512-b+gox68dqD6c3S3t+bZBKN6rYbVWdwpN12sHQLFTiacDT2rcq7fm07Ww+IKt/AvAkyCIe1f5ArP1bC/vAlx97A==",
|
||||
"version": "7.2.2",
|
||||
"resolved": "https://registry.npmjs.org/avvio/-/avvio-7.2.2.tgz",
|
||||
"integrity": "sha512-XW2CMCmZaCmCCsIaJaLKxAzPwF37fXi1KGxNOvedOpeisLdmxZnblGc3hpHWYnlP+KOUxZsazh43WXNHgXpbqw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"archy": "^1.0.0",
|
||||
|
@ -371,9 +371,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
||||
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
|
||||
"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
|
@ -435,9 +435,9 @@
|
|||
}
|
||||
},
|
||||
"cloudevents": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cloudevents/-/cloudevents-4.0.1.tgz",
|
||||
"integrity": "sha512-6Q0jwDOuDbBw9FS31YPggS+baB7/Lv44i6Hp7rMaivAQFdPrMZkdmchONwrKMamLD16myEeb7HNvx+NDqdU57Q==",
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/cloudevents/-/cloudevents-4.0.2.tgz",
|
||||
"integrity": "sha512-tIgdbZApPVT81PAOhmUcq8INkppmWeAsMAjp2EFmMoYc7Uez1B62m6AddxG9oVIUXyALWdATtzEeaSMhC83c/g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "~6.12.3",
|
||||
|
@ -725,13 +725,13 @@
|
|||
"dev": true
|
||||
},
|
||||
"faas-js-runtime": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/faas-js-runtime/-/faas-js-runtime-0.6.0.tgz",
|
||||
"integrity": "sha512-p4D8sRw7PArjlD02C9V8m42FBOs79qdqVP/BgWUX6pRIY2pJ6Vd6qTqZ99uBQqjb5HZJfACEcbFtWnUz9RE2Bw==",
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/faas-js-runtime/-/faas-js-runtime-0.7.1.tgz",
|
||||
"integrity": "sha512-BrIP4UtdCOOmCaX/oEpFOP24RIbikaCBQ8Iiaf6Zn54++nkTIvy6HyXzu+35sx4sQdB4w8G4uPFAzOphUQjbJA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^4.1.0",
|
||||
"cloudevents": "^4.0.0",
|
||||
"cloudevents": "^4.0.2",
|
||||
"commander": "^6.1.0",
|
||||
"death": "^1.1.0",
|
||||
"fastify": "^3.3.0",
|
||||
|
@ -758,9 +758,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"fast-json-stringify": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.5.4.tgz",
|
||||
"integrity": "sha512-fu74X0fRzQqADX6LFJ+5lSal1+j/QmX4oWrDnrfVAXV4qT6PwyymZmhGa/1SWgouOmf0tBJzZrHZPLymO00Lxg==",
|
||||
"version": "2.7.5",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.7.5.tgz",
|
||||
"integrity": "sha512-VClYNkPo7tyZr0BMrRWraDMTJwjH6dIaHc/b/BiA4Z2MpxpKZBu45akYVb0dOVwQbF22zUMmhdg1WjrUjzAN2g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.11.0",
|
||||
|
@ -770,9 +770,9 @@
|
|||
}
|
||||
},
|
||||
"fast-redact": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.0.tgz",
|
||||
"integrity": "sha512-a/S/Hp6aoIjx7EmugtzLqXmcNsyFszqbt6qQ99BdG61QjBZF6shNis0BYR6TsZOQ1twYc0FN2Xdhwwbv6+KD0w==",
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.1.tgz",
|
||||
"integrity": "sha512-kYpn4Y/valC9MdrISg47tZOpYBNoTXKgT9GYXFpHN/jYFs+lFkPoisY+LcBODdKVMY96ATzvzsWv+ES/4Kmufw==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-safe-stringify": {
|
||||
|
@ -782,9 +782,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"fastify": {
|
||||
"version": "3.14.2",
|
||||
"resolved": "https://registry.npmjs.org/fastify/-/fastify-3.14.2.tgz",
|
||||
"integrity": "sha512-/PY//7gJnGxLQORaRHCEW148vpFKFpBIQNz1Yo/DxbHuk5EQqK2comzyE2ug8FSEldDX8nleapTshl0m78Px2w==",
|
||||
"version": "3.15.1",
|
||||
"resolved": "https://registry.npmjs.org/fastify/-/fastify-3.15.1.tgz",
|
||||
"integrity": "sha512-QZBGrSOwcR+IJF5OwYTZ5662wEd68SqC6sG4aMu0GncKbYlG9GF88EF2PzN2HfXCCD9K0d/+ZNowuF8S893mOg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@fastify/proxy-addr": "^3.0.0",
|
||||
|
@ -817,9 +817,9 @@
|
|||
}
|
||||
},
|
||||
"fastify-error": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/fastify-error/-/fastify-error-0.3.0.tgz",
|
||||
"integrity": "sha512-Jm2LMTB5rsJqlS1+cmgqqM9tTs0UrlgYR7TvDT3ZgXsUI5ib1NjQlqZHf+tDK5tVPdFGwyq02wAoJtyYIRSiFA==",
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/fastify-error/-/fastify-error-0.3.1.tgz",
|
||||
"integrity": "sha512-oCfpcsDndgnDVgiI7bwFKAun2dO+4h84vBlkWsWnz/OUK9Reff5UFoFl241xTiLeHWX/vU9zkDVXqYUxjOwHcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"fastify-warning": {
|
||||
|
@ -1627,16 +1627,16 @@
|
|||
"dev": true
|
||||
},
|
||||
"pino": {
|
||||
"version": "6.11.2",
|
||||
"resolved": "https://registry.npmjs.org/pino/-/pino-6.11.2.tgz",
|
||||
"integrity": "sha512-bmzxwbrIPxQUlAuMkF4PWVErUGERU4z37HazlhflKFg08crsNE3fACGN6gPwg5xtKOK47Ux5cZm8YCuLV4wWJg==",
|
||||
"version": "6.11.3",
|
||||
"resolved": "https://registry.npmjs.org/pino/-/pino-6.11.3.tgz",
|
||||
"integrity": "sha512-drPtqkkSf0ufx2gaea3TryFiBHdNIdXKf5LN0hTM82SXI4xVIve2wLwNg92e1MT6m3jASLu6VO7eGY6+mmGeyw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-redact": "^3.0.0",
|
||||
"fast-safe-stringify": "^2.0.7",
|
||||
"flatstr": "^1.0.12",
|
||||
"pino-std-serializers": "^3.1.0",
|
||||
"quick-format-unescaped": "4.0.1",
|
||||
"quick-format-unescaped": "^4.0.3",
|
||||
"sonic-boom": "^1.0.2"
|
||||
}
|
||||
},
|
||||
|
@ -1714,9 +1714,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"quick-format-unescaped": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.1.tgz",
|
||||
"integrity": "sha512-RyYpQ6Q5/drsJyOhrWHYMWTedvjTIat+FTwv0K4yoUxzvekw2aRHMQJLlnvt8UantkZg2++bEzD9EdxXqkWf4A==",
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.3.tgz",
|
||||
"integrity": "sha512-MaL/oqh02mhEo5m5J2rwsVL23Iw2PEaGVHgT2vFt8AAsr0lfvQA5dpXo9TPu0rz7tSBdUPgkbam0j/fj5ZM8yg==",
|
||||
"dev": true
|
||||
},
|
||||
"rc": {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
"author": "",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"faas-js-runtime": "0.6.0",
|
||||
"faas-js-runtime": "0.7.1",
|
||||
"nodemon": "^2.0.4",
|
||||
"supertest": "^4.0.2",
|
||||
"tape": "^5.0.1"
|
||||
|
|
|
@ -1,56 +1,59 @@
|
|||
'use strict';
|
||||
|
||||
const runtime = require('faas-js-runtime');
|
||||
const { start } = require('faas-js-runtime');
|
||||
const request = require('supertest');
|
||||
|
||||
const func = require('..');
|
||||
const test = require('tape');
|
||||
|
||||
test('Integration: handles an HTTP GET', t => {
|
||||
runtime(func, server => {
|
||||
t.plan(2);
|
||||
request(server)
|
||||
.get('/?name=tiger')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, res) => {
|
||||
t.error(err, 'No error');
|
||||
t.deepEqual(res.body, { query: { name: 'tiger' }, name: 'tiger' });
|
||||
t.end();
|
||||
server.close();
|
||||
});
|
||||
}, { log: false });
|
||||
start(func)
|
||||
.then(server => {
|
||||
t.plan(2);
|
||||
request(server)
|
||||
.get('/?name=tiger')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, res) => {
|
||||
t.error(err, 'No error');
|
||||
t.deepEqual(res.body, { query: { name: 'tiger' }, name: 'tiger' });
|
||||
t.end();
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Integration: handles an HTTP POST', t => {
|
||||
runtime(func, server => {
|
||||
t.plan(2);
|
||||
request(server)
|
||||
.post('/')
|
||||
.send({ name: 'tiger' })
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, res) => {
|
||||
t.error(err, 'No error');
|
||||
t.deepEqual(res.body, { name: 'tiger' });
|
||||
t.end();
|
||||
server.close();
|
||||
});
|
||||
}, { log: false });
|
||||
start(func)
|
||||
.then(server => {
|
||||
t.plan(2);
|
||||
request(server)
|
||||
.post('/')
|
||||
.send({ name: 'tiger' })
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, res) => {
|
||||
t.error(err, 'No error');
|
||||
t.deepEqual(res.body, { name: 'tiger' });
|
||||
t.end();
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Integration: responds with error code if neither GET or POST', t => {
|
||||
runtime(func, server => {
|
||||
t.plan(1);
|
||||
request(server)
|
||||
.put('/')
|
||||
.send({ name: 'tiger' })
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, res) => {
|
||||
t.deepEqual(res.body, { message: 'Route PUT:/ not found', error: 'Not Found', statusCode: 404 });
|
||||
t.end();
|
||||
server.close();
|
||||
});
|
||||
}, { log: false });
|
||||
start(func)
|
||||
.then(server => {
|
||||
t.plan(1);
|
||||
request(server)
|
||||
.put('/')
|
||||
.send({ name: 'tiger' })
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
.end((err, res) => {
|
||||
t.deepEqual(res.body, { message: 'Route PUT:/ not found', error: 'Not Found', statusCode: 404 });
|
||||
t.end();
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue