2012-08-11 84 views
3

我正在设置将使用Node.js和Express构建的新项目的结构。我正在使用HTML5 Boilerplate作为最佳起点。它配备了多种类型的服务器的配置文件:阿帕奇,Nginx的,Node.js的,等等。以下是HTML5的样板团队提供的Node.js server configuration fileNode.js HTML5 Boilerplate服务器配置集成

/* h5bp server-configs project 
* 
* maintainer: @xonecas 
* contributors: @niftylettuce 
* 
* NOTES: 
* compression: use the compress middleware provided by connect 2.x to enable gzip/deflate compression 
*       http://www.senchalabs.org/connect/compress.html 
* 
* concatenation: use on of the following middlewares to enable automatic concatenation of static assets 
*        - https://github.com/mape/connect-assetmanager 
*        - https://github.com/TrevorBurnham/connect-assets 
*/ 
var h5bp = module.exports, 
    _http = require('http'), 
    _parse = require('url').parse; 

// send the IE=Edge and chrome=1 headers for IE browsers 
// on html/htm requests. 
h5bp.ieEdgeChromeFrameHeader = function() { 
    return function (req, res, next) { 
     var url = req.url, 
     ua = req.headers['user-agent']; 

     if (ua && ua.indexOf('MSIE') > -1 && /html?($|\?|#)/.test(url)) { 
     res.setHeader('X-UA-Compatible', 'IE=Edge,chrome=1'); 
     } 
     next(); 
    }; 
}; 

// block access to hidden files and directories. 
h5bp.protectDotfiles = function() { 
    return function (req, res, next) { 
     var error; 
     if (/(^|\/)\./.test(req.url)) { 
     error = new Error(_http.STATUS_CODES[405]); // 405, not allowed 
     error.status = 405; 
     } 
     next(error); 
    }; 
}; 

// block access to backup and source files 
h5bp.blockBackupFiles = function() { 
    return function (req, res, next) { 
     var error; 
     if (/\.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)|~/.test(req.url)) { 
     error = new Error(_http.STATUS_CODES[405]); // 405, not allowed 
     error.status = 405; 
     } 
     next(error); 
    }; 
}; 

// Do we want to advertise what kind of server we're running? 
h5bp.removePoweredBy = function() { 
    return function (req, res, next) { 
     res.removeHeader('X-Powered-By'); 
     next(); 
    }; 
}; 

// Enable CORS cross domain rules, more info at http://enble-cors.org/ 
h5bp.crossDomainRules = function() { 
    return function (req, res, next) { 
     res.setHeader('Access-Control-Allow-Origin', '*'); 
     res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With'); 
     next(); 
    }; 
}; 

// Suppress or force 'www' in the urls 
// @param suppress = boolean 
h5bp.suppressWww = function (suppress) { 
    return function (req, res, next) { 
     var url = req.url; 
     if (suppress && /^www\./.test(url)) { 
     res.statusCode = 302; 
     res.setHeader('Location', url.replace(/^www\./,'')); 
     } 
     if (!suppress && !/^www\./.test(url)) { 
     res.statusCode = 302; 
     res.setHeader('Location', "www."+url); 
     } 
     next(); 
    }; 
}; 

// Far expire headers 
// use this when not using connect.static for your own expires/etag control 
h5bp.expireHeaders = function (maxAge) { 
    return function (req, res, next) { 
     res.setHeader('Cache-Control', 'public, max-age='+ (maxAge)); 
     next(); 
    }; 
}; 

// Etag removal 
// only use this is you are setting far expires for your files 
// ** WARNING ** connect.static overrides this. 
h5bp.removeEtag = function() { 
    return function (req, res, next) { 
     res.removeHeader('Last-Modified'); 
     res.removeHeader('ETag'); 
     next(); 
    }; 
}; 

// set proper content type 
// @param mime = reference to the mime module (https://github.com/bentomas/node-mime) 
h5bp.setContentType = function (mime) { 
    return function (req, res, next) { 
     // I'm handling the dependency by having it passed as an argument 
     // we depend on the mime module to determine proper content types 
     // connect also has the same dependency for the static provider 
     // ** @TODO ** maybe connect/express expose this module somehow? 
     var path = _parse(req.url).pathname, 
     type = mime.lookup(path); 
     res.setHeader('Content-Type', type); 
     next(); 
    }; 
}; 

// return a express/connect server with the default middlewares. 
// @param serverConstructor = express/connect server instance 
// @param options = { 
// root: 'path/to/public/files', 
// maxAge: integer, time in miliseconds ex: 1000 * 60 * 60 * 24 * 30 = 30 days, 
// mime: reference to the mime module ex: require('mime') 
// } 
// Depends: 
// express or connect server 
// mime module [optional] 

