express
翻译
api文档
中文
javascript
--css
express()
用来建立一个Express的程序。express()
方法是express模块导出的顶层方法。html
var express = require('express');
var app = express();
express.static
是Express中惟一的内建中间件。它以server-static模块为基础开发,负责托管 Express 应用内的静态资源。
参数root
为静态资源的所在的根目录。
参数options
是可选的,支持如下的属性:前端
属性 | 描述 | 类型 | 默认值 |
---|---|---|---|
dotfiles | 是否响应点文件。供选择的值有"allow","deny"和"ignore" | String | "ignore" |
etag | 使能或者关闭etag | Boolean | true |
extensions | 设置文件延期回退 | Boolean | true |
index | 发送目录索引文件。设置false将不发送。 | Mixed | "index.html" |
lastModified | 设置文件在系统中的最后修改时间到Last-Modified 头部。可能的取值有false 和true 。 |
Boolean | true |
maxAge | 在Cache-Control头部中设置max-age 属性,精度为毫秒(ms)或则一段ms format的字符串 |
Number | 0 |
redirect | 当请求的pathname是一个目录的时候,重定向到尾随"/" | Boolean | true |
setHeaders | 当响应静态文件请求时设置headers的方法 | Funtion |
若是你想得到更多关于使用中间件的细节,你能够查阅Serving static files in Express。vue
app
对象通常用来表示Express程序。经过调用Express模块导出的顶层的express()
方法来建立它:java
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.send('hello world!');
});
app.listen(3000);
app
对象具备如下的方法:node
它还有一些属性设置,这些属性能够改变程序的行为。得到更多的信息,能够查阅Application settings。jquery
app.locals
对象是一个javascript对象,它的属性就是程序本地的变量。git
app.locals.title
// => 'My App'
app.locals.email
// => 'me@myapp.com'
一旦设定,app.locals
的各属性值将贯穿程序的整个生命周期,与其相反的是res.locals
,它只在此次请求的生命周期中有效。github
在程序中,你能够在渲染模板时使用这些本地变量。它们是很是有用的,能够为模板提供一些有用的方法,以及app
级别的数据。经过req.app.locals
(具体查看req.app),Locals能够在中间件中使用。
app.locals.title = 'My App';
app.locals.strftime = require('strftime');
app.locals.email = 'me@myapp.com';
app.mountpath
属性是子程序挂载的路径模式。
一个子程序是一个
express
的实例,其能够被用来做为路由句柄来处理请求。
var express = require('express');
var app = express(); // the main app
var admin = express(); // the sub app
admin.get('/', function(req, res) {
console.log(admin.mountpath); // /admin
res.send('Admin Homepage');
});
app.use('/admin', admin); // mount the sub app
它和req对象的baseUrl属性比较类似,除了req.baseUrl
是匹配的URL路径,而不是匹配的模式。若是一个子程序被挂载在多条路径模式,app.mountpath
就是一个关于挂载路径模式项的列表,以下面例子所示。
var admin = express();
admin.get('/', function(req, res) {
console.log(admin.mountpath); // ['adm*n', '/manager']
res.send('Admin Homepage');
});
var secret = express();
secret.get('/', function(req, res) {
console.log(secret.mountpath); // /secr*t
res.send('Admin secret');
});
admin.use('/secr*t', secret); // load the 'secret' router on '/secr*t', on the 'admin' sub app
app.use(['/adm*n', '/manager'], admin); // load the 'admin' router on '/adm*n' and '/manager' , on the parent app
当子程序被挂载到父程序时,mount
事件被发射。父程序对象做为参数,传递给回调方法。
var admin = 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.all
方法和标准的app.METHOD()
方法类似,除了它匹配全部的HTTP动词。
对于给一个特殊前缀映射一个全局的逻辑处理,或者无条件匹配,它是颇有效的。例如,若是你把下面内容放在全部其余的路由定义的前面,它要求全部从这个点开始的路由须要认证和自动加载一个用户。记住这些回调并非必定是终点:loadUser
能够在完成了一个任务后,调用next()
方法来继续匹配随后的路由。
app.all('*', requireAuthentication, loadUser);
或者这种相等的形式:
app.all('*', requireAuthentication);
app.all('*', loadUser);
另外一个例子是全局的白名单方法。这个例子和前面的很像,然而它只是限制以/api
开头的路径。
app.all('/api/*', requireAuthentication);
路由HTTP DELETE
请求到有特殊回调方法的特殊的路径。获取更多的信息,能够查阅routing guide。
你能够提供多个回调函数,它们的行为和中间件同样,除了这些回调能够经过调用next('router')
来绕过剩余的路由回调。你可使用这个机制来为一个路由设置一些前提条件,若是不能知足当前路由的处理条件,那么你能够传递控制到随后的路由。
app.delete('/', function(req, res) {
res.send('DELETE request to homepage');
});
设置类型为布尔的设置名为name
的值为false
,此处的name
是app settings table中各属性的一个。调用app.set('foo', false)
和调用app.disable('foo')
是等价的。
好比:
app.disable('trust proxy');
app.get('trust proxy');
// => false
返回true
若是布尔类型的设置值name
被禁用为false
,此处的name
是app settings table中各属性的一个。
app.disabled('trust proxy');
// => true
app.enable('trust proxy');
app.disabled('trust proxy');
// => false
设置布尔类型的设置值name
为true
,此处的name
是app settings table中各属性的一个。调用app.set('foo', true)
和调用app.enable('foo')
是等价的。
app.enable('trust proxy');
app.get('trust proxy');
// => true
返回true
若是布尔类型的设置值name
被启动为true
,此处的name
是app settings table中各属性的一个。
app.enabled('trust proxy');
// => false
app.enable('trust proxy');
app.enabled('trust proxy');
// => true
注册给定引擎的回调,用来渲染处理ext文件。
默认状况下,Express须要使用require()
来加载基于文件扩展的引擎。例如,若是你尝试渲染一个foo.jade
文件,Express在内部调用下面的内容,同时缓存require()
结果供随后的调用,来加速性能。
app.engine('jade', require('jade').__express);
使用下面的方法对于那些没有提供开箱即用的.__express
方法的模板,或者你但愿使用不一样的模板引擎扩展。
好比,使用EJS模板引擎来渲染.html
文件:
app.engine('html', require('ejs').renderFile);
在这个例子中,EJS提供了一个.renderFile
方法,这个方法知足了Express规定的签名规则:(path, options, callback)
,然而记住在内部它只是ejs.__express
的一个别名,因此你能够在不作任何事的状况下直接使用.ejs
扩展。
一些模板引擎没有遵循这种规范,consolidate.js库映射模板引擎如下面的使用方式,因此他们能够无缝的和Express工做。
var engines = require('consolidate');
app.engine('haml', engines.haml);
app.engine('html', engines.hogan);
得到设置名为name
的app设置的值,此处的name
是app settings table中各属性的一个。
以下:
app.get('title');
// => undefined
app.set('title', 'My Site');
app.get('title');
// => 'My Site'
路由HTTP GET
请求到有特殊回调的特殊路径。获取更多的信息,能够查阅routing guide。
你能够提供多个回调函数,它们的行为和中间件同样,除了这些回调能够经过调用next('router')
来绕过剩余的路由回调。你可使用这个机制来为一个路由设置一些前提条件,若是请求没能知足当前路由的处理条件,那么传递控制到随后的路由。
app.get('/', function(req, res) {
res.send('GET request to homepage');
});
绑定程序监听端口到指定的主机和端口号。这个方法和Node
中的http.Server.listen()是同样的。
var express = require('express');
var app = express();
app.listen(3000);
经过调用express()
返回获得的app
其实是一个JavaScript的Function
,被设计用来做为一个回调传递给Node HTTP servers
来处理请求。这样,其就能够很简便的基于同一份代码提供http和https版本,因此app没有从这些继承(它只是一个简单的回调)。
var express = require('express');
var https = require('https');
var http = require('http');
http.createServer(app).listen(80);
https.createServer(options, app).listen(443);
app.listen()
方法是下面所示的一个便利的方法(只针对HTTP协议):
app.listen = function() {
var server = http.createServer(this);
return server.listen.apply(server, arguments);
};
路由一个HTTP请求,METHOD
是这个请求的HTTP方法,好比GET
,PUT
,POST
等等,注意是小写的。因此,实际的方法是app.get()
,app.post()
,app.put()
等等。下面有关于方法的完整的表。
获取更多信息,请看routing guide。
Express支持下面的路由方法,对应与同名的HTTP方法:
|
|
|
若是使用上述方法时,致使了无效的javascript的变量名,可使用中括号符号,好比,
app['m-search']('/', function ...
你能够提供多个回调函数,它们的行为和中间件同样,除了这些回调能够经过调用next('router')
来绕过剩余的路由回调。你可使用这个机制来为一个路由设置一些前提条件,若是请求没有知足当前路由的处理条件,那么传递控制到随后的路由。
本API文档把使用比较多的HTTP方法
app.get()
,app.post
,app.put()
,app.delete()
做为一个个单独的项进行说明。然而,其余上述列出的方法以彻底相同的方式工做。
app.all()
是一个特殊的路由方法,它不属于HTTP协议中的规定的方法。它为一个路径加载中间件,其对全部的请求方法都有效。
app.all('/secret', function (req, res) {
console.log('Accessing the secret section...');
next(); // pass control to the next handler
});
给路由参数添加回调触发器,这里的name
是参数名或者参数数组,function
是回调方法。回调方法的参数按序是请求对象,响应对象,下个中间件,参数值和参数名。
若是name
是数组,会按照各个参数在数组中被声明的顺序将回调触发器注册下来。还有,对于除了最后一个参数的其余参数,在他们的回调中调用next()
来调用下个声明参数的回调。对于最后一个参数,在回调中调用next()
将调用位于当前处理路由中的下一个中间件,若是name
只是一个string
那就和它是同样的(就是说只有一个参数,那么就是最后一个参数,和数组中最后一个参数是同样的)。
例如,当:user
出如今路由路径中,你能够映射用户加载的逻辑处理来自动提供req.user
给这个路由,或者对输入的参数进行验证。
app.param('user', function(req, res, next, id) {
User.find(id, function(error, user) {
if (err) {
next(err);
}
else if (user){
req.user = user;
} else {
next(new Error('failed to load user'));
}
});
});
对于Param
的回调定义的路由来讲,他们是局部的。它们不会被挂载的app或者路由继承。因此,定义在app
上的Param
回调只有是在app
上的路由具备这个路由参数时才起做用。
在定义param
的路由上,param
回调都是第一个被调用的,它们在一个请求-响应循环中都会被调用一次而且只有一次,即便多个路由都匹配,以下面的例子:
app.param('id', function(req, res, next, id) {
console.log('CALLED ONLY ONCE');
next();
});
app.get('/user/:id', function(req, res, next) {
console.log('although this matches');
next();
});
app.get('/user/:id', function(req, res) {
console.log('and this mathces too');
res.end();
});
当GET /user/42
,获得下面的结果:
CALLED ONLY ONCE
although this matches
and this matches too
app.param(['id', 'page'], function(req, res, next, value) {
console.log('CALLED ONLY ONCE with', value);
next();
});
app.get('/user/:id/:page', function(req. res, next) {
console.log('although this matches');
next();
});
app.get('/user/:id/:page', function (req, res, next) {
console.log('and this matches too');
res.end();
});
当执行GET /user/42/3
,结果以下:
CALLED ONLY ONCE with 42
CALLED ONLY ONCE with 3
although this matches
and this mathes too
下面章节描述的
app.param(callback)
在v4.11.0以后被弃用。
经过只传递一个回调参数给app.param(name, callback)
方法,app.param(naem, callback)
方法的行为将被彻底改变。这个回调参数是关于app.param(name, callback)
该具备怎样的行为的一个自定义方法,这个方法必须接受两个参数而且返回一个中间件。
这个回调的第一个参数就是须要捕获的url的参数名,第二个参数能够是任一的JavaScript对象,其可能在实现返回一个中间件时被使用。
这个回调方法返回的中间件决定了当URL中包含这个参数时所采起的行为。
在下面的例子中,app.param(name, callback)
参数签名被修改为了app.param(name, accessId)
。替换接受一个参数名和回调,app.param()
如今接受一个参数名和一个数字。
var express = require('express');
var app = express();
app.param(function(param, option){
return function(req, res, next, val) {
if (val == option) {
next();
}
else {
res.sendStatus(403);
}
}
});
app.param('id', 1337);
app.get('/user/:id', function(req, res) {
res.send('Ok');
});
app.listen(3000, function() {
console.log('Ready');
});
在这个例子中,app.param(name, callback)
参数签名保持和原来同样,可是替换成了一个中间件,定义了一个自定义的数据类型检测方法来检测user id
的类型正确性。
app.param(function(param, validator) {
return function(req, res, next, val) {
if (validator(val)) {
next();
}
else {
res.sendStatus(403);
}
}
});
app.param('id', function(candidate) {
return !isNaN(parseFloat(candidate)) && isFinite(candidate);
});
在使用正则表达式来,不要使用
.
。例如,你不能使用/user-.+/
来捕获user-gami
,用使用[\\s\\S]
或者[\\w\\>W]
来代替(正如/user-[\\s\\S]+/
)。
//captures '1-a_6' but not '543-azser-sder'
router.get('/[0-9]+-[[\\w]]*', function);
//captures '1-a_6' and '543-az(ser"-sder' but not '5-a s'
router.get('/[0-9]+-[[\\S]]*', function);
//captures all (equivalent to '.*')
router.get('[[\\s\\S]]*', function);
经过这个方法能够获得app
典型的路径,其是一个string
。
var app = express()
, blog = express()
, blogAdmin = express();
app.use('/blog', blog);
app.use('/admin', blogAdmin);
console.log(app.path()); // ''
console.log(blog.path()); // '/blog'
console.log(blogAdmin.path()); // '/blog/admin'
若是app
挂载很复杂下,那么这个方法的行为也会很复杂:一种更好用的方式是使用req.baseUrl
来得到这个app的典型路径。
路由HTTP POST
请求到有特殊回调的特殊路径。获取更多的信息,能够查阅routing guide。
你能够提供多个回调函数,它们的行为和中间件同样,除了这些回调能够经过调用next('router')
来绕过剩余的路由回调。你可使用这个机制来为一个路由设置一些前提条件,若是请求没能知足当前路由的处理条件,那么传递控制到随后的路由。
app.post('/', function(req, res) {
res.send('POST request to homepage')
});
路由HTTP PUT
请求到有特殊回调的特殊路径。获取更多的信息,能够查阅routing guide。
你能够提供多个回调函数,它们的行为和中间件同样,除了这些回调能够经过调用next('router')
来绕过剩余的路由回调。你可使用这个机制来为一个路由设置一些前提条件,若是请求没能知足当前路由的处理条件,那么传递控制到随后的路由。
app.put('/', function(req, res) {
res.send('PUT request to homepage');
});
经过callback
回调返回一个view
渲染以后获得的HTML文本。它能够接受一个可选的参数,可选参数包含了这个view
须要用到的本地数据。这个方法相似于res.render()
,除了它不能把渲染获得的HTML文本发送给客户端。
将
app.render()
看成是能够生成渲染视图字符串的工具方法。在res.render()
内部,就是使用的app.render()
来渲染视图。若是使能了视图缓存,那么本地变量缓存就会保留。若是你想在开发的过程当中缓存视图,设置它为
true
。在生产环境中,视图缓存默认是打开的。
app.render('email', function(err, html) {
// ...
});
app.render('email', {name:'Tobi'}, function(err, html) {
// ...
});
返回一个单例模式的路由的实例,以后你能够在其上施加各类HTTP动做的中间件。使用app.route()
来避免重复路由名字(所以错字错误)--说的意思应该是使用app.router()
这个单例方法来避免同一个路径多个路由实例。
var app = express();
app.route('/events')
.all(function(req, res, next) {
// runs for all HTTP verbs first
// think of it as route specific middleware!
})
.get(function(req, res, next) {
res.json(...);
})
.post(function(req, res, next) {
// maybe add a new event...
})
给name
设置项赋value
值,name
是app settings table中属性的一项。
对于一个类型是布尔型的属性调用app.set('foo', ture)
等价于调用app.enable('foo')
。一样的,调用app.set('foo', false)
等价于调用app.disable('foo')
。
可使用app.get()
来取得设置的值:
app.set('title', 'My Site');
app.get('title'); // 'My Site'
Application Settings
若是name
是程序设置之一,它将影响到程序的行为。下边列出了程序中的设置。
Property | Type | Value | Default |
---|---|---|---|
case sensitive routing | Boolean | 启用区分大小写。 | 不启用。对/Foo 和/foo 处理是同样。 |
env | String | 环境模型。 | process.env.NODE_ENV(NODE_ENV环境变量)或者"development" |
etag | Varied | 设置ETag 响应头。可取的值,能够查阅etag options table。更多关于HTTP ETag header。 |
weak |
jsonp callback name | String | 指定默认JSONP回调的名称。 | ?callback= |
json replacer | String | JSON替代品回调 | null |
json spaces | Number | 当设置了这个值后,发送缩进空格美化过的JSON字符串。 | Disabled |
query parser | Varied | 设置值为false 来禁用query parser ,或者设置simple ,extended ,也能够本身实现query string 解析函数。simple 基于Node 原生的query 解析,querystring。 |
"extend" |
strict routing | Boolean | 启用严格的路由。 | 不启用。对/foo 和/foo/ 的路由处理是同样。 |
subdomain offset | Number | 用来删除访问子域的主机点分部分的个数 | 2 |
trust proxy | Varied | 指示app 在一个反向代理的后面,使用x-Forwarded-* 来肯定链接和客户端的IP地址。注意:X-Forwarded-* 头部很容易被欺骗,全部检测客户端的IP地址是靠不住的。trust proxy 默认不启用。当启用时,Express尝试经过前端代理或者一系列代理来获取已链接的客户端IP地址。req.ips 属性包含了已链接客户端IP地址的一个数组。为了启动它,须要设置在下面trust proxy options table中定义的值。trust proxy 的设置实现使用了proxy-addr 包。若是想得到更多的信息,能够查阅它的文档 |
Disable |
views | String or Array | view 所在的目录或者目录数组。若是是一个数组,将按在数组中的顺序来查找view 。 |
process.cwd() + '/views' |
view cache | Boolean | 启用视图模板编译缓存。 | 在生成环境默认开启。 |
view engine | String | 省略时,默认的引擎被扩展使用。 | |
x-powered-by | Boolean | 启用X-Powered-By:Express HTTP头部 |
true |
Options for trust proxy
settings
查阅Express behind proxies来获取更多信息。
Type | Value |
---|---|
Boolean | 若是为 |
IP addresses | 一个IP地址,子网,或者一组IP地址,和委托子网。下面列出的是一个预先配置的子网名列表。
使用下面方法中的任何一种来设置IP地址: app.set('trust proxy', 'loopback') // specify a single subnet app.set('trust proxy', 'loopback, 123.123.123.123') // specify a subnet and an address app.set('trust proxy', 'loopback, linklocal, uniquelocal') // specify multiple subnets as CSV app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal']) // specify multiple subnets as an array 当指定IP地址以后, 这个IP地址或子网会被设置了这个IP地址或子网的`app`排除在外, 最靠近程序服务的没有委托的地址将被看作客户端IP地址。 |
Number | 信任从反向代理到app中间小于等于n跳的链接为客户端。 |
Function | 客户自定义委托代理信任机制。若是你使用这个,请确保你本身知道你在干什么。 app.set('trust proxy', function (ip) { if (ip === '127.0.0.1' || ip === '123.123.123.123') return true; // trusted IPs else return false; }) |
Options for etag
settings ETag
功能的实现使用了etag包。若是你须要得到更多的信息,你能够查阅它的文档。
Type | Value |
---|---|
Boolean | 设置为 |
String | 若是是strong ,使能strong ETag。若是是weak ,启用weak ETag。 |
Function | 客户自定义`ETag`方法的实现. 若是你使用这个,请确保你本身知道你在干什么。 app.set('etag', function (body, encoding) { return generateHash(body, encoding); // consider the function is defined }) |
挂载中间件方法到路径上。若是路径未指定,那么默认为"/"。
一个路由将匹配任何路径若是这个路径以这个路由设置路径后紧跟着"/"。好比:
app.use('/appale', ...)
将匹配"/apple","/apple/images","/apple/images/news"等。中间件中的
req.originalUrl
是req.baseUrl
和req.path
的组合,以下面的例子所示。
app.use('/admin', function(req, res, next) {
// GET 'http://www.example.com/admin/new'
console.log(req.originalUrl); // '/admin/new'
console.log(req.baseUrl); // '/admin'
console.log(req.path);// '/new'
});
在一个路径上挂载一个中间件以后,每当请求的路径的前缀部分匹配了这个路由路径,那么这个中间件就会被执行。
因为默认的路径为/
,中间件挂载没有指定路径,那么对于每一个请求,这个中间件都会被执行。
// this middleware will be executed for every request to the app.
app.use(function(req, res, next) {
console.log('Time: %d', Date.now());
next();
});
中间件方法是顺序处理的,因此中间件包含的顺序是很重要的。
// this middleware will not allow the request to go beyond it
app.use(function(req, res, next) {
res.send('Hello World');
});
// this middleware will never reach this route
app.use('/', function(req, res) {
res.send('Welcome');
});
路径能够是表明路径的一串字符,一个路径模式,一个匹配路径的正则表达式,或者他们的一组集合。
下面是路径的简单的例子。
Type | Example |
---|---|
Path | // will match paths starting with /abcd
app.use('/abcd', function (req, res, next) { next(); }) |
Path Pattern | // will match paths starting with /abcd and /abd
app.use('/abc?d', function (req, res, next) { next(); }) // will match paths starting with /abcd, /abbcd, /abbbbbcd and so on app.use('/ab+cd', function (req, res, next) { next(); }) // will match paths starting with /abcd, /abxcd, /abFOOcd, /abbArcd and so on app.use('/ab\*cd', function (req, res, next) { next(); }) // will match paths starting with /ad and /abcd app.use('/a(bc)?d', function (req, res, next) { next(); }) |
Regular Expression | // will match paths starting with /abc and /xyz
app.use(/\/abc|\/xyz/, function (req, res, next) { next(); }) |
Array | // will match paths starting with /abcd, /xyza, /lmn, and /pqr
app.use(['/abcd', '/xyza', /\/lmn|\/pqr/], function (req, res, next) { next(); }) |
方法能够是一个中间件方法,一系列中间件方法,一组中间件方法或者他们的集合。因为router
和app
实现了中间件接口,你能够像使用其余任一中间件方法那样使用它们。
Usage | Example |
---|---|
单个中间件 | 你能够局部定义和挂载一个中间件。 app.use(function (req, res, next) { next(); }) 一个router 是有效的中间件。 var router = express.Router(); router.get('/', function (req, res, next) { next(); }) app.use(router); 一个Express 程序是一个有效的中间件。 var subApp = express(); subApp.get('/', function (req, res, next) { next(); }) app.use(subApp); |
一系列中间件 | 对于一个相同的挂载路径,你能够挂载超过一个的中间件。 var r1 = express.Router(); r1.get('/', function (req, res, next) { next(); }) var r2 = express.Router(); r2.get('/', function (req, res, next) { next(); }) app.use(r1, r2); |
一组中间件 | 在逻辑上使用一个数组来组织一组中间件。若是你传递一组中间件做为第一个或者惟一的参数,接着你须要指定挂载的路径。 var r1 = express.Router(); r1.get('/', function (req, res, next) { next(); }) var r2 = express.Router(); r2.get('/', function (req, res, next) { next(); }) app.use('/', [r1, r2]); |
组合 | 你能够组合下面的全部方法来挂载中间件。 function mw1(req, res, next) { next(); } function mw2(req, res, next) { next(); } var r1 = express.Router(); r1.get('/', function (req, res, next) { next(); }); var r2 = express.Router(); r2.get('/', function (req, res, next) { next(); }); var subApp = express(); subApp.get('/', function (req, res, next) { next(); }); app.use(mw1, [mw2, r1, r2], subApp); |
下面是一些例子,在Express
程序中使用express.static
中间件。
为程序托管位于程序目录下的public
目录下的静态资源:
// GET /style.css etc
app.use(express.static(__dirname + '/public'));
在/static
路径下挂载中间件来提供静态资源托管服务,只当请求是以/static
为前缀的时候。
// GET /static/style.css etc.
app.use('/static', express.static(express.__dirname + '/public'));
经过在设置静态资源中间件以后加载日志中间件来关闭静态资源请求的日志。
app.use(express.static(__dirname + '/public'));
app.use(logger());
托管静态资源从不一样的路径,但./public
路径比其余更容易被匹配:
app.use(express.static(__dirname + '/public'));
app.use(express.static(__dirname + '/files'));
app.use(express.static(__dirname + '/uploads'));
req
对象表明了一个HTTP请求,其具备一些属性来保存请求中的一些数据,好比query string
,parameters
,body
,HTTP headers
等等。在本文档中,按照惯例,这个对象老是简称为req
(http响应简称为res
),可是它们实际的名字由这个回调方法在那里使用时的参数决定。
以下例子:
app.get('/user/:id', function(req, res) {
res.send('user' + req.params.id);
});
其实你也能够这样写:
app.get('/user/:id', function(request, response) {
response.send('user' + request.params.id);
});
在Express 4
中,req.files
默认在req
对象中再也不是可用的。为了经过req.files
对象来得到上传的文件,你可使用一个multipart-handling
(多种处理的工具集)中间件,好比busboy
,multer
,formidable
,multipraty
,connect-multiparty
或者pez
。
这个属性持有express
程序实例的一个引用,其能够做为中间件使用。
若是你按照这个模式,你建立一个模块导出一个中间件,这个中间件只在你的主文件中require()
它,那么这个中间件能够经过req.app
来获取express的实例。
例如:
// index.js
app.get("/viewdirectory", require('./mymiddleware.js'));
// mymiddleware.js
module.exports = function(req, res) {
res.send('The views directory is ' + req.app.get('views'));
};
一个路由实例挂载的Url路径。
var greet = express.Router();
greet.get('/jp', function(req, res) {
console.log(req.baseUrl); // greet
res.send('Konichiwa!');
});
app.use('/greet', greet);
即便你使用的路径模式或者一系列路径模式来加载路由,baseUrl
属性返回匹配的字符串,而不是路由模式。下面的例子,greet
路由被加载在两个路径模式上。
app.use(['/gre+t', 'hel{2}o'], greet); // load the on router on '/gre+t' and '/hel{2}o'
当一个请求路径是/greet/jp
,baseUrl
是/greet
,当一个请求路径是/hello/jp
,req.baseUrl
是/hello
。 req.baseUrl
和app
对象的mountpath属性类似,除了app.mountpath
返回的是路径匹配模式。
在请求的body中保存的是提交的一对对键值数据。默认状况下,它是undefined
,当你使用好比body-parser
和multer
这类解析body
数据的中间件时,它是填充的。
下面的例子,给你展现了怎么使用body-parser
中间件来填充req.body
。
var app = require('express');
var bodyParser = require('body-parser');
var multer = require('multer');// v1.0.5
var upload = multer(); // for parsing multipart/form-data
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({extended:true})); // for parsing application/x-www-form-urlencoded
app.post('/profile', upload.array(), function(req, res, next) {
console.log(req.body);
res.json(req.body);
});
当使用cookie-parser
中间件的时候,这个属性是一个对象,其包含了请求发送过来的cookies
。若是请求没有带cookies
,那么其值为{}
。
// Cookie: name=tj
req.cookies.name
// => "tj"
获取更多信息,问题,或者关注,能够查阅cookie-parser。
指示这个请求是不是新鲜的。其和req.stale
是相反的。
当cache-control
请求头没有no-cache
指示和下面中的任一一个条件为true
,那么其就为true
:
if-modified-since
请求头被指定,和last-modified
请求头等于或者早于modified
响应头。if-none-match
请求头是*
。if-none-match
请求头在被解析进它的指令以后,不匹配etag
响应头(彻底不知道什么鬼)。req.fresh
// => true
包含了源自Host
HTTP头部的hostname
。
当trust proxy
设置项被设置为启用值,X-Forwarded-Host
头部被使用来代替Host
。这个头部能够被客户端或者代理设置。
// Host: "example.com"
req.hostname
// => "example.com"
当trust proxy
设置项被设置为启用值,这个属性包含了一组在X-Forwarded-For
请求头中指定的IP地址。否则,其就包含一个空的数组。这个头部能够被客户端或者代理设置。
例如,若是X-Forwarded-For
是client
,proxy1
,proxy2
,req.ips
就是["clinet", "proxy1", "proxy2"]
,这里proxy2
就是最远的下游。
req.url
不是一个原生的Express
属性,它继承自Node's http module。
这个属性很像req.url
;然而,其保留了原版的请求连接,容许你自由地重定向req.url
到内部路由。好比,app.use()
的mounting
特色能够重定向req.url
跳转到挂载点。
// GET /search?q=something
req.originalUrl
// => "/search?q=something"
一个对象,其包含了一系列的属性,这些属性和在路由中命名的参数名是一一对应的。例如,若是你有/user/:name
路由,name
属性可做为req.params.name
。这个对象默认值为{}
。
// GET /user/tj
req.params.name
// => "tj"
当你使用正则表达式来定义路由规则,捕获组的组合通常使用req.params[n]
,这里的n
是第几个捕获租。这个规则被施加在无名通配符匹配,好比/file/*
的路由:
// GET /file/javascripts/jquery.js
req.params[0]
// => "javascripts/jquery.js"
包含请求URL的部分路径。
// example.com/users?sort=desc
req.path
// => "/users"
当在一个中间件中被调用,挂载点不包含在
req.path
中。你能够查阅app.use()得到跟多的信息。
请求的协议,通常为http
,当启用TLS加密,则为https
。
当trust proxy
设置一个启用的参数,若是存在X-Forwarded-Proto
头部的话,其将被信赖和使用。这个头部能够被客户端或者代理设置。
req.ptotocol
// => "http"
一个对象,为每个路由中的query string
参数都分配一个属性。若是没有query string
,它就是一个空对象,{}
。
// GET /search?q=tobi+ferret
req.query.q
// => "tobi ferret"
// GET /shoes?order=desc&shoe[color]=blue&shoe[type]=converse
req.query.order
// => "desc"
req.query.shoe.color
// => "blue"
req.query.shoe.type
// => "converse"
当前匹配的路由,其为一串字符。好比:
app.get('/user/:id?', function userIdHandler(req, res) {
console.log(req.route);
res.send('GET')
})
前面片断的输出为:
{ path:"/user/:id?"
stack:
[
{ handle:[Function:userIdHandler],
name:"userIdHandler",
params:undefined,
path:undefined,
keys:[],
regexp:/^\/?$/i,
method:'get'
}
]
methods:{get:true}
}
一个布尔值,若是创建的是TLS的链接,那么就为true
。等价与:
'https' == req.protocol;
当使用cookie-parser
中间件的时候,这个属性包含的是请求发过来的签名cookies
,不签名的而且为使用作好了准备(这句真不知道怎么翻译了...)。签名cookies
驻留在不一样的对象中来体现开发者的意图;否则,一个恶意攻击能够被施加在req.cookie
值上(它是很容易被欺骗的)。记住,签名一个cookie
不是把它藏起来或者加密;而是简单的防止篡改(由于签名使用的加密是私人的)。若是没有发送签名的cookie
,那么这个属性默认为{}
。
// Cookie: user=tobi.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3
req.signedCookies.user
// => "tobi"
为了获取更多的信息,问题或者关注,能够参阅cookie-parser。
指示这个请求是不是stale
(陈旧的),它与req.fresh
是相反的。更多信息,能够查看req.fresh。
req.stale
// => true
请求中域名的子域名数组。
// Host: "tobi.ferrets.example.com"
req.subdomains
// => ["ferrets", "tobi"]
一个布尔值,若是X-Requested-With
的值为XMLHttpRequest
,那么其为true
,其指示这个请求是被一个客服端库发送,好比jQuery
。
req.xhr
// => true
检查这个指定的内容类型是否被接受,基于请求的Accept
HTTP头部。这个方法返回最佳匹配,若是没有一个匹配,那么其返回undefined
(在这个case下,服务器端应该返回406和"Not Acceptable")。 type
值能够是一个单的MIME type
字符串(好比application/json
),一个扩展名好比json
,一个逗号分隔的列表,或者一个数组。对于一个列表或者数组,这个方法返回最佳项(若是有的话)。
// Accept: text/html
req.accepts('html');
// => "html"
// Accept: text/*, application/json
req.accepts('html');
// => "html"
req.accepts('text/html');
// => "text/html"
req.accepts(['json', 'text']);
// => "json"
req.accepts('application/json');
// => "application/json"
// Accept: text/*, application/json
req.accepts('image/png');
req.accepts('png');
// => undefined
// Accept: text/*;q=.5, application/json
req.accepts(['html', 'json']);
// => "json"
获取更多信息,或者若是你有问题或关注,能够参阅accepts。
返回指定的字符集集合中第一个的配置的字符集,基于请求的Accept-Charset
HTTP头。若是指定的字符集没有匹配的,那么就返回false。
获取更多信息,或者若是你有问题或关注,能够参阅accepts。
返回指定的编码集合中第一个的配置的编码,基于请求的Accept-Encoding
HTTP头。若是指定的编码集没有匹配的,那么就返回false。
获取更多信息,或者若是你有问题或关注,能够参阅accepts。
返回指定的语言集合中第一个的配置的语言,基于请求的Accept-Language
HTTP头。若是指定的语言集没有匹配的,那么就返回false。
获取更多信息,或者若是你有问题或关注,能够参阅accepts。
返回指定的请求HTTP头部的域内容(不区分大小写)。Referrer
和Referer
的域内容可互换。
req.get('Content-type');
// => "text/plain"
req.get('content-type');
// => "text/plain"
req.get('Something')
// => undefined
其是req.header(field)
的别名。
若是进来的请求的Content-type
头部域匹配参数type
给定的MIME type
,那么其返回true
。不然返回false
。
// With Content-Type: text/html; charset=utf-8
req.is('html');
req.is('text/html');
req.is('text/*');
// => true
// When Content-Type is application/json
req.is('json');
req.is('application/json');
req.is('application/*');
// => true
req.is('html');
// => false
获取更多信息,或者若是你有问题或关注,能够参阅type-is。
过期的。能够在适合的状况下,使用
req.params
,req.body
或者req.query
。
返回当前参数name
的值。
// ?name=tobi
req.param('name')
// => "tobi"
// POST name=tobi
req.param('name')
// => "tobi"
// /user/tobi for /user/:name
req.param('name')
// => "tobi"
按下面给出的顺序查找:
可选的,你能够指定一个defaultValue
来设置一个默认值,若是这个参数在任何一个请求的对象中都不能找到。
直接经过
req.params
,req.body
,req.query
取得应该更加的清晰-除非你肯定每个对象的输入。Body-parser
中间件必须加载,若是你使用req.param()
。详细请看req.body。
res
对象表明了当一个HTTP请求到来时,Express
程序返回的HTTP响应。在本文档中,按照惯例,这个对象老是简称为res
(http请求简称为req
),可是它们实际的名字由这个回调方法在那里使用时的参数决定。
例如:
app.get('/user/:id', function(req, res) {
res.send('user' + req.params.id);
});
这样写也是同样的:
app.get('/user/:id', function(request, response) {
response.send('user' + request.params.id);
});
这个属性持有express
程序实例的一个引用,其能够在中间件中使用。 res.app
和请求对象中的req.app
属性是相同的。
布尔类型的属性,指示这个响应是否已经发送HTTP头部。
app.get('/', function(req, res) {
console.log(res.headersSent); // false
res.send('OK'); // send以后就发送了头部
console.log(res.headersSent); // true
});
一个对象,其包含了响应的可以反应出请求的本地参数和所以只提供给视图渲染,在请求响应的周期内(若是有的话)--我要翻译吐了。不然,其和app.locals
是同样的。(不知道翻译的什么...)
这个参数在导出请求级别的信息是颇有效的,这些信息好比请求路径,已认证的用户,用户设置等等。
app.use(function(req, res, next) {
res.locals.user = req.user;
res.locals.authenticated = !req.user.anonymous;
next();
});
res.append()方法在
Expresxs
4.11.0以上版本才支持。
在指定的field
的HTTP头部追加特殊的值value
。若是这个头部没有被设置,那么将用value
新建这个头部。value
能够是一个字符串或者数组。
注意:在res.append()
以后调用app.set()
函数将重置前面设置的值。
res.append('Lind', ['<http://localhost>', '<http://localhost:3000>']);
res.append('Set-Cookie', 'foo=bar;Path=/;HttpOnly');
res.append('Warning', '199 Miscellaneous warning');
设置HTTP响应的Content-Disposition
头内容为"attachment"。若是提供了filename
,那么将经过res.type()
得到扩展名来设置Content-Type
,而且设置Content-Disposition
内容为"filename="parameter。
res.attachment();
// Content-Disposition: attachment
res.attachment('path/to/logo.png');
// Content-Disposition: attachment; filename="logo.png"
// Content-Type: image/png
设置name
和value
的cookie
,value
参数能够是一串字符或者是转化为json字符串的对象。
options是一个对象,其能够有下列的属性。
属性 | 类型 | 描述 |
---|---|---|
domain | String | 设置cookie的域名。默认是你本app的域名。 |
expires | Date | cookie的过时时间,GMT格式。若是没有指定或者设置为0,则产生新的cookie。 |
httpOnly | Boolean | 这个cookie只能被web服务器获取的标示。 |
maxAge | String | 是设置过去时间的方便选项,其为过时时间到当前时间的毫秒值。 |
path | String | cookie的路径。默认值是/ 。 |
secure | Boolean | 标示这个cookie只用被HTTPS 协议使用。 |
signed | Boolean | 指示这个cookie应该是签名的。 |
res.cookie()所做的都是基于提供的
options
参数来设置Set-Cookie
头部。没有指定任何的options
,那么默认值在RFC6265
中指定。
使用实例:
res.cookie('name', 'tobi', {'domain':'.example.com', 'path':'/admin', 'secure':true});
res.cookie('remenberme', '1', {'expires':new Date(Date.now() + 90000), 'httpOnly':true});
maxAge
是一个方便设置过时时间的方便的选项,其以当前时间开始的毫秒数来计算。下面的示例和上面的第二条功效同样。
res.cookie('rememberme', '1', {'masAge':90000}, "httpOnly":true);
你能够设置传递一个对象做为value
的参数。而后其将被序列化为Json字符串,被bodyParser()
中间件解析。
res.cookie('cart', {'items':[1, 2, 3]});
res.cookie('cart', {'items':[1, 2, 3]}, {'maxAge':90000});
当咱们使用cookie-parser
中间件的时候,这个方法也支持签名的cookie。简单地,在设置options
时包含signed
选项为true
。而后res.cookie()
将使用传递给cookieParser(secret)
的密钥来签名这个值。
res.cookie('name', 'tobi', {'signed':true});
根据指定的name
清除对应的cookie。更多关于options
对象能够查阅res.cookie()
。
res.cookie('name', 'tobi', {'path':'/admin'});
res.clearCookie('name', {'path':'admin'});
传输path
指定文件做为一个附件。一般,浏览器提示用户下载。默认状况下,Content-Disposition
头部"filename="的参数为path
(一般会出如今浏览器的对话框中)。经过指定filename
参数来覆盖默认值。
当一个错误发生时或者传输完成,这个方法将调用fn
指定的回调方法。这个方法使用res.sendFile()
来传输文件。
res.download('/report-12345.pdf');
res.download('/report-12345.pdf', 'report.pdf');
res.download('report-12345.pdf', 'report.pdf', function(err) {
// Handle error, but keep in mind the response may be partially-sent
// so check res.headersSent
if (err) {
} else {
// decrement a download credit, etc.
}
});
结束本响应的过程。这个方法实际上来自Node
核心模块,具体的是response.end() method of http.ServerResponse。
用来快速结束请求,没有任何的数据。若是你须要发送数据,可使用res.send()和res.json()这类的方法。
res.end();
res.status(404).end();
进行内容协商,根据请求的对象中Accept
HTTP头部指定的接受内容。它使用req.accepts()来选择一个句柄来为请求服务,这些句柄按质量值进行排序。若是这个头部没有指定,那么第一个方法默认被调用。当不匹配时,服务器将返回406
"Not Acceptable",或者调用default
回调。 Content-Type
请求头被设置,当一个回调方法被选择。然而你能够改变他,在这个方法中使用这些方法,好比res.set()
或者res.type()
。
下面的例子,将回复{"message":"hey"}
,当请求的对象中Accept
头部设置成"application/json"或者"*/json"(不过若是是*/*
,而后这个回复就是"hey")。
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');
}
})
除了规范化的MIME类型以外,你也可使用拓展名来映射这些类型来避免冗长的实现:
res.format({
text:function() {
res.send('hey');
},
html:function() {
res.send('<p>hey</p>');
},
json:function() {
res.send({message:'hey'});
}
})
返回field
指定的HTTP响应的头部。匹配是区分大小写。
res.get('Content-Type');
// => "text/plain"
发送一个json的响应。这个方法和将一个对象或者一个数组做为参数传递给res.send()
方法的效果相同。不过,你可使用这个方法来转换其余的值到json,例如null
,undefined
。(虽然这些都是技术上无效的JSON)。
res.json(null);
res.json({user:'tobi'});
res.status(500).json({error:'message'});
发送一个json的响应,而且支持JSONP。这个方法和res.json()
效果相同,除了其在选项中支持JSONP回调。
res.jsonp(null)
// => null
res.jsonp({user:'tobi'})
// => {"user" : "tobi"}
res.status(500).jsonp({error:'message'})
// => {"error" : "message"}
默认状况下,jsonp的回调方法简单写做callback
。能够经过jsonp callback name设置来重写它。
下面是一些例子使用JSONP响应,使用相同的代码:
// ?callback=foo
res.jsonp({user:'tobo'})
// => foo({"user":"tobi"})
app.set('jsonp callback name', 'cb')
// ?cb=foo
res.status(500).jsonp({error:'message'})
// => foo({"error":"message"})
链接这些links
,links
是以传入参数的属性形式提供,链接以后的内容用来填充响应的Link HTTP头部。
res.links({
next:'http://api.example.com/users?page=2',
last:'http://api.example.com/user?page=5'
});
效果:
Link:<http://api.example.com/users?page=2>;rel="next",
<http://api.example.com/users?page=5>;rel="last"
设置响应的Location
HTTP头部为指定的path
参数。
res.location('/foo/bar');
res.location('http://example.com');
res.location('back');
当path
参数为back
时,其具备特殊的意义,其指定URL为请求对象的Referer
头部指定的URL。若是请求中没有指定,那么其即为"/"。
Express传递指定的URL字符串做为回复给浏览器响应中的
Location
头部的值,不检测和操做,除了当是back
这个case时。浏览器有推导预期URL从当前的URL或者指定的URL,和在Location
指定的URL的责任;相应地重定向它。(我也不知道翻译的什么...)
重定向来源于指定path
的URL,以及指定的HTTP status codestatus
。若是你没有指定status
,status code默认为"302 Found"。
res.redirect('/foo/bar');
res.redirect('http://example.com');
res.redirect(301, 'http://example.com');
res.redirect('../login');
重定向也能够是完整的URL,来重定向到不一样的站点。
res.redirect('http://google.com');
重定向也能够相对于主机的根路径。好比,若是程序的路径为http://example.com/admin/post/new
,那么下面将重定向到http://example.com/admim
:
res.redirect('/admin');
重定向也能够相对于当前的URL。好比,来之于http://example.com/blog/admin/
(注意结尾的/
),下面将重定向到http://example.com/blog/admin/post/new
。
res.redirect('post/new');
若是来至于http://example.com/blog/admin
(没有尾部/
),重定向post/new
,将重定向到http://example.com/blog/post/new
。若是你以为上面很混乱,能够把路径段认为目录(有'/')或者文件,这样是能够的。相对路径的重定向也是能够的。若是你当前的路径为http://example.com/admin/post/new
,下面的操做将重定向到http://example.com/admin/post
:
res.redirect('..');
back
将重定向请求到referer,当没有referer
的时候,默认为/
。
res.redirect('back');
渲染一个视图,而后将渲染获得的HTML文档发送给客户端。可选的参数为:
locals
,定义了视图本地参数属性的一个对象。callback
,一个回调方法。若是提供了这个参数,render
方法将返回错误和渲染以后的模板,而且不自动发送响应。当有错误发生时,能够在这个回调内部,调用next(err)
方法。本地变量缓存使能视图缓存。在开发环境中缓存视图,须要手动设置为true;视图缓存在生产环境中默认开启。
// send the rendered view to the client
res.render('index');
// if a callback is specified, the render HTML string has to be sent explicitly
res.render('index', function(err, html) {
res.send(html);
});
// pass a local variable to the view
res.render('user', {name:'Tobi'}, function(err, html) {
// ...
});
发送HTTP响应。 body
参数能够是一个Buffer
对象,一个字符串,一个对象,或者一个数组。好比:
res.send(new Buffer('whoop'));
res.send({some:'json'});
res.send('<p>some html</p>');
res.status(404).send('Sorry, we cannot find that!');
res.status(500).send({ error: 'something blew up' });
对于通常的非流请求,这个方法能够执行许多有用的的任务:好比,它自动给Content-Length
HTTP响应头赋值(除非先前定义),也支持自动的HEAD和HTTP缓存更新。
当参数是一个Buffer
对象,这个方法设置Content-Type
响应头为application/octet-stream
,除非事先提供,以下所示:
res.set('Content-Type', 'text/html');
res.send(new Buffer('<p>some html</p>'));
当参数是一个字符串,这个方法设置Content-Type
响应头为text/html
:
res.send('<p>some html</p>');
当参数是一个对象或者数组,Express使用JSON格式来表示:
res.send({user:'tobi'});
res.send([1, 2, 3]);
res.sendFile()
从Express v4.8.0
开始支持。
传输path
指定的文件。根据文件的扩展名设置Content-Type
HTTP头部。除非在options
中有关于root
的设置,path
必定是关于文件的绝对路径。
下面的表提供了options
参数的细节:
属性 | 描述 | 默认值 | 可用版本 |
---|---|---|---|
maxAge | 设置Cache-Control 的max-age 属性,格式为毫秒数,或者是ms format的一串字符串 |
0 | |
root | 相对文件名的根目录 | ||
lastModified | 设置Last-Modified 头部为此文件在系统中的最后一次修改时间。设置false 来禁用它 |
Enable | 4.9.0+ |
headers | 一个对象,包含了文件所在的sever的HTTP头部。(不知道怎么翻译了) | ||
dotfiles | 是否支持点开头文件名的选项。可选的值"allow","deny","ignore" | "ignore" |
当传输完成或者发生了什么错误,这个方法调用fn
回调方法。若是这个回调参数指定了和一个错误发生,回调方法必须明确地经过结束请求-响应循环或者传递控制到下个路由来处理响应过程。
下面是使用了全部参数的使用res.sendFile()
的例子:
app.get('/file/:name', function(req, res, next) {
var options = {
root:__dirname + '/public',
dotfile:'deny',
headers:{
'x-timestamp':Date.now(),
'x-sent':true
}
};
var fileName = req.params.name;
res.sendFile(fileName, options, function(err) {
if (err) {
console.log(err);
res.status(err.status).end();
}
else {
console.log('sent', fileName);
}
});
});
res.sendFile
提供了文件服务的细粒度支持,以下例子说明:
app.get('/user/:uid/photos/:file', function(req, res) {
var uid = req.params.uid
, file = req.params.file;
req.user.mayViewFilesFrom(uid, function(yes) {
if (yes) {
res.sendFile('/upload/' + uid + '/' + file);
}
else {
res.status(403).send('Sorry! you cant see that.');
}
});
})
获取更多信息,或者你有问题或者关注,能够查阅send。
设置响应对象的HTTP status code
为statusCode
而且发送statusCode
的相应的字符串形式做为响应的Body。
res.sendStatus(200); // equivalent to res.status(200).send('OK');
res.sendStatus(403); // equivalent to res.status(403).send('Forbidden');
res.sendStatus(404); // equivalent to res.status(404).send('Not Found');
res.sendStatus(500); // equivalent to res.status(500).send('Internal Server Error')
若是一个不支持的状态被指定,这个HTTP status依然被设置为statusCode
而且用这个code的字符串做为Body。
res.sendStatus(2000); // equivalent to res.status(2000).send('2000');
设置响应对象的HTTP头部field
为value
。为了一次设置多个值,那么能够传递一个对象为参数。
res.set('Content-Type', 'text/plain');
res.set({
'Content-Type':'text/plain',
'Content-Length':'123',
'ETag':'123456'
})
其和res.header(field [,value])
效果一致。
使用这个方法来设置响应对象的HTTP status。其是Node中response.statusCode的一个连贯性的别名。
res.status(403).end();
res.status(400).send('Bad Request');
res.status(404).sendFile('/absolute/path/to/404.png');
设置Content-Type
HTTP头部为MIME type,若是这个指定的type可以被mime.lookup肯定。若是type
包含/
字符,那么设置Content-Type
为type
(我已经晕了)。
res.type('.html'); // => 'text/html'
res.type('html'); // => 'text/html'
res.type('json'); // => 'application/json'
res.type('application/json'); // => 'application/json'
res.type('png'); // => image/png:
设置Vary
响应头为field
,若是已经不在那里。(不懂什么意思)
res.vary('User-Agent').render('docs');
一个router
对象是一个单独的实例关于中间件和路由。你能够认为其是一个"mini-application"(迷你程序),其具备操做中间件和路由方法的能力。每一个Express
程序有一个内建的app路由。
路由自身表现为一个中间件,因此你可使用它做为app.use()
方法的一个参数或者做为另外一个路由的use()
的参数。
顶层的express
对象有一个Router()
方法,你可使用Router()
来建立一个新的router
对象。
以下,能够建立一个路由:
var router = express.Router([options]);
options
参数能够指定路由的行为,其有下列选择:
属性 | 描述 | 默认值 | 可用性 |
---|---|---|---|
caseSensitive | 是否区分大小写 | 默认不启用。对待/Foo 和/foo 同样。 |
|
mergeParams | 保存父路由的res.params 。若是父路由参数和子路由参数冲突,子路由参数优先。 |
false | 4.5.0+ |
strict | 使能严格路由。 | 默认不启用,/foo 和/foo/ 被路由同样对待处理 |
你能够将router
看成一个程序,能够在其上添加中间件和HTTP路由方法(例如get
,put
,post
等等)。
// invoked for any requests passed to this router
router.use(function(req, res, next) {
// .. some logic here .. like any other middleware
next();
});
// will handle any request that ends in /events
// depends on where the router is "use()'d"
router.get('/events', function(req, res, next) {
// ..
});
你能够在一个特别的根URL上挂载一个路由,这样你就以将你的各个路由放到不一样的文件中或者甚至是mini的程序。
// only requests to /calendar/* will be sent to our "router"
app.use('/calendar', router);
这个方法和router.METHOD()
方法同样,除了这个方法会匹配全部的HTTP动做。
这个方法对想映射全局的逻辑处理到特殊的路径前缀或者任意匹配是十分有用的。好比,若是你放置下面所示的这个路由在其余路由的前面,那么其将要求从这个点开始的全部的路由进行验证操做和自动加载用户信息。记住,这些全局的逻辑操做,不须要结束请求响应周期:loaduser
能够执行一个任务,而后调用next()
来将执行流程移交到随后的路由。
router.all('*', requireAuthentication, loadUser);
相等的形式:
router.all('*', requireAuthentication)
router.all('*', loadUser);
这是一个白名单全局功能的例子。这个例子很像前面的,不过其仅仅做用于以/api
开头的路径:
router.all('/api/*', requireAuthentication);
router.METHOD()
方法提供了路由方法在Express
中,这里的METHOD
是HTTP方法中的一个,好比GET
,PUT
,POST
等等,但router
中的METHOD是小写的。因此,实际的方法是router.get()
,router.put()
,router.post()
等等。
你能够提供多个回调函数,它们的行为和中间件同样,除了这些回调能够经过调用next('router')
来绕过剩余的路由回调。你可使用这个机制来为一个路由设置一些前提条件,若是请求没有知足当前路由的处理条件,那么传递控制到随后的路由。
下面的片断可能说明了最简单的路由定义。Experss转换path字符串为正则表达式,用于内部匹配传入的请求。在匹配的时候,是不考虑Query strings
,例如,"GET /"将匹配下面的路由,"GET /?name=tobi"也是同样的。
router.get('/', function(req, res) {
res.send('Hello World');
});
若是你对匹配的path有特殊的限制,你可使用正则表达式,例如,下面的能够匹配"GET /commits/71dbb9c"和"GET /commits/71bb92..4c084f9"。
router.get(/^\/commits\/(\w+)(?:\.\.(\w+))?$/, function(req, res) {
var from = req.params[0];
var to = req.params[1];
res.send('commit range ' + from + '..' + to);
});
给路由参数添加回调触发器,这里的name
是参数名,function
是回调方法。回调方法的参数按序是请求对象,响应对象,下个中间件,参数值和参数名。虽然name
在技术上是可选的,可是自Express V4.11.0以后版本不推荐使用(见下面)。
不像
app.param()
,router.param()
不接受一个数组做为路由参数。
例如,当:user
出如今路由路径中,你能够映射用户加载的逻辑处理来自动提供req.user
给这个路由,或者对输入的参数进行验证。
router.param('user', function(req, res, next, id) {
User.find(id, function(error, user) {
if (err) {
next(err);
}
else if (user){
req.user = user;
} else {
next(new Error('failed to load user'));
}
});
});
对于Param
的回调定义的路由来讲,他们是局部的。它们不会被挂载的app或者路由继承。因此,定义在router
上的param
回调只有是在router
上的路由具备这个路由参数时才起做用。
在定义param
的路由上,param
回调都是第一个被调用的,它们在一个请求-响应循环中都会被调用一次而且只有一次,即便多个路由都匹配,以下面的例子:
router.param('id', function(req, res, next, id) {
console.log('CALLED ONLY ONCE');
next();
});
router.get('/user/:id', function(req, res, next) {
console.log('although this matches');
next();
});
router.get('/user/:id', function(req, res) {
console.log('and this mathces too');
res.end();
});
当GET /user/42
,获得下面的结果:
CALLED ONLY ONCE
although this matches
and this matches too
`
下面章节描述的
router.param(callback)
在v4.11.0以后被弃用。
经过只传递一个回调参数给router.param(name, callback)
方法,router.param(naem, callback)
方法的行为将被彻底改变。这个回调参数是关于router.param(name, callback)
该具备怎样的行为的一个自定义方法,这个方法必须接受两个参数而且返回一个中间件。
这个回调的第一个参数就是须要捕获的url的参数名,第二个参数能够是任一的JavaScript对象,其可能在实现返回一个中间件时被使用。
这个回调方法返回的中间件决定了当URL中包含这个参数时所采起的行为。
在下面的例子中,router.param(name, callback)
参数签名被修改为了router.param(name, accessId)
。替换接受一个参数名和回调,router.param()
如今接受一个参数名和一个数字。
var express = require('express');
var app = express();
var router = express.Router();
router.param(function(param, option){
return function(req, res, next, val) {
if (val == option) {
next();
}
else {
res.sendStatus(403);
}
}
});
router.param('id', 1337);
router.get('/user/:id', function(req, res) {
res.send('Ok');
});
app.use(router);
app.listen(3000, function() {
console.log('Ready');
});
在这个例子中,router.param(name. callback)
参数签名保持和原来同样,可是替换成了一个中间件,定义了一个自定义的数据类型检测方法来检测user id
的类型正确性。
router.param(function(param, validator) {
return function(req, res, next, val) {
if (validator(val)) {
next();
}
else {
res.sendStatus(403);
}
}
});
router.param('id', function(candidate) {
return !isNaN(parseFloat(candidate)) && isFinite(candidate);
});
返回一个单例模式的路由的实例,以后你能够在其上施加各类HTTP动做的中间件。使用app.route()
来避免重复路由名字(所以错字错误)--后面这句不知道说的什么鬼,大概的意思就是避免同一个路径有两个路由实例。
构建在上面的router.param()
例子之上,下面的代码展现了怎么使用router.route()
来指定各类HTTP方法的处理句柄。
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'));
})
这种方法重复使用单个/usrs/:user_id
路径来添加了各类的HTTP方法。
给可选的path
参数指定的路径挂载给定的中间件方法,未指定path
参数,默认值为/
。
这个方法相似于app.use()
。一个简单的例子和用例在下面描述。查阅app.use()得到更多的信息。
中间件就像一个水暖管道,请求在你定义的第一个中间件处开始,顺着中间件堆栈一路往下,若是路径匹配则处理这个请求。
var express = require('express');
var app = express();
var router = express.Router();
// simple logger for this router`s requests
// all requests to this router will first hit this middleware
router.use(function(req, res, next) {
console.log('%s %s %s', req.method, req.url, req.path);
next();
})
// this will only be invoked if the path starts with /bar form the mount ponit
router.use('/bar', function(req, res, next) {
// ... maybe some additional /bar logging ...
next();
})
// always be invoked
router.use(function(req, res, next) {
res.send('hello world');
})
app.use('/foo', router);
app.listen(3000);
对于中间件function
,挂载的路径是被剥离的和不可见的。关于这个特性主要的影响是对于不一样的路径,挂载相同的中间件可能对代码不作改动,尽管其前缀已经改变。
你使用router.use()
定义中间件的顺序很重要。中间们是按序被调用的,因此顺序决定了中间件的优先级。例如,一般日志是你将使用的第一个中间件,以便每个请求都被记录。
var logger = require('morgan');
router.use(logger());
router.use(express.static(__dirname + '/public'));
router.use(function(req, res) {
res.send('Hello');
});
如今为了支持你不但愿记录静态文件请求,但为了继续记录那些定义在logger()
以后的路由和中间件。你能够简单的将static()
移动到前面来解决:
router.use(express.static(__dirname + '/public'));
router.use(logger());
router.use(function(req, res){
res.send('Hello');
});
另一个确凿的例子是从不一样的路径托管静态文件,你能够将./public
放到前面来得到更高的优先级:
app.use(express.static(__dirname + '/public'));
app.use(express.static(__dirname + '/files'));
app.use(express.static(__dirname + '/uploads'));
router.use()
方法也支持命名参数,以便你的挂载点对于其余的路由而言,可使用命名参数来进行预加载,这样作是颇有益的。