前言

在 Express 中,请求对象(通常表示为 req)和响应对象(通常表示为 res)是处理 HTTP 请求和响应的关键组件。它们分别基于 Node.js 原生的 http.IncomingMessagehttp.ServerResponse 对象,但提供了更多有用的方法和属性。本文主要介绍的是 Express 的「响应对象」response。

参考资料

响应对象(res)

Express 的 res(响应)对象代表服务器发回给客户端的 HTTP 响应。res 对象提供了一系列方法和属性,允许您轻松地构建和发送 HTTP 响应。它包含了用于构建响应的方法,如设置响应头、状态码、发送响应主体等。通过使用这些请求对象和响应对象的属性和方法,开发者可以在 Express 中轻松地处理各种 HTTP 请求和构建响应。以下是一些我们可能需要了解的主要方法和属性:

  1. res.status(code): 设置 HTTP 响应状态码。例如,res.status(200) 表示成功的响应,res.status(404) 表示找不到资源。
  2. res.set(header, value): 设置一个 HTTP 响应头。例如,res.set('Content-Type', 'application/json') 设置响应内容类型为 JSON。
  3. res.get(header): 获取当前设置的 HTTP 响应头值。例如,res.get('Content-Type') 获取响应内容类型。
  4. res.send(body): 发送 HTTP 响应,并根据提供的响应体自动设置内容类型和长度。这是最常用的发送响应的方法。
  5. res.json(obj): 发送 JSON 格式的 HTTP 响应。这个方法会自动设置 Content-Typeapplication/json
  6. res.sendFile(path): 发送指定路径的文件作为 HTTP 响应。这对于静态文件服务非常有用。
  7. res.download(path): 发送指定路径的文件,并提示浏览器下载文件。
  8. res.redirect(url): 发送一个重定向响应,将客户端重定向到另一个 URL。
  9. res.locals: 一个对象,允许您在响应期间存储局部变量。这些变量可以在其他中间件和路由处理程序中访问。
  10. res.cookie(name, value, options): 设置一个 Cookie。您可以传递一个选项对象来配置 Cookie 的属性,如过期时间、路径、域等。
  11. 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 示例:

  1. const express = require('express');
  2. const app = express();
  3. const port = 3000;
  4. app.get('/success', (req, res) => {
  5. res.status(200).send('Success!'); // 设置状态码为 200,表示成功的响应
  6. });
  7. app.get('/created', (req, res) => {
  8. res.status(201).send('Resource created.'); // 设置状态码为 201,表示资源已成功创建
  9. });
  10. app.get('/bad-request', (req, res) => {
  11. res.status(400).send('Bad Request.'); // 设置状态码为 400,表示客户端请求有问题
  12. });
  13. app.get('/not-found', (req, res) => {
  14. res.status(404).send('Resource not found.'); // 设置状态码为 404,表示找不到请求的资源
  15. });
  16. app.listen(port, () => {
  17. console.log(`Server running at http://localhost:${port}`);
  18. });

在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含四个路由。每个路由都使用 res.status(code) 方法设置了不同的 HTTP 响应状态码,然后发送了一个简单的响应消息。

当我们访问这些不同的路由时,例如 http://localhost:3000/successhttp://localhost:3000/not-found,你会看到服务器返回的响应状态码和对应的消息。

demo | res.set(header, value)

以下是一个使用 res.set(header, value) 设置 HTTP 响应头的 Express 示例:

  1. const express = require('express');
  2. const app = express();
  3. const port = 3000;
  4. app.get('/plain-text', (req, res) => {
  5. res.set('Content-Type', 'text/plain'); // 设置响应头 Content-Type 为 text/plain
  6. res.send('This is plain text content.');
  7. });
  8. app.get('/json', (req, res) => {
  9. res.set('Content-Type', 'application/json'); // 设置响应头 Content-Type 为 application/json
  10. res.send({ message: 'This is JSON content.' });
  11. });
  12. app.get('/custom-header', (req, res) => {
  13. res.set('X-Custom-Header', 'CustomHeaderValue'); // 设置一个自定义响应头
  14. res.send('Response with a custom header.');
  15. });
  16. app.listen(port, () => {
  17. console.log(`Server running at http://localhost:${port}`);
  18. });

