Comparar commits

...

311 Commits

Autor SHA1 Mensagem Data
TJ Holowaychuk 197a2e3b54 Release 3.3.6 2013-08-27 13:49:09 -07:00
TJ Holowaychuk 6cf6c8b918 Revert "remove charset from json responses. Closes #1631"
This reverts commit 138d74aefa.
2013-08-27 13:48:18 -07:00
TJ Holowaychuk 752b5f705e Merge branch 'master' of github.com:visionmedia/express 2013-08-17 01:07:17 -07:00
TJ Holowaychuk e7fa579637 update license 2013-08-17 01:07:09 -07:00
TJ Holowaychuk 97781d4112 Merge pull request #1723 from gmethvin/accepts
Make req.accepts take an argument list
2013-08-16 16:32:48 -07:00
Greg Methvin 3ddd8e66a7 Make req.accepts take an argument list 2013-08-16 15:19:33 -07:00
TJ Holowaychuk 8a1e865e37 remove silly out-of-date dep badge 2013-08-15 08:18:01 -07:00
TJ Holowaychuk e850cb3ea3 Release 3.3.5 2013-08-11 07:50:51 +10:00
TJ Holowaychuk 13d3efe8df update fresh 2013-08-11 07:49:15 +10:00
TJ Holowaychuk d6ecf785a2 Merge pull request #1710 from hacksparrow/master
Fixed test cases for res.format
2013-08-09 15:03:45 -07:00
Hage Yaapa a38bdf6758 fixed test cases for res.format 2013-08-04 20:32:08 +05:30
TJ Holowaychuk 5aa9670120 Merge pull request #1685 from CharlesHolbrow/master
Fix typo in app.param comment
2013-08-02 14:46:40 -07:00
TJ Holowaychuk 8ad8cb93cc refactor 2013-08-02 14:46:25 -07:00
TJ Holowaychuk 610e172fcf Merge pull request #1694 from kavu/add_disable_etag
Add application setting to disable ETag (again)
2013-08-02 14:45:37 -07:00
TJ Holowaychuk 6942070a21 add [dir] to express(1) --help output. Closes #1699 2013-08-02 14:44:52 -07:00
TJ Holowaychuk e283200511 remove comma-first from express(1)-generated app 2013-08-01 11:10:21 -07:00
Max Riveiro 54a192a5c5 Add application setting to disable ETag completely 2013-07-21 12:49:28 +04:00
TJ Holowaychuk c3bd65eda2 Revert "remove old OPTIONS default response"
This reverts commit 2bba69f633.
2013-07-16 11:22:02 -07:00
Charles Holbrow 3de81e0147 Fix typo in app.param comment 2013-07-13 16:32:02 -07:00
TJ Holowaychuk 8fe1e2a5b4 Release 3.3.4 2013-07-08 14:42:45 -07:00
TJ Holowaychuk 909dbb81d5 update send and connect 2013-07-08 14:40:02 -07:00
TJ Holowaychuk 26802a689c fix package.json conflict 2013-07-04 13:39:36 -07:00
TJ Holowaychuk 37239fb67f Release 3.3.3 2013-07-04 07:37:17 -07:00
TJ Holowaychuk 018dc40b32 update connect 2013-07-04 07:36:57 -07:00
TJ Holowaychuk 52440955e6 Release 3.3.2 2013-07-03 11:25:54 -07:00
TJ Holowaychuk c2f3d6ce2b update connect 2013-07-03 11:25:15 -07:00
TJ Holowaychuk be858f5d07 update send 2013-07-03 11:24:31 -07:00
TJ Holowaychuk 1f14734f91 Merge pull request #1664 from paulmillr/topics/update-deps
Update commander and mkdirp dependencies.
2013-07-01 11:14:15 -07:00
Paul Miller 6d1d694dbb Update commander and mkdirp dependencies. 2013-06-28 19:15:32 +03:00
TJ Holowaychuk ba5c48aa86 remove .version export 2013-06-27 08:38:53 -07:00
TJ Holowaychuk 320d7807a9 Release 3.3.1 2013-06-27 08:32:37 -07:00
TJ Holowaychuk 6650a312b7 update connect 2013-06-27 08:32:20 -07:00
TJ Holowaychuk 832c3b3744 Release 3.3.0 2013-06-26 10:07:34 -07:00
TJ Holowaychuk 76691bfd6b update connect 2013-06-26 10:05:40 -07:00
TJ Holowaychuk 29fe5ea785 Merge pull request #1657 from ralphtheninja/master
use send 0.1.1 to get rid of npm warning during install
2013-06-26 09:54:24 -07:00
Lars-Magnus Skog 52a820113f use send 0.1.1 to get rid of npm warning 2013-06-23 00:49:20 +02:00
TJ Holowaychuk aec3428489 Merge pull request #1650 from printercu/master
move .app to req's & res's prototypes
2013-06-11 12:39:59 -07:00
TJ Holowaychuk a10f695b6f pin jade dev dep so tests do not break 2013-06-11 12:24:17 -07:00
Max Melentiev a3c9eacaf1 move .app to req's & res's prototypes 2013-06-11 19:42:30 +04:00
TJ Holowaychuk 19d685b152 return actual booleans from req.accept* functions 2013-06-06 13:47:18 -07:00
TJ Holowaychuk 8ab44081d4 add support for multiple X-Forwarded-Proto values. Closes #1646 2013-06-05 12:05:45 -07:00
TJ Holowaychuk 0431d22822 add req.secure tests 2013-06-05 11:59:47 -07:00
TJ Holowaychuk 138d74aefa remove charset from json responses. Closes #1631 2013-06-05 11:51:59 -07:00
TJ Holowaychuk 28562b2cf8 Merge pull request #1643 from jonjenkins/master
Fixed issue with callback querystring failure
2013-06-03 14:52:49 -07:00
TJ Holowaychuk e0afda444f Release 3.2.6 2013-06-02 17:15:39 -07:00
TJ Holowaychuk 5a4cac58af update connect 2013-06-02 17:15:14 -07:00
TJ Holowaychuk 545dca6c4d Merge pull request #1642 from jade-bot/master
Update jade files [bot-update#1]
2013-06-02 16:04:50 -07:00
TJ Holowaychuk e59a882389 Merge pull request #1634 from joshlangner/patch-1
added some additional explanation for clarity
2013-06-02 15:58:25 -07:00
TJ Holowaychuk ccd9828535 Merge pull request #1630 from EvanHahn/patch-1
Remove dead link from readme's "More Information"
2013-06-02 15:50:45 -07:00
TJ Holowaychuk 41f0d32355 Merge pull request #1622 from saintedlama/master
Fixes indentation for css engines when using express to scaffold an application
2013-06-02 15:47:36 -07:00
Jenkins 2f19b4fefc Corrected callback crashing app when array 2013-05-26 21:35:52 -05:00
jade-bot cd31cecfd1 Update to maintain compatability with the latest version of jade 2013-05-26 14:51:34 -07:00
TJ Holowaychuk 2fe46b3905 Release 3.2.5 2013-05-21 21:01:24 -07:00
TJ Holowaychuk 24974f1f8f update connect 2013-05-21 20:56:08 -07:00
joshlangner fd73bd006e added some additional explanation for clarity 2013-05-19 22:47:04 -04:00
Evan Hahn 7388c2c223 Remove dead link from readme's "More Information" 2013-05-17 11:37:21 -06:00
TJ Holowaychuk e2210b0b92 Merge pull request #1625 from ForbesLindesay/patch-1
Throw a meaningful error when there is no default engine
2013-05-15 08:27:47 -07:00
Forbes Lindesay 30919be2a0 Throw a meaningful error when there is no default engine 2013-05-15 12:39:06 +01:00
TJ Holowaychuk 10b21b41f7 Revert "fix infinite loop when res.send(status) is undefined. Closes #1623"
This reverts commit 28b8a3b5f7.
2013-05-13 13:23:23 -07:00
TJ Holowaychuk 28b8a3b5f7 fix infinite loop when res.send(status) is undefined. Closes #1623 2013-05-13 13:22:31 -07:00
saintelama 8b2f1bba95 fix indentation for css engine support 2013-05-12 23:43:52 +02:00
TJ Holowaychuk c805d80a9b Merge pull request #1592 from bartsqueezy/eb1bbb9
Removing dependency which is no longer supported
2013-05-11 15:36:39 -07:00
TJ Holowaychuk d876778d22 Merge pull request #1597 from Cauldrath/cookie_version
Version bump for node-cookie
2013-05-11 15:35:30 -07:00
TJ Holowaychuk 412e571600 Merge pull request #1618 from pwmckenna/patch-1
Flush messages exposed to locals *after* the view has the chance to proces...
2013-05-11 15:26:22 -07:00
TJ Holowaychuk 3296ed9cb3 change generation of ETags with res.send() to GET requests only. Closes #1619
if for some reason this is not ideal for your use-case please let me know and comment in the issue
2013-05-10 14:43:59 -07:00
Patrick Williams 91835e6816 Flush messages exposed to locals after the view has the chance to process them. 2013-05-10 09:05:37 -06:00
TJ Holowaychuk f976625281 Release 3.2.4 2013-05-09 09:17:48 -07:00
TJ Holowaychuk 028d9d8a0c Merge pull request #1598 from colynb/patch-1
the file is hosts not vhosts
2013-05-09 09:12:54 -07:00
TJ Holowaychuk 8559c0e2a4 fix req.subdomains when no Host is present 2013-05-09 09:10:52 -07:00
TJ Holowaychuk 06ead58240 fix req.host when no Host is present, return undefined 2013-05-09 09:06:11 -07:00
TJ Holowaychuk 28ca1b5221 add req.host tests 2013-05-09 09:03:52 -07:00
TJ Holowaychuk 6d872e6693 remove qs dep 2013-05-07 07:58:54 -07:00
TJ Holowaychuk 0b09c8981f Release 3.2.3 2013-05-07 07:55:06 -07:00
TJ Holowaychuk a1d5676ecb update connect / qs 2013-05-07 07:54:48 -07:00
TJ Holowaychuk f862ad29f5 Release 3.2.2 2013-05-03 12:54:52 -07:00
TJ Holowaychuk 15496da8fd remove ./client.js 2013-05-03 12:54:28 -07:00
TJ Holowaychuk 802fb1632c update qs 2013-05-03 12:53:50 -07:00
colynb 69453ff889 the file is hosts not vhosts 2013-05-01 16:27:29 -07:00
Benjamin Hanes 28752cc3c0 Version bump for node-cookie 2013-05-01 15:25:14 -04:00
TJ Holowaychuk 9f06d9b03f Release 3.2.1 2013-04-29 19:17:08 -07:00
TJ Holowaychuk 3fb7c4e1db update connect 2013-04-29 19:16:33 -07:00
Steve Bartnesky 5fa685b602 removing github-flavored-markdown as a dependency as it is no longer supported. switch to use marked instead 2013-04-29 09:12:29 -05:00
Steve Bartnesky eb1bbb92c0 removing github-flavored-markdown as a dependency as it is no longer supported. switch to use marked instead 2013-04-29 08:59:52 -05:00
TJ Holowaychuk d0e49f1a8a update qs and remove all ~ semver crap 2013-04-26 13:12:33 -07:00
TJ Holowaychuk ea2664a4b8 Merge branch 'master' of github.com:visionmedia/express 2013-04-25 16:29:50 -07:00
TJ Holowaychuk da6524bd06 Merge pull request #1589 from hacksparrow/master
Signed cookies can now accept numbers as values, like unsigned cookies
2013-04-25 16:29:39 -07:00
TJ Holowaychuk a231406931 Merge branch 'master' of github.com:visionmedia/express 2013-04-25 16:26:44 -07:00
Hack Sparrow 6d39ed8ef7 Accept number as value of Signed Cookie 2013-04-23 22:53:35 +05:30
TJ Holowaychuk f2563f4dde Merge pull request #1586 from yields/master
removed some spaces from bin/express
2013-04-21 18:18:19 -07:00
Amir Abu Shareb 3df265b36a remove spaces when a session is enabled. 2013-04-21 15:41:42 +03:00
TJ Holowaychuk e382e6adc7 update supertest dev dep 2013-04-16 06:49:56 -07:00
TJ Holowaychuk 91c71d6c2e add app.VERB() paths array deprecation warning 2013-04-15 15:18:28 -07:00
TJ Holowaychuk 0d40c65b7f Release 3.2.0 2013-04-15 12:34:41 -07:00
TJ Holowaychuk 58f2057ba7 revert cookie signature change causing session race conditions 2013-04-15 12:33:12 -07:00
TJ Holowaychuk 37179109db Revert "fix res.cookie() tests"
This reverts commit ed273448b9.
2013-04-15 12:29:42 -07:00
TJ Holowaychuk 579857cfaa fix example port 2013-04-13 10:14:23 -07:00
Caridy Patino 0b4e2df480 add "view" constructor setting to override view behaviour 2013-04-13 09:53:50 -07:00
TJ Holowaychuk 49cc1a70b1 Merge pull request #1571 from jlubawy/master
Change to crypto.pbkdf2 in Node v0.10 broke auth example
2013-04-13 09:35:11 -07:00
TJ Holowaychuk f8a33d137a refactor 2013-04-13 09:16:15 -07:00
TJ Holowaychuk 2db135dfc7 Merge pull request #1566 from daguej/v8-context-fix
Possible fix for #1557
2013-04-13 09:14:41 -07:00
TJ Holowaychuk 99bc628ad1 fix long list params test 2013-04-13 09:07:48 -07:00
TJ Holowaychuk 5ba6c301d7 Merge pull request #1578 from Notificare/master
Correct sorting of long list of accept header
2013-04-13 09:06:09 -07:00
silentjohnny 88273a59f8 Added originalIndex to parseQuality to correctly sort long lists (v8 does unstable quicksort for length > 10) 2013-04-13 12:36:35 +02:00
TJ Holowaychuk 2e53cb72ec add req.acceptsEncoding(name) 2013-04-12 12:56:50 -07:00
TJ Holowaychuk 3b1597d79e add req.acceptedEncodings 2013-04-12 12:55:53 -07:00
TJ Holowaychuk 776ee26bc3 Release 3.1.2 2013-04-12 12:14:02 -07:00
TJ Holowaychuk ed273448b9 fix res.cookie() tests 2013-04-12 12:13:12 -07:00
TJ Holowaychuk 4bb91b3f67 update connect 2013-04-12 12:10:48 -07:00
TJ Holowaychuk c5f866098e update cookie-signature 2013-04-12 12:07:43 -07:00
TJ Holowaychuk 6cfd01be6b Merge branch 'master' of github.com:visionmedia/express 2013-04-11 08:42:05 -07:00
TJ Holowaychuk 53b8e25731 ocd 2013-04-11 08:36:52 -07:00
Pavel Brylov 9e684d45bc add support for custom Accept parameters 2013-04-11 08:34:10 -07:00
TJ Holowaychuk 09d9201787 Merge pull request #1575 from jsmarkus/patch-1
Changed URL of russian docs in Readme.md
2013-04-09 15:47:31 -07:00
Mark a732d6d471 Changed URL of russian docs in Readme.md 2013-04-09 21:18:50 +03:00
Josh Lubawy ee9d50c128 Modified hash to return base64 encoded strings. 2013-04-04 23:26:27 -07:00
TJ Holowaychuk d1bafa0685 docs 2013-04-03 15:11:58 -07:00
TJ Holowaychuk 2604be5491 Merge branch 'master' of github.com:visionmedia/express 2013-04-03 08:26:23 -07:00
TJ Holowaychuk c52d9cdfbe add --check-leaks for mocha 2013-04-03 08:14:11 -07:00
TJ Holowaychuk aab6b7e721 Merge pull request #1567 from guybrush/fixTravis
fix .travis.yml
2013-04-02 14:42:06 -07:00
Patrick Pfeiffer d13cea46d5 fix .travis.yml 2013-04-02 16:16:30 +02:00
TJ Holowaychuk 82731dae6e Merge pull request #1503 from shesek/settings-inheritance
Inherit settings from parent application using [[Prototype]]
2013-04-01 14:29:20 -07:00
TJ Holowaychuk 476fba3e8b Release 3.1.1 2013-04-01 11:25:58 -07:00
TJ Holowaychuk a566624f2d refactor 2013-04-01 11:22:16 -07:00
TJ Holowaychuk c6d7352f5c Merge branch 'master' of github.com:visionmedia/express 2013-04-01 11:19:02 -07:00
TJ Holowaychuk 771573be30 Merge pull request #1516 from PatternConsulting/master
Fix Dotted Relative Redirects in Applications Mounted on Nested Paths
2013-04-01 11:18:50 -07:00
TJ Holowaychuk b7afa4f0f4 Merge pull request #1523 from thomseddon/fix-whitespace
Remove some superfluous trailing whitespace
2013-04-01 11:14:07 -07:00
TJ Holowaychuk 4a1fa58704 refactor req.host 2013-04-01 11:09:23 -07:00
TJ Holowaychuk 6654b7162c Merge branch 'master' of github.com:visionmedia/express 2013-04-01 11:07:05 -07:00
TJ Holowaychuk f26a3cc806 Merge pull request #1564 from cdauth/master
Consider X-Forwarded-Host if proxy is trusted
2013-04-01 11:06:39 -07:00
Josh Dague 57e48c4767 Possible fix for #1557, allows routes to be created using literal regexes across V8 contexts. Removes all uses of instanceof. 2013-04-01 14:03:32 -04:00
TJ Holowaychuk 66d9a4ad43 Merge branch 'master' of github.com:visionmedia/express 2013-04-01 11:02:56 -07:00
TJ Holowaychuk 78d9c98187 update connect 2013-04-01 11:02:29 -07:00
Candid Dauth b686ec1182 Considering X-Forwarded-Host header if proxy is trusted 2013-03-31 01:28:34 +01:00
TJ Holowaychuk 158f452b50 Merge pull request #1534 from lennym/patch-1
Made quotes consistent in generated app.js
2013-03-13 15:43:18 -07:00
TJ Holowaychuk 916acd1dd3 replace 0.6.x travis with 0.10.x 2013-03-12 17:26:24 -07:00
TJ Holowaychuk b4f612474b Merge pull request #1540 from fern4lvarez/master
Use End-of-line Node constant
2013-03-12 17:24:36 -07:00
fern4lvarez 9a884aa9ee Use End-of-line Node constant 2013-03-12 14:02:31 +01:00
TJ Holowaychuk db5636199e Merge pull request #1502 from qjcg/app-template-noconfigure
Remove legacy app.configure() method from app template.
2013-03-11 08:59:24 -07:00
Leonard Martin 8211562cf6 Made quotes consistent
One-off use of double quotes aggravated my OCD.
2013-03-07 11:12:22 +00:00
TJ Holowaychuk 9df93d6dec Merge pull request #1533 from shesek/old-viewcallbacks
Removed old references to viewCallbacks
2013-03-06 14:31:45 -08:00
Nadav Ivgi 1e251af8d3 Removed old references to viewCallbacks
Was part of the deprecated locals.use() functionallity
2013-03-07 00:12:50 +02:00
Thom Seddon eed0f598a0 Remove some superfluous trailing whitespace 2013-03-01 07:47:30 +00:00
TJ Holowaychuk ec4d4a792a Merge pull request #1519 from yawnt/master
Fix explicit .js on project creation
2013-02-28 12:16:27 -08:00
yawnt 84e745f67c [fix] add .js, fixes haibu compatibility 2013-02-26 18:19:06 +01:00
Michael Ahlers 97edb23dba See comments. 2013-02-24 18:54:17 -05:00
Michael Ahlers 856782c81c Never mind. 2013-02-24 18:47:43 -05:00
Michael Ahlers a7266392f9 Although unrelated to #1516, this broken test case is causing headaches. (This is a reasonable fix in any case.) 2013-02-24 18:43:19 -05:00
Michael Ahlers 04b0c44bdf Test cases document this. 2013-02-24 18:05:11 -05:00
Michael Ahlers 99c9eecde5 When in Rome… 2013-02-24 18:03:29 -05:00
Michael Ahlers 4d65bbf612 Test cases for pull-request #1516. 2013-02-24 18:01:50 -05:00
Michael Ahlers 956aa0cfff This works as expected, and has limited scope. 2013-02-24 13:40:51 -05:00
Michael Ahlers d874476f0b Proposal to allow relative redirects for applications that have been mounted at multiple paths. 2013-02-24 13:10:49 -05:00
TJ Holowaychuk 30f9805539 Merge pull request #1513 from killmenot/master
minor typo issue
2013-02-22 08:35:39 -08:00
Alexey Kucherenko 46536dee39 fixed typo 2013-02-22 15:52:42 +04:00
TJ Holowaychuk 24087d94df link to runnable 2013-02-20 09:18:42 -08:00
TJ Holowaychuk d02df2ebd5 update connect 2013-02-19 15:50:23 -08:00
TJ Holowaychuk 16ba1f62a3 Merge branch 'master' of github.com:visionmedia/express 2013-02-13 10:56:35 -08:00
TJ Holowaychuk 684dd1a3c6 update mkdirp 2013-02-13 10:56:22 -08:00
TJ Holowaychuk 8bcdcfeedd update buffer-crc32 2013-02-13 10:55:55 -08:00
TJ Holowaychuk 3bc372aa33 Merge pull request #1505 from gravis/patch-1
Update Readme.md
2013-02-13 10:54:35 -08:00
Philippe Lafoucrière fc1c024041 Update Readme.md
Add dependancies status badge.
The badge looks bigger than Travis, because it's using a more recent version:
https://github.com/olivierlacan/shields/
2013-02-13 15:28:31 +01:00
TJ Holowaychuk 89427228d1 typo 2013-02-08 08:42:47 -08:00
Nadav Ivgi 420225f370 inherit settings from parent application using [[Prototype]] 2013-02-08 12:58:07 +02:00
John Gosset 44a3fa6359 Remove legacy app.configure() method from app template. 2013-02-07 11:14:06 -05:00
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 b709009bc9 Release 3.0.3 2012-11-13 09:14:13 -08:00
TJ Holowaychuk b80d7ec257 update connect 2012-11-13 09:12:47 -08:00
TJ Holowaychuk ff0384e610 update cookie module 2012-11-13 09:12:32 -08:00
TJ Holowaychuk ab9c275bde fix cookie max-age
the cookie module we depend on never used to
set this value, however now it does :)
2012-11-13 09:08:37 -08:00
TJ Holowaychuk c70db96b06 Update examples/cors/index.js 2012-11-08 13:52:20 -08:00
TJ Holowaychuk 1c616e29e2 Merge branch 'master' of github.com:visionmedia/express 2012-11-08 09:20:29 -08:00
TJ Holowaychuk cb7518435f Merge pull request #1406 from DmitryBochkarev/patch-1
remove connect.static.send import from response.js
2012-11-08 09:20:20 -08:00
TJ Holowaychuk 79f81c0a25 Merge pull request #1408 from Laboratory/master
delete unused variables
2012-11-08 09:20:08 -08:00
TJ Holowaychuk 72b9e48331 Release 3.0.2 2012-11-08 09:15:59 -08:00
TJ Holowaychuk eba6aa1767 fix .version 2012-11-08 09:15:24 -08:00
Vitaly 534fbdb307 delete unused variables 2012-11-08 17:07:08 +04:00
Dmitry Bochkarev 6b309a4457 remove connect.static.send import from response.js 2012-11-08 12:43:38 +05:00
TJ Holowaychuk af5e38c31a Update Readme.md 2012-11-05 09:10:34 -08:00
TJ Holowaychuk 4283f38698 add OPTIONS to cors example. Closes #1398 2012-11-04 13:21:55 -08:00
TJ Holowaychuk 2d49c0d1f3 Merge branch 'master' of github.com:visionmedia/express 2012-11-04 12:28:53 -08:00
TJ Holowaychuk a7ca3817db fix route chaining regression. Closes #1397 2012-11-04 12:28:35 -08:00
TJ Holowaychuk 1f044547ee Release 3.0.1 2012-11-01 17:27:53 -07:00
TJ Holowaychuk 612fc47044 update connect 2012-11-01 17:27:33 -07:00
TJ Holowaychuk 8959ff155b Merge pull request #1388 from shtylman/unused-variables
remove unused variables
2012-10-27 13:10:14 -07:00
Roman Shtylman dadf57cc8b remove unused variables
Tests and examples with unused variables are unchanged.
2012-10-27 16:04:00 -04:00
TJ Holowaychuk 764b6c61d9 Merge pull request #1387 from valllabh/patch-1
Update Readme.md
2012-10-26 06:44:53 -07:00
vallabh 582dadf787 Update Readme.md
Text alignment in Contributors list
2012-10-26 12:24:01 +05:30
TJ Holowaychuk 12d97169d7 Release 3.0.0 2012-10-23 15:29:20 -07:00
TJ Holowaychuk c29cfa823d change res.redirect() to utilize a pathname-relative Location again. Closes #1382
nginx does not seem to set Host correctly,
though Location should be relative as per RFC
myself nor anyone else can report a client
that does not handle relative correctly so
this will be fine until then
2012-10-23 14:08:18 -07:00
TJ Holowaychuk e183a9694e add make clean 2012-10-19 11:47:36 -07:00
TJ Holowaychuk d6cb449011 add "Basic" check to req.auth 2012-10-19 11:46:46 -07:00
TJ Holowaychuk 7bf4ad30fc add req.auth test coverage 2012-10-19 11:44:44 -07:00
TJ Holowaychuk b3936b96e5 add cb && cb(payload) to res.jsonp(). Closes #1374 2012-10-16 11:57:37 -07:00
TJ Holowaychuk 44d0625e91 fix view-locals example. Closes #1370
this was from 2x, doesnt need to be there at all
2012-10-15 16:07:56 -07:00
TJ Holowaychuk c492cde048 Merge branch 'examples' 2012-10-09 19:31:56 -07:00
TJ Holowaychuk c2fa6cc94d fix route-separation example 2012-10-09 19:31:52 -07:00
TJ Holowaychuk 464608025b refactor ejs example some more 2012-10-09 19:26:55 -07:00
TJ Holowaychuk d653d2308b refactor ejs example 2012-10-09 19:26:17 -07:00
TJ Holowaychuk a52b1f121c add EJS title example to auth 2012-10-09 19:21:50 -07:00
TJ Holowaychuk 9edd8be520 remove user footer info from auth example
looks a little weird
2012-10-09 19:20:30 -07:00
TJ Holowaychuk aa1d47600a fix auth example acceptance tests 2012-10-09 19:19:54 -07:00
sakateka be7ec8b40e improved ejs Example 2012-10-09 19:16:54 -07:00
sakateka 8e12dd9c17 Checked all the examples 2012-10-09 19:16:54 -07:00
TJ Holowaychuk fee0f0dce0 Merge branch 'error-handling-routes' 2012-10-09 19:09:21 -07:00
TJ Holowaychuk 0dd80e7b50 refactor routes.error tests 2012-10-09 19:09:12 -07:00
TJ Holowaychuk 78d5b72081 rename a test file 2012-10-09 19:06:23 -07:00
Sean Soong e0df865401 make application routing callback behave the same as middleware, fix logic and add test code 2012-10-09 19:05:30 -07:00
Sean Soong 2abcbed67a make application routing callback behave the same as middleware 2012-10-09 19:05:30 -07:00
TJ Holowaychuk 02b9d0b2e6 fix express.mime reference, should be connect.mime 2012-10-09 18:59:44 -07:00
TJ Holowaychuk 927e181db7 update connect 2012-10-09 18:56:47 -07:00
TJ Holowaychuk dc411b3175 Merge pull request #1364 from isaacs/patch-1
package.json: Remove publishConfig field
2012-10-09 08:43:37 -07:00
Isaac Z. Schlueter 1e870f0f0d package.json: Remove publishConfig field
Fixes #1359
2012-10-09 08:14:36 -07:00
TJ Holowaychuk 3cd01598a5 Merge pull request #1355 from lihanli/view-cache-test
set the NODE_ENV to development for the development view cache test
2012-10-06 15:25:07 -07:00
lihan 3b6d683b7f set the NODE_ENV to development for the development view cache test 2012-10-06 17:58:17 -04:00
TJ Holowaychuk eeef763f6d Merge branch 'master' of github.com:visionmedia/express 2012-10-06 09:58:27 -07:00
TJ Holowaychuk 76d3ec583d move default of "views" out so multiple cwd() calls are not made 2012-10-06 09:58:17 -07:00
TJ Holowaychuk 077d8b9247 Merge pull request #1354 from sakateka/master
examples/auth/app.js
2012-10-05 09:17:18 -07:00
sakateka 92840b9f68 Fixed: notify of a successful auth. 2012-10-05 12:23:11 +04:00
TJ Holowaychuk bf60d5a041 update connect 2012-09-27 12:39:26 -07:00
TJ Holowaychuk 56ffab045e add backwards compat for res.redirect() status. Closes #1336 2012-09-26 09:07:22 -07:00
TJ Holowaychuk 496ee401d7 Merge branch 'master' of github.com:visionmedia/express 2012-09-26 09:04:35 -07:00
TJ Holowaychuk f0d5b3b368 remove non-primitive string support for res.send()
kinda silly.. valueOf() before if you happen to use
boxed strings, otherwise it is unfair that dont support
other boxed primitives all over, and quite frankly no one does
2012-09-26 09:04:26 -07:00
TJ Holowaychuk 88072a56ea refactor 2012-09-26 09:01:55 -07:00
TJ Holowaychuk 0d3a637389 add support for res.json() to retain previously defined Content-Types. Closes #1349 2012-09-26 09:00:52 -07:00
TJ Holowaychuk dc44f3c226 Update Readme.md 2012-09-25 13:55:57 -07:00
TJ Holowaychuk 1029b0b97f adjust locals tests 2012-09-25 08:45:09 -07:00
TJ Holowaychuk 84f8228b8c update send 2012-09-19 11:37:46 -07:00
TJ Holowaychuk 968e8f0121 Release 3.0.0rc5 2012-09-18 11:48:20 -07:00
TJ Holowaychuk 9eb1da4568 update connect 2012-09-18 11:44:50 -07:00
TJ Holowaychuk 315e79e9f0 add redis search example 2012-09-18 09:31:12 -07:00
TJ Holowaychuk 363d0d4f41 Merge branch 'master' of github.com:visionmedia/express 2012-09-13 09:52:46 -07:00
TJ Holowaychuk 5ac631a270 add "x-powered-by" setting 2012-09-13 09:52:35 -07:00
TJ Holowaychuk 75fc882001 Merge pull request #1319 from pyrotechnick/patch-1
typo
2012-09-04 12:50:46 -07:00
Nicholas Kinsey d7cb213eeb Update lib/application.js
typo: http -> https
2012-09-05 05:20:37 +10:00
TJ Holowaychuk 568e0d297a add "application/octet-stream" redirect Accept test case. Closes #1317 2012-09-03 16:17:49 -07:00
TJ Holowaychuk 8edf358739 refactor res.format(), dont pass "default" to req.accepts() 2012-09-03 16:16:46 -07:00
TJ Holowaychuk 40be3ed05d update connect dep 2012-09-03 14:49:46 -07:00
TJ Holowaychuk 2c174d6b3b add app.router to static-files example 2012-09-03 08:54:39 -07:00
TJ Holowaychuk 60ee465bf7 add static-files example
point people here if they have
problems with serving static files
2012-09-03 08:52:53 -07:00
TJ Holowaychuk 51210d6b95 Release 3.0.0rc4 2012-08-30 22:13:38 -07:00
TJ Holowaychuk a6caa267bd add res.jsonp(). Closes #1307
this also removes the jsonp
2012-08-30 09:29:43 -07:00
TJ Holowaychuk cdb3e9dc0d fix etag quoting. Closes #1310 2012-08-30 08:49:48 -07:00
TJ Holowaychuk f2f09767fb add etag util 2012-08-30 08:27:57 -07:00
TJ Holowaychuk eec31d7126 fix acceptance tests 2012-08-29 10:47:29 -07:00
TJ Holowaychuk 3c5ad753b6 add "verbose errors" option to error-pages example 2012-08-29 10:46:52 -07:00
TJ Holowaychuk dd338b5567 Merge pull request #1309 from nickjj/patch-1
fix error-pages 404 status
2012-08-29 10:42:42 -07:00
nickjj 1b15af713c fix error-pages 404 status 2012-08-29 14:31:13 -03:00
TJ Holowaychuk 89c5affc3b fix jsonp callback char restrictions 2012-08-28 18:11:49 -07:00
TJ Holowaychuk 2bba69f633 remove old OPTIONS default response
relatively useless since its so non-informative,
let me know if anyone has an objection to this,
i think its best to define these for your API
2012-08-28 17:24:52 -07:00
TJ Holowaychuk 4403f136b7 add another route example to express(1) so people are not so confused 2012-08-28 16:18:00 -07:00
TJ Holowaychuk f7c1c638bb add some comments to error-pages example 2012-08-28 10:28:58 -07:00
TJ Holowaychuk f2d7bbe0e9 change jsonp callback default to false. Closes #1304 2012-08-28 09:08:41 -07:00
TJ Holowaychuk 87468cffce update connect dep 2012-08-21 19:09:18 -07:00
TJ Holowaychuk 3f7e3a714e drop to assert() for less crazy error message 2012-08-16 10:14:05 -07:00
TJ Holowaychuk 38a9caf159 update send 2012-08-16 10:08:55 -07:00
TJ Holowaychuk 500c8ab4b3 docs 2012-08-14 04:14:37 -07:00
TJ Holowaychuk c4ad97d555 add redis online user activity tracking example 2012-08-14 04:13:55 -07:00
TJ Holowaychuk b96401ac83 Release 3.0.0rc3 2012-08-13 20:23:59 -07:00
TJ Holowaychuk 32a5c9cba5 Merge pull request #1286 from tnydwrds/fix-signed-cookie-prefix
Fix signed cookie prefix
2012-08-13 20:21:36 -07:00
Tony Edwards 0217e6ce96 Fix signed cookie prefix
Update res.cookie to prefix signed cookies with 's:'
2012-08-13 20:01:17 -07:00
TJ Holowaychuk 6bebe0837f refactor res.render() to prevent clobbering "locals" 2012-08-11 15:04:54 -07:00
TJ Holowaychuk ff1c6f0cfa rename multipart app.js to index.js 2012-08-09 20:08:03 -07:00
TJ Holowaychuk 8ac3e80bf0 Merge branch 'master' of github.com:visionmedia/express 2012-08-09 10:15:27 -07:00
TJ Holowaychuk 3923ec89f7 remove route-loading example
using vm for this is lame
2012-08-09 10:15:12 -07:00
TJ Holowaychuk fd8ca32ab2 Merge pull request #1273 from ritch/patch-1
Removed extraneous require('http')
2012-08-09 08:46:23 -07:00
Ritchie Martori ba2f66d765 Removed extraneous require('http') 2012-08-08 17:51:04 -07:00
TJ Holowaychuk 056c840a06 update connect dep 2012-08-07 09:10:40 -07:00
105 arquivos alterados com 2546 adições e 993 exclusões
+1
Ver Arquivo
@@ -16,3 +16,4 @@ testing
.coverage_data
cover_html
test.js
.idea
+2 -1
Ver Arquivo
@@ -1,3 +1,4 @@
language: node_js
node_js:
- 0.6
- "0.8"
- "0.10"
+272 -77
Ver Arquivo
@@ -1,5 +1,200 @@
3.0.0rc2 / 2012-08-03
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
@@ -8,7 +203,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
@@ -19,12 +214,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
@@ -34,7 +229,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
@@ -45,7 +240,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`
@@ -57,7 +252,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]
@@ -66,7 +261,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
@@ -74,13 +269,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`
@@ -89,14 +284,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
@@ -111,7 +306,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
@@ -127,7 +322,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)`
@@ -182,54 +377,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
@@ -238,7 +433,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
@@ -249,17 +444,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
@@ -267,25 +462,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
@@ -297,14 +492,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!
@@ -316,7 +511,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`
@@ -324,14 +519,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
@@ -350,7 +545,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
@@ -358,30 +553,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()`
@@ -391,7 +586,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()`
@@ -400,18 +595,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
@@ -425,7 +620,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
@@ -433,14 +628,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
@@ -451,20 +646,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
@@ -473,14 +668,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
@@ -498,13 +693,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
@@ -537,46 +732,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()`
@@ -584,7 +779,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.
@@ -598,7 +793,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.
@@ -611,7 +806,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
@@ -630,7 +825,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
@@ -653,7 +848,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
@@ -666,7 +861,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
==================
@@ -684,7 +879,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
==================
@@ -819,7 +1014,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
==================
@@ -886,16 +1081,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,6 +1,6 @@
(The MIT License)
Copyright (c) 2009-2011 TJ Holowaychuk <tj@vision-media.ca>
Copyright (c) 2009-2013 TJ Holowaychuk <tj@vision-media.ca>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
+6 -2
Ver Arquivo
@@ -1,5 +1,5 @@
MOCHA_OPTS=
MOCHA_OPTS= --check-leaks
REPORTER = dot
check: test
@@ -26,4 +26,8 @@ lib-cov:
benchmark:
@./support/bench
.PHONY: test test-unit test-acceptance benchmark
clean:
rm -f coverage.html
rm -fr lib-cov
.PHONY: test test-unit test-acceptance benchmark clean
+9 -13
Ver Arquivo
@@ -1,4 +1,3 @@
![express logo](http://f.cl.ly/items/0V2S1n0K1i3y1c122g04/Screen%20Shot%202012-04-11%20at%209.59.42%20AM.png)
Fast, unopinionated, minimalist web framework for [node](http://nodejs.org). [![Build Status](https://secure.travis-ci.org/visionmedia/express.png)](http://travis-ci.org/visionmedia/express)
@@ -18,10 +17,6 @@ app.listen(3000);
$ npm install -g express
To install the 3.0 alpha:
$ npm install -g express@3.0
## Quick Start
The quickest way to get started with express is to utilize the executable `express(1)` to generate an application as shown below:
@@ -56,7 +51,7 @@ app.listen(3000);
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.
Built on Connect you can use _only_ what you need, and nothing more, applications
can be as big or as small as you like, even a single file. Express does
not force you to use any specific ORM or template engine. With support for over
@@ -69,13 +64,14 @@ app.listen(3000);
* [Google Group](http://groups.google.com/group/express-js) for discussion
* Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) on twitter for updates
* Visit the [Wiki](http://github.com/visionmedia/express/wiki)
* [日本語ドキュメンテーション](http://hideyukisaito.com/doc/expressjs/) by [hideyukisaito](https://github.com/hideyukisaito)
* [Русскоязычная документация](http://express-js.ru/)
* [Русскоязычная документация](http://jsman.ru/express/)
* Run express examples [online](https://runnable.com/express)
## Viewing Examples
First install the dev dependencies to install all the example / test suite deps:
Clone the Express repo, then install the dev dependencies to install all the example / test suite deps:
$ git clone git://github.com/visionmedia/express.git --depth 1
$ cd express
$ npm install
@@ -100,14 +96,14 @@ project: express
commits: 3559
active : 468 days
files : 237
authors:
authors:
1891 Tj Holowaychuk 53.1%
1285 visionmedia 36.1%
182 TJ Holowaychuk 5.1%
54 Aaron Heckmann 1.5%
34 csausdev 1.0%
26 ciaranj 0.7%
21 Robert Sköld 0.6%
21 Robert Sköld 0.6%
6 Guillermo Rauch 0.2%
3 Dav Glass 0.1%
3 Nick Poulden 0.1%
@@ -153,11 +149,11 @@ authors:
1 Jonathan Zacsh 0.0%
1 Justin Lilly 0.0%
1 Ken Sato 0.0%
1 Maciej Małecki 0.0%
1 Maciej Małecki 0.0%
1 Masahiro Hayashi 0.0%
```
## License
## License
(The MIT License)
+42 -23
Ver Arquivo
@@ -16,6 +16,7 @@ var exec = require('child_process').exec
program
.version(version)
.usage('[options] [dir]')
.option('-s, --sessions', 'add session support')
.option('-e, --ejs', 'add ejs engine support (defaults to jade)')
.option('-J, --jshtml', 'add jshtml engine support (defaults to jade)')
@@ -30,7 +31,7 @@ var path = program.args.shift() || '.';
// end-of-line code
var eol = 'win32' == os.platform() ? '\r\n' : '\n'
var eol = os.EOL
// Template engine
@@ -54,6 +55,21 @@ var index = [
, '};'
].join(eol);
/**
* Routes users template.
*/
var users = [
''
, '/*'
, ' * GET users listing.'
, ' */'
, ''
, 'exports.list = function(req, res){'
, ' res.send("respond with a resource");'
, '};'
].join(eol);
/**
* Jade layout template.
*/
@@ -193,33 +209,35 @@ var app = [
, ' * Module dependencies.'
, ' */'
, ''
, 'var express = require(\'express\')'
, ' , routes = require(\'./routes\')'
, ' , http = require(\'http\')'
, ' , path = require(\'path\');'
, 'var express = require(\'express\');'
, 'var routes = require(\'./routes\');'
, 'var user = require(\'./routes/user\');'
, 'var http = require(\'http\');'
, 'var path = require(\'path\');'
, ''
, 'var app = express();'
, ''
, 'app.configure(function(){'
, ' app.set(\'port\', process.env.PORT || 3000);'
, ' app.set(\'views\', __dirname + \'/views\');'
, ' app.set(\'view engine\', \':TEMPLATE\');'
, ' app.use(express.favicon());'
, ' app.use(express.logger(\'dev\'));'
, ' app.use(express.bodyParser());'
, ' app.use(express.methodOverride());{sess}'
, ' app.use(app.router);{css}'
, ' app.use(express.static(path.join(__dirname, \'public\')));'
, '});'
, '// all environments'
, 'app.set(\'port\', process.env.PORT || 3000);'
, 'app.set(\'views\', __dirname + \'/views\');'
, 'app.set(\'view engine\', \':TEMPLATE\');'
, 'app.use(express.favicon());'
, 'app.use(express.logger(\'dev\'));'
, 'app.use(express.bodyParser());'
, 'app.use(express.methodOverride());{sess}'
, 'app.use(app.router);{css}'
, 'app.use(express.static(path.join(__dirname, \'public\')));'
, ''
, 'app.configure(\'development\', function(){'
, '// development only'
, 'if (\'development\' == app.get(\'env\')) {'
, ' app.use(express.errorHandler());'
, '});'
, '}'
, ''
, 'app.get(\'/\', routes.index);'
, 'app.get(\'/users\', user.list);'
, ''
, 'http.createServer(app).listen(app.get(\'port\'), function(){'
, ' console.log("Express server listening on port " + app.get(\'port\'));'
, ' console.log(\'Express server listening on port \' + app.get(\'port\'));'
, '});'
, ''
].join(eol);
@@ -280,6 +298,7 @@ function createApplicationAt(path) {
mkdir(path + '/routes', function(){
write(path + '/routes/index.js', index);
write(path + '/routes/user.js', users);
});
mkdir(path + '/views', function(){
@@ -305,10 +324,10 @@ function createApplicationAt(path) {
// CSS Engine support
switch (program.css) {
case 'less':
app = app.replace('{css}', eol + ' app.use(require(\'less-middleware\')({ src: __dirname + \'/public\' }));');
app = app.replace('{css}', eol + 'app.use(require(\'less-middleware\')({ src: __dirname + \'/public\' }));');
break;
case 'stylus':
app = app.replace('{css}', eol + ' app.use(require(\'stylus\').middleware(__dirname + \'/public\'));');
app = app.replace('{css}', eol + 'app.use(require(\'stylus\').middleware(__dirname + \'/public\'));');
break;
default:
app = app.replace('{css}', '');
@@ -316,7 +335,7 @@ function createApplicationAt(path) {
// Session support
app = app.replace('{sess}', program.sessions
? eol + ' app.use(express.cookieParser(\'your secret here\'));' + eol + ' app.use(express.session());'
? eol + 'app.use(express.cookieParser(\'your secret here\'));' + eol + 'app.use(express.session());'
: '');
// Template support
@@ -327,7 +346,7 @@ function createApplicationAt(path) {
name: 'application-name'
, version: '0.0.1'
, private: true
, scripts: { start: 'node app' }
, scripts: { start: 'node app.js' }
, dependencies: {
express: version
}
-25
Ver Arquivo
@@ -1,25 +0,0 @@
var http = require('http');
var times = 50;
while (times--) {
var req = http.request({
port: 3000
, method: 'POST'
, headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
req.on('response', function(res){
console.log(res.statusCode);
});
var n = 500000;
while (n--) {
req.write('foo=bar&bar=baz&');
}
req.write('foo=bar&bar=baz');
req.end();
}
+7 -9
Ver Arquivo
@@ -1,9 +1,8 @@
/**
* Module dependencies.
*/
var express = require('../../lib/express')
var express = require('../..')
, hash = require('./pass').hash;
var app = module.exports = express();
@@ -50,6 +49,7 @@ hash('foobar', function(err, salt, hash){
// Authenticate using our plain-object database of doom!
function authenticate(name, pass, fn) {
if (!module.parent) console.log('authenticating %s:%s', name, pass);
var user = users[name];
@@ -79,7 +79,7 @@ app.get('/', function(req, res){
});
app.get('/restricted', restrict, function(req, res){
res.send('Wahoo! restricted area');
res.send('Wahoo! restricted area, click to <a href="/logout">logout</a>');
});
app.get('/logout', function(req, res){
@@ -91,11 +91,6 @@ app.get('/logout', function(req, res){
});
app.get('/login', function(req, res){
if (req.session.user) {
req.session.success = 'Authenticated as ' + req.session.user.name
+ ' click to <a href="/logout">logout</a>. '
+ ' You may now access <a href="/restricted">/restricted</a>.';
}
res.render('login');
});
@@ -109,6 +104,9 @@ app.post('/login', function(req, res){
// in the session store to be retrieved,
// or in this case the entire user object
req.session.user = user;
req.session.success = 'Authenticated as ' + user.name
+ ' click to <a href="/logout">logout</a>. '
+ ' You may now access <a href="/restricted">/restricted</a>.';
res.redirect('back');
});
} else {
@@ -123,4 +121,4 @@ app.post('/login', function(req, res){
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
}
+5 -3
Ver Arquivo
@@ -31,7 +31,9 @@ var iterations = 12000;
exports.hash = function (pwd, salt, fn) {
if (3 == arguments.length) {
crypto.pbkdf2(pwd, salt, iterations, len, fn);
crypto.pbkdf2(pwd, salt, iterations, len, function(err, hash){
fn(err, (new Buffer(hash, 'binary')).toString('base64'));
});
} else {
fn = salt;
crypto.randomBytes(len, function(err, salt){
@@ -39,8 +41,8 @@ exports.hash = function (pwd, salt, fn) {
salt = salt.toString('base64');
crypto.pbkdf2(pwd, salt, iterations, len, function(err, hash){
if (err) return fn(err);
fn(null, salt, hash);
fn(null, salt, (new Buffer(hash, 'binary')).toString('base64'));
});
});
}
};
};
+2
Ver Arquivo
@@ -0,0 +1,2 @@
</body>
</html>
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>Authentication Example</title>
<title><%= title %></title>
<style>
body {
padding: 50px;
@@ -16,6 +16,3 @@
</style>
</head>
<body>
<%- body %>
</body>
</html>
+7 -1
Ver Arquivo
@@ -1,3 +1,7 @@
<% var title = 'Authentication Example' %>
<% include head %>
<h1>Login</h1>
<%- message %>
Try accessing <a href="/restricted">/restricted</a>, then authenticate with "tj" and "foobar".
@@ -13,4 +17,6 @@ Try accessing <a href="/restricted">/restricted</a>, then authenticate with "tj"
<p>
<input type="submit" value="Login">
</p>
</form>
</form>
<% include foot %>
+1 -1
Ver Arquivo
@@ -1,4 +1,4 @@
style
style.
body {
padding: 50px;
font: 16px "Helvetica Neue", Helvetica;
+2 -1
Ver Arquivo
@@ -1,4 +1,3 @@
/**
* Module dependencies.
*/
@@ -21,11 +20,13 @@ 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');
res.set('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type');
// res.set('Access-Control-Allow-Max-Age', 3600);
if ('OPTIONS' == req.method) return res.send(200);
next();
});
+9 -5
Ver Arquivo
@@ -31,16 +31,20 @@ app.set('view engine', 'html');
// Dummy users
var users = [
{ name: 'tobi', email: 'tobi@learnboost.com' }
, { name: 'loki', email: 'loki@learnboost.com' }
, { name: 'jane', email: 'jane@learnboost.com' }
{ name: 'tobi', email: 'tobi@learnboost.com' },
{ name: 'loki', email: 'loki@learnboost.com' },
{ name: 'jane', email: 'jane@learnboost.com' }
];
app.get('/', function(req, res){
res.render('users', { users: users });
res.render('users', {
users: users,
title: "EJS example",
header: "Some users"
});
});
if (!module.parent) {
app.listen(3000);
console.log('Express app started on port 3000');
}
}
+2
Ver Arquivo
@@ -0,0 +1,2 @@
</body>
</html>
+13
Ver Arquivo
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title> <%= title %> </title>
<style type="text/css">
body {
padding: 50px;
font: 13px Helvetica, Arial, sans-serif;
}
</style>
</head>
<body>
+6 -2
Ver Arquivo
@@ -1,6 +1,10 @@
<% include header.html %>
<h1>Users</h1>
<ul id="users">
<% users.forEach(function(user){ %>
<li><%= user.name %> <%= user.email %></li>
<li><%= user.name %> &lt;<%= user.email %>&gt;</li>
<% }) %>
</ul>
</ul>
<% include footer.html %>
+19 -2
Ver Arquivo
@@ -1,4 +1,3 @@
/**
* Module dependencies.
*/
@@ -7,9 +6,21 @@ var express = require('../../')
, app = module.exports = express()
, silent = 'test' == process.env.NODE_ENV;
// general config
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
// our custom "verbose errors" setting
// which we can use in the templates
// via settings['verbose errors']
app.enable('verbose errors');
// disable them in production
// use $ NODE_ENV=production node examples/error-pages
if ('production' == app.settings.env) {
app.disable('verbose errors');
}
app.use(express.favicon());
silent || app.use(express.logger('dev'));
@@ -32,9 +43,10 @@ app.use(app.router);
// $ curl http://localhost:3000/notfound -H "Accept: text/plain"
app.use(function(req, res, next){
res.status(404);
// respond with html page
if (req.accepts('html')) {
res.status(404);
res.render('404', { url: req.url });
return;
}
@@ -76,16 +88,21 @@ app.get('/', function(req, res){
});
app.get('/404', function(req, res, next){
// trigger a 404 since no other middleware
// will match /404 after this one, and we're not
// responding here
next();
});
app.get('/403', function(req, res, next){
// trigger a 403 error
var err = new Error('not allowed!');
err.status = 403;
next(err);
});
app.get('/500', function(req, res, next){
// trigger a generic (500) error
next(new Error('keyboard cat!'));
});
+4 -1
Ver Arquivo
@@ -7,4 +7,7 @@ extends error
block content
h1 Error: #{error.message}
pre= error.stack
if settings['verbose errors']
pre= error.stack
else
p An error ocurred!
+2 -2
Ver Arquivo
@@ -8,8 +8,8 @@ block content
| visit
a(href="/500") 500
li
| visit
| visit
a(href="/404") 404
li
| visit
| visit
a(href='/403') 403
+2 -2
Ver Arquivo
@@ -1,7 +1,7 @@
html
head
title Express
script
script.
// call this whatever you like,
// or dump them into individual
// props like "var user ="
@@ -10,5 +10,5 @@ html
h1 Expose client data
p The following was exposed to the client:
pre
script
script.
document.write(JSON.stringify(data, null, 2))
+2 -1
Ver Arquivo
@@ -1,3 +1,4 @@
body {
padding: 50px 80px;
font: 14px "Helvetica Nueue", "Lucida Grande", Arial, sans-serif;}
font: 14px "Helvetica Nueue", "Lucida Grande", Arial, sans-serif;
}
+3 -3
Ver Arquivo
@@ -3,9 +3,9 @@
* Module dependencies.
*/
var express = require('../../')
var express = require('../..')
, fs = require('fs')
, md = require('github-flavored-markdown').parse;
, md = require('marked').parse;
var app = module.exports = express();
@@ -42,4 +42,4 @@ app.get('/fail', function(req, res){
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
}
@@ -3,7 +3,7 @@
* Module dependencies.
*/
var express = require('../../')
var express = require('../..')
, format = require('util').format;
var app = module.exports = express()
+2 -3
Ver Arquivo
@@ -1,4 +1,3 @@
var express = require('../..');
var app = module.exports = express();
@@ -58,10 +57,10 @@ app.use(function(req, res, next){
});
*/
next();
// empty or "flush" the messages so they
// don't build up
req.session.messages = [];
next();
});
// load controllers
@@ -90,4 +89,4 @@ app.use(function(req, res, next){
if (!module.parent) {
app.listen(3000);
console.log('\n listening on port 3000\n');
}
}
+54
Ver Arquivo
@@ -0,0 +1,54 @@
// first:
// $ npm install redis online
// $ redis-server
/**
* Module dependencies.
*/
var express = require('../..')
, online = require('online')
, redis = require('redis')
, db = redis.createClient();
// online
online = online(db);
// app
var app = express();
// activity tracking, in this case using
// the UA string, you would use req.user.id etc
app.use(function(req, res, next){
// fire-and-forget
online.add(req.headers['user-agent']);
next();
});
/**
* List helper.
*/
function list(ids) {
return '<ul>' + ids.map(function(id){
return '<li>' + id + '</li>';
}).join('') + '</ul>';
}
/**
* GET users online.
*/
app.get('/', function(req, res, next){
online.last(5, function(err, ids){
if (err) return next(err);
res.send('<p>Users online: ' + ids.length + '</p>' + list(ids));
});
});
app.listen(3000);
console.log('listening on port 3000');
-26
Ver Arquivo
@@ -1,26 +0,0 @@
/**
* Module dependencies.
*/
var vm = require('vm')
, fs = require('fs');
module.exports = function(app, db){
var dir = __dirname + '/routes';
// grab a list of our route files
fs.readdirSync(dir).forEach(function(file){
var str = fs.readFileSync(dir + '/' + file, 'utf8');
// inject some pseudo globals by evaluating
// the file with vm.runInNewContext()
// instead of loading it with require(). require's
// internals use similar, so dont be afraid of "boot time".
var context = { app: app, db: db };
// we have to merge the globals for console, process etc
for (var key in global) context[key] = global[key];
// note that this is essentially no different than ... just using
// global variables, though it's only YOUR code that could influence
// them, which is a bonus.
vm.runInNewContext(str, context, file);
});
};
-20
Ver Arquivo
@@ -1,20 +0,0 @@
/**
* Module dependencies.
*/
var express = require('../../lib/express')
, app = express()
, db = { users: [] };
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
// pretend db is a database, could be
// whatever you like
require('./boot')(app, db);
app.listen(3000);
console.log('Express app started on port 3000');
-4
Ver Arquivo
@@ -1,4 +0,0 @@
app.get('/', function(req, res){
res.render('index');
});
-18
Ver Arquivo
@@ -1,18 +0,0 @@
app.get('/users', function(req, res){
res.render('user/list', { users: db.users });
});
app.get('/user/add', function(req, res){
res.render('user/add');
});
app.post('/user', function(req, res){
var user = req.body.user;
db.users.push(user);
res.redirect('/users');
});
app.get('/user/:id', function(req, res){
res.render('user');
});
-8
Ver Arquivo
@@ -1,8 +0,0 @@
extends layout
block content
h2 Route sharing example
ul
li: a(href='/user/add') Add user
li: a(href='/users') User list
-11
Ver Arquivo
@@ -1,11 +0,0 @@
doctype html
html
head
title Route loading example
style
body {
padding: 50px;
font: 14px/1.5 solid helvetica, arial, sans-serif;
}
body
block content
-9
Ver Arquivo
@@ -1,9 +0,0 @@
extends ../layout
block content
h2 Add a user
form(action='/user', method='post')
p: input(type='text', name='user[name]', placeholder='Username')
p: input(type='text', name='user[email]', placeholder='Email')
p: input(type='submit', value='Add')
-10
Ver Arquivo
@@ -1,10 +0,0 @@
extends ../layout
block content
h1= user.name
table
tbody
tr
td Email
td= user.email
-10
Ver Arquivo
@@ -1,10 +0,0 @@
extends ../layout
block content
h1 Users
if users.length
for user in users
include index
else
p No users, head over to <a href='/user/add'>/user/add</a> to create one.
+4 -2
Ver Arquivo
@@ -11,9 +11,11 @@ var express = require('../..')
// Config
app.set('view engine', 'ejs');
app.set('view engine', 'jade');
app.set('views', __dirname + '/views');
app.use(express.logger('dev'));
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.static(__dirname + '/public'));
@@ -35,4 +37,4 @@ app.put('/user/:id/edit', user.update);
app.get('/posts', post.list);
app.listen(3000);
console.log('Express app started on port 3000');
console.log('Express app started on port 3000');
+3 -3
Ver Arquivo
@@ -2,9 +2,9 @@
// Fake posts database
var posts = [
{ title: 'Foo', body: 'some foo bar' }
, { title: 'Foo bar', body: 'more foo bar' }
, { title: 'Foo bar baz', body: 'more foo bar baz' }
{ title: 'Foo', body: 'some foo bar' },
{ title: 'Foo bar', body: 'more foo bar' },
{ title: 'Foo bar baz', body: 'more foo bar baz' }
];
exports.list = function(req, res){
+2 -2
Ver Arquivo
@@ -11,10 +11,10 @@ a.edit {
opacity: .3;
}
a.edit::before {
content: '[ ';
content: ' [';
}
a.edit::after {
content: ' ]';
content: ']';
}
dt {
font-weight: bold;
+6 -6
Ver Arquivo
@@ -2,8 +2,8 @@
// Fake user database
var users = [
{ name: 'TJ', email: 'tj@vision-media.ca' }
, { name: 'Tobi', email: 'tobi@vision-media.ca' }
{ name: 'TJ', email: 'tj@vision-media.ca' },
{ name: 'Tobi', email: 'tobi@vision-media.ca' }
];
exports.list = function(req, res){
@@ -22,15 +22,15 @@ exports.load = function(req, res, next){
exports.view = function(req, res){
res.render('users/view', {
title: 'Viewing user ' + req.user.name
, user: req.user
title: 'Viewing user ' + req.user.name,
user: req.user
});
};
exports.edit = function(req, res){
res.render('users/edit', {
title: 'Editing user ' + req.user.name
, user: req.user
title: 'Editing user ' + req.user.name,
user: req.user
});
};
-4
Ver Arquivo
@@ -1,4 +0,0 @@
<ul>
<li>Visit the <a href="/users">users</a> page</li>
<li>Visit the <a href="/posts">posts</a> page</li>
</ul>
+6
Ver Arquivo
@@ -0,0 +1,6 @@
extends layout
block content
ul
li Visit the <a href="/users">users</a> page
li Visit the <a href="/posts">posts</a> page
-9
Ver Arquivo
@@ -1,9 +0,0 @@
<html>
<head>
<title><%= title %></title>
<link href="/style.css" rel="stylesheet" />
</head>
<body>
<%- body %>
</body>
</html>
@@ -0,0 +1,6 @@
html
head
title= title
link(href="/style.css", rel="stylesheet")
body
block content
@@ -1,7 +0,0 @@
<h1>Posts</h1>
<dl id="posts">
<% posts.forEach(function(post){ %>
<dt><%= post.title %></dt>
<dd><%= post.body %></dd>
<% }) %>
</dl>
@@ -0,0 +1,8 @@
extends ../layout
block content
h1 Posts
dl#posts
for post in posts
dt= post.title
dd= post.body
@@ -1,9 +0,0 @@
<h1>Editing <%= user.name %></h1>
<div id="user">
<form method="post">
<input type="hidden" value="put" name="_method" />
<p>Name: <input type="text" value="<%= user.name %>" name="user[name]"/></p>
<p>Email: <input type="text" value="<%= user.email %>" name="user[email]"/></p>
<p><input type="submit" value="Save" /></p>
</form>
</div>
@@ -0,0 +1,13 @@
extends ../layout
block content
h1 Editing #{user.name}
#user
form(method="post")
input(type="hidden", value="put", name="_method")
p Name:
input(type="text", value= user.name, name="user[name]")
p Email:
input(type="text", value= user.email, name="user[email]")
p
input(type="submit", value="Save")
@@ -1,9 +0,0 @@
<h1>Users</h1>
<ul id="users">
<% users.forEach(function(user, id){ %>
<li>
<a href="/user/<%= id %>"><%= user.name %></a>
<a class="edit" href="/user/<%= id %>/edit">edit</a>
</li>
<% }) %>
</ul>
@@ -0,0 +1,9 @@
extends ../layout
block content
h1 Users
#users
for user, i in users
li
a(href="/user/#{i}")= user.name
a.edit(href="/user/#{i}/edit") edit
@@ -1,4 +0,0 @@
<h1><%= user.name %></h1>
<div id="user">
<p>Email: <%= user.email %></p>
</div>
@@ -0,0 +1,6 @@
extends ../layout
block content
h1= user.name
#user
p Email: #{user.email}
+14
Ver Arquivo
@@ -0,0 +1,14 @@
var search = document.querySelector('[type=search]');
var code = document.querySelector('pre');
search.addEventListener('keyup', function(){
var xhr = new XMLHttpRequest;
xhr.open('GET', '/search/' + search.value, true);
xhr.onreadystatechange = function(){
if (4 == xhr.readyState) {
code.textContent = xhr.responseText;
}
};
xhr.send();
}, false);
+61
Ver Arquivo
@@ -0,0 +1,61 @@
// first:
// $ npm install redis
// $ redis-server
/**
* Module dependencies.
*/
var express = require('../..')
, redis = require('redis')
, db = redis.createClient();
// npm install redis
var app = express();
app.set('view engine', 'jade');
app.set('views', __dirname);
// populate search
db.sadd('ferret', 'tobi');
db.sadd('ferret', 'loki');
db.sadd('ferret', 'jane');
db.sadd('cat', 'manny');
db.sadd('cat', 'luna');
/**
* GET the search page.
*/
app.get('/', function(req, res){
res.render('search');
});
/**
* GET search for :query.
*/
app.get('/search/:query?', function(req, res){
var query = req.params.query;
db.smembers(query, function(err, vals){
if (err) return res.send(500);
res.send(vals);
});
});
/**
* GET client javascript. Here we use sendfile()
* because serving __dirname with the static() middleware
* would also mean serving our server "index.js" and the "search.jade"
* template.
*/
app.get('/client.js', function(req, res){
res.sendfile(__dirname + '/client.js');
});
app.listen(3000);
console.log('app listening on port 3000');
+15
Ver Arquivo
@@ -0,0 +1,15 @@
!!! 5
html
head
title Search example
style.
body {
font: 14px "Helvetica Neue", Helvetica;
padding: 50px;
}
body
h2 Search
p Try searching for "ferret" or "cat".
input(type='search')
pre
script(src='client.js')
+5 -1
Ver Arquivo
@@ -1,4 +1,8 @@
// first:
// $ npm install redis
// $ redis-server
var express = require('../..');
var app = express();
@@ -25,4 +29,4 @@ app.get('/', function(req, res){
});
app.listen(3000);
console.log('Express app started on port 3000');
console.log('Express app started on port 3000');
+44
Ver Arquivo
@@ -0,0 +1,44 @@
var express = require('../..');
var app = express();
// log requests
app.use(express.logger('dev'));
// express on its own has no notion
// of a "file". The express.static()
// middleware checks for a file matching
// the `req.path` within the directory
// that you pass it. In this case "GET /js/app.js"
// will look for "./public/js/app.js".
app.use(express.static(__dirname + '/public'));
// if you wanted to "prefix" you may use
// the mounting feature of Connect, for example
// "GET /static/js/app.js" instead of "GET /js/app.js".
// The mount-path "/static" is simply removed before
// passing control to the express.static() middleware,
// thus it serves the file correctly by ignoring "/static"
app.use('/static', express.static(__dirname + '/public'));
// if for some reason you want to serve files from
// several directories, you can use express.static()
// multiple times! Here we're passing "./public/css",
// this will allow "GET /style.css" instead of "GET /css/style.css":
app.use(express.static(__dirname + '/public/css'));
// this examples does not have any routes, however
// you may `app.use(app.router)` before or after these
// static() middleware. If placed before them your routes
// will be matched BEFORE file serving takes place. If placed
// after as shown here then file serving is performed BEFORE
// any routes are hit:
app.use(app.router);
app.listen(3000);
console.log('listening on port 3000');
console.log('try:');
console.log(' GET /hello.txt');
console.log(' GET /js/app.js');
console.log(' GET /css/style.css');
+3
Ver Arquivo
@@ -0,0 +1,3 @@
body {
}
+1
Ver Arquivo
@@ -0,0 +1 @@
hey
+1
Ver Arquivo
@@ -0,0 +1 @@
foo
+18 -22
Ver Arquivo
@@ -1,50 +1,46 @@
/**
* Module dependencies.
*/
var express = require('../..');
// Edit /etc/vhosts
/*
edit /etc/hosts:
// 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 server 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
// Vhost 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)) // Serves all subdomains via Redirect app
app.use(express.vhost('example.com', main)); // Serves top level domain via Main server app
app.listen(3000);
console.log('Express app started on port 3000');
console.log('Express app started on port 3000');
+52
Ver Arquivo
@@ -0,0 +1,52 @@
/**
* Module dependencies.
*/
var http = require('http')
, path = require('path')
, extname = path.extname
/**
* Expose `GithubView`.
*/
module.exports = GithubView;
/**
* Custom view that fetches and renders
* remove github templates. You could
* render templates from a database etc.
*/
function GithubView(name, options){
this.name = name;
options = options || {};
this.engine = options.engines[extname(name)];
// "root" is the app.set('views') setting, however
// in your own implementation you could ignore this
this.path = '/' + options.root + '/master/' + name;
}
/**
* Render the view.
*/
GithubView.prototype.render = function(options, fn){
var self = this;
var opts = {
host: 'rawgithub.com',
port: 80,
path: this.path,
method: 'GET'
};
http.request(opts, function(res) {
var buf = '';
res.setEncoding('utf8');
res.on('data', function(str){ buf += str });
res.on('end', function(){
self.engine(buf, options, fn);
});
}).end();
};
+47
Ver Arquivo
@@ -0,0 +1,47 @@
/**
* Module dependencies.
*/
var express = require('../../')
, http = require('http')
, GithubView = require('./github-view')
, md = require('marked').parse;
var app = module.exports = express();
// register .md as an engine in express view system
app.engine('md', function(str, options, fn){
try {
var html = md(str);
html = html.replace(/\{([^}]+)\}/g, function(_, name){
return options[name] || '';
})
fn(null, html);
} catch(err) {
fn(err);
}
})
// pointing to a particular github repo to load files from it
app.set('views', 'visionmedia/express');
// register a new view constructor
app.set('view', GithubView);
app.get('/', function(req, res){
// rendering a view relative to the repo.
// app.locals, res.locals, and locals passed
// work like they normally would
res.render('examples/markdown/views/index.md', { title: 'Example' });
})
app.get('/Readme.md', function(req, res){
// rendering a view from https://github.com/visionmedia/express/blob/master/Readme.md
res.render('Readme.md');
})
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
-5
Ver Arquivo
@@ -101,11 +101,6 @@ app.get('/middleware-locals', count2, users2, function(req, res, next){
res.render('user', { title: 'Users' });
});
app.get('/locals', function(req, res){
res.render('user', { title: 'Users' });
});
// keep in mind that middleware may be placed anywhere
// and in various combinations, so if you have locals
// that you wish to make available to all subsequent
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@ doctype 5
html
head
title= title
style
style.
body {
padding: 50px;
font: 16px Helvetica, Arial;
+33 -31
Ver Arquivo
@@ -9,12 +9,10 @@ var connect = require('connect')
, debug = require('debug')('express:application')
, locals = require('./utils').locals
, View = require('./view')
, url = require('url')
, utils = connect.utils
, path = require('path')
, http = require('http')
, join = path.join
, fs = require('fs');
, join = path.join;
/**
* Application prototype.
@@ -33,11 +31,9 @@ var app = exports = module.exports = {};
*/
app.init = function(){
var self = this;
this.cache = {};
this.settings = {};
this.engines = {};
this.viewCallbacks = [];
this.defaultConfiguration();
};
@@ -48,10 +44,11 @@ app.init = function(){
*/
app.defaultConfiguration = function(){
var self = this;
// default settings
this.enable('x-powered-by');
this.enable('etag');
this.set('env', process.env.NODE_ENV || 'development');
this.set('subdomain offset', 2);
debug('booting in %s mode', this.get('env'));
// implicit middleware
@@ -63,6 +60,7 @@ app.defaultConfiguration = function(){
this.request.__proto__ = parent.request;
this.response.__proto__ = parent.response;
this.engines.__proto__ = parent.engines;
this.settings.__proto__ = parent.settings;
});
// router
@@ -82,7 +80,8 @@ app.defaultConfiguration = function(){
this.locals.settings = this.settings;
// default configuration
this.enable('jsonp callback');
this.set('view', View);
this.set('views', process.cwd() + '/views');
this.set('jsonp callback name', 'callback');
this.configure('development', function(){
@@ -105,7 +104,7 @@ app.defaultConfiguration = function(){
*/
app.use = function(route, fn){
var app, home, handle;
var app;
// default route to '/'
if ('string' != typeof route) fn = route, route = '/';
@@ -119,7 +118,6 @@ app.use = function(route, fn){
fn = function(req, res, next) {
var orig = req.app;
app.handle(req, res, function(err){
req.app = res.app = orig;
req.__proto__ = orig.request;
res.__proto__ = orig.response;
next(err);
@@ -164,7 +162,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 seamlessly within Express.
*
* @param {String} ext
* @param {Function} fn
@@ -187,7 +185,7 @@ app.engine = function(ext, fn){
* could automatically load a user's information from the database without
* any additional code,
*
* The callback uses the samesignature as middleware, the only differencing
* The callback uses the same signature as middleware, the only differencing
* 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.
@@ -253,11 +251,7 @@ app.param = function(name, fn){
app.set = function(setting, val){
if (1 == arguments.length) {
if (this.settings.hasOwnProperty(setting)) {
return this.settings[setting];
} else if (this.parent) {
return this.parent.set(setting);
}
return this.settings[setting];
} else {
this.settings[setting] = val;
return this;
@@ -401,16 +395,25 @@ 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 ('get' == method && 1 == arguments.length) return this.set(path);
// deprecated
if (Array.isArray(path)) {
console.trace('passing an array to app.VERB() is deprecated and will be removed in 4.0');
}
// if no router attached yet, attach the router
if (!this._usedRouter) this.use(this.router);
return this._router.route.apply(this._router, args);
}
// setup route
this._router[method].apply(this._router, arguments);
return this;
};
});
/**
@@ -453,8 +456,7 @@ app.del = app.delete;
*/
app.render = function(name, options, fn){
var self = this
, opts = {}
var opts = {}
, cache = this.cache
, engines = this.engines
, view;
@@ -467,8 +469,8 @@ app.render = function(name, options, fn){
// merge app.locals
utils.merge(opts, this.locals);
// merge options.locals
if (options.locals) utils.merge(opts, options.locals);
// merge options._locals
if (options._locals) utils.merge(opts, options._locals);
// merge options
utils.merge(opts, options);
@@ -483,10 +485,10 @@ app.render = function(name, options, fn){
// view
if (!view) {
view = new View(name, {
defaultEngine: this.get('view engine')
, root: this.get('views') || process.cwd() + '/views'
, engines: engines
view = new (this.get('view'))(name, {
defaultEngine: this.get('view engine'),
root: this.get('views'),
engines: engines
});
if (!view.path) {
@@ -522,7 +524,7 @@ app.render = function(name, options, fn){
* , app = express();
*
* http.createServer(app).listen(80);
* http.createServer({ ... }, app).listen(443);
* https.createServer({ ... }, app).listen(443);
*
* @return {http.Server}
* @api public
+5 -14
Ver Arquivo
@@ -1,16 +1,13 @@
/**
* Module dependencies.
*/
var http = require('http')
, connect = require('connect')
var connect = require('connect')
, proto = require('./application')
, Route = require('./router/route')
, Router = require('./router')
, req = require('./request')
, res = require('./response')
, send = require('send')
, utils = connect.utils;
/**
@@ -19,17 +16,11 @@ var http = require('http')
exports = module.exports = createApplication;
/**
* Framework version.
*/
exports.version = '3.0.0rc2';
/**
* Expose mime.
*/
exports.mime = send.mime;
exports.mime = connect.mime;
/**
* Create an express application.
@@ -41,15 +32,15 @@ exports.mime = send.mime;
function createApplication() {
var app = connect();
utils.merge(app, proto);
app.request = { __proto__: req };
app.response = { __proto__: res };
app.request = { __proto__: req, app: app };
app.response = { __proto__: res, app: app };
app.init();
return app;
}
/**
* Expose connect.middleware as express.*
* for example `express.logger` etc.
* for example `express.logger` etc.
*/
for (var key in connect.middleware) {
+1 -2
Ver Arquivo
@@ -17,8 +17,7 @@ var utils = require('./utils');
exports.init = function(app){
return function expressInit(req, res, next){
req.app = res.app = app;
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;
+78 -33
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':
@@ -63,11 +63,12 @@ req.header = function(name){
* The `type` value may be a single mime type string
* such as "application/json", the extension name
* such as "json", a comma-delimted 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"
@@ -89,6 +90,7 @@ req.header = function(name){
*
* // Accept: text/*;q=.5, application/json
* req.accepts(['html', 'json']);
* req.accepts('html', 'json');
* req.accepts('html, json');
* // => "json"
*
@@ -98,7 +100,20 @@ req.header = function(name){
*/
req.accepts = function(type){
return utils.accepts(type, this.get('Accept'));
var args = arguments.length > 1 ? [].slice.apply(arguments) : type;
return utils.accepts(args, this.get('Accept'));
};
/**
* Check if the given `encoding` is accepted.
*
* @param {String} encoding
* @return {Boolean}
* @api public
*/
req.acceptsEncoding = function(encoding){
return !! ~this.acceptedEncodings.indexOf(encoding);
};
/**
@@ -113,7 +128,7 @@ req.accepts = function(type){
req.acceptsCharset = function(charset){
var accepted = this.acceptedCharsets;
return accepted.length
? ~accepted.indexOf(charset)
? !! ~accepted.indexOf(charset)
: true;
};
@@ -129,7 +144,7 @@ req.acceptsCharset = function(charset){
req.acceptsLanguage = function(lang){
var accepted = this.acceptedLanguages;
return accepted.length
? ~accepted.indexOf(lang)
? !! ~accepted.indexOf(lang)
: true;
};
@@ -159,6 +174,24 @@ req.range = function(size){
return parseRange(size, range);
};
/**
* Return an array of encodings.
*
* Examples:
*
* ['gzip', 'deflate']
*
* @return {Array}
* @api public
*/
req.__defineGetter__('acceptedEncodings', function(){
var accept = this.get('Accept-Encoding');
return accept
? accept.trim().split(/ *, */)
: [];
});
/**
* Return an array of Accepted media types
* ordered from highest quality to lowest.
@@ -202,7 +235,7 @@ req.__defineGetter__('acceptedLanguages', function(){
var accept = this.get('Accept-Language');
return accept
? utils
.parseQuality(accept)
.parseParams(accept)
.map(function(obj){
return obj.value;
})
@@ -226,7 +259,7 @@ req.__defineGetter__('acceptedCharsets', function(){
var accept = this.get('Accept-Charset');
return accept
? utils
.parseQuality(accept)
.parseParams(accept)
.map(function(obj){
return obj.value;
})
@@ -245,7 +278,7 @@ req.__defineGetter__('acceptedCharsets', function(){
* the `connect.bodyParser()` middleware.
*
* @param {String} name
* @param {Mixed} defaultValue
* @param {Mixed} [defaultValue]
* @return {String}
* @api public
*/
@@ -261,7 +294,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 +304,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 +336,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
@@ -315,11 +348,10 @@ req.is = function(type){
req.__defineGetter__('protocol', function(){
var trustProxy = this.app.get('trust proxy');
return this.connection.encrypted
? 'https'
: trustProxy
? (this.get('X-Forwarded-Proto') || 'http')
: 'http';
if (this.connection.encrypted) return 'https';
if (!trustProxy) return 'http';
var proto = this.get('X-Forwarded-Proto') || 'http';
return proto.split(/\s*,\s*/)[0];
});
/**
@@ -377,39 +409,48 @@ req.__defineGetter__('ips', function(){
* req.auth
* // => { username: 'tobi', password: 'hello' }
*
* @return {Object}
* @return {Object} or undefined
* @api public
*/
req.__defineGetter__('auth', function(){
// missing
var auth = this.get('Authorization');
if (!auth) return {};
if (!auth) return;
// malformed
auth = auth.split(' ')[1];
if (!auth) return {};
var parts = auth.split(' ');
if ('basic' != parts[0].toLowerCase()) return;
if (!parts[1]) return;
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(){
return this.get('Host')
var offset = this.app.get('subdomain offset');
return (this.host || '')
.split('.')
.slice(0, -2)
.reverse();
.reverse()
.slice(offset);
});
/**
@@ -431,7 +472,11 @@ req.__defineGetter__('path', function(){
*/
req.__defineGetter__('host', function(){
return this.get('Host').split(':')[0];
var trustProxy = this.app.get('trust proxy');
var host = trustProxy && this.get('X-Forwarded-Host');
host = host || this.get('Host');
if (!host) return;
return host.split(':')[0];
});
/**
+160 -77
Ver Arquivo
@@ -2,18 +2,17 @@
* Module dependencies.
*/
var fs = require('fs')
, http = require('http')
var http = require('http')
, path = require('path')
, connect = require('connect')
, utils = connect.utils
, sign = require('cookie-signature').sign
, normalizeType = require('./utils').normalizeType
, normalizeTypes = require('./utils').normalizeTypes
, etag = require('./utils').etag
, statusCodes = http.STATUS_CODES
, send = connect.static.send
, cookie = require('cookie')
, send = require('send')
, crc = require('crc')
, mime = connect.mime
, basename = path.basename
, extname = path.extname
@@ -79,9 +78,12 @@ res.links = function(links){
*/
res.send = function(body){
var req = this.req
, head = 'HEAD' == req.method
, len;
var req = this.req;
var head = 'HEAD' == req.method;
var len;
// settings
var app = this.app;
// allow status / body
if (2 == arguments.length) {
@@ -94,9 +96,6 @@ res.send = function(body){
}
}
// convert string objects to primitives
if (body instanceof String) body = body.toString();
switch (typeof body) {
// response status
case 'number':
@@ -132,10 +131,10 @@ res.send = function(body){
// ETag support
// TODO: W/ support
if (len > 1024) {
if (!this.get('ETag')) this.set('ETag', Buffer.isBuffer(body)
? crc.buffer.crc32(body)
: crc.crc32(body));
if (app.settings.etag && len > 1024 && 'GET' == req.method) {
if (!this.get('ETag')) {
this.set('ETag', etag(body));
}
}
// freshness
@@ -145,6 +144,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 = '';
}
@@ -182,21 +182,65 @@ res.json = function(obj){
}
// settings
var app = this.app
, jsonp = app.get('jsonp callback')
, replacer = app.get('json replacer')
, spaces = app.get('json spaces')
, body = JSON.stringify(obj, replacer, spaces)
, callback = this.req.query[app.get('jsonp callback name')];
var app = this.app;
var replacer = app.get('json replacer');
var spaces = app.get('json spaces');
var body = JSON.stringify(obj, replacer, spaces);
// content-type
this.charset = this.charset || 'utf-8';
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' });
* res.jsonp(500, 'oh noes!');
* res.jsonp(404, 'I dont have that');
*
* @param {Mixed} obj or status
* @param {Mixed} obj
* @return {ServerResponse}
* @api public
*/
res.jsonp = function(obj){
// allow status / body
if (2 == arguments.length) {
// res.json(body, status) backwards compat
if ('number' == typeof arguments[1]) {
this.statusCode = arguments[1];
} else {
this.statusCode = obj;
obj = arguments[1];
}
}
// settings
var app = this.app;
var replacer = app.get('json replacer');
var spaces = app.get('json 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 && jsonp) {
if (callback) {
if (callback instanceof Array) callback = callback[0];
this.set('Content-Type', 'text/javascript');
body = callback.replace(/[^[]\w$.]/g, '') + '(' + body + ');';
var cb = callback.replace(/[^\[\]\w$.]/g, '');
body = cb + ' && ' + cb + '(' + body + ');';
}
return this.send(body);
@@ -204,7 +248,7 @@ res.json = 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`
@@ -226,7 +270,7 @@ res.json = 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);
@@ -371,11 +415,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' });
* }
@@ -388,11 +432,11 @@ res.type = function(type){
* text: function(){
* res.send('hey');
* },
*
*
* html: function(){
* res.send('<p>hey</p>');
* },
*
*
* json: function(){
* res.send({ message: 'hey' });
* }
@@ -410,26 +454,26 @@ res.type = function(type){
*/
res.format = function(obj){
var keys = Object.keys(obj)
, req = this.req
var req = this.req
, next = req.next;
var fn = obj.default;
if (fn) delete obj.default;
var keys = Object.keys(obj);
var key = req.accepts(keys);
this.set('Vary', 'Accept');
if (key) {
this.set('Content-Type', normalizeType(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 = 406;
err.types = normalizeTypes(keys);
err.types = normalizeTypes(keys).map(function(o){ return o.value });
next(err);
}
@@ -458,24 +502,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;
@@ -533,21 +580,25 @@ 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 ('number' == typeof val) val = val.toString();
if ('object' == typeof val) val = 'j:' + JSON.stringify(val);
if (signed) val = utils.sign(val, secret);
if ('maxAge' in options) options.expires = new Date(Date.now() + options.maxAge);
if (signed) val = 's:' + sign(val, secret);
if ('maxAge' in options) {
options.expires = new Date(Date.now() + options.maxAge);
options.maxAge /= 1000;
}
if (null == options.path) options.path = '/';
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
@@ -555,41 +606,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('../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) {
status = url;
url = arguments[1];
}
, req = this.req;
// setup redirect map
var map = { back: req.get('Referrer') || '/' };
@@ -599,25 +639,69 @@ res.redirect = function(url){
// relative
if (!~url.indexOf('://') && 0 != url.indexOf('//')) {
var path = app.path();
var path
// relative to path
if ('.' == url[0]) {
url = req.path + '/' + url;
// relative to mount-point
path = req.originalUrl.split('?')[0]
url = path + ('/' == path[path.length - 1] ? '' : '/') + url;
// relative to mount-point
} else if ('/' != url[0]) {
path = app.path();
url = path + '/' + url;
}
// Absolute
var host = req.get('Host');
url = '//' + host + 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(){
@@ -632,7 +716,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);
};
@@ -665,7 +748,7 @@ res.render = function(view, options, fn){
}
// merge res.locals
options.locals = self.locals;
options._locals = self.locals;
// default callback to respond
fn = fn || function(err, str){
@@ -675,4 +758,4 @@ res.render = function(view, options, fn){
// render
app.render(view, options, fn);
};
};
+25 -9
Ver Arquivo
@@ -4,9 +4,9 @@
var Route = require('./route')
, utils = require('../utils')
, methods = require('methods')
, debug = require('debug')('express:router')
, parse = require('connect').utils.parseUrl
, methods = require('methods');
, parse = require('connect').utils.parseUrl;
/**
* Expose `Router` constructor.
@@ -16,7 +16,7 @@ exports = module.exports = Router;
/**
* Initialize a new `Router` with the given `options`.
*
*
* @param {Object} options
* @api private
*/
@@ -93,8 +93,7 @@ Router.prototype._dispatch = function(req, res, next){
, paramVal
, route
, keys
, key
, ret;
, key;
// match next route
function nextRoute(err) {
@@ -144,7 +143,7 @@ Router.prototype._dispatch = function(req, res, next){
};
param(err);
// single param callbacks
function paramCallback(err) {
var fn = paramCallbacks[paramIndex++];
@@ -162,7 +161,8 @@ Router.prototype._dispatch = function(req, res, next){
if (fn.length < 4) return callbacks(err);
fn(err, req, res, callbacks);
} else if (fn) {
fn(req, res, callbacks);
if (fn.length < 4) return fn(req, res, callbacks);
callbacks();
} else {
nextRoute(err);
}
@@ -282,14 +282,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;
};
});
+77 -33
Ver Arquivo
@@ -3,12 +3,31 @@
* Module dependencies.
*/
var mime = require('connect').mime;
var mime = require('connect').mime
, crc32 = require('buffer-crc32');
/**
* toString ref.
*/
var toString = {}.toString;
/**
* Return ETag for `body`.
*
* @param {String|Buffer} body
* @return {String}
* @api private
*/
exports.etag = function(body){
return '"' + crc32.signed(body) + '"';
};
/**
* Make `locals()` bound to the given `obj`.
*
* This is used for `app.locals` and `res.locals`.
*
* This is used for `app.locals` and `res.locals`.
*
* @param {Object} obj
* @return {Function}
@@ -16,8 +35,6 @@ var mime = require('connect').mime;
*/
exports.locals = function(obj){
obj.viewCallbacks = obj.viewCallbacks || [];
function locals(obj){
for (var key in obj) locals[key] = obj[key];
return obj;
@@ -64,12 +81,14 @@ exports.flatten = function(arr, ret){
* Normalize the given `type`, for example "html" becomes "text/html".
*
* @param {String} type
* @return {String}
* @return {Object}
* @api private
*/
exports.normalizeType = function(type){
return ~type.indexOf('/') ? type : mime.lookup(type);
return ~type.indexOf('/')
? acceptParams(type)
: { value: mime.lookup(type), params: {} };
};
/**
@@ -84,9 +103,7 @@ exports.normalizeTypes = function(types){
var ret = [];
for (var i = 0; i < types.length; ++i) {
ret.push(~types[i].indexOf('/')
? types[i]
: mime.lookup(types[i]));
ret.push(exports.normalizeType(types[i]));
}
return ret;
@@ -112,7 +129,7 @@ exports.acceptsArray = function(types, str){
for (var i = 0; i < len; ++i) {
for (var j = 0, jlen = types.length; j < jlen; ++j) {
if (exports.accept(normalized[j].split('/'), accepted[i])) {
if (exports.accept(normalized[j], accepted[i])) {
return types[j];
}
}
@@ -137,17 +154,34 @@ exports.accepts = function(type, str){
/**
* Check if `type` array is acceptable for `other`.
*
* @param {Array} type
* @param {Object} type
* @param {Object} other
* @return {Boolean}
* @api private
*/
exports.accept = function(type, other){
return (type[0] == other.type || '*' == other.type)
&& (type[1] == other.subtype || '*' == other.subtype);
var t = type.value.split('/');
return (t[0] == other.type || '*' == other.type)
&& (t[1] == other.subtype || '*' == other.subtype)
&& paramsEqual(type.params, other.params);
};
/**
* Check if accept params are equal.
*
* @param {Object} a
* @param {Object} b
* @return {Boolean}
* @api private
*/
function paramsEqual(a, b){
return !Object.keys(a).some(function(k) {
return a[k] != b[k];
});
}
/**
* Parse accept `str`, returning
* an array objects containing
@@ -162,7 +196,7 @@ exports.accept = function(type, other){
exports.parseAccept = function(str){
return exports
.parseQuality(str)
.parseParams(str)
.map(function(obj){
var parts = obj.value.split('/');
obj.type = parts[0];
@@ -173,44 +207,54 @@ exports.parseAccept = function(str){
/**
* Parse quality `str`, returning an
* array of objects with `.value` and
* `.quality`.
* array of objects with `.value`,
* `.quality` and optional `.params`
*
* @param {Type} name
* @return {Type}
* @param {String} str
* @return {Array}
* @api private
*/
exports.parseQuality = function(str){
exports.parseParams = function(str){
return str
.split(/ *, */)
.map(quality)
.map(acceptParams)
.filter(function(obj){
return obj.quality;
})
.sort(function(a, b){
return b.quality - a.quality;
if (a.quality === b.quality) {
return a.originalIndex - b.originalIndex;
} else {
return b.quality - a.quality;
}
});
};
/**
* Parse quality `str` returning an
* object with `.value` and `.quality`.
* 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 quality(str) {
var parts = str.split(/ *; */)
, val = parts[0];
function acceptParams(str, index) {
var parts = str.split(/ *; */);
var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index };
var q = parts[1]
? parseFloat(parts[1].split(/ *= */)[1])
: 1;
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 { value: val, quality: q };
return ret;
}
/**
@@ -247,7 +291,7 @@ exports.escape = function(html) {
*/
exports.pathRegexp = function(path, keys, sensitive, strict) {
if (path instanceof RegExp) return path;
if (toString.call(path) == '[object RegExp]') return path;
if (Array.isArray(path)) path = '(' + path.join('|') + ')';
path = path
.concat(strict ? '' : '/?')
@@ -266,4 +310,4 @@ exports.pathRegexp = function(path, keys, sensitive, strict) {
.replace(/([\/.])/g, '\\$1')
.replace(/\*/g, '(.*)');
return new RegExp('^' + path + '$', sensitive ? '' : 'i');
}
}
+6 -5
Ver Arquivo
@@ -8,7 +8,7 @@ var path = require('path')
, dirname = path.dirname
, basename = path.basename
, extname = path.extname
, exists = fs.existsSync || path.existsSync
, exists = fs.existsSync || path.existsSync
, join = path.join;
/**
@@ -22,9 +22,9 @@ module.exports = View;
*
* Options:
*
* - `defaultEngine` the default template engine name
* - `engines` template engine require() cache
* - `root` root path for view lookup
* - `defaultEngine` the default template engine name
* - `engines` template engine require() cache
* - `root` root path for view lookup
*
* @param {String} name
* @param {Object} options
@@ -38,7 +38,8 @@ 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 && !this.defaultEngine) throw new Error('No default engine was specified and no extension was provided.');
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);
}
+36 -21
Ver Arquivo
@@ -1,36 +1,49 @@
{
"name": "express",
"description": "Sinatra inspired web development framework",
"version": "3.0.0rc2",
"version": "3.3.6",
"author": "TJ Holowaychuk <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" }
"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.4.2",
"commander": "0.6.1",
"connect": "2.8.5",
"commander": "1.2.0",
"range-parser": "0.0.4",
"mkdirp": "0.3.3",
"cookie": "0.0.4",
"crc": "0.2.0",
"fresh": "0.1.0",
"mkdirp": "0.3.5",
"cookie": "0.1.0",
"buffer-crc32": "0.2.1",
"fresh": "0.2.0",
"methods": "0.0.1",
"send": "0.0.3",
"send": "0.1.4",
"cookie-signature": "1.0.1",
"debug": "*"
},
"devDependencies": {
"ejs": "*",
"mocha": "*",
"jade": "*",
"jade": "0.30.0",
"hjs": "*",
"stylus": "*",
"should": "*",
"connect-redis": "*",
"github-flavored-markdown": "*",
"supertest": "0.0.1"
"marked": "*",
"supertest": "0.6.0"
},
"keywords": [
"express",
@@ -43,14 +56,16 @@
"app",
"api"
],
"publishConfig": { "tag": "3.0" },
"repository": "git://github.com/visionmedia/express",
"main": "index",
"bin": { "express": "./bin/express" },
"bin": {
"express": "./bin/express"
},
"scripts": {
"prepublish" : "npm prune",
"prepublish": "npm prune",
"test": "make test"
},
"engines": { "node": "*" }
"engines": {
"node": "*"
}
}
+1 -3
Ver Arquivo
@@ -16,8 +16,6 @@ app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.locals.self = true;
var repo = require('../package.json');
app.get('/render', function(req, res){
res.render('hello');
});
@@ -65,4 +63,4 @@ app.get('/match', function(req, res){
res.send('Hello World\n');
});
app.listen(8000);
app.listen(8000);
+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(){});
})
})
})
+3 -3
Ver Arquivo
@@ -10,9 +10,9 @@ describe('ejs', function(){
.end(function(err, res){
res.should.have.status(200);
res.should.have.header('Content-Type', 'text/html; charset=utf-8');
res.text.should.include('<li>tobi tobi@learnboost.com</li>');
res.text.should.include('<li>loki loki@learnboost.com</li>');
res.text.should.include('<li>jane jane@learnboost.com</li>');
res.text.should.include('<li>tobi &lt;tobi@learnboost.com&gt;</li>');
res.text.should.include('<li>loki &lt;loki@learnboost.com&gt;</li>');
res.text.should.include('<li>jane &lt;jane@learnboost.com&gt;</li>');
done();
});
})
+1 -1
Ver Arquivo
@@ -85,7 +85,7 @@ describe('error-pages', function(){
request(app)
.get('/404')
.set('Accept', 'text/plain')
.expect(200)
.expect(404)
.expect('Not found', done);
})
})
+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();
})
})
})
})
+2
Ver Arquivo
@@ -57,8 +57,10 @@ describe('app.path()', function(){
describe('in development', function(){
it('should disable "view cache"', function(){
process.env.NODE_ENV = 'development';
var app = express();
app.enabled('view cache').should.be.false;
process.env.NODE_ENV = 'test';
})
})
+1 -1
Ver Arquivo
@@ -8,7 +8,7 @@ describe('app', function(){
var app = express();
app.param(function(name, regexp){
if (regexp instanceof RegExp) {
if (Object.prototype.toString.call(regexp) == '[object RegExp]') { // See #1557
return function(req, res, next, val){
var captures;
if (captures = regexp.exec(String(val))) {
+28 -5
Ver Arquivo
@@ -14,7 +14,7 @@ describe('app', function(){
done();
})
})
it('should support absolute paths with "view engine"', function(done){
var app = express();
@@ -40,7 +40,7 @@ describe('app', function(){
done();
})
})
it('should support index.<engine>', function(done){
var app = express();
@@ -109,8 +109,31 @@ describe('app', function(){
})
})
})
describe('when a "view" constructor is given', function(){
it('should create an instance of it', function(done){
var app = express();
function View(name, options){
this.name = name;
this.path = 'path is required by application.js as a signal of success even though it is not used there.';
}
View.prototype.render = function(options, fn){
fn(null, 'abstract engine');
};
app.set('view', View);
app.render('something', function(err, str){
if (err) return done(err);
str.should.equal('abstract engine');
done();
})
})
})
})
describe('.render(name, options, fn)', function(){
it('should render the template', function(done){
var app = express();
@@ -125,7 +148,7 @@ describe('app', function(){
done();
})
})
it('should expose app.locals', function(done){
var app = express();
@@ -138,7 +161,7 @@ describe('app', function(){
done();
})
})
it('should give precedence to app.render() locals', function(done){
var app = express();
+30 -43
Ver Arquivo
@@ -48,7 +48,7 @@ describe('app.router', function(){
calls.push('before');
next();
});
app.use(app.router);
app.use(function(req, res, next){
@@ -68,7 +68,7 @@ describe('app.router', function(){
done();
})
})
it('should be auto .use()d on the first app.VERB() call', function(done){
var app = express();
@@ -78,7 +78,7 @@ describe('app.router', function(){
calls.push('before');
next();
});
app.get('/', function(req, res, next){
calls.push('GET /')
next();
@@ -109,7 +109,7 @@ describe('app.router', function(){
.get('/user/12?foo=bar')
.expect('user', done);
})
it('should populate req.params with the captures', function(done){
var app = express();
@@ -124,24 +124,6 @@ describe('app.router', function(){
.expect('editing user 10', done);
})
})
describe('when given an array', function(){
it('should match all paths in the array', function(done){
var app = express();
app.get(['/one', '/two'], function(req, res){
res.end('works');
});
request(app)
.get('/one')
.expect('works', function() {
request(app)
.get('/two')
.expect('works', done);
});
})
})
describe('case sensitivity', function(){
it('should be disabled by default', function(done){
@@ -155,7 +137,7 @@ describe('app.router', function(){
.get('/USER')
.expect('tj', done);
})
describe('when "case sensitive routing" is enabled', function(){
it('should match identical casing', function(done){
var app = express();
@@ -170,7 +152,7 @@ describe('app.router', function(){
.get('/uSer')
.expect('tj', done);
})
it('should not match otherwise', function(done){
var app = express();
@@ -199,7 +181,7 @@ describe('app.router', function(){
.get('/user/')
.expect('tj', done);
})
describe('when "strict routing" is enabled', function(){
it('should match trailing slashes', function(done){
var app = express();
@@ -214,7 +196,7 @@ describe('app.router', function(){
.get('/user/')
.expect('tj', done);
})
it('should match no slashes', function(done){
var app = express();
@@ -228,7 +210,7 @@ describe('app.router', function(){
.get('/user')
.expect('tj', done);
})
it('should fail when omitting the trailing slash', function(done){
var app = express();
@@ -242,7 +224,7 @@ describe('app.router', function(){
.get('/user')
.expect(404, done);
})
it('should fail when adding the trailing slash', function(done){
var app = express();
@@ -275,7 +257,7 @@ describe('app.router', function(){
.expect(404, done);
});
})
it('should allow literal "."', function(done){
var app = express();
@@ -303,7 +285,7 @@ describe('app.router', function(){
.get('/user/tj.json')
.expect('tj', done);
})
it('should work with several', function(done){
var app = express();
@@ -346,7 +328,7 @@ describe('app.router', function(){
.get('/api/users/0.json')
.expect('users/0.json', done);
})
it('should not be greedy immediately after param', function(done){
var app = express();
@@ -370,7 +352,7 @@ describe('app.router', function(){
.get('/user/122/aaa')
.expect('122', done);
})
it('should span multiple segments', function(done){
var app = express();
@@ -382,7 +364,7 @@ describe('app.router', function(){
.get('/file/javascripts/jquery.js')
.expect('javascripts/jquery.js', done);
})
it('should be optional', function(done){
var app = express();
@@ -394,7 +376,7 @@ describe('app.router', function(){
.get('/file/')
.expect('', done);
})
it('should require a preceeding /', function(done){
var app = express();
@@ -420,7 +402,7 @@ describe('app.router', function(){
.get('/user/tj')
.expect('tj', done);
})
it('should match a single segment only', function(done){
var app = express();
@@ -432,7 +414,7 @@ describe('app.router', function(){
.get('/user/tj/edit')
.expect(404, done);
})
it('should allow several capture groups', function(done){
var app = express();
@@ -459,7 +441,7 @@ describe('app.router', function(){
.get('/user/tj')
.expect('viewing tj', done);
})
it('should populate the capture group', function(done){
var app = express();
@@ -473,7 +455,7 @@ describe('app.router', function(){
.expect('editing tj', done);
})
})
describe('.:name', function(){
it('should denote a format', function(done){
var app = express();
@@ -491,7 +473,7 @@ describe('app.router', function(){
});
})
})
describe('.:name?', function(){
it('should denote an optional format', function(done){
var app = express();
@@ -509,7 +491,7 @@ describe('app.router', function(){
});
})
})
describe('when next() is called', function(){
it('should continue lookup', function(done){
var app = express()
@@ -528,7 +510,7 @@ describe('app.router', function(){
calls.push('/foo');
next();
});
app.get('/foo', function(req, res, next){
calls.push('/foo 2');
res.end('done');
@@ -542,7 +524,7 @@ describe('app.router', function(){
})
})
})
describe('when next(err) is called', function(){
it('should break out of app.router', function(done){
var app = express()
@@ -561,7 +543,7 @@ describe('app.router', function(){
calls.push('/foo');
next(new Error('fail'));
});
app.get('/foo', function(req, res, next){
assert(0);
});
@@ -596,4 +578,9 @@ describe('app.router', function(){
.get('/account/edit')
.expect('editing user 12', done);
})
it('should be chainable', function(){
var app = express();
app.get('/', function(){}).should.equal(app);
})
})
+43
Ver Arquivo
@@ -0,0 +1,43 @@
var express = require('../')
, request = require('./support/http');
describe('app', function(){
describe('.VERB()', function(){
it('should only call an error handling routing callback when an error is propagated', function(done){
var app = express();
var a = false;
var b = false;
var c = false;
var d = false;
app.get('/', function(req, res, next){
next(new Error('fabricated error'));
}, function(req, res, next) {
a = true;
next();
}, function(err, req, res, next){
b = true;
err.message.should.equal('fabricated error');
next(err);
}, function(err, req, res, next){
c = true;
err.message.should.equal('fabricated error');
next();
}, function(err, req, res, next){
d = true;
next();
}, function(req, res){
a.should.be.false;
b.should.be.true;
c.should.be.true;
d.should.be.false;
res.send(204);
});
request(app)
.get('/')
.expect(204, done);
})
})
})
+7 -10
Ver Arquivo
@@ -1,12 +1,9 @@
var express = require('../')
, request = require('./support/http');
, request = require('./support/http')
, assert = require('assert');
describe('exports', function(){
it('should have .version', function(){
express.should.have.property('version');
})
it('should expose connect middleware', function(){
express.should.have.property('bodyParser');
express.should.have.property('session');
@@ -14,21 +11,21 @@ describe('exports', function(){
})
it('should expose .mime', function(){
express.mime.should.equal(require('connect').mime);
assert(express.mime == require('connect').mime, 'express.mime should be connect.mime');
})
it('should expose Router', function(){
express.Router.should.be.a('function');
})
it('should expose the application prototype', function(){
express.application.set.should.be.a('function');
})
it('should expose the request prototype', function(){
express.request.accepts.should.be.a('function');
})
it('should expose the response prototype', function(){
express.response.send.should.be.a('function');
})
@@ -50,7 +47,7 @@ describe('exports', function(){
.get('/')
.expect('bar', done);
})
it('should permit modifying the .response prototype', function(done){
express.response.foo = function(){ this.send('bar'); };
var app = express();
+36
Ver Arquivo
@@ -0,0 +1,36 @@
var express = require('../')
, request = require('./support/http');
describe('req', function(){
describe('.acceptedEncodings', function(){
it('should return an array of accepted encodings', function(done){
var app = express();
app.use(function(req, res){
req.acceptedEncodings.should.eql(['gzip', 'deflate']);
res.end();
});
request(app)
.get('/')
.set('Accept-Encoding', ' gzip, deflate')
.expect(200, done);
})
describe('when Accept-Encoding is not present', function(){
it('should default to []', function(done){
var app = express();
app.use(function(req, res){
req.acceptedEncodings.should.have.length(0);
res.end();
});
request(app)
.get('/')
.expect(200, done);
})
})
})
})
+15 -2
Ver Arquivo
@@ -15,7 +15,7 @@ describe('req', function(){
.get('/')
.expect('yes', done);
})
it('should return true when present', function(done){
var app = express();
@@ -28,7 +28,7 @@ describe('req', function(){
.set('Accept', 'application/json')
.expect('yes', done);
})
it('should return false otherwise', function(done){
var app = express();
@@ -56,6 +56,19 @@ describe('req', function(){
.expect('html', done);
})
it('should accept an argument list of type names', function(done){
var app = express();
app.use(function(req, res, next){
res.end(req.accepts('json', 'html'));
});
request(app)
.get('/')
.set('Accept', 'application/json')
.expect('json', done);
})
describe('.accept(types)', function(){
it('should return the first when Accept is not present', function(done){
var app = express();
+2 -2
Ver Arquivo
@@ -17,7 +17,7 @@ describe('req', function(){
.expect('yes', done);
})
})
describe('when Accept-Charset is not present', function(){
it('should return true when present', function(done){
var app = express();
@@ -31,7 +31,7 @@ describe('req', function(){
.set('Accept-Charset', 'foo, bar, utf-8')
.expect('yes', done);
})
it('should return false otherwise', function(done){
var app = express();
+94
Ver Arquivo
@@ -0,0 +1,94 @@
var express = require('../')
, request = require('./support/http');
describe('req', function(){
describe('.auth', function(){
describe('when Authorization is missing', function(){
it('should return undefined', function(done){
var app = express();
app.get('/', function(req, res){
res.send(req.auth || 'none');
});
request(app)
.get('/')
.expect('none', done)
})
})
describe('when Authorization 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', 'meow')
.expect('none', done)
})
})
describe('when Authorization is not Basic', 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', 'Meow dG9iaTpmZXJyZXQ')
.expect('none', done)
})
})
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();
app.get('/', function(req, res){
res.send(req.auth || 'none');
});
request(app)
.get('/')
.set('Authorization', 'Basic dG9iaTpmZXJyZXQ=')
.expect('{"username":"tobi","password":"ferret"}', done)
})
})
})
+27 -11
Ver Arquivo
@@ -1,18 +1,34 @@
var express = require('../');
function req(ret) {
return {
get: function(){ return ret }
, __proto__: express.request
};
}
var express = require('../')
, request = require('./support/http')
, assert = require('assert');
describe('req', function(){
describe('.host', function(){
it('should return hostname', function(){
req('example.com:3000').host.should.equal('example.com');
req('example.com').host.should.equal('example.com');
it('should return the Host when present', function(done){
var app = express();
app.use(function(req, res){
res.end(req.host);
});
request(app)
.post('/')
.set('Host', 'example.com')
.expect('example.com', done);
})
it('should return undefined otherwise', function(done){
var app = express();
app.use(function(req, res){
req.headers.host = null;
res.end(String(req.host));
});
request(app)
.post('/')
.expect('undefined', done);
})
})
})
+83
Ver Arquivo
@@ -0,0 +1,83 @@
var express = require('../')
, request = require('./support/http');
describe('req', function(){
describe('.secure', function(){
describe('when X-Forwarded-Proto is missing', function(){
it('should return false when http', function(done){
var app = express();
app.get('/', function(req, res){
res.send(req.secure ? 'yes' : 'no');
});
request(app)
.get('/')
.expect('no', done)
})
})
})
describe('.secure', function(){
describe('when X-Forwarded-Proto is present', function(){
it('should return false when http', function(done){
var app = express();
app.get('/', function(req, res){
res.send(req.secure ? 'yes' : 'no');
});
request(app)
.get('/')
.set('X-Forwarded-Proto', 'https')
.expect('no', done)
})
it('should return true when "trust proxy" is enabled', function(done){
var app = express();
app.enable('trust proxy');
app.get('/', function(req, res){
res.send(req.secure ? 'yes' : 'no');
});
request(app)
.get('/')
.set('X-Forwarded-Proto', 'https')
.expect('yes', done)
})
it('should return false when initial proxy is http', function(done){
var app = express();
app.enable('trust proxy');
app.get('/', function(req, res){
res.send(req.secure ? 'yes' : 'no');
});
request(app)
.get('/')
.set('X-Forwarded-Proto', 'http, https')
.expect('no', done)
})
it('should return true when initial proxy is https', function(done){
var app = express();
app.enable('trust proxy');
app.get('/', function(req, res){
res.send(req.secure ? 'yes' : 'no');
});
request(app)
.get('/')
.set('X-Forwarded-Proto', 'https, http')
.expect('yes', done)
})
})
})
})
+60
Ver Arquivo
@@ -0,0 +1,60 @@
var express = require('../')
, request = require('./support/http');
describe('req', function(){
describe('.signedCookies', function(){
it('should return a signed JSON cookie', function(done){
var app = express()
, cookieHeader
, val;
/* So we use the same serialization for expected results. */
var replacer = app.get('json replacer')
, spaces = app.get('json spaces');
app.use(express.cookieParser('secret'));
app.use(function(req, res){
res.send(req.signedCookies);
});
app.response.req = { secret: 'secret' };
app.response.cookie('obj', { foo: 'bar' }, { signed: true });
cookieHeader = app.response.get('set-cookie');
val = JSON.stringify({ obj: { foo: 'bar' } }, replacer, spaces);
request(app)
.get('/')
.set('Cookie', cookieHeader)
.expect(val, done);
})
it('should return a signed cookie', function(done){
var app = express()
, cookieHeader
, val;
/* So we use the same serialization for expected results. */
var replacer = app.get('json replacer')
, spaces = app.get('json spaces');
app.use(express.cookieParser('secret'));
app.use(function(req, res){
res.send(req.signedCookies);
});
app.response.req = { secret: 'secret' };
app.response.cookie('foo', 'bar', { signed: true });
cookieHeader = app.response.get('set-cookie');
val = JSON.stringify({ foo: 'bar' }, replacer, spaces);
request(app)
.get('/')
.set('Cookie', cookieHeader)
.expect(val, done);
})
})
})
+65
Ver Arquivo
@@ -33,5 +33,70 @@ describe('req', function(){
.expect('[]', done);
})
})
describe('with no host', function(){
it('should return an empty array', function(done){
var app = express();
app.use(function(req, res){
req.headers.host = null;
res.send(req.subdomains);
});
request(app)
.get('/')
.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);
})
})
})
})
})
+38 -2
Ver Arquivo
@@ -1,6 +1,7 @@
var express = require('../')
, request = require('./support/http')
, utils = require('connect').utils
, cookie = require('cookie');
describe('res', function(){
@@ -92,6 +93,41 @@ describe('res', function(){
done();
})
})
it('should set max-age', function(done){
var app = express();
app.use(function(req, res){
res.cookie('name', 'tobi', { maxAge: 1000 });
res.end();
});
request(app)
.get('/')
.end(function(err, res){
res.headers['set-cookie'][0].should.include('Max-Age=1');
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(){
@@ -109,7 +145,7 @@ describe('res', function(){
.end(function(err, res){
var val = res.headers['set-cookie'][0];
val = cookie.parse(val.split('.')[0]);
val.user.should.equal('j:{"name":"tobi"}');
val.user.should.equal('s:j:{"name":"tobi"}');
done();
})
})
@@ -128,7 +164,7 @@ describe('res', function(){
request(app)
.get('/')
.end(function(err, res){
var val = ['name=tobi.xJjV2iZ6EI7C8E5kzwbfA9PVLl1ZR07UTnuTgQQ4EnQ; Path=/'];
var val = ['name=s%3Atobi.xJjV2iZ6EI7C8E5kzwbfA9PVLl1ZR07UTnuTgQQ4EnQ; Path=/'];
res.headers['set-cookie'].should.eql(val);
done();
})
+3 -3
Ver Arquivo
@@ -53,7 +53,7 @@ app3.use(function(req, res, next){
})
});
describe('req', function(){
describe('res', function(){
describe('.format(obj)', function(){
describe('with canonicalized mime types', function(){
test(app);
@@ -79,14 +79,14 @@ function test(app) {
request(app)
.get('/')
.set('Accept', 'text/html; q=.5, application/json, */*; q=.1')
.expect('{"message":"hey"}', done);
.expect({"message":"hey"}, done);
})
it('should allow wildcard type/subtypes', function(done){
request(app)
.get('/')
.set('Accept', 'text/html; q=.5, application/*, */*; q=.1')
.expect('{"message":"hey"}', done);
.expect({"message":"hey"}, done);
})
it('should default the Content-Type', function(done){
+26 -47
Ver Arquivo
@@ -5,55 +5,16 @@ var express = require('../')
describe('res', function(){
describe('.json(object)', function(){
describe('when "jsonp callback" is enabled', function(){
it('should respond with jsonp', function(done){
var app = express();
it('should not support jsonp callbacks', function(done){
var app = express();
app.use(function(req, res){
res.json({ count: 1 });
});
app.use(function(req, res){
res.json({ foo: 'bar' });
});
request(app)
.get('/?callback=something')
.end(function(err, res){
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
res.text.should.equal('something({"count":1});');
done();
})
})
it('should allow renaming callback', function(done){
var app = express();
app.set('jsonp callback name', 'clb');
app.use(function(req, res){
res.json({ count: 1 });
});
request(app)
.get('/?clb=something')
.end(function(err, res){
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
res.text.should.equal('something({"count":1});');
done();
})
})
it('should allow []', function(done){
var app = express();
app.use(function(req, res){
res.json({ count: 1 });
});
request(app)
.get('/?callback=callbacks[123]')
.end(function(err, res){
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
res.text.should.equal('callbacks[123]({"count":1});');
done();
})
})
request(app)
.get('/?callback=foo')
.expect('{"foo":"bar"}', done);
})
describe('when given primitives', function(){
@@ -202,4 +163,22 @@ describe('res', function(){
})
})
})
it('should not override previous Content-Types', function(done){
var app = express();
app.get('/', function(req, res){
res.type('application/vnd.example+json');
res.json({ hello: 'world' });
});
request(app)
.get('/')
.end(function(err, res){
res.statusCode.should.equal(200);
res.headers.should.have.property('content-type', 'application/vnd.example+json');
res.text.should.equal('{"hello":"world"}');
done();
})
})
})
+236
Ver Arquivo
@@ -0,0 +1,236 @@
var express = require('../')
, request = require('./support/http')
, assert = require('assert');
describe('res', function(){
describe('.jsonp(object)', function(){
it('should respond with jsonp', function(done){
var app = express();
app.use(function(req, res){
res.jsonp({ count: 1 });
});
request(app)
.get('/?callback=something')
.end(function(err, res){
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
res.text.should.equal('something && something({"count":1});');
done();
})
})
it('should allow renaming callback', function(done){
var app = express();
app.set('jsonp callback name', 'clb');
app.use(function(req, res){
res.jsonp({ count: 1 });
});
request(app)
.get('/?clb=something')
.end(function(err, res){
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
res.text.should.equal('something && something({"count":1});');
done();
})
})
it('should allow []', function(done){
var app = express();
app.use(function(req, res){
res.jsonp({ count: 1 });
});
request(app)
.get('/?callback=callbacks[123]')
.end(function(err, res){
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
res.text.should.equal('callbacks[123] && callbacks[123]({"count":1});');
done();
})
})
it('should disallow arbitrary js', function(done){
var app = express();
app.use(function(req, res){
res.jsonp({});
});
request(app)
.get('/?callback=foo;bar()')
.end(function(err, res){
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
res.text.should.equal('foobar && foobar({});');
done();
})
})
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();
app.use(function(req, res){
res.jsonp(null);
});
request(app)
.get('/')
.end(function(err, res){
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
res.text.should.equal('null');
done();
})
})
})
describe('when given an array', function(){
it('should respond with json', function(done){
var app = express();
app.use(function(req, res){
res.jsonp(['foo', 'bar', 'baz']);
});
request(app)
.get('/')
.end(function(err, res){
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
res.text.should.equal('["foo","bar","baz"]');
done();
})
})
})
describe('when given an object', function(){
it('should respond with json', function(done){
var app = express();
app.use(function(req, res){
res.jsonp({ name: 'tobi' });
});
request(app)
.get('/')
.end(function(err, res){
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
res.text.should.equal('{"name":"tobi"}');
done();
})
})
})
describe('"json replacer" setting', function(){
it('should be passed to JSON.stringify()', function(done){
var app = express();
app.set('json replacer', function(key, val){
return '_' == key[0]
? undefined
: val;
});
app.use(function(req, res){
res.jsonp({ name: 'tobi', _id: 12345 });
});
request(app)
.get('/')
.end(function(err, res){
res.text.should.equal('{"name":"tobi"}');
done();
});
})
})
describe('"json spaces" setting', function(){
it('should default to 2 in development', function(){
process.env.NODE_ENV = 'development';
var app = express();
app.get('json spaces').should.equal(2);
process.env.NODE_ENV = 'test';
})
it('should be undefined otherwise', function(){
var app = express();
assert(undefined === app.get('json spaces'));
})
it('should be passed to JSON.stringify()', function(done){
var app = express();
app.set('json spaces', 2);
app.use(function(req, res){
res.jsonp({ name: 'tobi', age: 2 });
});
request(app)
.get('/')
.end(function(err, res){
res.text.should.equal('{\n "name": "tobi",\n "age": 2\n}');
done();
});
})
})
})
describe('.json(status, object)', function(){
it('should respond with json and set the .statusCode', function(done){
var app = express();
app.use(function(req, res){
res.jsonp(201, { id: 1 });
});
request(app)
.get('/')
.end(function(err, res){
res.statusCode.should.equal(201);
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
res.text.should.equal('{"id":1}');
done();
})
})
})
describe('.json(object, status)', function(){
it('should respond with json and set the .statusCode for backwards compat', function(done){
var app = express();
app.use(function(req, res){
res.jsonp({ id: 1 }, 201);
});
request(app)
.get('/')
.end(function(err, res){
res.statusCode.should.equal(201);
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
res.text.should.equal('{"id":1}');
done();
})
})
})
})
+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();
})
})
})
})
})
})
+112 -163
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', '//example.com/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', '//example.com/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', '//example.com/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', '//example.com/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', '//example.com/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', '//example.com/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', '//example.com/admin/login');
done();
})
})
})
})
})
describe('.redirect(status, url)', function(){
@@ -196,7 +38,25 @@ describe('res', function(){
})
})
})
describe('.redirect(url, status)', function(){
it('should set the response status', function(done){
var app = express();
app.use(function(req, res){
res.redirect('http://google.com', 303);
});
request(app)
.get('/')
.end(function(err, res){
res.statusCode.should.equal(303);
res.headers.should.have.property('location', 'http://google.com');
done();
})
})
})
describe('when the request method is HEAD', function(){
it('should ignore the body', function(done){
var app = express();
@@ -214,7 +74,7 @@ describe('res', function(){
})
})
})
describe('when accepting html', function(){
it('should respond with html', function(done){
var app = express();
@@ -245,12 +105,12 @@ describe('res', function(){
.set('Host', 'http://example.com')
.set('Accept', 'text/html')
.end(function(err, res){
res.text.should.equal('<p>Moved Temporarily. Redirecting to <a href="//http://example.com/&lt;lame&gt;">//http://example.com/&lt;lame&gt;</a></p>');
res.text.should.equal('<p>Moved Temporarily. Redirecting to <a href="/&lt;lame&gt;">/&lt;lame&gt;</a></p>');
done();
})
})
})
describe('when accepting text', function(){
it('should respond with text', function(done){
var app = express();
@@ -269,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(){
@@ -281,7 +158,7 @@ describe('res', function(){
request(app)
.get('/')
.set('Accept', 'foo/bar')
.set('Accept', 'application/octet-stream')
.end(function(err, res){
res.should.have.status(302);
res.headers.should.have.property('location', 'http://google.com');
@@ -292,4 +169,76 @@ describe('res', function(){
})
})
})
describe('responses redirected to relative paths', function(){
function create(depth, parent) {
var app = express();
if (parent) {
parent.use('/depth' + depth, app);
}
app.get('/', function(req, res){
res.redirect('./index');
});
app.get('/index', function(req, res){
res.json({ depth: depth, content: 'index' });
});
return app;
}
var root = create(0);
var depth1 = create(1, root);
var depth2 = create(2, depth1);
var depth3 = create(3, depth2);
root.use('/depth2', depth2);
root.use('/depth3', depth3);
it('should not contain redundant leading slashes in the location header', function(done){
request(root)
.get('/')
.end(function(err, res){
res.headers.location.search(/^\/{2}/).should.equal(-1);
done();
})
})
it('should preserve context when redirecting nested applications at any depth', function(done){
request(root)
.get('/depth1')
.end(function(err, res){
res.headers.should.have.property('location', '/depth1/./index');
request(root)
.get('/depth1/depth2')
.end(function(err, res){
res.headers.should.have.property('location', '/depth1/depth2/./index');
request(root)
.get('/depth1/depth2/depth3')
.end(function(err, res){
res.headers.should.have.property('location', '/depth1/depth2/depth3/./index');
done();
})
})
});
})
it('should redirect correctly for nested applications that have been remounted', function(done){
request(root)
.get('/depth2')
.end(function(err, res){
res.headers.should.have.property('location', '/depth2/./index');
request(root)
.get('/depth3')
.end(function(err, res){
res.headers.should.have.property('location', '/depth3/./index');
done();
})
})
})
})
})

Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais