forked from h5bp/server-configs
/
node.js
156 lines (144 loc) · 4.91 KB
/
node.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/* 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) {
return serverConstructor.createServer(
serverConstructor.logger('dev'),
this.suppressWww(true),
this.protectDotfiles(),
this.blockBackupFiles(),
this.crossDomainRules(),
this.ieEdgeChromeFrameHeader(),
//this.expireHeaders(options.maxAge),
//this.removeEtag(),
//this.setContentType(require('mime')),
//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
})
);
};