©
This document uses PHP Chinese website manual Release
创建一个Express应用程序。该express()
函数是express
模块导出的顶级函数。
var express = require('express');var app = express();
该中间件在Express v4.16.0及之后版本中提供。
这是Express中内置的中间件功能。它使用JSON有效负载分析传入请求,并基于body-parser。
返回仅分析JSON并仅查看Content-Type
标题与type
选项匹配的请求的中间件。该解析器接受身体的任何Unicode编码并支持自动膨胀gzip
和deflate
编码。
body
包含解析数据的新对象request
在中间件(ie req.body
)之后被填充到对象上,或者{}
如果没有要解析的主体,Content-Type
则不匹配或发生错误,则会填充空对象()。
下表介绍了可选options
对象的属性。
属性 | 描述 | 类型 | 默认 |
---|---|---|---|
inflate | 启用或禁用处理放气(压缩)的物体;当禁用时,放气的物体被拒绝。 | Boolean | true |
limit | 控制最大请求主体大小。如果这是一个数字,那么该值指定字节数;如果它是一个字符串,则将该值传递给字节库以供解析。 | Mixed | “100kb” |
reviver | 作为第二个参数,reviver选项直接传递给JSON.parse。您可以在关于JSON.parse的MDN文档中找到关于此参数的更多信息。 | Function | null |
strict | 启用或禁用只接受数组和对象; 禁用时将接受JSON.parse接受的任何内容。 | Boolean | true |
type | 这用于确定中间件将解析的媒体类型。该选项可以是字符串,字符串数组或函数。如果不是函数,则type选项直接传递到类型库,这可以是扩展名(如json),MIME类型(如application / json)或带有通配符的MIME类型(如* / *或* / json)。如果一个函数,类型选项被称为fn(req),并且如果它返回一个真值,则请求被解析。 | Mixed | "application/json" |
verify | 如果提供此选项,则称为verify(req,res,buf,encoding),其中buf是原始请求主体的缓冲区,编码是请求的编码。解析可以通过抛出错误来中止。 | Function | undefined |
这是Express中内置的中间件功能。它提供静态文件并基于服务静态。
注:为获得最佳结果,请使用反向代理缓存来提高服务静态资产的性能。
root
参数指定要从中为静态资产提供服务的根目录。该功能通过req.url
与提供的root
目录结合来确定要提供的文件。当找不到文件时,它不是发送404响应,而是调用next()
移动到下一个中间件,允许堆叠和回退。
下表介绍了该options
对象的属性。另见下面的例子。
Property | Description | Type | Default |
---|---|---|---|
dotfiles | 确定如何处理点文件(以“。”开头的文件或目录)。请参阅下面的dotfiles。 | String | “ignore” |
etag | 启用或禁用etag生成注意:express.static总是发送弱ETags。 | Boolean | true |
extensions | 设置文件扩展名回退:如果找不到文件,请搜索具有指定扩展名的文件并提供找到的第一个文件。例如:'html','htm'。 | Mixed | false |
fallthrough | 让客户端错误作为未处理的请求发生,否则转发客户端错误。请参阅下面的下文。 | Boolean | true |
immutable | 在Cache-Control响应头中启用或禁用不可变指令。如果启用,还应指定maxAge选项以启用缓存。不可变的指令将阻止受支持的客户端在maxAge选项生命期间发出条件请求,以检查文件是否已更改。 | Boolean | false |
index | 发送指定的目录索引文件。设置为false以禁用目录索引。 | Mixed | “index.html” |
lastModified | 将Last-Modified标题设置为操作系统上文件的最后修改日期。 | Boolean | true |
maxAge | 以毫秒为单位设置Cache-Control标头的max-age属性或以ms格式设置字符串。 | Number | 0 |
redirect | 当路径名称是目录时,重定向到尾随“/”。 | Boolean | true |
setHeaders | 用于设置HTTP头文件的功能。请参阅下面的setHeaders。 | Function |
有关更多信息,请参阅在Express中提供静态文件,并使用中间件 - 内置中间件。
此选项的可能值为:
“allow” - 没有针对dotfiles的特殊处理。
“deny” - 拒绝一个点文件的请求,回应403
,然后调用next()
。
“ignore” - 像dotfile不存在一样,使用404
,然后调用next()
。
注意:使用默认值,它不会忽略以点开头的目录中的文件。
如果选择此选项true
,客户端错误(例如错误的请求或对不存在的文件的请求)将导致此中间件仅调用next()
以调用堆栈中的下一个中间件。如果为false,则会调用这些错误(即使是404)next(err)
。
设置此选项为true
,以便您可以将多个物理目录映射到相同的Web地址或路径以填充不存在的文件。
如果您已经将该中间件安装在严格意义上为单个文件系统目录的路径中,则可以使用false
路径,从而可以短接404s以减少压力。这个中间件也会回复所有的方法。
对于此选项,指定一个函数来设置自定义响应标头。对标题的更改必须同步进行。
该函数的签名是:
fn(res, path, stat)
参数:
res
,响应对象。
path
,正在发送的文件路径。
stat
,stat
正在发送的文件的对象。
下面是一个使用express.static
中间件功能和精心设计的选项对象的例子:
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))
创建一个新的路由器对象。
var router = express.Router([options]);
可选options
参数指定路由器的行为。
属性 | 描述 | 默认 | 可用性 |
---|---|---|---|
caseSensitive | 启用区分大小写。 | 默认情况下禁用,将“/ Foo”和“/ foo”视为相同。 | |
mergeParams | 保留父路由器的req.params值。如果父和子有相互冲突的参数名称,则该子的值优先。 | false | 4.5.0+ |
strict | 启用严格的路由。 | 默认情况下,“/ foo”和“/ foo /”被路由器视为相同。 |
您可以添加中间件和HTTP方法路由(如get
,put
,post
,等),以router
就像一个应用程序。
有关更多信息,请参阅路由器。
该中间件在Express v4.16.0及之后版本中提供。
这是Express中内置的中间件功能。它使用urlencoded有效负载分析传入请求,并基于body-parser。
返回仅分析urlencoded主体的中间件,并仅查看Content-Type
标题与type
选项匹配的请求。该解析器只接受身体的UTF-8编码,并支持自动膨胀gzip
和deflate
编码。
body
包含解析数据的新对象request
在中间件(ie req.body
)之后被填充到对象上,或者{}
如果没有要解析的主体,Content-Type
则不匹配或发生错误,则会填充空对象()。该对象将包含键-值对,其中该值可以是一个字符串或阵列(时extended
是false
),或任何类型的(当extended
是true
)。
下表介绍了可选options
对象的属性。
属性 | 描述 | 类型 | 默认 |
---|---|---|---|
extended | 此选项允许选择使用查询字符串库(如果为false)或qs库(如果为true)解析URL编码数据。“扩展”语法允许将丰富的对象和数组编码为URL编码格式,从而允许使用URL编码的类似JSON的体验。有关更多信息,请参阅qs资料库。 | Boolean | true |
inflate | 启用或禁用处理放气(压缩)的物体; 当禁用时,放气的身体被拒绝。 | Boolean | true |
limit | 控制最大请求主体大小。如果这是一个数字,那么该值指定字节数; 如果它是一个字符串,则将该值传递给字节库以供解析。 | Mixed | “100kb” |
parameterLimit | 该选项控制URL编码数据中允许的最大参数数量。如果请求包含的参数多于此值,则会引发错误。 | Number | 1000 |
type | 这用于确定中间件将解析的媒体类型。该选项可以是字符串,字符串数组或函数。如果不是函数,则type选项将直接传递到type-is库,这可以是扩展名(如urlencoded),MIME类型(如application / x-www-form-urlencoded)或带MIME类型的MIME类型通配符(如* / x-www-form-urlencoded)。如果一个函数,类型选项被称为fn(req),并且如果它返回一个真值,则请求被解析。 | Mixed | "application/x-www-form-urlencoded" |
verify | 如果提供此选项,则称为verify(req,res,buf,encoding),其中buf是原始请求主体的缓冲区,编码是请求的编码。解析可以通过抛出错误来中止。 | Function | undefined |
该app
对象通常表示Express应用程序。通过调用express()
Express模块导出的顶级函数来创建它:
var express = require('express'); var app = express(); app.get('/', function(req, res){ res.send('hello world');}); app.listen(3000);
app
对象有方法
路由HTTP请求;例如,请参阅app.METHOD和app.param。
配置中间件;请参阅app.route。
呈现HTML视图;请参阅app.render。
注册模板引擎;请参阅app.engine。
它还具有影响应用程序行为方式的设置(属性); 有关更多信息,请参阅应用程序设置。
Express应用程序对象可以根据请求对象和响应对象被称为对应的req.app
,和res.app
。
app.locals
对象的属性是应用程序中的局部变量。
app.locals.title// => 'My App' app.locals.email// => 'me@myapp.com'
一旦设置,app.locals
属性的值将在应用程序的整个生命周期中持续存在,而res.locals属性只对请求的生命周期有效。
您可以访问应用程序中呈现的模板中的局部变量。这对于为模板提供帮助函数以及应用程序级数据很有用。局部变量在中间件中可用req.app.locals
(请参阅req.app)
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.METHOD()方法类似,只不过它匹配所有HTTP动词。
参数 | 描述 | 默认 |
---|---|---|
path | 中间件功能被调用的路径; 可以是以下任何一种:表示路径的字符串。路径模式。一个正则表达式模式来匹配路径。上述任何组合的数组。有关示例,请参阅路径示例。 | '/' (root path) |
callback | 回调函数; 可以是:中间件功能。一系列中间件功能(用逗号分隔)。一系列中间件功能。以上所有组合。您可以提供多个回调函数,其行为就像中间件一样,只不过这些回调可以调用next('route')来绕过剩余的路由回调。您可以使用此机制在路线上施加先决条件,并在没有理由继续使用当前路线时将控制权交给后续路线。由于路由器和应用程序实现了中间件接口,因此您可以像使用其他中间件功能一样使用它们。有关示例,请参阅中间件回调函数示例。 | None |
表示路径的字符串。
路径模式。
一个正则表达式模式来匹配路径。
上述任何组合的数组。
有关示例,请参阅路径示例。'/'(根路径)callback
回调函数;可以是:
中间件功能。
一系列中间件功能(用逗号分隔)。
一系列中间件功能。
以上所有组合。
您可以提供多个回调函数,其行为与中间件类似,只是这些回调可以调用next('route')
绕过剩余的路由回调。您可以使用此机制在路线上施加先决条件,并在没有理由继续使用当前路线时将控制权交给后续路线。
由于路由器和应用程序实现了中间件接口,因此您可以像使用其他中间件功能一样使用它们。
有关示例,请参阅中间件回调函数示例。
无
以下回调针对/secret
使用GET,POST,PUT,DELETE或任何其他HTTP请求方法的请求执行:
app.all('/secret', function (req, res, next) { console.log('Accessing the secret section ...') next() // pass control to the next handler});
app.all()
方法对于为特定路径前缀或任意匹配映射“全局”逻辑非常有用。例如,如果将以下内容放在所有其他路由定义的顶部,则要求所有来自该点的路由都要求进行身份验证,并自动加载用户。请记住,这些回调不必作为终点:loadUser
可以执行任务,然后调用next()
继续匹配后续路由。
app.all('*', requireAuthentication, loadUser);
或者相当于:
app.all('*', requireAuthentication);app.all('*', loadUser);
另一个例子是白名单“global”功能。这个例子与上面的例子类似,但它仅限制以“/ api”开头的路径:
app.all('/api/*', requireAuthentication);
使用指定的回调函数将HTTP DELETE请求路由到指定的路径。有关更多信息,请参阅路由指南。
参数 | 描述 | 默认 |
---|---|---|
path | 中间件功能被调用的路径;可以是以下任何一种:表示路径的字符串。路径模式。一个正则表达式模式来匹配路径。上述任何组合的数组。有关示例,请参阅路径示例。 | '/' (root path) |
callback | 回调函数;可以是:中间件功能、一系列中间件功能(用逗号分隔)、一系列中间件功能、以上所有组合。您可以提供多个回调函数,其行为就像中间件一样,只不过这些回调可以调用next('route')来绕过剩余的路由回调。您可以使用此机制在路线上施加先决条件,并在没有理由继续使用当前路线时将控制权交给后续路线。由于路由器和应用程序实现了中间件接口,因此您可以像使用其他中间件功能一样使用它们。有关示例,请参阅中间件回调函数示例。 | None |
表示路径的字符串。
路径模式。
一个正则表达式模式来匹配路径。
上述任何组合的数组。
有关示例,请参阅路径示例。'/'(根路径)callback
回调函数; 可以是:
中间件功能。
一系列中间件功能(用逗号分隔)。
一系列中间件功能。
以上所有组合。
您可以提供多个回调函数,其行为与中间件类似,只是这些回调可以调用next('route')
绕过剩余的路由回调。您可以使用此机制在路线上施加先决条件,并在没有理由继续使用当前路线时将控制权交给后续路线。
由于路由器和应用程序实现了中间件接口,因此您可以像使用其他中间件功能一样使用它们。
有关示例,请参阅中间件回调函数示例。
无
app.delete('/', function (req, res) { res.send('DELETE request to homepage');});
将布尔值设置name
为false
,其中name
是应用程序设置表中的其中一个属性。调用app.set('foo', false)
作为布尔属性与调用app.disable('foo')
相同。
例如:
app.disable('trust proxy'); app.get('trust proxy');// => false
如果布尔设置name
被禁用(false
),返回true。
其中name
是应用程序设置表中的一个属性。
app.disabled('trust proxy');// => true app.enable('trust proxy'); app.disabled('trust proxy');// => false
将布尔值设置name
为true
,其中name
是应用程序设置表中的其中一个属性。调用app.set('foo', true)
布尔属性与调用app.enable('foo')
相同。
app.enable('trust proxy'); app.get('trust proxy');// => true
如果name
启用了设置(true
),返回true
,其中name
是应用程序设置表中的其中一个属性。
app.enabled('trust proxy');// => false app.enable('trust proxy'); app.enabled('trust proxy');// => true
将给定的模板引擎注册callback
为ext
。
默认情况下,Express会根据文件扩展名来require()
引擎。例如,如果您尝试呈现“foo.pug”文件,则Express会在内部调用以下内容,并在随后的调用中缓存require()
以提高性能。
app.engine('pug', require('pug').__express);
对于不提供.__express
开箱即用的引擎,或者如果您希望将不同的扩展名映射到模板引擎,请使用此方法。
例如,要将EJS模板引擎映射到“.html”文件:
app.engine('html', require('ejs').renderFile);
在这种情况下,EJS提供了一个具有Express期望的相同签名(path, options, callback)
的.renderFile()
方法,但请注意,它在ejs.__express
内部将此方法进行了别名,因此如果使用“.ejs”扩展名,则不需要执行任何操作。
Some template engines do not follow this convention. The consolidate.js library maps Node template engines to follow this convention, so they work seamlessly with Express.
var engines = require('consolidate'); app.engine('haml', engines.haml); app.engine('html', engines.hogan);
返回name
应用设置的值,其中name
是应用设置表中的一个字符串。例如:
app.get('title');// => undefined app.set('title', 'My Site'); app.get('title');// => "My Site"
使用指定的回调函数将HTTP GET请求路由到指定的路径。
参数 | 描述 | 默认 |
---|---|---|
path | 中间件功能被调用的路径;可以是以下任何一种:表示路径的字符串、路径模式。一个正则表达式模式来匹配路径。上述任何组合的数组。有关示例,请参阅路径示例。 | '/' (root path) |
callback | 回调函数;可以是:中间件功能。一系列中间件功能(用逗号分隔)。一系列中间件功能。以上所有组合。您可以提供多个回调函数,其行为就像中间件一样,只不过这些回调可以调用next('route')来绕过剩余的路由回调。您可以使用此机制在路线上施加先决条件,并在没有理由继续使用当前路线时将控制权交给后续路线。由于路由器和应用程序实现了中间件接口,因此您可以像使用其他中间件功能一样使用它们。有关示例,请参阅中间件回调函数示例。 | None |
表示路径的字符串。
路径模式。
一个正则表达式模式来匹配路径。
上述任何组合的数组。
For examples, see Path examples. '/' (root path) callback
Callback functions; can be:
中间件功能。
一系列中间件功能(用逗号分隔)。
一系列中间件功能。
以上所有组合。
您可以提供多个回调函数,其行为与中间件类似,只是这些回调可以调用next('route')
绕过剩余的路由回调。您可以使用此机制在路线上施加先决条件,并在没有理由继续使用当前路线时将控制权交给后续路线。
由于路由器和应用程序实现了中间件接口,因此您可以像使用其他中间件功能一样使用它们。
有关示例,请参阅中间件回调函数示例。
无
有关更多信息,请参阅路由指南。
app.get('/', function (req, res) { res.send('GET request to homepage');});
启动一个UNIX套接字并给定路径上的连接。此方法与Node的http.Server.listen()相同。
var express = require('express'); var app = express();app.listen('/tmp/sock');
绑定并侦听指定主机和端口上的连接。此方法与Node的http.Server.listen()相同。
var express = require('express'); var app = express();app.listen(3000);
在app
返回的express()
实际上是一个JavaScript Function
,旨在传递到节点的HTTP服务器作为一个回调来处理请求。这使得您可以轻松地使用相同的代码库为您的应用程序提供HTTP和HTTPS版本,因为应用程序不会从这些应用程序继承(它只是一个回调):
var express = require('express'); var https = require('https'); var http = require('http'); var app = express(); http.createServer(app).listen(80); https.createServer(options, app).listen(443);
app.listen()
方法返回一个http.Server对象,并且(对于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()
,等等。请参阅下面的路由方法以获取完整列表。
参数 | 描述 | 默认 |
---|---|---|
path | 中间件功能被调用的路径; 可以是以下任何一种:表示路径的字符串。路径模式。一个正则表达式模式来匹配路径。上述任何组合的数组。有关示例,请参阅路径示例。 | '/' (root path) |
callback | 回调函数;可以是:中间件功能。一系列中间件功能(用逗号分隔)。一系列中间件功能。以上所有组合。您可以提供多个回调函数,其行为就像中间件一样,只不过这些回调可以调用next('route')来绕过剩余的路由回调。您可以使用此机制在路线上施加先决条件,并在没有理由继续使用当前路线时将控制权交给后续路线。由于路由器和应用程序实现了中间件接口,因此您可以像使用其他中间件功能一样使用它们。有关示例,请参阅中间件回调函数示例。 | None |
表示路径的字符串。
路径模式。
一个正则表达式模式来匹配路径。
上述任何组合的数组。
有关示例,请参阅路径示例 '/' (root path) callback
回调函数;可以是:
中间件功能。
一系列中间件功能(用逗号分隔)。
一系列中间件功能。
以上所有组合。
您可以提供多个回调函数,其行为与中间件类似,只是这些回调可以调用next('route')
绕过剩余的路由回调。您可以使用此机制在路线上施加先决条件,并在没有理由继续使用当前路线时将控制权交给后续路线。
由于路由器和应用程序实现了中间件接口,因此您可以像使用其他中间件功能一样使用它们。
有关示例,请参阅中间件回调函数示例。
无
Express支持以下与相同名称的HTTP方法相对应的路由方法:
checkout copy delete get head lock merge mkactivity | mkcol move m-search notify options patch post | purge put report search subscribe trace unlock unsubscribe |
---|
checkout
copy
delete
get
head
lock
merge
mkactivity
mkcol
move
m-search
notify
options
patch
post
purge
put
report
search
subscribe
trace
unlock
unsubscribe
API文档中有明确的项目只针对最流行的HTTP方法app.get()
,app.post()
,app.put()
,和app.delete()
。但是,上面列出的其他方法的工作方式完全相同。
要路由转换为无效JavaScript变量名称的方法,请使用括号表示法。例如,app['m-search']('/', function ...
。
除了GET
方法之外,如果以前app.head()
没有在app.get()
之前被路径app.get()
调用该函数,则会自动为HTTP HEAD
方法调用该函数。
方法app.all()
不是从任何HTTP方法派生的,并为所有 HTTP请求方法的指定路径加载中间件。有关更多信息,请参阅app.all。
有关路由的更多信息,请参阅路由指南。
添加回调触发器来路由参数,其中name
是参数的名称或它们的数组,并且callback
是回调函数。回调函数的参数依次为请求对象,响应对象,下一个中间件,参数值和参数名称。
如果name
是数组,callback
则为其中声明的每个参数以触发器的声明顺序注册触发器。此外,除了最后一个声明的参数外,next
对回调函数内部的调用将调用下一个声明参数的回调函数。对于最后一个参数,调用next
将为当前正在处理的路由调用下一个中间件,就像它name
只是一个字符串一样。
例如,当:user
存在于路径路径中时,您可以映射用户加载逻辑以自动提供req.user
给路径,或对参数输入执行验证。
app.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')); } });});
Param回调函数在它们被定义的路由器的本地。它们不会被安装的应用程序或路由器继承。因此,定义的参数回调app
将仅由路由上定义的路由参数触发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 matches 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) { console.log('and this matches too'); res.end();});
在GET /user/42/3
,打印如下:
CALLED ONLY ONCE with 42CALLED ONLY ONCE with 3although this matches and this matches too
以下部分描述了app.param(callback)
从v4.11.0开始不推荐使用的部分。
app.param(name, callback)
方法的行为可以完全通过只传递一个函数来改变app.param()
。这个函数是一个app.param(name, callback)
应该如何行为的自定义实现- 它接受两个参数并且必须返回一个中间件。
此函数的第一个参数是应该捕获的URL参数的名称,第二个参数可以是可用于返回中间件实现的任何JavaScript对象。
该函数返回的中间件决定捕获URL参数时发生的行为。
在这个例子中,app.param(name, callback)
签名被修改为app.param(name, accessId)
。app.param()
现在接受一个名字和一个数字,而不是接受一个名字和一个回调。
var express = require('express'); var app = express();// customizing the behavior of app.param() app.param(function(param, option) { return function (req, res, next, val) { if (val == option) { next(); } else { next('route'); } }});// using the customized app.param() app.param('id', 1337);// route to trigger the capture app.get('/user/:id', function (req, res) { res.send('OK');});app.listen(3000, function () { console.log('Ready');});
在此示例中,app.param(name, callback)
签名保持不变,但不是中间件回调,而是定义了自定义数据类型检查函数来验证用户标识的数据类型。
app.param(function(param, validator) { return function (req, res, next, val) { if (validator(val)) { next(); } else { next('route'); } }}); app.param('id', function (candidate) { return !isNaN(parseFloat(candidate)) && isFinite(candidate);});
' .
'字符不能用于捕获捕获正则表达式中的字符。例如,你不能用'/user-.+/'
来捕捉'users-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);
返回应用程序的规范路径,一个字符串。
var app = express() , blog = express() , blogAdmin = express(); app.use('/blog', blog); blog.use('/admin', blogAdmin); console.log(app.path()); // ''console.log(blog.path()); // '/blog'console.log(blogAdmin.path()); // '/blog/admin'
在安装应用程序的复杂情况下,此方法的行为可能会变得非常复杂:通常使用req.baseUrl获取应用程序的规范路径会更好。
使用指定的回调函数将HTTP POST请求路由到指定的路径。有关更多信息,请参阅路由指南。
参数 | 描述 | 默认 |
---|---|---|
path | 中间件功能被调用的路径;可以是以下任何一种:表示路径的字符串、路径模式和正则表达式模式来匹配路径,或上述任何组合的数组。有关示例,请参阅路径示例。 | '/' (root path) |
callback | 回调函数;可以是:中间件功能、一系列中间件功能(用逗号分隔)、一系列中间件功能,或以上所有组合。您可以提供多个回调函数,其行为就像中间件一样,只不过这些回调可以调用next('route')来绕过剩余的路由回调。您可以使用此机制在路线上施加先决条件,并在没有理由继续使用当前路线时将控制权交给后续路线。由于路由器和应用程序实现了中间件接口,因此您可以像使用其他中间件功能一样使用它们。有关示例,请参阅中间件回调函数示例。 | None |
表示路径的字符串。
路径模式。
一个正则表达式模式来匹配路径。
上述任何组合的数组。
有关示例,请参阅路径示例,'/' (root path) callback
回调函数;可以是:
中间件功能。
一系列中间件功能(用逗号分隔)。
一系列中间件功能。
以上所有组合。
您可以提供多个回调函数,其行为与中间件类似,只是这些回调可以调用next('route')
绕过剩余的路由回调。您可以使用此机制在路线上施加先决条件,并在没有理由继续使用当前路线时将控制权交给后续路线。
由于路由器和应用程序实现了中间件接口,因此您可以像使用其他中间件功能一样使用它们。
有关示例,请参阅中间件回调函数示例。
无
app.post('/', function (req, res) { res.send('POST request to homepage');});
使用指定的回调函数将HTTP PUT请求路由到指定的路径。
参数 | 描述 | 默认 |
---|---|---|
path | 中间件功能被调用的路径;可以是以下任何一种:表示路径的字符串、路径模式、一个正则表达式模式来匹配路径以及上述任何组合的数组。有关示例,请参阅路径示例。 | '/' (root path) |
callback | 回调函数;可以是:中间件功能、一系列中间件功能(用逗号分隔)、一系列中间件功能,及以上所有组合。您可以提供多个回调函数,其行为就像中间件一样,只不过这些回调可以调用next('route')来绕过剩余的路由回调。您可以使用此机制在路线上施加先决条件,并在没有理由继续使用当前路线时将控制权交给后续路线。由于路由器和应用程序实现了中间件接口,因此您可以像使用其他中间件功能一样使用它们。有关示例,请参阅中间件回调函数示例。 | None |
表示路径的字符串。
路径模式。
一个正则表达式模式来匹配路径。
上述任何组合的数组。
有关示例,请参阅路径示例。 '/' (root path)callback
回调函数; 可以是:
中间件功能。
一系列中间件功能(用逗号分隔)。
一系列中间件功能。
以上所有组合。
您可以提供多个回调函数,其行为与中间件类似,只是这些回调可以调用next('route')
绕过剩余的路由回调。您可以使用此机制在路线上施加先决条件,并在没有理由继续使用当前路线时将控制权交给后续路线。
由于路由器和应用程序实现了中间件接口,因此您可以像使用其他中间件功能一样使用它们。
有关示例,请参阅中间件回调函数示例。
无
app.put('/', function (req, res) { res.send('PUT request to homepage');});
通过callback
函数返回视图的呈现HTML 。它接受一个可选参数,该参数是包含视图的局部变量的对象。它就像res.render()一样,除了它不能将渲染视图自己发送到客户端。
将其app.render()
视为用于生成呈现视图字符串的实用程序函数。内部res.render()
用于app.render()
渲染视图。
本地变量cache
保留用于启用视图缓存。如果您想在开发期间缓存视图将其设置为true
;在生产中默认启用视图缓存。
app.render('email', function(err, html){ // ...}); app.render('email', { name: 'Tobi' }, function(err, html){ // ...});
返回单个路由的实例,然后您可以使用该实例来处理具有可选中间件的HTTP动词。使用app.route()
以避免重复路线名称(因此出现打字错误)。
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
。您可以存储您想要的任何值,但某些名称可用于配置服务器的行为。这些特殊名称在应用程序设置表中列出。
调用app.set('foo', true)
作为布尔属性与调用app.enable('foo')
相同。同样,调用app.set('foo', false)
作为布尔属性与调用app.disable('foo')
相同。
用app.get()
检索设置的值。
app.set('title', 'My Site'); app.get('title'); // "My Site"
下表列出了应用程序设置。
请注意,子应用程序将:
不继承具有默认值的设置的值。您必须在子应用程序中设置值。
继承没有默认值的设置值; 这些在下表中明确指出。
例外情况:子应用程序将继承trust proxy
的值,即使它具有默认值(用于向后兼容)。子应用程序不会继承view cache
生产中的价值(当NODE_ENV
是“production”)。
属性 | 类型 | 描述 | 默认 |
---|---|---|---|
case sensitive routing | 布尔 | 启用区分大小写。启用时,“/ Foo”和“/ foo”是不同的路线。禁用时,“/ Foo”和“/ foo”的处理方式相同。注意:子应用程序将继承此设置的值。 | N/A (undefined) |
env | 串 | 环境模式。确保在生产环境中设置为“生产”; 请参阅生产最佳实践:性能和可靠性。 | process.env.NODE_ENV (NODE_ENV environment variable) or “development” if NODE_ENV is not set. |
etag | 多变 | 设置ETag响应标题。有关可能的值,请参阅etag选项表。有关HTTP ETag标头的更多信息。 | weak |
jsonp callback name | 串 | 指定默认的JSONP回调名称。 | “callback” |
json escape | 布尔 | 启用从res.json,res.jsonp和res.send API转义的JSON响应。这将在JSON中转义字符<,>和&作为Unicode转义序列。这样做的目的是当客户端嗅探HTML响应时协助减轻某些类型的持续XSS攻击。注意:子应用程序将继承此设置的值。 | N/A (undefined) |
json replacer | 多变 | '替代者'论证使用的JSON.stringify。注意:子应用程序将继承此设置的值。 | N/A (undefined) |
json spaces | 多变 | “空间”论证使用JSON.stringify。这通常设置为用于缩进美化JSON的空格数量。注意:子应用程序将继承此设置的值。 | N/A (undefined) |
query parser | 多变 | 通过将该值设置为false来禁用查询分析,或者将查询分析器设置为使用“简单”或“扩展”或自定义查询字符串分析功能。简单的查询解析器基于Node的本地查询解析器querystring。扩展查询解析器基于qs。自定义查询字符串解析函数将接收完整的查询字符串,并且必须返回查询关键字及其值的对象。 | "extended" |
strict routing | 布尔 | 启用严格的路由。启用时,路由器将“/ foo”和“/ foo /”视为不同。否则,路由器将“/ foo”和“/ foo /”视为相同。注意:子应用程序将继承此设置的值。 | N/A (undefined) |
subdomain offset | 数 | 要移除以访问子域的主机的点分离部分的数量。 | 2 |
trust proxy | 多变 | 指示应用程序位于前置代理后面,并使用X-Forwarded- *标题确定客户端的连接和IP地址。注:X-Forwarded- *标头很容易被欺骗,检测到的IP地址不可靠。启用后,Express会尝试确定通过前置代理或一系列代理连接的客户端的IP地址。该req.ips属性然后包含客户端连接的一组IP地址。要启用它,请使用信任代理选项表中描述的值。该trust proxy设置是使用proxy-addr软件包实现的。有关更多信息,请参阅其文档。注:子应用程序将继承此设置的值,即使它具有默认值。 | false (disabled) |
views | 字符串或数组 | 应用程序视图的目录或目录数组。如果是数组,那么视图按照它们在数组中出现的顺序查找。 | process.cwd()+'/ views' |
view cache | 布尔 | 启用视图模板编译缓存。注意:子应用程序不会继承生产中此设置的值(何时NODE\_ENV为“生产”)。 | true in production, otherwise undefined. |
view engine | 串 | 省略时使用的默认引擎扩展。注意:子应用程序将继承此设置的值。 | N/A (undefined) |
x-powered-by | 布尔 | 启用“X-Powered-By:Express”HTTP标头。 | true |
loopback - 127.0.0.1/8
, ::1/128
linklocal - 169.254.0.0/16
, fe80::/10
uniquelocal - 10.0.0.0/8
, 172.16.0.0/12
, 192.168.0.0/16
, fc00::/7
通过以下任何方式设置IP地址:
指定一个子网:
app.set('trust proxy', 'loopback')
指定一个子网和一个地址:
app.set('trust proxy', 'loopback, 123.123.123.123')
指定多个子网为CSV:
app.set('trust proxy', 'loopback, linklocal, uniquelocal')
将多个子网指定为一个数组:
app.set('trust proxy', 'loopback', 'linklocal', 'uniquelocal')
指定时,将从地址确定过程中排除IP地址或子网,并将离应用程序服务器最近的不可信IP地址确定为客户端的IP地址。
Number Trust the _n_th hop from the front-facing proxy server as the client.
Function Custom trust implementation. Use this only if you know what you are doing.
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` setting
注:这些设置仅适用于动态文件,而不适用于静态文件。express.static中间件忽略这些设置。
ETag功能是使用etag软件包实现的。有关更多信息,请参阅其文档。
类型值布尔值 true
启用弱ETag。这是默认设置。
false
完全禁用ETag。
String If "strong", enables strong ETag.
如果“weak”,弱化ETag。函数自定义ETag函数的实现。只有当你知道你在做什么时才使用。
app.set('etag', function (body, encoding) { return generateHash(body, encoding); // consider the function is defined });
在指定的路径上安装指定的中间件功能或中间件功能:当请求的路径的基础匹配时,执行中间件功能path
。
参数 | 描述 | 默认 |
---|---|---|
path | 中间件功能被调用的路径;可以是以下任何一种:表示路径的字符串、路径模式、一个正则表达式模式来匹配路径、或上述任何组合的数组。有关示例,请参阅路径示例。 | '/' (root path) |
callback | 回调函数; 可以是:中间件功能、一系列中间件功能(用逗号分隔)、一系列中间件功能、或以上所有组合。您可以提供多个回调函数,其行为就像中间件一样,只不过这些回调可以调用next('route')来绕过剩余的路由回调。您可以使用此机制在路线上施加先决条件,并在没有理由继续使用当前路线时将控制权交给后续路线。由于路由器和应用程序实现了中间件接口,因此您可以像使用其他中间件功能一样使用它们。有关示例,请参阅中间件回调函数示例。 | None |
表示路径的字符串。
路径模式。
一个正则表达式模式来匹配路径。
上述任何组合的数组。
有关示例,请参阅路径示例'/' (root path)callback
回调函数;可以是:
中间件功能。
一系列中间件功能(用逗号分隔)。
一系列中间件功能。
以上所有组合。
您可以提供多个回调函数,其行为与中间件类似,只是这些回调可以调用next('route')
绕过剩余的路由回调。您可以使用此机制在路线上施加先决条件,并在没有理由继续使用当前路线时将控制权交给后续路线。
由于路由器和应用程序实现了中间件接口,因此您可以像使用其他中间件功能一样使用它们。
For examples, see Middleware callback function examples.
空
一条路径将立即匹配其路径后跟一个“ /
”的任何路径。例如:app.use('/apple', ...)
将匹配“/ apple”,“/ apple / images”,“/ apple / images / news”等。
由于path
缺省设置为“/”,因此无需路径安装的中间件将针对应用程序的每个请求执行。
例如,该中间件功能将针对应用程序的每个请求执行:
app.use(function (req, res, next) { console.log('Time: %d', Date.now()); next();});
注意
子应用程序将:
不继承具有默认值的设置的值。您必须在子应用程序中设置值。
继承没有默认值的设置值。
有关详情,请参阅应用程序设置
中间件功能是按顺序执行的,因此中间件包含的顺序非常重要。
// this middleware will not allow the request to go beyond itapp.use(function(req, res, next) { res.send('Hello World');});// requests will never reach this routeapp.get('/', function (req, res) { res.send('Welcome');});
错误处理中间件
错误处理中间件始终需要四个参数。您必须提供四个参数来将其标识为错误处理中间件功能。即使您不需要使用该next
对象,也必须指定它以维护签名。否则,该next
对象将被解释为常规中间件,并且将无法处理错误。有关错误处理中间件的详细信息,请参阅:错误处理。
使用与其他中间件功能相同的方式定义错误处理中间件函数,除了使用四个参数而不是三个参数,特别是签名(err, req, res, next)
):
app.use(function(err, req, res, next) { console.error(err.stack); res.status(500).send('Something broke!');});
下表提供了一些path
有关安装中间件的有效值的简单示例。
类型 | 示例 |
---|---|
路径 | 这将匹配从以下开始的路径/abcd:app.use('/ abcd',function(req,res,next){next();}); |
路径模式 | 这将匹配以/abcd和开头的路径/abd:app.use('/ abc?d',function(req,res,next){next();}); 这将匹配开始路径/abcd,/abbcd,/abbbbbcd,等:app.use( '/ AB + CD',功能(REQ,RES,下一个){下一个();}); 这将匹配开始路径/abcd,/abxcd,/abFOOcd,/abbArcd,等:app.use( '/ AB \ * CD',功能(REQ,RES,下一个){下一个();}); 这将匹配以/ad和开头的路径/abcd:app.use('/ a(bc)?d',function(req,res,next){next();}); |
正则表达式 | 这将匹配以/abc和开头的路径/xyz:app.use(/ \ / abc | \ / xyz /,function(req,res,next){next();}); |
排列 | 这将匹配的路径开始/abcd,/xyza,/lmn,和/pqr:app.use( '/ ABCD', '/ XYZA',/ \ / LMN | \ / PQR /,功能(REQ,RES,下一个){下一个();}) ; |
下表提供了可被用作的中间件功能一些简单的例子callback
参数app.use()
,app.METHOD()
和app.all()
。尽管例子是app.use()
,它们也适用于app.use()
,app.METHOD()
和app.all()
。
用法 | 示例 |
---|---|
单一中间件 | 您可以在本地定义和安装中间件功能。app.use(function(req,res,next){next();}); 路由器是有效的中间件。var router = express.Router(); router.get('/',function(req,res,next){next();}); app.use(路由器); 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); |
组合 | 您可以结合上述所有安装中间件的方式。函数mw1(req,res,next){next(); }函数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中间件的一些示例。
从应用程序目录中的“公共”目录为应用程序提供静态内容:
// GET /style.css etcapp.use(express.static(__dirname + '/public'));
仅当中间件的请求路径前缀为“/ static”时,才将中间件装入“/ static”以提供静态内容:
// GET /static/style.css etc.app.use('/static', express.static(__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请求,并具有请求查询字符串,参数,正文,HTTP标头等的属性。在本文档中,按照惯例,该对象总是被称为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);});
req
对象是Node自身请求对象的增强版本,并支持所有内置字段和方法。
在Express 4中,默认情况下req.files
在req
对象中不再可用。要访问req.files
对象上的上传文件,请使用多部件处理中间件,如busboy,multer,formidable,multiparty,connect-multiparty或pez。
该属性包含对使用中间件的Express应用程序实例的引用。
如果您遵循创建模块的模式,该模块只是将中间件功能导出并将require()
其存储在主文件中,那么中间件可以通过req.app
以下方式访问Express实例:
例如:
//index.jsapp.get('/viewdirectory', require('./mymiddleware.js'))
//mymiddleware.jsmodule.exports = function (req, res) { res.send('The views directory is ' + req.app.get('views'));});
路由器实例安装的URL路径。
req.baseUrl
属性与app
对象的mountpath属性相似,但app.mountpath
返回匹配的路径模式。
例如:
var greet = express.Router();greet.get('/jp', function (req, res) { console.log(req.baseUrl); // /greet res.send('Konichiwa!');});app.use('/greet', greet); // load the router on '/greet'
即使您使用路径模式或一组路径模式来加载路由器,该baseUrl
属性也会返回匹配的字符串,而不是模式。在以下示例中,greet
路由器以两种路径模式加载。
app.use(['/gre+t', '/hel{2}o'], greet); // load the router on '/gre+t' and '/hel{2}o'
当向/greet/jp
,req.baseUrl
提出的请求是“/greet”。当向/hello/jp
提出的请求是,req.baseUrl
是“/ hello”。
包含请求正文中提交的键值对数据。默认情况下,是undefined
。使用body-parser和multer等body分析中间件时被填充。
以下示例显示如何使用body分析中间件来填充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解析器中间件时,此属性是包含请求发送的Cookie的对象。如果请求不包含cookie,则默认为{}
。
// Cookie: name=tjreq.cookies.name// => "tj"
如果cookie已被签名,则必须使用req.signedCookies。
有关更多信息,问题或疑虑,请参阅cookie解析器。
指示请求是否为“fresh”。与此相反req.stale
。
如果cache-control
请求头没有no-cache
指令并且下列任何一个都为真,那么这是真的:
if-modified-since
请求标头中指定和last-modified
请求标头是等于或早于modified
响应。
if-none-match
请求标头是*
。
if-none-match
请求标头中,在被解析成它的指令,不匹配etag
的响应标头。
req.fresh// => true
有关更多信息,问题或疑虑,请参阅全新。
包含从Host
HTTP头派生的主机名。
当trust proxy
设置不计算时false
,此属性将改为具有X-Forwarded-Host
标题字段的值。这个标头可以由客户端或代理来设置。
// Host: "example.com:3000"req.hostname// => "example.com"
包含请求的远程IP地址。
当trust proxy
设置不计算到false
时,此属性的值将从头中最左边的条目派生X-Forwarded-For
。这个标头可以由客户端或代理来设置。
req.ip// => "127.0.0.1"
当trust proxy
设置不计算false
时,该属性包含X-Forwarded-For
请求头中指定的IP地址数组。否则,它包含一个空数组。这个头可以由客户端或代理来设置。
例如,如果X-Forwarded-For
是client, proxy1, proxy2
,req.ips
将是["client", "proxy1", "proxy2"]
,其中proxy2
是下游最远的。
包含对应于该请求的HTTP方法的字符串:GET
,POST
,PUT
,等。
req.url
不是本机Express特性,它是从Node的http模块继承而来的。
这个属性很像req.url
; 但是,它保留了原始的请求URL,允许您req.url
为内部路由目的自由重写。例如,app.use()的“挂载”功能将重写req.url
以剥离挂载点。
// GET /search?q=somethingreq.originalUrl// => "/search?q=something"
在中间件功能,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' next();});
该属性是一个包含映射到指定路由“参数”的属性的对象。例如,如果您有路线/user/:name
,那么“名称”属性可用req.params.name
。该对象默认为{}
。
// GET /user/tjreq.params.name// => "tj"
当为路由定义使用正则表达式时,使用的数组中提供了捕获组req.params[n]
,其中n
是第n个捕获组。此规则适用于具有字符串路由的未命名通配符匹配,例如/file/*
:
// GET /file/javascripts/jquery.jsreq.params[0]// => "javascripts/jquery.js"
如果您需要对键进行更改req.params
,请使用app.param处理程序。更改仅适用于已在路径路径中定义的参数。
对req.params
中间件或路由处理程序中的对象所做的任何更改都将被重置。
包含请求URL的路径部分。
// example.com/users?sort=descreq.path// => "/users"
从中间件调用时,挂载点不包含在内req.path
。有关更多详细信息,请参阅app.use()。
包含请求协议字符串:http
或者(for TLES requests)https
。
如果trust proxy
设置不计算为false
,则此属性将使用X-Forwarded-Proto
标题字段的值(如果存在)。这个标头可以由客户端或代理来设置。
req.protocol// => "http"
此属性是包含路由中每个查询字符串参数的属性的对象。如果没有查询字符串,它是空的对象,{}
。
// GET /search?q=tobi+ferretreq.query.q// => "tobi ferret"// GET /shoes?order=desc&shoe[color]=blue&shoe[type]=conversereq.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 } }
一个Boolean属性,如果建立了TLS连接,则为true。相当于:
'https' == req.protocol;
当使用cookie解析器中间件时,该属性包含请求发送的签名cookie,未签名并可以使用。签名的cookies位于不同的对象中以显示开发者的意图;否则,可能会对req.cookie
值进行恶意攻击(这很容易被欺骗)。请注意,签名cookie不会使其“隐藏”或加密;但只是防止篡改(因为用于签名的秘密是私密的)。
如果未发送签名的cookie,则属性默认为{}
。
// Cookie: user=tobi.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3req.signedCookies.user// => "tobi"
有关更多信息,问题或疑虑,请参阅cookie解析器。
指示请求是否为“stale”,还是与之相反req.fresh
。有关更多信息,请参阅req.fresh。
req.stale// => true
请求的域名中的一组子域。
// Host: "tobi.ferrets.example.com"req.subdomains// => ["ferrets", "tobi"]
应用程序属性subdomain offset
(默认为2)用于确定子域分段的开始。要更改此行为,请使用app.set更改其值。
一个布尔属性,true
如果请求的X-Requested-With
头部字段是“XMLHttpRequest”,则表示该请求是由诸如jQuery之类的客户端库发出的。
req.xhr// => true
根据请求的Accept
HTTP头字段检查指定的内容类型是否可接受。该方法返回最佳匹配,或者如果没有指定的内容类型是可接受的,则返回false
(在这种情况下,应用程序应回应406 "Not Acceptable"
)。
type
值可以是单个MIME类型的字符串(如“application / json”),扩展名称(如“json”),逗号分隔列表或数组。对于列表或数组,该方法返回最佳匹配(如果有)。
// Accept: text/htmlreq.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"
根据请求的Accept-Charset
HTTP头字段返回指定字符集的第一个接受字符集。如果没有指定的字符集被接受,则返回false
。
根据请求的Accept-Encoding
HTTP头字段返回指定编码的第一个可接受的编码。如果没有指定的编码被接受,则返回false
。
根据请求的Accept-Language
HTTP头字段返回指定语言的第一个接受的语言。如果没有指定的语言被接受,则返回false
。
返回指定的HTTP请求标头字段(不区分大小写的匹配)。在Referrer
和Referer
领域是可以互换的。
req.get('Content-Type');// => "text/plain"req.get('content-type');// => "text/plain"req.get('Something');// => undefined
别名为req.header(field)
。
如果传入请求的“Content-Type”HTTP标头字段与type
参数指定的MIME类型相匹配,则返回匹配的内容类型。否则返回false
。
// With Content-Type: text/html; charset=utf-8req.is('html'); // => 'html' req.is('text/html'); // => 'text/html' req.is('text/*'); // => 'text/*' // When Content-Type is application/json req.is('json'); // => 'json' req.is('application/json'); // => 'application/json' req.is('application/*'); // => 'application/*' req.is('html'); // => false
已过时。二者必选其一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"
查找按以下顺序执行:
req.params
req.body
req.query
或者,如果在任何请求对象中找不到该参数,则可以指定defaultValue
设置默认值。
直接访问req.body
,req.params
以及req.query
应该赞成清晰-除非你真正接受来自每个对象的输入。
body解析中间件必须被加载以便req.param()
可预测地工作。详情请参阅req.body。
Range
标头解析器。
该size
参数是资源的最大大小。
options
参数是一个可以具有以下属性的对象。
属性 | 类型 | 描述 |
---|---|---|
combine | Boolean | 指定是否重叠和相邻范围应该组合,默认为false。如果为true,范围将被组合并返回,就像它们在标题中指定的那样。 |
将返回范围数组或表示错误解析的负数。
-2
表示格式错误的标题字符串
-1
表示不可满足的范围
// parse header from requestvar range = req.range(1000)// the type of the rangeif (range.type === 'bytes') { // the ranges range.forEach(function (r) { // do something with r.start and r.end })}
res
对象表示Express应用程序在获取HTTP请求时发送的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);});
res
对象是Node自身响应对象的增强版本,并支持所有内置字段和方法。
该属性包含对使用中间件的Express应用程序实例的引用。
res.app
与请求对象中的req.app属性相同。
指示应用程序是否为响应发送HTTP标头的布尔属性。
app.get('/', function (req, res) { console.log(res.headersSent); // false res.send('OK'); 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()
由Express v4.11.0 +支持
将指定的附加value
到HTTP响应标头field
。如果标题尚未设置,则会使用指定的值创建标题。该value
参数可以是字符串或数组。
注:调用res.set()
之后res.append()
将重置先前设置的标头值。
res.append('Link', ['<http://localhost/>', '<http://localhost:3000/>']); res.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly'); res.append('Warning', '199 Miscellaneous warning');
将HTTP响应Content-Disposition
标题字段设置为“附件”。如果给出filename
,那么它通过扩展名设置Content-Type res.type()
,并设置Content-Disposition
“filename =”参数。
res.attachment();// Content-Disposition: attachmentres.attachment('path/to/logo.png'); // Content-Disposition: attachment; filename="logo.png"// Content-Type: image/png
将cookiename
设置为value
。该value
参数可能是一个字符串或对象转换为JSON。
options
参数是一个可以具有以下属性的对象。
属性 | 类型 | 描述 |
---|---|---|
domain | String | Cookie的域名。默认为应用程序的域名。 |
encode | Function | 用于cookie值编码的同步函数。默认为encodeURIComponent。 |
expires | Dat | 以GMT格式的cookie的有效日期。如果未指定或设置为0,则创建会话cookie。 |
httpOnly | Boolean | 将cookie标记为仅可由Web服务器访问。 |
maxAge | Number | 方便的选项,用于设置相对于当前时间的到期时间(以毫秒为单位)。 |
path | String | Cookie的路径。默认为“/”。 |
secure | Boolean | 将cookie标记为仅与HTTPS一起使用。 |
signed | Boolean | 指示是否应该对cookie进行签名。 |
sameSit | Boolean or String | “SameSite”Set-Cookie属性的值。更多信息请访问https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00#section-4.1.1。 |
所有的res.cookie()
操作都是Set-Cookie
使用提供的选项设置HTTP 标头。任何未指定的选项都默认为RFC 6265中规定的值。
例如:
res.cookie('name', 'tobi', { domain: '.example.com', path: '/admin', secure: true }); res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
encode
选项允许您选择用于cookie值编码的功能。不支持异步功能。
示例用例:您需要为组织中的其他站点设置一个域范围的cookie。这个其他网站(不在您的管理控制下)不使用URI编码的cookie值。
//Default encoding res.cookie('some_cross_domain_cookie', 'http://mysubdomain.example.com',{domain:'example.com'}); // Result: 'some_cross_domain_cookie=http%3A%2F%2Fmysubdomain.example.com; Domain=example.com; Path=/'//Custom encodingres.cookie('some_cross_domain_cookie', 'http://mysubdomain.example.com', {domain:'example.com', encode: String});// Result: 'some_cross_domain_cookie=http://mysubdomain.example.com; Domain=example.com; Path=/;'
maxAge
选项是一个方便的选项,用于设置相对于当前时间的“过期”(以毫秒为单位)。以下相当于上面的第二个例子。
res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true });
您可以传递一个对象作为value
参数; 然后将其序列化为JSON并由bodyParser()
中间件进行分析。
res.cookie('cart', { items: [1,2,3] });res.cookie('cart', { items: [1,2,3] }, { maxAge: 900000 });
在使用Cookie解析器中间件时,此方法也支持签名的Cookie。只需将包含signed
的选项设置为true
即可。然后将使用res.cookie()
传递给它的密码cookieParser(secret)
来签名。
res.cookie('name', 'tobi', { signed: true });
稍后,您可以通过req.signedCookie对象访问此值。
通过name
清除指定的cookie 。有关该options
对象的详细信息,请参阅res.cookie()。
Web浏览器和其他兼容的客户端将只清除cookie,如果给定的options
是给res.cookie(),排除expires
和maxAge
。
res.cookie('name', 'tobi', { path: '/admin' });res.clearCookie('name', { path: '/admin' });
options
在Express v4.16.0及更高版本支持可选参数。
path
以“附件”的形式传输文件。通常,浏览器会提示用户下载。默认情况下,Content-Disposition
头文件“filename =”参数是path
(通常出现在浏览器对话框中)。用filename
参数覆盖此默认值。
当发生错误或传输完成时,该方法会调用可选的回调函数fn
。此方法使用res.sendFile()传输文件。
可选options
参数传递给底层res.sendFile()调用,并使用完全相同的参数。
res.download('/report-12345.pdf'); res.download('/report-12345.pdf', 'report.pdf'); res.download('/report-12345.pdf', 'report.pdf', function(err){ if (err) { // Handle error, but keep in mind the response may be partially-sent // so check res.headersSent } else { // decrement a download credit, etc. }});
结束响应过程。这个方法实际上来自Node核心,特别是http.ServerResponse的response.end()方法。
用于快速结束没有任何数据的响应。如果您需要使用数据进行响应,请使用res.send()和res.json()等方法。
res.end();res.status(404).end();
Accept
对请求对象上的HTTP标头执行内容协商(如果存在)。它使用req.accepts()根据按质量值排序的可接受类型为请求选择处理程序。如果头没有指定,则调用第一个回调函数。当找不到匹配时,服务器回应406“不可接受”,或调用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() { // log the request and respond with 406 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' }); }});
返回由指定的HTTP响应头field
。不区分大小写。
res.get('Content-Type');// => "text/plain"
发送JSON响应。此方法使用JSON.stringify()将响应(使用正确的内容类型)作为参数转换为JSON字符串。
该参数可以是任何JSON类型,包括对象,数组,字符串,布尔值或数字,您也可以使用它将其他值转换为JSON,例如null
和undefined
(尽管这些在技术上无效JSON)。
res.json(null); res.json({ user: 'tobi' }); res.status(500).json({ error: 'message' });
使用JSONP支持发送JSON响应。res.json()
除了它选择JSONP回调支持之外,此方法与之相同。
res.jsonp(null);// => callback(null) res.jsonp({ user: 'tobi' });// => callback({ "user": "tobi" })res.status(500).jsonp({ error: 'message' });// => callback({ "error": "message" })
默认情况下,JSONP回调名称callback
很简单。用jsonp回调名称设置覆盖它。
以下是使用相同代码的JSONP响应的一些示例:
// ?callback=foores.jsonp({ user: 'tobi' }); // => foo({ "user": "tobi" }) app.set('jsonp callback name', 'cb'); // ?cb=foores.status(500).jsonp({ error: 'message' }); // => foo({ "error": "message" })
连接links
提供的参数属性以填充响应的Link
HTTP标头字段。
For example, the following call:
res.links({ next: 'http://api.example.com/users?page=2', last: 'http://api.example.com/users?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
“后”的值具有特殊的含义,它指的是在指定的URL Referer
的请求的报头中。如果Referer
未指定标题,则表示“/”。
对URL进行编码后,如果尚未编码,Express会将指定的URL传递到Location
标头中的浏览器,而不进行任何验证。
浏览器负责从当前URL或引用URL以及Location
头中指定的URL中派生出预期的URL ; 并相应地重定向用户。
重定向到从指定的URL派生的URL path
,带有指定的status
,与HTTP状态代码对应的正整数。如果未指定,则status
默认为“找到”302。
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
,则以下将重定向到URL http://example.com/admin
:
res.redirect('/admin');
重定向可以相对于当前的URL。例如,http://example.com/blog/admin/
(注意尾部斜线),以下内容将重定向到URL http://example.com/blog/admin/post/new
。
res.redirect('post/new');
重定向到post/new
的http://example.com/blog/admin
(没有尾随斜线),会重定向到http://example.com/blog/post/new
。
如果您发现上述行为令人困惑,请将路径段视为目录(尾随斜杠)和文件,它将开始有意义。
路径相对重定向也是可能的。如果你打开http://example.com/admin/post/new
,以下将重定向到http://example.com/admin/post
:
res.redirect('..');
back
重定向请求重定向回引荐,默认为/
引荐丢失时。
res.redirect('back');
渲染view
并将呈现的HTML字符串发送到客户端。可选参数:
locals
,其属性定义视图的局部变量的对象。
callback
,一个回调函数。如果提供,该方法返回可能的错误和呈现的字符串,但不执行自动响应。发生错误时,该方法将在next(err)
内部调用。
view
参数是一个字符串,它是视图文件来加载的文件路径。这可以是绝对路径,也可以是相对于views
设置的路径。如果路径不包含文件扩展名,则该view engine
设置将确定文件扩展名。如果路径包含文件扩展名,则Express将加载指定模板引擎的模块(通过require()
)并使用加载模块的__express
函数来加载它。
有关更多信息,请参阅使用Express模板引擎。
注:view
参数执行文件系统操作,比如从磁盘读取文件和评估的Node.js模块,并且因此出于安全考虑,不应该包含从最终用户的输入。
本地变量cache
启用视图缓存。将其设置为true
,在开发期间缓存视图; 视图缓存在生产中默认启用。
// send the rendered view to the clientres.render('index');// if a callback is specified, the rendered HTML string has to be sent explicitly res.render('index', function(err, html) { res.send(html);});// pass a local variable to the viewres.render('user', { name: 'Tobi' }, function(err, html) { // ...});
发送HTTP响应。
body
参数可以是一个Buffer
对象,一个String
对象或一个Array
。例如:
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>'));
当参数是String
时,该方法设置Content-Type
为“text / html”:
res.send('<p>some html</p>');
当参数是Array
或者Object
时,Express以JSON表示响应:
res.send({ user: 'tobi' });res.send([1,2,3]);
res.sendFile()
由Express v4.8.0起支持。
在给定的位置path
传输文件。Content-Type
根据文件名的扩展名设置响应HTTP头字段。除非root
在选项对象中设置选项,否则path
必须是该文件的绝对路径。
下表提供了options
参数的详细信息。
属性 | 描述 | 默认 | 可用性 |
---|---|---|---|
MAXAGE | 以毫秒为单位设置Cache-Control标头的max-age属性,或以ms格式设置字符串 | 0 | |
root | 相对文件名的根目录。 | ||
lastModified | 将Last-Modified标头设置为OS上文件的最后修改日期。设置为false将其禁用。 | 启用 | 4.9.0+ |
headers | 包含HTTP标头的对象以与该文件一起提供。 | ||
dotfiles | 提供点文件的选项。可能的值是“允许”,“拒绝”,“忽略”。 | “忽视” | |
acceptRanges | 启用或禁用接受范围的请求。 | 真正 | 4.14+ |
CacheControl | 启用或禁用设置缓存控制响应头。 | 真正 | 4.14+ |
一成不变 | 在Cache-Control响应头中启用或禁用不可变指令。如果启用,还应指定maxAge选项以启用缓存。不可变的指令将阻止受支持的客户端在maxAge选项生命期间发出条件请求,以检查文件是否已更改。 | 假 | 4.16+ |
fn(err)
方法在传输完成或发生错误时调用回调函数。如果指定了回调函数并且发生错误,则回调函数必须通过结束请求 - 响应循环或将控制权交给下一个路径来显式处理响应过程。
这是一个使用res.sendFile
所有参数的例子。
app.get('/file/:name', function (req, res, next) { var options = { root: __dirname + '/public/', dotfiles: 'deny', headers: { 'x-timestamp': Date.now(), 'x-sent': true } }; var fileName = req.params.name; res.sendFile(fileName, options, function (err) { if (err) { next(err); } 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('/uploads/' + uid + '/' + file); } else { res.status(403).send("Sorry! You can't see that."); } });});
有关更多信息,或者如果您有问题或疑虑,请参阅send.
将响应HTTP状态代码设置为statusCode
并将其字符串表示形式作为响应主体发送。
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状态仍然设置为statusCode
,并且代码的字符串版本将作为响应主体发送。
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': '12345'});
别名为res.header(field [, value])
。
设置响应的HTTP状态。它是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类型mime.lookup()为指定的type
。如果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
,则将字段添加到响应标题中。
res.vary('User-Agent').render('docs');
router
对象是一个孤立的中间件和路由实例。您可以将其视为只能执行中间件和路由功能的“小型应用程序”。每个Express应用程序都有一个内置的应用程序路由器。
路由器的行为就像中间件本身,因此您可以将其用作app.use()的参数或作为另一个路由器的use()方法的参数。
顶层express
对象有一个Router()创建新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) { // ..});
然后,您可以通过这种方式将路由器用于特定的根网址,将路线分隔为文件甚至迷你应用程序。
// 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);
Another example of this is white-listed “global” functionality. Here the example is much like before, but it only restricts paths prefixed with “/api”:
router.all('/api/*', requireAuthentication);
这些router.METHOD()
方法在Express中提供了路由功能,其中METHOD是小写的HTTP方法之一,如GET,PUT,POST等。因此,实际的方法是router.get()
,router.post()
,router.put()
等。
除了方法之外,如果以前没有为路径router.get()
调用函数GETrouter.head()
,则会自动为HTTP HEAD
方法调用router.get()
函数。
您可以提供多个回调,并且所有处理都是平等对待的,并且行为与中间件一样,只是这些回调可能会调用next('route')
绕过剩余的路由回调。您可以使用此机制在路线上执行前提条件,然后在没有理由继续匹配路线时将控制权传递给后续路线。
以下片段说明了可能的最简单的路由定义。Express将路径字符串转换为正则表达式,用于在内部匹配传入的请求。在执行这些匹配时,不会考虑查询字符串,例如“GET /”将与以下路由匹配,就像“GET /?name = tobi”一样。
router.get('/', function(req, res){ res.send('hello world');});
您也可以使用正则表达式 - 如果您有非常特定的约束条件,则很有用,例如,以下内容将与“GET / commits / 71dbb9c”以及“GET /commits/71dbb9c..4c084f9”匹配。
router.get(/^\/commits\/(\w+)(?:\.\.(\w+))?$/, function(req, res){ var from = req.params[0]; var to = req.params[1] || 'HEAD'; res.send('commit range ' + from + '..' + to);});
添加回调触发器来设置路由参数,其中name
是参数的名称并且callback
是回调函数。尽管name
在技术上是可选的,但使用这种没有它的方法已经被弃用,从Express v4.11.0开始(见下文)。
回调函数的参数是:
req
,请求对象。
res
,响应对象。
next
,表示下一个中间件功能。
name
参数的值。
参数的名称。
与app.param()
不同,router.param()
不接受一组路由参数。
例如,当:user
存在于路径路径中时,您可以映射用户加载逻辑以自动提供给req.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')); } });});
Param回调函数在它们被定义的路由器的本地。它们不会被安装的应用程序或路由器继承。因此,定义的参数回调router
将仅由路由上定义的路由参数触发router
。
即使参数在多个路由中匹配,参数回调也只会在请求 - 响应周期中调用一次,如以下示例所示。
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 matches 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()
。这个函数是一个自定义实现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(); // customizing the behavior of router.param() router.param(function(param, option) { return function (req, res, next, val) { if (val == option) { next(); } else { res.sendStatus(403); } }}); // using the customized router.param() router.param('id', 1337); // route to trigger the capture router.get('/user/:id', function (req, res) { res.send('OK');}); app.use(router); app.listen(3000, function () { console.log('Ready');} );
在此示例中,router.param(name, callback)
签名保持不变,但不是中间件回调,而是定义了自定义数据类型检查函数来验证用户标识的数据类型。
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指令。使用router.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'));});
此方法重新使用单个/users/:user_id
路径并为各种HTTP方法添加处理程序。
注意:在使用时router.route()
,中间件排序基于创建路由的时间,而不是处理程序添加到路由时的时间。为此,您可以考虑处理程序属于它们添加到的路线方法。
使用指定的中间件功能或可选的装载路径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 middlewarerouter.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 from the mount pointrouter.use('/bar', function(req, res, next) { // ... maybe some additional /bar logging ... next();});// always invokedrouter.use(function(req, res, next) { res.send('Hello World');});app.use('/foo', router);app.listen(3000);
“装载”路径被剥离并且对中间件功能不可见。此功能的主要作用是安装的中间件功能可以在无需更改代码的情况下运行,而不管其“前缀”路径名。
您使用router.use()
定义中间件的顺序非常重要。它们是按顺序调用的,因此顺序定义了中间件的优先级。例如,通常记录器是您要使用的第一个中间件,这样每个请求都会被记录下来。
var logger = require('morgan');router.use(logger()); router.use(express.static(__dirname + '/public')); router.use(function(req, res){ res.send('Hello');});
现在假设您想忽略对静态文件的记录请求,但要继续记录之后定义的路由和中间件logger()
。在添加记录器中间件之前,您只需将呼叫express.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()
方法还支持命名参数,以便其他路由器的安装点可以使用命名参数进行预加载。
注意:虽然这些中间件功能是通过特定路由器添加的,但它们运行时由其所连接的路径(而不是路由器)定义。因此,如果路由匹配,通过一台路由器添加的中间件可能会为其他路由器运行。例如,此代码显示了在同一路径上安装的两个不同的路由器:
var authRouter = express.Router(); var openRouter = express.Router(); authRouter.use(require('./authenticate').basic(usersdb)); authRouter.get('/:user_id/edit', function(req, res, next) { // ... Edit user UI ... });openRouter.get('/', function(req, res, next) { // ... List users ... })openRouter.get('/:user_id', function(req, res, next) { // ... View user ... })app.use('/users', authRouter);app.use('/users', openRouter);
即使身份验证中间件是通过authRouter
它添加的,它也会在由该openRouter
路由器安装的路由器上定义的路由上运行/users
。为了避免这种情况,请为每个路由器使用不同的路径。