您可以使用Node.js请求处理程序响应接收到的事件并执行相应的业务逻辑。本文介绍Node.js请求处理程序的相关概念、结构特点和示例。
什么是请求处理程序
FC函数的请求处理程序,是函数代码中处理请求的方法。当您的FC函数被调用时,函数计算会运行您提供的Handler方法处理请求。您可以通过函数计算控制台的请求处理程序参数配置Handler。
对Node.js语言的FC函数而言,您的请求处理程序格式为文件名.方法名
。例如,您的文件名为index.js
或index.mjs
,方法名为handler
,则请求处理程序为index.handler
。
关于FC函数的具体定义和相关操作,请参见创建事件函数。
请求处理程序的具体配置均需符合函数计算平台的配置规范。配置规范因请求处理程序类型而异。
Handler签名
函数计算从Node.js 18运行时开始支持ECMAScript(ES)模块。在此之前(Node.js 16及以前的版本),函数计算仅支持使用CommonJS 模块。详情请参见将请求处理程序指定为ES模块。
一个简单的Event Handler签名定义如下。
Node.js 18或Node.js 20
ES模块
当前示例代码支持一键部署,您可以直接在函数计算FC中一键部署本代码。start-fc3-nodejs-es
// index.mjs
export const handler = async (event, context) => {
console.log("receive event: \n" + event);
return "Hello World!";
};
CommonJS模块
// index.js
exports.handler = async function(event, context) {
console.log("receive event: \n" + event);
return "Hello World!";
};
Node.js 16及以下版本
// index.js
exports.handler = async function(event, context, callback) {
console.log("event: \n" + event);
callback(null, 'hello world');
};
以上示例代码解析如下:
handler
是方法名称,与函数计算控制台配置的请求处理程序相对应。例如,创建函数时指定的请求处理程序为index.handler
,那么函数计算会去加载index.js
中定义的handler
函数,并从这里开始执行。
函数计算运行时会将请求参数传递到请求处理程序中,第一个参数是event
对象,包含请求的有效负载信息,event
对象是Buffer类型,您可以将其转换成所需要的对象类型。第二个参数是 context
对象,提供在调用时的运行上下文信息。更多信息,请参见上下文。
使用Node.js 18及以上版本的运行时环境时,建议您使用Async/Await功能,而不是使用回调函数
callback
。函数计算会根据返回值的类型对返回结果做相应转换。
Buffer类型:不转换,原样返回。
Object类型:转换为JSON格式后返回。
其他类型:转换为字符串后返回。
Async/Await
使用Node.js 18及以上版本的运行时环境时,建议您使用Async/Await方式来实现。Async/Await是一种简洁、易读的Node.js异步代码编写方式,无需嵌套回调或链式调用。
如果您使用的Node.js 16及以下版本的运行时环境,则必须显式使用回调方法 callback
发送响应,否则会出现请求超时错误。
Async/Await方式与回调函数callback
相比,有以下优点:
可读性更好:Async/Await方式的代码更加线性和同步,更易于理解和维护。它避免了回调函数嵌套过深的情况,使代码结构更清晰。
调试和错误处理更简单:可以使用try-catch块更方便地捕获和处理异步操作中的错误,错误堆栈更加清晰,可以更准确地追踪错误发生的位置。
效率更高:回调函数通常需要在代码的不同部分之间切换。Async/Await方式可以减少上下文切换的数量,从而提高代码效率。
示例一:解析JSON格式参数
示例代码
当您传入JSON格式参数时,函数计算会透传参数内容,需要您在代码中自行解析。下面是解析JSON格式事件的代码示例。
ES模块
此示例仅支持运行在Node.js 18及以上版本的运行时环境。
export const handler = async (event, context) => {
var eventObj = JSON.parse(event.toString());
return eventObj['key'];
};
CommonJS模块
当前示例代码支持一键部署,您可以直接在函数计算FC中一键部署本代码。start-fc3-nodejs-json
exports.handler = function(event, context, callback) {
var eventObj = JSON.parse(event.toString());
callback(null, eventObj['key']);
};
前提条件
已创建Node.js函数,具体操作,请参见创建事件函数。如果您需要将代码指定为ES模块,创建函数时,运行环境需选择Node.js 18或Node.js 20。
操作步骤
登录函数计算控制台,在左侧导航栏,单击函数。
在顶部菜单栏,选择地域,然后在函数页面,单击目标函数。
在函数配置页面,选择代码页签,在代码编辑器中输入上述示例代码,然后单击部署代码。
说明上述示例代码中函数的请求处理程序是
index.js
中的handler
方法。如果您的函数的请求处理程序配置不同,请获取对应的文件和方法进行更新。在代码页签,单击测试函数右侧的图标,从下拉列表中选择配置测试参数,输入以下示例测试参数,然后单击确定。
{ "key": "value" }
单击测试函数。
函数执行成功后,查看返回结果,您可以看到返回结果为
value
。
示例二:通过临时密钥安全读写OSS的资源
示例代码
您可以使用函数计算为您提供的临时密钥访问对象存储OSS,代码示例如下所示。
ES模块
此示例仅支持运行在Node.js 18及以上版本的运行时环境。
// index.mjs
import OSSClient from 'ali-oss';
export const handler = async (event, context) => {
console.log(event.toString());
var ossClient = new OSSClient({
accessKeyId: context.credentials.accessKeyId,
accessKeySecret: context.credentials.accessKeySecret,
stsToken: context.credentials.securityToken,
region: 'oss-cn-shenzhen',
bucket: 'my-bucket',
});
try {
const uploadResult = await ossClient.put('myObj', Buffer.from('hello, fc', "utf-8"));
console.log('upload success, ', uploadResult);
return "put object"
} catch (error) {
throw error
}
};
代码示例解析:
context.credentials
:从 context 参数中获取临时密钥,避免在代码中硬编码密码等敏感信息。myObj
:OSS对象名。Buffer.from('hello, fc', "utf-8")
: 上传的对象内容。return "put object"
:上传成功正常返回 "put object"。throw err
:上传失败时抛出异常。
CommonJS模块
当前示例代码支持一键部署,您可以直接在函数计算FC中一键部署本代码。start-fc3-nodejs-oss
var OSSClient = require('ali-oss');
exports.handler = function (event, context, callback) {
console.log(event.toString());
var ossClient = new OSSClient({
accessKeyId: context.credentials.accessKeyId,
accessKeySecret: context.credentials.accessKeySecret,
stsToken: context.credentials.securityToken,
region: `oss-${context.region}`,
bucket: process.env.BUCKET_NAME,
});
ossClient.put('myObj', Buffer.from('hello, fc', "utf-8")).then(function (res) {
callback(null, 'put object');
}).catch(function (err) {
callback(err);
});
};
示例代码解析如下:
context.credentials
:表示从context
参数中获取临时密钥,避免在代码中硬编码密码等敏感信息。myObj
:OSS对象名称。Buffer.from('hello, fc', "utf-8")
:上传的对象的内容。callback(null, 'put object')
:上传成功正常返回put object
。callback(err)
:上传失败时返回err
。
前提条件
为服务配置具有访问对象存储OSS的权限的角色。具体操作,请参见授予函数计算访问其他云服务的权限。
创建运行环境为Node.js的函数。具体操作,请参见创建事件函数。如果您需要将代码指定为ES模块,创建函数时,运行环境需选择Node.js 18或Node.js 20。
操作步骤
登录函数计算控制台,在左侧导航栏,单击函数。
在顶部菜单栏,选择地域,然后在函数页面,单击目标函数。
(可选)在目标函数的函数详情页签,选择代码页签,然后在下方的WebIDE界面,依次选择
打开终端,执行以下命令安装ali-oss依赖。npm install ali-oss --save
安装完成后,在WebIDE界面左侧代码目录可以看到生成了
node_modules
文件夹,文件夹内包含ali-oss
目录以及其他依赖库。在目标函数的函数详情页签,选择代码页签,在下方的代码编辑器中输入上述示例代码,保存并单击部署代码。
说明上述示例代码中函数的请求处理程序是
index.js
或index.mjs
文件中的handler
方法。如果您的函数的请求处理程序配置不同,请获取对应的文件和方法进行更新。上述示例代码中
region
和bucket
需按照实际情况填写。
单击测试函数。
函数执行成功后,查看返回结果,您可以看到返回结果为
put object
。
示例三:调用外部命令
您的Node.js程序也可以创建fork
进程,调用外部命令。例如,您可以使用child_process
模块调用Linux的ls -l
命令,输出当前目录下的文件列表。代码示例如下所示。
ES模块
此示例仅支持运行在Node.js 18及以上版本的运行时环境。
'use strict';
import { exec } from 'child_process';
import { promisify } from 'util';
const execPromisify = promisify(exec);
export const handler = async (event, context) => {
try {
const { stdout, stderr } = await execPromisify("ls -l");
console.log(`stdout: ${stdout}`);
if (stderr !== "") {
console.error(`stderr: ${stderr}`);
}
return stdout;
} catch (error) {
console.error(`exec error: ${error}`);
return error;
}
}
CommonJS模块
当前示例代码支持一键部署,您可以直接在函数计算FC中一键部署本代码。start-fc3-nodejs-exec
'use strict';
var exec = require('child_process').exec;
exports.handler = (event, context, callback) => {
console.log('start to execute a command');
exec("ls -l", function(error, stdout, stderr){
callback(null, stdout);
});
}
示例四:使用HTTP触发器调用函数
示例代码
使用HTTP触发器提供的URL调用函数,函数代码示例如下。
如果HTTP触发器的认证方式为无需认证,您可以直接使用Postman或Curl工具来调用函数。具体操作,请参见操作步骤。
如果HTTP触发器的认证方式为签名认证或JWT认证,请使用签名方式或JWT认证方式来调用函数。具体操作,请参见认证鉴权。
关于HTTP触发调用的请求负载格式和响应负载格式,请参见HTTP触发器调用函数。
ES模块
此示例仅支持运行在Node.js 18及以上版本的运行时环境。
'use strict';
export const handler = async (event, context) => {
const eventObj = JSON.parse(event);
console.log(`receive event: ${JSON.stringify(eventObj)}`);
let body = 'Hello World!';
// get http request body
if ("body" in eventObj) {
body = eventObj.body;
if (eventObj.isBase64Encoded) {
body = Buffer.from(body, 'base64').toString('utf-8');
}
}
console.log(`receive http body: ${body}`);
return {
'statusCode': 200,
'body': body
};
}
CommonJS模块
当前示例代码支持一键部署,您可以直接在函数计算FC中一键部署本代码。start-fc3-nodejs-http
'use strict';
exports.handler = (event, context, callback) => {
const eventObj = JSON.parse(event);
console.log(`receive event: ${JSON.stringify(eventObj)}`);
let body = 'Hello World!';
// get http request body
if ("body" in eventObj) {
body = eventObj.body;
if (eventObj.isBase64Encoded) {
body = Buffer.from(body, 'base64').toString('utf-8');
}
}
console.log(`receive http body: ${body}`);
callback(null, {
'statusCode': 200,
'body': body
});
}
前提条件
已使用上述示例创建运行环境为Node.js的函数并创建HTTP触发器。具体操作,请参见创建事件函数和配置HTTP触发器并使用HTTP触发。如果您需要将代码指定为ES模块,创建函数时,运行环境需选择Node.js 18或Node.js 20。
操作步骤
登录函数计算控制台,在左侧导航栏,单击函数。
在顶部菜单栏,选择地域,然后在函数页面,单击目标函数。
在函数详情页面,单击配置页签,然后再左侧导航栏,单击触发器,在触发器页面获取HTTP触发器的公网访问地址。
在Curl工具执行以下命令,调用函数。
curl -i "https://test-nodejs-dlgxxr****.cn-shanghai.fcapp.run" -d 'Hello World!'
以上命令中,
https://test-nodejs-dlgxxr****.cn-shanghai.fcapp.run
为获取到的HTTP触发器公网访问地址。响应结果如下。
HTTP/1.1 200 OK Access-Control-Expose-Headers: Date,x-fc-request-id Content-Disposition: attachment Content-Length: 12 Content-Type: text/html; charset=utf-8 Etag: W/"c-Lve95gjOVATpfV8EL5X4nxwjKHE" X-Fc-Request-Id: 1-65d866a8-15d8796a-cb9b4feb69ca X-Powered-By: Express Date: Fri, 23 Feb 2024 09:34:34 GMT Hello World!curl: (3) URL using bad/illegal format or missing URL
示例五:使用HTTP触发器下载文件
示例代码
如果您想通过代码返回一个图片、压缩包或二进制文件,可以使用HTTP触发器实现在函数代码中返回,函数代码示例如下。
ES模块
此示例仅支持运行在Node.js 18及以上版本的运行时环境。
// index.mjs
'use strict';
import mime from 'mime';
import fs from 'fs/promises';
import path from 'path';
export const handler = async (event, context) => {
const fileContent = 'This is a sample text file created in the code.';
const fileName = 'sample.txt';
const filePath = path.join('/tmp', fileName);
try {
await fs.writeFile(filePath, fileContent);
const mimeType = mime.getType(filePath);
if (!mimeType) {
throw new Error('Unable to determine MIME type');
}
const fileData = await fs.readFile(filePath);
const fileBase64 = Buffer.from(fileData).toString('base64');
const fcResponse = {
'statusCode': 200,
'headers': {
'Content-Type': mimeType,
'Content-Disposition': `attachment; filename="${fileName}"`,
},
'body': fileBase64,
'isBase64Encoded': true
};
console.log('File generated and fetched successfully.');
return fcResponse;
} catch (err) {
console.error(err);
return {
'statusCode': 500,
'body': err.message
};
}
};
CommonJS模块
// index.js
'use strict';
const mime = require('mime');
const fs = require('fs');
const path = require('path');
exports.handler = async (event, context, callback) => {
const fileContent = 'This is a sample text file created in the code.';
const fileName = 'sample.txt';
const filePath = path.join('/tmp', fileName);
try {
fs.writeFileSync(filePath, fileContent);
const mimeType = mime.getType(filePath);
if (!mimeType) {
throw new Error('Unable to determine MIME type');
}
const fileData = fs.readFileSync(filePath);
const fileBase64 = Buffer.from(fileData).toString('base64');
const fcResponse = {
'statusCode': 200,
'headers': {
'Content-Type': mimeType,
'Content-Disposition': `attachment; filename="${fileName}"`,
},
'body': fileBase64,
'isBase64Encoded': true
};
console.log('File generated and fetched successfully.');
callback(null, fcResponse);
} catch (err) {
console.error(err);
callback(null, {
'statusCode': 500,
'body': err.message
});
}
};
前提条件
已使用上述示例创建运行环境为Node.js的函数并创建HTTP触发器。具体操作,请参见创建事件函数和配置HTTP触发器并使用HTTP触发。如果您需要将代码指定为ES模块,创建函数时,运行环境需选择Node.js 18或Node.js 20。
操作步骤
登录函数计算控制台,在左侧导航栏,单击函数。
在顶部菜单栏,选择地域,然后在函数页面,单击目标函数。
在函数详情页面,选择代码页签,然后选择
打开终端窗口,执行命令npm install mime@2
安装mime库。安装完成后,单击部署代码。在函数配置页面的触发器页签,获取HTTP触发器的公网访问地址,复制URL到浏览器并回车。
回车后触发器函数执行,执行成功后下载文件到本地。