Comparar commits

...

46 Commits

Autor SHA1 Mensagem Data
TJ Holowaychuk d853c833f0 Release 3.1.0 2013-01-25 20:28:58 -08:00
TJ Holowaychuk 03a796c460 Merge pull request #1478 from ericf/settings-view-engine-test
Add test for "view engine" setting with leading ".".
2013-01-24 08:33:24 -08:00
Eric Ferraiuolo 75e47f2883 Add test for "view engine" setting with leading ".". 2013-01-24 00:55:55 -05:00
TJ Holowaychuk a4b2e48dfe refactor res.set() array support 2013-01-23 20:31:25 -08:00
TJ Holowaychuk 57cda1578d Merge pull request #1477 from gmethvin/set_array
Allow setting an array of header values in the response
2013-01-23 20:29:17 -08:00
TJ Holowaychuk 6b1d7a94ff Merge branch 'integrate' 2013-01-23 20:21:43 -08:00
TJ Holowaychuk 49abd7bec1 merge 2013-01-23 20:21:36 -08:00
TJ Holowaychuk 0ebebd80fe Merge pull request #1466 from ericf/settings-view-engine
Add full extname support to the "view engine" setting; e.g., ".jade".
2013-01-23 20:17:42 -08:00
TJ Holowaychuk d157d47c6e add node 0.8.x to travis.yml 2013-01-23 20:16:34 -08:00
TJ Holowaychuk e3ac2c5b02 change req.subdomain styling back 2013-01-23 20:11:14 -08:00
TJ Holowaychuk cd54faa4af move "subdomain offset" defaulting to config 2013-01-23 20:10:29 -08:00
TJ Holowaychuk 5beb1c4e30 Merge pull request #1475 from gmethvin/subdomain_offset
Add subdomain offset setting
2013-01-23 20:09:25 -08:00
Greg Methvin 4031aaa591 Allow setting an array of header values in the response
Make setting multiple header values using an array work as expected.
If the header value is an array, coerce the values to strings instead
of the entire array.

Fixes #1419.
2013-01-22 18:32:22 -08:00
Greg Methvin ba00e23630 Add subdomain offset setting
Add a setting "subdomain offset" for the app, which can be used to
change the behavior of req.subdomains. This is useful when our "base"
domain contains more than two parts, e.g. example.co.uk, and also
when we are running locally with domains like xxx.local.

The default behavior is still to return all but the last two parts.
2013-01-20 19:27:58 -08:00
TJ Holowaychuk 8beb1f21ef change prev commit to use app.enabled() 2013-01-18 14:38:50 -08:00
TJ Holowaychuk fa8eec449b use app.get() for x-powered-by setting
see: http://stackoverflow.com/questions/14285050/broke-up-express-app-into-submodules-now-my-custom-x-powered-by-does-not-wor
2013-01-18 14:36:52 -08:00
TJ Holowaychuk ab75fa048e refactor vhost example 2013-01-14 09:51:56 +01:00
TJ Holowaychuk bb29da5980 refactor vhost example 2013-01-13 11:32:53 -08:00
Julian Gruber a4d7b75129 implemented res.location 2013-01-13 16:07:11 +01:00
Eric Ferraiuolo 0fdceb3de3 Add full extname support to the "view engine" setting; e.g., ".jade".
This allows View to support a `defaultEngine` (a.k.a. an app's
"view engine" setting) which contains a ".", for example:

```
app.engine('.jade', jadeEngine);
app.set('view engine', '.jade');
```

This brings View's handling of template filename extensions to parity
with `app.engine()`.

This allows an app's "view engine" setting to be a full extension name,
including the ".".
2013-01-10 21:41:24 -05:00
TJ Holowaychuk 480d0064e1 Merge pull request #1462 from gmethvin/colon_auth
Allow colons in passwords for req.auth
2013-01-09 12:47:29 -08:00
Greg Methvin 17bf04d1ef Allow colons in passwords for req.auth
Passwords in basic auth can contain colons (as per RFC2617), while
usernames cannot, so assume everything after the colon is a password.
This makes req.auth return the correct value if the user uses a colon
in his password.
2013-01-06 03:02:40 -05:00
TJ Holowaychuk 3ab30210a2 Release 3.0.6 2013-01-04 18:52:04 -08:00
TJ Holowaychuk 14fcfdee7e update connect 2013-01-04 18:37:21 -08:00
TJ Holowaychuk d4e56c1fa2 Merge pull request #1458 from gmethvin/cookie_options
Don't mangle the options object in res.cookie
2013-01-03 12:25:57 -08:00
Greg Methvin 39ee6f8e79 Don't mangle the options object in res.cookie
Make a copy of the cookie options before mutating it to pass to
cookie.serialize. This prevents unexpected things from happening when
we try to use the same options object multiple times.

Also add a test to verify that the options object does not change
after a request is made.
2013-01-03 02:00:15 -05:00
TJ Holowaychuk 8d21f1e45c change router callback check error message
to read:

Error: .get() requires callback functions but got a [object String]
2012-12-29 08:52:33 -07:00
TJ Holowaychuk 618484a4fe Merge pull request #1454 from shtylman/router-http-methods
add http verbs methods to Router
2012-12-28 09:30:20 -08:00
Guillermo Rauch 64a234958a fix jsonp whitespace escape. Closes #1132 2012-12-28 10:24:55 -07:00
Roman Shtylman e4907ce8e8 add http verbs methods to Router
By having the method verbs available on the router, users can set up
disjoint routers and organized paths easier.

It is now possible to have a .js file export the router.middleware and
attach these paths using an `app.use('/path', middleware)` call. This
means that any routes written in the separate file do not need to have a
full path hardcoded as they can be mounted by the application anywhere.

