前言
在 Express 中,请求对象(通常表示为 req
)和响应对象(通常表示为 res
)是处理 HTTP 请求和响应的关键组件。它们分别基于 Node.js 原生的 http.IncomingMessage
和 http.ServerResponse
对象,但提供了更多有用的方法和属性。本文主要介绍的是 Express 的「响应对象」response。
参考资料
- Express 官方文档 👉🏻 https://expressjs.com/en/api.html#res
响应对象(res)
Express 的 res
(响应)对象代表服务器发回给客户端的 HTTP 响应。res
对象提供了一系列方法和属性,允许您轻松地构建和发送 HTTP 响应。它包含了用于构建响应的方法,如设置响应头、状态码、发送响应主体等。通过使用这些请求对象和响应对象的属性和方法,开发者可以在 Express 中轻松地处理各种 HTTP 请求和构建响应。以下是一些我们可能需要了解的主要方法和属性:
res.status(code)
: 设置 HTTP 响应状态码。例如,res.status(200)
表示成功的响应,res.status(404)
表示找不到资源。res.set(header, value)
: 设置一个 HTTP 响应头。例如,res.set('Content-Type', 'application/json')
设置响应内容类型为 JSON。res.get(header)
: 获取当前设置的 HTTP 响应头值。例如,res.get('Content-Type')
获取响应内容类型。res.send(body)
: 发送 HTTP 响应,并根据提供的响应体自动设置内容类型和长度。这是最常用的发送响应的方法。res.json(obj)
: 发送 JSON 格式的 HTTP 响应。这个方法会自动设置Content-Type
为application/json
。res.sendFile(path)
: 发送指定路径的文件作为 HTTP 响应。这对于静态文件服务非常有用。res.download(path)
: 发送指定路径的文件,并提示浏览器下载文件。res.redirect(url)
: 发送一个重定向响应,将客户端重定向到另一个 URL。res.locals
: 一个对象,允许您在响应期间存储局部变量。这些变量可以在其他中间件和路由处理程序中访问。res.cookie(name, value, options)
: 设置一个 Cookie。您可以传递一个选项对象来配置 Cookie 的属性,如过期时间、路径、域等。res.clearCookie(name, options)
: 清除指定名称的 Cookie。
这些只是 res
对象上最常用的方法和属性。了解这些方法可以帮助您在 Express 应用程序中有效地处理 HTTP 响应。有关更多详细信息,请参阅 Express 官方文档。
demos
这一部分,我们将通过一些简单的小 demo 来认识一下 Express 的 res 对象身上的一些常见 api 的基本用法。
demo | res.status(code)
视频:
源码:230511_res.status(code).zip.zip%22%2C%22size%22%3A13890%2C%22ext%22%3A%22zip%22%2C%22source%22%3A%22%22%2C%22status%22%3A%22done%22%2C%22download%22%3Atrue%2C%22taskId%22%3A%22ubf0536d1-e333-46c1-9b94-08368309449%22%2C%22taskType%22%3A%22transfer%22%2C%22type%22%3A%22application%2Fzip%22%2C%22mode%22%3A%22title%22%2C%22id%22%3A%22u02c58ef7%22%2C%22card%22%3A%22file%22%7D)
以下是一个使用 res.status(code)
设置不同 HTTP 响应状态码的 Express 示例:
const express = require('express');
const app = express();
const port = 3000;
app.get('/success', (req, res) => {
res.status(200).send('Success!'); // 设置状态码为 200,表示成功的响应
});
app.get('/created', (req, res) => {
res.status(201).send('Resource created.'); // 设置状态码为 201,表示资源已成功创建
});
app.get('/bad-request', (req, res) => {
res.status(400).send('Bad Request.'); // 设置状态码为 400,表示客户端请求有问题
});
app.get('/not-found', (req, res) => {
res.status(404).send('Resource not found.'); // 设置状态码为 404,表示找不到请求的资源
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含四个路由。每个路由都使用 res.status(code)
方法设置了不同的 HTTP 响应状态码,然后发送了一个简单的响应消息。
当我们访问这些不同的路由时,例如 http://localhost:3000/success
或 http://localhost:3000/not-found
,你会看到服务器返回的响应状态码和对应的消息。
demo | res.set(header, value)
以下是一个使用 res.set(header, value)
设置 HTTP 响应头的 Express 示例:
const express = require('express');
const app = express();
const port = 3000;
app.get('/plain-text', (req, res) => {
res.set('Content-Type', 'text/plain'); // 设置响应头 Content-Type 为 text/plain
res.send('This is plain text content.');
});
app.get('/json', (req, res) => {
res.set('Content-Type', 'application/json'); // 设置响应头 Content-Type 为 application/json
res.send({ message: 'This is JSON content.' });
});
app.get('/custom-header', (req, res) => {
res.set('X-Custom-Header', 'CustomHeaderValue'); // 设置一个自定义响应头
res.send('Response with a custom header.');
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含三个路由。每个路由都使用 res.set(header, value)
方法设置了不同的 HTTP 响应头。
/plain-text
路由设置Content-Type
为text/plain
,表示响应内容是纯文本。/json
路由设置Content-Type
为application/json
,表示响应内容是 JSON 格式。/custom-header
路由设置了一个自定义响应头X-Custom-Header
,其值为CustomHeaderValue
。
当你访问这些不同的路由时,例如 http://localhost:3000/plain-text
或 `http://localhost:3000/json
demo | res.get(header)
以下是一个使用 res.get(header)
获取 HTTP 响应头的 Express 示例:
const express = require('express');
const app = express();
const port = 3000;
app.get('/check-content-type', (req, res) => {
res.set('Content-Type', 'application/json'); // 设置响应头 Content-Type 为 application/json
const contentType = res.get('Content-Type'); // 获取响应头 Content-Type 的值
console.log('Content-Type:', contentType); // 打印 Content-Type 的值
res.send({ message: 'The Content-Type header has been set and retrieved.' });
});
app.get('/check-custom-header', (req, res) => {
res.set('X-Custom-Header', 'CustomHeaderValue'); // 设置一个自定义响应头
const customHeader = res.get('X-Custom-Header'); // 获取自定义响应头 X-Custom-Header 的值
console.log('X-Custom-Header:', customHeader); // 打印 X-Custom-Header 的值
res.send('The custom header has been set and retrieved.');
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含两个路由。每个路由都使用 res.set(header, value)
方法设置了 HTTP 响应头,然后使用 res.get(header)
方法获取并打印这些响应头的值。
/check-content-type
路由设置Content-Type
为application/json
,然后获取并打印Content-Type
的值。/check-custom-header
路由设置了一个自定义响应头X-Custom-Header
,其值为CustomHeaderValue
,然后获取并打印X-Custom-Header
的值。
当你访问这些不同的路由时,例如 http://localhost:3000/check-content-type
或 http://localhost:3000/check-custom-header
,你会在服务器控制台看到打印出的响应头的值。
demo | res.send(body)
以下是一个使用 res.send(body)
发送不同类型 HTTP 响应体的 Express 示例:
const express = require('express');
const app = express();
const port = 3000;
app.get('/send-text', (req, res) => {
res.send('This is a plain text response.'); // 发送纯文本响应
});
app.get('/send-html', (req, res) => {
res.send('<h1>This is an HTML response.</h1>'); // 发送 HTML 响应
});
app.get('/send-json', (req, res) => {
res.send({ message: 'This is a JSON response.' }); // 发送 JSON 响应
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含三个路由。每个路由都使用 res.send(body)
方法发送不同类型的响应体。
/send-text
路由发送纯文本响应。/send-html
路由发送 HTML 响应。/send-json
路由发送 JSON 响应。
当你访问这些不同的路由时,例如 http://localhost:3000/send-text
、http://localhost:3000/send-html
或 http://localhost:3000/send-json
,你会看到服务器返回的不同类型的响应体。
需要注意的是,res.send()
方法会根据提供的响应体自动设置 Content-Type
和 Content-Length
响应头。
demo | res.json(obj)
以下是一个使用 res.json(obj)
发送 JSON 格式响应的 Express 示例:
const express = require('express');
const app = express();
const port = 3000;
app.get('/json-object', (req, res) => {
const responseObject = { message: 'This is a JSON object response.' };
res.json(responseObject); // 发送 JSON 对象响应
});
app.get('/json-array', (req, res) => {
const responseArray = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
res.json(responseArray); // 发送 JSON 数组响应
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含两个路由。每个路由都使用 res.json(obj)
方法发送 JSON 格式的响应体。
/json-object
路由发送 JSON 对象响应。/json-array
路由发送 JSON 数组响应。
当你访问这些不同的路由时,例如 http://localhost:3000/json-object
或 http://localhost:3000/json-array
,你会看到服务器返回的 JSON 格式的响应体。
需要注意的是,res.json()
方法会自动设置 Content-Type
响应头为 application/json
。
demo | res.sendFile(path)
以下是一个使用 res.sendFile(path)
发送文件作为响应的 Express 示例:
首先,我们创建一个名为 public
的文件夹,然后在其中创建一个名为 image.jpg
的图片文件。
接着,创建一个名为 server.js
的文件,内容如下:
const express = require('express');
const app = express();
const port = 3000;
const path = require('path');
app.get('/send-image', (req, res) => {
const imagePath = path.join(__dirname, 'public', 'image.jpg');
res.sendFile(imagePath); // 发送图片文件作为响应
});
app.get('/send-html', (req, res) => {
const htmlPath = path.join(__dirname, 'public', 'index.html');
res.sendFile(htmlPath); // 发送 HTML 文件作为响应
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含两个路由。每个路由都使用 res.sendFile(path)
方法发送文件作为响应。
/send-image
路由发送名为image.jpg
的图片文件作为响应。/send-html
路由发送名为index.html
的 HTML 文件作为响应。
在这个示例中,我们使用了 path.join()
方法来构建文件路径,以确保在不同操作系统上能正确处理文件路径。
当你访问这些不同的路由时,例如 http://localhost:3000/send-image
或 http://localhost:3000/send-html
,你会看到服务器返回的文件作为响应。
demo | res.download(path)
以下是一个使用 res.download(path)
使浏览器下载文件的 Express 示例:
首先,我们创建一个名为 files
的文件夹,然后在其中创建一个名为 sample.txt
的文本文件。
接着,创建一个名为 server.js
的文件,内容如下:
const express = require('express');
const app = express();
const port = 3000;
const path = require('path');
app.get('/download-file', (req, res) => {
const filePath = path.join(__dirname, 'files', 'sample.txt');
res.download(filePath); // 使浏览器下载 sample.txt 文件
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含一个路由。这个路由使用 res.download(path)
方法使浏览器下载 sample.txt
文件。
当你访问这个路由,例如 http://localhost:3000/download-file
,浏览器会开始下载 sample.txt
文件。
需要注意的是,res.download()
方法会自动设置响应头 Content-Disposition
为 attachment
,这告诉浏览器下载文件而不是直接在浏览器中显示文件内容。
demo | res.redirect(url)
以下是一个使用 res.redirect(url)
实现 HTTP 重定向的 Express 示例:
const express = require('express');
const app = express();
const port = 3000;
app.get('/', (req, res) => {
res.send('This is the home page.');
});
app.get('/old-page', (req, res) => {
res.redirect('/new-page'); // 重定向到新页面
});
app.get('/new-page', (req, res) => {
res.send('This is the new page.');
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含三个路由:
/
路由是主页。/old-page
路由使用res.redirect(url)
方法实现 HTTP 重定向,将用户重定向到/new-page
。/new-page
路由是新页面。
当你访问 /old-page
路由,例如 http://localhost:3000/old-page
,浏览器会被重定向到 /new-page
,并显示新页面的内容。
需要注意的是,默认情况下,res.redirect()
方法使用 HTTP 302 Found 状态码执行临时重定向。如果需要使用其他状态码,可以将其作为第一个参数传递,例如 res.redirect(301, '/new-page')
实现永久重定向。
demo | res.locals
以下是一个使用 res.locals
在 Express 应用程序中传递数据的示例:
const express = require('express');
const app = express();
const port = 3000;
// 中间件:设置一个全局变量
app.use((req, res, next) => {
res.locals.globalVar = 'Global Variable';
next();
});
// 中间件:为每个请求设置一个特定变量
app.use((req, res, next) => {
res.locals.requestVar = `Request-specific Variable: ${req.url}`;
next();
});
app.get('/', (req, res) => {
res.send(`Home Page: ${res.locals.globalVar} - ${res.locals.requestVar}`);
});
app.get('/about', (req, res) => {
res.send(`About Page: ${res.locals.globalVar} - ${res.locals.requestVar}`);
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含两个路由。在路由之前,我们定义了两个中间件来设置 res.locals
对象的属性。
- 第一个中间件设置了一个全局变量
globalVar
,其值为 “Global Variable”。 - 第二个中间件设置了一个请求特定的变量
requestVar
,其值根据请求的 URL 生成。
然后,我们在两个路由(/
和 /about
)中访问这些局部变量,并将它们包含在响应中。当你访问这些路由时,例如 http://localhost:3000/
或 http://localhost:3000/about
,你会看到包含 globalVar
和 requestVar
的响应。
res.locals
对象在整个请求周期中保持其数据,使得您可以轻松地在路由和中间件之间传递数据。
demo | res.cookie(name, value, options)
以下是一个使用 res.cookie(name, value, options)
设置 Cookie 的 Express 示例:
首先,安装 cookie-parser
中间件:
npm install cookie-parser
接着,创建一个名为 server.js
的文件,内容如下:
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
const port = 3000;
app.use(cookieParser());
app.get('/set-cookie', (req, res) => {
res.cookie('username', 'JohnDoe', { maxAge: 60000, httpOnly: true }); // 设置 Cookie
res.send('Cookie has been set.');
});
app.get('/get-cookie', (req, res) => {
if (req.cookies.username) {
res.send(`Hello, ${req.cookies.username}!`);
} else {
res.send('No cookie found.');
}
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含两个路由。
/set-cookie
路由使用res.cookie(name, value, options)
方法设置名为username
的 Cookie,值为 “JohnDoe”。我们还设置了一些选项,例如maxAge
(Cookie 的有效期)和httpOnly
(只允许服务器访问 Cookie,客户端 JavaScript 无法访问)。/get-cookie
路由检查请求中是否存在名为username
的 Cookie,并根据其存在与否返回不同的响应。
当你访问 /set-cookie
路由,例如 http://localhost:3000/set-cookie
,服务器会设置一个 Cookie。然后访问 /get-cookie
路由,例如 http://localhost:3000/get-cookie
,浏览器会发送包含 Cookie 的请求,服务器将返回包含 Cookie 值的响应。
demo | res.clearCookie(name, options)
以下是一个使用 res.clearCookie(name, options)
清除 Cookie 的 Express 示例:
首先,请确保已安装 cookie-parser
中间件:
npm install cookie-parser
接着,创建一个名为 server.js
的文件,内容如下:
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
const port = 3000;
app.use(cookieParser());
app.get('/set-cookie', (req, res) => {
res.cookie('username', 'JohnDoe', { maxAge: 60000, httpOnly: true }); // 设置 Cookie
res.send('Cookie has been set.');
});
app.get('/get-cookie', (req, res) => {
if (req.cookies.username) {
res.send(`Hello, ${req.cookies.username}!`);
} else {
res.send('No cookie found.');
}
});
app.get('/clear-cookie', (req, res) => {
res.clearCookie('username'); // 清除 Cookie
res.send('Cookie has been cleared.');
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含三个路由。
/set-cookie
路由设置了一个名为username
的 Cookie,值为 “JohnDoe”。/get-cookie
路由检查请求中是否存在名为username
的 Cookie,并根据其存在与否返回不同的响应。/clear-cookie
路由使用res.clearCookie(name, options)
方法清除名为username
的 Cookie。
当你访问 /set-cookie
路由,例如 http://localhost:3000/set-cookie
,服务器会设置一个 Cookie。然后访问 /clear-cookie
路由,例如 http://localhost:3000/clear-cookie
,服务器将清除之前设置的 Cookie。最后,再访问 /get-cookie
路由,例如 http://localhost:3000/get-cookie
,由于之前清除了 Cookie,此时将返回 “No cookie found.”。