Express中间件,看这篇文章就够了(#^.^#)
底层:http模块
express目前是最流行的基于Node.js的web开发框架,express框架建立在内置的http模块上,
var http = require('http')
var app = http.createServer(function(req,res){
res.writeHead(200,{"Content-type":"text/plain"});
res.end('hello world')
})
app.listen(3000,'lcoalhost')
上面代码的关键是使用createServer
方法,生成一个HTTP的服务器实例。该方法接受一个回调函数,回调函数的参数分别代表HTTP请求和HTTP回应的request
和response
对象
Experss框架的核心是对http模块的再包装,
var express = require('express')
var port = process.env.PORT || 3000
var app = express()
app.get('/',fcuntion(req,res){
res.send('hello world')
})
app.listen(port)
比较http.createServer()
方法创建一个app实例和Express的构造方法,生成一个Express实例,两者的回调函数都是相同的。Express框架等于在http模块之上,加了一个中间层
中间件
Express是一个自身功能极简单,完全由路由
和中间件
构成的web开发框架,从本质上说,一个Express应用是在调用各种中间件
中间件(middleware)
是一个函数,他可以访问请求对象(request object(req)),响应对象(response object(res))和web应用中处于请求-响应循环
Express可以使用如下几种中间件:
- 应用级中间件
- 路由级中间件
- 错误处理中间件
- 内置中间件
- 第三方中间件
应用级中间件
应用级中间键绑定到app对象
使用app.use
和app.METHOD()-需要处理http请求的方法,例如GET、PUT、POST
var app = express()
// 没有挂载路径的中间件,应用中的每个请求都会执行该中间件
app.use((req,res,next) => {
console.log('Time',Dtae.now());
next(); // 传递request对象给下一个中间件
})
// 挂载至/user/:id的中间件,任何执行/user/:id的请求都会执行它
app.use('/use/:id',(req,res,next) => {
console.log('Request Type',req.method);
next();
})
// 路由和句柄函数(中间件系统),处理指向/user/:id的GET请求
app.get('/user/:id',(req,res,next)=>{
console.log('USER');
})
如果我们想要处理挂在至/user/:id
的中间件的GET请求,我们需要使用next()
将request
对象传递给下一个中间件
否者:
得不到下一个中间件处理的它,一直在等待...
最终会抛出localhost未发送任何数据的错误
如何你不想要终止请求-响应循环
,总是记得通过next()
传递request对象
如果你想要在中间件栈中跳过剩余中间件,调用next('route')方法将控制权交给下一个路由
app.get('/user/:id',(req,res,next)=>{
if(req.params.id==0) next('route')
else next()
},(req,res,next)=>{
// 渲染常规页面
res.render('regular')
})
// 处理/user/:id,渲染一个id为0的特殊页面
app.get('/user/:id',(req,res,next)=>{
res.render('special')
})
路由级中间件
路由级中间件和应用级中间件类似,只不过是它绑定对象为express.Router()
var router = express.Router()
路由级使用router.use()
或router.VERB()
加载
举个栗子
var app = express()
var router = express.Router()
// 没有挂载路径的中间件,通过该路由的每个请求都会执行该中间件
router.use(function (req, res, next) {
console.log('Time:', Date.now());
next();
})
// 一个中间件,显示任何指向/user/:id的HTTP请求的信息
router.use('/user/:id',(req,res,next)=>{
console.log('Request URL',req.originalUrl)
next()
},(req,res,next)=>{
console.log('Request Type',req.method)
next()
})
// 一个中间件栈,处理指向/user/:id的GET请求
router.get('/user/:id',(req,res,next)=>{
if(req.params.id == 0) next('router')
else next()
},(req,res,next)=>{
res.render('regular')
})
// 处理/user/:id,渲染一个特殊页面
router.get('user/:id',(req,res,next)=>{
console.log(req.params.id)
res.render('special')
})
// 将路由挂载至应用
app.use('/',router)
错误处理中间件
错误处理中间件有四个参数,定义错误处理中间件必须使用这四个参数。即使不需要next对象,也必须在参数中声明它,否者中间件会识别为一个常规中间件,不能处理错误
举个栗子:
app.use((err,req,res,next)=>{
console.error(err.stack)
res.status(500).send('Something broke')
})
中间件返回的响应是随意的,可以响应一个 HTML 错误页面、一句简单的话、一个 JSON 字符串,或者其他任何您想要的东西。
所以你可能想要像处理常规中间件那样,定义多个错误处理中间件
,比如您想为使用 XHR 的请求定义一个,还想为没有使用的定义一个,那么:
app.use(logErrors)
app.use(clientErrorHandler)
app.use(errorHandler)
logErrors
将请求和错误信息写入标准错误输出、日志或者类似服务
function logErrors(err,req,res,next){
console.error(err.stack)
next(err)
}
clientErrorHandler
定义如下(这里将错误直接传给了next)
function clientErrorHandler(err,req,res,next){
if(req.xhr){
res.status(500).send({error:'Something blew up!'})
}else{
next(err)
}
}
errorHandler
捕获所有错误
function errorHandler(err,req,res,next){
res.status(500)
res.render('error',{error:err})
}
内置中间件
从版本4.x开始,Express不再依赖Content
,除了 express.static
, Express 以前内置的中间件现在已经全部单独作为模块安装使用
express.static
是 Express 唯一内置的中间件。
它基于 serve-static
,负责在 Express 应用中提托管静态资源。
可选options
参数拥有如下属性
属性 | 描述 | 类型 | 缺省值 |
---|---|---|---|
dotfiles | 是否对外输出文件名以点(.)开头的文件。可选值为 “allow”、“deny” 和 “ignore” | String | "ignore" |
etag | 是否启用etag生成 | Boolean | true |
extensions | 设置文件扩展名备份选项 | Array | [ ] |
index | 发送目录索引文件,设置为 false 禁用目录索引。 | mixed | "index.html" |
lastModified | 设置 Last-Modified 头为文件在操作系统上的最后修改日期 | Boolean | true |
maxAge | 毫秒或者其字符串格式设置 Cache-Control 头的 max-age 属性 | Number | 0 |
redirect | 当路径为目录时,重定向至"/" | Boolean | true |
setHeaders | 设置HTTP头以提供文件的函数 | Function |
下面的栗子使用了 express.static
中间件,其中的 options
对象经过了精心的设计。
var options = {
dotfiles: 'ignore',
etag: false,
extensions: ['htm', 'html'],
index: false,
maxAge: '1d',
redirect: false,
setHeaders: function (res, path, stat) {
res.set('x-timestamp', Date.now());
}
}
app.use(express.static('public', options));
我们总是需要使用express.static
指定多个静态资源文件,比如:
app.use(express.static('public'))
app.use(express.static('files'))
第三方中间件
通过使用第三方中间件从而为Express应用增加更多的功能
安装所需功能的node模块,并在应用中加载,可以在应用级中加载,也可以在路由级中加载
举个栗子
$ npm install cookie-parser
var express = require('express')
var app = express()
var cookieParser = require('cookie-parser')
// 加载用于解析cookie的中间件
app.use(cookieParser())
参考资料
随机推荐
- 一文学redis操作(记录向)
相关内容: 虽然有参考文档,而且记忆太多也是耗脑,但学习的时候还是想要有个系统划分开知识点的文档,即使不要求去细致记忆,但划分开知识块后脑子里的印象才会更清晰,所以就有了这个博文. 主要是将各种命令进 ...
- python自动化报告的输出
1.设计简单的用例 2.设计用例 以TestBaiduLinks.py命名 # coding:utf-8 from selenium import webdriver import unittest ...
- C#微信公众号开发——获取access_token
access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token.正常情况下access_token有效期为7200秒(两个小时),微信获取access_token接 ...
- MySQL 并行复制演进及 MySQL 8.0 中基于 WriteSet 的优化
MySQL 8.0 可以说是MySQL发展历史上里程碑式的一个版本,包括了多个重大更新,目前 Generally Available 版本已经已经发布,正式版本即将发布,在此将介绍8.0版本中引入的一 ...
- VMware安装CentOS6
1. 搭建虚拟化环境常见故障讲解 2. 安装CentOS Linux系统 ……………… PS:运维老鸟教你安装centos6.5如何选择安装包 3. 远程连接LInux ip配置 注意:不用做任何修改 ...
- Linux 小知识翻译 - 「路径设置」
这次聊聊路径的使用,这里的路径是「命令搜索路径」的简称. 在Linux上执行命令的时候,本来是需要命令的所在位置的绝对路径的,就像「/usr/bin/passwd」这样. 但是,对于经常使用的命令,如 ...
- January 22nd, 2018 Week 04th Monday
It is only when you are pursued that you become swift. 唯有在被追赶的时候,你才能真正地奔跑. It is so bad a feeling wh ...
- SQL注入的绕过
一.常用符号的绕过 1.空格 1 空格代替:+ %20 %09 %0a %0b %0c %0d %a0 %00 /**/ /*!*/ 2 括号绕过:常用于基于时间延迟的盲注,例如构造语句: ?id=1 ...
- 17秋 软件工程 团队第五次作业 Alpha Scrum10
17秋 软件工程 团队第五次作业 Alpha Scrum10 今日完成的任务 世强:Android客户端成员列表完善.APP前端子部门和活动中心界面与数据交互: 港晨:Web前端主页的接口对接: 树民 ...
- [ISE 14.7] _pn.exe 崩溃问题 点击浏览崩溃问题
前言 装了大半天的ISE 14.7 结果新建工程的时候只要点击浏览文件夹,直接无响应,其实和其他_pn.exe崩溃是一样的. 解决方法 第一步:非常重要,进行文件备份,将"F:\Xilinx ...