diff options
author | Yaroslav De La Peña Smirnov <yaros.rus_89@live.com.mx> | 2017-11-29 11:44:34 +0300 |
---|---|---|
committer | Yaroslav De La Peña Smirnov <yaros.rus_89@live.com.mx> | 2017-11-29 11:44:34 +0300 |
commit | 67fdec20726e48ba3a934cb25bb30d47ec4a4f29 (patch) | |
tree | 37fd9f4f0b0c20103e1646fc83021e4765de3680 /node_modules/express | |
download | spanish-checkers-67fdec20726e48ba3a934cb25bb30d47ec4a4f29.tar.gz spanish-checkers-67fdec20726e48ba3a934cb25bb30d47ec4a4f29.zip |
Initial commit, version 0.5.3
Diffstat (limited to 'node_modules/express')
-rw-r--r-- | node_modules/express/History.md | 3374 | ||||
-rw-r--r-- | node_modules/express/LICENSE | 24 | ||||
-rw-r--r-- | node_modules/express/Readme.md | 153 | ||||
-rw-r--r-- | node_modules/express/index.js | 11 | ||||
-rw-r--r-- | node_modules/express/lib/application.js | 644 | ||||
-rw-r--r-- | node_modules/express/lib/express.js | 112 | ||||
-rw-r--r-- | node_modules/express/lib/middleware/init.js | 43 | ||||
-rw-r--r-- | node_modules/express/lib/middleware/query.js | 47 | ||||
-rw-r--r-- | node_modules/express/lib/request.js | 521 | ||||
-rw-r--r-- | node_modules/express/lib/response.js | 1137 | ||||
-rw-r--r-- | node_modules/express/lib/router/index.js | 662 | ||||
-rw-r--r-- | node_modules/express/lib/router/layer.js | 181 | ||||
-rw-r--r-- | node_modules/express/lib/router/route.js | 216 | ||||
-rw-r--r-- | node_modules/express/lib/utils.js | 306 | ||||
-rw-r--r-- | node_modules/express/lib/view.js | 182 | ||||
-rw-r--r-- | node_modules/express/package.json | 201 |
16 files changed, 7814 insertions, 0 deletions
diff --git a/node_modules/express/History.md b/node_modules/express/History.md new file mode 100644 index 0000000..fbf59a2 --- /dev/null +++ b/node_modules/express/History.md @@ -0,0 +1,3374 @@ +4.16.2 / 2017-10-09 +=================== + + * Fix `TypeError` in `res.send` when given `Buffer` and `ETag` header set + * perf: skip parsing of entire `X-Forwarded-Proto` header + +4.16.1 / 2017-09-29 +=================== + + * deps: send@0.16.1 + * deps: serve-static@1.13.1 + - Fix regression when `root` is incorrectly set to a file + - deps: send@0.16.1 + +4.16.0 / 2017-09-28 +=================== + + * Add `"json escape"` setting for `res.json` and `res.jsonp` + * Add `express.json` and `express.urlencoded` to parse bodies + * Add `options` argument to `res.download` + * Improve error message when autoloading invalid view engine + * Improve error messages when non-function provided as middleware + * Skip `Buffer` encoding when not generating ETag for small response + * Use `safe-buffer` for improved Buffer API + * deps: accepts@~1.3.4 + - deps: mime-types@~2.1.16 + * deps: content-type@~1.0.4 + - perf: remove argument reassignment + - perf: skip parameter parsing when no parameters + * deps: etag@~1.8.1 + - perf: replace regular expression with substring + * deps: finalhandler@1.1.0 + - Use `res.headersSent` when available + * deps: parseurl@~1.3.2 + - perf: reduce overhead for full URLs + - perf: unroll the "fast-path" `RegExp` + * deps: proxy-addr@~2.0.2 + - Fix trimming leading / trailing OWS in `X-Forwarded-For` + - deps: forwarded@~0.1.2 + - deps: ipaddr.js@1.5.2 + - perf: reduce overhead when no `X-Forwarded-For` header + * deps: qs@6.5.1 + - Fix parsing & compacting very deep objects + * deps: send@0.16.0 + - Add 70 new types for file extensions + - Add `immutable` option + - Fix missing `</html>` in default error & redirects + - Set charset as "UTF-8" for .js and .json + - Use instance methods on steam to check for listeners + - deps: mime@1.4.1 + - perf: improve path validation speed + * deps: serve-static@1.13.0 + - Add 70 new types for file extensions + - Add `immutable` option + - Set charset as "UTF-8" for .js and .json + - deps: send@0.16.0 + * deps: setprototypeof@1.1.0 + * deps: utils-merge@1.0.1 + * deps: vary@~1.1.2 + - perf: improve header token parsing speed + * perf: re-use options object when generating ETags + * perf: remove dead `.charset` set in `res.jsonp` + +4.15.5 / 2017-09-24 +=================== + + * deps: debug@2.6.9 + * deps: finalhandler@~1.0.6 + - deps: debug@2.6.9 + - deps: parseurl@~1.3.2 + * deps: fresh@0.5.2 + - Fix handling of modified headers with invalid dates + - perf: improve ETag match loop + - perf: improve `If-None-Match` token parsing + * deps: send@0.15.6 + - Fix handling of modified headers with invalid dates + - deps: debug@2.6.9 + - deps: etag@~1.8.1 + - deps: fresh@0.5.2 + - perf: improve `If-Match` token parsing + * deps: serve-static@1.12.6 + - deps: parseurl@~1.3.2 + - deps: send@0.15.6 + - perf: improve slash collapsing + +4.15.4 / 2017-08-06 +=================== + + * deps: debug@2.6.8 + * deps: depd@~1.1.1 + - Remove unnecessary `Buffer` loading + * deps: finalhandler@~1.0.4 + - deps: debug@2.6.8 + * deps: proxy-addr@~1.1.5 + - Fix array argument being altered + - deps: ipaddr.js@1.4.0 + * deps: qs@6.5.0 + * deps: send@0.15.4 + - deps: debug@2.6.8 + - deps: depd@~1.1.1 + - deps: http-errors@~1.6.2 + * deps: serve-static@1.12.4 + - deps: send@0.15.4 + +4.15.3 / 2017-05-16 +=================== + + * Fix error when `res.set` cannot add charset to `Content-Type` + * deps: debug@2.6.7 + - Fix `DEBUG_MAX_ARRAY_LENGTH` + - deps: ms@2.0.0 + * deps: finalhandler@~1.0.3 + - Fix missing `</html>` in HTML document + - deps: debug@2.6.7 + * deps: proxy-addr@~1.1.4 + - deps: ipaddr.js@1.3.0 + * deps: send@0.15.3 + - deps: debug@2.6.7 + - deps: ms@2.0.0 + * deps: serve-static@1.12.3 + - deps: send@0.15.3 + * deps: type-is@~1.6.15 + - deps: mime-types@~2.1.15 + * deps: vary@~1.1.1 + - perf: hoist regular expression + +4.15.2 / 2017-03-06 +=================== + + * deps: qs@6.4.0 + - Fix regression parsing keys starting with `[` + +4.15.1 / 2017-03-05 +=================== + + * deps: send@0.15.1 + - Fix issue when `Date.parse` does not return `NaN` on invalid date + - Fix strict violation in broken environments + * deps: serve-static@1.12.1 + - Fix issue when `Date.parse` does not return `NaN` on invalid date + - deps: send@0.15.1 + +4.15.0 / 2017-03-01 +=================== + + * Add debug message when loading view engine + * Add `next("router")` to exit from router + * Fix case where `router.use` skipped requests routes did not + * Remove usage of `res._headers` private field + - Improves compatibility with Node.js 8 nightly + * Skip routing when `req.url` is not set + * Use `%o` in path debug to tell types apart + * Use `Object.create` to setup request & response prototypes + * Use `setprototypeof` module to replace `__proto__` setting + * Use `statuses` instead of `http` module for status messages + * deps: debug@2.6.1 + - Allow colors in workers + - Deprecated `DEBUG_FD` environment variable set to `3` or higher + - Fix error when running under React Native + - Use same color for same namespace + - deps: ms@0.7.2 + * deps: etag@~1.8.0 + - Use SHA1 instead of MD5 for ETag hashing + - Works with FIPS 140-2 OpenSSL configuration + * deps: finalhandler@~1.0.0 + - Fix exception when `err` cannot be converted to a string + - Fully URL-encode the pathname in the 404 + - Only include the pathname in the 404 message + - Send complete HTML document + - Set `Content-Security-Policy: default-src 'self'` header + - deps: debug@2.6.1 + * deps: fresh@0.5.0 + - Fix false detection of `no-cache` request directive + - Fix incorrect result when `If-None-Match` has both `*` and ETags + - Fix weak `ETag` matching to match spec + - perf: delay reading header values until needed + - perf: enable strict mode + - perf: hoist regular expressions + - perf: remove duplicate conditional + - perf: remove unnecessary boolean coercions + - perf: skip checking modified time if ETag check failed + - perf: skip parsing `If-None-Match` when no `ETag` header + - perf: use `Date.parse` instead of `new Date` + * deps: qs@6.3.1 + - Fix array parsing from skipping empty values + - Fix compacting nested arrays + * deps: send@0.15.0 + - Fix false detection of `no-cache` request directive + - Fix incorrect result when `If-None-Match` has both `*` and ETags + - Fix weak `ETag` matching to match spec + - Remove usage of `res._headers` private field + - Support `If-Match` and `If-Unmodified-Since` headers + - Use `res.getHeaderNames()` when available + - Use `res.headersSent` when available + - deps: debug@2.6.1 + - deps: etag@~1.8.0 + - deps: fresh@0.5.0 + - deps: http-errors@~1.6.1 + * deps: serve-static@1.12.0 + - Fix false detection of `no-cache` request directive + - Fix incorrect result when `If-None-Match` has both `*` and ETags + - Fix weak `ETag` matching to match spec + - Remove usage of `res._headers` private field + - Send complete HTML document in redirect response + - Set default CSP header in redirect response + - Support `If-Match` and `If-Unmodified-Since` headers + - Use `res.getHeaderNames()` when available + - Use `res.headersSent` when available + - deps: send@0.15.0 + * perf: add fast match path for `*` route + * perf: improve `req.ips` performance + +4.14.1 / 2017-01-28 +=================== + + * deps: content-disposition@0.5.2 + * deps: finalhandler@0.5.1 + - Fix exception when `err.headers` is not an object + - deps: statuses@~1.3.1 + - perf: hoist regular expressions + - perf: remove duplicate validation path + * deps: proxy-addr@~1.1.3 + - deps: ipaddr.js@1.2.0 + * deps: send@0.14.2 + - deps: http-errors@~1.5.1 + - deps: ms@0.7.2 + - deps: statuses@~1.3.1 + * deps: serve-static@~1.11.2 + - deps: send@0.14.2 + * deps: type-is@~1.6.14 + - deps: mime-types@~2.1.13 + +4.14.0 / 2016-06-16 +=================== + + * Add `acceptRanges` option to `res.sendFile`/`res.sendfile` + * Add `cacheControl` option to `res.sendFile`/`res.sendfile` + * Add `options` argument to `req.range` + - Includes the `combine` option + * Encode URL in `res.location`/`res.redirect` if not already encoded + * Fix some redirect handling in `res.sendFile`/`res.sendfile` + * Fix Windows absolute path check using forward slashes + * Improve error with invalid arguments to `req.get()` + * Improve performance for `res.json`/`res.jsonp` in most cases + * Improve `Range` header handling in `res.sendFile`/`res.sendfile` + * deps: accepts@~1.3.3 + - Fix including type extensions in parameters in `Accept` parsing + - Fix parsing `Accept` parameters with quoted equals + - Fix parsing `Accept` parameters with quoted semicolons + - Many performance improvments + - deps: mime-types@~2.1.11 + - deps: negotiator@0.6.1 + * deps: content-type@~1.0.2 + - perf: enable strict mode + * deps: cookie@0.3.1 + - Add `sameSite` option + - Fix cookie `Max-Age` to never be a floating point number + - Improve error message when `encode` is not a function + - Improve error message when `expires` is not a `Date` + - Throw better error for invalid argument to parse + - Throw on invalid values provided to `serialize` + - perf: enable strict mode + - perf: hoist regular expression + - perf: use for loop in parse + - perf: use string concatination for serialization + * deps: finalhandler@0.5.0 + - Change invalid or non-numeric status code to 500 + - Overwrite status message to match set status code + - Prefer `err.statusCode` if `err.status` is invalid + - Set response headers from `err.headers` object + - Use `statuses` instead of `http` module for status messages + * deps: proxy-addr@~1.1.2 + - Fix accepting various invalid netmasks + - Fix IPv6-mapped IPv4 validation edge cases + - IPv4 netmasks must be contingous + - IPv6 addresses cannot be used as a netmask + - deps: ipaddr.js@1.1.1 + * deps: qs@6.2.0 + - Add `decoder` option in `parse` function + * deps: range-parser@~1.2.0 + - Add `combine` option to combine overlapping ranges + - Fix incorrectly returning -1 when there is at least one valid range + - perf: remove internal function + * deps: send@0.14.1 + - Add `acceptRanges` option + - Add `cacheControl` option + - Attempt to combine multiple ranges into single range + - Correctly inherit from `Stream` class + - Fix `Content-Range` header in 416 responses when using `start`/`end` options + - Fix `Content-Range` header missing from default 416 responses + - Fix redirect error when `path` contains raw non-URL characters + - Fix redirect when `path` starts with multiple forward slashes + - Ignore non-byte `Range` headers + - deps: http-errors@~1.5.0 + - deps: range-parser@~1.2.0 + - deps: statuses@~1.3.0 + - perf: remove argument reassignment + * deps: serve-static@~1.11.1 + - Add `acceptRanges` option + - Add `cacheControl` option + - Attempt to combine multiple ranges into single range + - Fix redirect error when `req.url` contains raw non-URL characters + - Ignore non-byte `Range` headers + - Use status code 301 for redirects + - deps: send@0.14.1 + * deps: type-is@~1.6.13 + - Fix type error when given invalid type to match against + - deps: mime-types@~2.1.11 + * deps: vary@~1.1.0 + - Only accept valid field names in the `field` argument + * perf: use strict equality when possible + +4.13.4 / 2016-01-21 +=================== + + * deps: content-disposition@0.5.1 + - perf: enable strict mode + * deps: cookie@0.1.5 + - Throw on invalid values provided to `serialize` + * deps: depd@~1.1.0 + - Support web browser loading + - perf: enable strict mode + * deps: escape-html@~1.0.3 + - perf: enable strict mode + - perf: optimize string replacement + - perf: use faster string coercion + * deps: finalhandler@0.4.1 + - deps: escape-html@~1.0.3 + * deps: merge-descriptors@1.0.1 + - perf: enable strict mode + * deps: methods@~1.1.2 + - perf: enable strict mode + * deps: parseurl@~1.3.1 + - perf: enable strict mode + * deps: proxy-addr@~1.0.10 + - deps: ipaddr.js@1.0.5 + - perf: enable strict mode + * deps: range-parser@~1.0.3 + - perf: enable strict mode + * deps: send@0.13.1 + - deps: depd@~1.1.0 + - deps: destroy@~1.0.4 + - deps: escape-html@~1.0.3 + - deps: range-parser@~1.0.3 + * deps: serve-static@~1.10.2 + - deps: escape-html@~1.0.3 + - deps: parseurl@~1.3.0 + - deps: send@0.13.1 + +4.13.3 / 2015-08-02 +=================== + + * Fix infinite loop condition using `mergeParams: true` + * Fix inner numeric indices incorrectly altering parent `req.params` + +4.13.2 / 2015-07-31 +=================== + + * deps: accepts@~1.2.12 + - deps: mime-types@~2.1.4 + * deps: array-flatten@1.1.1 + - perf: enable strict mode + * deps: path-to-regexp@0.1.7 + - Fix regression with escaped round brackets and matching groups + * deps: type-is@~1.6.6 + - deps: mime-types@~2.1.4 + +4.13.1 / 2015-07-05 +=================== + + * deps: accepts@~1.2.10 + - deps: mime-types@~2.1.2 + * deps: qs@4.0.0 + - Fix dropping parameters like `hasOwnProperty` + - Fix various parsing edge cases + * deps: type-is@~1.6.4 + - deps: mime-types@~2.1.2 + - perf: enable strict mode + - perf: remove argument reassignment + +4.13.0 / 2015-06-20 +=================== + + * Add settings to debug output + * Fix `res.format` error when only `default` provided + * Fix issue where `next('route')` in `app.param` would incorrectly skip values + * Fix hiding platform issues with `decodeURIComponent` + - Only `URIError`s are a 400 + * Fix using `*` before params in routes + * Fix using capture groups before params in routes + * Simplify `res.cookie` to call `res.append` + * Use `array-flatten` module for flattening arrays + * deps: accepts@~1.2.9 + - deps: mime-types@~2.1.1 + - perf: avoid argument reassignment & argument slice + - perf: avoid negotiator recursive construction + - perf: enable strict mode + - perf: remove unnecessary bitwise operator + * deps: cookie@0.1.3 + - perf: deduce the scope of try-catch deopt + - perf: remove argument reassignments + * deps: escape-html@1.0.2 + * deps: etag@~1.7.0 + - Always include entity length in ETags for hash length extensions + - Generate non-Stats ETags using MD5 only (no longer CRC32) + - Improve stat performance by removing hashing + - Improve support for JXcore + - Remove base64 padding in ETags to shorten + - Support "fake" stats objects in environments without fs + - Use MD5 instead of MD4 in weak ETags over 1KB + * deps: finalhandler@0.4.0 + - Fix a false-positive when unpiping in Node.js 0.8 + - Support `statusCode` property on `Error` objects + - Use `unpipe` module for unpiping requests + - deps: escape-html@1.0.2 + - deps: on-finished@~2.3.0 + - perf: enable strict mode + - perf: remove argument reassignment + * deps: fresh@0.3.0 + - Add weak `ETag` matching support + * deps: on-finished@~2.3.0 + - Add defined behavior for HTTP `CONNECT` requests + - Add defined behavior for HTTP `Upgrade` requests + - deps: ee-first@1.1.1 + * deps: path-to-regexp@0.1.6 + * deps: send@0.13.0 + - Allow Node.js HTTP server to set `Date` response header + - Fix incorrectly removing `Content-Location` on 304 response + - Improve the default redirect response headers + - Send appropriate headers on default error response + - Use `http-errors` for standard emitted errors + - Use `statuses` instead of `http` module for status messages + - deps: escape-html@1.0.2 + - deps: etag@~1.7.0 + - deps: fresh@0.3.0 + - deps: on-finished@~2.3.0 + - perf: enable strict mode + - perf: remove unnecessary array allocations + * deps: serve-static@~1.10.0 + - Add `fallthrough` option + - Fix reading options from options prototype + - Improve the default redirect response headers + - Malformed URLs now `next()` instead of 400 + - deps: escape-html@1.0.2 + - deps: send@0.13.0 + - perf: enable strict mode + - perf: remove argument reassignment + * deps: type-is@~1.6.3 + - deps: mime-types@~2.1.1 + - perf: reduce try block size + - perf: remove bitwise operations + * perf: enable strict mode + * perf: isolate `app.render` try block + * perf: remove argument reassignments in application + * perf: remove argument reassignments in request prototype + * perf: remove argument reassignments in response prototype + * perf: remove argument reassignments in routing + * perf: remove argument reassignments in `View` + * perf: skip attempting to decode zero length string + * perf: use saved reference to `http.STATUS_CODES` + +4.12.4 / 2015-05-17 +=================== + + * deps: accepts@~1.2.7 + - deps: mime-types@~2.0.11 + - deps: negotiator@0.5.3 + * deps: debug@~2.2.0 + - deps: ms@0.7.1 + * deps: depd@~1.0.1 + * deps: etag@~1.6.0 + - Improve support for JXcore + - Support "fake" stats objects in environments without `fs` + * deps: finalhandler@0.3.6 + - deps: debug@~2.2.0 + - deps: on-finished@~2.2.1 + * deps: on-finished@~2.2.1 + - Fix `isFinished(req)` when data buffered + * deps: proxy-addr@~1.0.8 + - deps: ipaddr.js@1.0.1 + * deps: qs@2.4.2 + - Fix allowing parameters like `constructor` + * deps: send@0.12.3 + - deps: debug@~2.2.0 + - deps: depd@~1.0.1 + - deps: etag@~1.6.0 + - deps: ms@0.7.1 + - deps: on-finished@~2.2.1 + * deps: serve-static@~1.9.3 + - deps: send@0.12.3 + * deps: type-is@~1.6.2 + - deps: mime-types@~2.0.11 + +4.12.3 / 2015-03-17 +=================== + + * deps: accepts@~1.2.5 + - deps: mime-types@~2.0.10 + * deps: debug@~2.1.3 + - Fix high intensity foreground color for bold + - deps: ms@0.7.0 + * deps: finalhandler@0.3.4 + - deps: debug@~2.1.3 + * deps: proxy-addr@~1.0.7 + - deps: ipaddr.js@0.1.9 + * deps: qs@2.4.1 + - Fix error when parameter `hasOwnProperty` is present + * deps: send@0.12.2 + - Throw errors early for invalid `extensions` or `index` options + - deps: debug@~2.1.3 + * deps: serve-static@~1.9.2 + - deps: send@0.12.2 + * deps: type-is@~1.6.1 + - deps: mime-types@~2.0.10 + +4.12.2 / 2015-03-02 +=================== + + * Fix regression where `"Request aborted"` is logged using `res.sendFile` + +4.12.1 / 2015-03-01 +=================== + + * Fix constructing application with non-configurable prototype properties + * Fix `ECONNRESET` errors from `res.sendFile` usage + * Fix `req.host` when using "trust proxy" hops count + * Fix `req.protocol`/`req.secure` when using "trust proxy" hops count + * Fix wrong `code` on aborted connections from `res.sendFile` + * deps: merge-descriptors@1.0.0 + +4.12.0 / 2015-02-23 +=================== + + * Fix `"trust proxy"` setting to inherit when app is mounted + * Generate `ETag`s for all request responses + - No longer restricted to only responses for `GET` and `HEAD` requests + * Use `content-type` to parse `Content-Type` headers + * deps: accepts@~1.2.4 + - Fix preference sorting to be stable for long acceptable lists + - deps: mime-types@~2.0.9 + - deps: negotiator@0.5.1 + * deps: cookie-signature@1.0.6 + * deps: send@0.12.1 + - Always read the stat size from the file + - Fix mutating passed-in `options` + - deps: mime@1.3.4 + * deps: serve-static@~1.9.1 + - deps: send@0.12.1 + * deps: type-is@~1.6.0 + - fix argument reassignment + - fix false-positives in `hasBody` `Transfer-Encoding` check + - support wildcard for both type and subtype (`*/*`) + - deps: mime-types@~2.0.9 + +4.11.2 / 2015-02-01 +=================== + + * Fix `res.redirect` double-calling `res.end` for `HEAD` requests + * deps: accepts@~1.2.3 + - deps: mime-types@~2.0.8 + * deps: proxy-addr@~1.0.6 + - deps: ipaddr.js@0.1.8 + * deps: type-is@~1.5.6 + - deps: mime-types@~2.0.8 + +4.11.1 / 2015-01-20 +=================== + + * deps: send@0.11.1 + - Fix root path disclosure + * deps: serve-static@~1.8.1 + - Fix redirect loop in Node.js 0.11.14 + - Fix root path disclosure + - deps: send@0.11.1 + +4.11.0 / 2015-01-13 +=================== + + * Add `res.append(field, val)` to append headers + * Deprecate leading `:` in `name` for `app.param(name, fn)` + * Deprecate `req.param()` -- use `req.params`, `req.body`, or `req.query` instead + * Deprecate `app.param(fn)` + * Fix `OPTIONS` responses to include the `HEAD` method properly + * Fix `res.sendFile` not always detecting aborted connection + * Match routes iteratively to prevent stack overflows + * deps: accepts@~1.2.2 + - deps: mime-types@~2.0.7 + - deps: negotiator@0.5.0 + * deps: send@0.11.0 + - deps: debug@~2.1.1 + - deps: etag@~1.5.1 + - deps: ms@0.7.0 + - deps: on-finished@~2.2.0 + * deps: serve-static@~1.8.0 + - deps: send@0.11.0 + +4.10.8 / 2015-01-13 +=================== + + * Fix crash from error within `OPTIONS` response handler + * deps: proxy-addr@~1.0.5 + - deps: ipaddr.js@0.1.6 + +4.10.7 / 2015-01-04 +=================== + + * Fix `Allow` header for `OPTIONS` to not contain duplicate methods + * Fix incorrect "Request aborted" for `res.sendFile` when `HEAD` or 304 + * deps: debug@~2.1.1 + * deps: finalhandler@0.3.3 + - deps: debug@~2.1.1 + - deps: on-finished@~2.2.0 + * deps: methods@~1.1.1 + * deps: on-finished@~2.2.0 + * deps: serve-static@~1.7.2 + - Fix potential open redirect when mounted at root + * deps: type-is@~1.5.5 + - deps: mime-types@~2.0.7 + +4.10.6 / 2014-12-12 +=================== + + * Fix exception in `req.fresh`/`req.stale` without response headers + +4.10.5 / 2014-12-10 +=================== + + * Fix `res.send` double-calling `res.end` for `HEAD` requests + * deps: accepts@~1.1.4 + - deps: mime-types@~2.0.4 + * deps: type-is@~1.5.4 + - deps: mime-types@~2.0.4 + +4.10.4 / 2014-11-24 +=================== + + * Fix `res.sendfile` logging standard write errors + +4.10.3 / 2014-11-23 +=================== + + * Fix `res.sendFile` logging standard write errors + * deps: etag@~1.5.1 + * deps: proxy-addr@~1.0.4 + - deps: ipaddr.js@0.1.5 + * deps: qs@2.3.3 + - Fix `arrayLimit` behavior + +4.10.2 / 2014-11-09 +=================== + + * Correctly invoke async router callback asynchronously + * deps: accepts@~1.1.3 + - deps: mime-types@~2.0.3 + * deps: type-is@~1.5.3 + - deps: mime-types@~2.0.3 + +4.10.1 / 2014-10-28 +=================== + + * Fix handling of URLs containing `://` in the path + * deps: qs@2.3.2 + - Fix parsing of mixed objects and values + +4.10.0 / 2014-10-23 +=================== + + * Add support for `app.set('views', array)` + - Views are looked up in sequence in array of directories + * Fix `res.send(status)` to mention `res.sendStatus(status)` + * Fix handling of invalid empty URLs + * Use `content-disposition` module for `res.attachment`/`res.download` + - Sends standards-compliant `Content-Disposition` header + - Full Unicode support + * Use `path.resolve` in view lookup + * deps: debug@~2.1.0 + - Implement `DEBUG_FD` env variable support + * deps: depd@~1.0.0 + * deps: etag@~1.5.0 + - Improve string performance + - Slightly improve speed for weak ETags over 1KB + * deps: finalhandler@0.3.2 + - Terminate in progress response only on error + - Use `on-finished` to determine request status + - deps: debug@~2.1.0 + - deps: on-finished@~2.1.1 + * deps: on-finished@~2.1.1 + - Fix handling of pipelined requests + * deps: qs@2.3.0 + - Fix parsing of mixed implicit and explicit arrays + * deps: send@0.10.1 + - deps: debug@~2.1.0 + - deps: depd@~1.0.0 + - deps: etag@~1.5.0 + - deps: on-finished@~2.1.1 + * deps: serve-static@~1.7.1 + - deps: send@0.10.1 + +4.9.8 / 2014-10-17 +================== + + * Fix `res.redirect` body when redirect status specified + * deps: accepts@~1.1.2 + - Fix error when media type has invalid parameter + - deps: negotiator@0.4.9 + +4.9.7 / 2014-10-10 +================== + + * Fix using same param name in array of paths + +4.9.6 / 2014-10-08 +================== + + * deps: accepts@~1.1.1 + - deps: mime-types@~2.0.2 + - deps: negotiator@0.4.8 + * deps: serve-static@~1.6.4 + - Fix redirect loop when index file serving disabled + * deps: type-is@~1.5.2 + - deps: mime-types@~2.0.2 + +4.9.5 / 2014-09-24 +================== + + * deps: etag@~1.4.0 + * deps: proxy-addr@~1.0.3 + - Use `forwarded` npm module + * deps: send@0.9.3 + - deps: etag@~1.4.0 + * deps: serve-static@~1.6.3 + - deps: send@0.9.3 + +4.9.4 / 2014-09-19 +================== + + * deps: qs@2.2.4 + - Fix issue with object keys starting with numbers truncated + +4.9.3 / 2014-09-18 +================== + + * deps: proxy-addr@~1.0.2 + - Fix a global leak when multiple subnets are trusted + - deps: ipaddr.js@0.1.3 + +4.9.2 / 2014-09-17 +================== + + * Fix regression for empty string `path` in `app.use` + * Fix `router.use` to accept array of middleware without path + * Improve error message for bad `app.use` arguments + +4.9.1 / 2014-09-16 +================== + + * Fix `app.use` to accept array of middleware without path + * deps: depd@0.4.5 + * deps: etag@~1.3.1 + * deps: send@0.9.2 + - deps: depd@0.4.5 + - deps: etag@~1.3.1 + - deps: range-parser@~1.0.2 + * deps: serve-static@~1.6.2 + - deps: send@0.9.2 + +4.9.0 / 2014-09-08 +================== + + * Add `res.sendStatus` + * Invoke callback for sendfile when client aborts + - Applies to `res.sendFile`, `res.sendfile`, and `res.download` + - `err` will be populated with request aborted error + * Support IP address host in `req.subdomains` + * Use `etag` to generate `ETag` headers + * deps: accepts@~1.1.0 + - update `mime-types` + * deps: cookie-signature@1.0.5 + * deps: debug@~2.0.0 + * deps: finalhandler@0.2.0 + - Set `X-Content-Type-Options: nosniff` header + - deps: debug@~2.0.0 + * deps: fresh@0.2.4 + * deps: media-typer@0.3.0 + - Throw error when parameter format invalid on parse + * deps: qs@2.2.3 + - Fix issue where first empty value in array is discarded + * deps: range-parser@~1.0.2 + * deps: send@0.9.1 + - Add `lastModified` option + - Use `etag` to generate `ETag` header + - deps: debug@~2.0.0 + - deps: fresh@0.2.4 + * deps: serve-static@~1.6.1 + - Add `lastModified` option + - deps: send@0.9.1 + * deps: type-is@~1.5.1 + - fix `hasbody` to be true for `content-length: 0` + - deps: media-typer@0.3.0 + - deps: mime-types@~2.0.1 + * deps: vary@~1.0.0 + - Accept valid `Vary` header string as `field` + +4.8.8 / 2014-09-04 +================== + + * deps: send@0.8.5 + - Fix a path traversal issue when using `root` + - Fix malicious path detection for empty string path + * deps: serve-static@~1.5.4 + - deps: send@0.8.5 + +4.8.7 / 2014-08-29 +================== + + * deps: qs@2.2.2 + - Remove unnecessary cloning + +4.8.6 / 2014-08-27 +================== + + * deps: qs@2.2.0 + - Array parsing fix + - Performance improvements + +4.8.5 / 2014-08-18 +================== + + * deps: send@0.8.3 + - deps: destroy@1.0.3 + - deps: on-finished@2.1.0 + * deps: serve-static@~1.5.3 + - deps: send@0.8.3 + +4.8.4 / 2014-08-14 +================== + + * deps: qs@1.2.2 + * deps: send@0.8.2 + - Work around `fd` leak in Node.js 0.10 for `fs.ReadStream` + * deps: serve-static@~1.5.2 + - deps: send@0.8.2 + +4.8.3 / 2014-08-10 +================== + + * deps: parseurl@~1.3.0 + * deps: qs@1.2.1 + * deps: serve-static@~1.5.1 + - Fix parsing of weird `req.originalUrl` values + - deps: parseurl@~1.3.0 + - deps: utils-merge@1.0.0 + +4.8.2 / 2014-08-07 +================== + + * deps: qs@1.2.0 + - Fix parsing array of objects + +4.8.1 / 2014-08-06 +================== + + * fix incorrect deprecation warnings on `res.download` + * deps: qs@1.1.0 + - Accept urlencoded square brackets + - Accept empty values in implicit array notation + +4.8.0 / 2014-08-05 +================== + + * add `res.sendFile` + - accepts a file system path instead of a URL + - requires an absolute path or `root` option specified + * deprecate `res.sendfile` -- use `res.sendFile` instead + * support mounted app as any argument to `app.use()` + * deps: qs@1.0.2 + - Complete rewrite + - Limits array length to 20 + - Limits object depth to 5 + - Limits parameters to 1,000 + * deps: send@0.8.1 + - Add `extensions` option + * deps: serve-static@~1.5.0 + - Add `extensions` option + - deps: send@0.8.1 + +4.7.4 / 2014-08-04 +================== + + * fix `res.sendfile` regression for serving directory index files + * deps: send@0.7.4 + - Fix incorrect 403 on Windows and Node.js 0.11 + - Fix serving index files without root dir + * deps: serve-static@~1.4.4 + - deps: send@0.7.4 + +4.7.3 / 2014-08-04 +================== + + * deps: send@0.7.3 + - Fix incorrect 403 on Windows and Node.js 0.11 + * deps: serve-static@~1.4.3 + - Fix incorrect 403 on Windows and Node.js 0.11 + - deps: send@0.7.3 + +4.7.2 / 2014-07-27 +================== + + * deps: depd@0.4.4 + - Work-around v8 generating empty stack traces + * deps: send@0.7.2 + - deps: depd@0.4.4 + * deps: serve-static@~1.4.2 + +4.7.1 / 2014-07-26 +================== + + * deps: depd@0.4.3 + - Fix exception when global `Error.stackTraceLimit` is too low + * deps: send@0.7.1 + - deps: depd@0.4.3 + * deps: serve-static@~1.4.1 + +4.7.0 / 2014-07-25 +================== + + * fix `req.protocol` for proxy-direct connections + * configurable query parser with `app.set('query parser', parser)` + - `app.set('query parser', 'extended')` parse with "qs" module + - `app.set('query parser', 'simple')` parse with "querystring" core module + - `app.set('query parser', false)` disable query string parsing + - `app.set('query parser', true)` enable simple parsing + * deprecate `res.json(status, obj)` -- use `res.status(status).json(obj)` instead + * deprecate `res.jsonp(status, obj)` -- use `res.status(status).jsonp(obj)` instead + * deprecate `res.send(status, body)` -- use `res.status(status).send(body)` instead + * deps: debug@1.0.4 + * deps: depd@0.4.2 + - Add `TRACE_DEPRECATION` environment variable + - Remove non-standard grey color from color output + - Support `--no-deprecation` argument + - Support `--trace-deprecation` argument + * deps: finalhandler@0.1.0 + - Respond after request fully read + - deps: debug@1.0.4 + * deps: parseurl@~1.2.0 + - Cache URLs based on original value + - Remove no-longer-needed URL mis-parse work-around + - Simplify the "fast-path" `RegExp` + * deps: send@0.7.0 + - Add `dotfiles` option + - Cap `maxAge` value to 1 year + - deps: debug@1.0.4 + - deps: depd@0.4.2 + * deps: serve-static@~1.4.0 + - deps: parseurl@~1.2.0 + - deps: send@0.7.0 + * perf: prevent multiple `Buffer` creation in `res.send` + +4.6.1 / 2014-07-12 +================== + + * fix `subapp.mountpath` regression for `app.use(subapp)` + +4.6.0 / 2014-07-11 +================== + + * accept multiple callbacks to `app.use()` + * add explicit "Rosetta Flash JSONP abuse" protection + - previous versions are not vulnerable; this is just explicit protection + * catch errors in multiple `req.param(name, fn)` handlers + * deprecate `res.redirect(url, status)` -- use `res.redirect(status, url)` instead + * fix `res.send(status, num)` to send `num` as json (not error) + * remove unnecessary escaping when `res.jsonp` returns JSON response + * support non-string `path` in `app.use(path, fn)` + - supports array of paths + - supports `RegExp` + * router: fix optimization on router exit + * router: refactor location of `try` blocks + * router: speed up standard `app.use(fn)` + * deps: debug@1.0.3 + - Add support for multiple wildcards in namespaces + * deps: finalhandler@0.0.3 + - deps: debug@1.0.3 + * deps: methods@1.1.0 + - add `CONNECT` + * deps: parseurl@~1.1.3 + - faster parsing of href-only URLs + * deps: path-to-regexp@0.1.3 + * deps: send@0.6.0 + - deps: debug@1.0.3 + * deps: serve-static@~1.3.2 + - deps: parseurl@~1.1.3 + - deps: send@0.6.0 + * perf: fix arguments reassign deopt in some `res` methods + +4.5.1 / 2014-07-06 +================== + + * fix routing regression when altering `req.method` + +4.5.0 / 2014-07-04 +================== + + * add deprecation message to non-plural `req.accepts*` + * add deprecation message to `res.send(body, status)` + * add deprecation message to `res.vary()` + * add `headers` option to `res.sendfile` + - use to set headers on successful file transfer + * add `mergeParams` option to `Router` + - merges `req.params` from parent routes + * add `req.hostname` -- correct name for what `req.host` returns + * deprecate things with `depd` module + * deprecate `req.host` -- use `req.hostname` instead + * fix behavior when handling request without routes + * fix handling when `route.all` is only route + * invoke `router.param()` only when route matches + * restore `req.params` after invoking router + * use `finalhandler` for final response handling + * use `media-typer` to alter content-type charset + * deps: accepts@~1.0.7 + * deps: send@0.5.0 + - Accept string for `maxage` (converted by `ms`) + - Include link in default redirect response + * deps: serve-static@~1.3.0 + - Accept string for `maxAge` (converted by `ms`) + - Add `setHeaders` option + - Include HTML link in redirect response + - deps: send@0.5.0 + * deps: type-is@~1.3.2 + +4.4.5 / 2014-06-26 +================== + + * deps: cookie-signature@1.0.4 + - fix for timing attacks + +4.4.4 / 2014-06-20 +================== + + * fix `res.attachment` Unicode filenames in Safari + * fix "trim prefix" debug message in `express:router` + * deps: accepts@~1.0.5 + * deps: buffer-crc32@0.2.3 + +4.4.3 / 2014-06-11 +================== + + * fix persistence of modified `req.params[name]` from `app.param()` + * deps: accepts@1.0.3 + - deps: negotiator@0.4.6 + * deps: debug@1.0.2 + * deps: send@0.4.3 + - Do not throw un-catchable error on file open race condition + - Use `escape-html` for HTML escaping + - deps: debug@1.0.2 + - deps: finished@1.2.2 + - deps: fresh@0.2.2 + * deps: serve-static@1.2.3 + - Do not throw un-catchable error on file open race condition + - deps: send@0.4.3 + +4.4.2 / 2014-06-09 +================== + + * fix catching errors from top-level handlers + * use `vary` module for `res.vary` + * deps: debug@1.0.1 + * deps: proxy-addr@1.0.1 + * deps: send@0.4.2 + - fix "event emitter leak" warnings + - deps: debug@1.0.1 + - deps: finished@1.2.1 + * deps: serve-static@1.2.2 + - fix "event emitter leak" warnings + - deps: send@0.4.2 + * deps: type-is@1.2.1 + +4.4.1 / 2014-06-02 +================== + + * deps: methods@1.0.1 + * deps: send@0.4.1 + - Send `max-age` in `Cache-Control` in correct format + * deps: serve-static@1.2.1 + - use `escape-html` for escaping + - deps: send@0.4.1 + +4.4.0 / 2014-05-30 +================== + + * custom etag control with `app.set('etag', val)` + - `app.set('etag', function(body, encoding){ return '"etag"' })` custom etag generation + - `app.set('etag', 'weak')` weak tag + - `app.set('etag', 'strong')` strong etag + - `app.set('etag', false)` turn off + - `app.set('etag', true)` standard etag + * mark `res.send` ETag as weak and reduce collisions + * update accepts to 1.0.2 + - Fix interpretation when header not in request + * update send to 0.4.0 + - Calculate ETag with md5 for reduced collisions + - Ignore stream errors after request ends + - deps: debug@0.8.1 + * update serve-static to 1.2.0 + - Calculate ETag with md5 for reduced collisions + - Ignore stream errors after request ends + - deps: send@0.4.0 + +4.3.2 / 2014-05-28 +================== + + * fix handling of errors from `router.param()` callbacks + +4.3.1 / 2014-05-23 +================== + + * revert "fix behavior of multiple `app.VERB` for the same path" + - this caused a regression in the order of route execution + +4.3.0 / 2014-05-21 +================== + + * add `req.baseUrl` to access the path stripped from `req.url` in routes + * fix behavior of multiple `app.VERB` for the same path + * fix issue routing requests among sub routers + * invoke `router.param()` only when necessary instead of every match + * proper proxy trust with `app.set('trust proxy', trust)` + - `app.set('trust proxy', 1)` trust first hop + - `app.set('trust proxy', 'loopback')` trust loopback addresses + - `app.set('trust proxy', '10.0.0.1')` trust single IP + - `app.set('trust proxy', '10.0.0.1/16')` trust subnet + - `app.set('trust proxy', '10.0.0.1, 10.0.0.2')` trust list + - `app.set('trust proxy', false)` turn off + - `app.set('trust proxy', true)` trust everything + * set proper `charset` in `Content-Type` for `res.send` + * update type-is to 1.2.0 + - support suffix matching + +4.2.0 / 2014-05-11 +================== + + * deprecate `app.del()` -- use `app.delete()` instead + * deprecate `res.json(obj, status)` -- use `res.json(status, obj)` instead + - the edge-case `res.json(status, num)` requires `res.status(status).json(num)` + * deprecate `res.jsonp(obj, status)` -- use `res.jsonp(status, obj)` instead + - the edge-case `res.jsonp(status, num)` requires `res.status(status).jsonp(num)` + * fix `req.next` when inside router instance + * include `ETag` header in `HEAD` requests + * keep previous `Content-Type` for `res.jsonp` + * support PURGE method + - add `app.purge` + - add `router.purge` + - include PURGE in `app.all` + * update debug to 0.8.0 + - add `enable()` method + - change from stderr to stdout + * update methods to 1.0.0 + - add PURGE + +4.1.2 / 2014-05-08 +================== + + * fix `req.host` for IPv6 literals + * fix `res.jsonp` error if callback param is object + +4.1.1 / 2014-04-27 +================== + + * fix package.json to reflect supported node version + +4.1.0 / 2014-04-24 +================== + + * pass options from `res.sendfile` to `send` + * preserve casing of headers in `res.header` and `res.set` + * support unicode file names in `res.attachment` and `res.download` + * update accepts to 1.0.1 + - deps: negotiator@0.4.0 + * update cookie to 0.1.2 + - Fix for maxAge == 0 + - made compat with expires field + * update send to 0.3.0 + - Accept API options in options object + - Coerce option types + - Control whether to generate etags + - Default directory access to 403 when index disabled + - Fix sending files with dots without root set + - Include file path in etag + - Make "Can't set headers after they are sent." catchable + - Send full entity-body for multi range requests + - Set etags to "weak" + - Support "If-Range" header + - Support multiple index paths + - deps: mime@1.2.11 + * update serve-static to 1.1.0 + - Accept options directly to `send` module + - Resolve relative paths at middleware setup + - Use parseurl to parse the URL from request + - deps: send@0.3.0 + * update type-is to 1.1.0 + - add non-array values support + - add `multipart` as a shorthand + +4.0.0 / 2014-04-09 +================== + + * remove: + - node 0.8 support + - connect and connect's patches except for charset handling + - express(1) - moved to [express-generator](https://github.com/expressjs/generator) + - `express.createServer()` - it has been deprecated for a long time. Use `express()` + - `app.configure` - use logic in your own app code + - `app.router` - is removed + - `req.auth` - use `basic-auth` instead + - `req.accepted*` - use `req.accepts*()` instead + - `res.location` - relative URL resolution is removed + - `res.charset` - include the charset in the content type when using `res.set()` + - all bundled middleware except `static` + * change: + - `app.route` -> `app.mountpath` when mounting an express app in another express app + - `json spaces` no longer enabled by default in development + - `req.accepts*` -> `req.accepts*s` - i.e. `req.acceptsEncoding` -> `req.acceptsEncodings` + - `req.params` is now an object instead of an array + - `res.locals` is no longer a function. It is a plain js object. Treat it as such. + - `res.headerSent` -> `res.headersSent` to match node.js ServerResponse object + * refactor: + - `req.accepts*` with [accepts](https://github.com/expressjs/accepts) + - `req.is` with [type-is](https://github.com/expressjs/type-is) + - [path-to-regexp](https://github.com/component/path-to-regexp) + * add: + - `app.router()` - returns the app Router instance + - `app.route()` - Proxy to the app's `Router#route()` method to create a new route + - Router & Route - public API + +3.21.2 / 2015-07-31 +=================== + + * deps: connect@2.30.2 + - deps: body-parser@~1.13.3 + - deps: compression@~1.5.2 + - deps: errorhandler@~1.4.2 + - deps: method-override@~2.3.5 + - deps: serve-index@~1.7.2 + - deps: type-is@~1.6.6 + - deps: vhost@~3.0.1 + * deps: vary@~1.0.1 + - Fix setting empty header from empty `field` + - perf: enable strict mode + - perf: remove argument reassignments + +3.21.1 / 2015-07-05 +=================== + + * deps: basic-auth@~1.0.3 + * deps: connect@2.30.1 + - deps: body-parser@~1.13.2 + - deps: compression@~1.5.1 + - deps: errorhandler@~1.4.1 + - deps: morgan@~1.6.1 + - deps: pause@0.1.0 + - deps: qs@4.0.0 + - deps: serve-index@~1.7.1 + - deps: type-is@~1.6.4 + +3.21.0 / 2015-06-18 +=================== + + * deps: basic-auth@1.0.2 + - perf: enable strict mode + - perf: hoist regular expression + - perf: parse with regular expressions + - perf: remove argument reassignment + * deps: connect@2.30.0 + - deps: body-parser@~1.13.1 + - deps: bytes@2.1.0 + - deps: compression@~1.5.0 + - deps: cookie@0.1.3 + - deps: cookie-parser@~1.3.5 + - deps: csurf@~1.8.3 + - deps: errorhandler@~1.4.0 + - deps: express-session@~1.11.3 + - deps: finalhandler@0.4.0 + - deps: fresh@0.3.0 + - deps: morgan@~1.6.0 + - deps: serve-favicon@~2.3.0 + - deps: serve-index@~1.7.0 + - deps: serve-static@~1.10.0 + - deps: type-is@~1.6.3 + * deps: cookie@0.1.3 + - perf: deduce the scope of try-catch deopt + - perf: remove argument reassignments + * deps: escape-html@1.0.2 + * deps: etag@~1.7.0 + - Always include entity length in ETags for hash length extensions + - Generate non-Stats ETags using MD5 only (no longer CRC32) + - Improve stat performance by removing hashing + - Improve support for JXcore + - Remove base64 padding in ETags to shorten + - Support "fake" stats objects in environments without fs + - Use MD5 instead of MD4 in weak ETags over 1KB + * deps: fresh@0.3.0 + - Add weak `ETag` matching support + * deps: mkdirp@0.5.1 + - Work in global strict mode + * deps: send@0.13.0 + - Allow Node.js HTTP server to set `Date` response header + - Fix incorrectly removing `Content-Location` on 304 response + - Improve the default redirect response headers + - Send appropriate headers on default error response + - Use `http-errors` for standard emitted errors + - Use `statuses` instead of `http` module for status messages + - deps: escape-html@1.0.2 + - deps: etag@~1.7.0 + - deps: fresh@0.3.0 + - deps: on-finished@~2.3.0 + - perf: enable strict mode + - perf: remove unnecessary array allocations + +3.20.3 / 2015-05-17 +=================== + + * deps: connect@2.29.2 + - deps: body-parser@~1.12.4 + - deps: compression@~1.4.4 + - deps: connect-timeout@~1.6.2 + - deps: debug@~2.2.0 + - deps: depd@~1.0.1 + - deps: errorhandler@~1.3.6 + - deps: finalhandler@0.3.6 + - deps: method-override@~2.3.3 + - deps: morgan@~1.5.3 + - deps: qs@2.4.2 + - deps: response-time@~2.3.1 + - deps: serve-favicon@~2.2.1 + - deps: serve-index@~1.6.4 + - deps: serve-static@~1.9.3 + - deps: type-is@~1.6.2 + * deps: debug@~2.2.0 + - deps: ms@0.7.1 + * deps: depd@~1.0.1 + * deps: proxy-addr@~1.0.8 + - deps: ipaddr.js@1.0.1 + * deps: send@0.12.3 + - deps: debug@~2.2.0 + - deps: depd@~1.0.1 + - deps: etag@~1.6.0 + - deps: ms@0.7.1 + - deps: on-finished@~2.2.1 + +3.20.2 / 2015-03-16 +=================== + + * deps: connect@2.29.1 + - deps: body-parser@~1.12.2 + - deps: compression@~1.4.3 + - deps: connect-timeout@~1.6.1 + - deps: debug@~2.1.3 + - deps: errorhandler@~1.3.5 + - deps: express-session@~1.10.4 + - deps: finalhandler@0.3.4 + - deps: method-override@~2.3.2 + - deps: morgan@~1.5.2 + - deps: qs@2.4.1 + - deps: serve-index@~1.6.3 + - deps: serve-static@~1.9.2 + - deps: type-is@~1.6.1 + * deps: debug@~2.1.3 + - Fix high intensity foreground color for bold + - deps: ms@0.7.0 + * deps: merge-descriptors@1.0.0 + * deps: proxy-addr@~1.0.7 + - deps: ipaddr.js@0.1.9 + * deps: send@0.12.2 + - Throw errors early for invalid `extensions` or `index` options + - deps: debug@~2.1.3 + +3.20.1 / 2015-02-28 +=================== + + * Fix `req.host` when using "trust proxy" hops count + * Fix `req.protocol`/`req.secure` when using "trust proxy" hops count + +3.20.0 / 2015-02-18 +=================== + + * Fix `"trust proxy"` setting to inherit when app is mounted + * Generate `ETag`s for all request responses + - No longer restricted to only responses for `GET` and `HEAD` requests + * Use `content-type` to parse `Content-Type` headers + * deps: connect@2.29.0 + - Use `content-type` to parse `Content-Type` headers + - deps: body-parser@~1.12.0 + - deps: compression@~1.4.1 + - deps: connect-timeout@~1.6.0 + - deps: cookie-parser@~1.3.4 + - deps: cookie-signature@1.0.6 + - deps: csurf@~1.7.0 + - deps: errorhandler@~1.3.4 + - deps: express-session@~1.10.3 + - deps: http-errors@~1.3.1 + - deps: response-time@~2.3.0 + - deps: serve-index@~1.6.2 + - deps: serve-static@~1.9.1 + - deps: type-is@~1.6.0 + * deps: cookie-signature@1.0.6 + * deps: send@0.12.1 + - Always read the stat size from the file + - Fix mutating passed-in `options` + - deps: mime@1.3.4 + +3.19.2 / 2015-02-01 +=================== + + * deps: connect@2.28.3 + - deps: compression@~1.3.1 + - deps: csurf@~1.6.6 + - deps: errorhandler@~1.3.3 + - deps: express-session@~1.10.2 + - deps: serve-index@~1.6.1 + - deps: type-is@~1.5.6 + * deps: proxy-addr@~1.0.6 + - deps: ipaddr.js@0.1.8 + +3.19.1 / 2015-01-20 +=================== + + * deps: connect@2.28.2 + - deps: body-parser@~1.10.2 + - deps: serve-static@~1.8.1 + * deps: send@0.11.1 + - Fix root path disclosure + +3.19.0 / 2015-01-09 +=================== + + * Fix `OPTIONS` responses to include the `HEAD` method property + * Use `readline` for prompt in `express(1)` + * deps: commander@2.6.0 + * deps: connect@2.28.1 + - deps: body-parser@~1.10.1 + - deps: compression@~1.3.0 + - deps: connect-timeout@~1.5.0 + - deps: csurf@~1.6.4 + - deps: debug@~2.1.1 + - deps: errorhandler@~1.3.2 + - deps: express-session@~1.10.1 + - deps: finalhandler@0.3.3 + - deps: method-override@~2.3.1 + - deps: morgan@~1.5.1 + - deps: serve-favicon@~2.2.0 + - deps: serve-index@~1.6.0 + - deps: serve-static@~1.8.0 + - deps: type-is@~1.5.5 + * deps: debug@~2.1.1 + * deps: methods@~1.1.1 + * deps: proxy-addr@~1.0.5 + - deps: ipaddr.js@0.1.6 + * deps: send@0.11.0 + - deps: debug@~2.1.1 + - deps: etag@~1.5.1 + - deps: ms@0.7.0 + - deps: on-finished@~2.2.0 + +3.18.6 / 2014-12-12 +=================== + + * Fix exception in `req.fresh`/`req.stale` without response headers + +3.18.5 / 2014-12-11 +=================== + + * deps: connect@2.27.6 + - deps: compression@~1.2.2 + - deps: express-session@~1.9.3 + - deps: http-errors@~1.2.8 + - deps: serve-index@~1.5.3 + - deps: type-is@~1.5.4 + +3.18.4 / 2014-11-23 +=================== + + * deps: connect@2.27.4 + - deps: body-parser@~1.9.3 + - deps: compression@~1.2.1 + - deps: errorhandler@~1.2.3 + - deps: express-session@~1.9.2 + - deps: qs@2.3.3 + - deps: serve-favicon@~2.1.7 + - deps: serve-static@~1.5.1 + - deps: type-is@~1.5.3 + * deps: etag@~1.5.1 + * deps: proxy-addr@~1.0.4 + - deps: ipaddr.js@0.1.5 + +3.18.3 / 2014-11-09 +=================== + + * deps: connect@2.27.3 + - Correctly invoke async callback asynchronously + - deps: csurf@~1.6.3 + +3.18.2 / 2014-10-28 +=================== + + * deps: connect@2.27.2 + - Fix handling of URLs containing `://` in the path + - deps: body-parser@~1.9.2 + - deps: qs@2.3.2 + +3.18.1 / 2014-10-22 +=================== + + * Fix internal `utils.merge` deprecation warnings + * deps: connect@2.27.1 + - deps: body-parser@~1.9.1 + - deps: express-session@~1.9.1 + - deps: finalhandler@0.3.2 + - deps: morgan@~1.4.1 + - deps: qs@2.3.0 + - deps: serve-static@~1.7.1 + * deps: send@0.10.1 + - deps: on-finished@~2.1.1 + +3.18.0 / 2014-10-17 +=================== + + * Use `content-disposition` module for `res.attachment`/`res.download` + - Sends standards-compliant `Content-Disposition` header + - Full Unicode support + * Use `etag` module to generate `ETag` headers + * deps: connect@2.27.0 + - Use `http-errors` module for creating errors + - Use `utils-merge` module for merging objects + - deps: body-parser@~1.9.0 + - deps: compression@~1.2.0 + - deps: connect-timeout@~1.4.0 + - deps: debug@~2.1.0 + - deps: depd@~1.0.0 + - deps: express-session@~1.9.0 + - deps: finalhandler@0.3.1 + - deps: method-override@~2.3.0 + - deps: morgan@~1.4.0 + - deps: response-time@~2.2.0 + - deps: serve-favicon@~2.1.6 + - deps: serve-index@~1.5.0 + - deps: serve-static@~1.7.0 + * deps: debug@~2.1.0 + - Implement `DEBUG_FD` env variable support + * deps: depd@~1.0.0 + * deps: send@0.10.0 + - deps: debug@~2.1.0 + - deps: depd@~1.0.0 + - deps: etag@~1.5.0 + +3.17.8 / 2014-10-15 +=================== + + * deps: connect@2.26.6 + - deps: compression@~1.1.2 + - deps: csurf@~1.6.2 + - deps: errorhandler@~1.2.2 + +3.17.7 / 2014-10-08 +=================== + + * deps: connect@2.26.5 + - Fix accepting non-object arguments to `logger` + - deps: serve-static@~1.6.4 + +3.17.6 / 2014-10-02 +=================== + + * deps: connect@2.26.4 + - deps: morgan@~1.3.2 + - deps: type-is@~1.5.2 + +3.17.5 / 2014-09-24 +=================== + + * deps: connect@2.26.3 + - deps: body-parser@~1.8.4 + - deps: serve-favicon@~2.1.5 + - deps: serve-static@~1.6.3 + * deps: proxy-addr@~1.0.3 + - Use `forwarded` npm module + * deps: send@0.9.3 + - deps: etag@~1.4.0 + +3.17.4 / 2014-09-19 +=================== + + * deps: connect@2.26.2 + - deps: body-parser@~1.8.3 + - deps: qs@2.2.4 + +3.17.3 / 2014-09-18 +=================== + + * deps: proxy-addr@~1.0.2 + - Fix a global leak when multiple subnets are trusted + - deps: ipaddr.js@0.1.3 + +3.17.2 / 2014-09-15 +=================== + + * Use `crc` instead of `buffer-crc32` for speed + * deps: connect@2.26.1 + - deps: body-parser@~1.8.2 + - deps: depd@0.4.5 + - deps: express-session@~1.8.2 + - deps: morgan@~1.3.1 + - deps: serve-favicon@~2.1.3 + - deps: serve-static@~1.6.2 + * deps: depd@0.4.5 + * deps: send@0.9.2 + - deps: depd@0.4.5 + - deps: etag@~1.3.1 + - deps: range-parser@~1.0.2 + +3.17.1 / 2014-09-08 +=================== + + * Fix error in `req.subdomains` on empty host + +3.17.0 / 2014-09-08 +=================== + + * Support `X-Forwarded-Host` in `req.subdomains` + * Support IP address host in `req.subdomains` + * deps: connect@2.26.0 + - deps: body-parser@~1.8.1 + - deps: compression@~1.1.0 + - deps: connect-timeout@~1.3.0 + - deps: cookie-parser@~1.3.3 + - deps: cookie-signature@1.0.5 + - deps: csurf@~1.6.1 + - deps: debug@~2.0.0 + - deps: errorhandler@~1.2.0 + - deps: express-session@~1.8.1 + - deps: finalhandler@0.2.0 + - deps: fresh@0.2.4 + - deps: media-typer@0.3.0 + - deps: method-override@~2.2.0 + - deps: morgan@~1.3.0 + - deps: qs@2.2.3 + - deps: serve-favicon@~2.1.3 + - deps: serve-index@~1.2.1 + - deps: serve-static@~1.6.1 + - deps: type-is@~1.5.1 + - deps: vhost@~3.0.0 + * deps: cookie-signature@1.0.5 + * deps: debug@~2.0.0 + * deps: fresh@0.2.4 + * deps: media-typer@0.3.0 + - Throw error when parameter format invalid on parse + * deps: range-parser@~1.0.2 + * deps: send@0.9.1 + - Add `lastModified` option + - Use `etag` to generate `ETag` header + - deps: debug@~2.0.0 + - deps: fresh@0.2.4 + * deps: vary@~1.0.0 + - Accept valid `Vary` header string as `field` + +3.16.10 / 2014-09-04 +==================== + + * deps: connect@2.25.10 + - deps: serve-static@~1.5.4 + * deps: send@0.8.5 + - Fix a path traversal issue when using `root` + - Fix malicious path detection for empty string path + +3.16.9 / 2014-08-29 +=================== + + * deps: connect@2.25.9 + - deps: body-parser@~1.6.7 + - deps: qs@2.2.2 + +3.16.8 / 2014-08-27 +=================== + + * deps: connect@2.25.8 + - deps: body-parser@~1.6.6 + - deps: csurf@~1.4.1 + - deps: qs@2.2.0 + +3.16.7 / 2014-08-18 +=================== + + * deps: connect@2.25.7 + - deps: body-parser@~1.6.5 + - deps: express-session@~1.7.6 + - deps: morgan@~1.2.3 + - deps: serve-static@~1.5.3 + * deps: send@0.8.3 + - deps: destroy@1.0.3 + - deps: on-finished@2.1.0 + +3.16.6 / 2014-08-14 +=================== + + * deps: connect@2.25.6 + - deps: body-parser@~1.6.4 + - deps: qs@1.2.2 + - deps: serve-static@~1.5.2 + * deps: send@0.8.2 + - Work around `fd` leak in Node.js 0.10 for `fs.ReadStream` + +3.16.5 / 2014-08-11 +=================== + + * deps: connect@2.25.5 + - Fix backwards compatibility in `logger` + +3.16.4 / 2014-08-10 +=================== + + * Fix original URL parsing in `res.location` + * deps: connect@2.25.4 + - Fix `query` middleware breaking with argument + - deps: body-parser@~1.6.3 + - deps: compression@~1.0.11 + - deps: connect-timeout@~1.2.2 + - deps: express-session@~1.7.5 + - deps: method-override@~2.1.3 + - deps: on-headers@~1.0.0 + - deps: parseurl@~1.3.0 + - deps: qs@1.2.1 + - deps: response-time@~2.0.1 + - deps: serve-index@~1.1.6 + - deps: serve-static@~1.5.1 + * deps: parseurl@~1.3.0 + +3.16.3 / 2014-08-07 +=================== + + * deps: connect@2.25.3 + - deps: multiparty@3.3.2 + +3.16.2 / 2014-08-07 +=================== + + * deps: connect@2.25.2 + - deps: body-parser@~1.6.2 + - deps: qs@1.2.0 + +3.16.1 / 2014-08-06 +=================== + + * deps: connect@2.25.1 + - deps: body-parser@~1.6.1 + - deps: qs@1.1.0 + +3.16.0 / 2014-08-05 +=================== + + * deps: connect@2.25.0 + - deps: body-parser@~1.6.0 + - deps: compression@~1.0.10 + - deps: csurf@~1.4.0 + - deps: express-session@~1.7.4 + - deps: qs@1.0.2 + - deps: serve-static@~1.5.0 + * deps: send@0.8.1 + - Add `extensions` option + +3.15.3 / 2014-08-04 +=================== + + * fix `res.sendfile` regression for serving directory index files + * deps: connect@2.24.3 + - deps: serve-index@~1.1.5 + - deps: serve-static@~1.4.4 + * deps: send@0.7.4 + - Fix incorrect 403 on Windows and Node.js 0.11 + - Fix serving index files without root dir + +3.15.2 / 2014-07-27 +=================== + + * deps: connect@2.24.2 + - deps: body-parser@~1.5.2 + - deps: depd@0.4.4 + - deps: express-session@~1.7.2 + - deps: morgan@~1.2.2 + - deps: serve-static@~1.4.2 + * deps: depd@0.4.4 + - Work-around v8 generating empty stack traces + * deps: send@0.7.2 + - deps: depd@0.4.4 + +3.15.1 / 2014-07-26 +=================== + + * deps: connect@2.24.1 + - deps: body-parser@~1.5.1 + - deps: depd@0.4.3 + - deps: express-session@~1.7.1 + - deps: morgan@~1.2.1 + - deps: serve-index@~1.1.4 + - deps: serve-static@~1.4.1 + * deps: depd@0.4.3 + - Fix exception when global `Error.stackTraceLimit` is too low + * deps: send@0.7.1 + - deps: depd@0.4.3 + +3.15.0 / 2014-07-22 +=================== + + * Fix `req.protocol` for proxy-direct connections + * Pass options from `res.sendfile` to `send` + * deps: connect@2.24.0 + - deps: body-parser@~1.5.0 + - deps: compression@~1.0.9 + - deps: connect-timeout@~1.2.1 + - deps: debug@1.0.4 + - deps: depd@0.4.2 + - deps: express-session@~1.7.0 + - deps: finalhandler@0.1.0 + - deps: method-override@~2.1.2 + - deps: morgan@~1.2.0 + - deps: multiparty@3.3.1 + - deps: parseurl@~1.2.0 + - deps: serve-static@~1.4.0 + * deps: debug@1.0.4 + * deps: depd@0.4.2 + - Add `TRACE_DEPRECATION` environment variable + - Remove non-standard grey color from color output + - Support `--no-deprecation` argument + - Support `--trace-deprecation` argument + * deps: parseurl@~1.2.0 + - Cache URLs based on original value + - Remove no-longer-needed URL mis-parse work-around + - Simplify the "fast-path" `RegExp` + * deps: send@0.7.0 + - Add `dotfiles` option + - Cap `maxAge` value to 1 year + - deps: debug@1.0.4 + - deps: depd@0.4.2 + +3.14.0 / 2014-07-11 +=================== + + * add explicit "Rosetta Flash JSONP abuse" protection + - previous versions are not vulnerable; this is just explicit protection + * deprecate `res.redirect(url, status)` -- use `res.redirect(status, url)` instead + * fix `res.send(status, num)` to send `num` as json (not error) + * remove unnecessary escaping when `res.jsonp` returns JSON response + * deps: basic-auth@1.0.0 + - support empty password + - support empty username + * deps: connect@2.23.0 + - deps: debug@1.0.3 + - deps: express-session@~1.6.4 + - deps: method-override@~2.1.0 + - deps: parseurl@~1.1.3 + - deps: serve-static@~1.3.1 + * deps: debug@1.0.3 + - Add support for multiple wildcards in namespaces + * deps: methods@1.1.0 + - add `CONNECT` + * deps: parseurl@~1.1.3 + - faster parsing of href-only URLs + +3.13.0 / 2014-07-03 +=================== + + * add deprecation message to `app.configure` + * add deprecation message to `req.auth` + * use `basic-auth` to parse `Authorization` header + * deps: connect@2.22.0 + - deps: csurf@~1.3.0 + - deps: express-session@~1.6.1 + - deps: multiparty@3.3.0 + - deps: serve-static@~1.3.0 + * deps: send@0.5.0 + - Accept string for `maxage` (converted by `ms`) + - Include link in default redirect response + +3.12.1 / 2014-06-26 +=================== + + * deps: connect@2.21.1 + - deps: cookie-parser@1.3.2 + - deps: cookie-signature@1.0.4 + - deps: express-session@~1.5.2 + - deps: type-is@~1.3.2 + * deps: cookie-signature@1.0.4 + - fix for timing attacks + +3.12.0 / 2014-06-21 +=================== + + * use `media-typer` to alter content-type charset + * deps: connect@2.21.0 + - deprecate `connect(middleware)` -- use `app.use(middleware)` instead + - deprecate `connect.createServer()` -- use `connect()` instead + - fix `res.setHeader()` patch to work with with get -> append -> set pattern + - deps: compression@~1.0.8 + - deps: errorhandler@~1.1.1 + - deps: express-session@~1.5.0 + - deps: serve-index@~1.1.3 + +3.11.0 / 2014-06-19 +=================== + + * deprecate things with `depd` module + * deps: buffer-crc32@0.2.3 + * deps: connect@2.20.2 + - deprecate `verify` option to `json` -- use `body-parser` npm module instead + - deprecate `verify` option to `urlencoded` -- use `body-parser` npm module instead + - deprecate things with `depd` module + - use `finalhandler` for final response handling + - use `media-typer` to parse `content-type` for charset + - deps: body-parser@1.4.3 + - deps: connect-timeout@1.1.1 + - deps: cookie-parser@1.3.1 + - deps: csurf@1.2.2 + - deps: errorhandler@1.1.0 + - deps: express-session@1.4.0 + - deps: multiparty@3.2.9 + - deps: serve-index@1.1.2 + - deps: type-is@1.3.1 + - deps: vhost@2.0.0 + +3.10.5 / 2014-06-11 +=================== + + * deps: connect@2.19.6 + - deps: body-parser@1.3.1 + - deps: compression@1.0.7 + - deps: debug@1.0.2 + - deps: serve-index@1.1.1 + - deps: serve-static@1.2.3 + * deps: debug@1.0.2 + * deps: send@0.4.3 + - Do not throw un-catchable error on file open race condition + - Use `escape-html` for HTML escaping + - deps: debug@1.0.2 + - deps: finished@1.2.2 + - deps: fresh@0.2.2 + +3.10.4 / 2014-06-09 +=================== + + * deps: connect@2.19.5 + - fix "event emitter leak" warnings + - deps: csurf@1.2.1 + - deps: debug@1.0.1 + - deps: serve-static@1.2.2 + - deps: type-is@1.2.1 + * deps: debug@1.0.1 + * deps: send@0.4.2 + - fix "event emitter leak" warnings + - deps: finished@1.2.1 + - deps: debug@1.0.1 + +3.10.3 / 2014-06-05 +=================== + + * use `vary` module for `res.vary` + * deps: connect@2.19.4 + - deps: errorhandler@1.0.2 + - deps: method-override@2.0.2 + - deps: serve-favicon@2.0.1 + * deps: debug@1.0.0 + +3.10.2 / 2014-06-03 +=================== + + * deps: connect@2.19.3 + - deps: compression@1.0.6 + +3.10.1 / 2014-06-03 +=================== + + * deps: connect@2.19.2 + - deps: compression@1.0.4 + * deps: proxy-addr@1.0.1 + +3.10.0 / 2014-06-02 +=================== + + * deps: connect@2.19.1 + - deprecate `methodOverride()` -- use `method-override` npm module instead + - deps: body-parser@1.3.0 + - deps: method-override@2.0.1 + - deps: multiparty@3.2.8 + - deps: response-time@2.0.0 + - deps: serve-static@1.2.1 + * deps: methods@1.0.1 + * deps: send@0.4.1 + - Send `max-age` in `Cache-Control` in correct format + +3.9.0 / 2014-05-30 +================== + + * custom etag control with `app.set('etag', val)` + - `app.set('etag', function(body, encoding){ return '"etag"' })` custom etag generation + - `app.set('etag', 'weak')` weak tag + - `app.set('etag', 'strong')` strong etag + - `app.set('etag', false)` turn off + - `app.set('etag', true)` standard etag + * Include ETag in HEAD requests + * mark `res.send` ETag as weak and reduce collisions + * update connect to 2.18.0 + - deps: compression@1.0.3 + - deps: serve-index@1.1.0 + - deps: serve-static@1.2.0 + * update send to 0.4.0 + - Calculate ETag with md5 for reduced collisions + - Ignore stream errors after request ends + - deps: debug@0.8.1 + +3.8.1 / 2014-05-27 +================== + + * update connect to 2.17.3 + - deps: body-parser@1.2.2 + - deps: express-session@1.2.1 + - deps: method-override@1.0.2 + +3.8.0 / 2014-05-21 +================== + + * keep previous `Content-Type` for `res.jsonp` + * set proper `charset` in `Content-Type` for `res.send` + * update connect to 2.17.1 + - fix `res.charset` appending charset when `content-type` has one + - deps: express-session@1.2.0 + - deps: morgan@1.1.1 + - deps: serve-index@1.0.3 + +3.7.0 / 2014-05-18 +================== + + * proper proxy trust with `app.set('trust proxy', trust)` + - `app.set('trust proxy', 1)` trust first hop + - `app.set('trust proxy', 'loopback')` trust loopback addresses + - `app.set('trust proxy', '10.0.0.1')` trust single IP + - `app.set('trust proxy', '10.0.0.1/16')` trust subnet + - `app.set('trust proxy', '10.0.0.1, 10.0.0.2')` trust list + - `app.set('trust proxy', false)` turn off + - `app.set('trust proxy', true)` trust everything + * update connect to 2.16.2 + - deprecate `res.headerSent` -- use `res.headersSent` + - deprecate `res.on("header")` -- use on-headers module instead + - fix edge-case in `res.appendHeader` that would append in wrong order + - json: use body-parser + - urlencoded: use body-parser + - dep: bytes@1.0.0 + - dep: cookie-parser@1.1.0 + - dep: csurf@1.2.0 + - dep: express-session@1.1.0 + - dep: method-override@1.0.1 + +3.6.0 / 2014-05-09 +================== + + * deprecate `app.del()` -- use `app.delete()` instead + * deprecate `res.json(obj, status)` -- use `res.json(status, obj)` instead + - the edge-case `res.json(status, num)` requires `res.status(status).json(num)` + * deprecate `res.jsonp(obj, status)` -- use `res.jsonp(status, obj)` instead + - the edge-case `res.jsonp(status, num)` requires `res.status(status).jsonp(num)` + * support PURGE method + - add `app.purge` + - add `router.purge` + - include PURGE in `app.all` + * update connect to 2.15.0 + * Add `res.appendHeader` + * Call error stack even when response has been sent + * Patch `res.headerSent` to return Boolean + * Patch `res.headersSent` for node.js 0.8 + * Prevent default 404 handler after response sent + * dep: compression@1.0.2 + * dep: connect-timeout@1.1.0 + * dep: debug@^0.8.0 + * dep: errorhandler@1.0.1 + * dep: express-session@1.0.4 + * dep: morgan@1.0.1 + * dep: serve-favicon@2.0.0 + * dep: serve-index@1.0.2 + * update debug to 0.8.0 + * add `enable()` method + * change from stderr to stdout + * update methods to 1.0.0 + - add PURGE + * update mkdirp to 0.5.0 + +3.5.3 / 2014-05-08 +================== + + * fix `req.host` for IPv6 literals + * fix `res.jsonp` error if callback param is object + +3.5.2 / 2014-04-24 +================== + + * update connect to 2.14.5 + * update cookie to 0.1.2 + * update mkdirp to 0.4.0 + * update send to 0.3.0 + +3.5.1 / 2014-03-25 +================== + + * pin less-middleware in generated app + +3.5.0 / 2014-03-06 +================== + + * bump deps + +3.4.8 / 2014-01-13 +================== + + * prevent incorrect automatic OPTIONS responses #1868 @dpatti + * update binary and examples for jade 1.0 #1876 @yossi, #1877 @reqshark, #1892 @matheusazzi + * throw 400 in case of malformed paths @rlidwka + +3.4.7 / 2013-12-10 +================== + + * update connect + +3.4.6 / 2013-12-01 +================== + + * update connect (raw-body) + +3.4.5 / 2013-11-27 +================== + + * update connect + * res.location: remove leading ./ #1802 @kapouer + * res.redirect: fix `res.redirect('toString') #1829 @michaelficarra + * res.send: always send ETag when content-length > 0 + * router: add Router.all() method + +3.4.4 / 2013-10-29 +================== + + * update connect + * update supertest + * update methods + * express(1): replace bodyParser() with urlencoded() and json() #1795 @chirag04 + +3.4.3 / 2013-10-23 +================== + + * update connect + +3.4.2 / 2013-10-18 +================== + + * update connect + * downgrade commander + +3.4.1 / 2013-10-15 +================== + + * update connect + * update commander + * jsonp: check if callback is a function + * router: wrap encodeURIComponent in a try/catch #1735 (@lxe) + * res.format: now includes charset @1747 (@sorribas) + * res.links: allow multiple calls @1746 (@sorribas) + +3.4.0 / 2013-09-07 +================== + + * add res.vary(). Closes #1682 + * update connect + +3.3.8 / 2013-09-02 +================== + + * update connect + +3.3.7 / 2013-08-28 +================== + + * update connect + +3.3.6 / 2013-08-27 +================== + + * Revert "remove charset from json responses. Closes #1631" (causes issues in some clients) + * add: req.accepts take an argument list + +3.3.4 / 2013-07-08 +================== + + * update send and connect + +3.3.3 / 2013-07-04 +================== + + * update connect + +3.3.2 / 2013-07-03 +================== + + * update connect + * update send + * remove .version export + +3.3.1 / 2013-06-27 +================== + + * update connect + +3.3.0 / 2013-06-26 +================== + + * update connect + * add support for multiple X-Forwarded-Proto values. Closes #1646 + * change: remove charset from json responses. Closes #1631 + * change: return actual booleans from req.accept* functions + * fix jsonp callback array throw + +3.2.6 / 2013-06-02 +================== + + * update connect + +3.2.5 / 2013-05-21 +================== + + * update connect + * update node-cookie + * add: throw a meaningful error when there is no default engine + * change generation of ETags with res.send() to GET requests only. Closes #1619 + +3.2.4 / 2013-05-09 +================== + + * fix `req.subdomains` when no Host is present + * fix `req.host` when no Host is present, return undefined + +3.2.3 / 2013-05-07 +================== + + * update connect / qs + +3.2.2 / 2013-05-03 +================== + + * update qs + +3.2.1 / 2013-04-29 +================== + + * add app.VERB() paths array deprecation warning + * update connect + * update qs and remove all ~ semver crap + * fix: accept number as value of Signed Cookie + +3.2.0 / 2013-04-15 +================== + + * add "view" constructor setting to override view behaviour + * add req.acceptsEncoding(name) + * add req.acceptedEncodings + * revert cookie signature change causing session race conditions + * fix sorting of Accept values of the same quality + +3.1.2 / 2013-04-12 +================== + + * add support for custom Accept parameters + * update cookie-signature + +3.1.1 / 2013-04-01 +================== + + * add X-Forwarded-Host support to `req.host` + * fix relative redirects + * update mkdirp + * update buffer-crc32 + * remove legacy app.configure() method from app template. + +3.1.0 / 2013-01-25 +================== + + * add support for leading "." in "view engine" setting + * add array support to `res.set()` + * add node 0.8.x to travis.yml + * add "subdomain offset" setting for tweaking `req.subdomains` + * add `res.location(url)` implementing `res.redirect()`-like setting of Location + * use app.get() for x-powered-by setting for inheritance + * fix colons in passwords for `req.auth` + +3.0.6 / 2013-01-04 +================== + + * add http verb methods to Router + * update connect + * fix mangling of the `res.cookie()` options object + * fix jsonp whitespace escape. Closes #1132 + +3.0.5 / 2012-12-19 +================== + + * add throwing when a non-function is passed to a route + * fix: explicitly remove Transfer-Encoding header from 204 and 304 responses + * revert "add 'etag' option" + +3.0.4 / 2012-12-05 +================== + + * add 'etag' option to disable `res.send()` Etags + * add escaping of urls in text/plain in `res.redirect()` + for old browsers interpreting as html + * change crc32 module for a more liberal license + * update connect + +3.0.3 / 2012-11-13 +================== + + * update connect + * update cookie module + * fix cookie max-age + +3.0.2 / 2012-11-08 +================== + + * add OPTIONS to cors example. Closes #1398 + * fix route chaining regression. Closes #1397 + +3.0.1 / 2012-11-01 +================== + + * update connect + +3.0.0 / 2012-10-23 +================== + + * add `make clean` + * add "Basic" check to req.auth + * add `req.auth` test coverage + * add cb && cb(payload) to `res.jsonp()`. Closes #1374 + * add backwards compat for `res.redirect()` status. Closes #1336 + * add support for `res.json()` to retain previously defined Content-Types. Closes #1349 + * update connect + * change `res.redirect()` to utilize a pathname-relative Location again. Closes #1382 + * remove non-primitive string support for `res.send()` + * fix view-locals example. Closes #1370 + * fix route-separation example + +3.0.0rc5 / 2012-09-18 +================== + + * update connect + * add redis search example + * add static-files example + * add "x-powered-by" setting (`app.disable('x-powered-by')`) + * add "application/octet-stream" redirect Accept test case. Closes #1317 + +3.0.0rc4 / 2012-08-30 +================== + + * add `res.jsonp()`. Closes #1307 + * add "verbose errors" option to error-pages example + * add another route example to express(1) so people are not so confused + * add redis online user activity tracking example + * update connect dep + * fix etag quoting. Closes #1310 + * fix error-pages 404 status + * fix jsonp callback char restrictions + * remove old OPTIONS default response + +3.0.0rc3 / 2012-08-13 +================== + + * update connect dep + * fix signed cookies to work with `connect.cookieParser()` ("s:" prefix was missing) [tnydwrds] + * fix `res.render()` clobbering of "locals" + +3.0.0rc2 / 2012-08-03 +================== + + * add CORS example + * update connect dep + * deprecate `.createServer()` & remove old stale examples + * fix: escape `res.redirect()` link + * fix vhost example + +3.0.0rc1 / 2012-07-24 +================== + + * add more examples to view-locals + * add scheme-relative redirects (`res.redirect("//foo.com")`) support + * update cookie dep + * update connect dep + * update send dep + * fix `express(1)` -h flag, use -H for hogan. Closes #1245 + * fix `res.sendfile()` socket error handling regression + +3.0.0beta7 / 2012-07-16 +================== + + * update connect dep for `send()` root normalization regression + +3.0.0beta6 / 2012-07-13 +================== + + * add `err.view` property for view errors. Closes #1226 + * add "jsonp callback name" setting + * add support for "/foo/:bar*" non-greedy matches + * change `res.sendfile()` to use `send()` module + * change `res.send` to use "response-send" module + * remove `app.locals.use` and `res.locals.use`, use regular middleware + +3.0.0beta5 / 2012-07-03 +================== + + * add "make check" support + * add route-map example + * add `res.json(obj, status)` support back for BC + * add "methods" dep, remove internal methods module + * update connect dep + * update auth example to utilize cores pbkdf2 + * updated tests to use "supertest" + +3.0.0beta4 / 2012-06-25 +================== + + * Added `req.auth` + * Added `req.range(size)` + * Added `res.links(obj)` + * Added `res.send(body, status)` support back for backwards compat + * Added `.default()` support to `res.format()` + * Added 2xx / 304 check to `req.fresh` + * Revert "Added + support to the router" + * Fixed `res.send()` freshness check, respect res.statusCode + +3.0.0beta3 / 2012-06-15 +================== + + * Added hogan `--hjs` to express(1) [nullfirm] + * Added another example to content-negotiation + * Added `fresh` dep + * Changed: `res.send()` always checks freshness + * Fixed: expose connects mime module. Closes #1165 + +3.0.0beta2 / 2012-06-06 +================== + + * Added `+` support to the router + * Added `req.host` + * Changed `req.param()` to check route first + * Update connect dep + +3.0.0beta1 / 2012-06-01 +================== + + * Added `res.format()` callback to override default 406 behaviour + * Fixed `res.redirect()` 406. Closes #1154 + +3.0.0alpha5 / 2012-05-30 +================== + + * Added `req.ip` + * Added `{ signed: true }` option to `res.cookie()` + * Removed `res.signedCookie()` + * Changed: dont reverse `req.ips` + * Fixed "trust proxy" setting check for `req.ips` + +3.0.0alpha4 / 2012-05-09 +================== + + * Added: allow `[]` in jsonp callback. Closes #1128 + * Added `PORT` env var support in generated template. Closes #1118 [benatkin] + * Updated: connect 2.2.2 + +3.0.0alpha3 / 2012-05-04 +================== + + * Added public `app.routes`. Closes #887 + * Added _view-locals_ example + * Added _mvc_ example + * Added `res.locals.use()`. Closes #1120 + * Added conditional-GET support to `res.send()` + * Added: coerce `res.set()` values to strings + * Changed: moved `static()` in generated apps below router + * Changed: `res.send()` only set ETag when not previously set + * Changed connect 2.2.1 dep + * Changed: `make test` now runs unit / acceptance tests + * Fixed req/res proto inheritance + +3.0.0alpha2 / 2012-04-26 +================== + + * Added `make benchmark` back + * Added `res.send()` support for `String` objects + * Added client-side data exposing example + * Added `res.header()` and `req.header()` aliases for BC + * Added `express.createServer()` for BC + * Perf: memoize parsed urls + * Perf: connect 2.2.0 dep + * Changed: make `expressInit()` middleware self-aware + * Fixed: use app.get() for all core settings + * Fixed redis session example + * Fixed session example. Closes #1105 + * Fixed generated express dep. Closes #1078 + +3.0.0alpha1 / 2012-04-15 +================== + + * Added `app.locals.use(callback)` + * Added `app.locals` object + * Added `app.locals(obj)` + * Added `res.locals` object + * Added `res.locals(obj)` + * Added `res.format()` for content-negotiation + * Added `app.engine()` + * Added `res.cookie()` JSON cookie support + * Added "trust proxy" setting + * Added `req.subdomains` + * Added `req.protocol` + * Added `req.secure` + * Added `req.path` + * Added `req.ips` + * Added `req.fresh` + * Added `req.stale` + * Added comma-delimited / array support for `req.accepts()` + * Added debug instrumentation + * Added `res.set(obj)` + * Added `res.set(field, value)` + * Added `res.get(field)` + * Added `app.get(setting)`. Closes #842 + * Added `req.acceptsLanguage()` + * Added `req.acceptsCharset()` + * Added `req.accepted` + * Added `req.acceptedLanguages` + * Added `req.acceptedCharsets` + * Added "json replacer" setting + * Added "json spaces" setting + * Added X-Forwarded-Proto support to `res.redirect()`. Closes #92 + * Added `--less` support to express(1) + * Added `express.response` prototype + * Added `express.request` prototype + * Added `express.application` prototype + * Added `app.path()` + * Added `app.render()` + * Added `res.type()` to replace `res.contentType()` + * Changed: `res.redirect()` to add relative support + * Changed: enable "jsonp callback" by default + * Changed: renamed "case sensitive routes" to "case sensitive routing" + * Rewrite of all tests with mocha + * Removed "root" setting + * Removed `res.redirect('home')` support + * Removed `req.notify()` + * Removed `app.register()` + * Removed `app.redirect()` + * Removed `app.is()` + * Removed `app.helpers()` + * Removed `app.dynamicHelpers()` + * Fixed `res.sendfile()` with non-GET. Closes #723 + * Fixed express(1) public dir for windows. Closes #866 + +2.5.9/ 2012-04-02 +================== + + * Added support for PURGE request method [pbuyle] + * Fixed `express(1)` generated app `app.address()` before `listening` [mmalecki] + +2.5.8 / 2012-02-08 +================== + + * Update mkdirp dep. Closes #991 + +2.5.7 / 2012-02-06 +================== + + * Fixed `app.all` duplicate DELETE requests [mscdex] + +2.5.6 / 2012-01-13 +================== + + * Updated hamljs dev dep. Closes #953 + +2.5.5 / 2012-01-08 +================== + + * Fixed: set `filename` on cached templates [matthewleon] + +2.5.4 / 2012-01-02 +================== + + * Fixed `express(1)` eol on 0.4.x. Closes #947 + +2.5.3 / 2011-12-30 +================== + + * Fixed `req.is()` when a charset is present + +2.5.2 / 2011-12-10 +================== + + * Fixed: express(1) LF -> CRLF for windows + +2.5.1 / 2011-11-17 +================== + + * Changed: updated connect to 1.8.x + * Removed sass.js support from express(1) + +2.5.0 / 2011-10-24 +================== + + * Added ./routes dir for generated app by default + * Added npm install reminder to express(1) app gen + * Added 0.5.x support + * Removed `make test-cov` since it wont work with node 0.5.x + * Fixed express(1) public dir for windows. Closes #866 + +2.4.7 / 2011-10-05 +================== + + * Added mkdirp to express(1). Closes #795 + * Added simple _json-config_ example + * Added shorthand for the parsed request's pathname via `req.path` + * Changed connect dep to 1.7.x to fix npm issue... + * Fixed `res.redirect()` __HEAD__ support. [reported by xerox] + * Fixed `req.flash()`, only escape args + * Fixed absolute path checking on windows. Closes #829 [reported by andrewpmckenzie] + +2.4.6 / 2011-08-22 +================== + + * Fixed multiple param callback regression. Closes #824 [reported by TroyGoode] + +2.4.5 / 2011-08-19 +================== + + * Added support for routes to handle errors. Closes #809 + * Added `app.routes.all()`. Closes #803 + * Added "basepath" setting to work in conjunction with reverse proxies etc. + * Refactored `Route` to use a single array of callbacks + * Added support for multiple callbacks for `app.param()`. Closes #801 +Closes #805 + * Changed: removed .call(self) for route callbacks + * Dependency: `qs >= 0.3.1` + * Fixed `res.redirect()` on windows due to `join()` usage. Closes #808 + +2.4.4 / 2011-08-05 +================== + + * Fixed `res.header()` intention of a set, even when `undefined` + * Fixed `*`, value no longer required + * Fixed `res.send(204)` support. Closes #771 + +2.4.3 / 2011-07-14 +================== + + * Added docs for `status` option special-case. Closes #739 + * Fixed `options.filename`, exposing the view path to template engines + +2.4.2. / 2011-07-06 +================== + + * Revert "removed jsonp stripping" for XSS + +2.4.1 / 2011-07-06 +================== + + * Added `res.json()` JSONP support. Closes #737 + * Added _extending-templates_ example. Closes #730 + * Added "strict routing" setting for trailing slashes + * Added support for multiple envs in `app.configure()` calls. Closes #735 + * Changed: `res.send()` using `res.json()` + * Changed: when cookie `path === null` don't default it + * Changed; default cookie path to "home" setting. Closes #731 + * Removed _pids/logs_ creation from express(1) + +2.4.0 / 2011-06-28 +================== + + * Added chainable `res.status(code)` + * Added `res.json()`, an explicit version of `res.send(obj)` + * Added simple web-service example + +2.3.12 / 2011-06-22 +================== + + * \#express is now on freenode! come join! + * Added `req.get(field, param)` + * Added links to Japanese documentation, thanks @hideyukisaito! + * Added; the `express(1)` generated app outputs the env + * Added `content-negotiation` example + * Dependency: connect >= 1.5.1 < 2.0.0 + * Fixed view layout bug. Closes #720 + * Fixed; ignore body on 304. Closes #701 + +2.3.11 / 2011-06-04 +================== + + * Added `npm test` + * Removed generation of dummy test file from `express(1)` + * Fixed; `express(1)` adds express as a dep + * Fixed; prune on `prepublish` + +2.3.10 / 2011-05-27 +================== + + * Added `req.route`, exposing the current route + * Added _package.json_ generation support to `express(1)` + * Fixed call to `app.param()` function for optional params. Closes #682 + +2.3.9 / 2011-05-25 +================== + + * Fixed bug-ish with `../' in `res.partial()` calls + +2.3.8 / 2011-05-24 +================== + + * Fixed `app.options()` + +2.3.7 / 2011-05-23 +================== + + * Added route `Collection`, ex: `app.get('/user/:id').remove();` + * Added support for `app.param(fn)` to define param logic + * Removed `app.param()` support for callback with return value + * Removed module.parent check from express(1) generated app. Closes #670 + * Refactored router. Closes #639 + +2.3.6 / 2011-05-20 +================== + + * Changed; using devDependencies instead of git submodules + * Fixed redis session example + * Fixed markdown example + * Fixed view caching, should not be enabled in development + +2.3.5 / 2011-05-20 +================== + + * Added export `.view` as alias for `.View` + +2.3.4 / 2011-05-08 +================== + + * Added `./examples/say` + * Fixed `res.sendfile()` bug preventing the transfer of files with spaces + +2.3.3 / 2011-05-03 +================== + + * Added "case sensitive routes" option. + * Changed; split methods supported per rfc [slaskis] + * Fixed route-specific middleware when using the same callback function several times + +2.3.2 / 2011-04-27 +================== + + * Fixed view hints + +2.3.1 / 2011-04-26 +================== + + * Added `app.match()` as `app.match.all()` + * Added `app.lookup()` as `app.lookup.all()` + * Added `app.remove()` for `app.remove.all()` + * Added `app.remove.VERB()` + * Fixed template caching collision issue. Closes #644 + * Moved router over from connect and started refactor + +2.3.0 / 2011-04-25 +================== + + * Added options support to `res.clearCookie()` + * Added `res.helpers()` as alias of `res.locals()` + * Added; json defaults to UTF-8 with `res.send()`. Closes #632. [Daniel * Dependency `connect >= 1.4.0` + * Changed; auto set Content-Type in res.attachement [Aaron Heckmann] + * Renamed "cache views" to "view cache". Closes #628 + * Fixed caching of views when using several apps. Closes #637 + * Fixed gotcha invoking `app.param()` callbacks once per route middleware. +Closes #638 + * Fixed partial lookup precedence. Closes #631 +Shaw] + +2.2.2 / 2011-04-12 +================== + + * Added second callback support for `res.download()` connection errors + * Fixed `filename` option passing to template engine + +2.2.1 / 2011-04-04 +================== + + * Added `layout(path)` helper to change the layout within a view. Closes #610 + * Fixed `partial()` collection object support. + Previously only anything with `.length` would work. + When `.length` is present one must still be aware of holes, + however now `{ collection: {foo: 'bar'}}` is valid, exposes + `keyInCollection` and `keysInCollection`. + + * Performance improved with better view caching + * Removed `request` and `response` locals + * Changed; errorHandler page title is now `Express` instead of `Connect` + +2.2.0 / 2011-03-30 +================== + + * Added `app.lookup.VERB()`, ex `app.lookup.put('/user/:id')`. Closes #606 + * Added `app.match.VERB()`, ex `app.match.put('/user/12')`. Closes #606 + * Added `app.VERB(path)` as alias of `app.lookup.VERB()`. + * Dependency `connect >= 1.2.0` + +2.1.1 / 2011-03-29 +================== + + * Added; expose `err.view` object when failing to locate a view + * Fixed `res.partial()` call `next(err)` when no callback is given [reported by aheckmann] + * Fixed; `res.send(undefined)` responds with 204 [aheckmann] + +2.1.0 / 2011-03-24 +================== + + * Added `<root>/_?<name>` partial lookup support. Closes #447 + * Added `request`, `response`, and `app` local variables + * Added `settings` local variable, containing the app's settings + * Added `req.flash()` exception if `req.session` is not available + * Added `res.send(bool)` support (json response) + * Fixed stylus example for latest version + * Fixed; wrap try/catch around `res.render()` + +2.0.0 / 2011-03-17 +================== + + * Fixed up index view path alternative. + * Changed; `res.locals()` without object returns the locals + +2.0.0rc3 / 2011-03-17 +================== + + * Added `res.locals(obj)` to compliment `res.local(key, val)` + * Added `res.partial()` callback support + * Fixed recursive error reporting issue in `res.render()` + +2.0.0rc2 / 2011-03-17 +================== + + * Changed; `partial()` "locals" are now optional + * Fixed `SlowBuffer` support. Closes #584 [reported by tyrda01] + * Fixed .filename view engine option [reported by drudge] + * Fixed blog example + * Fixed `{req,res}.app` reference when mounting [Ben Weaver] + +2.0.0rc / 2011-03-14 +================== + + * Fixed; expose `HTTPSServer` constructor + * Fixed express(1) default test charset. Closes #579 [reported by secoif] + * Fixed; default charset to utf-8 instead of utf8 for lame IE [reported by NickP] + +2.0.0beta3 / 2011-03-09 +================== + + * Added support for `res.contentType()` literal + The original `res.contentType('.json')`, + `res.contentType('application/json')`, and `res.contentType('json')` + will work now. + * Added `res.render()` status option support back + * Added charset option for `res.render()` + * Added `.charset` support (via connect 1.0.4) + * Added view resolution hints when in development and a lookup fails + * Added layout lookup support relative to the page view. + For example while rendering `./views/user/index.jade` if you create + `./views/user/layout.jade` it will be used in favour of the root layout. + * Fixed `res.redirect()`. RFC states absolute url [reported by unlink] + * Fixed; default `res.send()` string charset to utf8 + * Removed `Partial` constructor (not currently used) + +2.0.0beta2 / 2011-03-07 +================== + + * Added res.render() `.locals` support back to aid in migration process + * Fixed flash example + +2.0.0beta / 2011-03-03 +================== + + * Added HTTPS support + * Added `res.cookie()` maxAge support + * Added `req.header()` _Referrer_ / _Referer_ special-case, either works + * Added mount support for `res.redirect()`, now respects the mount-point + * Added `union()` util, taking place of `merge(clone())` combo + * Added stylus support to express(1) generated app + * Added secret to session middleware used in examples and generated app + * Added `res.local(name, val)` for progressive view locals + * Added default param support to `req.param(name, default)` + * Added `app.disabled()` and `app.enabled()` + * Added `app.register()` support for omitting leading ".", either works + * Added `res.partial()`, using the same interface as `partial()` within a view. Closes #539 + * Added `app.param()` to map route params to async/sync logic + * Added; aliased `app.helpers()` as `app.locals()`. Closes #481 + * Added extname with no leading "." support to `res.contentType()` + * Added `cache views` setting, defaulting to enabled in "production" env + * Added index file partial resolution, eg: partial('user') may try _views/user/index.jade_. + * Added `req.accepts()` support for extensions + * Changed; `res.download()` and `res.sendfile()` now utilize Connect's + static file server `connect.static.send()`. + * Changed; replaced `connect.utils.mime()` with npm _mime_ module + * Changed; allow `req.query` to be pre-defined (via middleware or other parent + * Changed view partial resolution, now relative to parent view + * Changed view engine signature. no longer `engine.render(str, options, callback)`, now `engine.compile(str, options) -> Function`, the returned function accepts `fn(locals)`. + * Fixed `req.param()` bug returning Array.prototype methods. Closes #552 + * Fixed; using `Stream#pipe()` instead of `sys.pump()` in `res.sendfile()` + * Fixed; using _qs_ module instead of _querystring_ + * Fixed; strip unsafe chars from jsonp callbacks + * Removed "stream threshold" setting + +1.0.8 / 2011-03-01 +================== + + * Allow `req.query` to be pre-defined (via middleware or other parent app) + * "connect": ">= 0.5.0 < 1.0.0". Closes #547 + * Removed the long deprecated __EXPRESS_ENV__ support + +1.0.7 / 2011-02-07 +================== + + * Fixed `render()` setting inheritance. + Mounted apps would not inherit "view engine" + +1.0.6 / 2011-02-07 +================== + + * Fixed `view engine` setting bug when period is in dirname + +1.0.5 / 2011-02-05 +================== + + * Added secret to generated app `session()` call + +1.0.4 / 2011-02-05 +================== + + * Added `qs` dependency to _package.json_ + * Fixed namespaced `require()`s for latest connect support + +1.0.3 / 2011-01-13 +================== + + * Remove unsafe characters from JSONP callback names [Ryan Grove] + +1.0.2 / 2011-01-10 +================== + + * Removed nested require, using `connect.router` + +1.0.1 / 2010-12-29 +================== + + * Fixed for middleware stacked via `createServer()` + previously the `foo` middleware passed to `createServer(foo)` + would not have access to Express methods such as `res.send()` + or props like `req.query` etc. + +1.0.0 / 2010-11-16 +================== + + * Added; deduce partial object names from the last segment. + For example by default `partial('forum/post', postObject)` will + give you the _post_ object, providing a meaningful default. + * Added http status code string representation to `res.redirect()` body + * Added; `res.redirect()` supporting _text/plain_ and _text/html_ via __Accept__. + * Added `req.is()` to aid in content negotiation + * Added partial local inheritance [suggested by masylum]. Closes #102 + providing access to parent template locals. + * Added _-s, --session[s]_ flag to express(1) to add session related middleware + * Added _--template_ flag to express(1) to specify the + template engine to use. + * Added _--css_ flag to express(1) to specify the + stylesheet engine to use (or just plain css by default). + * Added `app.all()` support [thanks aheckmann] + * Added partial direct object support. + You may now `partial('user', user)` providing the "user" local, + vs previously `partial('user', { object: user })`. + * Added _route-separation_ example since many people question ways + to do this with CommonJS modules. Also view the _blog_ example for + an alternative. + * Performance; caching view path derived partial object names + * Fixed partial local inheritance precedence. [reported by Nick Poulden] Closes #454 + * Fixed jsonp support; _text/javascript_ as per mailinglist discussion + +1.0.0rc4 / 2010-10-14 +================== + + * Added _NODE_ENV_ support, _EXPRESS_ENV_ is deprecated and will be removed in 1.0.0 + * Added route-middleware support (very helpful, see the [docs](http://expressjs.com/guide.html#Route-Middleware)) + * Added _jsonp callback_ setting to enable/disable jsonp autowrapping [Dav Glass] + * Added callback query check on response.send to autowrap JSON objects for simple webservice implementations [Dav Glass] + * Added `partial()` support for array-like collections. Closes #434 + * Added support for swappable querystring parsers + * Added session usage docs. Closes #443 + * Added dynamic helper caching. Closes #439 [suggested by maritz] + * Added authentication example + * Added basic Range support to `res.sendfile()` (and `res.download()` etc) + * Changed; `express(1)` generated app using 2 spaces instead of 4 + * Default env to "development" again [aheckmann] + * Removed _context_ option is no more, use "scope" + * Fixed; exposing _./support_ libs to examples so they can run without installs + * Fixed mvc example + +1.0.0rc3 / 2010-09-20 +================== + + * Added confirmation for `express(1)` app generation. Closes #391 + * Added extending of flash formatters via `app.flashFormatters` + * Added flash formatter support. Closes #411 + * Added streaming support to `res.sendfile()` using `sys.pump()` when >= "stream threshold" + * Added _stream threshold_ setting for `res.sendfile()` + * Added `res.send()` __HEAD__ support + * Added `res.clearCookie()` + * Added `res.cookie()` + * Added `res.render()` headers option + * Added `res.redirect()` response bodies + * Added `res.render()` status option support. Closes #425 [thanks aheckmann] + * Fixed `res.sendfile()` responding with 403 on malicious path + * Fixed `res.download()` bug; when an error occurs remove _Content-Disposition_ + * Fixed; mounted apps settings now inherit from parent app [aheckmann] + * Fixed; stripping Content-Length / Content-Type when 204 + * Fixed `res.send()` 204. Closes #419 + * Fixed multiple _Set-Cookie_ headers via `res.header()`. Closes #402 + * Fixed bug messing with error handlers when `listenFD()` is called instead of `listen()`. [thanks guillermo] + + +1.0.0rc2 / 2010-08-17 +================== + + * Added `app.register()` for template engine mapping. Closes #390 + * Added `res.render()` callback support as second argument (no options) + * Added callback support to `res.download()` + * Added callback support for `res.sendfile()` + * Added support for middleware access via `express.middlewareName()` vs `connect.middlewareName()` + * Added "partials" setting to docs + * Added default expresso tests to `express(1)` generated app. Closes #384 + * Fixed `res.sendfile()` error handling, defer via `next()` + * Fixed `res.render()` callback when a layout is used [thanks guillermo] + * Fixed; `make install` creating ~/.node_libraries when not present + * Fixed issue preventing error handlers from being defined anywhere. Closes #387 + +1.0.0rc / 2010-07-28 +================== + + * Added mounted hook. Closes #369 + * Added connect dependency to _package.json_ + + * Removed "reload views" setting and support code + development env never caches, production always caches. + + * Removed _param_ in route callbacks, signature is now + simply (req, res, next), previously (req, res, params, next). + Use _req.params_ for path captures, _req.query_ for GET params. + + * Fixed "home" setting + * Fixed middleware/router precedence issue. Closes #366 + * Fixed; _configure()_ callbacks called immediately. Closes #368 + +1.0.0beta2 / 2010-07-23 +================== + + * Added more examples + * Added; exporting `Server` constructor + * Added `Server#helpers()` for view locals + * Added `Server#dynamicHelpers()` for dynamic view locals. Closes #349 + * Added support for absolute view paths + * Added; _home_ setting defaults to `Server#route` for mounted apps. Closes #363 + * Added Guillermo Rauch to the contributor list + * Added support for "as" for non-collection partials. Closes #341 + * Fixed _install.sh_, ensuring _~/.node_libraries_ exists. Closes #362 [thanks jf] + * Fixed `res.render()` exceptions, now passed to `next()` when no callback is given [thanks guillermo] + * Fixed instanceof `Array` checks, now `Array.isArray()` + * Fixed express(1) expansion of public dirs. Closes #348 + * Fixed middleware precedence. Closes #345 + * Fixed view watcher, now async [thanks aheckmann] + +1.0.0beta / 2010-07-15 +================== + + * Re-write + - much faster + - much lighter + - Check [ExpressJS.com](http://expressjs.com) for migration guide and updated docs + +0.14.0 / 2010-06-15 +================== + + * Utilize relative requires + * Added Static bufferSize option [aheckmann] + * Fixed caching of view and partial subdirectories [aheckmann] + * Fixed mime.type() comments now that ".ext" is not supported + * Updated haml submodule + * Updated class submodule + * Removed bin/express + +0.13.0 / 2010-06-01 +================== + + * Added node v0.1.97 compatibility + * Added support for deleting cookies via Request#cookie('key', null) + * Updated haml submodule + * Fixed not-found page, now using using charset utf-8 + * Fixed show-exceptions page, now using using charset utf-8 + * Fixed view support due to fs.readFile Buffers + * Changed; mime.type() no longer accepts ".type" due to node extname() changes + +0.12.0 / 2010-05-22 +================== + + * Added node v0.1.96 compatibility + * Added view `helpers` export which act as additional local variables + * Updated haml submodule + * Changed ETag; removed inode, modified time only + * Fixed LF to CRLF for setting multiple cookies + * Fixed cookie complation; values are now urlencoded + * Fixed cookies parsing; accepts quoted values and url escaped cookies + +0.11.0 / 2010-05-06 +================== + + * Added support for layouts using different engines + - this.render('page.html.haml', { layout: 'super-cool-layout.html.ejs' }) + - this.render('page.html.haml', { layout: 'foo' }) // assumes 'foo.html.haml' + - this.render('page.html.haml', { layout: false }) // no layout + * Updated ext submodule + * Updated haml submodule + * Fixed EJS partial support by passing along the context. Issue #307 + +0.10.1 / 2010-05-03 +================== + + * Fixed binary uploads. + +0.10.0 / 2010-04-30 +================== + + * Added charset support via Request#charset (automatically assigned to 'UTF-8' when respond()'s + encoding is set to 'utf8' or 'utf-8'. + * Added "encoding" option to Request#render(). Closes #299 + * Added "dump exceptions" setting, which is enabled by default. + * Added simple ejs template engine support + * Added error response support for text/plain, application/json. Closes #297 + * Added callback function param to Request#error() + * Added Request#sendHead() + * Added Request#stream() + * Added support for Request#respond(304, null) for empty response bodies + * Added ETag support to Request#sendfile() + * Added options to Request#sendfile(), passed to fs.createReadStream() + * Added filename arg to Request#download() + * Performance enhanced due to pre-reversing plugins so that plugins.reverse() is not called on each request + * Performance enhanced by preventing several calls to toLowerCase() in Router#match() + * Changed; Request#sendfile() now streams + * Changed; Renamed Request#halt() to Request#respond(). Closes #289 + * Changed; Using sys.inspect() instead of JSON.encode() for error output + * Changed; run() returns the http.Server instance. Closes #298 + * Changed; Defaulting Server#host to null (INADDR_ANY) + * Changed; Logger "common" format scale of 0.4f + * Removed Logger "request" format + * Fixed; Catching ENOENT in view caching, preventing error when "views/partials" is not found + * Fixed several issues with http client + * Fixed Logger Content-Length output + * Fixed bug preventing Opera from retaining the generated session id. Closes #292 + +0.9.0 / 2010-04-14 +================== + + * Added DSL level error() route support + * Added DSL level notFound() route support + * Added Request#error() + * Added Request#notFound() + * Added Request#render() callback function. Closes #258 + * Added "max upload size" setting + * Added "magic" variables to collection partials (\_\_index\_\_, \_\_length\_\_, \_\_isFirst\_\_, \_\_isLast\_\_). Closes #254 + * Added [haml.js](http://github.com/visionmedia/haml.js) submodule; removed haml-js + * Added callback function support to Request#halt() as 3rd/4th arg + * Added preprocessing of route param wildcards using param(). Closes #251 + * Added view partial support (with collections etc) + * Fixed bug preventing falsey params (such as ?page=0). Closes #286 + * Fixed setting of multiple cookies. Closes #199 + * Changed; view naming convention is now NAME.TYPE.ENGINE (for example page.html.haml) + * Changed; session cookie is now httpOnly + * Changed; Request is no longer global + * Changed; Event is no longer global + * Changed; "sys" module is no longer global + * Changed; moved Request#download to Static plugin where it belongs + * Changed; Request instance created before body parsing. Closes #262 + * Changed; Pre-caching views in memory when "cache view contents" is enabled. Closes #253 + * Changed; Pre-caching view partials in memory when "cache view partials" is enabled + * Updated support to node --version 0.1.90 + * Updated dependencies + * Removed set("session cookie") in favour of use(Session, { cookie: { ... }}) + * Removed utils.mixin(); use Object#mergeDeep() + +0.8.0 / 2010-03-19 +================== + + * Added coffeescript example app. Closes #242 + * Changed; cache api now async friendly. Closes #240 + * Removed deprecated 'express/static' support. Use 'express/plugins/static' + +0.7.6 / 2010-03-19 +================== + + * Added Request#isXHR. Closes #229 + * Added `make install` (for the executable) + * Added `express` executable for setting up simple app templates + * Added "GET /public/*" to Static plugin, defaulting to <root>/public + * Added Static plugin + * Fixed; Request#render() only calls cache.get() once + * Fixed; Namespacing View caches with "view:" + * Fixed; Namespacing Static caches with "static:" + * Fixed; Both example apps now use the Static plugin + * Fixed set("views"). Closes #239 + * Fixed missing space for combined log format + * Deprecated Request#sendfile() and 'express/static' + * Removed Server#running + +0.7.5 / 2010-03-16 +================== + + * Added Request#flash() support without args, now returns all flashes + * Updated ext submodule + +0.7.4 / 2010-03-16 +================== + + * Fixed session reaper + * Changed; class.js replacing js-oo Class implementation (quite a bit faster, no browser cruft) + +0.7.3 / 2010-03-16 +================== + + * Added package.json + * Fixed requiring of haml / sass due to kiwi removal + +0.7.2 / 2010-03-16 +================== + + * Fixed GIT submodules (HAH!) + +0.7.1 / 2010-03-16 +================== + + * Changed; Express now using submodules again until a PM is adopted + * Changed; chat example using millisecond conversions from ext + +0.7.0 / 2010-03-15 +================== + + * Added Request#pass() support (finds the next matching route, or the given path) + * Added Logger plugin (default "common" format replaces CommonLogger) + * Removed Profiler plugin + * Removed CommonLogger plugin + +0.6.0 / 2010-03-11 +================== + + * Added seed.yml for kiwi package management support + * Added HTTP client query string support when method is GET. Closes #205 + + * Added support for arbitrary view engines. + For example "foo.engine.html" will now require('engine'), + the exports from this module are cached after the first require(). + + * Added async plugin support + + * Removed usage of RESTful route funcs as http client + get() etc, use http.get() and friends + + * Removed custom exceptions + +0.5.0 / 2010-03-10 +================== + + * Added ext dependency (library of js extensions) + * Removed extname() / basename() utils. Use path module + * Removed toArray() util. Use arguments.values + * Removed escapeRegexp() util. Use RegExp.escape() + * Removed process.mixin() dependency. Use utils.mixin() + * Removed Collection + * Removed ElementCollection + * Shameless self promotion of ebook "Advanced JavaScript" (http://dev-mag.com) ;) + +0.4.0 / 2010-02-11 +================== + + * Added flash() example to sample upload app + * Added high level restful http client module (express/http) + * Changed; RESTful route functions double as HTTP clients. Closes #69 + * Changed; throwing error when routes are added at runtime + * Changed; defaulting render() context to the current Request. Closes #197 + * Updated haml submodule + +0.3.0 / 2010-02-11 +================== + + * Updated haml / sass submodules. Closes #200 + * Added flash message support. Closes #64 + * Added accepts() now allows multiple args. fixes #117 + * Added support for plugins to halt. Closes #189 + * Added alternate layout support. Closes #119 + * Removed Route#run(). Closes #188 + * Fixed broken specs due to use(Cookie) missing + +0.2.1 / 2010-02-05 +================== + + * Added "plot" format option for Profiler (for gnuplot processing) + * Added request number to Profiler plugin + * Fixed binary encoding for multi-part file uploads, was previously defaulting to UTF8 + * Fixed issue with routes not firing when not files are present. Closes #184 + * Fixed process.Promise -> events.Promise + +0.2.0 / 2010-02-03 +================== + + * Added parseParam() support for name[] etc. (allows for file inputs with "multiple" attr) Closes #180 + * Added Both Cache and Session option "reapInterval" may be "reapEvery". Closes #174 + * Added expiration support to cache api with reaper. Closes #133 + * Added cache Store.Memory#reap() + * Added Cache; cache api now uses first class Cache instances + * Added abstract session Store. Closes #172 + * Changed; cache Memory.Store#get() utilizing Collection + * Renamed MemoryStore -> Store.Memory + * Fixed use() of the same plugin several time will always use latest options. Closes #176 + +0.1.0 / 2010-02-03 +================== + + * Changed; Hooks (before / after) pass request as arg as well as evaluated in their context + * Updated node support to 0.1.27 Closes #169 + * Updated dirname(__filename) -> __dirname + * Updated libxmljs support to v0.2.0 + * Added session support with memory store / reaping + * Added quick uid() helper + * Added multi-part upload support + * Added Sass.js support / submodule + * Added production env caching view contents and static files + * Added static file caching. Closes #136 + * Added cache plugin with memory stores + * Added support to StaticFile so that it works with non-textual files. + * Removed dirname() helper + * Removed several globals (now their modules must be required) + +0.0.2 / 2010-01-10 +================== + + * Added view benchmarks; currently haml vs ejs + * Added Request#attachment() specs. Closes #116 + * Added use of node's parseQuery() util. Closes #123 + * Added `make init` for submodules + * Updated Haml + * Updated sample chat app to show messages on load + * Updated libxmljs parseString -> parseHtmlString + * Fixed `make init` to work with older versions of git + * Fixed specs can now run independent specs for those who cant build deps. Closes #127 + * Fixed issues introduced by the node url module changes. Closes 126. + * Fixed two assertions failing due to Collection#keys() returning strings + * Fixed faulty Collection#toArray() spec due to keys() returning strings + * Fixed `make test` now builds libxmljs.node before testing + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/express/LICENSE b/node_modules/express/LICENSE new file mode 100644 index 0000000..aa927e4 --- /dev/null +++ b/node_modules/express/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2009-2014 TJ Holowaychuk <tj@vision-media.ca> +Copyright (c) 2013-2014 Roman Shtylman <shtylman+expressjs@gmail.com> +Copyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/express/Readme.md b/node_modules/express/Readme.md new file mode 100644 index 0000000..3cd2203 --- /dev/null +++ b/node_modules/express/Readme.md @@ -0,0 +1,153 @@ +[![Express Logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](http://expressjs.com/) + + Fast, unopinionated, minimalist web framework for [node](http://nodejs.org). + + [![NPM Version][npm-image]][npm-url] + [![NPM Downloads][downloads-image]][downloads-url] + [![Linux Build][travis-image]][travis-url] + [![Windows Build][appveyor-image]][appveyor-url] + [![Test Coverage][coveralls-image]][coveralls-url] + +```js +var express = require('express') +var app = express() + +app.get('/', function (req, res) { + res.send('Hello World') +}) + +app.listen(3000) +``` + +## Installation + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). + +Before installing, [download and install Node.js](https://nodejs.org/en/download/). +Node.js 0.10 or higher is required. + +Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```bash +$ npm install express +``` + +Follow [our installing guide](http://expressjs.com/en/starter/installing.html) +for more information. + +## Features + + * Robust routing + * Focus on high performance + * Super-high test coverage + * HTTP helpers (redirection, caching, etc) + * View system supporting 14+ template engines + * Content negotiation + * Executable for generating applications quickly + +## Docs & Community + + * [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/expressjs/expressjs.com)] + * [#express](https://webchat.freenode.net/?channels=express) on freenode IRC + * [GitHub Organization](https://github.com/expressjs) for Official Middleware & Modules + * Visit the [Wiki](https://github.com/expressjs/express/wiki) + * [Google Group](https://groups.google.com/group/express-js) for discussion + * [Gitter](https://gitter.im/expressjs/express) for support and discussion + +**PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/expressjs/express/wiki/New-features-in-4.x). + +### Security Issues + +If you discover a security vulnerability in Express, please see [Security Policies and Procedures](Security.md). + +## Quick Start + + The quickest way to get started with express is to utilize the executable [`express(1)`](https://github.com/expressjs/generator) to generate an application as shown below: + + Install the executable. The executable's major version will match Express's: + +```bash +$ npm install -g express-generator@4 +``` + + Create the app: + +```bash +$ express /tmp/foo && cd /tmp/foo +``` + + Install dependencies: + +```bash +$ npm install +``` + + Start the server: + +```bash +$ npm start +``` + +## Philosophy + + The Express philosophy is to provide small, robust tooling for HTTP servers, making + it a great solution for single page applications, web sites, hybrids, or public + HTTP APIs. + + Express does not force you to use any specific ORM or template engine. With support for over + 14 template engines via [Consolidate.js](https://github.com/tj/consolidate.js), + you can quickly craft your perfect framework. + +## Examples + + To view the examples, clone the Express repo and install the dependencies: + +```bash +$ git clone git://github.com/expressjs/express.git --depth 1 +$ cd express +$ npm install +``` + + Then run whichever example you want: + +```bash +$ node examples/content-negotiation +``` + +## Tests + + To run the test suite, first install the dependencies, then run `npm test`: + +```bash +$ npm install +$ npm test +``` + +## People + +The original author of Express is [TJ Holowaychuk](https://github.com/tj) [![TJ's Gratipay][gratipay-image-visionmedia]][gratipay-url-visionmedia] + +The current lead maintainer is [Douglas Christopher Wilson](https://github.com/dougwilson) [![Doug's Gratipay][gratipay-image-dougwilson]][gratipay-url-dougwilson] + +[List of all contributors](https://github.com/expressjs/express/graphs/contributors) + +## License + + [MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/express.svg +[npm-url]: https://npmjs.org/package/express +[downloads-image]: https://img.shields.io/npm/dm/express.svg +[downloads-url]: https://npmjs.org/package/express +[travis-image]: https://img.shields.io/travis/expressjs/express/master.svg?label=linux +[travis-url]: https://travis-ci.org/expressjs/express +[appveyor-image]: https://img.shields.io/appveyor/ci/dougwilson/express/master.svg?label=windows +[appveyor-url]: https://ci.appveyor.com/project/dougwilson/express +[coveralls-image]: https://img.shields.io/coveralls/expressjs/express/master.svg +[coveralls-url]: https://coveralls.io/r/expressjs/express?branch=master +[gratipay-image-visionmedia]: https://img.shields.io/gratipay/visionmedia.svg +[gratipay-url-visionmedia]: https://gratipay.com/visionmedia/ +[gratipay-image-dougwilson]: https://img.shields.io/gratipay/dougwilson.svg +[gratipay-url-dougwilson]: https://gratipay.com/dougwilson/ diff --git a/node_modules/express/index.js b/node_modules/express/index.js new file mode 100644 index 0000000..d219b0c --- /dev/null +++ b/node_modules/express/index.js @@ -0,0 +1,11 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +module.exports = require('./lib/express'); diff --git a/node_modules/express/lib/application.js b/node_modules/express/lib/application.js new file mode 100644 index 0000000..91f77d2 --- /dev/null +++ b/node_modules/express/lib/application.js @@ -0,0 +1,644 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var finalhandler = require('finalhandler'); +var Router = require('./router'); +var methods = require('methods'); +var middleware = require('./middleware/init'); +var query = require('./middleware/query'); +var debug = require('debug')('express:application'); +var View = require('./view'); +var http = require('http'); +var compileETag = require('./utils').compileETag; +var compileQueryParser = require('./utils').compileQueryParser; +var compileTrust = require('./utils').compileTrust; +var deprecate = require('depd')('express'); +var flatten = require('array-flatten'); +var merge = require('utils-merge'); +var resolve = require('path').resolve; +var setPrototypeOf = require('setprototypeof') +var slice = Array.prototype.slice; + +/** + * Application prototype. + */ + +var app = exports = module.exports = {}; + +/** + * Variable for trust proxy inheritance back-compat + * @private + */ + +var trustProxyDefaultSymbol = '@@symbol:trust_proxy_default'; + +/** + * Initialize the server. + * + * - setup default configuration + * - setup default middleware + * - setup route reflection methods + * + * @private + */ + +app.init = function init() { + this.cache = {}; + this.engines = {}; + this.settings = {}; + + this.defaultConfiguration(); +}; + +/** + * Initialize application configuration. + * @private + */ + +app.defaultConfiguration = function defaultConfiguration() { + var env = process.env.NODE_ENV || 'development'; + + // default settings + this.enable('x-powered-by'); + this.set('etag', 'weak'); + this.set('env', env); + this.set('query parser', 'extended'); + this.set('subdomain offset', 2); + this.set('trust proxy', false); + + // trust proxy inherit back-compat + Object.defineProperty(this.settings, trustProxyDefaultSymbol, { + configurable: true, + value: true + }); + + debug('booting in %s mode', env); + + this.on('mount', function onmount(parent) { + // inherit trust proxy + if (this.settings[trustProxyDefaultSymbol] === true + && typeof parent.settings['trust proxy fn'] === 'function') { + delete this.settings['trust proxy']; + delete this.settings['trust proxy fn']; + } + + // inherit protos + setPrototypeOf(this.request, parent.request) + setPrototypeOf(this.response, parent.response) + setPrototypeOf(this.engines, parent.engines) + setPrototypeOf(this.settings, parent.settings) + }); + + // setup locals + this.locals = Object.create(null); + + // top-most app is mounted at / + this.mountpath = '/'; + + // default locals + this.locals.settings = this.settings; + + // default configuration + this.set('view', View); + this.set('views', resolve('views')); + this.set('jsonp callback name', 'callback'); + + if (env === 'production') { + this.enable('view cache'); + } + + Object.defineProperty(this, 'router', { + get: function() { + throw new Error('\'app.router\' is deprecated!\nPlease see the 3.x to 4.x migration guide for details on how to update your app.'); + } + }); +}; + +/** + * lazily adds the base router if it has not yet been added. + * + * We cannot add the base router in the defaultConfiguration because + * it reads app settings which might be set after that has run. + * + * @private + */ +app.lazyrouter = function lazyrouter() { + if (!this._router) { + this._router = new Router({ + caseSensitive: this.enabled('case sensitive routing'), + strict: this.enabled('strict routing') + }); + + this._router.use(query(this.get('query parser fn'))); + this._router.use(middleware.init(this)); + } +}; + +/** + * Dispatch a req, res pair into the application. Starts pipeline processing. + * + * If no callback is provided, then default error handlers will respond + * in the event of an error bubbling through the stack. + * + * @private + */ + +app.handle = function handle(req, res, callback) { + var router = this._router; + + // final handler + var done = callback || finalhandler(req, res, { + env: this.get('env'), + onerror: logerror.bind(this) + }); + + // no routes + if (!router) { + debug('no routes defined on app'); + done(); + return; + } + + router.handle(req, res, done); +}; + +/** + * Proxy `Router#use()` to add middleware to the app router. + * See Router#use() documentation for details. + * + * If the _fn_ parameter is an express app, then it will be + * mounted at the _route_ specified. + * + * @public + */ + +app.use = function use(fn) { + var offset = 0; + var path = '/'; + + // default path to '/' + // disambiguate app.use([fn]) + if (typeof fn !== 'function') { + var arg = fn; + + while (Array.isArray(arg) && arg.length !== 0) { + arg = arg[0]; + } + + // first arg is the path + if (typeof arg !== 'function') { + offset = 1; + path = fn; + } + } + + var fns = flatten(slice.call(arguments, offset)); + + if (fns.length === 0) { + throw new TypeError('app.use() requires a middleware function') + } + + // setup router + this.lazyrouter(); + var router = this._router; + + fns.forEach(function (fn) { + // non-express app + if (!fn || !fn.handle || !fn.set) { + return router.use(path, fn); + } + + debug('.use app under %s', path); + fn.mountpath = path; + fn.parent = this; + + // restore .app property on req and res + router.use(path, function mounted_app(req, res, next) { + var orig = req.app; + fn.handle(req, res, function (err) { + setPrototypeOf(req, orig.request) + setPrototypeOf(res, orig.response) + next(err); + }); + }); + + // mounted an app + fn.emit('mount', this); + }, this); + + return this; +}; + +/** + * Proxy to the app `Router#route()` + * Returns a new `Route` instance for the _path_. + * + * Routes are isolated middleware stacks for specific paths. + * See the Route api docs for details. + * + * @public + */ + +app.route = function route(path) { + this.lazyrouter(); + return this._router.route(path); +}; + +/** + * Register the given template engine callback `fn` + * as `ext`. + * + * By default will `require()` the engine based on the + * file extension. For example if you try to render + * a "foo.ejs" file Express will invoke the following internally: + * + * app.engine('ejs', require('ejs').__express); + * + * For engines that do not provide `.__express` out of the box, + * or if you wish to "map" a different extension to the template engine + * you may use this method. For example mapping the EJS template engine to + * ".html" files: + * + * app.engine('html', require('ejs').renderFile); + * + * In this case EJS provides a `.renderFile()` method with + * the same signature that Express expects: `(path, options, callback)`, + * though note that it aliases this method as `ejs.__express` internally + * so if you're using ".ejs" extensions you dont need to do anything. + * + * Some template engines do not follow this convention, the + * [Consolidate.js](https://github.com/tj/consolidate.js) + * library was created to map all of node's popular template + * engines to follow this convention, thus allowing them to + * work seamlessly within Express. + * + * @param {String} ext + * @param {Function} fn + * @return {app} for chaining + * @public + */ + +app.engine = function engine(ext, fn) { + if (typeof fn !== 'function') { + throw new Error('callback function required'); + } + + // get file extension + var extension = ext[0] !== '.' + ? '.' + ext + : ext; + + // store engine + this.engines[extension] = fn; + + return this; +}; + +/** + * Proxy to `Router#param()` with one added api feature. The _name_ parameter + * can be an array of names. + * + * See the Router#param() docs for more details. + * + * @param {String|Array} name + * @param {Function} fn + * @return {app} for chaining + * @public + */ + +app.param = function param(name, fn) { + this.lazyrouter(); + + if (Array.isArray(name)) { + for (var i = 0; i < name.length; i++) { + this.param(name[i], fn); + } + + return this; + } + + this._router.param(name, fn); + + return this; +}; + +/** + * Assign `setting` to `val`, or return `setting`'s value. + * + * app.set('foo', 'bar'); + * app.set('foo'); + * // => "bar" + * + * Mounted servers inherit their parent server's settings. + * + * @param {String} setting + * @param {*} [val] + * @return {Server} for chaining + * @public + */ + +app.set = function set(setting, val) { + if (arguments.length === 1) { + // app.get(setting) + return this.settings[setting]; + } + + debug('set "%s" to %o', setting, val); + + // set value + this.settings[setting] = val; + + // trigger matched settings + switch (setting) { + case 'etag': + this.set('etag fn', compileETag(val)); + break; + case 'query parser': + this.set('query parser fn', compileQueryParser(val)); + break; + case 'trust proxy': + this.set('trust proxy fn', compileTrust(val)); + + // trust proxy inherit back-compat + Object.defineProperty(this.settings, trustProxyDefaultSymbol, { + configurable: true, + value: false + }); + + break; + } + + return this; +}; + +/** + * Return the app's absolute pathname + * based on the parent(s) that have + * mounted it. + * + * For example if the application was + * mounted as "/admin", which itself + * was mounted as "/blog" then the + * return value would be "/blog/admin". + * + * @return {String} + * @private + */ + +app.path = function path() { + return this.parent + ? this.parent.path() + this.mountpath + : ''; +}; + +/** + * Check if `setting` is enabled (truthy). + * + * app.enabled('foo') + * // => false + * + * app.enable('foo') + * app.enabled('foo') + * // => true + * + * @param {String} setting + * @return {Boolean} + * @public + */ + +app.enabled = function enabled(setting) { + return Boolean(this.set(setting)); +}; + +/** + * Check if `setting` is disabled. + * + * app.disabled('foo') + * // => true + * + * app.enable('foo') + * app.disabled('foo') + * // => false + * + * @param {String} setting + * @return {Boolean} + * @public + */ + +app.disabled = function disabled(setting) { + return !this.set(setting); +}; + +/** + * Enable `setting`. + * + * @param {String} setting + * @return {app} for chaining + * @public + */ + +app.enable = function enable(setting) { + return this.set(setting, true); +}; + +/** + * Disable `setting`. + * + * @param {String} setting + * @return {app} for chaining + * @public + */ + +app.disable = function disable(setting) { + return this.set(setting, false); +}; + +/** + * Delegate `.VERB(...)` calls to `router.VERB(...)`. + */ + +methods.forEach(function(method){ + app[method] = function(path){ + if (method === 'get' && arguments.length === 1) { + // app.get(setting) + return this.set(path); + } + + this.lazyrouter(); + + var route = this._router.route(path); + route[method].apply(route, slice.call(arguments, 1)); + return this; + }; +}); + +/** + * Special-cased "all" method, applying the given route `path`, + * middleware, and callback to _every_ HTTP method. + * + * @param {String} path + * @param {Function} ... + * @return {app} for chaining + * @public + */ + +app.all = function all(path) { + this.lazyrouter(); + + var route = this._router.route(path); + var args = slice.call(arguments, 1); + + for (var i = 0; i < methods.length; i++) { + route[methods[i]].apply(route, args); + } + + return this; +}; + +// del -> delete alias + +app.del = deprecate.function(app.delete, 'app.del: Use app.delete instead'); + +/** + * Render the given view `name` name with `options` + * and a callback accepting an error and the + * rendered template string. + * + * Example: + * + * app.render('email', { name: 'Tobi' }, function(err, html){ + * // ... + * }) + * + * @param {String} name + * @param {Object|Function} options or fn + * @param {Function} callback + * @public + */ + +app.render = function render(name, options, callback) { + var cache = this.cache; + var done = callback; + var engines = this.engines; + var opts = options; + var renderOptions = {}; + var view; + + // support callback function as second arg + if (typeof options === 'function') { + done = options; + opts = {}; + } + + // merge app.locals + merge(renderOptions, this.locals); + + // merge options._locals + if (opts._locals) { + merge(renderOptions, opts._locals); + } + + // merge options + merge(renderOptions, opts); + + // set .cache unless explicitly provided + if (renderOptions.cache == null) { + renderOptions.cache = this.enabled('view cache'); + } + + // primed cache + if (renderOptions.cache) { + view = cache[name]; + } + + // view + if (!view) { + var View = this.get('view'); + + view = new View(name, { + defaultEngine: this.get('view engine'), + root: this.get('views'), + engines: engines + }); + + if (!view.path) { + var dirs = Array.isArray(view.root) && view.root.length > 1 + ? 'directories "' + view.root.slice(0, -1).join('", "') + '" or "' + view.root[view.root.length - 1] + '"' + : 'directory "' + view.root + '"' + var err = new Error('Failed to lookup view "' + name + '" in views ' + dirs); + err.view = view; + return done(err); + } + + // prime the cache + if (renderOptions.cache) { + cache[name] = view; + } + } + + // render + tryRender(view, renderOptions, done); +}; + +/** + * Listen for connections. + * + * A node `http.Server` is returned, with this + * application (which is a `Function`) as its + * callback. If you wish to create both an HTTP + * and HTTPS server you may do so with the "http" + * and "https" modules as shown here: + * + * var http = require('http') + * , https = require('https') + * , express = require('express') + * , app = express(); + * + * http.createServer(app).listen(80); + * https.createServer({ ... }, app).listen(443); + * + * @return {http.Server} + * @public + */ + +app.listen = function listen() { + var server = http.createServer(this); + return server.listen.apply(server, arguments); +}; + +/** + * Log error using console.error. + * + * @param {Error} err + * @private + */ + +function logerror(err) { + /* istanbul ignore next */ + if (this.get('env') !== 'test') console.error(err.stack || err.toString()); +} + +/** + * Try rendering a view. + * @private + */ + +function tryRender(view, options, callback) { + try { + view.render(options, callback); + } catch (err) { + callback(err); + } +} diff --git a/node_modules/express/lib/express.js b/node_modules/express/lib/express.js new file mode 100644 index 0000000..485a8fc --- /dev/null +++ b/node_modules/express/lib/express.js @@ -0,0 +1,112 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + */ + +var bodyParser = require('body-parser') +var EventEmitter = require('events').EventEmitter; +var mixin = require('merge-descriptors'); +var proto = require('./application'); +var Route = require('./router/route'); +var Router = require('./router'); +var req = require('./request'); +var res = require('./response'); + +/** + * Expose `createApplication()`. + */ + +exports = module.exports = createApplication; + +/** + * Create an express application. + * + * @return {Function} + * @api public + */ + +function createApplication() { + var app = function(req, res, next) { + app.handle(req, res, next); + }; + + mixin(app, EventEmitter.prototype, false); + mixin(app, proto, false); + + // expose the prototype that will get set on requests + app.request = Object.create(req, { + app: { configurable: true, enumerable: true, writable: true, value: app } + }) + + // expose the prototype that will get set on responses + app.response = Object.create(res, { + app: { configurable: true, enumerable: true, writable: true, value: app } + }) + + app.init(); + return app; +} + +/** + * Expose the prototypes. + */ + +exports.application = proto; +exports.request = req; +exports.response = res; + +/** + * Expose constructors. + */ + +exports.Route = Route; +exports.Router = Router; + +/** + * Expose middleware + */ + +exports.json = bodyParser.json +exports.query = require('./middleware/query'); +exports.static = require('serve-static'); +exports.urlencoded = bodyParser.urlencoded + +/** + * Replace removed middleware with an appropriate error message. + */ + +;[ + 'bodyParser', + 'compress', + 'cookieSession', + 'session', + 'logger', + 'cookieParser', + 'favicon', + 'responseTime', + 'errorHandler', + 'timeout', + 'methodOverride', + 'vhost', + 'csrf', + 'directory', + 'limit', + 'multipart', + 'staticCache', +].forEach(function (name) { + Object.defineProperty(exports, name, { + get: function () { + throw new Error('Most middleware (like ' + name + ') is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware.'); + }, + configurable: true + }); +}); diff --git a/node_modules/express/lib/middleware/init.js b/node_modules/express/lib/middleware/init.js new file mode 100644 index 0000000..dfd0427 --- /dev/null +++ b/node_modules/express/lib/middleware/init.js @@ -0,0 +1,43 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var setPrototypeOf = require('setprototypeof') + +/** + * Initialization middleware, exposing the + * request and response to each other, as well + * as defaulting the X-Powered-By header field. + * + * @param {Function} app + * @return {Function} + * @api private + */ + +exports.init = function(app){ + return function expressInit(req, res, next){ + if (app.enabled('x-powered-by')) res.setHeader('X-Powered-By', 'Express'); + req.res = res; + res.req = req; + req.next = next; + + setPrototypeOf(req, app.request) + setPrototypeOf(res, app.response) + + res.locals = res.locals || Object.create(null); + + next(); + }; +}; + diff --git a/node_modules/express/lib/middleware/query.js b/node_modules/express/lib/middleware/query.js new file mode 100644 index 0000000..7e91669 --- /dev/null +++ b/node_modules/express/lib/middleware/query.js @@ -0,0 +1,47 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + */ + +var merge = require('utils-merge') +var parseUrl = require('parseurl'); +var qs = require('qs'); + +/** + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function query(options) { + var opts = merge({}, options) + var queryparse = qs.parse; + + if (typeof options === 'function') { + queryparse = options; + opts = undefined; + } + + if (opts !== undefined && opts.allowPrototypes === undefined) { + // back-compat for qs module + opts.allowPrototypes = true; + } + + return function query(req, res, next){ + if (!req.query) { + var val = parseUrl(req).query; + req.query = queryparse(val, opts); + } + + next(); + }; +}; diff --git a/node_modules/express/lib/request.js b/node_modules/express/lib/request.js new file mode 100644 index 0000000..8bb86a9 --- /dev/null +++ b/node_modules/express/lib/request.js @@ -0,0 +1,521 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var accepts = require('accepts'); +var deprecate = require('depd')('express'); +var isIP = require('net').isIP; +var typeis = require('type-is'); +var http = require('http'); +var fresh = require('fresh'); +var parseRange = require('range-parser'); +var parse = require('parseurl'); +var proxyaddr = require('proxy-addr'); + +/** + * Request prototype. + * @public + */ + +var req = Object.create(http.IncomingMessage.prototype) + +/** + * Module exports. + * @public + */ + +module.exports = req + +/** + * Return request header. + * + * The `Referrer` header field is special-cased, + * both `Referrer` and `Referer` are interchangeable. + * + * Examples: + * + * req.get('Content-Type'); + * // => "text/plain" + * + * req.get('content-type'); + * // => "text/plain" + * + * req.get('Something'); + * // => undefined + * + * Aliased as `req.header()`. + * + * @param {String} name + * @return {String} + * @public + */ + +req.get = +req.header = function header(name) { + if (!name) { + throw new TypeError('name argument is required to req.get'); + } + + if (typeof name !== 'string') { + throw new TypeError('name must be a string to req.get'); + } + + var lc = name.toLowerCase(); + + switch (lc) { + case 'referer': + case 'referrer': + return this.headers.referrer + || this.headers.referer; + default: + return this.headers[lc]; + } +}; + +/** + * To do: update docs. + * + * Check if the given `type(s)` is acceptable, returning + * the best match when true, otherwise `undefined`, in which + * case you should respond with 406 "Not Acceptable". + * + * The `type` value may be a single MIME type string + * such as "application/json", an extension name + * such as "json", a comma-delimited list such as "json, html, text/plain", + * an argument list such as `"json", "html", "text/plain"`, + * or an array `["json", "html", "text/plain"]`. When a list + * or array is given, the _best_ match, if any is returned. + * + * Examples: + * + * // Accept: text/html + * req.accepts('html'); + * // => "html" + * + * // Accept: text/*, application/json + * req.accepts('html'); + * // => "html" + * req.accepts('text/html'); + * // => "text/html" + * req.accepts('json, text'); + * // => "json" + * req.accepts('application/json'); + * // => "application/json" + * + * // Accept: text/*, application/json + * req.accepts('image/png'); + * req.accepts('png'); + * // => undefined + * + * // Accept: text/*;q=.5, application/json + * req.accepts(['html', 'json']); + * req.accepts('html', 'json'); + * req.accepts('html, json'); + * // => "json" + * + * @param {String|Array} type(s) + * @return {String|Array|Boolean} + * @public + */ + +req.accepts = function(){ + var accept = accepts(this); + return accept.types.apply(accept, arguments); +}; + +/** + * Check if the given `encoding`s are accepted. + * + * @param {String} ...encoding + * @return {String|Array} + * @public + */ + +req.acceptsEncodings = function(){ + var accept = accepts(this); + return accept.encodings.apply(accept, arguments); +}; + +req.acceptsEncoding = deprecate.function(req.acceptsEncodings, + 'req.acceptsEncoding: Use acceptsEncodings instead'); + +/** + * Check if the given `charset`s are acceptable, + * otherwise you should respond with 406 "Not Acceptable". + * + * @param {String} ...charset + * @return {String|Array} + * @public + */ + +req.acceptsCharsets = function(){ + var accept = accepts(this); + return accept.charsets.apply(accept, arguments); +}; + +req.acceptsCharset = deprecate.function(req.acceptsCharsets, + 'req.acceptsCharset: Use acceptsCharsets instead'); + +/** + * Check if the given `lang`s are acceptable, + * otherwise you should respond with 406 "Not Acceptable". + * + * @param {String} ...lang + * @return {String|Array} + * @public + */ + +req.acceptsLanguages = function(){ + var accept = accepts(this); + return accept.languages.apply(accept, arguments); +}; + +req.acceptsLanguage = deprecate.function(req.acceptsLanguages, + 'req.acceptsLanguage: Use acceptsLanguages instead'); + +/** + * Parse Range header field, capping to the given `size`. + * + * Unspecified ranges such as "0-" require knowledge of your resource length. In + * the case of a byte range this is of course the total number of bytes. If the + * Range header field is not given `undefined` is returned, `-1` when unsatisfiable, + * and `-2` when syntactically invalid. + * + * When ranges are returned, the array has a "type" property which is the type of + * range that is required (most commonly, "bytes"). Each array element is an object + * with a "start" and "end" property for the portion of the range. + * + * The "combine" option can be set to `true` and overlapping & adjacent ranges + * will be combined into a single range. + * + * NOTE: remember that ranges are inclusive, so for example "Range: users=0-3" + * should respond with 4 users when available, not 3. + * + * @param {number} size + * @param {object} [options] + * @param {boolean} [options.combine=false] + * @return {number|array} + * @public + */ + +req.range = function range(size, options) { + var range = this.get('Range'); + if (!range) return; + return parseRange(size, range, options); +}; + +/** + * Return the value of param `name` when present or `defaultValue`. + * + * - Checks route placeholders, ex: _/user/:id_ + * - Checks body params, ex: id=12, {"id":12} + * - Checks query string params, ex: ?id=12 + * + * To utilize request bodies, `req.body` + * should be an object. This can be done by using + * the `bodyParser()` middleware. + * + * @param {String} name + * @param {Mixed} [defaultValue] + * @return {String} + * @public + */ + +req.param = function param(name, defaultValue) { + var params = this.params || {}; + var body = this.body || {}; + var query = this.query || {}; + + var args = arguments.length === 1 + ? 'name' + : 'name, default'; + deprecate('req.param(' + args + '): Use req.params, req.body, or req.query instead'); + + if (null != params[name] && params.hasOwnProperty(name)) return params[name]; + if (null != body[name]) return body[name]; + if (null != query[name]) return query[name]; + + return defaultValue; +}; + +/** + * Check if the incoming request contains the "Content-Type" + * header field, and it contains the give mime `type`. + * + * Examples: + * + * // With Content-Type: text/html; charset=utf-8 + * req.is('html'); + * req.is('text/html'); + * req.is('text/*'); + * // => true + * + * // When Content-Type is application/json + * req.is('json'); + * req.is('application/json'); + * req.is('application/*'); + * // => true + * + * req.is('html'); + * // => false + * + * @param {String|Array} types... + * @return {String|false|null} + * @public + */ + +req.is = function is(types) { + var arr = types; + + // support flattened arguments + if (!Array.isArray(types)) { + arr = new Array(arguments.length); + for (var i = 0; i < arr.length; i++) { + arr[i] = arguments[i]; + } + } + + return typeis(this, arr); +}; + +/** + * Return the protocol string "http" or "https" + * when requested with TLS. When the "trust proxy" + * setting trusts the socket address, the + * "X-Forwarded-Proto" header field will be trusted + * and used if present. + * + * If you're running behind a reverse proxy that + * supplies https for you this may be enabled. + * + * @return {String} + * @public + */ + +defineGetter(req, 'protocol', function protocol(){ + var proto = this.connection.encrypted + ? 'https' + : 'http'; + var trust = this.app.get('trust proxy fn'); + + if (!trust(this.connection.remoteAddress, 0)) { + return proto; + } + + // Note: X-Forwarded-Proto is normally only ever a + // single value, but this is to be safe. + var header = this.get('X-Forwarded-Proto') || proto + var index = header.indexOf(',') + + return index !== -1 + ? header.substring(0, index).trim() + : header.trim() +}); + +/** + * Short-hand for: + * + * req.protocol === 'https' + * + * @return {Boolean} + * @public + */ + +defineGetter(req, 'secure', function secure(){ + return this.protocol === 'https'; +}); + +/** + * Return the remote address from the trusted proxy. + * + * The is the remote address on the socket unless + * "trust proxy" is set. + * + * @return {String} + * @public + */ + +defineGetter(req, 'ip', function ip(){ + var trust = this.app.get('trust proxy fn'); + return proxyaddr(this, trust); +}); + +/** + * When "trust proxy" is set, trusted proxy addresses + client. + * + * For example if the value were "client, proxy1, proxy2" + * you would receive the array `["client", "proxy1", "proxy2"]` + * where "proxy2" is the furthest down-stream and "proxy1" and + * "proxy2" were trusted. + * + * @return {Array} + * @public + */ + +defineGetter(req, 'ips', function ips() { + var trust = this.app.get('trust proxy fn'); + var addrs = proxyaddr.all(this, trust); + + // reverse the order (to farthest -> closest) + // and remove socket address + addrs.reverse().pop() + + return addrs +}); + +/** + * Return subdomains as an array. + * + * Subdomains are the dot-separated parts of the host before the main domain of + * the app. By default, the domain of the app is assumed to be the last two + * parts of the host. This can be changed by setting "subdomain offset". + * + * For example, if the domain is "tobi.ferrets.example.com": + * If "subdomain offset" is not set, req.subdomains is `["ferrets", "tobi"]`. + * If "subdomain offset" is 3, req.subdomains is `["tobi"]`. + * + * @return {Array} + * @public + */ + +defineGetter(req, 'subdomains', function subdomains() { + var hostname = this.hostname; + + if (!hostname) return []; + + var offset = this.app.get('subdomain offset'); + var subdomains = !isIP(hostname) + ? hostname.split('.').reverse() + : [hostname]; + + return subdomains.slice(offset); +}); + +/** + * Short-hand for `url.parse(req.url).pathname`. + * + * @return {String} + * @public + */ + +defineGetter(req, 'path', function path() { + return parse(this).pathname; +}); + +/** + * Parse the "Host" header field to a hostname. + * + * When the "trust proxy" setting trusts the socket + * address, the "X-Forwarded-Host" header field will + * be trusted. + * + * @return {String} + * @public + */ + +defineGetter(req, 'hostname', function hostname(){ + var trust = this.app.get('trust proxy fn'); + var host = this.get('X-Forwarded-Host'); + + if (!host || !trust(this.connection.remoteAddress, 0)) { + host = this.get('Host'); + } + + if (!host) return; + + // IPv6 literal support + var offset = host[0] === '[' + ? host.indexOf(']') + 1 + : 0; + var index = host.indexOf(':', offset); + + return index !== -1 + ? host.substring(0, index) + : host; +}); + +// TODO: change req.host to return host in next major + +defineGetter(req, 'host', deprecate.function(function host(){ + return this.hostname; +}, 'req.host: Use req.hostname instead')); + +/** + * Check if the request is fresh, aka + * Last-Modified and/or the ETag + * still match. + * + * @return {Boolean} + * @public + */ + +defineGetter(req, 'fresh', function(){ + var method = this.method; + var res = this.res + var status = res.statusCode + + // GET or HEAD for weak freshness validation only + if ('GET' !== method && 'HEAD' !== method) return false; + + // 2xx or 304 as per rfc2616 14.26 + if ((status >= 200 && status < 300) || 304 === status) { + return fresh(this.headers, { + 'etag': res.get('ETag'), + 'last-modified': res.get('Last-Modified') + }) + } + + return false; +}); + +/** + * Check if the request is stale, aka + * "Last-Modified" and / or the "ETag" for the + * resource has changed. + * + * @return {Boolean} + * @public + */ + +defineGetter(req, 'stale', function stale(){ + return !this.fresh; +}); + +/** + * Check if the request was an _XMLHttpRequest_. + * + * @return {Boolean} + * @public + */ + +defineGetter(req, 'xhr', function xhr(){ + var val = this.get('X-Requested-With') || ''; + return val.toLowerCase() === 'xmlhttprequest'; +}); + +/** + * Helper function for creating a getter on an object. + * + * @param {Object} obj + * @param {String} name + * @param {Function} getter + * @private + */ +function defineGetter(obj, name, getter) { + Object.defineProperty(obj, name, { + configurable: true, + enumerable: true, + get: getter + }); +} diff --git a/node_modules/express/lib/response.js b/node_modules/express/lib/response.js new file mode 100644 index 0000000..9c1796d --- /dev/null +++ b/node_modules/express/lib/response.js @@ -0,0 +1,1137 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var Buffer = require('safe-buffer').Buffer +var contentDisposition = require('content-disposition'); +var deprecate = require('depd')('express'); +var encodeUrl = require('encodeurl'); +var escapeHtml = require('escape-html'); +var http = require('http'); +var isAbsolute = require('./utils').isAbsolute; +var onFinished = require('on-finished'); +var path = require('path'); +var statuses = require('statuses') +var merge = require('utils-merge'); +var sign = require('cookie-signature').sign; +var normalizeType = require('./utils').normalizeType; +var normalizeTypes = require('./utils').normalizeTypes; +var setCharset = require('./utils').setCharset; +var cookie = require('cookie'); +var send = require('send'); +var extname = path.extname; +var mime = send.mime; +var resolve = path.resolve; +var vary = require('vary'); + +/** + * Response prototype. + * @public + */ + +var res = Object.create(http.ServerResponse.prototype) + +/** + * Module exports. + * @public + */ + +module.exports = res + +/** + * Module variables. + * @private + */ + +var charsetRegExp = /;\s*charset\s*=/; + +/** + * Set status `code`. + * + * @param {Number} code + * @return {ServerResponse} + * @public + */ + +res.status = function status(code) { + this.statusCode = code; + return this; +}; + +/** + * Set Link header field with the given `links`. + * + * Examples: + * + * res.links({ + * next: 'http://api.example.com/users?page=2', + * last: 'http://api.example.com/users?page=5' + * }); + * + * @param {Object} links + * @return {ServerResponse} + * @public + */ + +res.links = function(links){ + var link = this.get('Link') || ''; + if (link) link += ', '; + return this.set('Link', link + Object.keys(links).map(function(rel){ + return '<' + links[rel] + '>; rel="' + rel + '"'; + }).join(', ')); +}; + +/** + * Send a response. + * + * Examples: + * + * res.send(Buffer.from('wahoo')); + * res.send({ some: 'json' }); + * res.send('<p>some html</p>'); + * + * @param {string|number|boolean|object|Buffer} body + * @public + */ + +res.send = function send(body) { + var chunk = body; + var encoding; + var req = this.req; + var type; + + // settings + var app = this.app; + + // allow status / body + if (arguments.length === 2) { + // res.send(body, status) backwards compat + if (typeof arguments[0] !== 'number' && typeof arguments[1] === 'number') { + deprecate('res.send(body, status): Use res.status(status).send(body) instead'); + this.statusCode = arguments[1]; + } else { + deprecate('res.send(status, body): Use res.status(status).send(body) instead'); + this.statusCode = arguments[0]; + chunk = arguments[1]; + } + } + + // disambiguate res.send(status) and res.send(status, num) + if (typeof chunk === 'number' && arguments.length === 1) { + // res.send(status) will set status message as text string + if (!this.get('Content-Type')) { + this.type('txt'); + } + + deprecate('res.send(status): Use res.sendStatus(status) instead'); + this.statusCode = chunk; + chunk = statuses[chunk] + } + + switch (typeof chunk) { + // string defaulting to html + case 'string': + if (!this.get('Content-Type')) { + this.type('html'); + } + break; + case 'boolean': + case 'number': + case 'object': + if (chunk === null) { + chunk = ''; + } else if (Buffer.isBuffer(chunk)) { + if (!this.get('Content-Type')) { + this.type('bin'); + } + } else { + return this.json(chunk); + } + break; + } + + // write strings in utf-8 + if (typeof chunk === 'string') { + encoding = 'utf8'; + type = this.get('Content-Type'); + + // reflect this in content-type + if (typeof type === 'string') { + this.set('Content-Type', setCharset(type, 'utf-8')); + } + } + + // determine if ETag should be generated + var etagFn = app.get('etag fn') + var generateETag = !this.get('ETag') && typeof etagFn === 'function' + + // populate Content-Length + var len + if (chunk !== undefined) { + if (Buffer.isBuffer(chunk)) { + // get length of Buffer + len = chunk.length + } else if (!generateETag && chunk.length < 1000) { + // just calculate length when no ETag + small chunk + len = Buffer.byteLength(chunk, encoding) + } else { + // convert chunk to Buffer and calculate + chunk = Buffer.from(chunk, encoding) + encoding = undefined; + len = chunk.length + } + + this.set('Content-Length', len); + } + + // populate ETag + var etag; + if (generateETag && len !== undefined) { + if ((etag = etagFn(chunk, encoding))) { + this.set('ETag', etag); + } + } + + // freshness + if (req.fresh) this.statusCode = 304; + + // strip irrelevant headers + if (204 === this.statusCode || 304 === this.statusCode) { + this.removeHeader('Content-Type'); + this.removeHeader('Content-Length'); + this.removeHeader('Transfer-Encoding'); + chunk = ''; + } + + if (req.method === 'HEAD') { + // skip body for HEAD + this.end(); + } else { + // respond + this.end(chunk, encoding); + } + + return this; +}; + +/** + * Send JSON response. + * + * Examples: + * + * res.json(null); + * res.json({ user: 'tj' }); + * + * @param {string|number|boolean|object} obj + * @public + */ + +res.json = function json(obj) { + var val = obj; + + // allow status / body + if (arguments.length === 2) { + // res.json(body, status) backwards compat + if (typeof arguments[1] === 'number') { + deprecate('res.json(obj, status): Use res.status(status).json(obj) instead'); + this.statusCode = arguments[1]; + } else { + deprecate('res.json(status, obj): Use res.status(status).json(obj) instead'); + this.statusCode = arguments[0]; + val = arguments[1]; + } + } + + // settings + var app = this.app; + var escape = app.get('json escape') + var replacer = app.get('json replacer'); + var spaces = app.get('json spaces'); + var body = stringify(val, replacer, spaces, escape) + + // content-type + if (!this.get('Content-Type')) { + this.set('Content-Type', 'application/json'); + } + + return this.send(body); +}; + +/** + * Send JSON response with JSONP callback support. + * + * Examples: + * + * res.jsonp(null); + * res.jsonp({ user: 'tj' }); + * + * @param {string|number|boolean|object} obj + * @public + */ + +res.jsonp = function jsonp(obj) { + var val = obj; + + // allow status / body + if (arguments.length === 2) { + // res.json(body, status) backwards compat + if (typeof arguments[1] === 'number') { + deprecate('res.jsonp(obj, status): Use res.status(status).json(obj) instead'); + this.statusCode = arguments[1]; + } else { + deprecate('res.jsonp(status, obj): Use res.status(status).jsonp(obj) instead'); + this.statusCode = arguments[0]; + val = arguments[1]; + } + } + + // settings + var app = this.app; + var escape = app.get('json escape') + var replacer = app.get('json replacer'); + var spaces = app.get('json spaces'); + var body = stringify(val, replacer, spaces, escape) + var callback = this.req.query[app.get('jsonp callback name')]; + + // content-type + if (!this.get('Content-Type')) { + this.set('X-Content-Type-Options', 'nosniff'); + this.set('Content-Type', 'application/json'); + } + + // fixup callback + if (Array.isArray(callback)) { + callback = callback[0]; + } + + // jsonp + if (typeof callback === 'string' && callback.length !== 0) { + this.set('X-Content-Type-Options', 'nosniff'); + this.set('Content-Type', 'text/javascript'); + + // restrict callback charset + callback = callback.replace(/[^\[\]\w$.]/g, ''); + + // replace chars not allowed in JavaScript that are in JSON + body = body + .replace(/\u2028/g, '\\u2028') + .replace(/\u2029/g, '\\u2029'); + + // the /**/ is a specific security mitigation for "Rosetta Flash JSONP abuse" + // the typeof check is just to reduce client error noise + body = '/**/ typeof ' + callback + ' === \'function\' && ' + callback + '(' + body + ');'; + } + + return this.send(body); +}; + +/** + * Send given HTTP status code. + * + * Sets the response status to `statusCode` and the body of the + * response to the standard description from node's http.STATUS_CODES + * or the statusCode number if no description. + * + * Examples: + * + * res.sendStatus(200); + * + * @param {number} statusCode + * @public + */ + +res.sendStatus = function sendStatus(statusCode) { + var body = statuses[statusCode] || String(statusCode) + + this.statusCode = statusCode; + this.type('txt'); + + return this.send(body); +}; + +/** + * Transfer the file at the given `path`. + * + * Automatically sets the _Content-Type_ response header field. + * The callback `callback(err)` is invoked when the transfer is complete + * or when an error occurs. Be sure to check `res.sentHeader` + * if you wish to attempt responding, as the header and some data + * may have already been transferred. + * + * Options: + * + * - `maxAge` defaulting to 0 (can be string converted by `ms`) + * - `root` root directory for relative filenames + * - `headers` object of headers to serve with file + * - `dotfiles` serve dotfiles, defaulting to false; can be `"allow"` to send them + * + * Other options are passed along to `send`. + * + * Examples: + * + * The following example illustrates how `res.sendFile()` may + * be used as an alternative for the `static()` middleware for + * dynamic situations. The code backing `res.sendFile()` is actually + * the same code, so HTTP cache support etc is identical. + * + * 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.send(403, 'Sorry! you cant see that.'); + * } + * }); + * }); + * + * @public + */ + +res.sendFile = function sendFile(path, options, callback) { + var done = callback; + var req = this.req; + var res = this; + var next = req.next; + var opts = options || {}; + + if (!path) { + throw new TypeError('path argument is required to res.sendFile'); + } + + // support function as second arg + if (typeof options === 'function') { + done = options; + opts = {}; + } + + if (!opts.root && !isAbsolute(path)) { + throw new TypeError('path must be absolute or specify root to res.sendFile'); + } + + // create file stream + var pathname = encodeURI(path); + var file = send(req, pathname, opts); + + // transfer + sendfile(res, file, opts, function (err) { + if (done) return done(err); + if (err && err.code === 'EISDIR') return next(); + + // next() all but write errors + if (err && err.code !== 'ECONNABORTED' && err.syscall !== 'write') { + next(err); + } + }); +}; + +/** + * Transfer the file at the given `path`. + * + * Automatically sets the _Content-Type_ response header field. + * The callback `callback(err)` is invoked when the transfer is complete + * or when an error occurs. Be sure to check `res.sentHeader` + * if you wish to attempt responding, as the header and some data + * may have already been transferred. + * + * Options: + * + * - `maxAge` defaulting to 0 (can be string converted by `ms`) + * - `root` root directory for relative filenames + * - `headers` object of headers to serve with file + * - `dotfiles` serve dotfiles, defaulting to false; can be `"allow"` to send them + * + * Other options are passed along to `send`. + * + * Examples: + * + * The following example illustrates how `res.sendfile()` may + * be used as an alternative for the `static()` middleware for + * dynamic situations. The code backing `res.sendfile()` is actually + * the same code, so HTTP cache support etc is identical. + * + * 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.send(403, 'Sorry! you cant see that.'); + * } + * }); + * }); + * + * @public + */ + +res.sendfile = function (path, options, callback) { + var done = callback; + var req = this.req; + var res = this; + var next = req.next; + var opts = options || {}; + + // support function as second arg + if (typeof options === 'function') { + done = options; + opts = {}; + } + + // create file stream + var file = send(req, path, opts); + + // transfer + sendfile(res, file, opts, function (err) { + if (done) return done(err); + if (err && err.code === 'EISDIR') return next(); + + // next() all but write errors + if (err && err.code !== 'ECONNABORT' && err.syscall !== 'write') { + next(err); + } + }); +}; + +res.sendfile = deprecate.function(res.sendfile, + 'res.sendfile: Use res.sendFile instead'); + +/** + * Transfer the file at the given `path` as an attachment. + * + * Optionally providing an alternate attachment `filename`, + * and optional callback `callback(err)`. The callback is invoked + * when the data transfer is complete, or when an error has + * ocurred. Be sure to check `res.headersSent` if you plan to respond. + * + * Optionally providing an `options` object to use with `res.sendFile()`. + * This function will set the `Content-Disposition` header, overriding + * any `Content-Disposition` header passed as header options in order + * to set the attachment and filename. + * + * This method uses `res.sendFile()`. + * + * @public + */ + +res.download = function download (path, filename, options, callback) { + var done = callback; + var name = filename; + var opts = options || null + + // support function as second or third arg + if (typeof filename === 'function') { + done = filename; + name = null; + opts = null + } else if (typeof options === 'function') { + done = options + opts = null + } + + // set Content-Disposition when file is sent + var headers = { + 'Content-Disposition': contentDisposition(name || path) + }; + + // merge user-provided headers + if (opts && opts.headers) { + var keys = Object.keys(opts.headers) + for (var i = 0; i < keys.length; i++) { + var key = keys[i] + if (key.toLowerCase() !== 'content-disposition') { + headers[key] = opts.headers[key] + } + } + } + + // merge user-provided options + opts = Object.create(opts) + opts.headers = headers + + // Resolve the full path for sendFile + var fullPath = resolve(path); + + // send file + return this.sendFile(fullPath, opts, done) +}; + +/** + * Set _Content-Type_ response header with `type` through `mime.lookup()` + * when it does not contain "/", or set the Content-Type to `type` otherwise. + * + * Examples: + * + * res.type('.html'); + * res.type('html'); + * res.type('json'); + * res.type('application/json'); + * res.type('png'); + * + * @param {String} type + * @return {ServerResponse} for chaining + * @public + */ + +res.contentType = +res.type = function contentType(type) { + var ct = type.indexOf('/') === -1 + ? mime.lookup(type) + : type; + + return this.set('Content-Type', ct); +}; + +/** + * Respond to the Acceptable formats using an `obj` + * of mime-type callbacks. + * + * This method uses `req.accepted`, an array of + * acceptable types ordered by their quality values. + * When "Accept" is not present the _first_ callback + * is invoked, otherwise the first match is used. When + * no match is performed the server responds with + * 406 "Not Acceptable". + * + * Content-Type is set for you, however if you choose + * you may alter this within the callback using `res.type()` + * or `res.set('Content-Type', ...)`. + * + * res.format({ + * 'text/plain': function(){ + * res.send('hey'); + * }, + * + * 'text/html': function(){ + * res.send('<p>hey</p>'); + * }, + * + * 'appliation/json': function(){ + * res.send({ message: 'hey' }); + * } + * }); + * + * In addition to canonicalized MIME types you may + * also use extnames mapped to these types: + * + * res.format({ + * text: function(){ + * res.send('hey'); + * }, + * + * html: function(){ + * res.send('<p>hey</p>'); + * }, + * + * json: function(){ + * res.send({ message: 'hey' }); + * } + * }); + * + * By default Express passes an `Error` + * with a `.status` of 406 to `next(err)` + * if a match is not made. If you provide + * a `.default` callback it will be invoked + * instead. + * + * @param {Object} obj + * @return {ServerResponse} for chaining + * @public + */ + +res.format = function(obj){ + var req = this.req; + var next = req.next; + + var fn = obj.default; + if (fn) delete obj.default; + var keys = Object.keys(obj); + + var key = keys.length > 0 + ? req.accepts(keys) + : false; + + this.vary("Accept"); + + if (key) { + this.set('Content-Type', normalizeType(key).value); + obj[key](req, this, next); + } else if (fn) { + fn(); + } else { + var err = new Error('Not Acceptable'); + err.status = err.statusCode = 406; + err.types = normalizeTypes(keys).map(function(o){ return o.value }); + next(err); + } + + return this; +}; + +/** + * Set _Content-Disposition_ header to _attachment_ with optional `filename`. + * + * @param {String} filename + * @return {ServerResponse} + * @public + */ + +res.attachment = function attachment(filename) { + if (filename) { + this.type(extname(filename)); + } + + this.set('Content-Disposition', contentDisposition(filename)); + + return this; +}; + +/** + * Append additional header `field` with value `val`. + * + * Example: + * + * res.append('Link', ['<http://localhost/>', '<http://localhost:3000/>']); + * res.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly'); + * res.append('Warning', '199 Miscellaneous warning'); + * + * @param {String} field + * @param {String|Array} val + * @return {ServerResponse} for chaining + * @public + */ + +res.append = function append(field, val) { + var prev = this.get(field); + var value = val; + + if (prev) { + // concat the new and prev vals + value = Array.isArray(prev) ? prev.concat(val) + : Array.isArray(val) ? [prev].concat(val) + : [prev, val]; + } + + return this.set(field, value); +}; + +/** + * Set header `field` to `val`, or pass + * an object of header fields. + * + * Examples: + * + * res.set('Foo', ['bar', 'baz']); + * res.set('Accept', 'application/json'); + * res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' }); + * + * Aliased as `res.header()`. + * + * @param {String|Object} field + * @param {String|Array} val + * @return {ServerResponse} for chaining + * @public + */ + +res.set = +res.header = function header(field, val) { + if (arguments.length === 2) { + var value = Array.isArray(val) + ? val.map(String) + : String(val); + + // add charset to content-type + if (field.toLowerCase() === 'content-type') { + if (Array.isArray(value)) { + throw new TypeError('Content-Type cannot be set to an Array'); + } + if (!charsetRegExp.test(value)) { + var charset = mime.charsets.lookup(value.split(';')[0]); + if (charset) value += '; charset=' + charset.toLowerCase(); + } + } + + this.setHeader(field, value); + } else { + for (var key in field) { + this.set(key, field[key]); + } + } + return this; +}; + +/** + * Get value for header `field`. + * + * @param {String} field + * @return {String} + * @public + */ + +res.get = function(field){ + return this.getHeader(field); +}; + +/** + * Clear cookie `name`. + * + * @param {String} name + * @param {Object} [options] + * @return {ServerResponse} for chaining + * @public + */ + +res.clearCookie = function clearCookie(name, options) { + var opts = merge({ expires: new Date(1), path: '/' }, options); + + return this.cookie(name, '', opts); +}; + +/** + * Set cookie `name` to `value`, with the given `options`. + * + * Options: + * + * - `maxAge` max-age in milliseconds, converted to `expires` + * - `signed` sign the cookie + * - `path` defaults to "/" + * + * Examples: + * + * // "Remember Me" for 15 minutes + * res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true }); + * + * // save as above + * res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true }) + * + * @param {String} name + * @param {String|Object} value + * @param {Object} [options] + * @return {ServerResponse} for chaining + * @public + */ + +res.cookie = function (name, value, options) { + var opts = merge({}, options); + var secret = this.req.secret; + var signed = opts.signed; + + if (signed && !secret) { + throw new Error('cookieParser("secret") required for signed cookies'); + } + + var val = typeof value === 'object' + ? 'j:' + JSON.stringify(value) + : String(value); + + if (signed) { + val = 's:' + sign(val, secret); + } + + if ('maxAge' in opts) { + opts.expires = new Date(Date.now() + opts.maxAge); + opts.maxAge /= 1000; + } + + if (opts.path == null) { + opts.path = '/'; + } + + this.append('Set-Cookie', cookie.serialize(name, String(val), opts)); + + return this; +}; + +/** + * Set the location header to `url`. + * + * The given `url` can also be "back", which redirects + * to the _Referrer_ or _Referer_ headers or "/". + * + * Examples: + * + * res.location('/foo/bar').; + * res.location('http://example.com'); + * res.location('../login'); + * + * @param {String} url + * @return {ServerResponse} for chaining + * @public + */ + +res.location = function location(url) { + var loc = url; + + // "back" is an alias for the referrer + if (url === 'back') { + loc = this.req.get('Referrer') || '/'; + } + + // set location + return this.set('Location', encodeUrl(loc)); +}; + +/** + * Redirect to the given `url` with optional response `status` + * defaulting to 302. + * + * The resulting `url` is determined by `res.location()`, so + * it will play nicely with mounted apps, relative paths, + * `"back"` etc. + * + * Examples: + * + * res.redirect('/foo/bar'); + * res.redirect('http://example.com'); + * res.redirect(301, 'http://example.com'); + * res.redirect('../login'); // /blog/post/1 -> /blog/login + * + * @public + */ + +res.redirect = function redirect(url) { + var address = url; + var body; + var status = 302; + + // allow status / url + if (arguments.length === 2) { + if (typeof arguments[0] === 'number') { + status = arguments[0]; + address = arguments[1]; + } else { + deprecate('res.redirect(url, status): Use res.redirect(status, url) instead'); + status = arguments[1]; + } + } + + // Set location header + address = this.location(address).get('Location'); + + // Support text/{plain,html} by default + this.format({ + text: function(){ + body = statuses[status] + '. Redirecting to ' + address + }, + + html: function(){ + var u = escapeHtml(address); + body = '<p>' + statuses[status] + '. Redirecting to <a href="' + u + '">' + u + '</a></p>' + }, + + default: function(){ + body = ''; + } + }); + + // Respond + this.statusCode = status; + this.set('Content-Length', Buffer.byteLength(body)); + + if (this.req.method === 'HEAD') { + this.end(); + } else { + this.end(body); + } +}; + +/** + * Add `field` to Vary. If already present in the Vary set, then + * this call is simply ignored. + * + * @param {Array|String} field + * @return {ServerResponse} for chaining + * @public + */ + +res.vary = function(field){ + // checks for back-compat + if (!field || (Array.isArray(field) && !field.length)) { + deprecate('res.vary(): Provide a field name'); + return this; + } + + vary(this, field); + + return this; +}; + +/** + * Render `view` with the given `options` and optional callback `fn`. + * When a callback function is given a response will _not_ be made + * automatically, otherwise a response of _200_ and _text/html_ is given. + * + * Options: + * + * - `cache` boolean hinting to the engine it should cache + * - `filename` filename of the view being rendered + * + * @public + */ + +res.render = function render(view, options, callback) { + var app = this.req.app; + var done = callback; + var opts = options || {}; + var req = this.req; + var self = this; + + // support callback function as second arg + if (typeof options === 'function') { + done = options; + opts = {}; + } + + // merge res.locals + opts._locals = self.locals; + + // default callback to respond + done = done || function (err, str) { + if (err) return req.next(err); + self.send(str); + }; + + // render + app.render(view, opts, done); +}; + +// pipe the send file stream +function sendfile(res, file, options, callback) { + var done = false; + var streaming; + + // request aborted + function onaborted() { + if (done) return; + done = true; + + var err = new Error('Request aborted'); + err.code = 'ECONNABORTED'; + callback(err); + } + + // directory + function ondirectory() { + if (done) return; + done = true; + + var err = new Error('EISDIR, read'); + err.code = 'EISDIR'; + callback(err); + } + + // errors + function onerror(err) { + if (done) return; + done = true; + callback(err); + } + + // ended + function onend() { + if (done) return; + done = true; + callback(); + } + + // file + function onfile() { + streaming = false; + } + + // finished + function onfinish(err) { + if (err && err.code === 'ECONNRESET') return onaborted(); + if (err) return onerror(err); + if (done) return; + + setImmediate(function () { + if (streaming !== false && !done) { + onaborted(); + return; + } + + if (done) return; + done = true; + callback(); + }); + } + + // streaming + function onstream() { + streaming = true; + } + + file.on('directory', ondirectory); + file.on('end', onend); + file.on('error', onerror); + file.on('file', onfile); + file.on('stream', onstream); + onFinished(res, onfinish); + + if (options.headers) { + // set headers on successful transfer + file.on('headers', function headers(res) { + var obj = options.headers; + var keys = Object.keys(obj); + + for (var i = 0; i < keys.length; i++) { + var k = keys[i]; + res.setHeader(k, obj[k]); + } + }); + } + + // pipe + file.pipe(res); +} + +/** + * Stringify JSON, like JSON.stringify, but v8 optimized, with the + * ability to escape characters that can trigger HTML sniffing. + * + * @param {*} value + * @param {function} replaces + * @param {number} spaces + * @param {boolean} escape + * @returns {string} + * @private + */ + +function stringify (value, replacer, spaces, escape) { + // v8 checks arguments.length for optimizing simple call + // https://bugs.chromium.org/p/v8/issues/detail?id=4730 + var json = replacer || spaces + ? JSON.stringify(value, replacer, spaces) + : JSON.stringify(value); + + if (escape) { + json = json.replace(/[<>&]/g, function (c) { + switch (c.charCodeAt(0)) { + case 0x3c: + return '\\u003c' + case 0x3e: + return '\\u003e' + case 0x26: + return '\\u0026' + default: + return c + } + }) + } + + return json +} diff --git a/node_modules/express/lib/router/index.js b/node_modules/express/lib/router/index.js new file mode 100644 index 0000000..60727ed --- /dev/null +++ b/node_modules/express/lib/router/index.js @@ -0,0 +1,662 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var Route = require('./route'); +var Layer = require('./layer'); +var methods = require('methods'); +var mixin = require('utils-merge'); +var debug = require('debug')('express:router'); +var deprecate = require('depd')('express'); +var flatten = require('array-flatten'); +var parseUrl = require('parseurl'); +var setPrototypeOf = require('setprototypeof') + +/** + * Module variables. + * @private + */ + +var objectRegExp = /^\[object (\S+)\]$/; +var slice = Array.prototype.slice; +var toString = Object.prototype.toString; + +/** + * Initialize a new `Router` with the given `options`. + * + * @param {Object} options + * @return {Router} which is an callable function + * @public + */ + +var proto = module.exports = function(options) { + var opts = options || {}; + + function router(req, res, next) { + router.handle(req, res, next); + } + + // mixin Router class functions + setPrototypeOf(router, proto) + + router.params = {}; + router._params = []; + router.caseSensitive = opts.caseSensitive; + router.mergeParams = opts.mergeParams; + router.strict = opts.strict; + router.stack = []; + + return router; +}; + +/** + * Map the given param placeholder `name`(s) to the given callback. + * + * Parameter mapping is used to provide pre-conditions to routes + * which use normalized placeholders. For example a _:user_id_ parameter + * could automatically load a user's information from the database without + * any additional code, + * + * The callback uses the same signature as middleware, the only difference + * being that the value of the placeholder is passed, in this case the _id_ + * of the user. Once the `next()` function is invoked, just like middleware + * it will continue on to execute the route, or subsequent parameter functions. + * + * Just like in middleware, you must either respond to the request or call next + * to avoid stalling the request. + * + * app.param('user_id', function(req, res, next, id){ + * User.find(id, function(err, user){ + * if (err) { + * return next(err); + * } else if (!user) { + * return next(new Error('failed to load user')); + * } + * req.user = user; + * next(); + * }); + * }); + * + * @param {String} name + * @param {Function} fn + * @return {app} for chaining + * @public + */ + +proto.param = function param(name, fn) { + // param logic + if (typeof name === 'function') { + deprecate('router.param(fn): Refactor to use path params'); + this._params.push(name); + return; + } + + // apply param functions + var params = this._params; + var len = params.length; + var ret; + + if (name[0] === ':') { + deprecate('router.param(' + JSON.stringify(name) + ', fn): Use router.param(' + JSON.stringify(name.substr(1)) + ', fn) instead'); + name = name.substr(1); + } + + for (var i = 0; i < len; ++i) { + if (ret = params[i](name, fn)) { + fn = ret; + } + } + + // ensure we end up with a + // middleware function + if ('function' !== typeof fn) { + throw new Error('invalid param() call for ' + name + ', got ' + fn); + } + + (this.params[name] = this.params[name] || []).push(fn); + return this; +}; + +/** + * Dispatch a req, res into the router. + * @private + */ + +proto.handle = function handle(req, res, out) { + var self = this; + + debug('dispatching %s %s', req.method, req.url); + + var idx = 0; + var protohost = getProtohost(req.url) || '' + var removed = ''; + var slashAdded = false; + var paramcalled = {}; + + // store options for OPTIONS request + // only used if OPTIONS request + var options = []; + + // middleware and routes + var stack = self.stack; + + // manage inter-router variables + var parentParams = req.params; + var parentUrl = req.baseUrl || ''; + var done = restore(out, req, 'baseUrl', 'next', 'params'); + + // setup next layer + req.next = next; + + // for options requests, respond with a default if nothing else responds + if (req.method === 'OPTIONS') { + done = wrap(done, function(old, err) { + if (err || options.length === 0) return old(err); + sendOptionsResponse(res, options, old); + }); + } + + // setup basic req values + req.baseUrl = parentUrl; + req.originalUrl = req.originalUrl || req.url; + + next(); + + function next(err) { + var layerError = err === 'route' + ? null + : err; + + // remove added slash + if (slashAdded) { + req.url = req.url.substr(1); + slashAdded = false; + } + + // restore altered req.url + if (removed.length !== 0) { + req.baseUrl = parentUrl; + req.url = protohost + removed + req.url.substr(protohost.length); + removed = ''; + } + + // signal to exit router + if (layerError === 'router') { + setImmediate(done, null) + return + } + + // no more matching layers + if (idx >= stack.length) { + setImmediate(done, layerError); + return; + } + + // get pathname of request + var path = getPathname(req); + + if (path == null) { + return done(layerError); + } + + // find next matching layer + var layer; + var match; + var route; + + while (match !== true && idx < stack.length) { + layer = stack[idx++]; + match = matchLayer(layer, path); + route = layer.route; + + if (typeof match !== 'boolean') { + // hold on to layerError + layerError = layerError || match; + } + + if (match !== true) { + continue; + } + + if (!route) { + // process non-route handlers normally + continue; + } + + if (layerError) { + // routes do not match with a pending error + match = false; + continue; + } + + var method = req.method; + var has_method = route._handles_method(method); + + // build up automatic options response + if (!has_method && method === 'OPTIONS') { + appendMethods(options, route._options()); + } + + // don't even bother matching route + if (!has_method && method !== 'HEAD') { + match = false; + continue; + } + } + + // no match + if (match !== true) { + return done(layerError); + } + + // store route for dispatch on change + if (route) { + req.route = route; + } + + // Capture one-time layer values + req.params = self.mergeParams + ? mergeParams(layer.params, parentParams) + : layer.params; + var layerPath = layer.path; + + // this should be done for the layer + self.process_params(layer, paramcalled, req, res, function (err) { + if (err) { + return next(layerError || err); + } + + if (route) { + return layer.handle_request(req, res, next); + } + + trim_prefix(layer, layerError, layerPath, path); + }); + } + + function trim_prefix(layer, layerError, layerPath, path) { + if (layerPath.length !== 0) { + // Validate path breaks on a path separator + var c = path[layerPath.length] + if (c && c !== '/' && c !== '.') return next(layerError) + + // Trim off the part of the url that matches the route + // middleware (.use stuff) needs to have the path stripped + debug('trim prefix (%s) from url %s', layerPath, req.url); + removed = layerPath; + req.url = protohost + req.url.substr(protohost.length + removed.length); + + // Ensure leading slash + if (!protohost && req.url[0] !== '/') { + req.url = '/' + req.url; + slashAdded = true; + } + + // Setup base URL (no trailing slash) + req.baseUrl = parentUrl + (removed[removed.length - 1] === '/' + ? removed.substring(0, removed.length - 1) + : removed); + } + + debug('%s %s : %s', layer.name, layerPath, req.originalUrl); + + if (layerError) { + layer.handle_error(layerError, req, res, next); + } else { + layer.handle_request(req, res, next); + } + } +}; + +/** + * Process any parameters for the layer. + * @private + */ + +proto.process_params = function process_params(layer, called, req, res, done) { + var params = this.params; + + // captured parameters from the layer, keys and values + var keys = layer.keys; + + // fast track + if (!keys || keys.length === 0) { + return done(); + } + + var i = 0; + var name; + var paramIndex = 0; + var key; + var paramVal; + var paramCallbacks; + var paramCalled; + + // process params in order + // param callbacks can be async + function param(err) { + if (err) { + return done(err); + } + + if (i >= keys.length ) { + return done(); + } + + paramIndex = 0; + key = keys[i++]; + name = key.name; + paramVal = req.params[name]; + paramCallbacks = params[name]; + paramCalled = called[name]; + + if (paramVal === undefined || !paramCallbacks) { + return param(); + } + + // param previously called with same value or error occurred + if (paramCalled && (paramCalled.match === paramVal + || (paramCalled.error && paramCalled.error !== 'route'))) { + // restore value + req.params[name] = paramCalled.value; + + // next param + return param(paramCalled.error); + } + + called[name] = paramCalled = { + error: null, + match: paramVal, + value: paramVal + }; + + paramCallback(); + } + + // single param callbacks + function paramCallback(err) { + var fn = paramCallbacks[paramIndex++]; + + // store updated value + paramCalled.value = req.params[key.name]; + + if (err) { + // store error + paramCalled.error = err; + param(err); + return; + } + + if (!fn) return param(); + + try { + fn(req, res, paramCallback, paramVal, key.name); + } catch (e) { + paramCallback(e); + } + } + + param(); +}; + +/** + * Use the given middleware function, with optional path, defaulting to "/". + * + * Use (like `.all`) will run for any http METHOD, but it will not add + * handlers for those methods so OPTIONS requests will not consider `.use` + * functions even if they could respond. + * + * The other difference is that _route_ path is stripped and not visible + * to the handler function. The main effect of this feature is that mounted + * handlers can operate without any code changes regardless of the "prefix" + * pathname. + * + * @public + */ + +proto.use = function use(fn) { + var offset = 0; + var path = '/'; + + // default path to '/' + // disambiguate router.use([fn]) + if (typeof fn !== 'function') { + var arg = fn; + + while (Array.isArray(arg) && arg.length !== 0) { + arg = arg[0]; + } + + // first arg is the path + if (typeof arg !== 'function') { + offset = 1; + path = fn; + } + } + + var callbacks = flatten(slice.call(arguments, offset)); + + if (callbacks.length === 0) { + throw new TypeError('Router.use() requires a middleware function') + } + + for (var i = 0; i < callbacks.length; i++) { + var fn = callbacks[i]; + + if (typeof fn !== 'function') { + throw new TypeError('Router.use() requires a middleware function but got a ' + gettype(fn)) + } + + // add the middleware + debug('use %o %s', path, fn.name || '<anonymous>') + + var layer = new Layer(path, { + sensitive: this.caseSensitive, + strict: false, + end: false + }, fn); + + layer.route = undefined; + + this.stack.push(layer); + } + + return this; +}; + +/** + * Create a new Route for the given path. + * + * Each route contains a separate middleware stack and VERB handlers. + * + * See the Route api documentation for details on adding handlers + * and middleware to routes. + * + * @param {String} path + * @return {Route} + * @public + */ + +proto.route = function route(path) { + var route = new Route(path); + + var layer = new Layer(path, { + sensitive: this.caseSensitive, + strict: this.strict, + end: true + }, route.dispatch.bind(route)); + + layer.route = route; + + this.stack.push(layer); + return route; +}; + +// create Router#VERB functions +methods.concat('all').forEach(function(method){ + proto[method] = function(path){ + var route = this.route(path) + route[method].apply(route, slice.call(arguments, 1)); + return this; + }; +}); + +// append methods to a list of methods +function appendMethods(list, addition) { + for (var i = 0; i < addition.length; i++) { + var method = addition[i]; + if (list.indexOf(method) === -1) { + list.push(method); + } + } +} + +// get pathname of request +function getPathname(req) { + try { + return parseUrl(req).pathname; + } catch (err) { + return undefined; + } +} + +// Get get protocol + host for a URL +function getProtohost(url) { + if (typeof url !== 'string' || url.length === 0 || url[0] === '/') { + return undefined + } + + var searchIndex = url.indexOf('?') + var pathLength = searchIndex !== -1 + ? searchIndex + : url.length + var fqdnIndex = url.substr(0, pathLength).indexOf('://') + + return fqdnIndex !== -1 + ? url.substr(0, url.indexOf('/', 3 + fqdnIndex)) + : undefined +} + +// get type for error message +function gettype(obj) { + var type = typeof obj; + + if (type !== 'object') { + return type; + } + + // inspect [[Class]] for objects + return toString.call(obj) + .replace(objectRegExp, '$1'); +} + +/** + * Match path to a layer. + * + * @param {Layer} layer + * @param {string} path + * @private + */ + +function matchLayer(layer, path) { + try { + return layer.match(path); + } catch (err) { + return err; + } +} + +// merge params with parent params +function mergeParams(params, parent) { + if (typeof parent !== 'object' || !parent) { + return params; + } + + // make copy of parent for base + var obj = mixin({}, parent); + + // simple non-numeric merging + if (!(0 in params) || !(0 in parent)) { + return mixin(obj, params); + } + + var i = 0; + var o = 0; + + // determine numeric gaps + while (i in params) { + i++; + } + + while (o in parent) { + o++; + } + + // offset numeric indices in params before merge + for (i--; i >= 0; i--) { + params[i + o] = params[i]; + + // create holes for the merge when necessary + if (i < o) { + delete params[i]; + } + } + + return mixin(obj, params); +} + +// restore obj props after function +function restore(fn, obj) { + var props = new Array(arguments.length - 2); + var vals = new Array(arguments.length - 2); + + for (var i = 0; i < props.length; i++) { + props[i] = arguments[i + 2]; + vals[i] = obj[props[i]]; + } + + return function () { + // restore vals + for (var i = 0; i < props.length; i++) { + obj[props[i]] = vals[i]; + } + + return fn.apply(this, arguments); + }; +} + +// send an OPTIONS response +function sendOptionsResponse(res, options, next) { + try { + var body = options.join(','); + res.set('Allow', body); + res.send(body); + } catch (err) { + next(err); + } +} + +// wrap a function +function wrap(old, fn) { + return function proxy() { + var args = new Array(arguments.length + 1); + + args[0] = old; + for (var i = 0, len = arguments.length; i < len; i++) { + args[i + 1] = arguments[i]; + } + + fn.apply(this, args); + }; +} diff --git a/node_modules/express/lib/router/layer.js b/node_modules/express/lib/router/layer.js new file mode 100644 index 0000000..4dc8e86 --- /dev/null +++ b/node_modules/express/lib/router/layer.js @@ -0,0 +1,181 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var pathRegexp = require('path-to-regexp'); +var debug = require('debug')('express:router:layer'); + +/** + * Module variables. + * @private + */ + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +/** + * Module exports. + * @public + */ + +module.exports = Layer; + +function Layer(path, options, fn) { + if (!(this instanceof Layer)) { + return new Layer(path, options, fn); + } + + debug('new %o', path) + var opts = options || {}; + + this.handle = fn; + this.name = fn.name || '<anonymous>'; + this.params = undefined; + this.path = undefined; + this.regexp = pathRegexp(path, this.keys = [], opts); + + // set fast path flags + this.regexp.fast_star = path === '*' + this.regexp.fast_slash = path === '/' && opts.end === false +} + +/** + * Handle the error for the layer. + * + * @param {Error} error + * @param {Request} req + * @param {Response} res + * @param {function} next + * @api private + */ + +Layer.prototype.handle_error = function handle_error(error, req, res, next) { + var fn = this.handle; + + if (fn.length !== 4) { + // not a standard error handler + return next(error); + } + + try { + fn(error, req, res, next); + } catch (err) { + next(err); + } +}; + +/** + * Handle the request for the layer. + * + * @param {Request} req + * @param {Response} res + * @param {function} next + * @api private + */ + +Layer.prototype.handle_request = function handle(req, res, next) { + var fn = this.handle; + + if (fn.length > 3) { + // not a standard request handler + return next(); + } + + try { + fn(req, res, next); + } catch (err) { + next(err); + } +}; + +/** + * Check if this route matches `path`, if so + * populate `.params`. + * + * @param {String} path + * @return {Boolean} + * @api private + */ + +Layer.prototype.match = function match(path) { + var match + + if (path != null) { + // fast path non-ending match for / (any path matches) + if (this.regexp.fast_slash) { + this.params = {} + this.path = '' + return true + } + + // fast path for * (everything matched in a param) + if (this.regexp.fast_star) { + this.params = {'0': decode_param(path)} + this.path = path + return true + } + + // match the path + match = this.regexp.exec(path) + } + + if (!match) { + this.params = undefined; + this.path = undefined; + return false; + } + + // store values + this.params = {}; + this.path = match[0] + + var keys = this.keys; + var params = this.params; + + for (var i = 1; i < match.length; i++) { + var key = keys[i - 1]; + var prop = key.name; + var val = decode_param(match[i]) + + if (val !== undefined || !(hasOwnProperty.call(params, prop))) { + params[prop] = val; + } + } + + return true; +}; + +/** + * Decode param value. + * + * @param {string} val + * @return {string} + * @private + */ + +function decode_param(val) { + if (typeof val !== 'string' || val.length === 0) { + return val; + } + + try { + return decodeURIComponent(val); + } catch (err) { + if (err instanceof URIError) { + err.message = 'Failed to decode param \'' + val + '\''; + err.status = err.statusCode = 400; + } + + throw err; + } +} diff --git a/node_modules/express/lib/router/route.js b/node_modules/express/lib/router/route.js new file mode 100644 index 0000000..178df0d --- /dev/null +++ b/node_modules/express/lib/router/route.js @@ -0,0 +1,216 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var debug = require('debug')('express:router:route'); +var flatten = require('array-flatten'); +var Layer = require('./layer'); +var methods = require('methods'); + +/** + * Module variables. + * @private + */ + +var slice = Array.prototype.slice; +var toString = Object.prototype.toString; + +/** + * Module exports. + * @public + */ + +module.exports = Route; + +/** + * Initialize `Route` with the given `path`, + * + * @param {String} path + * @public + */ + +function Route(path) { + this.path = path; + this.stack = []; + + debug('new %o', path) + + // route handlers for various http methods + this.methods = {}; +} + +/** + * Determine if the route handles a given method. + * @private + */ + +Route.prototype._handles_method = function _handles_method(method) { + if (this.methods._all) { + return true; + } + + var name = method.toLowerCase(); + + if (name === 'head' && !this.methods['head']) { + name = 'get'; + } + + return Boolean(this.methods[name]); +}; + +/** + * @return {Array} supported HTTP methods + * @private + */ + +Route.prototype._options = function _options() { + var methods = Object.keys(this.methods); + + // append automatic head + if (this.methods.get && !this.methods.head) { + methods.push('head'); + } + + for (var i = 0; i < methods.length; i++) { + // make upper case + methods[i] = methods[i].toUpperCase(); + } + + return methods; +}; + +/** + * dispatch req, res into this route + * @private + */ + +Route.prototype.dispatch = function dispatch(req, res, done) { + var idx = 0; + var stack = this.stack; + if (stack.length === 0) { + return done(); + } + + var method = req.method.toLowerCase(); + if (method === 'head' && !this.methods['head']) { + method = 'get'; + } + + req.route = this; + + next(); + + function next(err) { + // signal to exit route + if (err && err === 'route') { + return done(); + } + + // signal to exit router + if (err && err === 'router') { + return done(err) + } + + var layer = stack[idx++]; + if (!layer) { + return done(err); + } + + if (layer.method && layer.method !== method) { + return next(err); + } + + if (err) { + layer.handle_error(err, req, res, next); + } else { + layer.handle_request(req, res, next); + } + } +}; + +/** + * Add a handler for all HTTP verbs to this route. + * + * Behaves just like middleware and can respond or call `next` + * to continue processing. + * + * You can use multiple `.all` call to add multiple handlers. + * + * function check_something(req, res, next){ + * next(); + * }; + * + * function validate_user(req, res, next){ + * next(); + * }; + * + * route + * .all(validate_user) + * .all(check_something) + * .get(function(req, res, next){ + * res.send('hello world'); + * }); + * + * @param {function} handler + * @return {Route} for chaining + * @api public + */ + +Route.prototype.all = function all() { + var handles = flatten(slice.call(arguments)); + + for (var i = 0; i < handles.length; i++) { + var handle = handles[i]; + + if (typeof handle !== 'function') { + var type = toString.call(handle); + var msg = 'Route.all() requires a callback function but got a ' + type + throw new TypeError(msg); + } + + var layer = Layer('/', {}, handle); + layer.method = undefined; + + this.methods._all = true; + this.stack.push(layer); + } + + return this; +}; + +methods.forEach(function(method){ + Route.prototype[method] = function(){ + var handles = flatten(slice.call(arguments)); + + for (var i = 0; i < handles.length; i++) { + var handle = handles[i]; + + if (typeof handle !== 'function') { + var type = toString.call(handle); + var msg = 'Route.' + method + '() requires a callback function but got a ' + type + throw new Error(msg); + } + + debug('%s %o', method, this.path) + + var layer = Layer('/', {}, handle); + layer.method = method; + + this.methods[method] = true; + this.stack.push(layer); + } + + return this; + }; +}); diff --git a/node_modules/express/lib/utils.js b/node_modules/express/lib/utils.js new file mode 100644 index 0000000..bd81ac7 --- /dev/null +++ b/node_modules/express/lib/utils.js @@ -0,0 +1,306 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @api private + */ + +var Buffer = require('safe-buffer').Buffer +var contentDisposition = require('content-disposition'); +var contentType = require('content-type'); +var deprecate = require('depd')('express'); +var flatten = require('array-flatten'); +var mime = require('send').mime; +var etag = require('etag'); +var proxyaddr = require('proxy-addr'); +var qs = require('qs'); +var querystring = require('querystring'); + +/** + * Return strong ETag for `body`. + * + * @param {String|Buffer} body + * @param {String} [encoding] + * @return {String} + * @api private + */ + +exports.etag = createETagGenerator({ weak: false }) + +/** + * Return weak ETag for `body`. + * + * @param {String|Buffer} body + * @param {String} [encoding] + * @return {String} + * @api private + */ + +exports.wetag = createETagGenerator({ weak: true }) + +/** + * Check if `path` looks absolute. + * + * @param {String} path + * @return {Boolean} + * @api private + */ + +exports.isAbsolute = function(path){ + if ('/' === path[0]) return true; + if (':' === path[1] && ('\\' === path[2] || '/' === path[2])) return true; // Windows device path + if ('\\\\' === path.substring(0, 2)) return true; // Microsoft Azure absolute path +}; + +/** + * Flatten the given `arr`. + * + * @param {Array} arr + * @return {Array} + * @api private + */ + +exports.flatten = deprecate.function(flatten, + 'utils.flatten: use array-flatten npm module instead'); + +/** + * Normalize the given `type`, for example "html" becomes "text/html". + * + * @param {String} type + * @return {Object} + * @api private + */ + +exports.normalizeType = function(type){ + return ~type.indexOf('/') + ? acceptParams(type) + : { value: mime.lookup(type), params: {} }; +}; + +/** + * Normalize `types`, for example "html" becomes "text/html". + * + * @param {Array} types + * @return {Array} + * @api private + */ + +exports.normalizeTypes = function(types){ + var ret = []; + + for (var i = 0; i < types.length; ++i) { + ret.push(exports.normalizeType(types[i])); + } + + return ret; +}; + +/** + * Generate Content-Disposition header appropriate for the filename. + * non-ascii filenames are urlencoded and a filename* parameter is added + * + * @param {String} filename + * @return {String} + * @api private + */ + +exports.contentDisposition = deprecate.function(contentDisposition, + 'utils.contentDisposition: use content-disposition npm module instead'); + +/** + * Parse accept params `str` returning an + * object with `.value`, `.quality` and `.params`. + * also includes `.originalIndex` for stable sorting + * + * @param {String} str + * @return {Object} + * @api private + */ + +function acceptParams(str, index) { + var parts = str.split(/ *; */); + var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index }; + + for (var i = 1; i < parts.length; ++i) { + var pms = parts[i].split(/ *= */); + if ('q' === pms[0]) { + ret.quality = parseFloat(pms[1]); + } else { + ret.params[pms[0]] = pms[1]; + } + } + + return ret; +} + +/** + * Compile "etag" value to function. + * + * @param {Boolean|String|Function} val + * @return {Function} + * @api private + */ + +exports.compileETag = function(val) { + var fn; + + if (typeof val === 'function') { + return val; + } + + switch (val) { + case true: + fn = exports.wetag; + break; + case false: + break; + case 'strong': + fn = exports.etag; + break; + case 'weak': + fn = exports.wetag; + break; + default: + throw new TypeError('unknown value for etag function: ' + val); + } + + return fn; +} + +/** + * Compile "query parser" value to function. + * + * @param {String|Function} val + * @return {Function} + * @api private + */ + +exports.compileQueryParser = function compileQueryParser(val) { + var fn; + + if (typeof val === 'function') { + return val; + } + + switch (val) { + case true: + fn = querystring.parse; + break; + case false: + fn = newObject; + break; + case 'extended': + fn = parseExtendedQueryString; + break; + case 'simple': + fn = querystring.parse; + break; + default: + throw new TypeError('unknown value for query parser function: ' + val); + } + + return fn; +} + +/** + * Compile "proxy trust" value to function. + * + * @param {Boolean|String|Number|Array|Function} val + * @return {Function} + * @api private + */ + +exports.compileTrust = function(val) { + if (typeof val === 'function') return val; + + if (val === true) { + // Support plain true/false + return function(){ return true }; + } + + if (typeof val === 'number') { + // Support trusting hop count + return function(a, i){ return i < val }; + } + + if (typeof val === 'string') { + // Support comma-separated values + val = val.split(/ *, */); + } + + return proxyaddr.compile(val || []); +} + +/** + * Set the charset in a given Content-Type string. + * + * @param {String} type + * @param {String} charset + * @return {String} + * @api private + */ + +exports.setCharset = function setCharset(type, charset) { + if (!type || !charset) { + return type; + } + + // parse type + var parsed = contentType.parse(type); + + // set charset + parsed.parameters.charset = charset; + + // format type + return contentType.format(parsed); +}; + +/** + * Create an ETag generator function, generating ETags with + * the given options. + * + * @param {object} options + * @return {function} + * @private + */ + +function createETagGenerator (options) { + return function generateETag (body, encoding) { + var buf = !Buffer.isBuffer(body) + ? Buffer.from(body, encoding) + : body + + return etag(buf, options) + } +} + +/** + * Parse an extended query string with qs. + * + * @return {Object} + * @private + */ + +function parseExtendedQueryString(str) { + return qs.parse(str, { + allowPrototypes: true + }); +} + +/** + * Return new empty object. + * + * @return {Object} + * @api private + */ + +function newObject() { + return {}; +} diff --git a/node_modules/express/lib/view.js b/node_modules/express/lib/view.js new file mode 100644 index 0000000..cf101ca --- /dev/null +++ b/node_modules/express/lib/view.js @@ -0,0 +1,182 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var debug = require('debug')('express:view'); +var path = require('path'); +var fs = require('fs'); + +/** + * Module variables. + * @private + */ + +var dirname = path.dirname; +var basename = path.basename; +var extname = path.extname; +var join = path.join; +var resolve = path.resolve; + +/** + * Module exports. + * @public + */ + +module.exports = View; + +/** + * Initialize a new `View` with the given `name`. + * + * Options: + * + * - `defaultEngine` the default template engine name + * - `engines` template engine require() cache + * - `root` root path for view lookup + * + * @param {string} name + * @param {object} options + * @public + */ + +function View(name, options) { + var opts = options || {}; + + this.defaultEngine = opts.defaultEngine; + this.ext = extname(name); + this.name = name; + this.root = opts.root; + + if (!this.ext && !this.defaultEngine) { + throw new Error('No default engine was specified and no extension was provided.'); + } + + var fileName = name; + + if (!this.ext) { + // get extension from default engine name + this.ext = this.defaultEngine[0] !== '.' + ? '.' + this.defaultEngine + : this.defaultEngine; + + fileName += this.ext; + } + + if (!opts.engines[this.ext]) { + // load engine + var mod = this.ext.substr(1) + debug('require "%s"', mod) + + // default engine export + var fn = require(mod).__express + + if (typeof fn !== 'function') { + throw new Error('Module "' + mod + '" does not provide a view engine.') + } + + opts.engines[this.ext] = fn + } + + // store loaded engine + this.engine = opts.engines[this.ext]; + + // lookup path + this.path = this.lookup(fileName); +} + +/** + * Lookup view by the given `name` + * + * @param {string} name + * @private + */ + +View.prototype.lookup = function lookup(name) { + var path; + var roots = [].concat(this.root); + + debug('lookup "%s"', name); + + for (var i = 0; i < roots.length && !path; i++) { + var root = roots[i]; + + // resolve the path + var loc = resolve(root, name); + var dir = dirname(loc); + var file = basename(loc); + + // resolve the file + path = this.resolve(dir, file); + } + + return path; +}; + +/** + * Render with the given options. + * + * @param {object} options + * @param {function} callback + * @private + */ + +View.prototype.render = function render(options, callback) { + debug('render "%s"', this.path); + this.engine(this.path, options, callback); +}; + +/** + * Resolve the file within the given directory. + * + * @param {string} dir + * @param {string} file + * @private + */ + +View.prototype.resolve = function resolve(dir, file) { + var ext = this.ext; + + // <path>.<ext> + var path = join(dir, file); + var stat = tryStat(path); + + if (stat && stat.isFile()) { + return path; + } + + // <path>/index.<ext> + path = join(dir, basename(file, ext), 'index' + ext); + stat = tryStat(path); + + if (stat && stat.isFile()) { + return path; + } +}; + +/** + * Return a stat, maybe. + * + * @param {string} path + * @return {fs.Stats} + * @private + */ + +function tryStat(path) { + debug('stat "%s"', path); + + try { + return fs.statSync(path); + } catch (e) { + return undefined; + } +} diff --git a/node_modules/express/package.json b/node_modules/express/package.json new file mode 100644 index 0000000..eff3463 --- /dev/null +++ b/node_modules/express/package.json @@ -0,0 +1,201 @@ +{ + "_args": [ + [ + { + "raw": "express", + "scope": null, + "escapedName": "express", + "name": "express", + "rawSpec": "", + "spec": "latest", + "type": "tag" + }, + "/mnt/e/Yaroslav/Documents/Webs/nodejs/checkers" + ] + ], + "_from": "express@latest", + "_id": "express@4.16.2", + "_inCache": true, + "_location": "/express", + "_nodeVersion": "6.11.1", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/express-4.16.2.tgz_1507605225187_0.6328138182871044" + }, + "_npmUser": { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + "_npmVersion": "3.10.10", + "_phantomChildren": {}, + "_requested": { + "raw": "express", + "scope": null, + "escapedName": "express", + "name": "express", + "rawSpec": "", + "spec": "latest", + "type": "tag" + }, + "_requiredBy": [ + "#USER", + "/" + ], + "_resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz", + "_shasum": "e35c6dfe2d64b7dca0a5cd4f21781be3299e076c", + "_shrinkwrap": null, + "_spec": "express", + "_where": "/mnt/e/Yaroslav/Documents/Webs/nodejs/checkers", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "bugs": { + "url": "https://github.com/expressjs/express/issues" + }, + "contributors": [ + { + "name": "Aaron Heckmann", + "email": "aaron.heckmann+github@gmail.com" + }, + { + "name": "Ciaran Jessup", + "email": "ciaranj@gmail.com" + }, + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Guillermo Rauch", + "email": "rauchg@gmail.com" + }, + { + "name": "Jonathan Ong", + "email": "me@jongleberry.com" + }, + { + "name": "Roman Shtylman", + "email": "shtylman+expressjs@gmail.com" + }, + { + "name": "Young Jae Sim", + "email": "hanul@hanul.me" + } + ], + "dependencies": { + "accepts": "~1.3.4", + "array-flatten": "1.1.1", + "body-parser": "1.18.2", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.1", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.0", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.2", + "qs": "6.5.1", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.1", + "send": "0.16.1", + "serve-static": "1.13.1", + "setprototypeof": "1.1.0", + "statuses": "~1.3.1", + "type-is": "~1.6.15", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "description": "Fast, unopinionated, minimalist web framework", + "devDependencies": { + "after": "0.8.2", + "connect-redis": "~2.4.1", + "cookie-parser": "~1.4.3", + "cookie-session": "1.3.2", + "ejs": "2.5.7", + "eslint": "2.13.1", + "express-session": "1.15.6", + "hbs": "4.0.1", + "istanbul": "0.4.5", + "marked": "0.3.6", + "method-override": "2.3.10", + "mocha": "3.5.3", + "morgan": "1.9.0", + "multiparty": "4.1.3", + "pbkdf2-password": "1.2.1", + "should": "13.1.0", + "supertest": "1.2.0", + "vhost": "~3.0.2" + }, + "directories": {}, + "dist": { + "shasum": "e35c6dfe2d64b7dca0a5cd4f21781be3299e076c", + "tarball": "https://registry.npmjs.org/express/-/express-4.16.2.tgz" + }, + "engines": { + "node": ">= 0.10.0" + }, + "files": [ + "LICENSE", + "History.md", + "Readme.md", + "index.js", + "lib/" + ], + "gitHead": "351396f971280ab79faddcf9782ea50f4e88358d", + "homepage": "http://expressjs.com/", + "keywords": [ + "express", + "framework", + "sinatra", + "web", + "rest", + "restful", + "router", + "app", + "api" + ], + "license": "MIT", + "maintainers": [ + { + "name": "hacksparrow", + "email": "captain@hacksparrow.com" + }, + { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + }, + { + "name": "jasnell", + "email": "jasnell@gmail.com" + }, + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + } + ], + "name": "express", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/expressjs/express.git" + }, + "scripts": { + "lint": "eslint .", + "test": "mocha --require test/support/env --reporter spec --bail --check-leaks --no-exit test/ test/acceptance/", + "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks --no-exit test/ test/acceptance/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks --no-exit test/ test/acceptance/", + "test-tap": "mocha --require test/support/env --reporter tap --check-leaks --no-exit test/ test/acceptance/" + }, + "version": "4.16.2" +} |