express()

express()用来创建一个Express的程序。express()方法是express模块导出的顶层方法。

var express = require('express');var app = express();

Methods

express.static(root, [options])

express.static是Express中唯一的内建中间件。它以server-static模块为基础开发 负责托管 Express 应用内的静态资源。参数root为静态资源的所在的根目录。参数options是可选的 支持以下的属性:

属性描述类型默认值
dotfiles是否响应点文件。供选择的值有"allow" "deny"和"ignore"String"ignore"
etag使能或者关闭etagBooleantrue
extensions设置文件延期回退Booleantrue
index发送目录索引文件。设置false将不发送。Mixed"index.html"
lastModified设置文件在系统中的最后修改时间到Last-Modified头部。可能的取值有falsetrueBooleantrue
maxAge在Cache-Control头部中设置max-age属性 精度为毫秒(ms)或则一段ms format的字符串Number0
redirect当请求的pathname是一个目录的时候 重定向到尾随"/"Booleantrue
setHeaders当响应静态文件请求时设置headers的方法Funtion 

如果你想获得更多关于使用中间件的细节 你可以查阅Serving static files in Express

Application()

app对象一般用来表示Express程序。通过调用Express模块导出的顶层的express()方法来创建它:

var express = require('express');var app = express();app.get('/', function(req, res) {  res.send('hello world!');});app.listen(3000);

app 对象具有以下的方法:

它还有一些属性设置 这些属性可以改变程序的行为。获得更多的信息 可以查阅Application settings

Properties

app.locals

app.locals对象是一个javascript对象 它的属性就是程序本地的变量。

app.locals.title// => 'My App'app.locals.email// => 'me@myapp.com'

一旦设定 app.locals的各属性值将贯穿程序的整个生命周期 与其相反的是 res.locals 它只在这次请求的生命周期中有效。

在程序中 你可以在渲染模板时使用这些本地变量。它们是非常有用的 可以为模板提供一些有用的方法 以及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

app.mountpath属性是子程序挂载的路径模式。

一个子程序是一个express的实例 其可以被用来作为路由句柄来处理请求。

var express = require('express');var app = express(); // the main appvar admin = express(); // the sub appadmin.get('/', function(req, res) {  console.log(admin.mountpath); // /admin  res.send('Admin Homepage');});app.use('/admin', admin); // mount the sub app

它和req对象的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 appapp.use(['/adm*n', '/manager'], admin); // load the 'admin' router on '/adm*n' and '/manager', on the parent app

Events

app.on('mount', callback(parent))

当子程序被挂载到父程序时 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);

Methods

app.all(path, callback[, callback ...]

app.all方法和标准的app.METHOD()方法相似 除了它匹配所有的HTTP动词。对于给一个特殊前缀映射一个全局的逻辑处理 或者无条件匹配 它是很有效的。例如 如果你把下面内容放在所有其他的路由定义的前面 它要求所有从这个点开始的路由需要认证和自动加载一个用户。记住这些回调并不是一定是终点:loadUser可以在完成了一个任务后 调用next()方法来继续匹配随后的路由。

app.all('*', requireAuthentication, loadUser);

或者这种相等的形式:

app.all('*', requireAuthentication);app.all('*', loadUser);

另一个例子是全局的白名单方法。这个例子和前面的很像 然而它只是限制以/api开头的路径。

app.all('/api/*', requireAuthentication);

app.delete(path, callback[, callback ...])

路由HTTP DELETE请求到有特殊回调方法的特殊的路径。获取更多的信息 可以查阅routing guide。你可以提供多个回调函数 它们的行为和中间件一样 除了这些回调可以通过调用next('router')来绕过剩余的路由回调。你可以使用这个机制来为一个路由设置一些前提条件 如果不能满足当前路由的处理条件 那么你可以传递控制到随后的路由。

app.delete('/', function(req, res) {  res.send('DELETE request to homepage');});

app.disable(name)

设置类型为布尔的设置名为name的值为false 此处的nameapp settings table中各属性的一个。调用app.set('foo', false)和调用app.disable('foo')是等价的。比如:

app.disable('trust proxy');app.get('trust proxy');// => false

app.disabled(name)

返回true如果布尔类型的设置值name被禁用为false 此处的nameapp settings table中各属性的一个。

app.disabled('trust proxy');// => trueapp.enable('trust proxy');app.disabled('trust proxy');// => false

app.enable(name)

设置布尔类型的设置值nametrue 此处的name是app settings table中各属性的一个。调用app.set('foo', true)和调用app.enable('foo')是等价的。

app.enable('trust proxy');app.get('trust proxy');// => true

app.enabled(name)

返回true如果布尔类型的设置值name被启动为true 此处的nameapp settings table中各属性的一个。

app.enabled('trust proxy');// => falseapp.enable('trust proxy');app.enabled('trust proxy');// => true

app.engine(ext, callback)

注册给定引擎的回调 用来渲染处理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);

