Skip to content
快速预览

express路由

✍️ w 🕒 2023-06-06 08:22:52(a year ago) 🔗 B.NodeJS学习 服务端 express

路由确定了应用程序如何响应客户端对特定端点的请求,包含一个 URI(或路径)和一个特定的 HTTP 请求方法(GET、POST 等)。每个路由可以具有一个或多个处理程序函数,这些函数在路由匹配时执行。

一个路由的组成有 请求方法 , 路径 和 回调函数 组成

js
app.<method>(pathcallback)

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');
  });

Released under the MIT License.