在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含三个路由。每个路由都使用 res.set(header, value) 方法设置了不同的 HTTP 响应头。

  1. /plain-text 路由设置 Content-Typetext/plain,表示响应内容是纯文本。
  2. /json 路由设置 Content-Typeapplication/json,表示响应内容是 JSON 格式。
  3. /custom-header 路由设置了一个自定义响应头 X-Custom-Header,其值为 CustomHeaderValue

当你访问这些不同的路由时,例如 http://localhost:3000/plain-text 或 `http://localhost:3000/json

demo | res.get(header)

以下是一个使用 res.get(header) 获取 HTTP 响应头的 Express 示例:

  1. const express = require('express');
  2. const app = express();
  3. const port = 3000;
  4. app.get('/check-content-type', (req, res) => {
  5. res.set('Content-Type', 'application/json'); // 设置响应头 Content-Type 为 application/json
  6. const contentType = res.get('Content-Type'); // 获取响应头 Content-Type 的值
  7. console.log('Content-Type:', contentType); // 打印 Content-Type 的值
  8. res.send({ message: 'The Content-Type header has been set and retrieved.' });
  9. });
  10. app.get('/check-custom-header', (req, res) => {
  11. res.set('X-Custom-Header', 'CustomHeaderValue'); // 设置一个自定义响应头
  12. const customHeader = res.get('X-Custom-Header'); // 获取自定义响应头 X-Custom-Header 的值
  13. console.log('X-Custom-Header:', customHeader); // 打印 X-Custom-Header 的值
  14. res.send('The custom header has been set and retrieved.');
  15. });
  16. app.listen(port, () => {
  17. console.log(`Server running at http://localhost:${port}`);
  18. });

在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含两个路由。每个路由都使用 res.set(header, value) 方法设置了 HTTP 响应头,然后使用 res.get(header) 方法获取并打印这些响应头的值。

  1. /check-content-type 路由设置 Content-Typeapplication/json,然后获取并打印 Content-Type 的值。
  2. /check-custom-header 路由设置了一个自定义响应头 X-Custom-Header,其值为 CustomHeaderValue,然后获取并打印 X-Custom-Header 的值。

当你访问这些不同的路由时,例如 http://localhost:3000/check-content-typehttp://localhost:3000/check-custom-header,你会在服务器控制台看到打印出的响应头的值。

demo | res.send(body)

以下是一个使用 res.send(body) 发送不同类型 HTTP 响应体的 Express 示例:

  1. const express = require('express');
  2. const app = express();
  3. const port = 3000;
  4. app.get('/send-text', (req, res) => {
  5. res.send('This is a plain text response.'); // 发送纯文本响应
  6. });
  7. app.get('/send-html', (req, res) => {
  8. res.send('<h1>This is an HTML response.</h1>'); // 发送 HTML 响应
  9. });
  10. app.get('/send-json', (req, res) => {
  11. res.send({ message: 'This is a JSON response.' }); // 发送 JSON 响应
  12. });
  13. app.listen(port, () => {
  14. console.log(`Server running at http://localhost:${port}`);
  15. });

在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含三个路由。每个路由都使用 res.send(body) 方法发送不同类型的响应体。

  1. /send-text 路由发送纯文本响应。
  2. /send-html 路由发送 HTML 响应。
  3. /send-json 路由发送 JSON 响应。

当你访问这些不同的路由时,例如 http://localhost:3000/send-texthttp://localhost:3000/send-htmlhttp://localhost:3000/send-json,你会看到服务器返回的不同类型的响应体。

需要注意的是,res.send() 方法会根据提供的响应体自动设置 Content-TypeContent-Length 响应头。

demo | res.json(obj)

以下是一个使用 res.json(obj) 发送 JSON 格式响应的 Express 示例:

  1. const express = require('express');
  2. const app = express();
  3. const port = 3000;
  4. app.get('/json-object', (req, res) => {
  5. const responseObject = { message: 'This is a JSON object response.' };
  6. res.json(responseObject); // 发送 JSON 对象响应
  7. });
  8. app.get('/json-array', (req, res) => {
  9. const responseArray = [
  10. { id: 1, name: 'Alice' },
  11. { id: 2, name: 'Bob' },
  12. ];
  13. res.json(responseArray); // 发送 JSON 数组响应
  14. });
  15. app.listen(port, () => {
  16. console.log(`Server running at http://localhost:${port}`);
  17. });