app.get(name)

获得设置名为name的app设置的值 此处的nameapp settings table中各属性的一个。如下:

app.get('title');// => undefinedapp.set('title', 'My Site');app.get('title');// => 'My Site'

app.get(path, callback [, callback ...])

路由HTTP GET请求到有特殊回调的特殊路径。获取更多的信息 可以查阅routing guide。你可以提供多个回调函数 它们的行为和中间件一样 除了这些回调可以通过调用next('router')来绕过剩余的路由回调。你可以使用这个机制来为一个路由设置一些前提条件 如果请求没能满足当前路由的处理条件 那么传递控制到随后的路由。

app.get('/', function(req, res) {  res.send('GET request to homepage');});

app.listen(port, [hostname], [backlog], [callback])

绑定程序监听端口到指定的主机和端口号。这个方法和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);};

app.METHOD(path, callback [, callback ...])

路由一个HTTP请求 METHOD是这个请求的HTTP方法 比如GET PUT POST等等 注意是小写的。所以 实际的方法是app.get() app.post() app.put()等等。下面有关于方法的完整的表。

获取更多信息 请看routing guide。Express支持下面的路由方法 对应与同名的HTTP方法:

  • checkout
  • connect
  • copy
  • delete
  • get
  • head
  • lock
  • merge
  • mkactivity
    • mkcol
    • move
    • m-search
    • notify
    • options
    • patch
    • post
    • propfind
    • proppatch
      • purege
      • put
      • report
      • search
      • subscribe
      • trace
      • unlock
      • unsubscribe

        如果使用上述方法时 导致了无效的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});

        app.param([name], callback)

        给路由参数添加回调触发器 这里的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 ONCEalthough this matchesand 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 42CALLED ONLY ONCE with 3although this matchesand 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 用使用[\]或者[\w\>W]来代替(正如/user-[\]+/)。

        //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]+-[[]]*', function); //captures all (equivalent to '.*')router.get('[[\]]*', function); 

        app.path()

        通过这个方法可以得到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的典型路径。

        app.post(path, callback, [callback ...])

        路由HTTP POST请求到有特殊回调的特殊路径。获取更多的信息 可以查阅[routing guide](http://expressjs.com/guide/routing.html)。

        你可以提供多个回调函数 它们的行为和中间件一样 除了这些回调可以通过调用next('router')来绕过剩余的路由回调。你可以使用这个机制来为一个路由设置一些前提条件 如果请求没能满足当前路由的处理条件 那么传递控制到随后的路由。

        app.post('/', function(req, res) {  res.send('POST request to homepage')});

        app.put(path, callback, [callback ...])

        路由HTTP PUT请求到有特殊回调的特殊路径。获取更多的信息 可以查阅routing guide

        你可以提供多个回调函数 它们的行为和中间件一样 除了这些回调可以通过调用next('router')来绕过剩余的路由回调。你可以使用这个机制来为一个路由设置一些前提条件 如果请求没能满足当前路由的处理条件 那么传递控制到随后的路由。

        app.put('/', function(req, res) {  res.send('PUT request to homepage');});

        app.render(view, [locals], callback)

        通过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) {// ...});

        app.route(path)

        返回一个单例模式的路由的实例 之后你可以在其上施加各种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...})

        app.set(name, value)

        给 name 设置项赋 value 值 name 是 Application settings 中属性的一项。对于一个类型是布尔型的属性调用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是程序设置之一 它将影响到程序的行为。下边列出了程序中的设置。

        属性类型值默认
        case sensitive routingBoolean启用区分大小写。不启用。对/Foo/foo处理是一样。
        envString环境模型。process.env.NODEENV(NODEENV环境变量)或者"development"
        etagVaried设置ETag响应头。可取的值 可以查阅etag options table。更多关于HTTP ETag headerweak
        jsonp callback nameString指定默认JSONP回调的名称。?callback=
        json replacerStringJSON替代品回调null
        json spacesNumber当设置了这个值后 发送缩进空格美化过的JSON字符串。Disabled
        query parserVaried设置值为false来禁用query parser 或者设置simple,extended 也可以自己实现query string解析函数。simple基于Node原生的query解析 querystring"extend"
        strict routingBoolean启用严格的路由。不启用。对/foo/foo/的路由处理是一样。
        subdomain offsetNumber用来删除访问子域的主机点分部分的个数2
        trust proxyVaried指示app在一个反向代理的后面 使用x-Forwarded-*来确定连接和客户端的IP地址。注意:X-Forwarded-*头部很容易被欺骗 所有检测客户端的IP地址是靠不住的。trust proxy默认不启用。当启用时 Express尝试通过前端代理或者一系列代理来获取已连接的客户端IP地址。req.ips属性包含了已连接客户端IP地址的一个数组。为了启动它 需要设置在下面trust proxy options table中定义的值。trust proxy的设置实现使用了proxy-addr包。如果想获得更多的信息 可以查阅它的文档Disable
        viewsString or Arrayview所在的目录或者目录数组。如果是一个数组 将按在数组中的顺序来查找viewprocess.cwd() + '/views'
        view cacheBoolean启用视图模板编译缓存。在生成环境默认开启。
        view engineString省略时 默认的引擎被扩展使用。
        x-powered-byBoolean启用X-Powered-By:ExpressHTTP头部true

        trust proxy 选项设置查阅Express behind proxies来获取更多信息。

        TypeValue
        Boolean

        如果为true 客户端的IP地址作为X-Forwarded-*头部的最左边的条目。如果为false 可以理解为app直接与英特网直连 客户端的IP地址衍生自req.connection.remoteAddressfalse是默认设置。

        IP addresses

        一个IP地址 子网 或者一组IP地址 和委托子网。下面列出的是一个预先配置的子网名列表。

        • 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') // specify a single subnetapp.set('trust proxy', 'loopback, 123.123.123.123') // specify a subnet and an addressapp.set('trust proxy', 'loopback, linklocal, uniquelocal') // specify multiple subnets as CSVapp.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; })

        etag 设置选项ETag功能的实现使用了etag包。如果你需要获得更多的信息 你可以查阅它的文档。

        TypeValue
        Boolean

        设置为true 启用weak ETag。这个是默认设置。设置false 禁用所有的ETag。

        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([path,], function [, function...])

        挂载中间件方法到路径上。如果路径未指定 那么默认为"/"。

        一个路由将匹配任何路径如果这个路径以这个路由设置路径后紧跟着"/"。比如:app.use('/appale', ...)将匹配"/apple" "/apple/images" "/apple/images/news"等。

        中间件中的req.originalUrlreq.baseUrlreq.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 itapp.use(function(req, res, next) {  res.send('Hello World');});// this middleware will never reach this routeapp.use('/', function(req, res) {  res.send('Welcome');});

        路径可以是代表路径的一串字符 一个路径模式 一个匹配路径的正则表达式 或者他们的一组集合。

        下面是路径的简单的例子。

        类型 实例
        Path
        // will match paths starting with /abcdapp.use('/abcd', function (req, res, next) { next();})
        Path Pattern
        // will match paths starting with /abcd and /abdapp.use('/abc?d', function (req, res, next) { next();})// will match paths starting with /abcd, /abbcd, /abbbbbcd and so onapp.use('/ab+cd', function (req, res, next) { next();})// will match paths starting with /abcd, /abxcd, /abFOOcd, /abbArcd and so onapp.use('/ab*cd', function (req, res, next) { next();})// will match paths starting with /ad and /abcdapp.use('/a(bc)?d', function (req, res, next) { next();})
        Regular Expression
        // will match paths starting with /abc and /xyzapp.use(//abc|/xyz/, function (req, res, next) { next();})
        Array
        // will match paths starting with /abcd, /xyza, /lmn, and /pqrapp.use(['/abcd', '/xyza', //lmn|/pqr/], function (req, res, next) { next();})

        方法可以是一个中间件方法 一系列中间件方法 一组中间件方法或者他们的集合。由于router和app实现了中间件接口 你可以像使用其他任一中间件方法那样使用它们。

        用法实例
        单个中间件你可以局部定义和挂载一个中间件。
        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);
        Array在逻辑上使用一个数组来组织一组中间件。如果你传递一组中间件作为第一个或者唯一的参数 接着你需要指定挂载的路径。
        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]);
        Combination你可以组合下面的所有方法来挂载中间件。
        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 etcapp.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'));

        Request

        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);});

        Properties

        Express 4req.files默认在req对象中不再是可用的。为了通过req.files对象来获得上传的文件 你可以使用一个multipart-handling(多种处理的工具集)中间件 比如busboy multer formidable multipraty connect-multiparty或者pez

        req.app

        这个属性持有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'));};

        req.baseUrl

        一个路由实例挂载的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/helloreq.baseUrlapp对象的mountpath属性相似 除了app.mountpath返回的是路径匹配模式。

        req.body

        在请求的body中保存的是提交的一对对键值数据。默认情况下 它是undefined 当你使用比如body-parsermulter这类解析body数据的中间件时 它是填充的。下面的例子 给你展示了怎么使用body-parser中间件来填充req.body

        var app = require('express');var bodyParser = require('body-parser');var multer = require('multer');// v1.0.5var upload = multer(); // for parsing multipart/form-dataapp.use(bodyParser.json()); // for parsing application/jsonapp.use(bodyParser.urlencoded({extended:true})); // for parsing application/x-www-form-urlencodedapp.post('/profile', upload.array(), function(req, res, next) {  console.log(req.body);  res.json(req.body);});

        req.cookies

        当使用cookie-parser中间件的时候 这个属性是一个对象 其包含了请求发送过来的cookies。如果请求没有带cookies 那么其值为{}。

        // Cookie: name=tjreq.cookies.name// => "tj"

        获取更多信息 问题 或者关注 可以查阅cookie-parser

        req.fresh

        指示这个请求是否是新鲜的。其和req.stale是相反的。当cache-control请求头没有no-cache指示和下面中的任一一个条件为true 那么其就为true

        • if-modified-since请求头被指定 和last-modified请求头等于或者早于modified响应头。
        • if-none-match请求头是*
        • if-none-match请求头在被解析进它的指令之后 和etag响应头的值不相等

        ps:If-None-Match作用: If-None-Match和ETag一起工作 工作原理是在HTTP Response中添加ETag信息。 当用户再次请求该资源时 将在HTTP Request 中加入If-None-Match信息(ETag的值)。如果服务器验证资源的ETag没有改变(该资源没有更新) 将返回一个304状态告诉客户端使用本地缓存文件。否则将返回200状态和新的资源和Etag. 使用这样的机制将提高网站的性能

        req.fresh// => true

        req.hostname

        包含了源自HostHTTP头部的hostname

        trust proxy设置项被设置为启用值 X-Forwarded-Host头部被使用来代替Host。这个头部可以被客户端或者代理设置。

        // Host: "example.com"req.hostname// => "example.com"

        req.ips

        trust proxy设置项被设置为启用值 这个属性包含了一组在X-Forwarded-For请求头中指定的IP地址。不然 其就包含一个空的数组。这个头部可以被客户端或者代理设置。

        例如 如果X-Forwarded-Forclient proxy1 proxy2 req.ips就是["clinet", "proxy1", "proxy2"] 这里proxy2就是最远的下游。

        req.originalUrl

        req.url不是一个原生的Express属性 它继承自Node's http module

        这个属性很像req.url;然而 其保留了原版的请求链接 允许你自由地重定向req.url到内部路由。比如 app.use()mounting特点可以重定向req.url跳转到挂载点。

        // GET /search?q=somethingreq.originalUrl// => "/search?q=something"

        req.params

        一个对象 其包含了一系列的属性 这些属性和在路由中命名的参数名是一一对应的。例如 如果你有/user/:name路由 name属性可作为req.params.name。这个对象默认值为{}

        // GET /user/tjreq.params.name// => "tj"

        当你使用正则表达式来定义路由规则 捕获组的组合一般使用req.params[n] 这里的n是第几个捕获租。这个规则被施加在无名通配符匹配 比如/file/*的路由:

        // GET /file/javascripts/jquery.jsreq.params[0]// => "javascripts/jquery.js"

        req.path

        包含请求URL的部分路径。

        // example.com/users?sort=descreq.path// => "/users"

        当在一个中间件中被调用 挂载点不包含在req.path中。你可以查阅app.use()获得跟多的信息。

        req.protocol

        请求的协议 一般为http 当启用TLS加密 则为https

        trust proxy设置一个启用的参数 如果存在X-Forwarded-Proto头部的话 其将被信赖和使用。这个头部可以被客户端或者代理设置。

        req.ptotocol// => "http"

        req.query

        一个对象 为每一个路由中的query string参数都分配一个属性。如果没有query string 它就是一个空对象 {}

        // 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"

        req.route

        当前匹配的路由 其为一串字符。比如:

        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}}

        req.secure

        一个布尔值 如果建立的是TLS的连接 那么就为true。等价于:

        'https' == req.protocol;

        req.signedCookies

        当使用cookie-parser中间件的时候 这个属性包含的是请求发过来的签名cookies 这个属性取得的是不含签名 可以直接使用的值。签名的cookies保存在不同的对象中来体现开发者的意图;不然 一个恶意攻击可以被施加在req.cookie值上(它是很容易被欺骗的)。记住 签名一个cookie不是把它藏起来或者加密;而是简单的防止篡改(因为签名使用的加密是私人的)。如果没有发送签名的cookie 那么这个属性默认为{}

        // Cookie: user=tobi.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3req.signedCookies.user// => "tobi"

        为了获取更多的信息 问题或者关注 可以参阅cookie-parser

        req.stale

        指示这个请求是否是stale(陈旧的) 它与req.fresh是相反的。更多信息 可以查看req.fresh

        req.stale// => true

        req.subdomains

        请求中域名的子域名数组。

        // Host: "tobi.ferrets.example.com"req.subdomains// => ["ferrets", "tobi"]

        req.xhr

        一个布尔值 如果X-Requested-With的值为XMLHttpRequest 那么其为true 其指示这个请求是被一个客服端库发送 比如jQuery

        req.xhr// => true

        Methods

        req.accepts(types)

        检查这个指定的内容类型是否被接受 基于请求的Accept HTTP头部。这个方法返回最佳匹配 如果没有一个匹配 那么其返回undefined(在这个case下 服务器端应该返回406和"Not Acceptable")。

        type值可以是一个单的MIME type字符串(比如application/json) 一个扩展名比如json 一个逗号分隔的列表 或者一个数组。对于一个列表或者数组 这个方法返回最佳项(如果有的话)。

        // Accept: text/htmlreq.accepts('html');// => "html"// Accept: text/*, application/jsonreq.accepts('html');// => "html"req.accepts('text/html');// => "text/html"req.accepts(['json', 'text']);// => "json"req.accepts('application/json');// => "application/json"// Accept: text/*, application/jsonreq.accepts('image/png');req.accepts('png');// => undefined// Accept: text/*;q=.5, application/jsonreq.accepts(['html', 'json']);// => "json"

        获取更多信息 或者如果你有问题或关注 可以参阅accepts

        req.acceptsCharsets(charset[, ...])

        返回指定的字符集集合中第一个的配置的字符集 基于请求的Accept-CharsetHTTP头。如果指定的字符集没有匹配的 那么就返回false。获取更多信息 或者如果你有问题或关注 可以参阅accepts

        req.acceptsEncodings(encoding[, ...])

        返回指定的编码集合中第一个的配置的编码 基于请求的Accept-EncodingHTTP头。如果指定的编码集没有匹配的 那么就返回false。获取更多信息 或者如果你有问题或关注 可以参阅accepts

        req.acceptsLanguages(lang [, ...])

        返回指定的语言集合中第一个的配置的语言 基于请求的Accept-LanguageHTTP头。如果指定的语言集没有匹配的 那么就返回false。获取更多信息 或者如果你有问题或关注 可以参阅accepts

        req.get(field)

        返回指定的请求HTTP头部的域内容(不区分大小写)。ReferrerReferer的域内容可互换。

        req.get('Content-type');// => "text/plain"req.get('content-type');// => "text/plain"req.get('Something')// => undefined

        其是req.header(field)的别名。

        req.is(type)

        如果进来的请求的Content-type头部域匹配参数type给定的MIME type 那么其返回true。否则返回false

        // With Content-Type: text/html; charset=utf-8req.is('html');req.is('text/html');req.is('text/*');// => true// When Content-Type is application/jsonreq.is('json');req.is('application/json');req.is('application/*');// => truereq.is('html');// => false

        获取更多信息 或者如果你有问题或关注 可以参阅type-is

        req.param(naem, [, defaultValue])

        过时的。可以在适合的情况下 使用req.params req.body或者req.query

        返回当前参数name的值。

        // ?name=tobireq.param('name')// => "tobi"// POST name=tobireq.param('name')// => "tobi"// /user/tobi for /user/:namereq.param('name')// => "tobi"

        按下面给出的顺序查找:

        • req.params
        • req.body
        • req.query

        可选的 你可以指定一个defaultValue来设置一个默认值 如果这个参数在任何一个请求的对象中都不能找到。

        直接通过req.params req.body req.query取得应该更加的清晰-除非你确定每一个对象的输入。Body-parser中间件必须加载 如果你使用req.param()。详细请看req.body

        Response

        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);});

        Properties

        res.app

        这个属性持有express程序实例的一个引用 其可以在中间件中使用。

        res.app和请求对象中的req.app属性是相同的。/p>

        res.headersSent

        布尔类型的属性 指示这个响应是否已经发送HTTP头部。

        app.get('/', function(req, res) {  console.log(res.headersSent); // false  res.send('OK'); // send之后就发送了头部  console.log(res.headersSent); // true});

        res.locals

        一个对象 其包含了本次请求的响应中的变量和因此它的变量只提供给本次请求响应的周期内视图渲染里使用(如果有视图的话)。其他方面 其和app.locals是一样的。

        这个参数在导出请求级别的信息是很有效的 这些信息比如请求路径 已认证的用户 用户设置等等。

        app.use(function(req, res, next) {  res.locals.user = req.user;  res.locals.authenticated = !req.user.anonymous;  next();});

        Methods

        res.append(field [, value])

        res.append()方法在Expresxs4.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');

        res.attachment([filename])

        设置HTTP响应的Content-Disposition头内容为"attachment"。如果提供了filename 那么将通过res.type()获得扩展名来设置Content-Type 并且设置Content-Disposition内容为"filename="parameter。

        res.attachment();// Content-Disposition: attachmentres.attachment('path/to/logo.png');// Content-Disposition: attachment; filename="logo.png"// Content-Type: image/png

        res.cookie(name, value [,options])

        设置namevaluecookie value参数可以是一串字符或者是转化为json字符串的对象。

        options是一个对象 其可以有下列的属性。

        属性类型描述
        domainString设置cookie的域名。默认是你本app的域名。
        expiresDatecookie的过期时间 GMT格式。如果没有指定或者设置为0 则产生新的cookie。
        httpOnlyBoolean这个cookie只能被web服务器获取的标示。
        maxAgeString是设置过去时间的方便选项 其为过期时间到当前时间的毫秒值。
        pathStringcookie的路径。默认值是/
        secureBoolean标示这个cookie只用被HTTPS协议使用。
        signedBoolean指示这个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', {'maxAge':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});

        res.clearCookie(name [,options])

        根据指定的name清除对应的cookie。更多关于options对象可以查阅res.cookie()

        res.cookie('name', 'tobi', {'path':'/admin'});res.clearCookie('name', {'path':'admin'});

        res.download(path, [,filename], [,fn])

        传输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.headersSentif (err) {} else {// decrement a download credit, etc.}});

        res.end([data] [, encoding])

        结束本响应的过程。这个方法实际上来自Node核心模块 具体的是response.end() method of http.ServerResponse

        用来快速结束请求 没有任何的数据。如果你需要发送数据 可以使用res.send()res.json()这类的方法。

        res.end();res.status(404).end();

        res.format(object)

        进行内容协商 根据请求的对象中AcceptHTTP头部指定的接受内容。它使用 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'});  }})

        res.get(field)

        返回field指定的HTTP响应的头部。匹配是区分大小写。

        res.get('Content-Type');// => "text/plain"

        res.json([body])

        发送一个json的响应。这个方法和将一个对象或者一个数组作为参数传递给res.send()方法的效果相同。不过 你可以使用这个方法来转换其他的值到json 例如null undefined。(虽然这些都是技术上无效的JSON)。

        res.json(null);res.json({user:'tobi'});res.status(500).json({error:'message'});

        res.jsonp([body])

        发送一个json的响应 并且支持JSONP。这个方法和res.json()效果相同 除了其在选项中支持JSONP回调。

        res.jsonp(null)// => nullres.jsonp({user:'tobi'})// => {"user" : "tobi"}res.status(500).jsonp({error:'message'})// => {"error" : "message"}

        默认情况下 jsonp的回调方法简单写作callback。可以通过jsonp callback name设置来重写它。

        下面是一些例子使用JSONP响应 使用相同的代码:

        // ?callback=foores.jsonp({user:'tobo'})// => foo({"user":"tobi"})app.set('jsonp callback name', 'cb')// ?cb=foores.status(500).jsonp({error:'message'})// => foo({"error":"message"})

        res.links(links)

        连接这些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"

        res.lo