深色模式
Node.js 云函数
云函数让您可以运行 JavaScript 后端代码,处理动态 API 请求、操作文件、调用外部 API 等。只需将文件命名为 .node.js 结尾(如 api.node.js),代码就会在服务器后端执行。
第一个云函数
在文件列表中创建一个以 .node.js 结尾的 JavaScript 文件,例如 hello.node.js。这个文件将包含如下云函数代码:
js
document.write("Hello, World!");访问这个文件,您会看到「Hello, World!」。就这么简单!
由于代码在服务器上运行,当您通过浏览器开发者工具检查时,不会看到任何 JavaScript 代码,只会看到运行结果,因为代码是在服务器后端动态执行的。
获取请求信息
我们提供了全局的 req 对象,其风格受 Express.js 启发。您可以使用 req 对象访问请求参数。同时,我们实现了一些浏览器前端风格的接口,可以用和前端一样的方式获取信息,方便前端开发者快速上手。
访问查询参数
您可以通过 req.query 访问 URL 查询参数。例如,当网址带有 ?name=Alice 时,您可以这样获取 name 参数的值:
js
const name = req.query.name;
document.write(name); // 输出 "Alice"您也可以通过 location.search 获取查询字符串:
js
document.write(location.search); // 输出 "?name=Alice"访问 POST 参数
对于 POST 请求,您可以通过 req.body 访问请求体中的参数。例如,假设您发送了一个包含 message=Hello 的 POST 请求,您可以这样获取 message 参数的值:
js
const message = req.body.message;
document.write(message); // 输出 "Hello"获取请求头
您可以通过 req.headers 访问请求头的键值对。例如,获取名为 Accept-Language 的请求头:
js
const acceptLanguage = req.headers["accept-language"];
document.write(acceptLanguage);获取 Cookie
您可以通过 req.cookies 访问请求中的 Cookie。例如,获取名为 sessionId 的 Cookie:
js
const sessionId = req.cookies.sessionId;
document.write(sessionId);获取用户代理
您可以从请求头中获取用户代理信息,了解访客使用的浏览器和操作系统。
js
const userAgent = req.headers["user-agent"];
document.write(userAgent);您也可以通过 navigator.userAgent 获取用户代理信息:
js
document.write(navigator.userAgent);获取来源网址
您可以通过 req.headers.referer 或 document.referrer 获取请求的来源网址,即用户从哪个页面来到当前页面。
拼写差异
由于 HTTP 历史原因,req.headers 中的拼写是「referer」而不是「referrer」,但在 document 中是正确的拼写。
js
document.write(req.headers.referer);
document.write(document.referrer);获取访客 IP 地址
您可以通过 req.ip 获取访客的 IP 地址:
js
const ip = req.ip;
document.write(ip);获取当前网址
您可以通过 req.url 或 location.href 获取当前请求的完整网址:
js
const url = req.url;
document.write(url);获取请求方法
您可以通过 req.method 获取当前请求方法(如 GET、POST 等):
js
const method = req.method;
document.write(method); // 输出 "GET" 或 "POST"响应请求
您可以使用全局的 res 对象来设置响应头和状态码,并发送响应内容。
输出内容
您可以使用这些函数输出内容:
console.logdocument.writeres.write
这些函数的功能是相同的。它们都可以被多次调用,输出的内容会按调用顺序拼接在一起,作为响应体发送给客户端。如果您用过 PHP,这与使用 echo 输出内容类似。
js
res.write("Hello, ");
res.write("World");
res.write("!");您会看到输出结果为 "Hello, World!"。
由于没有服务器控制台,console.log 的输出等同于 document.write,会直接输出到响应内容中。
输出内容并退出
如果您希望输出一次内容后立即退出程序,可以使用以下函数:
res.endres.send
这两个函数的功能是相同的。如果您用过 PHP,这相当于 echo 后马上调用 exit。
js
res.end("Goodbye, World!");
res.write("This will not be sent.");您会看到输出结果只有 "Goodbye, World!",因为后续的代码不会被执行。
输出 JSON
如果您想输出 JSON 格式的数据,可以使用 res.json 函数。这个函数会自动将 JSON 转换为字符串,设置适当的响应头,发送给客户端,并退出程序。
js
const data = { message: "Hello, JSON!" };
res.json(data);您会看到输出结果为 {"message": "Hello, JSON!"},其后续代码不会被执行。
设置响应状态码
默认情况下,状态码为 200(成功)。您可以使用 res.status 函数更改响应的 HTTP 状态码。例如,设置状态码为 404(未找到):
js
res.status(404);您也可以通过直接更改 res.statusCode 的值来设置状态码:
js
res.statusCode = 404;您可以在 MDN 或 HTTP Cats 查看各个状态码的含义。
设置响应头
您可以使用 res.setHeader 或 res.set 函数设置响应头。例如,设置缓存时长为 1 小时:
js
res.setHeader("Cache-Control", "max-age=3600");设置 Cookie
您可以使用 res.cookie 函数设置 Cookie。例如,设置一个名为 username 的 Cookie,值为 Alice,并设置过期时间为 7 天:
js
res.cookie("username", "Alice", { maxAge: 7 * 24 * 60 * 60 * 1000 });重定向跳转
res.redirect 函数将当前请求重定向到另一个网址,并退出程序。
例如,将当前请求重定向到百度首页:
js
res.redirect("https://www.baidu.com/");您也可以使用和前端一样的方式进行重定向,这和 res.redirect 行为一致:
js
location.href = "https://www.baidu.com/";如果您想让浏览器和搜索引擎知道这是一个永久重定向,可以传入响应状态码 301:
js
res.redirect(301, "https://www.baidu.com/");提前退出程序
如果您想在某些条件下提前终止程序执行,可以使用 process.exit() 函数,这会立即停止程序运行。
js
document.write("1");
process.exit();
document.write("2");您会看到输出结果只有 "1",因为程序在执行到 process.exit() 时就停止了,后续代码不会被执行。
读写文件
您可以使用内置的 fs 模块读写同网站上的文件,用法与 Node.js 基本一致。我们的 fs 是一个全局对象,无需使用 import 或 require 导入,直接使用即可。目前只支持非异步函数。
读取文件
您可以使用 fs.readFileSync 读取文件内容。例如,读取当前网站下的 data.txt 文件:
js
const content = fs.readFileSync("data.txt");
document.write(content);如果文件不存在,会抛出错误。您可以使用 fs.existsSync 先判断文件是否存在:
js
if (fs.existsSync("data.txt")) {
const content = fs.readFileSync("data.txt");
document.write(content);
} else {
document.write("文件不存在。");
}如果您更熟悉前端的写法,您也可以使用 localStorage 来读写文件内容,效果与 fs 相同:
js
const content = localStorage.getItem("data.txt");
document.write(content);请注意
如果您要读写的文件位于某个文件夹中,不管云函数文件在哪里,都需要使用完整的绝对路径。在热铁盒网页托管,/ 是文件名的一部分,因此不支持相对路径。假设您要读写的文件在 databases 文件夹中,那么您的代码应该是这样的:
js
const content = fs.readFileSync("databases/data.txt");
document.write(content);读取 JSON 文件
您可以使用 fs.readFileSync 读取 JSON 文件内容,然后使用 JSON.parse 将其转换为 JS 对象。例如,读取当前网站下的 data.json 文件:
js
const content = fs.readFileSync("data.json");
const data = JSON.parse(content);写入文件
您可以使用 fs.writeFileSync 或 localStorage.setItem 写入文件内容。例如,向当前网站下的 data.txt 文件写入新内容覆盖原有内容:
js
fs.writeFileSync("data.txt", "Hello, File!");
localStorage.setItem("data.txt", "Hello, File!");出于安全原因,不能写入 CSS、JavaScript、PHP 等类型的代码文件。
请注意
由于技术限制,目前只有当网站的文本文件总大小不超过 4 MB 时,才能读写文件和引入其他文件。您可以在写入前使用 os.diskFreeSpace() 检查剩余空间:
js
const freeSpace = os.diskFreeSpace();
document.write(`剩余空间:${freeSpace} 字节`);如需存储用户数据,请使用数据库。数据库不限制总空间大小。
写入 JSON 文件
您可以使用 JSON.stringify 将 JS 对象转换为字符串,然后使用 fs.writeFileSync 写入 JSON 文件。例如,向当前网站下的 data.json 文件写入数据:
js
const data = { key: "value" };
fs.writeFileSync("data.json", JSON.stringify(data));列出文件
您可以使用 fs.readdirSync 列出当前网站下的所有文件和文件夹。例如,列出当前网站下的所有文件:
js
const files = fs.readdirSync(".");
document.write(files);引入其他文件
您可以使用 require() 函数引入同网站上的其他 Node.js 云函数,实现代码模块化。这与 Node.js 的 CommonJS 模块系统类似。
导出模块
在被引入的文件中,您可以使用 module.exports 导出函数、对象或变量。例如,创建一个 utils.node.js 文件:
js
function add(a, b) {
return a + b;
}
function greet(name) {
return `Hello, ${name}!`;
}
module.exports = { add, greet };引入模块
在云函数文件中,使用 require() 引入其他文件。例如,在 api.node.js 中引入上面的 utils.node.js:
js
const utils = require("utils.node.js");
const message = utils.greet("Alice");
document.write(message); // 输出 "Hello, Alice!"
const sum = utils.add(3, 5);
document.write(sum); // 输出 8请注意
与读写文件类似,如果被引入的文件位于某个文件夹中,需要使用完整的路径。例如,如果 utils.node.js 在 lib 文件夹中,应该这样引入:
js
const utils = require("lib/utils.node.js");引入 JSON 文件
除了引入 JavaScript 模块,您也可以使用 require() 直接引入 JSON 文件。require() 会自动解析 JSON 文件并返回对应的对象,无需手动调用 JSON.parse()。
例如,假设您有一个 config.json 文件:
json
{
"appName": "我的应用",
"version": "1.0.0"
}您可以这样引入并使用:
js
const config = require("config.json");
document.write(config.appName); // 输出 "我的应用"
document.write(config.version); // 输出 "1.0.0"与 fs.readFileSync 的区别是,使用 require() 引入 JSON 文件时,文件内容会被缓存,直到下次运行云函数时才会重新读取。fs.readFileSync 则每次都会读取最新的文件内容。
Node.js 内置模块
您可以引入 Node.js 内置模块来扩展云函数的功能。目前支持以下模块:
crypto:用于加密和解密数据。fs:用于读写文件。os:用于获取操作系统相关信息。path:用于处理和转换文件路径。process:用于控制当前 Node.js 进程。querystring:用于解析和格式化 URL 查询字符串。
与标准的差异
云函数运行在热铁盒自研的 Serverless 环境中,和传统的 Node.js 运行环境有一些差异。目前暂不支持安装 npm 依赖。