在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含两个路由。每个路由都使用 res.json(obj) 方法发送 JSON 格式的响应体。

  1. /json-object 路由发送 JSON 对象响应。
  2. /json-array 路由发送 JSON 数组响应。

当你访问这些不同的路由时,例如 http://localhost:3000/json-objecthttp://localhost:3000/json-array,你会看到服务器返回的 JSON 格式的响应体。

需要注意的是,res.json() 方法会自动设置 Content-Type 响应头为 application/json

demo | res.sendFile(path)

以下是一个使用 res.sendFile(path) 发送文件作为响应的 Express 示例:

首先,我们创建一个名为 public 的文件夹,然后在其中创建一个名为 image.jpg 的图片文件。

接着,创建一个名为 server.js 的文件,内容如下:

  1. const express = require('express');
  2. const app = express();
  3. const port = 3000;
  4. const path = require('path');
  5. app.get('/send-image', (req, res) => {
  6. const imagePath = path.join(__dirname, 'public', 'image.jpg');
  7. res.sendFile(imagePath); // 发送图片文件作为响应
  8. });
  9. app.get('/send-html', (req, res) => {
  10. const htmlPath = path.join(__dirname, 'public', 'index.html');
  11. res.sendFile(htmlPath); // 发送 HTML 文件作为响应
  12. });
  13. app.listen(port, () => {
  14. console.log(`Server running at http://localhost:${port}`);
  15. });

在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含两个路由。每个路由都使用 res.sendFile(path) 方法发送文件作为响应。

  1. /send-image 路由发送名为 image.jpg 的图片文件作为响应。
  2. /send-html 路由发送名为 index.html 的 HTML 文件作为响应。

在这个示例中,我们使用了 path.join() 方法来构建文件路径,以确保在不同操作系统上能正确处理文件路径。

当你访问这些不同的路由时,例如 http://localhost:3000/send-imagehttp://localhost:3000/send-html,你会看到服务器返回的文件作为响应。

demo | res.download(path)

以下是一个使用 res.download(path) 使浏览器下载文件的 Express 示例:

首先,我们创建一个名为 files 的文件夹,然后在其中创建一个名为 sample.txt 的文本文件。

接着,创建一个名为 server.js 的文件,内容如下:

  1. const express = require('express');
  2. const app = express();
  3. const port = 3000;
  4. const path = require('path');
  5. app.get('/download-file', (req, res) => {
  6. const filePath = path.join(__dirname, 'files', 'sample.txt');
  7. res.download(filePath); // 使浏览器下载 sample.txt 文件
  8. });
  9. app.listen(port, () => {
  10. console.log(`Server running at http://localhost:${port}`);
  11. });

在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含一个路由。这个路由使用 res.download(path) 方法使浏览器下载 sample.txt 文件。

当你访问这个路由,例如 http://localhost:3000/download-file,浏览器会开始下载 sample.txt 文件。

需要注意的是,res.download() 方法会自动设置响应头 Content-Dispositionattachment,这告诉浏览器下载文件而不是直接在浏览器中显示文件内容。

demo | res.redirect(url)

以下是一个使用 res.redirect(url) 实现 HTTP 重定向的 Express 示例:

  1. const express = require('express');
  2. const app = express();
  3. const port = 3000;
  4. app.get('/', (req, res) => {
  5. res.send('This is the home page.');
  6. });
  7. app.get('/old-page', (req, res) => {
  8. res.redirect('/new-page'); // 重定向到新页面
  9. });
  10. app.get('/new-page', (req, res) => {
  11. res.send('This is the new page.');
  12. });
  13. app.listen(port, () => {
  14. console.log(`Server running at http://localhost:${port}`);
  15. });

