express是一款简单的web开发应用框架,这里主要是一些主要api的使用方法和总结记录。
中间件
首先,express的灵魂就是中间件,它能影响到使用者的开发思路,能将请求响应的流程拆分成不同模块进行开发,然后app.use调用(可以一个或多个)。这就是其中间件的的基本特征,然后编写一个中间件也比较简单:
var express = require('express')
var app = express()
var myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}
var Login = function (req, res, next) {
// do something for login
next()
}
app.use(myLogger)
app.use(Login)
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.listen(3000)
上面例子是摘自官方文档的一小段代码。首先app.use()
就是调用中间件(myLogger,Login)的关键,然后(myLogger,Login)函数里有个next回调函数,当调用它时可以执行下一个中间件。不过也可以不写(表示最后一个中间件)或者提前使用res.end()之类的提前结束。
接下来是关于API的一些记录,从express和其子实例,request,response,router
五个主要API入手。
express
导入的express模块可以直接执行,然后生成子实例。但express本身也带有一些方便的方法:
- express.json()
- express.raw()
- express.Router() // 陌生,这里不记录
- express.static()
- express.text()
- express.urlencoded()
当一个请求过来时,其参数有可能放在请求主体里,可以通过request的body、query、params的属性来访问这些参数。但如果请求方法是post,且参数是通过JSON,XML或者就一段文本方式放在主体里传过来,直接拿req.body反而获取不到,需要通过request的on监听data事件,例如
app.post("/a", (req, res, next) => {
req.on("data", (chunk) => {
console.log(chunk.toString())
})
next()
})
然后express就提供了一些内置的中间件,就例如express.json()、express.raw()、express.text(),甚至有解码用的express.urlencoded(),只需在自己代码之前用就可以了。
app.use(express.json())
app.use((req,res,next)=>{
// 自己代码
next()
})
express.static()提供了一个比较方便的方法供请求静态资源,他接受一个root路径和一个对象参数,当访问者访问“/root/xxx.html”时,express会帮我们自动响应响应的“/root/xxx.html”文件,如果没有就会调用next回调进入下一中间件。
express子实例
感觉这个也可以当做是express来记录,但文档也将其分开,那这里也分开记录(部分)。
var express = require('express')
var app = express() // the main app
var admin = express() // the main app
这里用app替代express子实例的叫法
app有两个属性locals、mountPath,一个mount事件,十九个方法。
app.locals作为局部变量可存储对象,这个能一直在应用程序的整个生命周期中保持不变,app存在局部变量也存在,人在塔在!
app.mountpath可以返回不同路径模式的路径数组,例如app和admin同时用get监听“/”路径,那么app.mountpath将可以有效区别request的路径,这和request.baseurl的有点不同。
app.on('mount',callback(parent))也是在两个子实例情况下应用,当mount事件安装在父应用程序上时,该事件将在子应用程序上触发。父应用程序将传递给回调函数。
var admin = express()
var app= express()
admin.on('mount', function (parent) {
// 这里将被执行
console.log('Admin Mounted')
console.log(parent) // refers to the parent app
})
admin.get('/', function (req, res) {
res.send('Admin Homepage')
})
app.use('/admin', admin)
app.get()有两个用法,当你传一个字符串参数时,它会返回上面所说的局部变量locals的相应值。当两个参数(一个字符串和一个回调函数),它就是监听相应路径的get请求方法,这是这个方法基本和post,put,patch,delete,all,METHOD类似的。
app.param([name], callback)是一个有趣的方法,param里如果存在相应的[name]属性,则执行后面的callback。
app.set(name, value)比较特殊,可以存储一些自定义的键值对,但app也提供了一些特别的设置(例如:env,etag,jsonp callback name),可以前往官网查看。
app.use([path,] callback [, callback...])很常见也很重要,第一个参数是路径,之后的就是回调,当匹配到相应路径执行后面的回调,当然是按照先后顺序,多个回调里的函数顺序比下一个中间件执行时机早。callback里有四个参数,形式:
app.use(function ([err,] req, res, next) {
console.error(err.stack)
res.status(500).send('Something broke!')
})
如果使用四个参数,那么它是一个错误处理中间件,否则3个是常规中间件.
Request
request包含了app作为其属性,所以通过req.app来访问app的所有权限。
request.baseUrl可以获得app.use监听的路径。
request.body可以获取请求存储在主体的参数,不过正常情况下都是undefined,所以才需要使用诸如express.json()或的正文解析中间件时进行填充express.urlencoded() 。
request.cookies可以获取请求里的cookie,如果没有返回空对象。
request.hostname可以获取域名,如果你要用得上的话。
request.query和request.params也可以获取参数,但query只需要在路由上写?a=1&b=2
之类的附加值就可以获得,而params需要请求固定设置或路由上设置/user/:name
之类的。
request有一些方法,
req.accepts(types),根据请求的Accept
HTTP标头字段检查指定的内容类型是否可接受,以下三个方法基本也是在设置headers的头部字段
req.acceptsCharsets(charset [,...]),
req.acceptsEncodings(encoding [,...]),
req.acceptsLanguages(lang [, ...])
然后也可以通过req.get(type)来获取某个字段的值,或者req.is(value)判断该value是不是请求过来“Content-Type”的值。
Response
首先说属性,简称Response为res
res也可以访问app,也有个loacals属性(但只能在本次请求周期使用)
res有21个方法,这里挑几个常用的记录:
append(field [, value])用于设置头部的属性和值;
cookie(name, value [, options])用于设置cookie;
clearCookie(name, [, options])用于清除cookie;
res.download(path [, filename] [, options] [, fn])用于响应用户,下载指定的静态文件等;
res.end([data] [, encoding])结束响应,和node的一致;
res.format(object)这个根据请求的accept字段值不同做不同的响应;
res.send([body])用于发送响应,但能发送很多类型的数据,除了文件
res.sendFile(path [, options] [, fn])和send相似,但传送文件,注意path是绝对路径
res.status(code)用于发送状态码,例如403等
res.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly')
res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true })
res.clearCookie('rememberme')
res.download('/report-12345.pdf')
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')
}
})
Router
Router的用法基本和app.use监听某些路由一样,有五个方法:
- router.all()
- router.METHOD()
- router.param()
- router.route()
- router.use()
但从用法上感觉和app.xxx没什么区别!