express的API总共分为五类,分别是Express()、application、request、response、router等。
一、Express()
1. express.json()
内置中间件。由于request.body
的内容基于用户的输入,因此该对象中的所有属性和值都不可信,应在可信之前进行验证。例如,request.body.foo.toString()
可能以多种方式失败,例如 foo
可能不存在或可能不是字符串,并且toString
可能不是函数,而是字符串或其他用户输入。express.json()使用body解析器解析带有JSON负载的传入请求,返回仅解析JSON并且仅查看Content-Type
标头与type
选项匹配的请求的中间件。该解析器接受主体的任何Unicode编码,并支持gzip
和 deflate
编码的自动填充。例:
const express = require('express')
const app = express()
app.use(express.json())
app.use((request,response,next)=>{
console.log(request.body)
response.send('hi');
request.on('data',(chunk)=>{
console..log(chunk.toString())
})
next()
})
上代码中, request.body
会被处理然后打印出来,而 chunk.toString()
则会被忽略,因为返回数据已被上面捕获处理。
2. express.static(root,[options])
该root
参数指定要从其提供静态资源的根目录。该功能通过req.url
与提供的root
目录结合来确定要提供的文件。当找不到文件时,它不会发送404响应,而是调用next()
移至下一个中间件,从而可以进行堆栈和回退。
app.use(express.static('yyy'))
如果在yyy路径找到文件,返回该静态文件,如果没有,调用next()进入下一个中间件。
二、app.xxx
1. app.set(name, value)
设置name
和value
。您可以存储所需的任何值,但是可以使用某些名称来配置服务器的行为。这些特殊名称在应用程序设置表中列出。例:
app.set('case sensitive routing',true)//默认false,资源访问路径是是否对大小写敏感。set必须写在所有中间件的最前面。
app.set('views','test') //设备默认视图的目录为test;
app.set('view engine','pug') //设备默认引擎为pug;
app.get('/style.css',(resquest,response,next)=>{
resquest.send('style.css')
})
上述代码执行中,如果访问路径为xxx/STYLE.css
,将不会得到任何响应.
2. app.get()、app.post()、app.put()、app.delete()
页面被请求时的响应方法。例:
app.get('/test',(req,res,next)=>{
res.send('get /test')
})
app.post('/test',(req,res,next)=>{
res.send('post /test')
})
app.put('/test',(req,res,next)=>{
res.send('put /test')
})
app.delete('/test',(req,res,next)=>{
res.send('delete /test')
})
中间件之间获取参数的方法:
//app.js
const express = require('express')
const app = express()
const fn1 = require('./fn1')
app.locals.title = '这是标题'
app.use(fn1)
//fn1.js
const fn1 = (req,res,next)=>{
res.render('test',{pageTitle:req.app.locals.title}) //app.locals默认附加在req中
}
module.exports = fn1
三、Request.xxx
1. request.params
此属性是一个对象,其中包含映射到命名路由“ parameters”的属性。例如,请求路径/user/:name
,则“ name”属性可以被req.params.name
获取。该对象默认为{}
。例:
// GET /users/1
app.get('/users/:id',(req,res,next)=>{
console.log(req.params) //=> 此处返回{id:1}
})
2. request.path
返回请求路径, 不包含查询字符串。例:
// example.com/users?sort=desc
console.dir(req.path)
// => '/users'
3. request.query
返回每个查询字符串参数的属性。例:
// GET /search?q=tobi+ferret
console.dir(req.query.q)
// => 'tobi ferret'
// GET /shoes?order=desc&shoe[color]=blue&shoe[type]=converse
console.dir(req.query.order)
// => 'desc'
console.dir(req.query.shoe.color)
// => 'blue'
console.dir(req.query.shoe.type)
// => 'converse'
// GET /shoes?color[]=blue&color[]=black&color[]=red
console.dir(req.query.color)
// => ['blue', 'black', 'red']
四、Response.xxx
1. response.set(field [, value])
响应头设置。要一次设置多个字段,请传递一个对象作为参数。例:
res.set('Content-Type', 'text/plain')
res.set({
'Content-Type': 'text/plain',
'Content-Length': '123',
ETag: '12345'
})
它的别名为res.header(field [, value])
。
2. res.format(object)
可以根据请求头的accept值判断返回不同的响应。例:
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')
}
})
3. res.redirect([status,] path)
地址重定向到path。并指定当前status,如果未指定,则status
默认为302。例:
res.redirect('/foo/bar')
res.redirect('http://example.com')
res.redirect(301, 'http://example.com')
res.redirect('../login')
重定向可是指向其他站点网址:
res.redirect('http://google.com')
重定向可以相对于主机名的根目录。例如,如果打开[http://example.com/admin/post/new](http://example.com/admin/post/new)
,则执行以下内容将重定向到URL [http://example.com/admin](http://example.com/admin)
:
res.redirect('/admin')
重定向可以相对于当前URL。例如,从[http://example.com/blog/admin/](http://example.com/blog/admin/)
(注意结尾的斜杠),以下内容将重定向到URL [http://example.com/blog/admin/post/new](http://example.com/blog/admin/post/new)
。
res.redirect('post/new')
如果结尾不存在斜杠,post/new
从重定向到[http://example.com/blog/admin](http://example.com/blog/admin)
(不带斜杠),将重定向到[http://example.com/blog/post/new](http://example.com/blog/post/new)
。
重定向也可以作用于相对路径,如:
res.redirect('..')
[http://example.com/admin/post/new](http://example.com/admin/post/new)
,将重定向到 [http://example.com/admin/post](http://example.com/admin/post)
。
五、Router
1router.all(path, [callback, …] callback)
可用于全局路由逻辑映射到特定路径前缀或对路由的任意匹配项进行下一步操作。如跳转前的身份验证:
router.all('*', requireAuthentication, loadUser)
或者是白名单功能:
router.all('/api/*', requireAuthentication) //限制'/api'为前缀的路径
2. router.METHOD(path, [callback, …] callback)
路由的请求方法设置,如:router.get()
,router.post()
, router.put()
router.get('/', function (req, res) {
res.send('hello world')
})
3. router.param(name, callback)
路由参数。与app.param()不同的是,它不接受数组成为路由参数。下列例子中,当路径中存在 :user ,可以映射相应的加载逻辑,或获取参数以进行下一步操作。
router.param('user', function (req, res, next, id) {
// try to get the user details from the User model and attach it to the request object
User.find(id, function (err, user) {
if (err) {
next(err)
} else if (user) {
req.user = user
next()
} else {
next(new Error('failed to load user'))
}
})
})
4. router.route(path)
指定单个路由实例,加载中间件以做特定路由的操作。例:
var router = express.Router()
router.param('user_id', function (req, res, next, id) {
// sample user, would actually fetch from DB, etc...
req.user = {
id: id,
name: 'TJ'
}
next()
})
router.route('/users/:user_id')
.all(function (req, res, next) {
// runs for all HTTP verbs first
// think of it as route specific middleware!
next()
})
.get(function (req, res, next) {
res.json(req.user)
})
.put(function (req, res, next) {
// just an example of maybe updating the user
req.user.name = req.params.name
// save user ... etc
res.json(req.user)
})
.post(function (req, res, next) {
next(new Error('not implemented'))
})
.delete(function (req, res, next) {
next(new Error('not implemented'))
})
这种方法针对单个/users/:user_id
路径,并为之添加了单独的处理操作。
5. router.use([path], [function, …] function)
类似于app.use(),以下是例子:
var express = require('express')
var app = express()
var router = express.Router()
//所有的请求都会先经过该中间件进行逻辑操作
router.use(function (req, res, next) {
console.log('%s %s %s', req.method, req.url, req.path)
next()
})
// 仅当路径以/bar开头时才会调用该方法
router.use('/bar', function (req, res, next) {
// ... maybe some additional /bar logging ...
next()
})
// 路由中总是会调用的方法
router.use(function (req, res, next) {
res.send('Hello World')
})
app.use('/foo', router)
app.listen(3000)
要注意的是,router.use()的定义顺序非常重要,它总是从上往下顺序调用,用顺序确定执行优先级。举例来说,如果定义一个记录器,它通常会写在最前面,这样每个请求才会都被记录下来。
现在,假设您想忽略对静态文件的日志记录请求,但是继续记录在之后定义的路由和中间件logger()
。您只需express.static()
在添加记录器中间件之前将调用移至顶部即可:
router.use(express.static(path.join(__dirname, 'public')))
router.use(logger())
router.use(function (req, res) {
res.send('Hello')
})