h5bp.server = function (serverConstructor, options) { 
    var server = serverConstructor.createServer(), 
     stack = [ 
     this.suppressWww(true), 
     this.protectDotfiles(), 
     this.blockBackupFiles(), 
     this.crossDomainRules(), 
     this.ieEdgeChromeFrameHeader() 
     //,this.expireHeaders(options.maxAge), 
     // this.removeEtag(), 
     // this.setContentType(require('mime')) 
     ]; 
    // express/connect 
    if (server.use) { 
     stack.unshift(serverConstructor.logger('dev')); 
     stack.push(
     //serverConstructor.compress(), // express doesn't seem to expose this middleware 
     serverConstructor['static'](options.root, { maxAge: options.maxAge }), // static is a reserved 
     serverConstructor.favicon(options.root, { maxAge: options.maxAge }), 
     serverConstructor.errorHandler({ 
      stack: true, 
      message: true, 
      dump: true 
     }) 
    ); 
     for (var i = 0, len = stack.length; i < len; ++i) server.use(stack[i]); 
    } else { 
     server.on('request', function (req, res) { 
     var newStack = stack, 
      func; 
     (function next (err) { 
      if (err) { 
       throw err; 
       return; 
      } else { 
       func = newStack.shift(); 
       if (func) func(req, res, next); 
       return; 
      } 
     })(); 
     }); 
    } 
    return server; 
}; 

我的问题是:究竟如何做我去关于将此与Express整合?特别让我困惑的部分代码是底部:

// return a express/connect server with the default middlewares. 
// @param serverConstructor = express/connect server instance 
// @param options = { 
// root: 'path/to/public/files', 
// maxAge: integer, time in miliseconds ex: 1000 * 60 * 60 * 24 * 30 = 30 days, 
// mime: reference to the mime module ex: require('mime') 
// } 
// Depends: 
// express or connect server 
// mime module [optional] 

h5bp.server = function (serverConstructor, options) { 
    var server = serverConstructor.createServer(), 
     stack = [ 
     this.suppressWww(true), 
     this.protectDotfiles(), 
     this.blockBackupFiles(), 
     this.crossDomainRules(), 
     this.ieEdgeChromeFrameHeader() 
     //,this.expireHeaders(options.maxAge), 
     // this.removeEtag(), 
     // this.setContentType(require('mime')) 
     ]; 
    // express/connect 
    if (server.use) { 
     stack.unshift(serverConstructor.logger('dev')); 
     stack.push(
     //serverConstructor.compress(), // express doesn't seem to expose this middleware 
     serverConstructor['static'](options.root, { maxAge: options.maxAge }), // static is a reserved 
     serverConstructor.favicon(options.root, { maxAge: options.maxAge }), 
     serverConstructor.errorHandler({ 
      stack: true, 
      message: true, 
      dump: true 
     }) 
    ); 
     for (var i = 0, len = stack.length; i < len; ++i) server.use(stack[i]); 
    } else { 
     server.on('request', function (req, res) { 
     var newStack = stack, 
      func; 
     (function next (err) { 
      if (err) { 
       throw err; 
       return; 
      } else { 
       func = newStack.shift(); 
       if (func) func(req, res, next); 
       return; 
      } 
     })(); 
     }); 
    } 
    return server; 
}; 

我的JavaScript并不完全在初学者级别,但我也不会说我是先进的。这段代码超越了我。任何关于我可以阅读,观看或做什么的指针,了解我在这里显然想念的东西将不胜感激。

回答

5

Most of the file由一系列函数组成,这些函数生成符合Connect中间件规范的Express等框架中间件。第二个代码清单旨在创建一个HTTP服务器,其中使用所有这些功能。从我所知道的情况来看,它看起来应该通过你通常所说的createServer,而h5bp会为你创建和设置。例如,如果你通常会做:

var express = require('express'); 
var server = express.createServer(); 

你反而会传递expressh5bp.server,这对无论你在马上蝙蝠通过调用createServer

var express = require('express'); 
var server = h5bp.server(express, options); 

一些设置后,它会检查服务器是否具有名为use(该行为if (server.use))的功能,如果是,则使用该功能将其设置的所有中间件注入服务器。如果它不是,那么它假定您正在使用原始Node.js HTTP服务器,并设置必要的代码以手动传递请求通过stack中的每个项目(这是Connect/Express的作用您)。

值得注意的是,在Express 3(目前处于发布候选阶段)中,由Express创建的应用程序不再继承自Node的HTTP服务器,因此您不需要在express上调用createServer;相反,您只需拨打express(),然后将结果传递给http.createServer。 (有关更多信息,请参阅Migrating from 2.x to 3.x on the Express wiki上的“应用程序功能”。)这意味着此脚本与Express的最新版本不兼容。

[更新]

如果你看看在GitHub上test目录,你可以看到an example app

var express = require('express'), 
    h5bp  = require('../node.js'), 
    server = h5bp.server(express, { 
     root: __dirname, 
     maxAge: 1000 * 60 * 60 * 30 
    }); 

server.listen(8080); 
console.log('ok'); 
+0

感谢您的答复,这是相当翔实。正如你所说,由于提供的脚本与Express 3不兼容,我想我只会尝试自己复制这些功能。再次感谢您提供简洁,翔实和快速的回​​复。 – 2012-08-11 05:50:37

+0

很高兴有帮助。在查看脚本的同时,您可能会发现每个中间件都非常自包含,并且不言自明,而且实现起来也不那么困难。 (事实上​​,我意识到我忘了在最近的一个项目中重定向流量,并使用他们的技术修改来实现它。) – 2012-08-11 06:22:55

1

h5bp为node.js中的重大更新
您现在可以使用它作为快递中间件。

存储库已移到此处:https://github.com/h5bp/node-server-config

从文档:

var express = require('express'), 
h5bp = require('h5bp'); 

var app = express(); 
// ... 
app.use(h5bp({ root: __dirname + '/public' })); 
app.use(express.compress()); 
app.use(express.static(__dirname + '/public')); 
// ... 
app.listen(3000);