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回应的requestresponse对象

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.useapp.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())

express部分第三方中间件

参考资料

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏刘望舒

Android网络编程(九)Retrofit2前篇[基本使用]

前言 Retrofit是Square公司开发的一款针对Android网络请求的框架,Retrofit2底层基于OkHttp实现的,而OkHttp现在已经得到Go...

1826
来自专栏大魏分享(微信公众号:david-share)

干货来了:构建RESTful Web Service分几步?| 从开发角度看应用架构11

为了不同应用组件的互联互通,web services通过http将标准的通讯方式暴露出来。通过将应用抽取成独立的组件,并让这些组件通过web service方式...

1062
来自专栏hightopo

基于 HTML5 Canvas 的工控机柜 U 位动态管理

1244
来自专栏前端杂货铺

webpack配置别名alias出现的错误匹配

@(webpack) webpack是一款功能强大的前端构建工具,不仅仅是针对js,它也可通过各种loader来构建相关的less,html,image等各种资...

3466
来自专栏Java3y

从零单排学Redis【黄金】

好的,今天我们要上黄金段位了,如果还没经历过青铜和白银阶段的,可以先去蹭蹭经验再回来:

912
来自专栏小李刀刀的专栏

[译]Laravel 5.0 之 表单验证类 (Form Requests)

本文译自 Matt Stauffer 的系列文章. ---- 让人头痛的表单验证 只要你曾经在使用 Laravel 框架的过程中试图找到有关用户输入验证的最佳实...

3545
来自专栏皮振伟的专栏

[kvm][virt]PIO技术分析

前言: 基于KVM的设备虚拟化,就从这里开始吧。 分析: 1,PIO Port IO,所谓端口IO,x86上使用in、out指令进行访问。和内存的地址空间完...

2897
来自专栏编程思想之路

BLE低功耗蓝牙开发相关概念问题记录

蓝牙ble的传输速率是指主从机每秒所传输的字节数。既然是传输速率那就涉及到时间和每次所传递包大小的问题。 关于ble通信的demo可以参考蓝牙API介绍及基...

2506
来自专栏枕边书

用C写一个web服务器(一) 基础功能

前言 C 语言是一门很基础的语言,程序员们对它推崇备至,虽然它是我的入门语言,但大学的 C 语言知道早已经还给了老师,C 的使用可以说是从头学起。 之前一直在读...

1929
来自专栏Java帮帮-微信公众号-技术文章全总结

springmvc学习第二天

Springmvc第二天 回顾第一天课程内容: 1.JAVAEE体系结构 2.什么是springmvc? * mvc设计模式 * springmvc框架原理 3...

3158

扫码关注云+社区