在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含三个路由:

  1. / 路由是主页。
  2. /old-page 路由使用 res.redirect(url) 方法实现 HTTP 重定向,将用户重定向到 /new-page
  3. /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 应用程序中传递数据的示例:

  1. const express = require('express');
  2. const app = express();
  3. const port = 3000;
  4. // 中间件:设置一个全局变量
  5. app.use((req, res, next) => {
  6. res.locals.globalVar = 'Global Variable';
  7. next();
  8. });
  9. // 中间件:为每个请求设置一个特定变量
  10. app.use((req, res, next) => {
  11. res.locals.requestVar = `Request-specific Variable: ${req.url}`;
  12. next();
  13. });
  14. app.get('/', (req, res) => {
  15. res.send(`Home Page: ${res.locals.globalVar} - ${res.locals.requestVar}`);
  16. });
  17. app.get('/about', (req, res) => {
  18. res.send(`About Page: ${res.locals.globalVar} - ${res.locals.requestVar}`);
  19. });
  20. app.listen(port, () => {
  21. console.log(`Server running at http://localhost:${port}`);
  22. });

在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含两个路由。在路由之前,我们定义了两个中间件来设置 res.locals 对象的属性。

  1. 第一个中间件设置了一个全局变量 globalVar,其值为 “Global Variable”。
  2. 第二个中间件设置了一个请求特定的变量 requestVar,其值根据请求的 URL 生成。

然后,我们在两个路由(//about)中访问这些局部变量,并将它们包含在响应中。当你访问这些路由时,例如 http://localhost:3000/http://localhost:3000/about,你会看到包含 globalVarrequestVar 的响应。

res.locals 对象在整个请求周期中保持其数据,使得您可以轻松地在路由和中间件之间传递数据。

demo | res.cookie(name, value, options)

以下是一个使用 res.cookie(name, value, options) 设置 Cookie 的 Express 示例:

首先,安装 cookie-parser 中间件:

  1. npm install cookie-parser

接着,创建一个名为 server.js 的文件,内容如下:

  1. const express = require('express');
  2. const cookieParser = require('cookie-parser');
  3. const app = express();
  4. const port = 3000;
  5. app.use(cookieParser());
  6. app.get('/set-cookie', (req, res) => {
  7. res.cookie('username', 'JohnDoe', { maxAge: 60000, httpOnly: true }); // 设置 Cookie
  8. res.send('Cookie has been set.');
  9. });
  10. app.get('/get-cookie', (req, res) => {
  11. if (req.cookies.username) {
  12. res.send(`Hello, ${req.cookies.username}!`);
  13. } else {
  14. res.send('No cookie found.');
  15. }
  16. });
  17. app.listen(port, () => {
  18. console.log(`Server running at http://localhost:${port}`);
  19. });

在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含两个路由。

  1. /set-cookie 路由使用 res.cookie(name, value, options) 方法设置名为 username 的 Cookie,值为 “JohnDoe”。我们还设置了一些选项,例如 maxAge(Cookie 的有效期)和 httpOnly(只允许服务器访问 Cookie,客户端 JavaScript 无法访问)。
  2. /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 中间件:

  1. npm install cookie-parser

接着,创建一个名为 server.js 的文件,内容如下:

  1. const express = require('express');
  2. const cookieParser = require('cookie-parser');
  3. const app = express();
  4. const port = 3000;
  5. app.use(cookieParser());
  6. app.get('/set-cookie', (req, res) => {
  7. res.cookie('username', 'JohnDoe', { maxAge: 60000, httpOnly: true }); // 设置 Cookie
  8. res.send('Cookie has been set.');
  9. });
  10. app.get('/get-cookie', (req, res) => {
  11. if (req.cookies.username) {
  12. res.send(`Hello, ${req.cookies.username}!`);
  13. } else {
  14. res.send('No cookie found.');
  15. }
  16. });
  17. app.get('/clear-cookie', (req, res) => {
  18. res.clearCookie('username'); // 清除 Cookie
  19. res.send('Cookie has been cleared.');
  20. });
  21. app.listen(port, () => {
  22. console.log(`Server running at http://localhost:${port}`);
  23. });

在这个示例中,我们创建了一个简单的 Express 应用程序,其中包含三个路由。

  1. /set-cookie 路由设置了一个名为 username 的 Cookie,值为 “JohnDoe”。
  2. /get-cookie 路由检查请求中是否存在名为 username 的 Cookie,并根据其存在与否返回不同的响应。
  3. /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.”。