前言
在 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/plainres.send('This is plain text content.');});app.get('/json', (req, res) => {res.set('Content-Type', 'application/json'); // 设置响应头 Content-Type 为 application/jsonres.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/jsonconst 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 }); // 设置 Cookieres.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 }); // 设置 Cookieres.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'); // 清除 Cookieres.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.”。
