Express 是一个精简的、灵活的 Node.js Web 程序框架,为构建单页、多页及混合的 Web 程序提供了一系列健壮的功能特性,可以快速的搭建一个完整功能的网站。
参考
express()
用于创建一个 Express 应用程序 app
对象, 这个 app 实际上是一个 Function 可以被用来作为一个回调函数传递给 Node HTTP server 来处理请求,这样就可以简单的基于同一份代码提供 http 和 https 版本express.static(root,[options])
Express 唯一内建中间件,负责托管 Express 应用中的静态资源,参数 root 姿态资源目录,options 配置express.Route([options])
创建一个 router 路由对象,一个 router 对象可以看做是一个程序,可以在其上添加中间件和HTTP路由方法 const express = require('express');
const app = express();
const router = express.Router();
app.set('port', process.env.PORT || 8854);
router.all('/a', function (req, res) {
res.send('finish');
})
app.use('/static', express.static('public'));
...
// app 开启端口监听
http.createServer(app).listen(80);
https.createServer(options, app).listen(443);
app.listen(8888, function () {}) // http.createServer(app).listen() 的一种便利写法
app 对象,通过
express()
创建
app.locals
用于存放程序的本地变量,一旦设定 app.locals
的各个属性值将贯穿程序的整个生命周期,可以在渲染模板时使用这些本地变量,为模板提供一些有用的方法、以及 app 级别的数据app.mountpath
返回子程序挂载的路径模式app.all(path,callback...)
匹配所有的 HTTP 动词,给某个路径 path 映射一个全局的逻辑处理,它的回调函数并不一定是终点 可以通过 next() 匹配随后的路由app.get(path, callback...)
匹配指定路径 获得 GET 请求后 执行回调函数,可以设置多个回调,他们的行为与中间件一样,并且可以通过调用 next('route')
来绕过剩余的回调,传递控制权到随后的路由app.MAETHOD(path, callback...)
路由一个 HTTP 请求, METHOD 是这个请求的方法 GET POST DELETE… 工作方式与 app.get(path, callback..)
基本一致app.route(path)
返回一个单利模式的路由实例,之后可以在其上施加各种 HTTP 动作的中间件,可以用来避免同一个路径多个路由实例app.param([name], callabck)
给路由参数添加回调触发器,name 是参数名或者参数数组,回调参数:req, res, next, value(参数值), name(参数名) 如果 name 是数组,会按照各个参数在数组中被声明的顺序将回调触发器注册下来,在定义的 param 的路由上,param 回调都是第一个被调用的,并且只会被调用一次app.render(view, [locals], callback)
通过 callback 回调返回一个 view 模板渲染之后得到的 HTML 类似于 res.render()
但是不会将结果返回给客户端use([path], function [,function])
挂载中间件方法到路径上,如果未指定路径默认为/
,在一个路径上挂载一个中间件之后,每当请求的路径的前缀部分匹配这个路由路径,那么中间件就会被执行,挂载在 ‘/’ 路径上的中间件对于每个请求都会执行,中间件方法是顺序执行的所有挂载顺序很重要app.listen(port, [hostname],[backlog],[callback])
绑定程序监听端口到指定的主机和端口号,与 Node 中 HTTP 模块的 server.listen() 方法是一样的 只针对 http 协议app.path()
返回 app 的 典型路径app.set(name, value)
给 name 设置项赋值为 value app.get(name)
获取设置名为 name 的 app 设置的值app.disable(name)
将名为 name 的设置的值改为 false 与调用 app.set(name, false)
等价app.disabled(name)
判断名为 name 的设置的值是否为 falseapp.enable(name)
将名为 name 的设置的值改为 true 与调用 app.set(name, true)
等价app.enabled(name)
判断名为 name 的设置的值是否为 trueapp.on('mount', function (parent) {})
挂载事件,在子程序挂载到父程序时触发 // 伪代码
const express = require('express');
const fs = require('fs');
// express() 创建应用 app
const app = express();
const admin = express();
console.log(typeof app);// function
// app.set(name, value) 给 name 设置项赋值为 value,也可以在 app.locals.settings 属性下查询到
app.set('port', process.env.PORT || 8854);
// app.get(name) 获取设置名为 name 的 app 设置的值
console.log(app.get('port')); // 8854
// app.locals 返回 app级别的本地变量
console.log(app.locals);
// disable() 设置值为 false disabled() 查询值是否为 false
app.disable('test');
console.log('test is disabled', app.disabled('test'));
// enable() 设置值为 true enabled() 查询值是否为 true
app.enable('test');
console.log('test is enabled', app.enabled('test'));
app.set('view engine', 'jade');//设置默认的模板引擎
app.set('views', __dirname + '/views');//设置views路径映射到views文件夹
// app.render() 通过 callback 回调返回一个 view 模板渲染之后得到的 HTML
app.render('a.jade', function (err, html) {
fs.writeFileSync('./public/a.html', html);
})
admin.get('/', function (req, res) {
console.log('mountpath', admin.mountpath); // [ '/admin', '/manager' ]
})
// app.on('mount') 事件,在子程序挂载到父程序时触发
admin.on('mount', function (parent) {
console.log('Admin Mounted', parent === app); // true
//
console.log(admin.path());
})
app.use(['/admin', '/manager'], admin);
// app.use() 挂载中间件方法到指定路径上,未指定路径则默认为 '/'
app.use(function (req, res, next) {
res.send('all will get');
next();
})
// app.param(name) 给路由参数添加回调触发器,name 是参数名或者参数数组
app.param('user', function (req, res, next, value, name) {
console.log('name', name, 'value', value);
next();
})
app.get('/users/:user', function (req, res) {
console.log('in users/:user');
res.send('in users/:user');
})
// app.all(path) 匹配指定路径下的所有 HTTP 响应
app.all('*', function (req, res, next) {
res.status(200);
res.statusMessage = 'test statusMessage';
next();
});
// app.get(path) 匹配指定路径 获得 GET 请求后 执行回调函数
app.get('/*', function (req, res, next) {
// next() 方法 进入下一个回调 next('route') 绕过剩余的回调,传递控制权到随后的路由
req.originalUrl === '/a' ? next('route') : next();
console.log(req.originalUrl);
}, function (req, res, next) {
res.send('enter /*');
next();
});
app.get('/a', function (req, res) {
res.send('enter /a');
})
// app.METHOD(path) 匹配指定路径的 METHOD 请求,然后执行回调,METHOD 可以是任意 HTTP 请求方法
app.post('/a', function (req, res) {
res.send('post success');
})
// app.route(path) 返回一个单利的路由实例,可以在其上链式调用 HTTP 动作方法
app.route('/events')
.all(function(req, res, next) {
res.status(200);
next();
})
.get(function(req, res, next) {
res.send('xx');
})
.post(function(req, res, next) {
res.send('xx')
})
// app.listen() 绑定监听程序到指定端口
const server = app.listen(app.get('port'), function () {
console.log('Express started on http://localhost:' + app.get('port') + '; press Ctrl-C to terminate.');
console.log(server.address());
})
req
代表一个 HTTP 请求,其具有一些属性来保存请求中的一些数据,一般为中间件的第一个参数、或者路由回调的第一个参数
req.app
属性,持有 express 实例的一个引用,便于模块导出后使用 express 实例中的方法req.baseUrl
属性,返回路由实例挂载的 url 路径req.originalUrl
属性,返回请求连接,并保留原版req.url
属性,返回请求链接,但是如果当前路由挂载到其他路径下,返回的是去掉 baseUrl
后的路径req.hostname
属性,返回包含源自 Host HTTP 头部的 hostname, 如果有代理,则可以被代理设置req.path
属性,返回包含请求 url 的部分路径req.protocol
属性,返回请求的协议req.query
属性,为每一个路由中的query string参数都分配一个属性。默认为 {}
req.params
属性,另一个对象包含在路由中命名的参数req.ips
属性,当trust proxy设置项被设置为启用值,这个属性包含了一组在X-Forwarded-For请求头中指定的IP地址。不然,其就包含一个空的数组。req.body
属性,返回提交时的请求体中的数据req.cookies
属性,当使用cookie-parser中间件的时候,这个属性是一个对象,其包含了请求发送过来的cookies。如果请求没有带cookies,那么其值为{}req.route
属性,返回当前匹配的路由req.secure
属性,返回链接的安全性,也就是是不是 https 链接req.signedCookies
属性,返回签名的 cookiesreq.stale
属性,返回这个请求是否为陈旧的,它与req.fresh是相反的req.fresh
属性,指示这个请求是否是新鲜的req.subdomains
属性,请求域名中,子域名的数组req.xhr
属性,一个布尔值,如果X-Requested-With的值为XMLHttpRequest,那么其为true,其指示这个请求是被一个客服端库发送,比如jQuery。req.accepts(types)
检查指定的内容类型是否被接受,基于请求的Accept HTTP头部。这个方法返回最佳匹配,如果没有一个匹配,那么其返回undefined,type值可以是一个单的MIME type字符串(比如application/json),一个扩展名比如json,一个逗号分隔的列表,或者一个数组。req.acceptsCharsets(charset[, ...])
返回指定的字符集集合中第一个的配置的字符集req.acceptsEncodings(encoding[, ...])
返回指定的编码集合中第一个的配置的编码req.acceptsLanguages(lang [, ...])
返回指定的语言集合中第一个的配置的语言req.get(field)
返回指定的 HTTP 头部的内容,不区分大小写req.is(type)
如果进来的请求的Content-type头部域匹配参数type给定的MIME type,那么其返回true。否则返回false。 const express = require('express');
const fs = require('fs');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const app = express();
const user = express.Router();
app.set('port', process.env.PORT || 8854);
app.use(bodyParser.json()); // 解析 application/json
app.use(bodyParser.urlencoded({extended: true})); // 解析 application/x-www-form-urlencoded
app.use(cookieParser());
// GET http://localhost:8854/admin/88?name=yeye&age=90#hh
user.get('/:id', function (req, res, next) {
// req.baseUrl 返回路由实例挂载的 url 路径
console.log(req.baseUrl); // /admin
console.log(req.originalUrl); // /admin/88?name=yeye&age=90
console.log(req.url); // /88?name=yeye&age=90
console.log(req.hostname); // localhost
console.log(req.path); // /88
console.log(req.protocol); // http
console.log(req.query); // { name: 'yeye', age: '90' }
console.log(req.params); // { id: '88' }
console.log(req.ips); // []
next();
})
user.post('/:id', function (req, res, next) {
// 需要 body-parser 中间件配合使用,否则返回 undefined
console.log(req.body);
// 需要 cookie-parser 中间件配合使用
console.log(req.cookies);
// req.route 返回匹配的路由
console.log(req.route);
// req.secure 判断是否为 https 链接
console.log(req.secure);
console.log(req.fresh); // false
console.log(req.stale); // true
// req.subdomains 请求域名中,子域名的数组
console.log(req.subdomains);
console.log(req.xhr);
res.send('finish');
})
app.use('/admin', user);
app.get('/admin/:id', function (req, res) {
// req.app 返回持有 express 实例的一个引用
console.log(req.app === app); // true
res.send(req.app.get('views'));
})
app.get('/temp', function (req, res, next) {
// req.accepts() 检查指定的内容类型是否被接受
console.log(req.accepts('html'));
// req.get() 返回指定的 HTTP 头部的内容
console.log(req.get('Content-type'));
// req.is() 返回 Content-type头部域 是否匹配参数
console.log(req.is('json'));
res.send('get /temp success');
})
const server = app.listen(app.get('port'), function () {
console.log('Express started on http://localhost:' + app.get('port') + '; press Ctrl-C to terminate.');
console.log(server.address());
})
res 对象代表了,当一个 HTTP 请求到来时,Express 程序返回的 HTTP 响应
res.app
属性,持有express程序实例的一个引用,其可以在中间件中使用。 res.headersSent
属性,指示响应是否已经发送 HTTP 头部res.locals
属性,是一个对象,主要作用是将值传递到所渲染的模板中,在模板中可以直接引用该对象的属性,也可以通过该对象引用,与 app.locals
相比,同样会传递至渲染的模板中,但是 app.locals 会在整个生命周期中起作用;而 res.locals 只会有当前请求中起作用。 app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.get('/temp', function (req, res, next) {
// res.app 持有express程序实例的一个引用
console.log(res.app === app); // true
// res.headersSent 指示响应是否已经发送 HTTP 头部
console.log(res.headersSent); // false
// res.locals 将值传递到所渲染的模板中
// res.render('a.jade', {name: 'name 1', age: 10}); // 方法 1
res.locals.name = 'name 2'; // 方法 2 将值挂载到 locals 属性下
res.locals.age = 40;
res.render('a.jade');
console.log(res.headersSent); // true
})
res.json([body])
发送一个json的响应。这个方法和将一个对象或者一个数组作为参数传递给res.send()方法的效果相同。不过,你可以使用这个方法来转换其他的值到json,例如null,undefined。res.jsonp([body])
发送一个json的响应,并且支持JSONP。这个方法和res.json()效果相同,除了其在选项中支持JSONP回调res.send([body])
发送HTTP响应。 body参数可以是一个Buffer对象,一个字符串,一个对象,或者一个数组。res.sendFile(path [, options] [, fn])
传输path指定的文件。根据文件的扩展名设置Content-TypeHTTP头部。除非在options中有关于root的设置,path一定是关于文件的绝对路径。 option 用于配置 root 根目录等;fn 回调函数是错误处理res.render(view [, locals] [, callback])
渲染一个视图,然后将渲染得到的HTML文档发送给客户端 locals 与 res.locals 作用一致,向模板中传递数据;callback 回调,返回错误以及渲染后的模板,如果设置 callback 则需要手动触发 res.send() res.write()
http.ServerResponse 的方法,可以被多次调用,写返回的响应主体res.end([data] [, encoding])
用来快速结束请求res.status(code)
使用这个方法来设置响应对象的HTTP status。res.sendStatus(statusCode)
设置响应对象的HTTP status code为statusCode并且发送statusCode的相应的字符串形式作为响应的Bodyres.set(field [, value])
设置响应对象的HTTP头部field为value。为了一次设置多个值,那么可以传递一个对象为参数。res.get(field)
返回field指定的HTTP响应的头部res.append(field [, value])
在指定的field的HTTP头部追加特殊的值value。如果这个头部没有被设置,那么将用value新建这个头部。value可以是一个字符串或者数组,在res.append()之后调用app.set()函数将重置前面设置的值。res.type(type)
设置Content-TypeHTTP头部为MIME typeres.format(object)
进行内容协商,根据请求的对象 req 中Accept HTTP头部指定的接受内容它使用req.accepts()来选择一个句柄来为请求服务,这些句柄按质量值进行排序。如果这个头部没有指定,那么第一个方法默认被调用。res.cookie(name, value [,options])
设置name和value的cookie,value参数可以是一串字符或者是转化为json字符串的对。 options 可以用来设置 Cookie 的域名、过期时间、是否签名等res.clearCookie(name [,options])
根据指定的name清除对应的cookie。 // 伪代码
const express = require('express');
const fs = require('fs');
const app = express();
app.set('port', process.env.PORT || 8854);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.get('/temp', function (req, res, next) {
// res.json 向客户端发送 json 数据
res.json({name: 'name 1'});
/*
使用 jsonp 的方式向客户端发送数据,请求中要有 ?callback=cb 指定回调函数名
可以使用 app.set('jsonp callback name', 'cb') 替换 callback 为 cb (?cb=cb)
*/
res.jsonp({name: 'name 1'});
// res.send 发送HTTP响应
res.send('send something');
// res.sendFile 发送文件
res.sendFile(__dirname + '/public/test.txt', function (err) {
if (err) {
console.log(err);
res.status(err.status).end();
} else {
console.log('sent success');
}
})
// res.render 渲染模板,将等到的 html 发送给客户端
res.render('a.jade', {name: 'name render', age: 90}, function (err, html) {
if (err) {
next(err);
} else {
res.send(html);
}
})
// res.status 设置响应对象的HTTP status
res.status(200);
// res.sendStatus 设置响应对象的HTTP status 并发送
res.sendStatus(200);
// res.set 设置响应对象的HTTP头部
res.set({
'Content-Type':'text/plain',
'Content-Length':'50'
})
// res.get 返回指定的HTTP响应的头部
console.log(res.get('Content-Type'));
// res.append 在指定的field的HTTP头部追加特殊的值value
res.append('Set-Cookie', 'foo=bar;Path=/;HttpOnly');
// res.type 设置Content-TypeHTTP头部
res.type('json');
// res.write 可以多次写入 res.end 用来快速结束请求
res.write('first\n');
res.write('second\n');
res.end('end\n');
})
app.post('/temp', function (req, res) {
// res.cookie 设置 cookie
res.cookie('test', {name: 'cookie name', age: 90}, {maxAge: 100000});
// res.clearCookie 删除 cookie
res.clearCookie('test');
// res.format 进行内容协商, 根据的是 req 的 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() {
res.status(406).send('Not Acceptable');
}
})
})
const server = app.listen(app.get('port'), function () {
console.log('Express started on http://localhost:' + app.get('port') + '; press Ctrl-C to terminate.');
console.log(server.address());
})