0 REST.Client插件
用于在vscode中构造请求
新建以.http
为后缀的文件:
1
2
3
4
5
6
7
8
9
10
11
|
@url=http://localhost:8080 --- @用于定义变量,{{}}使用此变量
### --- 以###作为请求分割符号
get {{url}}/users --- 注意空格
###
post {{url}}
Content-Type: application/json
--- 请求头与消息体直接有空行
{
"username": "gsq",
"age": 19
}
|
1 express.xxx
共7个api,主要是一些内置的中间件,例如用来自动处理不同类型的请求体数据
1.1 express.json()
以监听消息体中数据流data事件的方式,拿到全部的json数据并自动解析成对象,放到request.body中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
const express = require('express')
const app = express()
// 尝试将此中间件注释后,观察控制台打印内容
app.use(express.json())
app.use((req,res,next)=>{
console.log(req.body)
res.send('aaa')
next()
})
app.listen(8080,()=>{
console.log('listening 8080...')
})
|
1.2 express.static()
指定静态资源路径,用户请求的静态数据首先从指定路径寻找,优先级高于其他中间件
1
2
3
4
5
6
7
8
9
10
11
|
...
// 指定静态资源目录,如果在xxx目录中找到了就发送给浏览器,如果没有就next()
app.use(express.static('xxx'))
app.use((req,res,next)=>{
res.send('aaa')
next()
})
...
// 在.http文件中,构造请求静态资源
get {{url}}/index.html
|
1.3 express.Router()
实例化一个mini-app
,拥有app的部分api,方便路由管理与配置,具体用法见第五章节
2 app.xxx
共22个api,主要负责应用设置(如模板配置、中间件、挂载路由等)
2.1 app.use()
- 将指定的中间件功能挂载到指定的路径上;当请求路径的基础与路径匹配时,中间件功能将被执行。
- 接收两个参数,第一个是挂载点(可选),第二个是中间件(函数)。中间件根据参数的多少决定是哪种类型:三个参数(req,res,next)为RequestHandler,四个参数(error,req,res,next)为错误处理(ErrorRequestHandler)。
- app中最基本的api之一,
app.get()
、app.post()
、app.delete()
、app.put()
等实际上都是app.use()
的语法糖
2.2 app.set()
- 能够对应用进行一些特殊配置(此时要放在全部中间件的最上方)
1
2
3
4
5
6
7
8
9
10
11
12
13
|
...
// 设置路径大小写敏感度
app.set('case sensitive routing', true)
// 设置render视图的路径,默认为views
app.set('views', 'xxx')
// 设置render的引擎
app.set('view engine', 'ejs')
app.get('/testview', (rep,res,next)=>{
res.render('index', { title:'guosenquan' })
next()
})
...
|
Property |
Type |
Description |
Default |
case sensitive routing |
Boolean |
对请求路径大小写是否敏感,如/STYLE.css和/style.css |
undefined(false) |
views |
String or Array |
指定render视图的路径 |
‘views’ |
view engine |
String |
指定render视图模板的引擎 |
undefined |
strict routing |
Boolean |
请求路径是否开启严格模式,例如'/foo’和'/foo/‘不表示同一路径 |
undefined |
- 也可以设置一个变量,这个变量能够被
app.get(name)
获取到
1
2
3
4
5
6
7
8
|
...
app.set('title', 'gsq')
app.get('/testset', (req, res, next) => {
res.render('index', { title: app.get('title') })
next()
})
...
|
2.3 app.local
app.locals.xxx
定义局部变量,其他中间件可以通过req.app.locals.xxx
来获取
1
2
3
4
5
6
7
8
9
|
...
// local一个局部变量
app.locals.title = 'gsq'
app.get('/testlocal', (req, res, next) => {
res.render('index', { title: req.app.locals.title })
next()
})
...
|
2.4 app.get()
- app.get()只有一个参数(字符串)时,表示获取set的值
1
2
3
4
5
6
|
app.get('title')
// => undefined
app.set('title', 'My Site')
app.get('title')
// => "My Site"
|
- app.get(‘路径’,fn)表示处理get请求
1
2
3
4
|
app.get('/style.css', (rep, res, next) => {
res.send('style.css')
next()
})
|
3 req.xxx
共28个api,用来操作请求
3.1 req.app
3.2 req.body
3.3 req.method
3.4 req.params
- 此属性是一个对象,包含映射到指定路由“参数”的属性。例如,如果你有
route /user/:name
,那么" name “属性是可用的req.params.name
。该对象默认为{}
1
2
3
4
5
6
7
8
9
10
11
12
|
app.use('/user/:id',(req,res,next)=>{
res.send(req.params)
next()
})
// app.http中构造请求
###
get {{url}}/user/1
// => { "id" : "1" }
// 注意,params只能读取路由中定义的字段,例如
get {{url}}/user/1?name=gsq
// 仍返回{ "id" : "1" }
// 同样在请求body中的内容也是读取不到的
|
3.5 req.query
- 获取上文中路由后面的(‘?’后面的)查询参数,可以使用
req.query
,express会将查询参数封装为query对象:
1
2
3
4
5
6
7
8
9
|
app.use('/user/:id',(req,res,next)=>{
res.send(req.query)
next()
})
// app.http中构造请求
###
get {{url}}/user/1?name=gsq&age=15
// => { "name" : "gsq", "age" : "15" }
// 同样在请求body中的内容也是读取不到的
|
3.6 req.get()
1
|
req.get('Content-Type')
|
3.7 req.param()
1
2
3
4
|
app.use('/user/:id',(req,res,next)=>{
res.send(req.param('name'))
next()
})
|
- 此方法被遗弃,express推荐使用
req.query
结合req.params
来实现查询参数的获取。
3.8 req.range()
分块下载
4 res.xxx
共24个api,用来操作响应
4.1 res.set()
- 添加响应头参数。如果一次添加多行header,使用
object
的形式传参
1
2
3
4
5
6
7
|
res.set('Content-Type', 'text/plain')
res.set({
'Content-Type': 'text/plain',
'Content-Length': '123',
ETag: '12345'
})
|
4.2 res.append()
- 将指定的值
附加
到HTTP响应报头字段。如果字段还没有set,它将使用指定的值创建header。value参数可以是字符串或数组。
1
2
3
|
res.append('Link', ['<http://localhost/>', '<http://localhost:3000/>'])
res.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly')
res.append('Warning', '199 Miscellaneous warning')
|
- 注意:在res.append()之后调用res.set()将重置之前设置的头文件值。
4.3 res.get()
-
根据请求对象上的Accept字段存在时进行内容协商。它使用req. accept()根据根据质量值排序的可接受类型选择请求的处理程序。如果未指定Accept字段,则调用第一个回调。当没有找到匹配,服务器响应406 “Not Acceptable”,或调用默认回调。
-
在选择回调时设置Content-Type响应头。但是,您可以在回调中使用res.set()或res.type()等方法更改此参数。
-
下面的例子将在Accept报头字段设置为"application/json"
或"*/json"
时响应{"message": "hey"}
(但是如果是"*/*"
,则响应将是"hey”)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
res.format({
'text/plain': function () {
res.send('hey')
},
'text/html': function () {
res.send('<p>hey</p>')
},
'application/json': function () {
res.send({ message: 'hey' })
},
default: function () {
// log the request and respond with 406
res.status(406).send('Not Acceptable')
}
})
// app,http构造请求
###
get {{url}}/test
Accept: text/plain
|
4.5 res.location()
- 设置响应头的location字段,表示重定向后的路由,一般配合状态码301,302或307等使用会自动跳转。
1
2
3
4
5
|
app.use('/oldroute',(req, res, next) => {
res.status(301).location('/newroute')
res.end()// 要加上响应关闭的方法
next()
})
|
4.6 res.redirect()
1
2
3
4
|
app.use('/oldroute',(req, res, next) => {
res.redirect('/newroute')
next()
})
|
4.7 res.render()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// 指定渲染模板的路径和模板引擎
app.set('views', 'xxx')
app.set('view engine', 'ejs')
// 向客户端发送渲染后的视图
res.render('index')
// 如果有回调函数, 模板就只能在回调中用send发送
res.render('index', function (err, html) {
res.send(html)
})
// 向渲染的页面中传入一个变量
res.render('user', { name: 'Tobi' }, function (err, html) {
// ...
})
|
4.8 res.send()
4.9 res.sendFile()
- 发送到客户端的响应体数据,可以手动配置响应头等内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
app.get('/file/:name', function (req, res, next) {
var options = {
root: path.join(__dirname, 'public'),
dotfiles: 'deny',
headers: {
'x-timestamp': Date.now(),
'x-sent': true
}
}
var fileName = req.params.name
res.sendFile(fileName, options, function (err) {
if (err) {
next(err)
} else {
console.log('Sent:', fileName)
}
})
})
|
5 router.xxx
1
2
3
4
|
app.use('/users', (req, res, next) => {})
app.use('/users/:id', (req, res, next) => {})
app.use('/users/:id/edit', (req, res, next) => {})
...
|
- 为方便路由的组织管理以及后期维护,可以将路由逻辑拆出来,放至
routes
文件夹下。新建user.js
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
const express = require('express')
// 用express实例化router
const router = express.Router()
// 路径可以去掉路由前缀users
router.get('/', (req, res, next) => {
res.send('获取了全部users')
next()
})
router.get('/:id', (req, res, next) => {
res.send(`获取了id=${req.params.id}用户`)
next()
})
router.get('/:id/edit', (req, res, next) => {
res.send(`对id为${req.params.id}的用户进行编辑`)
next()
})
// 导出users路由对象
module.exports = router
|
1
2
3
4
5
6
7
|
const express = require('express')
const app = express()
// 引入users路由对象
const users = require('./routes/users')
// 挂载路由
app.use('/users', users)
app.listen(8080)
|