Comparar commits

...

164 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
42 arquivos alterados com 962 adições e 293 exclusões
+2 -2
Ver Arquivo
@@ -1,4 +1,4 @@
language: node_js
node_js:
- 0.6
- 0.8
- "0.8"
- "0.10"
+98
Ver Arquivo
@@ -1,4 +1,102 @@
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
==================
+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
+1 -1
Ver Arquivo
@@ -1,5 +1,5 @@
MOCHA_OPTS=
MOCHA_OPTS= --check-leaks
REPORTER = dot
check: test
+5 -5
Ver Arquivo
@@ -51,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
@@ -64,8 +64,8 @@ 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
@@ -96,7 +96,7 @@ 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%
@@ -153,7 +153,7 @@ authors:
1 Masahiro Hayashi 0.0%
```
## License
## License
(The MIT License)
+25 -24
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
@@ -208,35 +209,35 @@ var app = [
, ' * Module dependencies.'
, ' */'
, ''
, 'var express = require(\'express\')'
, ' , routes = require(\'./routes\')'
, ' , user = require(\'./routes/user\')'
, ' , 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);
@@ -323,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}', '');
@@ -334,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
@@ -345,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();
}
+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'));
});
});
}
};
};
+1 -1
Ver Arquivo
@@ -1,4 +1,4 @@
style
style.
body {
padding: 50px;
font: 16px "Helvetica Neue", Helvetica;
+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))
+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');
}
}
+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');
}
}
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
html
head
title Search example
style
style.
body {
font: 14px "Helvetica Neue", Helvetica;
padding: 50px;
+5 -6
Ver Arquivo
@@ -1,4 +1,3 @@
/**
* Module dependencies.
*/
@@ -6,14 +5,14 @@
var express = require('../..');
/*
edit /etc/vhosts:
edit /etc/hosts:
127.0.0.1 foo.example.com
127.0.0.1 bar.example.com
127.0.0.1 example.com
*/
// Main app
// Main server app
var main = express();
@@ -36,12 +35,12 @@ redirect.all('*', function(req, res){
res.redirect('http://example.com:3000/' + req.subdomains[0]);
});
// Main app
// Vhost app
var app = express();
app.use(express.vhost('*.example.com', redirect))
app.use(express.vhost('example.com', main));
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');
+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');
}
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@ doctype 5
html
head
title= title
style
style.
body {
padding: 50px;
font: 16px Helvetica, Arial;
+13 -11
Ver Arquivo
@@ -34,7 +34,6 @@ app.init = function(){
this.cache = {};
this.settings = {};
this.engines = {};
this.viewCallbacks = [];
this.defaultConfiguration();
};
@@ -47,6 +46,7 @@ app.init = function(){
app.defaultConfiguration = function(){
// 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'));
@@ -60,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
@@ -79,6 +80,7 @@ app.defaultConfiguration = function(){
this.locals.settings = this.settings;
// default configuration
this.set('view', View);
this.set('views', process.cwd() + '/views');
this.set('jsonp callback name', 'callback');
@@ -116,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);
@@ -161,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 seeessly within Express.
* work seamlessly within Express.
*
* @param {String} ext
* @param {Function} fn
@@ -184,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.
@@ -250,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;
@@ -405,7 +402,12 @@ methods.forEach(function(method){
app[method] = function(path){
if ('get' == method && 1 == arguments.length) return this.set(path);
// if no router attacked yet, attach the router
// 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);
// setup route
@@ -483,7 +485,7 @@ app.render = function(name, options, fn){
// view
if (!view) {
view = new View(name, {
view = new (this.get('view'))(name, {
defaultEngine: this.get('view engine'),
root: this.get('views'),
engines: engines
+2 -8
Ver Arquivo
@@ -16,12 +16,6 @@ var connect = require('connect')
exports = module.exports = createApplication;
/**
* Framework version.
*/
exports.version = '3.1.0';
/**
* Expose mime.
*/
@@ -38,8 +32,8 @@ exports.mime = connect.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;
}
-1
Ver Arquivo
@@ -17,7 +17,6 @@ var utils = require('./utils');
exports.init = function(app){
return function expressInit(req, res, next){
req.app = res.app = app;
if (app.enabled('x-powered-by')) res.setHeader('X-Powered-By', 'Express');
req.res = res;
res.req = req;
+49 -13
Ver Arquivo
@@ -63,6 +63,7 @@ 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.
*
@@ -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
*/
@@ -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];
});
/**
@@ -415,7 +447,7 @@ req.__defineGetter__('auth', function(){
req.__defineGetter__('subdomains', function(){
var offset = this.app.get('subdomain offset');
return this.get('Host')
return (this.host || '')
.split('.')
.reverse()
.slice(offset);
@@ -440,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];
});
/**
+16 -9
Ver Arquivo
@@ -78,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) {
@@ -128,7 +131,7 @@ res.send = function(body){
// ETag support
// TODO: W/ support
if (len > 1024) {
if (app.settings.etag && len > 1024 && 'GET' == req.method) {
if (!this.get('ETag')) {
this.set('ETag', etag(body));
}
@@ -234,6 +237,7 @@ res.jsonp = function(obj){
// jsonp
if (callback) {
if (callback instanceof Array) callback = callback[0];
this.set('Content-Type', 'text/javascript');
var cb = callback.replace(/[^\[\]\w$.]/g, '');
body = cb + ' && ' + cb + '(' + body + ');';
@@ -462,14 +466,14 @@ res.format = function(obj){
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);
}
@@ -580,6 +584,7 @@ res.cookie = function(name, val, 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 = 's:' + sign(val, secret);
if ('maxAge' in options) {
@@ -634,13 +639,15 @@ res.location = 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;
}
}
+38
Ver Arquivo
@@ -103,6 +103,9 @@ Router.prototype._dispatch = function(req, res, next){
// match route
req.route = route = self.matchRequest(req, i);
// implied OPTIONS
if (!route && 'OPTIONS' == req.method) return self._options(req, res);
// no route
if (!route) return next(err);
debug('matched %s %s', route.method, route.path);
@@ -170,6 +173,41 @@ Router.prototype._dispatch = function(req, res, next){
})(0);
};
/**
* Respond to __OPTIONS__ method.
*
* @param {IncomingMessage} req
* @param {ServerResponse} res
* @api private
*/
Router.prototype._options = function(req, res){
var path = parse(req).pathname
, body = this._optionsFor(path).join(',');
res.set('Allow', body).send(body);
};
/**
* Return an array of HTTP verbs or "options" for `path`.
*
* @param {String} path
* @return {Array}
* @api private
*/
Router.prototype._optionsFor = function(path){
var self = this;
return methods.filter(function(method){
var routes = self.map[method];
if (!routes || 'options' == method) return;
for (var i = 0, len = routes.length; i < len; ++i) {
if (routes[i].match(path)) return true;
}
}).map(function(method){
return method.toUpperCase();
});
};
/**
* Attempt to match a route for `req`
* with optional starting index of `i`
+63 -32
Ver Arquivo
@@ -6,6 +6,12 @@
var mime = require('connect').mime
, crc32 = require('buffer-crc32');
/**
* toString ref.
*/
var toString = {}.toString;
/**
* Return ETag for `body`.
*
@@ -20,8 +26,8 @@ exports.etag = function(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}
@@ -29,8 +35,6 @@ exports.etag = function(body){
*/
exports.locals = function(obj){
obj.viewCallbacks = obj.viewCallbacks || [];
function locals(obj){
for (var key in obj) locals[key] = obj[key];
return obj;
@@ -77,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: {} };
};
/**
@@ -97,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;
@@ -125,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];
}
}
@@ -150,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
@@ -175,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];
@@ -186,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;
}
/**
@@ -260,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 ? '' : '/?')
@@ -279,4 +310,4 @@ exports.pathRegexp = function(path, keys, sensitive, strict) {
.replace(/([\/.])/g, '\\$1')
.replace(/\*/g, '(.*)');
return new RegExp('^' + path + '$', sensitive ? '' : 'i');
}
}
+5 -4
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,6 +38,7 @@ function View(name, options) {
var engines = options.engines;
this.defaultEngine = options.defaultEngine;
var ext = this.ext = extname(name);
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);
+35 -20
Ver Arquivo
@@ -1,37 +1,49 @@
{
"name": "express",
"description": "Sinatra inspired web development framework",
"version": "3.1.0",
"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" }
{
"name": "TJ Holowaychuk",
"email": "tj@vision-media.ca"
},
{
"name": "Aaron Heckmann",
"email": "aaron.heckmann+github@gmail.com"
},
{
"name": "Ciaran Jessup",
"email": "ciaranj@gmail.com"
},
{
"name": "Guillermo Rauch",
"email": "rauchg@gmail.com"
}
],
"dependencies": {
"connect": "2.7.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.5",
"buffer-crc32": "0.1.1",
"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.1.0",
"cookie-signature": "0.0.1",
"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",
@@ -46,11 +58,14 @@
],
"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": "*"
}
}
+37
Ver Arquivo
@@ -0,0 +1,37 @@
var express = require('../')
, request = require('./support/http');
describe('OPTIONS', function(){
it('should default to the routes defined', function(done){
var app = express();
app.del('/', function(){});
app.get('/users', function(req, res){});
app.put('/users', function(req, res){});
request(app)
.options('/users')
.expect('GET,PUT')
.expect('Allow', 'GET,PUT', done);
})
})
describe('app.options()', function(){
it('should override the default behavior', function(done){
var app = express();
app.options('/users', function(req, res){
res.set('Allow', 'GET');
res.send('GET');
});
app.get('/users', function(req, res){});
app.put('/users', function(req, res){});
request(app)
.options('/users')
.expect('GET')
.expect('Allow', 'GET', done);
})
})
+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();
+25 -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);
});
+4 -8
Ver Arquivo
@@ -4,10 +4,6 @@ var express = require('../')
, 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');
@@ -21,15 +17,15 @@ describe('exports', function(){
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');
})
@@ -51,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();
+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)
})
})
})
})
+10 -2
Ver Arquivo
@@ -9,6 +9,10 @@ describe('req', function(){
, 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){
@@ -19,7 +23,7 @@ describe('req', function(){
app.response.cookie('obj', { foo: 'bar' }, { signed: true });
cookieHeader = app.response.get('set-cookie');
val = JSON.stringify({ obj: { foo: 'bar' } });
val = JSON.stringify({ obj: { foo: 'bar' } }, replacer, spaces);
request(app)
.get('/')
.set('Cookie', cookieHeader)
@@ -31,6 +35,10 @@ describe('req', function(){
, 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){
@@ -41,7 +49,7 @@ describe('req', function(){
app.response.cookie('foo', 'bar', { signed: true });
cookieHeader = app.response.get('set-cookie');
val = JSON.stringify({ foo: 'bar' });
val = JSON.stringify({ foo: 'bar' }, replacer, spaces);
request(app)
.get('/')
.set('Cookie', cookieHeader)
+15
Ver Arquivo
@@ -34,6 +34,21 @@ describe('req', function(){
})
})
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){
+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){
+74 -2
Ver Arquivo
@@ -74,7 +74,7 @@ describe('res', function(){
})
})
})
describe('when accepting html', function(){
it('should respond with html', function(done){
var app = express();
@@ -110,7 +110,7 @@ describe('res', function(){
})
})
})
describe('when accepting text', function(){
it('should respond with text', function(done){
var app = express();
@@ -169,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();
})
})
})
})
})
+83 -7
Ver Arquivo
@@ -1,6 +1,7 @@
var express = require('../')
, request = require('./support/http');
, request = require('./support/http')
, assert = require('assert');
describe('res', function(){
describe('.send(null)', function(){
@@ -16,7 +17,7 @@ describe('res', function(){
.expect('', done);
})
})
describe('.send(undefined)', function(){
it('should set body to ""', function(done){
var app = express();
@@ -45,7 +46,7 @@ describe('res', function(){
.expect(201, done);
})
})
describe('.send(code, body)', function(){
it('should set .statusCode and body', function(done){
var app = express();
@@ -107,7 +108,24 @@ describe('res', function(){
.expect('ETag', '"-1498647312"')
.end(done);
})
it('should not set ETag for non-GET/HEAD', function(done){
var app = express();
app.use(function(req, res){
var str = Array(1024 * 2).join('-');
res.send(str);
});
request(app)
.post('/')
.end(function(err, res){
if (err) return done(err);
assert(!res.header.etag, 'has an ETag');
done();
});
})
it('should not override Content-Type', function(done){
var app = express();
@@ -122,7 +140,7 @@ describe('res', function(){
.expect(200, done);
})
})
describe('.send(Buffer)', function(){
it('should send as octet-stream', function(done){
var app = express();
@@ -172,7 +190,7 @@ describe('res', function(){
})
})
})
describe('.send(Object)', function(){
it('should send as application/json', function(done){
var app = express();
@@ -224,7 +242,7 @@ describe('res', function(){
})
})
})
describe('when .statusCode is 304', function(){
it('should strip Content-* fields, Transfer-Encoding field, and body', function(done){
var app = express();
@@ -300,4 +318,62 @@ describe('res', function(){
.get('/?callback=foo')
.expect('{"foo":"bar"}', done);
})
describe('"etag" setting', function(){
describe('when enabled', function(){
it('should send ETag ', function(done){
var app = express();
app.use(function(req, res){
var str = Array(1024 * 2).join('-');
res.send(str);
});
request(app)
.get('/')
.end(function(err, res){
res.headers.should.have.property('etag', '"-1498647312"');
done();
});
});
});
describe('when disabled', function(){
it('should send no ETag', function(done){
var app = express();
app.use(function(req, res){
var str = Array(1024 * 2).join('-');
res.send(str);
});
app.disable('etag');
request(app)
.get('/')
.end(function(err, res){
res.headers.should.not.have.property('etag');
done();
});
});
it('should send ETag when manually set', function(done){
var app = express();
app.disable('etag');
app.use(function(req, res){
res.set('etag', 1);
res.send(200);
});
request(app)
.get('/')
.end(function(err, res){
res.headers.should.have.property('etag');
done();
});
});
});
})
})
+47 -31
Ver Arquivo
@@ -6,7 +6,7 @@ describe('utils.etag(body)', function(){
var str = 'Hello CRC';
var strUTF8 = '<!DOCTYPE html>\n<html>\n<head>\n</head>\n<body><p>自動販売</p></body></html>';
it('should support strings', function(){
utils.etag(str).should.eql('"-2034458343"');
})
@@ -27,7 +27,7 @@ describe('utils.isAbsolute()', function(){
assert(utils.isAbsolute('c:\\'));
assert(!utils.isAbsolute(':\\'));
})
it('should unices', function(){
assert(utils.isAbsolute('/foo/bar'));
assert(!utils.isAbsolute('foo/bar'));
@@ -49,44 +49,60 @@ describe('utils.escape(html)', function(){
})
})
describe('utils.parseQuality(str)', function(){
describe('utils.parseParams(str)', function(){
it('should default quality to 1', function(){
utils.parseQuality('text/html')
.should.eql([{ value: 'text/html', quality: 1 }]);
utils.parseParams('text/html')
.should.eql([{ value: 'text/html', quality: 1, params: {}, originalIndex: 0 }]);
})
it('should parse qvalues', function(){
utils.parseQuality('text/html; q=0.5')
.should.eql([{ value: 'text/html', quality: 0.5 }]);
utils.parseQuality('text/html; q=.2')
.should.eql([{ value: 'text/html', quality: 0.2 }]);
it('should parse qvalues', function(){
utils.parseParams('text/html; q=0.5')
.should.eql([{ value: 'text/html', quality: 0.5, params: {}, originalIndex: 0 }]);
utils.parseParams('text/html; q=.2')
.should.eql([{ value: 'text/html', quality: 0.2, params: {}, originalIndex: 0 }]);
})
it('should parse accept parameters', function(){
utils.parseParams('application/json; ver=2.0')
.should.eql([{ value: 'application/json', quality: 1, params: {ver: "2.0"}, originalIndex: 0 }]);
utils.parseParams('text/html; q=0.5; level=2')
.should.eql([{ value: 'text/html', quality: 0.5, params: {level: "2"}, originalIndex: 0 }]);
utils.parseParams('text/html;q=.2;ver=beta')
.should.eql([{ value: 'text/html', quality: 0.2, params: {ver: "beta"}, originalIndex: 0 }]);
})
it('should work with messed up whitespace', function(){
utils.parseQuality('text/html ; q = .2')
.should.eql([{ value: 'text/html', quality: 0.2 }]);
utils.parseParams('text/html ; q = .2')
.should.eql([{ value: 'text/html', quality: 0.2, params: {}, originalIndex: 0 }]);
})
it('should work with multiples', function(){
var str = 'da, en;q=.5, en-gb;q=.8';
var arr = utils.parseQuality(str);
var arr = utils.parseParams(str);
arr[0].value.should.equal('da');
arr[1].value.should.equal('en-gb');
arr[2].value.should.equal('en');
})
it('should work with long lists', function(){
var str = 'en, nl, fr, de, ja, it, es, pt, pt-PT, da, fi, nb, sv, ko, zh-Hans, zh-Hant, ru, pl';
var arr = utils.parseParams(str).map(function(o){ return o.value });
arr.should.eql(str.split(', '));
})
it('should sort by quality', function(){
var str = 'text/plain;q=.2, application/json, text/html;q=0.5';
var arr = utils.parseQuality(str);
var arr = utils.parseParams(str);
arr[0].value.should.equal('application/json');
arr[1].value.should.equal('text/html');
arr[2].value.should.equal('text/plain');
})
it('should exclude those with a quality of 0', function(){
var str = 'text/plain;q=.2, application/json, text/html;q=0';
var arr = utils.parseQuality(str);
var arr = utils.parseParams(str);
arr.should.have.length(2);
})
})
@@ -96,7 +112,7 @@ describe('utils.parseAccept(str)', function(){
var arr = utils.parseAccept('text/html');
arr[0].type.should.equal('text');
})
it('should provide .subtype', function(){
var arr = utils.parseAccept('text/html');
arr[0].subtype.should.equal('html');
@@ -110,7 +126,7 @@ describe('utils.accepts(type, str)', function(){
.should.equal('text/html');
})
})
describe('when a string is empty', function(){
it('should return the value', function(){
utils.accepts('text/html', '')
@@ -156,44 +172,44 @@ describe('utils.accepts(type, str)', function(){
utils.accepts('text/html', 'text/plain, text/html')
.should.equal('text/html');
})
it('should return undefined otherwise', function(){
assert(null == utils.accepts('text/html', 'text/plain, application/json'));
})
})
describe('when accepting */subtype', function(){
it('should return the value when present', function(){
utils.accepts('text/html', 'text/*')
.should.equal('text/html');
})
it('should return undefined otherwise', function(){
assert(null == utils.accepts('text/html', 'image/*'));
})
})
describe('when accepting type/*', function(){
it('should return the value when present', function(){
utils.accepts('text/html', '*/html')
.should.equal('text/html');
})
it('should return undefined otherwise', function(){
assert(null == utils.accepts('text/html', '*/json'));
})
})
describe('when an extension is given', function(){
it('should return the value when present', function(){
utils.accepts('html', 'text/html, application/json')
.should.equal('html');
})
it('should return undefined otherwise', function(){
assert(null == utils.accepts('html', 'text/plain, application/json'));
})
it('should support *', function(){
utils.accepts('html', 'text/*')
.should.equal('html');
@@ -202,4 +218,4 @@ describe('utils.accepts(type, str)', function(){
.should.equal('html');
})
})
})
})