This is already possible using `router.route(verb, args)` however is
needlessly verbose without this patch.
2012-12-25 16:43:56 -05:00
TJ Holowaychuk 33eaa8329c Release 3.0.5 2012-12-19 13:46:16 -08:00
TJ Holowaychuk 3c4fd57e51 Merge pull request #1451 from aweeks/fix-304-must-not-contain-body
Explicitly remove Transfer-Encoding header from 204 and 304 responses
2012-12-19 13:34:16 -08:00
Alex Weeks a1e42ac33f Explicitly remove Transfer-Encoding header from 204 and 304 responses
Per RFC 2616 §10.3.6 & §10.2.5 (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) "The [204/304] response MUST NOT contain a message-body, and thus is always terminated by the first empty line after the header fields."
2012-12-19 10:53:17 -08:00
Thorsten Lorenz ce7d7bfd8d add throwing when a non-function is passed to a route 2012-12-14 15:06:17 -08:00
TJ Holowaychuk 9bd86cdddc Revert "add 'etag' option"
This reverts commit 6f6eec7d8d.
2012-12-06 15:15:49 -08:00
TJ Holowaychuk 0117464ac2 Release 3.0.4 2012-12-05 17:10:59 -08:00
Max Riveiro 6f6eec7d8d add 'etag' option 2012-12-05 16:49:09 -08:00
TJ Holowaychuk a4e93c0fb8 update connect 2012-12-05 16:35:44 -08:00
TJ Holowaychuk e2ad0d3d6e merge 2012-11-21 08:46:36 -08:00
TJ Holowaychuk 763be5e631 Merge pull request #1426 from piscis/master
change crc generator because of license issue
2012-11-21 08:45:42 -08:00
TJ Holowaychuk c8526932f3 Merge branch 'master' of github.com:visionmedia/express 2012-11-21 08:43:13 -08:00
TJ Holowaychuk 5cf29a3d29 Merge pull request #1425 from gmethvin/encode_text_redirect
Escape URLs in text/plain res.redirect response
2012-11-21 08:42:33 -08:00
Alexander Pirsig 18a3cc03ee use buffer-crc32 module for ETag CRC generator 2012-11-21 12:44:07 +01:00
Greg Methvin ea5e254c7d Escape URLs in text/plain res.redirect response
Escape the URL printed by res.redirect using URL encoding. This
prevents some browsers (primarily old versions of IE) from attempting
to sniff the Content-Type and evaluate it as HTML, which causes a
cross-site scripting vulnerability.
2012-11-21 02:22:37 -05:00
TJ Holowaychuk 060653bd4c Merge branch 'master' of github.com:visionmedia/express 2012-11-20 14:25:30 -08:00
TJ Holowaychuk c70db96b06 Update examples/cors/index.js 2012-11-08 13:52:20 -08:00
25 arquivos alterados com 686 adições e 362 exclusões
+2 -1
Ver Arquivo
@@ -1,3 +1,4 @@
language: node_js
node_js:
- 0.6
- 0.6
- 0.8
+119 -84
Ver Arquivo
@@ -1,23 +1,58 @@
3.0.3 / 2012-11-13
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
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
3.0.1 / 2012-11-01
==================
* update connect
3.0.0 / 2012-10-23
3.0.0 / 2012-10-23
==================
* add `make clean`
@@ -32,7 +67,7 @@
* fix view-locals example. Closes #1370
* fix route-separation example
3.0.0rc5 / 2012-09-18
3.0.0rc5 / 2012-09-18
==================
* update connect
@@ -41,7 +76,7 @@
* 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
3.0.0rc4 / 2012-08-30
==================
* add `res.jsonp()`. Closes #1307
@@ -54,14 +89,14 @@
* fix jsonp callback char restrictions
* remove old OPTIONS default response
3.0.0rc3 / 2012-08-13
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
3.0.0rc2 / 2012-08-03
==================
* add CORS example
@@ -70,7 +105,7 @@
* fix: escape `res.redirect()` link
* fix vhost example
3.0.0rc1 / 2012-07-24
3.0.0rc1 / 2012-07-24
==================
* add more examples to view-locals
@@ -81,12 +116,12 @@
* fix `express(1)` -h flag, use -H for hogan. Closes #1245
* fix `res.sendfile()` socket error handling regression
3.0.0beta7 / 2012-07-16
3.0.0beta7 / 2012-07-16
==================
* update connect dep for `send()` root normalization regression
3.0.0beta6 / 2012-07-13
3.0.0beta6 / 2012-07-13
==================
* add `err.view` property for view errors. Closes #1226
@@ -96,7 +131,7 @@
* 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
3.0.0beta5 / 2012-07-03
==================
* add "make check" support
@@ -107,7 +142,7 @@
* update auth example to utilize cores pbkdf2
* updated tests to use "supertest"
3.0.0beta4 / 2012-06-25
3.0.0beta4 / 2012-06-25
==================
* Added `req.auth`
@@ -119,7 +154,7 @@
* Revert "Added + support to the router"
* Fixed `res.send()` freshness check, respect res.statusCode
3.0.0beta3 / 2012-06-15
3.0.0beta3 / 2012-06-15
==================
* Added hogan `--hjs` to express(1) [nullfirm]
@@ -128,7 +163,7 @@
* Changed: `res.send()` always checks freshness
* Fixed: expose connects mime module. Cloases #1165
3.0.0beta2 / 2012-06-06
3.0.0beta2 / 2012-06-06
==================
* Added `+` support to the router
@@ -136,13 +171,13 @@
* Changed `req.param()` to check route first
* Update connect dep
3.0.0beta1 / 2012-06-01
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
3.0.0alpha5 / 2012-05-30
==================
* Added `req.ip`
@@ -151,14 +186,14 @@
* Changed: dont reverse `req.ips`
* Fixed "trust proxy" setting check for `req.ips`
3.0.0alpha4 / 2012-05-09
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
3.0.0alpha3 / 2012-05-04
==================
* Added public `app.routes`. Closes #887
@@ -173,7 +208,7 @@
* Changed: `make test` now runs unit / acceptance tests
* Fixed req/res proto inheritance
3.0.0alpha2 / 2012-04-26
3.0.0alpha2 / 2012-04-26
==================
* Added `make benchmark` back
@@ -189,7 +224,7 @@
* Fixed session example. Closes #1105
* Fixed generated express dep. Closes #1078
3.0.0alpha1 / 2012-04-15
3.0.0alpha1 / 2012-04-15
==================
* Added `app.locals.use(callback)`
@@ -244,54 +279,54 @@
* Fixed `res.sendfile()` with non-GET. Closes #723
* Fixed express(1) public dir for windows. Closes #866
2.5.9/ 2012-04-02
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
2.5.8 / 2012-02-08
==================
* Update mkdirp dep. Closes #991
2.5.7 / 2012-02-06
2.5.7 / 2012-02-06
==================
* Fixed `app.all` duplicate DELETE requests [mscdex]
2.5.6 / 2012-01-13
2.5.6 / 2012-01-13
==================
* Updated hamljs dev dep. Closes #953
2.5.5 / 2012-01-08
2.5.5 / 2012-01-08
==================
* Fixed: set `filename` on cached templates [matthewleon]
2.5.4 / 2012-01-02
2.5.4 / 2012-01-02
==================
* Fixed `express(1)` eol on 0.4.x. Closes #947
2.5.3 / 2011-12-30
2.5.3 / 2011-12-30
==================
* Fixed `req.is()` when a charset is present
2.5.2 / 2011-12-10
2.5.2 / 2011-12-10
==================
* Fixed: express(1) LF -> CRLF for windows
2.5.1 / 2011-11-17
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
2.5.0 / 2011-10-24
==================
* Added ./routes dir for generated app by default
@@ -300,7 +335,7 @@
* 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
2.4.7 / 2011-10-05
==================
* Added mkdirp to express(1). Closes #795
@@ -311,17 +346,17 @@
* Fixed `req.flash()`, only escape args
* Fixed absolute path checking on windows. Closes #829 [reported by andrewpmckenzie]
2.4.6 / 2011-08-22
2.4.6 / 2011-08-22
==================
* Fixed multiple param callback regression. Closes #824 [reported by TroyGoode]
2.4.5 / 2011-08-19
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.
* 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
@@ -329,25 +364,25 @@ Closes #805
* Dependency: `qs >= 0.3.1`
* Fixed `res.redirect()` on windows due to `join()` usage. Closes #808
2.4.4 / 2011-08-05
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
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
2.4.2. / 2011-07-06
==================
* Revert "removed jsonp stripping" for XSS
2.4.1 / 2011-07-06
2.4.1 / 2011-07-06
==================
* Added `res.json()` JSONP support. Closes #737
@@ -359,14 +394,14 @@ Closes #805
* Changed; default cookie path to "home" setting. Closes #731
* Removed _pids/logs_ creation from express(1)
2.4.0 / 2011-06-28
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
2.3.12 / 2011-06-22
==================
* \#express is now on freenode! come join!
@@ -378,7 +413,7 @@ Closes #805
* Fixed view layout bug. Closes #720
* Fixed; ignore body on 304. Closes #701
2.3.11 / 2011-06-04
2.3.11 / 2011-06-04
==================
* Added `npm test`
@@ -386,14 +421,14 @@ Closes #805
* Fixed; `express(1)` adds express as a dep
* Fixed; prune on `prepublish`
2.3.10 / 2011-05-27
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
2.3.9 / 2011-05-25
==================
* Fixed bug-ish with `../' in `res.partial()` calls
@@ -412,7 +447,7 @@ Closes #805
* Removed module.parent check from express(1) generated app. Closes #670
* Refactored router. Closes #639
2.3.6 / 2011-05-20
2.3.6 / 2011-05-20
==================
* Changed; using devDependencies instead of git submodules
@@ -420,30 +455,30 @@ Closes #805
* Fixed markdown example
* Fixed view caching, should not be enabled in development
2.3.5 / 2011-05-20
2.3.5 / 2011-05-20
==================
* Added export `.view` as alias for `.View`
2.3.4 / 2011-05-08
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
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
2.3.2 / 2011-04-27
==================
* Fixed view hints
2.3.1 / 2011-04-26
2.3.1 / 2011-04-26
==================
* Added `app.match()` as `app.match.all()`
@@ -453,7 +488,7 @@ Closes #805
* Fixed template caching collision issue. Closes #644
* Moved router over from connect and started refactor
2.3.0 / 2011-04-25
2.3.0 / 2011-04-25
==================
* Added options support to `res.clearCookie()`
@@ -462,18 +497,18 @@ Closes #805
* 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.
* 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
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
2.2.1 / 2011-04-04
==================
* Added `layout(path)` helper to change the layout within a view. Closes #610
@@ -487,7 +522,7 @@ Shaw]
* Removed `request` and `response` locals
* Changed; errorHandler page title is now `Express` instead of `Connect`
2.2.0 / 2011-03-30
2.2.0 / 2011-03-30
==================
* Added `app.lookup.VERB()`, ex `app.lookup.put('/user/:id')`. Closes #606
@@ -495,14 +530,14 @@ Shaw]
* Added `app.VERB(path)` as alias of `app.lookup.VERB()`.
* Dependency `connect >= 1.2.0`
2.1.1 / 2011-03-29
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
2.1.0 / 2011-03-24
==================
* Added `<root>/_?<name>` partial lookup support. Closes #447
@@ -513,20 +548,20 @@ Shaw]
* Fixed stylus example for latest version
* Fixed; wrap try/catch around `res.render()`
2.0.0 / 2011-03-17
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
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
2.0.0rc2 / 2011-03-17
==================
* Changed; `partial()` "locals" are now optional
@@ -535,14 +570,14 @@ Shaw]
* Fixed blog example
* Fixed `{req,res}.app` reference when mounting [Ben Weaver]
2.0.0rc / 2011-03-14
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
2.0.0beta3 / 2011-03-09
==================
* Added support for `res.contentType()` literal
@@ -560,13 +595,13 @@ Shaw]
* Fixed; default `res.send()` string charset to utf8
* Removed `Partial` constructor (not currently used)
2.0.0beta2 / 2011-03-07
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
2.0.0beta / 2011-03-03
==================
* Added HTTPS support
@@ -599,46 +634,46 @@ Shaw]
* Fixed; strip unsafe chars from jsonp callbacks
* Removed "stream threshold" setting
1.0.8 / 2011-03-01
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
1.0.7 / 2011-02-07
==================
* Fixed `render()` setting inheritance.
Mounted apps would not inherit "view engine"
1.0.6 / 2011-02-07
1.0.6 / 2011-02-07
==================
* Fixed `view engine` setting bug when period is in dirname
1.0.5 / 2011-02-05
1.0.5 / 2011-02-05
==================
* Added secret to generated app `session()` call
1.0.4 / 2011-02-05
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
1.0.3 / 2011-01-13
==================
* Remove unsafe characters from JSONP callback names [Ryan Grove]
1.0.2 / 2011-01-10
1.0.2 / 2011-01-10
==================
* Removed nested require, using `connect.router`
1.0.1 / 2010-12-29
1.0.1 / 2010-12-29
==================
* Fixed for middleware stacked via `createServer()`
@@ -646,7 +681,7 @@ Shaw]
would not have access to Express methods such as `res.send()`
or props like `req.query` etc.
1.0.0 / 2010-11-16
1.0.0 / 2010-11-16
==================
* Added; deduce partial object names from the last segment.
@@ -660,7 +695,7 @@ Shaw]
* 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
* 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.
@@ -673,7 +708,7 @@ Shaw]
* 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
1.0.0rc4 / 2010-10-14
==================
* Added _NODE_ENV_ support, _EXPRESS_ENV_ is deprecated and will be removed in 1.0.0
@@ -692,7 +727,7 @@ Shaw]
* Fixed; exposing _./support_ libs to examples so they can run without installs
* Fixed mvc example
1.0.0rc3 / 2010-09-20
1.0.0rc3 / 2010-09-20
==================
* Added confirmation for `express(1)` app generation. Closes #391
@@ -715,7 +750,7 @@ Shaw]
* Fixed bug messing with error handlers when `listenFD()` is called instead of `listen()`. [thanks guillermo]
1.0.0rc2 / 2010-08-17
1.0.0rc2 / 2010-08-17
==================
* Added `app.register()` for template engine mapping. Closes #390
@@ -728,7 +763,7 @@ Shaw]
* 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
* Fixed issue preventing error handlers from being defined anywhere. Closes #387
1.0.0rc / 2010-07-28
==================
@@ -746,7 +781,7 @@ Shaw]
* Fixed "home" setting
* Fixed middleware/router precedence issue. Closes #366
* Fixed; _configure()_ callbacks called immediately. Closes #368
1.0.0beta2 / 2010-07-23
==================
@@ -881,7 +916,7 @@ Shaw]
* Updated dependencies
* Removed set("session cookie") in favour of use(Session, { cookie: { ... }})
* Removed utils.mixin(); use Object#mergeDeep()
0.8.0 / 2010-03-19
==================
@@ -948,16 +983,16 @@ Shaw]
* 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
+1 -1
Ver Arquivo
@@ -1,4 +1,3 @@
/**
* Module dependencies.
*/
@@ -21,6 +20,7 @@ api.use(express.bodyParser());
*/
api.all('*', function(req, res, next){
if (!req.get('Origin')) return next();
// use "*" here to accept any origin
res.set('Access-Control-Allow-Origin', 'http://localhost:3000');
res.set('Access-Control-Allow-Methods', 'GET, POST');
+17 -20
Ver Arquivo
@@ -5,46 +5,43 @@
var express = require('../..');
// Edit /etc/vhosts
/*
edit /etc/vhosts:
// First app
127.0.0.1 foo.example.com
127.0.0.1 bar.example.com
127.0.0.1 example.com
*/
var one = express();
// Main app
one.use(express.logger());
var main = express();
one.get('/', function(req, res){
res.send('Hello from app one!')
main.use(express.logger('dev'));
main.get('/', function(req, res){
res.send('Hello from main app!')
});
one.get('/:sub', function(req, res){
main.get('/:sub', function(req, res){
res.send('requsted ' + req.params.sub);
});
// App two
var two = express();
two.get('/', function(req, res){
res.send('Hello from app two!')
});
// Redirect app
var redirect = express();
redirect.all('*', function(req, res){
console.log(req.subdomains);
res.redirect('http://localhost:3000/' + req.subdomains[0]);
res.redirect('http://example.com:3000/' + req.subdomains[0]);
});
// Main app
var app = express();
app.use(express.vhost('*.localhost', redirect))
app.use(express.vhost('localhost', one));
app.use(express.vhost('dev', two));
app.use(express.vhost('*.example.com', redirect))
app.use(express.vhost('example.com', main));
app.listen(3000);
console.log('Express app started on port 3000');
console.log('Express app started on port 3000');
+8 -4
Ver Arquivo
@@ -48,6 +48,7 @@ app.defaultConfiguration = function(){
// default settings
this.enable('x-powered-by');
this.set('env', process.env.NODE_ENV || 'development');
this.set('subdomain offset', 2);
debug('booting in %s mode', this.get('env'));
// implicit middleware
@@ -160,7 +161,7 @@ app.use = function(route, fn){
* [Consolidate.js](https://github.com/visionmedia/consolidate.js)
* library was created to map all of node's popular template
* engines to follow this convention, thus allowing them to
* work seemlessly within Express.
* work seeessly within Express.
*
* @param {String} ext
* @param {Function} fn
@@ -397,15 +398,18 @@ app.configure = function(env, fn){
};
/**
* Delegate `.VERB(...)` calls to `.route(VERB, ...)`.
* Delegate `.VERB(...)` calls to `router.VERB(...)`.
*/
methods.forEach(function(method){
app[method] = function(path){
if ('get' == method && 1 == arguments.length) return this.set(path);
var args = [method].concat([].slice.call(arguments));
// if no router attacked yet, attach the router
if (!this._usedRouter) this.use(this.router);
this._router.route.apply(this._router, args);
// setup route
this._router[method].apply(this._router, arguments);
return this;
};
});
+2 -2
Ver Arquivo
@@ -20,7 +20,7 @@ exports = module.exports = createApplication;
* Framework version.
*/
exports.version = '3.0.3';
exports.version = '3.1.0';
/**
* Expose mime.
@@ -46,7 +46,7 @@ function createApplication() {
/**
* Expose connect.middleware as express.*
* for example `express.logger` etc.
* for example `express.logger` etc.
*/
for (var key in connect.middleware) {
+1 -1
Ver Arquivo
@@ -18,7 +18,7 @@ var utils = require('./utils');
exports.init = function(app){
return function expressInit(req, res, next){
req.app = res.app = app;
if (app.settings['x-powered-by']) res.setHeader('X-Powered-By', 'Express');
if (app.enabled('x-powered-by')) res.setHeader('X-Powered-By', 'Express');
req.res = res;
res.req = req;
req.next = next;
+23 -16
Ver Arquivo
@@ -29,21 +29,21 @@ var req = exports = module.exports = {
*
* 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}
* @return {String}
* @api public
*/
req.get =
req.get =
req.header = function(name){
switch (name = name.toLowerCase()) {
case 'referer':
@@ -67,7 +67,7 @@ req.header = function(name){
* or array is given the _best_ match, if any is returned.
*
* Examples:
*
*
* // Accept: text/html
* req.accepts('html');
* // => "html"
@@ -261,7 +261,7 @@ req.param = function(name, defaultValue){
};
/**
* Check if the incoming request contains the "Content-Type"
* Check if the incoming request contains the "Content-Type"
* header field, and it contains the give mime `type`.
*
* Examples:
@@ -271,16 +271,16 @@ req.param = function(name, defaultValue){
* 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} type
* @return {Boolean}
* @api public
@@ -303,7 +303,7 @@ req.is = function(type){
/**
* Return the protocol string "http" or "https"
* when requested with TLS. When the "trust proxy"
* when requested with TLS. When the "trust proxy"
* setting is enabled the "X-Forwarded-Proto" header
* field will be trusted. If you're running behind
* a reverse proxy that supplies https for you this
@@ -393,25 +393,32 @@ req.__defineGetter__('auth', function(){
auth = parts[1];
// credentials
auth = new Buffer(auth, 'base64').toString().split(':');
return { username: auth[0], password: auth[1] };
auth = new Buffer(auth, 'base64').toString().match(/^([^:]*):(.*)$/);
if (!auth) return;
return { username: auth[1], password: auth[2] };
});
/**
* Return subdomains as an array.
*
* For example "tobi.ferrets.example.com"
* would provide `["ferrets", "tobi"]`.
* 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}
* @api public
*/
req.__defineGetter__('subdomains', function(){
var offset = this.app.get('subdomain offset');
return this.get('Host')
.split('.')
.slice(0, -2)
.reverse();
.reverse()
.slice(offset);
});
/**
+86 -49
Ver Arquivo
@@ -141,6 +141,7 @@ res.send = function(body){
if (204 == this.statusCode || 304 == this.statusCode) {
this.removeHeader('Content-Type');
this.removeHeader('Content-Length');
this.removeHeader('Transfer-Encoding');
body = '';
}
@@ -186,7 +187,7 @@ res.json = function(obj){
// content-type
this.charset = this.charset || 'utf-8';
this.get('Content-Type') || this.set('Content-Type', 'application/json');
return this.send(body);
};
@@ -222,13 +223,15 @@ res.jsonp = function(obj){
var app = this.app;
var replacer = app.get('json replacer');
var spaces = app.get('json spaces');
var body = JSON.stringify(obj, replacer, spaces);
var body = JSON.stringify(obj, replacer, spaces)
.replace(/\u2028/g, '\\u2028')
.replace(/\u2029/g, '\\u2029');
var callback = this.req.query[app.get('jsonp callback name')];
// content-type
this.charset = this.charset || 'utf-8';
this.set('Content-Type', 'application/json');
// jsonp
if (callback) {
this.set('Content-Type', 'text/javascript');
@@ -241,7 +244,7 @@ res.jsonp = function(obj){
/**
* Transfer the file at the given `path`.
*
*
* Automatically sets the _Content-Type_ response header field.
* The callback `fn(err)` is invoked when the transfer is complete
* or when an error occurs. Be sure to check `res.sentHeader`
@@ -263,7 +266,7 @@ res.jsonp = function(obj){
* 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);
@@ -408,11 +411,11 @@ res.type = function(type){
* 'text/plain': function(){
* res.send('hey');
* },
*
*
* 'text/html': function(){
* res.send('<p>hey</p>');
* },
*
*
* 'appliation/json': function(){
* res.send({ message: 'hey' });
* }
@@ -425,11 +428,11 @@ res.type = function(type){
* text: function(){
* res.send('hey');
* },
*
*
* html: function(){
* res.send('<p>hey</p>');
* },
*
*
* json: function(){
* res.send({ message: 'hey' });
* }
@@ -495,24 +498,27 @@ res.attachment = function(filename){
*
* Examples:
*
* res.set('Foo', ['bar', 'baz']);
* res.set('Accept', 'application/json');
* res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' });
*
* Aliased as `res.header()`.
* Aliased as `res.header()`.
*
* @param {String|Object} field
* @param {String|Object|Array} field
* @param {String} val
* @return {ServerResponse} for chaining
* @api public
*/
res.set =
res.set =
res.header = function(field, val){
if (2 == arguments.length) {
this.setHeader(field, '' + val);
if (Array.isArray(val)) val = val.map(String);
else val = String(val);
this.setHeader(field, val);
} else {
for (var key in field) {
this.setHeader(key, '' + field[key]);
this.set(key, field[key]);
}
}
return this;
@@ -570,22 +576,24 @@ res.clearCookie = function(name, options){
*/
res.cookie = function(name, val, options){
options = options || {};
options = utils.merge({}, options);
var secret = this.req.secret;
var signed = options.signed;
if (signed && !secret) throw new Error('connect.cookieParser("secret") required for signed cookies');
if ('object' == typeof val) val = 'j:' + JSON.stringify(val);
if (signed) val = 's:' + sign(val, secret);
if ('maxAge' in options) options.expires = new Date(Date.now() + options.maxAge);
if ('maxAge' in options) {
options.expires = new Date(Date.now() + options.maxAge);
options.maxAge /= 1000;
}
if (null == options.path) options.path = '/';
options.maxAge /= 1000;
this.set('Set-Cookie', cookie.serialize(name, String(val), options));
return this;
};
/**
* Redirect to the given `url` with optional response `status`
* defaulting to 302.
* Set the location header to `url`.
*
* The given `url` can also be the name of a mapped url, for
* example by default express supports "back" which redirects
@@ -593,46 +601,30 @@ res.cookie = function(name, val, options){
*
* Examples:
*
* res.redirect('/foo/bar');
* res.redirect('http://example.com');
* res.redirect(301, 'http://example.com');
* res.redirect('http://example.com', 301);
* res.redirect('../login'); // /blog/post/1 -> /blog/login
* res.location('/foo/bar').;
* res.location('http://example.com');
* res.location('../login'); // /blog/post/1 -> /blog/login
*
* Mounting:
*
* When an application is mounted, and `res.redirect()`
* is given a path that does _not_ lead with "/". For
* example suppose a "blog" app is mounted at "/blog",
* the following redirect would result in "/blog/login":
* When an application is mounted and `res.location()`
* is given a path that does _not_ lead with "/" it becomes
* relative to the mount-point. For example if the application
* is mounted at "/blog", the following would become "/blog/login".
*
* res.redirect('login');
* res.location('login');
*
* While the leading slash would result in a redirect to "/login":
* While the leading slash would result in a location of "/login":
*
* res.redirect('/login');
* res.location('/login');
*
* @param {String} url
* @param {Number} code
* @api public
*/
res.redirect = function(url){
res.location = function(url){
var app = this.app
, req = this.req
, head = 'HEAD' == req.method
, status = 302
, body;
// allow status / url
if (2 == arguments.length) {
if ('number' == typeof url) {
status = url;
url = arguments[1];
} else {
status = arguments[1];
}
}
, req = this.req;
// setup redirect map
var map = { back: req.get('Referrer') || '/' };
@@ -653,10 +645,56 @@ res.redirect = function(url){
}
}
// Respond
this.set('Location', url);
return this;
};
/**
* 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('http://example.com', 301);
* res.redirect('../login'); // /blog/post/1 -> /blog/login
*
* @param {String} url
* @param {Number} code
* @api public
*/
res.redirect = function(url){
var app = this.app
, head = 'HEAD' == this.req.method
, status = 302
, body;
// allow status / url
if (2 == arguments.length) {
if ('number' == typeof url) {
status = url;
url = arguments[1];
} else {
status = arguments[1];
}
}
// Set location header
this.location(url);
url = this.get('Location');
// Support text/{plain,html} by default
this.format({
text: function(){
body = statusCodes[status] + '. Redirecting to ' + url;
body = statusCodes[status] + '. Redirecting to ' + encodeURI(url);
},
html: function(){
@@ -671,7 +709,6 @@ res.redirect = function(url){
// Respond
this.statusCode = status;
this.set('Location', url);
this.set('Content-Length', Buffer.byteLength(body));
this.end(head ? null : body);
};
+21 -4
Ver Arquivo
@@ -4,6 +4,7 @@
var Route = require('./route')
, utils = require('../utils')
, methods = require('methods')
, debug = require('debug')('express:router')
, parse = require('connect').utils.parseUrl;
@@ -15,7 +16,7 @@ exports = module.exports = Router;
/**
* Initialize a new `Router` with the given `options`.
*
*
* @param {Object} options
* @api private
*/
@@ -139,7 +140,7 @@ Router.prototype._dispatch = function(req, res, next){
};
param(err);
// single param callbacks
function paramCallback(err) {
var fn = paramCallbacks[paramIndex++];
@@ -243,14 +244,30 @@ Router.prototype.route = function(method, path, callbacks){
// ensure path was given
if (!path) throw new Error('Router#' + method + '() requires a path');
// ensure all callbacks are functions
callbacks.forEach(function(fn, i){
if ('function' == typeof fn) return;
var type = {}.toString.call(fn);
var msg = '.' + method + '() requires callback functions but got a ' + type;
throw new Error(msg);
});
// create the route
debug('defined %s %s', method, path);
var route = new Route(method, path, callbacks, {
sensitive: this.caseSensitive
, strict: this.strict
sensitive: this.caseSensitive,
strict: this.strict
});
// add it
(this.map[method] = this.map[method] || []).push(route);
return this;
};
methods.forEach(function(method){
Router.prototype[method] = function(path){
var args = [method].concat([].slice.call(arguments));
this.route.apply(this, args);
return this;
};
});
+2 -4
Ver Arquivo
@@ -4,7 +4,7 @@
*/
var mime = require('connect').mime
, crc = require('crc');
, crc32 = require('buffer-crc32');
/**
* Return ETag for `body`.
@@ -15,9 +15,7 @@ var mime = require('connect').mime
*/
exports.etag = function(body){
return '"' + (Buffer.isBuffer(body)
? crc.buffer.crc32(body)
: crc.crc32(body)) + '"';
return '"' + crc32.signed(body) + '"';
};
/**
+1 -1
Ver Arquivo
@@ -38,7 +38,7 @@ function View(name, options) {
var engines = options.engines;
this.defaultEngine = options.defaultEngine;
var ext = this.ext = extname(name);
if (!ext) name += (ext = this.ext = '.' + this.defaultEngine);
if (!ext) name += (ext = this.ext = ('.' != this.defaultEngine[0] ? '.' : '') + this.defaultEngine);
this.engine = engines[ext] || (engines[ext] = require(ext.slice(1)).__express);
this.path = this.lookup(name);
}
+5 -5
Ver Arquivo
@@ -1,21 +1,21 @@
{
"name": "express",
"description": "Sinatra inspired web development framework",
"version": "3.0.3",
"version": "3.1.0",
"author": "TJ Holowaychuk <tj@vision-media.ca>",
"contributors": [
{ "name": "TJ Holowaychuk", "email": "tj@vision-media.ca" },
"contributors": [
{ "name": "TJ Holowaychuk", "email": "tj@vision-media.ca" },
{ "name": "Aaron Heckmann", "email": "aaron.heckmann+github@gmail.com" },
{ "name": "Ciaran Jessup", "email": "ciaranj@gmail.com" },
{ "name": "Guillermo Rauch", "email": "rauchg@gmail.com" }
],
"dependencies": {
"connect": "2.7.0",
"connect": "2.7.2",
"commander": "0.6.1",
"range-parser": "0.0.4",
"mkdirp": "0.3.3",
"cookie": "0.0.5",
"crc": "0.2.0",
"buffer-crc32": "0.1.1",
"fresh": "0.1.0",
"methods": "0.0.1",
"send": "0.1.0",
+25 -1
Ver Arquivo
@@ -76,4 +76,28 @@ describe('Router', function(){
.expect('foo', done);
})
})
})
describe('.multiple callbacks', function(){
it('should throw if a callback is null', function(){
assert.throws(function () {
router.route('get', '/foo', null, function(){});
})
})
it('should throw if a callback is undefined', function(){
assert.throws(function () {
router.route('get', '/foo', undefined, function(){});
})
})
it('should throw if a callback is not a function', function(){
assert.throws(function () {
router.route('get', '/foo', 'not a function', function(){});
})
})
it('should not throw if all callbacks are functions', function(){
router.route('get', '/foo', function(){}, function(){});
})
})
})
+15
Ver Arquivo
@@ -61,5 +61,20 @@ describe('app', function(){
done();
})
})
it('should work "view engine" with leading "."', function(done){
var app = express();
app.set('views', __dirname + '/fixtures');
app.engine('.html', render);
app.set('view engine', '.html');
app.locals.user = { name: 'tobi' };
app.render('user', function(err, str){
if (err) return done(err);
str.should.equal('<p>tobi</p>');
done();
})
})
})
})
+30
Ver Arquivo
@@ -48,6 +48,36 @@ describe('req', function(){
})
})
describe('when encoded string is malformed', function(){
it('should return undefined', function(done){
var app = express();
app.get('/', function(req, res){
res.send(req.auth || 'none');
});
request(app)
.get('/')
.set('Authorization', 'Basic Z21ldGh2aW4=')
.expect('none', done)
})
})
describe('when password contains a colon', function(){
it('should return .username and .password', function(done){
var app = express();
app.get('/', function(req, res){
res.send(req.auth || 'none');
});
request(app)
.get('/')
.set('Authorization', 'Basic dG9iaTpmZXJyZXQ6ZmVycmV0')
.expect('{"username":"tobi","password":"ferret:ferret"}', done)
})
})
it('should return .username and .password', function(done){
var app = express();
+50
Ver Arquivo
@@ -33,5 +33,55 @@ describe('req', function(){
.expect('[]', done);
})
})
describe('when subdomain offset is set', function(){
describe('when subdomain offset is zero', function(){
it('should return an array with the whole domain', function(done){
var app = express();
app.set('subdomain offset', 0);
app.use(function(req, res){
res.send(req.subdomains);
});
request(app)
.get('/')
.set('Host', 'tobi.ferrets.sub.example.com')
.expect('["com","example","sub","ferrets","tobi"]', done);
})
})
describe('when present', function(){
it('should return an array', function(done){
var app = express();
app.set('subdomain offset', 3);
app.use(function(req, res){
res.send(req.subdomains);
});
request(app)
.get('/')
.set('Host', 'tobi.ferrets.sub.example.com')
.expect('["ferrets","tobi"]', done);
})
})
describe('otherwise', function(){
it('should return an empty array', function(done){
var app = express();
app.set('subdomain offset', 3);
app.use(function(req, res){
res.send(req.subdomains);
});
request(app)
.get('/')
.set('Host', 'sub.example.com')
.expect('[]', done);
})
})
})
})
})
+20
Ver Arquivo
@@ -1,6 +1,7 @@
var express = require('../')
, request = require('./support/http')
, utils = require('connect').utils
, cookie = require('cookie');
describe('res', function(){
@@ -108,6 +109,25 @@ describe('res', function(){
done();
})
})
it('should not mutate the options object', function(done){
var app = express();
var options = { maxAge: 1000 };
var optionsCopy = utils.merge({}, options);
app.use(function(req, res){
res.cookie('name', 'tobi', options)
res.end();
});
request(app)
.get('/')
.end(function(err, res){
options.should.eql(optionsCopy);
done();
})
})
})
describe('signed', function(){
+16
Ver Arquivo
@@ -71,6 +71,22 @@ describe('res', function(){
})
})
it('should escape utf whitespace', function(done){
var app = express();
app.use(function(req, res){
res.jsonp({ str: '\u2028 \u2029 woot' });
});
request(app)
.get('/?callback=foo')
.end(function(err, res){
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
res.text.should.equal('foo && foo({"str":"\\u2028 \\u2029 woot"});');
done();
});
});
describe('when given primitives', function(){
it('should respond with json', function(done){
var app = express();
+171
Ver Arquivo
@@ -0,0 +1,171 @@
var express = require('../')
, request = require('./support/http');
describe('res', function(){
describe('.location(url)', function(){
it('should set the header', function(done){
var app = express();
app.use(function(req, res){
res.location('http://google.com').end();
});
request(app)
.get('/')
.end(function(err, res){
res.headers.should.have.property('location', 'http://google.com');
done();
})
})
describe('with leading //', function(){
it('should pass through scheme-relative urls', function(done){
var app = express();
app.use(function(req, res){
res.location('//cuteoverload.com').end();
});
request(app)
.get('/')
.end(function(err, res){
res.headers.should.have.property('location', '//cuteoverload.com');
done();
})
})
})
describe('with leading /', function(){
it('should construct scheme-relative urls', function(done){
var app = express();
app.use(function(req, res){
res.location('/login').end();
});
request(app)
.get('/')
.end(function(err, res){
res.headers.should.have.property('location', '/login');
done();
})
})
})
describe('with leading ./', function(){
it('should construct path-relative urls', function(done){
var app = express();
app.use(function(req, res){
res.location('./edit').end();
});
request(app)
.get('/post/1')
.end(function(err, res){
res.headers.should.have.property('location', '/post/1/./edit');
done();
})
})
})
describe('with leading ../', function(){
it('should construct path-relative urls', function(done){
var app = express();
app.use(function(req, res){
res.location('../new').end();
});
request(app)
.get('/post/1')
.end(function(err, res){
res.headers.should.have.property('location', '/post/1/../new');
done();
})
})
})
describe('without leading /', function(){
it('should construct mount-point relative urls', function(done){
var app = express();
app.use(function(req, res){
res.location('login').end();
});
request(app)
.get('/')
.end(function(err, res){
res.headers.should.have.property('location', '/login');
done();
})
})
})
describe('when mounted', function(){
describe('deeply', function(){
it('should respect the mount-point', function(done){
var app = express()
, blog = express()
, admin = express();
admin.use(function(req, res){
res.location('login').end();
});
app.use('/blog', blog);
blog.use('/admin', admin);
request(app)
.get('/blog/admin')
.end(function(err, res){
res.headers.should.have.property('location', '/blog/admin/login');
done();
})
})
})
describe('omitting leading /', function(){
it('should respect the mount-point', function(done){
var app = express()
, admin = express();
admin.use(function(req, res){
res.location('admin/login').end();
});
app.use('/blog', admin);
request(app)
.get('/blog')
.end(function(err, res){
res.headers.should.have.property('location', '/blog/admin/login');
done();
})
})
})
describe('providing leading /', function(){
it('should ignore mount-point', function(done){
var app = express()
, admin = express();
admin.use(function(req, res){
res.location('/admin/login').end();
});
app.use('/blog', admin);
request(app)
.get('/blog')
.end(function(err, res){
res.headers.should.have.property('location', '/admin/login');
done();
})
})
})
})
})
})
+17 -158
Ver Arquivo
@@ -19,164 +19,6 @@ describe('res', function(){
done();
})
})
describe('with leading //', function(){
it('should pass through scheme-relative urls', function(done){
var app = express();
app.use(function(req, res){
res.redirect('//cuteoverload.com');
});
request(app)
.get('/')
.set('Host', 'example.com')
.end(function(err, res){
res.headers.should.have.property('location', '//cuteoverload.com');
done();
})
})
})
describe('with leading /', function(){
it('should construct scheme-relative urls', function(done){
var app = express();
app.use(function(req, res){
res.redirect('/login');
});
request(app)
.get('/')
.set('Host', 'example.com')
.end(function(err, res){
res.headers.should.have.property('location', '/login');
done();
})
})
})
describe('with leading ./', function(){
it('should construct path-relative urls', function(done){
var app = express();
app.use(function(req, res){
res.redirect('./edit');
});
request(app)
.get('/post/1')
.set('Host', 'example.com')
.end(function(err, res){
res.headers.should.have.property('location', '/post/1/./edit');
done();
})
})
})
describe('with leading ../', function(){
it('should construct path-relative urls', function(done){
var app = express();
app.use(function(req, res){
res.redirect('../new');
});
request(app)
.get('/post/1')
.set('Host', 'example.com')
.end(function(err, res){
res.headers.should.have.property('location', '/post/1/../new');
done();
})
})
})
describe('without leading /', function(){
it('should construct mount-point relative urls', function(done){
var app = express();
app.use(function(req, res){
res.redirect('login');
});
request(app)
.get('/')
.set('Host', 'example.com')
.end(function(err, res){
res.headers.should.have.property('location', '/login');
done();
})
})
})
describe('when mounted', function(){
describe('deeply', function(){
it('should respect the mount-point', function(done){
var app = express()
, blog = express()
, admin = express();
admin.use(function(req, res){
res.redirect('login');
});
app.use('/blog', blog);
blog.use('/admin', admin);
request(app)
.get('/blog/admin')
.set('Host', 'example.com')
.end(function(err, res){
res.headers.should.have.property('location', '/blog/admin/login');
done();
})
})
})
describe('omitting leading /', function(){
it('should respect the mount-point', function(done){
var app = express()
, admin = express();
admin.use(function(req, res){
res.redirect('admin/login');
});
app.use('/blog', admin);
request(app)
.get('/blog')
.set('Host', 'example.com')
.end(function(err, res){
res.headers.should.have.property('location', '/blog/admin/login');
done();
})
})
})
describe('providing leading /', function(){
it('should ignore mount-point', function(done){
var app = express()
, admin = express();
admin.use(function(req, res){
res.redirect('/admin/login');
});
app.use('/blog', admin);
request(app)
.get('/blog')
.set('Host', 'example.com')
.end(function(err, res){
res.headers.should.have.property('location', '/admin/login');
done();
})
})
})
})
})
describe('.redirect(status, url)', function(){
@@ -287,6 +129,23 @@ describe('res', function(){
done();
})
})
it('should encode the url', function(done){
var app = express();
app.use(function(req, res){
res.redirect('http://example.com/?param=<script>alert("hax");</script>');
});
request(app)
.get('/')
.set('Host', 'http://example.com')
.set('Accept', 'text/plain, */*')
.end(function(err, res){
res.text.should.equal('Moved Temporarily. Redirecting to http://example.com/?param=%3Cscript%3Ealert(%22hax%22);%3C/script%3E');
done();
})
})
})
describe('when accepting neither text or html', function(){
+6 -4
Ver Arquivo
@@ -206,11 +206,11 @@ describe('res', function(){
})
describe('when .statusCode is 204', function(){
it('should strip Content-* fields & body', function(done){
it('should strip Content-* fields, Transfer-Encoding field, and body', function(done){
var app = express();
app.use(function(req, res){
res.status(204).send('foo');
res.status(204).set('Transfer-Encoding', 'chunked').send('foo');
});
request(app)
@@ -218,6 +218,7 @@ describe('res', function(){
.end(function(err, res){
res.headers.should.not.have.property('content-type');
res.headers.should.not.have.property('content-length');
res.headers.should.not.have.property('transfer-encoding');
res.text.should.equal('');
done();
})
@@ -225,11 +226,11 @@ describe('res', function(){
})
describe('when .statusCode is 304', function(){
it('should strip Content-* fields & body', function(done){
it('should strip Content-* fields, Transfer-Encoding field, and body', function(done){
var app = express();
app.use(function(req, res){
res.status(304).send('foo');
res.status(304).set('Transfer-Encoding', 'chunked').send('foo');
});
request(app)
@@ -237,6 +238,7 @@ describe('res', function(){
.end(function(err, res){
res.headers.should.not.have.property('content-type');
res.headers.should.not.have.property('content-length');
res.headers.should.not.have.property('transfer-encoding');
res.text.should.equal('');
done();
})
+7 -7
Ver Arquivo
@@ -127,7 +127,7 @@ describe('res', function(){
});
})
})
describe('with a relative path', function(){
it('should transfer the file', function(done){
var app = express();
@@ -144,7 +144,7 @@ describe('res', function(){
done();
});
})
it('should serve relative to "root"', function(done){
var app = express();
@@ -160,7 +160,7 @@ describe('res', function(){
done();
});
})
it('should consider ../ malicious when "root" is not set', function(done){
var app = express();
@@ -172,7 +172,7 @@ describe('res', function(){
.get('/')
.expect(403, done);
})
it('should allow ../ when "root" is set', function(done){
var app = express();
@@ -184,7 +184,7 @@ describe('res', function(){
.get('/')
.expect(200, done);
})
it('should disallow requesting out of "root"', function(done){
var app = express();
@@ -196,7 +196,7 @@ describe('res', function(){
.get('/')
.expect(403, done);
})
it('should next(404) when not found', function(done){
var app = express()
, calls = 0;
@@ -208,7 +208,7 @@ describe('res', function(){
app.use(function(req, res){
assert(0, 'this should not be called');
});
app.use(function(err, req, res, next){
++calls;
next(err);
+21
Ver Arquivo
@@ -24,6 +24,27 @@ describe('res', function(){
res.get('ETag').should.equal('123');
})
})
describe('.set(field, values)', function(){
it('should set multiple response header fields', function(done){
var app = express();
app.use(function(req, res){
res.set('Set-Cookie', ["type=ninja", "language=javascript"]);
res.send(res.get('Set-Cookie'));
});
request(app)
.get('/')
.expect('["type=ninja","language=javascript"]', done);
})
it('should coerce to an array of strings', function(){
res.headers = {};
res.set('ETag', [123, 456]);
JSON.stringify(res.get('ETag')).should.equal('["123","456"]');
})
})
describe('.set(object)', function(){
it('should set multiple fields', function(done){
+20
Ver Arquivo
@@ -2,6 +2,26 @@
var utils = require('../lib/utils')
, assert = require('assert');
describe('utils.etag(body)', function(){
var str = 'Hello CRC';
var strUTF8 = '<!DOCTYPE html>\n<html>\n<head>\n</head>\n<body><p>自動販売</p></body></html>';
it('should support strings', function(){
utils.etag(str).should.eql('"-2034458343"');
})
it('should support utf8 strings', function(){
utils.etag(strUTF8).should.eql('"1395090196"');
})
it('should support buffer', function(){
utils.etag(new Buffer(strUTF8)).should.eql('"1395090196"');
utils.etag(new Buffer(str)).should.eql('"-2034458343"');
})
})
describe('utils.isAbsolute()', function(){
it('should support windows', function(){
assert(utils.isAbsolute('c:\\'));