Appearance
路由确定了应用程序如何响应客户端对特定端点的请求,包含一个 URI(或路径)和一个特定的 HTTP 请求方法(GET、POST 等)。每个路由可以具有一个或多个处理程序函数,这些函数在路由匹配时执行。
一个路由的组成有 请求方法 , 路径 和 回调函数 组成
js
app.<method>(path,callback)
api 介绍
Express 支持与所有 HTTP 请求方法相对应的方法 method 可以包含多种方法例如 'all' | 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options' | 'head'
- all: 匹配所有 HTTP 方法。这个方法可以用于在任何请求方法下处理特定路由的共同逻辑。
- get: 处理 HTTP GET 请求。
- post: 处理 HTTP POST 请求。
- put: 处理 HTTP PUT 请求。
- delete: 处理 HTTP DELETE 请求。
- patch: 处理 HTTP PATCH 请求。
- options: 处理 HTTP OPTIONS 请求。
- head: 处理 HTTP HEAD 请求。
path 路由参数格式 遵循path-to-regexp ,常见一些格式可以是字符窜、正则表达式、数组
类型 | 示例 | 描述 |
---|---|---|
字符串 | '/users/:id' | 表示一个包含动态参数的路由路径,如:/users/123 |
正则表达式 | /^\/users\/(\d+)$/ | 使用正则表达式来匹配路由路径,如:匹配 /users/123 ,但不匹配 /users/abc |
数组(字符串) | ['/users', '/users/:id'] | 将多个路由路径的处理函数组合在一起,如:匹配 /users 和 /users/123 |
数组(正则表达式) | [/^/users$/, /^/users/(\d+)$/ ] | 将多个正则表达式的处理函数组合在一起,如:匹配 /users 和 /users/123 ,但不匹配/users/abc |
callback 回调函数函数里面的参数有 ,请求对象(request对象)、响应对象(response对象)、next函数(在express中定义的用于执行下一个中间件的函数)
属性/方法 | 参数 | 解释 |
---|---|---|
req.body | 包含 POST 请求体中提交的数据的对象。在使用中间件解析请求体后可用。 | |
req.cookies | 包含解析的 cookies 的对象。会自动解析 HTTP 请求中的 cookie 字段。 | |
req.get(header) | header | 获取指定请求头的值。如果请求头存在多个值,则返回第一个值。 |
req.header(header) | header | 获取指定请求头的值。如果请求头存在多个值,则返回以逗号分隔的字符串。 |
req.hostname | 返回主机名,如 "example.com"。 | |
req.ip | 返回客户端的 IP 地址。 | |
req.path | 返回 URL 的路径部分,如 "/user"。 | |
req.params | 包含以冒号标记的路由参数的对象。例如,在路由路径 /user/:id 中,如果一个请求的 URL 为/user/123,则 req.params 拥有一个属性 id,其值为 "123"。 | |
req.protocol | 返回请求协议,如 "http" 或 "https"。 | |
req.query | 包含 URL 查询参数的对象。例如,在 URL "/user?id=123" 中, req.query 拥有一个属性 id,其值为 "123"。 | |
req.secure | 如果请求通过 HTTPS 协议,则返回 true。 | |
req.url | 返回完整的 URL,包括查询参数和哈希部分。 | |
req.xhr | 如果请求通过 AJAX 发起,则返回 true。 |
属性/方法 | 参数 | 解释 |
---|---|---|
res.append(field, value) | field, value | 在响应头中添加一个值。 |
res.cookie(name, value, options) | name, value, options | 设置一个 HTTP cookie。 |
res.clearCookie(name, options) | name, options | 删除一个 HTTP cookie。 |
res.download(path, [filename], [options], [callback]) | path, filename, options, callback | 提供文件下载。 |
res.end([data], [encoding]) | data, encoding | 结束响应流,并发送响应数据。如果提供了数据,则相当于同时调用 res.write() 和 res.end()。 |
res.format(obj) | obj | 根据请求 Accept 头发送不同的响应格式。 |
res.get(field) | field | 获取响应头中指定字段的值。如果响应头存在多个值,则返回第一个值。 |
res.json([body]) | body | 发送一个 JSON 格式的响应。 |
res.jsonp([body]) | body | 发送一个 JSONP 格式的响应。 |
res.links(links) | links | 发送 Link 标头。 |
res.location(url) | url | 设置 "Location" 响应头,将客户端重定向到指定的 URL。 |
res.redirect([status,] path) | status, path | 将客户端重定向到指定的 URL。 |
res.render(view [, locals] [, callback]) | view, locals, callback | 通过模板引擎渲染模板,并发送响应。 |
res.send([body]) | body | 发送一个 HTTP 响应。针对不同类型的数据采用适当的响应头。 |
res.sendFile(path [, options] [, fn]) | path, options, fn | 发送文件。 |
res.setHeader(name, value) | name, value | 设置响应头的值。 |
res.status(code) | code | 设定 HTTP 响应状态码。 |
res.type(type) | type | 设置 Content-Type 响应头的值。 |
next() 是用于传递请求到下一个 middleware 或者路由处理函数中的一个函数,如果没有执行 next(),那么请求将被阻塞,无法响应客户端。如果传入了参数,则 Express 会认为这是一个错误,并交给内置的错误处理函数处理。如果在中间件函数中调用了 next("some error message"),那么这个请求会被 Express 视为发生了错误,并交给 Express 内置的 error handler 函数处理。
基础案例
js
// 导入express模块
const express = require('express')
// 创建express实例
const app = express()
// 定义路由 首页
app.get('/', (req, res) => {
res.send('Hello World!')
})
// 创建一个登录页
app.get('/user/:id', (req, res) => {
res.send('Hello ' + req.params.id)
})
// 获取请求头
app.head('/head', (req, res) => {})
//匹配所有的请求方法 get post 啥都收到
app.all('/search', (req, res) => {
console.log(11)
res.send('1 秒钟为您找到相关结果约 100,000,000 个')
})
// 此路由路径将匹配 butterfly 和 dragonfly,但是不匹配 butterflyman、dragonfly man 等。
app.get(/.*fly$/, function (req, res) {
res.send('/.*fly$/')
})
//自定义 404 路由 所有都没有匹配到 就是404
app.all('*', (req, res) => {
res.send('<h1>404 Not Found</h1>')
})
app.listen(3000, () => {
console.log('http://localhost:3000')
})
使用next 案例
js
// 导入express模块
const express = require('express')
// 创建express实例
const app = express()
const fn = (req, res, next) => {
console.log('处理完毕下一个')
next()
}
const fn1 = (req, res, next) => {
console.log('我来处理')
res.send('我来处理')
}
app.get('/', fn, fn1)
app.listen(3000, () => {
console.log('http://localhost:3000')
})
api 介绍
method 可以包含多种方法例如 'all' | 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options' | 'head'
- all: 匹配所有 HTTP 方法。这个方法可以用于在任何请求方法下处理特定路由的共同逻辑。
- get: 处理 HTTP GET 请求。
- post: 处理 HTTP POST 请求。
- put: 处理 HTTP PUT 请求。
- delete: 处理 HTTP DELETE 请求。
- patch: 处理 HTTP PATCH 请求。
- options: 处理 HTTP OPTIONS 请求。
- head: 处理 HTTP HEAD 请求。
path 路由参数格式 遵循path-to-regexp ,常见一些格式可以是字符窜、正则表达式、数组
类型 | 示例 | 描述 |
---|---|---|
字符串 | '/users/:id' | 表示一个包含动态参数的路由路径,如:/users/123 |
正则表达式 | /^\/users\/(\d+)$/ | 使用正则表达式来匹配路由路径,如:匹配 /users/123 ,但不匹配 /users/abc |
数组(字符串) | ['/users', '/users/:id'] | 将多个路由路径的处理函数组合在一起,如:匹配 /users 和 /users/123 |
数组(正则表达式) | [/^/users$/, /^/users/(\d+)$/ ] | 将多个正则表达式的处理函数组合在一起,如:匹配 /users 和 /users/123 ,但不匹配/users/abc |
callback 回调函数函数里面的参数有 ,请求对象(request对象)、响应对象(response对象)、next函数(在express中定义的用于执行下一个中间件的函数)
属性/方法 | 参数 | 解释 |
---|---|---|
req.body | 包含 POST 请求体中提交的数据的对象。在使用中间件解析请求体后可用。 | |
req.cookies | 包含解析的 cookies 的对象。会自动解析 HTTP 请求中的 cookie 字段。 | |
req.get(header) | header | 获取指定请求头的值。如果请求头存在多个值,则返回第一个值。 |
req.header(header) | header | 获取指定请求头的值。如果请求头存在多个值,则返回以逗号分隔的字符串。 |
req.hostname | 返回主机名,如 "example.com"。 | |
req.ip | 返回客户端的 IP 地址。 | |
req.path | 返回 URL 的路径部分,如 "/user"。 | |
req.params | 包含以冒号标记的路由参数的对象。例如,在路由路径 /user/:id 中,如果一个请求的 URL 为/user/123,则 req.params 拥有一个属性 id,其值为 "123"。 | |
req.protocol | 返回请求协议,如 "http" 或 "https"。 | |
req.query | 包含 URL 查询参数的对象。例如,在 URL "/user?id=123" 中, req.query 拥有一个属性 id,其值为 "123"。 | |
req.secure | 如果请求通过 HTTPS 协议,则返回 true。 | |
req.url | 返回完整的 URL,包括查询参数和哈希部分。 | |
req.xhr | 如果请求通过 AJAX 发起,则返回 true。 |
属性/方法 | 参数 | 解释 |
---|---|---|
res.append(field, value) | field, value | 在响应头中添加一个值。 |
res.cookie(name, value, options) | name, value, options | 设置一个 HTTP cookie。 |
res.clearCookie(name, options) | name, options | 删除一个 HTTP cookie。 |
res.download(path, [filename], [options], [callback]) | path, filename, options, callback | 提供文件下载。 |
res.end([data], [encoding]) | data, encoding | 结束响应流,并发送响应数据。如果提供了数据,则相当于同时调用 res.write() 和 res.end()。 |
res.format(obj) | obj | 根据请求 Accept 头发送不同的响应格式。 |
res.get(field) | field | 获取响应头中指定字段的值。如果响应头存在多个值,则返回第一个值。 |
res.json([body]) | body | 发送一个 JSON 格式的响应。 |
res.jsonp([body]) | body | 发送一个 JSONP 格式的响应。 |
res.links(links) | links | 发送 Link 标头。 |
res.location(url) | url | 设置 "Location" 响应头,将客户端重定向到指定的 URL。 |
res.redirect([status,] path) | status, path | 将客户端重定向到指定的 URL。 |
res.render(view [, locals] [, callback]) | view, locals, callback | 通过模板引擎渲染模板,并发送响应。 |
res.send([body]) | body | 发送一个 HTTP 响应。针对不同类型的数据采用适当的响应头。 |
res.sendFile(path [, options] [, fn]) | path, options, fn | 发送文件。 |
res.setHeader(name, value) | name, value | 设置响应头的值。 |
res.status(code) | code | 设定 HTTP 响应状态码。 |
res.type(type) | type | 设置 Content-Type 响应头的值。 |
next() 是用于传递请求到下一个 middleware 或者路由处理函数中的一个函数,如果没有执行 next(),那么请求将被阻塞,无法响应客户端。如果传入了参数,则 Express 会认为这是一个错误,并交给内置的错误处理函数处理。如果在中间件函数中调用了 next("some error message"),那么这个请求会被 Express 视为发生了错误,并交给 Express 内置的 error handler 函数处理。
关于匹配规则
路由路径与请求方法结合,定义了可以进行请求的端点。路由路径可以是字符串,字符串模式或正则表达式。 字符?,+,*,和()是他们的正则表达式的对应的子集。连字符(-)和点(.)由基于字符串的路径按字面意义进行解释。 如果您需要在路径字符串中使用美元字符(),请将其转义 ( [ 并括在和中 ] ) 。例如,“ / d a t a / 在路径字符串中使用美元字符(),请将其转义([并括在和中])。例如,“ /data/在路径字符串中使用美元字符(),请将其转义([并括在和中])。例如,“/data/book”处用于请求的路径字符串将为“ /data/([$])book”。
Express使用path-to-regexp来匹配路由路径;有关定义路由路径的所有可能性,请参见正则表达式路径文档。Express Route Tester尽管不支持模式匹配,但却是用于测试基本Express路由的便捷工具。
以下是一些基于字符串的路由路径示例。 此路由路径会将请求匹配到根路由/。
js
app.get('/', function (req, res) {
res.send('root')
})
此路由路径会将请求匹配到/about。
js
app.get('/about', function (req, res) {
res.send('about')
})
此路由路径会将请求匹配到/random.text。
js
app.get('/random.text', function (req, res) {
res.send('random.text')
})
以下是一些基于字符串模式的路由路径示例。此路由路径将与acd和匹配abcd。
js
app.get('/ab?cd', function (req, res) {
res.send('ab?cd')
})
这条路线的路径将会匹配abcd,abbcd,abbbcd,等等。
js
app.get('/ab+cd', function (req, res) {
res.send('ab+cd')
})
这条路线的路径将会匹配abcd,abxcd,abRANDOMcd,ab123cd,等。
js
app.get('/ab*cd', function (req, res) {
res.send('ab*cd')
})
此路由路径将与/abe和匹配/abcde。
js
app.get('/ab(cd)?e', function (req, res) {
res.send('ab(cd)?e')
})
这条路线的路径将匹配butterfly和dragonfly,但不butterflyman,dragonflyman等。
js
app.get(/.*fly$/, function (req, res) {
res.send('/.*fly$/')
})
获取路由值
路由参数被命名为 URL 段,用于捕获 URL 中在其位置处指定的值。捕获的值将填充到 req.params 对象中,并将路径中指定的 route 参数的名称作为其各自的键。
js
Route path: /users/:userId/books/:bookId
Request URL: http://localhost:3000/users/34/books/8989
req.params: { "userId": "34", "bookId": "8989" }
要使用路由参数定义路由,只需在路由路径中指定路由参数,如下所示。
js
app.get('/users/:userId/books/:bookId', function (req, res) {
res.send(req.params)
})
路径参数的名称必须由“文字字符”([A-Za-z0-9_])组成。由于连字符(-)和点(.)是按字面解释的,因此可以将它们与路由参数一起使用,以实现有用的目的。
js
Route path: /plantae/:genus.:species
Request URL: http://localhost:3000/plantae/Prunus.persica
req.params: { "genus": "Prunus", "species": "persica" }
js
Route path: /flights/:from-:to
Request URL: http://localhost:3000/flights/LAX-SFO
req.params: { "from": "LAX", "to": "SFO" }
要更好地控制可以由 route 参数匹配的确切字符串,可以在括号(())后面附加一个正则表达式:
js
Route path: /user/:userId(\d+)
Request URL: http://localhost:3000/user/42
req.params: {"userId": "42"}
由于正则表达式通常是文字字符串的一部分,因此请确保\使用其他反斜杠对所有字符进行转义,例如\d+。在Express 4.x中,不以常规方式解释正则表达式中的字符。解决方法是,使用{0,}代替。这可能会在Express 5中修复。
基础案例
js
// 导入express模块
const express = require('express')
// 创建express实例
const app = express()
// 定义路由 首页
app.get('/', (req, res) => {
res.send('Hello World!')
})
// 创建一个登录页
app.get('/user/:id', (req, res) => {
res.send('Hello ' + req.params.id)
})
// 获取请求头
app.head('/head', (req, res) => {})
//匹配所有的请求方法 get post 啥都收到
app.all('/search', (req, res) => {
console.log(11)
res.send('1 秒钟为您找到相关结果约 100,000,000 个')
})
// 此路由路径将匹配 butterfly 和 dragonfly,但是不匹配 butterflyman、dragonfly man 等。
app.get(/.*fly$/, function (req, res) {
res.send('/.*fly$/')
})
//自定义 404 路由 所有都没有匹配到 就是404
app.all('*', (req, res) => {
res.send('<h1>404 Not Found</h1>')
})
app.listen(3000, () => {
console.log('http://localhost:3000')
})
使用next 案例
js
// 导入express模块
const express = require('express')
// 创建express实例
const app = express()
const fn = (req, res, next) => {
console.log('处理完毕下一个')
next()
}
const fn1 = (req, res, next) => {
console.log('我来处理')
res.send('我来处理')
}
app.get('/', fn, fn1)
app.listen(3000, () => {
console.log('http://localhost:3000')
})
获取请求参数的案例
express 框架封装了一些 API 来方便获取请求报文中的数据,并且兼容原生 HTTP 模块的获取方式
js
// 导入express模块
const express = require('express')
// 创建express实例
const app = express()
app.get('/', (req,res ) => {
//1. 获取报文的方式与原生 HTTP 获取方式是兼容的
console.log(req.method) // GET
console.log(req.url) // /
console.log(req.httpVersion) // 1.1
/**
{
'user-agent': 'PostmanRuntime/7.32.2',
accept: '*\/*',
'postman-token': '8a1d3aeb-db2b-443a-8555-5bbac9db285f',
host: 'localhost:3000',
'accept-encoding': 'gzip, deflate, br',
connection: 'keep-alive'
}
*/
console.log(req.headers)
//2. express 独有的获取报文的方式
//获取查询字符串 根据连接拼接对象
console.log(req.query) // {}
// 获取指定的请求头
console.log(req.get('host'))
res.send('你是谁')
})
app.listen(3000, () => {
console.log('http://localhost:3000')
})
设置响应
express 框架封装了一些 API 来方便给客户端响应数据,并且兼容原生 HTTP 模块的获取方式
js
//获取请求的路由规则
app.get('/response', (req, res) => {
//1. express 中设置响应的方式兼容 HTTP 模块的方式
res.statusCode = 404
res.statusMessage = 'xxx'
res.setHeader('abc', 'xyz')
res.write('响应体')
res.end('xxx')
//2. express 的响应方法
res.status(500) //设置响应状态码
res.set('xxx', 'yyy') //设置响应头
res.send('中文响应不乱码') //设置响应体
//连贯操作
res.status(404).set('xxx', 'yyy').send('你好朋友')
//3. 其他响应
res.redirect('http://atguigu.com') //重定向
res.download('./package.json') //下载响应
res.json() //响应 JSON
res.sendFile(__dirname + '/home.html') //响应文件内容
})
链式调用
js
app.route('/book')
.get(function(req, res) {
res.send('Get a random book');
})
.post(function(req, res) {
res.send('Add a book');
})
.put(function(req, res) {
res.send('Update the book');
});