Comparar commits

...

806 Commits

Autor SHA1 Mensagem Data
Tj Holowaychuk 83f1ccb8ad Updated history some more 2010-07-15 16:45:11 -07:00
Tj Holowaychuk cea401c513 More error handling docs 2010-07-15 16:41:37 -07:00
Tj Holowaychuk 6b54c1b6d4 listen in generated app 2010-07-15 16:25:25 -07:00
Tj Holowaychuk 193c4a953e Updated install docs 2010-07-15 16:20:32 -07:00
Tj Holowaychuk d389134036 install.sh now installs connect as well 2010-07-15 16:19:31 -07:00
Tj Holowaychuk d8b140e341 More install docs 2010-07-15 16:04:25 -07:00
Tj Holowaychuk 5931e1143b Updating install docs 2010-07-15 16:01:49 -07:00
Tj Holowaychuk e6d0c4b79f Updated connect submodule 2010-07-15 15:56:22 -07:00
Tj Holowaychuk 44a4a18320 Removed version format test 2010-07-15 15:52:47 -07:00
Tj Holowaychuk 2f96506a6e Added more view docs 2010-07-15 15:49:25 -07:00
Tj Holowaychuk f904606b32 Merge branch 'ejs' into connect 2010-07-15 15:38:12 -07:00
Tj Holowaychuk 99bb14680a Added ejs example 2010-07-15 15:38:08 -07:00
Tj Holowaychuk 83df3dda95 Started ejs example 2010-07-15 14:59:02 -07:00
Tj Holowaychuk 5e4d67209c Executable docs 2010-07-15 14:50:26 -07:00
Tj Holowaychuk 2798af1668 Updated history 2010-07-15 14:48:55 -07:00
Tj Holowaychuk f0e41ce4c7 Bump to 1.0.0beta 2010-07-15 14:44:37 -07:00
Tj Holowaychuk 300602dd32 Contrib middleware link 2010-07-15 14:38:44 -07:00
Tj Holowaychuk 136f6778e2 Tasks 2010-07-15 14:36:24 -07:00
Tj Holowaychuk 2fa7907054 Unix domain socket docs 2010-07-15 13:49:11 -07:00
Tj Holowaychuk f3803c4c22 Server#listen() docs 2010-07-15 13:46:42 -07:00
Tj Holowaychuk 5d37927b0a More docs 2010-07-15 13:39:57 -07:00
Tj Holowaychuk 6227f5cfa2 More error docs 2010-07-15 13:30:43 -07:00
Tj Holowaychuk 9fbb9fa5e1 Error handling docs 2010-07-15 13:29:50 -07:00
Tj Holowaychuk de81ee7ee6 More docs 2010-07-15 13:24:43 -07:00
Tj Holowaychuk 5fcf971e28 Fixed reload views example 2010-07-15 13:10:00 -07:00
Tj Holowaychuk 492f70fc4b Merge branch 'docs' into connect 2010-07-15 13:09:00 -07:00
Tj Holowaychuk 3ced7b7212 No underlines for FF 2010-07-15 13:08:34 -07:00
Tj Holowaychuk 7b55867ea7 Misc styling 2010-07-15 13:06:56 -07:00
Tj Holowaychuk 3e15ef1c86 Setting up TOC 2010-07-15 12:49:57 -07:00
Tj Holowaychuk 0cdc836054 Generating TOC 2010-07-15 12:06:54 -07:00
Tj Holowaychuk 1aad62b95d Docs 2010-07-15 11:11:05 -07:00
Tj Holowaychuk ed1c88920e Tasks 2010-07-15 11:08:17 -07:00
Tj Holowaychuk e6ca20c4a2 Added views / reload views settings to bin/express app 2010-07-15 11:07:56 -07:00
Tj Holowaychuk cfa3470df6 Tasks 2010-07-15 11:02:03 -07:00
Tj Holowaychuk 479f297cf6 Improved pages demo 2010-07-15 10:55:45 -07:00
Tj Holowaychuk 7e1b222f90 Fixed pages app example 2010-07-15 10:52:38 -07:00
Tj Holowaychuk 69baa6ea1a Regenerated api docs 2010-07-15 10:44:47 -07:00
Tj Holowaychuk 0fce93be37 Removed connect.redirect() 2010-07-15 08:56:51 -07:00
Tj Holowaychuk 51611ec2bb Added test for multiple app.error() calls 2010-07-14 17:36:16 -07:00
Tj Holowaychuk 228a78136d Server#error() no longer requires arity of 4 2010-07-14 17:25:25 -07:00
Tj Holowaychuk 34d10ace7a Added test to confirm app.error() works with thrown exceptions 2010-07-14 17:19:40 -07:00
Tj Holowaychuk 57bd0a5628 Tasks 2010-07-14 17:16:18 -07:00
Tj Holowaychuk 42e4860855 Tasks 2010-07-14 17:12:14 -07:00
Tj Holowaychuk ea1c9f70d7 Merge branch 'pages' into connect 2010-07-14 17:09:21 -07:00
Tj Holowaychuk d3085b0450 Added custom pages example 2010-07-14 17:09:17 -07:00
Tj Holowaychuk 63d02f1d5f Install docs 2010-07-14 16:27:50 -07:00
Tj Holowaychuk dfecbe5bfa More docs 2010-07-14 16:15:00 -07:00
Tj Holowaychuk bcf9f00de5 Added install.sh 2010-07-14 16:06:07 -07:00
Tj Holowaychuk a8e8e35678 Removed seed.yml 2010-07-14 15:59:26 -07:00
Tj Holowaychuk 2ec4a8b4ce Test prefixes 2010-07-14 15:50:40 -07:00
Tj Holowaychuk 6c3d3dee81 Tasks 2010-07-14 15:49:36 -07:00
Tj Holowaychuk 40b3116ed7 Tasks 2010-07-14 15:44:13 -07:00
Tj Holowaychuk df7582b138 Tasks 2010-07-14 15:30:46 -07:00
Tj Holowaychuk b08dab9aa1 Docs for new res methods 2010-07-14 15:29:18 -07:00
Tj Holowaychuk da5a4804df Added res.download() 2010-07-14 15:15:25 -07:00
Tj Holowaychuk d12f43498e Merge branch 'sendfile' into connect 2010-07-14 15:06:45 -07:00
Tj Holowaychuk f9f2facd76 Added res.sendfile() 2010-07-14 15:06:41 -07:00
Tj Holowaychuk eaee3954c1 Tasks 2010-07-14 14:48:43 -07:00
Tj Holowaychuk eb235e11b6 Docs for res.attachment() 2010-07-14 14:45:30 -07:00
Tj Holowaychuk 0c5fe61ed3 More docs :) 2010-07-14 14:42:44 -07:00
Tj Holowaychuk 76052b443a By default a Buffer passed through res.send() is application/octet-stream 2010-07-14 14:38:29 -07:00
Tj Holowaychuk 5a48248e1e Docs for res.send() 2010-07-14 14:36:29 -07:00
Tj Holowaychuk bedff3278f More docs 2010-07-14 14:30:51 -07:00
Tj Holowaychuk 0bb48153a5 Added dynamic redirect mapping 2010-07-14 14:17:48 -07:00
Tj Holowaychuk b75246e3ca Added app.redirect(key, url) 2010-07-14 14:03:30 -07:00
Tj Holowaychuk 2d31f0d7fe res.redirect() docs 2010-07-14 13:59:26 -07:00
Tj Holowaychuk 87cfca721e Merge branch 'redirect' into connect 2010-07-14 13:49:59 -07:00
Tj Holowaychuk 54d36f3337 Removed traces of connect.redirect() 2010-07-14 13:49:51 -07:00
Tj Holowaychuk a4a17d171a Added custom redirect map support 2010-07-14 13:37:30 -07:00
Tj Holowaychuk 7c2673fc66 Added tests for res.redirect() 2010-07-14 13:29:39 -07:00
Tj Holowaychuk c77ecbb10f Started ServerResponse#redirect() 2010-07-14 13:17:39 -07:00
Tj Holowaychuk f0ba57ba23 Added contrib docs 2010-07-14 12:06:56 -07:00
Tj Holowaychuk 893aa80361 Added link to user account for github example 2010-07-14 11:40:58 -07:00
Tj Holowaychuk 59ac3d1d45 Merge branch 'github' into connect 2010-07-14 11:36:38 -07:00
Tj Holowaychuk 247a9478c8 Finished github example 2010-07-14 11:36:32 -07:00
Tj Holowaychuk 1c64d858c2 Added total watchers 2010-07-14 11:23:39 -07:00
Tj Holowaychuk 91a1d7faaf Sorting github repos 2010-07-14 11:19:57 -07:00
Tj Holowaychuk 214bbfa7b6 Simplified github example 2010-07-14 11:15:18 -07:00
Tj Holowaychuk 3ee4492b3c Started github example 2010-07-14 11:11:14 -07:00
Tj Holowaychuk 38c453b3c6 More migration docs 2010-07-14 10:49:23 -07:00
Tj Holowaychuk 3d41c61991 Updated docs 2010-07-14 10:23:43 -07:00
Tj Holowaychuk 1f9f47f97e Readme 2010-07-14 10:18:12 -07:00
Tj Holowaychuk 41cc2923b1 Updated multipart example 2010-07-14 09:34:38 -07:00
Tj Holowaychuk 4c180f3eed Added connect-form submodule 2010-07-14 08:59:34 -07:00
Tj Holowaychuk 5f9a64dbea Redirecting in multipart example 2010-07-14 08:49:20 -07:00
Tj Holowaychuk 9d37bfdcf1 listen() in examples 2010-07-14 08:43:23 -07:00
Tj Holowaychuk d738c3aca6 Added methodOverride to generated app 2010-07-13 11:32:37 -07:00
Tj Holowaychuk 836c4313ab Tasks 2010-07-13 11:31:21 -07:00
Tj Holowaychuk 91c6478add Updated submodules 2010-07-13 11:29:19 -07:00
Tj Holowaychuk fce527a55b Added progress to multipart example 2010-07-13 10:07:41 -07:00
Tj Holowaychuk 9a1f62fc1f Added multipart example 2010-07-13 09:48:33 -07:00
Tj Holowaychuk 018d8656d3 Added form example 2010-07-13 09:37:39 -07:00
Tj Holowaychuk 2636e1ba45 Added app.error() support 2010-07-13 09:09:10 -07:00
Tj Holowaychuk caed07dfc1 Added exception example 2010-07-13 08:48:44 -07:00
Tj Holowaychuk 373cf3328d Added test to confirm set() is chainable 2010-07-13 08:36:56 -07:00
Tj Holowaychuk 0370c3fa01 configure() is chainable 2010-07-13 08:36:22 -07:00
Tj Holowaychuk f5143a7d63 Added test to confirm that configure() callbacks execute in context to the server 2010-07-13 08:35:22 -07:00
Tj Holowaychuk 346b2a27cb Removed annoying padding transition 2010-07-12 17:46:26 -07:00
Tj Holowaychuk 38281e6361 Added more setting docs 2010-07-12 17:43:01 -07:00
Tj Holowaychuk 6e8413f568 Moved config docs up 2010-07-12 17:39:14 -07:00
Tj Holowaychuk cb04364381 Configuration docs 2010-07-12 17:37:26 -07:00
Tj Holowaychuk 83d2555123 Added configuration section 2010-07-12 17:32:07 -07:00
Tj Holowaychuk 0ace97c8d4 Route passing docs 2010-07-12 17:09:52 -07:00
Tj Holowaychuk 9e3a0c61b8 Started guide 2010-07-12 17:06:35 -07:00
Tj Holowaychuk 2fda5c7873 Fixed banner 2010-07-12 16:47:30 -07:00
Tj Holowaychuk e29868c8ce Added some links 2010-07-12 16:44:53 -07:00
Tj Holowaychuk ac560be870 Added menu to docs 2010-07-12 16:42:11 -07:00
Tj Holowaychuk 5a29cbf4a7 Better hello world example 2010-07-12 16:36:01 -07:00
Tj Holowaychuk dc77894f68 Migration docs for req.param() 2010-07-12 16:32:43 -07:00
Tj Holowaychuk 74432a6b9d Added redirect migration docs 2010-07-12 16:29:53 -07:00
Tj Holowaychuk 2b2fa7e77c Absolute labs banner 2010-07-12 16:23:16 -07:00
Tj Holowaychuk c3f71b33aa Removed backticks from docs 2010-07-12 16:17:40 -07:00
Tj Holowaychuk 927aae72d1 Docs for plugins vs middleware 2010-07-12 16:15:53 -07:00
Tj Holowaychuk 2a674f4e8d Added partial migration docs 2010-07-12 16:07:03 -07:00
Tj Holowaychuk 0b86ce2bda Added view rendering migration section 2010-07-12 15:58:54 -07:00
Tj Holowaychuk 548a0709f4 Control passing docs 2010-07-12 15:47:09 -07:00
Tj Holowaychuk da84c0bb4d Migration docs for params 2010-07-12 15:42:38 -07:00
Tj Holowaychuk 9e68a5b9ab Started migration docs 2010-07-12 15:28:46 -07:00
Tj Holowaychuk 6982bdaa28 Updated expresso submodule 2010-07-12 14:55:32 -07:00
Tj Holowaychuk c1809232fe Merge branch 'flash' into connect 2010-07-12 14:55:19 -07:00
Tj Holowaychuk 3c06c82eb7 Added tests for req.flash() 2010-07-12 14:55:14 -07:00
Tj Holowaychuk 1bcccb3134 Added req.flash() 2010-07-12 14:14:50 -07:00
Tj Holowaychuk cdf49dc87e Removed a utils.merge() call 2010-07-12 11:35:07 -07:00
Tj Holowaychuk 0a0fb8f803 Updated expresso submodule 2010-07-09 16:41:38 -07:00
Tj Holowaychuk 60cfd56369 Regenerated docs 2010-07-09 15:32:13 -07:00
Tj Holowaychuk 73050d38c5 Added make install-docs 2010-07-09 15:31:05 -07:00
Tj Holowaychuk c50e941972 Tasks 2010-07-09 15:28:51 -07:00
Tj Holowaychuk 7c59fd21e2 Fixed package.json 2010-07-09 13:56:07 -07:00
Tj Holowaychuk b095a4221c Added ejs submodule 2010-07-09 13:19:37 -07:00
Tj Holowaychuk 1ef39fa3b8 Updated Connect submodule 2010-07-09 10:53:57 -07:00
Tj Holowaychuk fcf4530d83 Tasks 2010-07-08 14:59:57 -07:00
Tj Holowaychuk 0515e14d27 Added make test-cov 2010-07-08 14:49:13 -07:00
Tj Holowaychuk ddbef0bd79 Merge branch 'view-helpers' into connect 2010-07-08 14:47:21 -07:00
Tj Holowaychuk bc5d31f86a Added view helper support 2010-07-08 14:47:13 -07:00
Tj Holowaychuk 09147a2aab Regenerated docs 2010-07-08 14:33:54 -07:00
Tj Holowaychuk a75a119e2f Added default view engine support
Now app.set("view engine", "jade") allows you to
res.render("jade")
2010-07-08 14:31:27 -07:00
Tj Holowaychuk c1b3546161 More example docs 2010-07-08 14:07:05 -07:00
Tj Holowaychuk 8338432c7b Added app generation to bin/express 2010-07-08 14:01:56 -07:00
Tj Holowaychuk 8beae065cf Added view callback error test 2010-07-08 13:17:30 -07:00
Tj Holowaychuk 0e7d39aa13 Added invalid view test 2010-07-08 13:16:36 -07:00
Tj Holowaychuk 74063ad735 Tasks 2010-07-08 13:10:53 -07:00
Tj Holowaychuk 55a29808c9 Added view callback test 2010-07-08 13:09:15 -07:00
Tj Holowaychuk 40f3de3939 Merge branch 'view-reloading' into connect 2010-07-08 13:04:50 -07:00
Tj Holowaychuk 5d94ab09e3 Updated jade submodule 2010-07-08 13:04:21 -07:00
Tj Holowaychuk b34ff6853d Renamed setting to "reload views" 2010-07-08 12:45:03 -07:00
Tj Holowaychuk e2570be957 Added view reloading 2010-07-08 12:38:16 -07:00
Tj Holowaychuk 95e6fff3da Added another example 2010-07-08 11:49:12 -07:00
Tj Holowaychuk 9de12b7385 Tasks 2010-07-08 11:33:39 -07:00
Tj Holowaychuk beffe906e4 ws 2010-07-08 11:12:42 -07:00
Tj Holowaychuk e850d1073d Partials without extensions use the same extension as the parent view 2010-07-08 11:01:20 -07:00
Tj Holowaychuk c02a2ba5ba Exposing __filename as a local for views 2010-07-08 10:49:46 -07:00
Tj Holowaychuk f92bb6690b Todo 2010-07-08 10:40:46 -07:00
Tj Holowaychuk 5842a3bba6 Added test for non-collection partial support 2010-07-08 10:38:30 -07:00
Tj Holowaychuk fcf691d97c Added view test for magic locals 2010-07-08 10:27:23 -07:00
Tj Holowaychuk a32c7d5f07 Added as: global support 2010-07-08 10:24:12 -07:00
Tj Holowaychuk edfb18b75a Added as: this support 2010-07-08 10:17:11 -07:00
Tj Holowaychuk 5544c5d5d4 Added collection "as" option test 2010-07-08 10:13:24 -07:00
Tj Holowaychuk 22100f7c3a Added support for partial(view, array) as collection 2010-07-08 10:09:03 -07:00
Tj Holowaychuk 8ece01ccda Fixed partial support 2010-07-08 09:56:03 -07:00
Tj Holowaychuk 9b68039a62 Caching view contents 2010-07-08 09:53:34 -07:00
Tj Holowaychuk a914326e75 todo 2010-07-08 09:49:13 -07:00
Tj Holowaychuk 2b7dd35e05 Todo 2010-07-08 09:36:59 -07:00
Tj Holowaychuk 15e41169ad Added bin/express to package.json 2010-07-08 09:25:43 -07:00
Tj Holowaychuk f8c5219c12 Updated jade submodule 2010-07-08 09:23:37 -07:00
Tj Holowaychuk c570b67dda Updated jade submodule 2010-07-08 09:16:57 -07:00
Tj Holowaychuk 456fac1700 Tasks 2010-07-08 07:43:17 -07:00
Tj Holowaychuk 41e58c394b Updated tasks 2010-07-07 17:16:18 -07:00
Tj Holowaychuk 5aeda5f67b Added .pomo
Used with my ruby "pomo" executable, for managing tasks
2010-07-07 17:15:36 -07:00
Tj Holowaychuk c96adf168c Added ./index.js
For super easy git installs
2010-07-07 17:13:49 -07:00
Tj Holowaychuk 40c5bc01ff Docs 2010-07-07 17:08:07 -07:00
Tj Holowaychuk 09dabef70c Updated docs 2010-07-07 17:03:23 -07:00
Tj Holowaychuk 96edee806e req.param() docs 2010-07-07 17:03:13 -07:00
Tj Holowaychuk e58f4683d1 Finished req.accepts() 2010-07-07 17:00:23 -07:00
Tj Holowaychuk 9750817bf0 Added more tests for req.accepts() 2010-07-07 16:44:42 -07:00
Tj Holowaychuk 7099d730e6 Docs for req.accepts() 2010-07-07 16:41:07 -07:00
Tj Holowaychuk 13c290e99f Docs for req.accepts() 2010-07-07 16:40:29 -07:00
Tj Holowaychuk cf37966e39 Added req.accepts() 2010-07-07 16:38:23 -07:00
Tj Holowaychuk 9449c4b9b5 Merge branch 'params' into connect 2010-07-07 16:05:43 -07:00
Tj Holowaychuk 046172e5d9 Added req.param() POST support via connect.bodyDecoder() 2010-07-07 16:05:32 -07:00
Tj Holowaychuk c74446e38c Added req.param() 2010-07-07 15:54:25 -07:00
Tj Holowaychuk 7897460993 Added req.header() tests 2010-07-07 15:38:06 -07:00
Tj Holowaychuk 4b59583bca Docs 2010-07-07 15:34:46 -07:00
Tj Holowaychuk 41f73559f2 Setting res.render() cache to true in production 2010-07-07 15:21:21 -07:00
Tj Holowaychuk d3090c0965 Added option docs to res.render() 2010-07-07 15:17:48 -07:00
Tj Holowaychuk dc5caebbf8 Added haml test 2010-07-07 15:10:16 -07:00
Tj Holowaychuk 14280dfedb Added buffer support to res.send() 2010-07-07 14:54:23 -07:00
Tj Holowaychuk 8fdf11135a Added res.attachment() 2010-07-07 14:45:45 -07:00
Tj Holowaychuk c8baa8f349 Added res.send() Content-Type precedence test 2010-07-07 14:38:41 -07:00
Tj Holowaychuk a6e25b46af Added res.send() examples 2010-07-07 14:29:18 -07:00
Tj Holowaychuk 395d14ab58 Allowing status as first or second arg to res.send() 2010-07-07 14:25:06 -07:00
Tj Holowaychuk 0d4b57df7a req.send() headers take precedence 2010-07-07 14:11:00 -07:00
Tj Holowaychuk 416e7617b3 res.contentType() using res.header() 2010-07-07 14:02:55 -07:00
Tj Holowaychuk 838c470017 Added res.header() 2010-07-07 14:02:16 -07:00
Tj Holowaychuk f0a09665db res.send() only setting Content-Type when not already present 2010-07-07 13:57:56 -07:00
Tj Holowaychuk 1397fa64d5 Added req.header(name, defaultValue) 2010-07-07 13:33:21 -07:00
Tj Holowaychuk ac17a6afcf Added res.contentType() tests 2010-07-07 13:32:16 -07:00
Tj Holowaychuk 35af1bab30 Added req.xhr as alias of req.isXMLHttpRequest 2010-07-07 13:22:59 -07:00
Tj Holowaychuk 1fe7bb271a Added req.isXMLHttpRequest 2010-07-07 13:21:07 -07:00
Tj Holowaychuk 774e25d944 Added make install-support and make uninstall-support 2010-07-07 13:06:41 -07:00
Tj Holowaychuk 6770e8541d Added `make install 2010-07-07 13:05:21 -07:00
Tj Holowaychuk 70e94e4dde Updated connect submodule 2010-07-07 12:54:28 -07:00
Tj Holowaychuk 0ffbc6e345 Added jade submodule 2010-07-07 12:43:48 -07:00
Tj Holowaychuk 25e796753f Added Connect submodule 2010-07-07 12:43:01 -07:00
Tj Holowaychuk 70d9ef4f77 Added test for next()ing 2010-07-07 11:56:37 -07:00
Tj Holowaychuk fd67c9a589 Exposing req / res to each other 2010-07-07 11:52:18 -07:00
Tj Holowaychuk f0917ff774 Ignore pids 2010-07-07 07:49:40 -07:00
Tj Holowaychuk 843281dec0 Added hello-world example
run with:
    connect -C examples/helloworld
2010-07-07 07:49:01 -07:00
Tj Holowaychuk 3a21588429 Docs :) 2010-07-07 07:35:57 -07:00
Tj Holowaychuk 21eeb09a3c Executable docs 2010-07-06 20:31:52 -07:00
Tj Holowaychuk 900c5ed358 More docs 2010-07-06 19:46:48 -07:00
Tj Holowaychuk 195c8a92d1 Added contributors back to docs 2010-07-06 19:42:06 -07:00
Tj Holowaychuk 7c651e6093 More styling
gahh!!
2010-07-06 17:10:59 -07:00
Tj Holowaychuk 860b899f0c Added images back to docs 2010-07-06 17:06:39 -07:00
Tj Holowaychuk 87b7524de9 More doc styling 2010-07-06 17:01:04 -07:00
Tj Holowaychuk 29641ae16a Started new docs 2010-07-06 16:56:42 -07:00
Tj Holowaychuk 02e32a7a9d App generation in bin/express 2010-07-06 08:17:35 -07:00
Tj Holowaychuk 3056369c6e Started bin/express 2010-07-06 08:06:39 -07:00
Tj Holowaychuk 3da75726d3 Error handling for views 2010-07-06 07:53:18 -07:00
Tj Holowaychuk b7346de47d Fixed partials 2010-07-06 07:07:56 -07:00
Tj Holowaychuk 7a69100b2f Updated copyright 2010-07-06 06:53:13 -07:00
Tj Holowaychuk 2732d2b9d3 Updated docs 2010-07-06 06:52:48 -07:00
Tj Holowaychuk 87bb27cc4f Added migrate doc files
yet to be filled with copy :)
2010-07-05 21:56:58 -07:00
Tj Holowaychuk bafa300b0f Generated docs 2010-07-05 21:52:49 -07:00
Tj Holowaychuk 939cf4542f Added make docs 2010-07-05 21:47:37 -07:00
Tj Holowaychuk 874975da54 Added response helpers 2010-07-05 21:37:56 -07:00
Tj Holowaychuk f0bebd4c33 Docs 2010-07-05 16:58:07 -07:00
Tj Holowaychuk c444a11862 Todo 2010-07-05 16:55:16 -07:00
Tj Holowaychuk 4c0704e338 Started implementing partials again 2010-07-05 16:50:37 -07:00
Tj Holowaychuk 77f4cd5d58 Refactord ServerResponse#render() 2010-07-05 16:30:55 -07:00
Tj Holowaychuk 9858d3c5a8 Refactord ServerResponse#render() 2010-07-05 16:30:21 -07:00
Tj Holowaychuk 414acbc9ec Added layout support 2010-07-05 16:29:39 -07:00
Tj Holowaychuk 21f904db42 Started ServerResponse#render() 2010-07-05 16:14:34 -07:00
Tj Holowaychuk f6ca253849 Applying arguments from createServer() 2010-07-05 15:54:35 -07:00
Tj Holowaychuk 3f989191e3 Added failing constructor middleware test 2010-07-05 15:49:38 -07:00
Tj Holowaychuk 2bea014e89 Added middleware usage test 2010-07-05 15:43:10 -07:00
Tj Holowaychuk 84fc19a75f Docs 2010-07-05 15:33:56 -07:00
Tj Holowaychuk d803924ef0 Added Server#{set,enable,disable}() and friends 2010-07-05 15:32:54 -07:00
Tj Holowaychuk 889f8d9d30 Added server.js 2010-07-05 15:13:32 -07:00
Tj Holowaychuk 1dcb7eaf1f . 2010-07-05 15:13:19 -07:00
Tj Holowaychuk 5f9e4ace2f Added basic app test 2010-07-05 15:02:25 -07:00
Tj Holowaychuk 6386330973 Started tests 2010-07-05 14:58:38 -07:00
Tj Holowaychuk fd89b9755e Removed benchmarks 2010-07-05 14:52:19 -07:00
Tj Holowaychuk 730f454278 Removed examples 2010-07-05 14:51:53 -07:00
Tj Holowaychuk e2fca29c91 Cleared out makefile 2010-07-05 14:51:45 -07:00
Tj Holowaychuk f97a222cf5 Removed specs 2010-07-05 14:50:39 -07:00
Tj Holowaychuk c75105e977 Added expresso submodule 2010-07-05 14:50:21 -07:00
Tj Holowaychuk 7096471d65 Removed submodules 2010-07-05 14:49:57 -07:00
Tj Holowaychuk cc1cee8a38 Auto-requiring ./view.js 2010-06-19 22:25:10 -07:00
Tj Holowaychuk 5f2680889f Added application.js 2010-06-19 22:18:35 -07:00
Tj Holowaychuk b3ae8bb606 Added Application#runConfig() 2010-06-19 22:07:18 -07:00
Tj Holowaychuk 72d9f37845 Added Application#{set,enable,disable}() 2010-06-19 21:39:36 -07:00
Tj Holowaychuk fdfccafd84 Fixed another typo 2010-06-19 21:35:16 -07:00
Tj Holowaychuk a784f946ba Fixed ternary typo 2010-06-19 21:34:12 -07:00
Tj Holowaychuk a04af6c4bd Started re-write of views 2010-06-19 21:33:29 -07:00
Tj Holowaychuk 64b24a96c8 Fixing chat example 2010-06-18 17:30:20 -07:00
Tj Holowaychuk a62a5d0d7b Removed old cruft
wow express is light now! haha.. go connect go
2010-06-18 17:16:17 -07:00
Tj Holowaychuk 3043d1e839 Hello world working (somewhat) 2010-06-18 17:00:07 -07:00
Tj Holowaychuk a3aefb6902 Removed spec crap
not a good fit for async
2010-06-18 16:23:08 -07:00
Tj Holowaychuk a42aaa270c Removed lib/support
you will all have to install these via kiwi or npm etc,
bundling is no more! (at least for now)
2010-06-18 16:22:48 -07:00
Tj Holowaychuk f8b471c17b Started the destruction :) 2010-06-18 16:21:16 -07:00
Tj Holowaychuk 87adff44db Added connect submodule 2010-06-18 16:15:52 -07:00
isaacs 767bba9c04 s/parseQuery/parse/g (The node querystring module changed recently) 2010-06-16 00:54:19 -07:00
Tj Holowaychuk 0c827521d0 Added npm install docs 2010-06-15 14:25:20 -07:00
Tj Holowaychuk 80cec7d12f Release 0.14.0 2010-06-15 14:22:51 -07:00
Tj Holowaychuk 5f916357e9 Make Express npm friendly
Since wayyy back in the early days of node we did
not have relative require :)
2010-06-15 14:14:40 -07:00
Tj Holowaychuk ea82eea9bb Misc package.json updates 2010-06-15 13:50:17 -07:00
Aaron Heckmann 22222d7db4 update node version 2010-06-14 01:54:34 -04:00
Aaron Heckmann cebee369d1 add ciaran 2010-06-13 19:59:39 -04:00
Aaron Heckmann faf809851c add contributors 2010-06-10 21:21:32 -04:00
Aaron Heckmann d05aafd76b use plugin option instead of global set() 2010-06-10 20:21:52 -04:00
visionmedia 8d52721873 Removed bufferSize from static benchmarks 2010-06-10 11:09:26 -07:00
visionmedia 66c6152cd2 Merge remote branch 'aheckmann/staticbuffersize' 2010-06-10 11:08:40 -07:00
Aaron Heckmann 32cd51d3a5 add 'static buffer size' setting 2010-06-09 21:19:02 -04:00
Aaron Heckmann 497a28401e cache view and partial subdirectories 2010-06-09 08:04:45 -07:00
visionmedia e46912047c Updated haml submodule 2010-06-08 05:44:54 -07:00
visionmedia 56b573ede5 Updated class submodule 2010-06-04 11:07:38 -07:00
visionmedia 0276be1789 Updated haml submodule 2010-06-04 11:05:47 -07:00
visionmedia 7db4c60fc3 Removed old release details link
Not really relevant anymore. (but really im just testing
my new CI server haha :D )
2010-06-03 16:39:43 -07:00
visionmedia 95cc01dd91 Added missing file comment 2010-06-03 16:36:11 -07:00
visionmedia cce1dddf42 Added author to package.json
Guys feel free to add yourself as contributors in there :)
2010-06-03 16:31:08 -07:00
visionmedia 0938b57841 Removed bin/express
for now :) maybe it will come back some day when it is
more useful
2010-06-03 16:25:50 -07:00
visionmedia aef8550e2f Removed old todo comment 2010-06-03 16:22:45 -07:00
visionmedia 71bf0bde32 Readme typo 2010-06-03 16:18:59 -07:00
visionmedia 750623b9b1 Fixed mime.type() comments now that ".ext" is not supported 2010-06-03 16:15:32 -07:00
visionmedia 1f12c53b65 Added Connect port notice 2010-06-03 16:04:36 -07:00
visionmedia 8717ea1b95 Updated seed.yml 2010-06-01 08:49:21 -07:00
visionmedia db2eb658ca Release 0.13.0 2010-06-01 08:49:04 -07:00
visionmedia 70483484ce Fixed upload example 2010-06-01 08:44:26 -07:00
visionmedia d21afc43a1 Merge branch 'charset' of git://github.com/aheckmann/express 2010-05-31 14:06:29 -07:00
visionmedia 7ad0803f2e Updated package.json 2010-05-31 14:05:15 -07:00
Aaron Heckmann ec4bfd55f9 not-found exceptions using utf-8 2010-05-31 12:58:53 -04:00
Aaron Heckmann f65174a0db show-exceptions uses utf-8 2010-05-31 12:56:30 -04:00
visionmedia 8b1fcd4dd7 mime.type() no longer accepts ".type" 2010-05-30 13:14:08 -07:00
visionmedia 9509237958 Fixed mime.type() due to path.extname() changes 2010-05-30 13:04:35 -07:00
visionmedia f20fd20a06 Fixed view support due to fs.readFile Buffers 2010-05-30 12:46:15 -07:00
visionmedia 8e48120fb7 Updated JSpec 2010-05-30 12:42:31 -07:00
visionmedia 44cc5ac883 Updated haml submodule 2010-05-27 15:32:30 -07:00
visionmedia 9a43cc8c4b Updated haml submodule 2010-05-25 16:08:50 -07:00
visionmedia 8dfc0d54f4 Updated haml submodule 2010-05-25 13:49:30 -07:00
visionmedia 77febd21de Fixed code styling 2010-05-23 09:38:42 -07:00
Aaron Heckmann 84a997c66b Added support for deleting cookies via Request#cookie('key', null) 2010-05-23 09:37:53 -07:00
Aaron Heckmann b900a59fc2 respond(204) should not have a body 2010-05-22 12:13:15 -04:00
visionmedia ca782dbc58 Release 0.12.0 2010-05-22 08:24:22 -07:00
visionmedia 746cda27ec Fixed cookie spec urlencoding 2010-05-22 08:23:28 -07:00
visionmedia 16d1651656 Fixed a cookie spec 2010-05-22 08:22:01 -07:00
visionmedia 4735fb2377 Merge branch 'master' of git://github.com/tritonrc/express 2010-05-22 08:21:08 -07:00
Aaron Heckmann ec6b518fd2 compatible with node v0.1.96 2010-05-22 08:09:09 -07:00
Brian McKinney 580ad1b192 Make sure to URL encode cookie name and value on response if we are going to URL decode on request 2010-05-18 18:53:01 -06:00
visionmedia 23d8810486 Updated haml submodule 2010-05-17 15:43:38 -07:00
visionmedia d579d62eb6 Comment changed to match others 2010-05-14 07:30:14 -07:00
visionmedia 529f785e3c Merge branch 'master' of git://github.com/Guille/express 2010-05-14 07:28:53 -07:00
Guillermo Rauch 0581ae87b4 Renaming Globals to helpers (I'm sold) 2010-05-14 11:16:51 -03:00
visionmedia cda1059336 Updated readme, we are compatible with node --version v0.1.95 2010-05-14 06:51:59 -07:00
Aaron Heckmann 1aed6b5c30 Merge branch 'master' into encoding 2010-05-14 08:05:46 -04:00
Aaron Heckmann 4e68705b24 compatible with node v0.1.95 2010-05-14 08:01:05 -04:00
Guillermo Rauch 216cb1ea12 Added support for globals (eg: helpers) in views
- Added export.Globals in plugins/view.js
 - Added two specs (one for a simple template, one for a template with a layout) with a dummy i18n helper
 - Updated README features list
2010-05-13 20:35:25 -03:00
Guillermo Rauch 8ef6a0b432 Merge branch 'master' of http://github.com/visionmedia/express
* 'master' of http://github.com/visionmedia/express: (168 commits)
  Updated haml submodule
  s/==/===/
  Misc refactoring to make parseCookie() more readable / spec for overriding keys
  s/QueryString/queryString/
  Added spec for malformed cookies
  regexps have no "n" flag
  No need to quote key in spec
  Fixed LF -> CRLF for setting multiple cookies
  Redo cookies parsing to accept quoted values and url escaped cookies
  Remove inode from ETag, modified time only
  Release 0.11.0
  Works fine with node --version v0.1.94
  Refactoring some spec fixtures
  Fixing spec for EJS partial
  Updated ext
  Updated haml
  Added spec / refactored layout of different engine support
  Added spec for layouts with different engines
  Fixing EJS partial support by passing along the context. Issue #307
  Allow layouts to use different engines
  ...

Conflicts:
	lib/express/core.js
2010-05-13 18:53:11 -03:00
visionmedia 5dc152c46e Updated haml submodule 2010-05-11 13:22:32 -07:00
visionmedia c3a21437e4 Merge branch 'integration' 2010-05-11 07:57:50 -07:00
visionmedia 32bc8dcbf9 s/==/===/ 2010-05-11 07:57:24 -07:00
visionmedia 677ca7b4aa Misc refactoring to make parseCookie() more readable / spec for overriding keys 2010-05-11 07:55:15 -07:00
visionmedia dfc2331104 s/QueryString/queryString/ 2010-05-11 07:47:20 -07:00
visionmedia cd06bbfb8d Added spec for malformed cookies 2010-05-11 07:46:44 -07:00
visionmedia 1d596bcbac regexps have no "n" flag 2010-05-11 07:44:31 -07:00
visionmedia 0cb7b9c13d No need to quote key in spec 2010-05-11 07:42:23 -07:00
visionmedia a180efeca7 Merge branch 'master' of git://github.com/tritonrc/express into integration 2010-05-11 07:41:15 -07:00
visionmedia eef24ea29c Fixed LF -> CRLF for setting multiple cookies 2010-05-11 07:25:08 -07:00
Brian McKinney 458bb3d7f7 Redo cookies parsing to accept quoted values and url escaped cookies 2010-05-10 17:18:42 -06:00
visionmedia ffb23d92c0 Remove inode from ETag, modified time only 2010-05-07 13:52:13 -07:00
visionmedia 0ce39a4cf6 Release 0.11.0 2010-05-06 15:41:15 -07:00
visionmedia a24c70e490 Works fine with node --version v0.1.94 2010-05-06 15:36:06 -07:00
visionmedia 8d4ef6e883 Merge branch 'integration' 2010-05-06 15:35:39 -07:00
visionmedia 54865ebdee Refactoring some spec fixtures 2010-05-06 15:24:30 -07:00
visionmedia cb8e704d5c Merged bdotdub/master 2010-05-06 15:21:47 -07:00
Benny Wong 57f4978442 Fixing spec for EJS partial
* Had to use double quote and not single quote for the partial filename
* Couldn't get each to work. Using ugly `for` for now
2010-05-06 13:59:50 -04:00
visionmedia b8833f4c9e Updated ext 2010-05-06 10:29:15 -07:00
visionmedia 5c40cbc675 Merge branch 'update-haml' 2010-05-06 09:17:13 -07:00
visionmedia a455dcc919 Updated haml 2010-05-06 09:17:08 -07:00
visionmedia 289487cc46 Merge branch 'integration' 2010-05-06 07:52:32 -07:00
visionmedia 42b28d5bd6 Added spec / refactored layout of different engine support 2010-05-06 07:52:28 -07:00
visionmedia 46bee05d93 Merge branch 'master' of git://github.com/nick/express into integration 2010-05-06 07:44:43 -07:00
visionmedia 49bed5cd5f Added spec for layouts with different engines 2010-05-06 07:43:54 -07:00
Benny Wong 624cf93e2e Fixing EJS partial support by passing along the context. Issue #307 2010-05-06 01:20:35 -04:00
Nick Poulden 6ab76cda51 Allow layouts to use different engines 2010-05-05 13:19:16 -07:00
Nick Poulden 15beb81368 Allow ejs templates to contain single quotes 2010-05-05 11:42:41 -07:00
visionmedia 6a6cce03b7 Release 0.10.1 2010-05-03 08:42:01 -07:00
Matt Colyer 970ff87ef6 Fix binary uploads. 2010-05-01 11:46:25 -07:00
visionmedia 8b6c4d322f Updated history 2010-04-30 10:46:24 -07:00
visionmedia 4467a00acd Release 0.10.0 2010-04-30 10:34:13 -07:00
visionmedia 63efc61517 Added "dump exceptions" setting, which is enabled by default 2010-04-30 10:09:53 -07:00
visionmedia 7aa18345c8 Added better ejs usage example 2010-04-30 10:05:04 -07:00
visionmedia 34149187a8 Catching ENOENT in view caching, preventing error when "views/partials" is not found 2010-04-30 10:00:00 -07:00
visionmedia 2d132cd0d5 Merge branch 'ejs' 2010-04-30 09:57:23 -07:00
visionmedia 8d741361e0 Added simple ejs support 2010-04-30 09:57:19 -07:00
visionmedia 2bcea3a370 Added more cache key specs 2010-04-30 09:33:10 -07:00
visionmedia ead3cace02 No need to reverse plugins on each request
This was slowing things down quite a bit
2010-04-30 09:24:17 -07:00
visionmedia 7afa5c7b43 Revert "Clone / reverse plugins ONCE"
shit, was causing some bugs, will figure that out first

This reverts commit 115765e1ee.
2010-04-30 09:18:38 -07:00
visionmedia 115765e1ee Clone / reverse plugins ONCE
huuuuge performance boost
2010-04-30 09:12:48 -07:00
visionmedia d712fae2d7 Fixed bug producing messed up response bodies
Express was trying to respond twice to the same request
due to an error caused by having no callback,
which was then caught, and responded to using Request#error()

haha!
2010-04-30 08:53:52 -07:00
visionmedia 0dba9bd87f Removed Logger "request" format 2010-04-30 08:40:59 -07:00
visionmedia 2fbc495088 Merge branch 'update-ext' 2010-04-30 08:00:04 -07:00
visionmedia 37d490cbe4 Fixed bug recently introduced preventing plugin events to trigger 2010-04-30 07:59:57 -07:00
visionmedia 451679c582 Cache reaper destroys null caches as well
so they dont linger until expired
2010-04-29 09:01:17 -07:00
visionmedia 7270a13ef7 Fixed compileCookie() utility due to ext changes 2010-04-29 08:56:55 -07:00
visionmedia 16f3f90ed7 Todo 2010-04-29 08:52:48 -07:00
visionmedia 9ff2f81a10 Fixed cache bugs introduced by 1bc9a1a 2010-04-29 08:52:01 -07:00
visionmedia 1bc9a1af6a Fixed Cache Store.Memory usage of Object#reduce() 2010-04-29 08:42:51 -07:00
visionmedia 760d9e3341 Fixed error page hash iteration 2010-04-29 08:35:20 -07:00
visionmedia 5b28abc5ed Fixed session / cache key iteration due to ext changes 2010-04-29 08:23:24 -07:00
visionmedia defb1596bb Removed Array#at() usage 2010-04-29 08:10:31 -07:00
visionmedia 9c117d5875 Request#accepts() fixed due to ext changes 2010-04-29 08:09:48 -07:00
visionmedia 1b09fce42a Todo 2010-04-29 08:05:51 -07:00
visionmedia 5e328830e7 Replace merge() calls with Object.merge() 2010-04-29 08:04:42 -07:00
visionmedia 606da1c45b Merge branch 'integration' 2010-04-29 06:50:52 -07:00
visionmedia 6232c1a8f3 Several fixes to http client
- Only attempts to "render" data on first request (not redirects)
  - Allows setting of "redirects" via the data variable
  - Fixed Host header predecence issue
  - Only setting Content-Length / Content-Type when not previously set
  - Passing response object on errors
2010-04-29 06:50:46 -07:00
Viktor Kelemen 15a24e68d2 In case of redirect the request function was called with a wrong param list 2010-04-29 19:21:14 +09:00
visionmedia c12ace81db Fixed Logger content-length 2010-04-28 16:57:55 -07:00
visionmedia 531990b516 Merge branch 'rename-halt' 2010-04-26 09:17:06 -07:00
visionmedia b90a3dbffe Renamed Request#halt() to Request#respond(). Closes #289
deprecated Request#halt(), however it will remain until 1.0
2010-04-26 09:17:01 -07:00
visionmedia 0352b97798 Merge branch 'integration' 2010-04-26 07:07:15 -07:00
visionmedia e45abe60bf _ -> val 2010-04-26 07:07:11 -07:00
visionmedia 8077481707 Merge branch 'cache' of git://github.com/aheckmann/express into integration 2010-04-26 07:05:49 -07:00
visionmedia 4651dd33cd Updated haml submodule 2010-04-26 06:56:07 -07:00
visionmedia c93cfa0871 Added "encoding" option to Request#render(). Closes #299
Should work :)
2010-04-26 06:44:29 -07:00
Aaron Heckmann d57cb7d411 utilize each() 2010-04-25 00:02:20 -04:00
visionmedia 81088766ee Updated ext submodule 2010-04-24 14:14:51 -07:00
visionmedia ae59a50c28 Added benchmark link 2010-04-23 15:24:40 -07:00
visionmedia 4a05056393 Removed unused param in Cache.startReaper()
wtf?
2010-04-23 15:15:27 -07:00
visionmedia 71e97c815a Merge branch 'benchmarks' 2010-04-23 14:40:04 -07:00
visionmedia 8b7787aa60 Added sass benchmarks 2010-04-23 14:39:58 -07:00
visionmedia e0f94b052b Added ruby haml :ugly option to make it render faster in benchmarks 2010-04-23 11:56:12 -07:00
visionmedia eb2c9ffd32 Added haml benchmarks 2010-04-23 11:49:22 -07:00
visionmedia 5af315c165 Using sys.inspect() instead of JSON.encode() for error output
produces cleaner output
2010-04-23 10:30:59 -07:00
visionmedia e9fdfc339b Added error reponse support for text/plain, application/json. Closes #297 2010-04-23 10:28:12 -07:00
visionmedia 132730acea Added specs for errors with text/plain and application/json 2010-04-23 09:55:10 -07:00
visionmedia 405097d323 Fixed Request#sendfile() 404 support even when a callback is available 2010-04-23 06:57:02 -07:00
visionmedia c9d79f26c5 Smooth line graph 2010-04-22 14:18:13 -07:00
visionmedia 7ef13eaf0c Merge branch 'benchmarks' 2010-04-22 14:15:41 -07:00
visionmedia 2756aba21f Added COL 2010-04-22 14:15:36 -07:00
visionmedia c01a7f57df Merge branch 'benchmarks' 2010-04-22 13:43:14 -07:00
visionmedia 33a4dd3841 Fixed graph labels 2010-04-22 13:43:11 -07:00
visionmedia 3c150db4a2 Merge branch 'benchmarks' 2010-04-22 13:20:27 -07:00
visionmedia e31f5d2325 Generating bar graphs for requests per sec 2010-04-22 13:20:24 -07:00
visionmedia f8a61c667e My bad, swap express -> node in graphs 2010-04-22 12:09:40 -07:00
visionmedia e2fe60399f Merge branch 'benchmarks' 2010-04-22 12:04:32 -07:00
visionmedia 59c4e35691 Added graphing capabilities (gnuplot must be installed) 2010-04-22 12:04:28 -07:00
visionmedia 2dc5afd018 Docs 2010-04-22 11:04:04 -07:00
visionmedia b5df39bc46 Merge branch 'benchmarks' 2010-04-22 11:02:24 -07:00
visionmedia f87b709923 Added node static / large static benchmarks 2010-04-22 11:02:21 -07:00
visionmedia 671aa1036b Merge branch 'benchmarks' 2010-04-22 10:55:52 -07:00
visionmedia 4580340db3 Added simple node benchmark 2010-04-22 10:55:46 -07:00
visionmedia 31b53eae39 Added larger ~550kb static benchmarks 2010-04-22 10:41:04 -07:00
visionmedia 089423958d run() returns the http.Server instance. Closes #298 2010-04-22 09:48:20 -07:00
visionmedia 0d02ea43e1 Default Server#host to null (INADDR_ANY)
use run(3000, localhost) etc as needed
2010-04-22 09:43:57 -07:00
visionmedia 93239ae3fb Logger "common" format scale of 0.4f 2010-04-22 09:01:08 -07:00
visionmedia 5d21e9364d Match sinatra buffer size for static benchmark 2010-04-21 18:06:57 -07:00
visionmedia b9306c4cca Added sinatra static benchmark 2010-04-21 18:05:03 -07:00
visionmedia c07bd31f61 Outputting rps while benchmarking 2010-04-21 17:07:13 -07:00
visionmedia fee4830669 Added simple sinatra benchmark 2010-04-21 17:05:39 -07:00
visionmedia 9016b6778e Remove pids 2010-04-21 17:04:19 -07:00
visionmedia e05501a1ae Added simple thin benchmark 2010-04-21 17:03:39 -07:00
visionmedia 23d09fcc9e Added express static benchmark 2010-04-21 16:53:11 -07:00
visionmedia 5d11fccbf2 Ignore *.out 2010-04-21 16:42:39 -07:00
visionmedia 3851957dd0 Started benchmark script 2010-04-21 16:41:50 -07:00
visionmedia 135afb0883 Revert "Renamed session Base" - haha :) just kidding
This reverts commit 27b27af7cd.
2010-04-21 15:50:54 -07:00
visionmedia 27b27af7cd Renamed session Base 2010-04-21 15:50:43 -07:00
visionmedia 20fe31b803 Removed ETag work-around for bug in node
commit that fixed this: http://github.com/ry/node/commit/3934cb54853ca23cee7ef3c6206a5b1264f8ba6d
2010-04-21 15:33:06 -07:00
visionmedia ebca9aab8d Fix chat app plugins 2010-04-21 15:13:10 -07:00
visionmedia 49821e0416 Request#stream() fixes
a) on "end" the stream is already destroyed
  b) AFAIK its not destroyed on "error", so now we destroy it
  c) no need to callback(err) unless first
2010-04-21 14:53:46 -07:00
visionmedia b5d6f1ada5 Merge branch 'etag' 2010-04-21 14:37:17 -07:00
visionmedia b40325cd7b Misc refactoring to Request#trigger() 2010-04-21 13:49:44 -07:00
visionmedia 3b27ec66e1 Removed "data || {}" in Event constructor. Not needed anymore since Object#merge() handles non objects 2010-04-21 13:42:49 -07:00
visionmedia 52b8b36d54 Updated ext submodule which includes higher performance Object#merge() 2010-04-21 13:14:35 -07:00
visionmedia 7e3106dd1b Increase performance by preventing several calls to toLowerCase() in Router#match()
Roughly 10% increase for routing speeds
2010-04-21 12:48:37 -07:00
visionmedia 399e0d94fc Merge branch 'fix-opera' 2010-04-21 11:45:32 -07:00
visionmedia eef1ff9e87 Fixed bug preventing Opera from retaining the generated session id. Closes #292
This might not be the best solution, I am not sure what the cookie spec states.
But it works for now :)
2010-04-21 11:45:27 -07:00
visionmedia 9202c7504b Added "request" logger format for debugging http requests 2010-04-21 10:46:01 -07:00
visionmedia 3fd7e3b93e Added make prof so that we can generate v8.log and analyse the output 2010-04-21 09:58:39 -07:00
visionmedia b6996df86a Added "template created in ..." message in bin/express 2010-04-21 09:24:55 -07:00
visionmedia 4b3efd7bfa Added PREFIX to makefile 2010-04-21 09:24:30 -07:00
visionmedia 12c2682c34 Merge branch 'bin' 2010-04-21 08:57:55 -07:00
visionmedia 2caf67b813 Bash template generator with dummy app 2010-04-21 08:57:50 -07:00
visionmedia fbbe13661a Added view partials to feature list 2010-04-20 20:59:23 -07:00
visionmedia 0fb102edae Normalized another header name 2010-04-20 20:57:12 -07:00
visionmedia b4dd90d074 0.9.0 release details link 2010-04-20 19:53:42 -07:00
visionmedia 2e3f806d07 Normalized header conventions.
For example use Content-Type instead of content-type,
Request#header() lowercases when reading a header,
however does not when writing.
2010-04-20 19:33:54 -07:00
visionmedia f76092e83e Request#error() now accepts a callback function
A common idiom is / will be to accept a callback function in most cases
so this will help to keep things DRY
2010-04-20 19:23:16 -07:00
visionmedia 1e44081583 Added Request#sendHead() 2010-04-20 19:15:30 -07:00
visionmedia 26b3a4259d Added support for Request#halt(status, null) (empty response body) 2010-04-20 19:11:18 -07:00
visionmedia 8a074a7e6d Request#sendfile() Content-Length prevents images from rendering for some reason
commented out for now
2010-04-20 17:27:32 -07:00
visionmedia e99434582f Added ETag support to Request#sendfile() 2010-04-20 16:44:11 -07:00
visionmedia fec57df994 Added options to Request#sendfile(), passed to fs.createReadStream() 2010-04-20 13:09:24 -07:00
visionmedia 033cb2d20a Updated haml submodule 2010-04-20 11:07:58 -07:00
visionmedia a5fa58e3e6 Updated ext submodule 2010-04-20 09:59:35 -07:00
visionmedia fdc9d2714b Removed unused script from sample upload app.
This was preventing the page from loading
2010-04-20 09:46:02 -07:00
visionmedia 824ca9b513 Merge branch 'update-ext' 2010-04-20 09:32:57 -07:00
visionmedia a74a740964 Updated ext submodule 2010-04-20 09:32:52 -07:00
visionmedia 2041d52495 no need for type coercion for testing methods 2010-04-20 08:13:38 -07:00
visionmedia fb5d528eff Merge branch 'stream' 2010-04-19 15:22:24 -07:00
visionmedia a2cedbd9da Request#download() now accepts second filename arg 2010-04-19 15:20:35 -07:00
visionmedia 8574eddfa0 Misc refactoring to Request#stream() 2010-04-19 14:43:42 -07:00
visionmedia 2ccf876929 Started Request#stream() based of Aarons work on Static#streamfile() 2010-04-19 13:58:29 -07:00
visionmedia 28df150784 Revert "Only unshift support libs once"
This reverts commit 0950083da2.
2010-04-16 10:27:33 -07:00
visionmedia 0950083da2 Only unshift support libs once 2010-04-16 10:25:21 -07:00
visionmedia 88c5f910da Changed; sendfile() using notFound()
instead of halt() so that our DSL-level notFound()
route can handle this as needed. Also outputs the pretty
page when visiting directly
2010-04-15 09:43:29 -07:00
visionmedia a9d3e4798e Updated node --version supported 2010-04-15 08:50:25 -07:00
visionmedia d85d834b23 Updated JSpec 2010-04-15 08:49:59 -07:00
visionmedia 5729da5a9f Release 0.9.0 2010-04-14 17:03:57 -07:00
visionmedia 1255331160 Release 0.9.0 2010-04-14 16:56:13 -07:00
visionmedia 0fef51b5f6 Updated git submodules 2010-04-14 16:41:42 -07:00
visionmedia 7cf18c0468 Merge branch 'fix-querystring-0' 2010-04-13 13:25:55 -07:00
visionmedia b994509b9d Fixed bug preventing falsey params. Closes #286
Request#param() would prevously fail with ?page=0 for example
when param("page") is used since it would return undefined and not 0
2010-04-13 13:25:44 -07:00
visionmedia 6571e19e8f Added spec for #286 2010-04-13 13:17:27 -07:00
visionmedia 7441164db9 Merge branch 'integration' 2010-04-12 20:40:03 -07:00
visionmedia 09bb10cd3f Merge branch 'download' of git://github.com/aheckmann/express into integration 2010-04-12 20:39:20 -07:00
Aaron Heckmann bd6f24f4b1 add cookie support to readme 2010-04-12 22:56:59 -04:00
Aaron Heckmann 0a174ad219 move Request#download to Static plugin
#download() was a hangover from before the Static plugin existed and no longer worked. Also added missing specs so this won't happen again.
2010-04-12 22:49:49 -04:00
visionmedia 33d004fb9a Fixed MockResponse to match node API 2010-04-12 11:04:52 -07:00
visionmedia 652bf34c77 Merge branch 'integration' 2010-04-12 10:40:08 -07:00
Aaron Heckmann 3f11bad68e fix FileWriteStream.prototype.close renamed to end() 2010-04-11 23:10:41 -04:00
Aaron Heckmann 5245fbfc6d fix OutgoingMessage.prototype.close has been renamed to end() 2010-04-11 23:06:09 -04:00
visionmedia 68f8ee8a99 Fixed "express" executable due to node 0.1.90 changes 2010-04-11 18:39:14 -07:00
visionmedia 7b83a52dce http client fix from node renaming close to end 2010-04-11 18:10:58 -07:00
visionmedia 5f57c82478 Merge branch 'integration' 2010-04-11 18:08:05 -07:00
visionmedia 3128cbef73 Removed TODO comment
added an issue http://github.com/visionmedia/express/issues/issue/285
2010-04-11 18:08:00 -07:00
visionmedia 694b2bf055 Merge branch 'node_0.1.9_fixes' of git://github.com/ciaranj/express into integration 2010-04-11 18:04:31 -07:00
visionmedia e03a023c5f Merge branch 'integration' 2010-04-11 17:45:19 -07:00
ciaranj 3ff5d3bd09 Temporarily add back in the old multipart support
This will at least get us going again whilst decisions are made :)
2010-04-10 10:06:04 +01:00
ciaranj 04841196e3 Fixed the cookie test so it will work in different timezones.
Tj, I'm not sure what timezone you were in when you wrote the test, but
I've guessed that it was PDT ?   Hopefully this fix allows the test to
run in any timezone :) .. I was surprised that cookies don't use UTC which
could've mate things a lot cleaner, meh, old tech eh.
2010-04-10 09:59:41 +01:00
visionmedia 18dd495d99 Revert "Fixed relative require of Class"
This reverts commit f714945bbb.
2010-04-08 16:09:06 -07:00
visionmedia f714945bbb Fixed relative require of Class 2010-04-08 15:43:33 -07:00
visionmedia a318ef2232 Cookie expires now using Date#toGMTString()
Spec I found wanted hyphens, but this appears to be the norm
for JS cookies
2010-04-06 19:40:59 -07:00
visionmedia 8ed24de9d3 Updated haml submodule 2010-04-06 15:32:36 -07:00
visionmedia e06e50936d Updated sass submodule 2010-04-06 14:38:06 -07:00
visionmedia d710e9cb47 Merge branch 'integration' 2010-04-06 11:01:23 -07:00
Aaron Heckmann 9af3699850 utilize Date.now() 2010-04-04 12:50:11 -04:00
visionmedia 3cc7b4d8c2 Utilizing Date.now() 2010-04-02 14:12:36 -07:00
visionmedia 8b58732a1f Merge branch 'globals' 2010-04-02 13:35:04 -07:00
visionmedia a2a0935343 Request is no longer global 2010-04-02 13:13:26 -07:00
visionmedia 2668156e53 Event is no longer global 2010-04-02 13:07:54 -07:00
visionmedia d67615d239 puts() -> sys.puts() 2010-04-02 13:06:25 -07:00
visionmedia afd70b64ed Removed "sys" global merge 2010-04-02 13:05:18 -07:00
visionmedia 78a6e43667 Request#render() now only sets option.cache to true when set("cache view contents") is true
to allow development editing of the views
2010-03-31 10:36:52 -07:00
visionmedia a65af97e43 Docs 2010-03-31 10:28:40 -07:00
visionmedia 637dfabe69 render() always passing "cache" and "filename" options
if the engine does not use them, then they
will be ignored. However this already bumps
haml.js by about %25 in terms of performance
2010-03-31 10:20:24 -07:00
visionmedia ff8b3c10f3 Updated haml submodule 2010-03-31 10:14:29 -07:00
visionmedia f442555d8f Updated haml submodule 2010-03-31 08:10:28 -07:00
visionmedia bdf9f882ad Merge branch 'better-haml' 2010-03-31 07:51:00 -07:00
visionmedia 1e5c5bfe00 Switching around partial filename 2010-03-31 07:50:11 -07:00
visionmedia 0e78fdfcb4 Templates using haml.js instead of haml-js 2010-03-29 10:23:22 -07:00
visionmedia 4f532f86dc Added haml.js submodule; removed haml-js 2010-03-29 09:21:33 -07:00
visionmedia 92844825cb Always httpOnly session cookie 2010-03-29 08:37:57 -07:00
visionmedia 6b13fc99b0 Merge branch 'flip-views' 2010-03-29 08:25:23 -07:00
visionmedia 0f7aa26757 Added deprecation warning for views 2010-03-29 08:25:18 -07:00
visionmedia a06f963263 Merge branch 'flipViewExt' of git://github.com/aheckmann/express into flip-views 2010-03-29 07:58:13 -07:00
visionmedia d31de1e654 Defaulting httpOnly for Session cookies, however overridable 2010-03-29 07:55:37 -07:00
Aaron Heckmann 46a0301022 session cookie now httpOnly 2010-03-27 00:21:37 -04:00
Aaron Heckmann 73d26036ef updated specs and example apps
all tests passing
2010-03-27 00:00:49 -04:00
Aaron Heckmann b9637c9d7d started flipping view extensions 2010-03-27 00:00:49 -04:00
visionmedia 08497683bf Fixed setting of multiple cookies. Closes #199 2010-03-26 16:08:39 -07:00
visionmedia 44a50f6e58 Moved require("http") out of Server#run() 2010-03-26 07:16:55 -07:00
visionmedia 4c2b4e5c66 Removed unused require 2010-03-26 07:16:12 -07:00
Guillermo Rauch b0884ad7c3 Correction 2010-03-25 19:33:45 -07:00
Guillermo Rauch cf09f86df2 Expose the http.Server instance 2010-03-25 19:17:43 -07:00
visionmedia d33c38f671 Merge branch 'integration' 2010-03-25 15:57:08 -07:00
Aaron Heckmann fbfba21854 multipart parse only when needed 2010-03-25 18:03:32 -04:00
visionmedia b2093d6f10 Merge branch 'partial-index-and-length' 2010-03-25 12:47:22 -07:00
visionmedia 736a0190c1 Passing __index__, __length__, __isFirst__, __isLast__ to collection partials. Closes #254 2010-03-25 12:47:17 -07:00
visionmedia a74c259c38 Request instance created before body parsing. Closes #262
Merge branch 'request'
2010-03-25 11:48:35 -07:00
visionmedia d3dedd6312 Fixed post param issue 2010-03-25 11:44:55 -07:00
visionmedia 920eab0ef9 Fixed mocks to work with new routing api 2010-03-25 11:37:56 -07:00
visionmedia d576085e8d . 2010-03-25 11:09:50 -07:00
visionmedia 62b9a9e287 Docs 2010-03-25 10:49:25 -07:00
visionmedia 56ffe1d62a Merge branch 'upload-limit' 2010-03-25 10:49:00 -07:00
visionmedia 14acbcb5f1 Added "max upload size" setting 2010-03-25 10:48:55 -07:00
visionmedia 9a0011bf49 Updated ext. Closes #256
Should be fixed now :)
2010-03-25 09:29:52 -07:00
visionmedia 7b9f18b097 Added Request#render() callback function. Closes #258 2010-03-25 08:53:47 -07:00
visionmedia f8e4333157 Merge branch 'integration' 2010-03-25 08:40:47 -07:00
visionmedia b5c933aa94 fn -> callback 2010-03-25 08:40:18 -07:00
visionmedia c441af3f2c Typo 2010-03-25 08:39:48 -07:00
visionmedia e885421a67 Merge branch 'master' of git://github.com/aheckmann/express into integration 2010-03-25 08:38:54 -07:00
visionmedia ce4fe24a93 Updated to JSpec 4.0.0 2010-03-25 08:25:38 -07:00
visionmedia 1c0e2ceba5 error() is passed the exception 2010-03-25 08:24:19 -07:00
Aaron Heckmann a435e8ec47 fn -> callback 2010-03-25 11:22:48 -04:00
visionmedia b958393135 Added DSL level error() route support 2010-03-25 08:21:49 -07:00
visionmedia a6dd697a68 Added DSL level notFound() route support 2010-03-25 08:13:22 -07:00
visionmedia a4833e7b35 Added specs for Request#notFound() 2010-03-25 07:58:28 -07:00
visionmedia 54fa643c10 More Request#error() specs 2010-03-25 07:54:07 -07:00
visionmedia 6047cd4542 Added specs for Request#error() 2010-03-25 07:51:19 -07:00
visionmedia 8c5f7df280 Merge branch 'errors' 2010-03-25 07:35:44 -07:00
visionmedia ff1250c33c Added publish Request#notFound() 2010-03-25 07:35:39 -07:00
visionmedia 4297c10fe9 Removed Express.error(), Added public Request#error() 2010-03-25 07:18:55 -07:00
visionmedia ab6ad94ec3 Request#halt() accepts callback function as 3rd/4th arg 2010-03-24 16:05:34 -07:00
visionmedia 759183461f Merge branch 'error-handling' 2010-03-24 15:44:50 -07:00
visionmedia f850fa6bc9 Misc error handling improvements 2010-03-24 15:44:46 -07:00
visionmedia 5a242d35b7 Removed unused variable 2010-03-24 15:15:45 -07:00
visionmedia abf5d66e01 Merge branch 'error-handling' 2010-03-24 15:08:51 -07:00
visionmedia e92360e0d4 Caching notFound / showException modules 2010-03-24 15:08:06 -07:00
visionmedia b5c0fdc013 Express.error() now acts as the core exception handler 2010-03-24 14:54:13 -07:00
visionmedia 906ef02c5e request response event is now fired in reverse.
This does a few things:
  a. Allows plugins such as Logger to properly "wrap" all
     other plugins when it is the first passed to use().

  b. Lessons the chance of a plugin failure effecting another plugin
2010-03-24 14:45:46 -07:00
visionmedia 7550decbc0 Handle when a plugin response fails 2010-03-24 14:32:08 -07:00
visionmedia acd88c3c8a next -> callback 2010-03-24 12:56:26 -07:00
visionmedia a3854a2de1 Styling 2010-03-24 12:54:52 -07:00
visionmedia 880aca5d83 Removed set("session cookie") in favour of use(Session, { cookie: { ... }}) 2010-03-24 12:53:33 -07:00
visionmedia 2d1c98a5a7 Docs for stable / edge 2010-03-24 08:33:43 -07:00
visionmedia fefa06ba21 Merge branch 'route-wildcards' 2010-03-23 10:41:31 -07:00
visionmedia 18faa91c94 Added preprocessing of route param wildcards using param(). Closes #251
Async is yet to come
2010-03-23 10:41:25 -07:00
visionmedia 9f23c7b31a Added specs for param() 2010-03-23 10:31:46 -07:00
visionmedia eee6926bab Added more route wildcard specs 2010-03-23 10:11:52 -07:00
visionmedia 6806f952d6 Merge branch 'pre-cache-views' 2010-03-23 09:53:23 -07:00
visionmedia faaef54b42 Pre-caching views in memory. Closes #253
This mirrors the partial caching functionality. This
causes a slight overhead at boot time, however prevents
the need to perform cache checks per render() call.
2010-03-23 09:53:17 -07:00
visionmedia c29852fae7 Started pre caching of views 2010-03-23 09:42:23 -07:00
visionmedia 7d100dae97 Merge branch 'integration' 2010-03-22 15:34:50 -07:00
visionmedia 206e800963 Added assertion to ensure that partials dir is relative to set("views") 2010-03-22 15:34:46 -07:00
visionmedia 555a334315 Re-using variables 2010-03-22 15:33:08 -07:00
visionmedia d2c5def108 Using set("views") when setting set("partials")
So that /partials is always relative by default
2010-03-22 15:31:39 -07:00
visionmedia 98323c530e partialscache -> partials 2010-03-22 15:30:34 -07:00
Aaron Heckmann b36510dbb9 preload partials
add settings
bug fix, partial now works when cache view contents is true
2010-03-22 18:16:40 -04:00
Aaron Heckmann 50e533c32b add cache view partials 2010-03-22 16:40:35 -04:00
visionmedia 33277c3d37 Removed utils.mixin() use Object#mergeDeep()
jQuery is messy, and this implementation is way to
slow for SSJS, and just gross :)
2010-03-22 11:28:23 -07:00
visionmedia 28f2ad0109 Merge branch 'partials' 2010-03-22 10:21:42 -07:00
visionmedia 5d10ee4e61 Chat sample app using partials as an example 2010-03-22 10:21:37 -07:00
visionmedia b4190ada0c Added partial "as" option 2010-03-22 10:16:12 -07:00
visionmedia 60d314552d Partial collection should not introduce newlines 2010-03-22 10:13:25 -07:00
visionmedia c971d54543 Added partial collection support 2010-03-22 10:12:52 -07:00
visionmedia 346f019fa8 Started view partial support 2010-03-22 10:05:05 -07:00
visionmedia d61c2480b6 Updated ext submodule 2010-03-22 09:12:24 -07:00
visionmedia e30b5b86da Removed Request#_blendInNodeRequest() 2010-03-22 09:12:09 -07:00
visionmedia bd74fe24fd Merge branch 'net2_fixes' of git://github.com/ciaranj/express 2010-03-22 09:05:58 -07:00
visionmedia b30eaa8ee3 Updated support to v0.1.33 2010-03-22 08:34:05 -07:00
ciaranj 75c530516a Various minor fixes required to make express work post the net2 merge branch 2010-03-20 12:26:37 +00:00
visionmedia 3b49821e82 Release 0.8.0 2010-03-19 16:51:43 -07:00
visionmedia febf443960 Fixed session reaper 2010-03-19 15:57:25 -07:00
visionmedia f5da81e782 Removed a comment from chat app 2010-03-19 14:38:26 -07:00
visionmedia 9cb23ac584 Merge branch 'coffee' 2010-03-19 14:14:52 -07:00
visionmedia 6ff3100c1f Added coffeescript example app. Closes #242 2010-03-19 14:14:46 -07:00
visionmedia e3ea3723bf Added dir for coffeescript example 2010-03-19 13:56:31 -07:00
visionmedia 33443d9b41 Merge branch 'integration' 2010-03-19 10:13:26 -07:00
visionmedia e0ef61659f Merge branch 'async-session' into integration 2010-03-19 10:12:56 -07:00
visionmedia 655ad77bce fn -> callback 2010-03-19 09:55:06 -07:00
visionmedia c09e546240 Removed session reaper try/catch
we can revisit this issue later,
and deal with it across Cache as well
2010-03-19 09:53:33 -07:00
visionmedia a08b14a89e Misc Session refactoring 2010-03-19 09:52:18 -07:00
visionmedia 12e90b0eef Merge branch 'session_with_callbacks' of git://github.com/ciaranj/express into async-session 2010-03-19 09:41:30 -07:00
visionmedia 7606f1bcbd Merge branch 'async-cache' 2010-03-19 09:38:47 -07:00
visionmedia cabb43b187 Finished converting async cache api. Closes #240 2010-03-19 09:38:42 -07:00
visionmedia b85cda3f6e Cache api is now async 2010-03-19 09:19:22 -07:00
visionmedia b92f1b7497 Async cache specs 2010-03-19 09:04:31 -07:00
visionmedia 273a51a335 Release 0.7.6 2010-03-19 08:55:52 -07:00
ciaranj 212dc88b89 Squashed commit of the changes I've put in place to support callback
methods on the session object.

This code changes the behaviour of the session handling in a fairly key
way:

If an unknown session id is seen then a *new* session is created with a *new* session
id.  The previous behaviour was to create a new session with the existing id.
2010-03-19 13:55:51 +00:00
visionmedia ce82a91d14 Revert "Fail to test CI"
This reverts commit 52a08401c7.
2010-03-18 16:20:53 -07:00
visionmedia 52a08401c7 Fail to test CI 2010-03-18 16:20:12 -07:00
visionmedia 706c0cb033 View support listed in features already 2010-03-18 16:19:39 -07:00
visionmedia 1567a613a6 Closes #63.
Merge branch 'cli'
2010-03-18 13:02:00 -07:00
visionmedia d767d80d20 Added make install 2010-03-18 13:01:28 -07:00
visionmedia 1103a9d510 Moved a helper function to the helpers section 2010-03-18 13:00:34 -07:00
visionmedia c34af4b97a Started executable 2010-03-18 12:57:44 -07:00
visionmedia 8dcee4d338 Request#render() only calls cache.get() once 2010-03-18 11:40:48 -07:00
visionmedia fc1e69ea73 Namespacing View caches with "view:" 2010-03-18 11:40:04 -07:00
visionmedia db460117c1 Namespacing Static caches with "static:" 2010-03-18 11:39:23 -07:00
visionmedia 1c514df0fd Fixed ternary style 2010-03-18 11:37:34 -07:00
visionmedia 780ec5cbec Docs 2010-03-18 11:27:15 -07:00
visionmedia 3721873b62 Both example apps now use Static 2010-03-18 11:23:07 -07:00
visionmedia 3bdc77ca91 Deprecated Request#sendfile() and express/static 2010-03-18 11:22:40 -07:00
visionmedia b8f54d64a4 Closes #88.
Merge branch 'runtime-routes'
2010-03-18 11:17:16 -07:00
visionmedia 90d48b320a Added "GET /public/*" to Static plugin, defaulting to <root>/public 2010-03-18 11:16:55 -07:00
visionmedia a797342800 Static is now a plugin 2010-03-18 11:09:25 -07:00
visionmedia 31e608e0ae Added Request#sendfile() specs 2010-03-18 10:58:50 -07:00
visionmedia ebcfb0e577 Removed Server#running 2010-03-18 10:31:40 -07:00
visionmedia 161c9f9142 Closes #52
fs.readFile becomes fs.readFileSync when testing

Merge branch 'view-specs'
2010-03-18 10:17:03 -07:00
visionmedia 2a099da726 Fixed a few specs 2010-03-18 10:16:14 -07:00
visionmedia 5118397004 Added auto content-type view spec 2010-03-18 10:14:10 -07:00
visionmedia 546c340656 Added view custom context spec 2010-03-18 10:12:20 -07:00
visionmedia 3034cc7c52 View context spec 2010-03-18 10:10:10 -07:00
visionmedia d89381ff78 Added layout local var access spec 2010-03-18 10:04:25 -07:00
visionmedia 86cac58100 Added view locals spec 2010-03-18 09:54:29 -07:00
visionmedia 8fc062007e Added spec for invalid view engine 2010-03-18 09:51:48 -07:00
visionmedia 9fd92e3306 Added view caching specs 2010-03-18 09:50:16 -07:00
visionmedia a4cbbe5dd4 Spec for layout: false 2010-03-18 09:36:57 -07:00
visionmedia da7ea9655f Spec for custom layout 2010-03-18 09:36:12 -07:00
visionmedia 00a8c642dd Started view specs 2010-03-18 09:32:32 -07:00
visionmedia e1152f6e56 Typo 2010-03-18 09:12:46 -07:00
visionmedia 7cf9c6842a Merge branch 'fix-views' 2010-03-18 09:08:06 -07:00
visionmedia d375535cd9 Fixed set("views"). Closes #239
This actually should have never worked (if it even did).
My bad :)
2010-03-18 09:08:02 -07:00
visionmedia c5ea868f47 Merge branch 'bugfix' of git://github.com/aheckmann/express 2010-03-18 08:02:23 -07:00
visionmedia 884d333805 Added Request#isXHR. Closes #229
Merge branch 'integration'
2010-03-18 07:55:30 -07:00
visionmedia 3b9921a15b Added Request#isXHR specs 2010-03-18 07:54:34 -07:00
Aaron Heckmann 17b753d95e add missing space to combined log format 2010-03-17 22:38:45 -04:00
Aaron Heckmann 6a8781b5e2 add request.isXHR 2010-03-17 22:16:13 -04:00
Aaron Heckmann 0dfaf01749 add git clone to git command 2010-03-17 21:40:13 -04:00
visionmedia 088aa83e22 Updated feature list 2010-03-17 16:07:53 -07:00
visionmedia 934adb1e9f Release 0.7.5 2010-03-16 19:38:21 -07:00
visionmedia 50e0593de6 Request#flash() without args now returns all flashes 2010-03-16 19:34:11 -07:00
visionmedia f2637c6421 Fixed Request#flash() specs 2010-03-16 19:22:10 -07:00
visionmedia a52dacea68 Updated ext 2010-03-16 19:12:15 -07:00
visionmedia f56a33d22d Release 0.7.4 2010-03-16 16:14:48 -07:00
visionmedia 2aa858b0fb Merge branch 'class' 2010-03-16 16:12:42 -07:00
visionmedia c3b8ba4b9a NewClass -> Class, removed js-oo dependency 2010-03-16 16:12:14 -07:00
visionmedia ac96b8c0e1 Update class.js submodule with Class#include() 2010-03-16 16:10:39 -07:00
visionmedia a329a9f4d8 Converted more to use class.js 2010-03-16 15:53:32 -07:00
visionmedia 63cc7eb44d Converted more to use class.js 2010-03-16 15:50:17 -07:00
visionmedia 6505f32221 Started conversion of js-oo Class -> class.js 2010-03-16 15:46:22 -07:00
visionmedia 22088260f4 Fixed session reaper 2010-03-16 13:25:39 -07:00
visionmedia d893009a8d Release 0.7.3 2010-03-16 13:17:41 -07:00
visionmedia b62e1741be Fixed requiring of haml / sass 2010-03-16 13:16:55 -07:00
visionmedia 903c2aa642 Added package.json 2010-03-16 08:31:33 -07:00
visionmedia d0a8bb550e Release 0.7.2 2010-03-16 08:08:17 -07:00
visionmedia f96f1423e1 Fixed GIT submodules (HAH!) 2010-03-16 08:06:26 -07:00
visionmedia 7bf17f2f61 Removed old support dir 2010-03-16 08:03:57 -07:00
visionmedia 670b6cfc15 Merge branch 'remove-kiwi' 2010-03-16 08:03:33 -07:00
visionmedia b6d2c8479c Release 0.7.1 2010-03-16 08:03:06 -07:00
visionmedia 5aaa114271 Docs 2010-03-16 08:01:51 -07:00
visionmedia e99c2791bb Docs 2010-03-16 07:58:06 -07:00
visionmedia 656d7754cd Express now using submodules again until a PM is adopted 2010-03-16 07:54:20 -07:00
visionmedia 4aaf10fbfc Moved support 2010-03-16 07:39:56 -07:00
visionmedia 85e77b77aa Added submodules 2010-03-16 07:02:49 -07:00
visionmedia f23ef09247 Chat example using millisecond conversions from ext 2010-03-15 16:00:39 -07:00
visionmedia 440d956438 Refactored Session#startReaper() with ext millisecond conversions 2010-03-15 15:59:37 -07:00
visionmedia acd2852cf3 ext >= 0.2.4 2010-03-15 15:58:02 -07:00
visionmedia 4246f43bdf ext >= 0.2.3 2010-03-15 09:57:38 -07:00
visionmedia 7d33769cd2 Revert "Removed sass / haml "dependencies""
This reverts commit 31fdba80d4.
2010-03-15 09:43:29 -07:00
visionmedia 31fdba80d4 Removed sass / haml "dependencies" 2010-03-15 09:42:15 -07:00
visionmedia 77f8e460d0 Better example app 2010-03-15 09:31:11 -07:00
visionmedia 51e51db9f7 Docs 2010-03-15 09:16:13 -07:00
visionmedia 73c506f19c Release 0.7.0 2010-03-15 09:13:18 -07:00
visionmedia 79143f3334 Chat sample app using pass() 2010-03-15 09:10:50 -07:00
visionmedia 128ba9040e Refactored Router#matchingRoute() 2010-03-15 09:09:51 -07:00
visionmedia 300cfe74ad Request#pass() accepts a pathname string 2010-03-15 09:02:44 -07:00
visionmedia f008af05bd Merge branch 'pull' 2010-03-15 08:54:57 -07:00
Aaron Heckmann 3aa870d6bd return this in pass 2010-03-15 08:50:35 -07:00
Aaron Heckmann 25e1a8c001 add pass specs 2010-03-15 08:50:26 -07:00
Aaron Heckmann 0ba3b114b0 add pass support 2010-03-15 08:50:20 -07:00
visionmedia c429e88e8e Updated --version of node tested against in readme 2010-03-15 08:42:22 -07:00
Aaron Heckmann c7a2fe8440 remove profiler from plugins.js 2010-03-15 08:41:21 -07:00
Aaron Heckmann de237e760b remove Profiler 2010-03-15 08:41:03 -07:00
visionmedia 927f5c9883 Logger copyright 2010-03-12 07:36:50 -08:00
visionmedia 88f461baf2 Logger using Date#format() 2010-03-12 07:14:57 -08:00
visionmedia 3251ae26a0 Fixed plot format 2010-03-12 07:09:56 -08:00
visionmedia e84c81633e "combined" using printf() 2010-03-12 07:09:20 -08:00
visionmedia a2ec966ac7 "common" Logger format using printf() 2010-03-12 07:06:47 -08:00
visionmedia 69660fbfda Merge branch 'integration' 2010-03-12 06:58:34 -08:00
visionmedia dcedca1a80 Removed 'sinatra' logger, added duration to 'common' log format 2010-03-12 06:58:23 -08:00
visionmedia 6455e954fc Removed CommonLogger, use Logger 2010-03-12 06:53:17 -08:00
visionmedia 646904688f No need for utils.mixin() here 2010-03-11 11:16:48 -08:00
visionmedia 62779fc972 Doc typo 2010-03-11 11:14:33 -08:00
visionmedia fdee4cde26 Sample app in readme 2010-03-11 11:14:02 -08:00
visionmedia 0c18ac5adc Added kiwi installation docs 2010-03-11 11:05:41 -08:00
visionmedia 6da4a942ca Managing dependencies with the kiwi package manager. Closes #228
Merge branch 'kiwi'
2010-03-11 11:01:54 -08:00
visionmedia 565f68d2d7 Added kiwi.seed() calls to make them available via require()
This is needed since the view plugin uses
the regular require() and not kiwi.require()
2010-03-11 11:00:47 -08:00
visionmedia a7cee4c889 Removed references to submodules 2010-03-11 10:57:26 -08:00
visionmedia 4f315f9b11 Added haml / sass dependencies 2010-03-11 10:46:08 -08:00
visionmedia 51febfec2d Actually added seed.yml :) 2010-03-10 19:23:56 -08:00
visionmedia df8bd96b2e Added support for arbitrary view engines 2010-03-10 19:23:56 -08:00
visionmedia 9da9beb342 Added seed.yml for kiwi package management support 2010-03-10 19:23:56 -08:00
visionmedia f93af823df Fixed typo 2010-03-10 19:23:51 -08:00
Aaron Heckmann 5e74723a92 add logger 2010-03-10 22:09:07 -05:00
visionmedia ec77e1acea HTTP client appends query string when method is GET. Closes #205 2010-03-10 19:01:40 -08:00
visionmedia 1afad64972 Misc refactoring to http client 2010-03-10 18:53:12 -08:00
visionmedia a3365dda07 Removed usage of RESTful route funcs as http client 2010-03-10 18:49:04 -08:00
visionmedia 4c246a4cd1 Merge branch 'async-plugins' 2010-03-10 18:34:09 -08:00
visionmedia 934ffd0731 Fixed params in show-exception page 2010-03-10 18:32:25 -08:00
visionmedia 790e2c233d Inverted plugin async support. Return true WHEN async 2010-03-10 17:06:46 -08:00
visionmedia 9e9967381c Misc refactoring 2010-03-10 17:01:40 -08:00
visionmedia 891ed08827 Request#trigger() now supports callback as 2nd or 3rd arg 2010-03-10 17:01:08 -08:00
visionmedia 55d13a6f08 Doc typo 2010-03-10 16:58:53 -08:00
visionmedia 5569ea4397 Removed custom exceptions
because they are lame
2010-03-10 16:57:51 -08:00
visionmedia 693e37459a Removed InvalidResponseBody / InvalidStatusCode
stupid anyway, just dont fuck shit up :)
2010-03-10 16:46:47 -08:00
visionmedia 90de1fa55d Refactoring routing slightly 2010-03-10 16:34:21 -08:00
visionmedia 6d6e1557ce Refactored Request#trigger() 2010-03-10 16:26:20 -08:00
visionmedia 2d84f16dc0 Hooks do not support async at the moment anyway, return true 2010-03-10 16:14:54 -08:00
visionmedia 2f98ef9f6d Strict comparisons 2010-03-10 16:12:16 -08:00
visionmedia e0c07d2385 Fixed typo 2010-03-10 16:11:38 -08:00
ciaranj 0b2413d8c0 Missed a curly brace out 2010-03-10 23:52:31 +00:00
ciaranj e92b01f813 Change the approach to be truth based
Now just enforces that a plugin returns true, if it doesn't return true then
we assume the plugin is taking care of making sure that the plugin chain continues.

A sensible enhancement to this might be to improve the request.trigger function to timeout
after a fixed period, log a warning, then carry on as normal ??

I'm not too sure of what 'Hooks.js' does so I may haveconfigured that incorrectly, just FYI
2010-03-10 23:49:38 +00:00
ciaranj 27ff13459f Merge branch 'master' of git://github.com/visionmedia/express into async_plugins
Conflicts:
	lib/express/plugins/cookie.js
	lib/express/plugins/hooks.js
	lib/express/request.js
2010-03-10 23:36:18 +00:00
ciaranj 3e80915454 Oops, still had some proto code in there 2010-03-10 23:23:37 +00:00
ciaranj 4063d2e2c4 Initial stab at async plugin execution 2010-03-10 23:16:31 +00:00
visionmedia ce9416857b Renamed params -> keys now that ext.js is fixed 2010-03-10 13:39:49 -08:00
visionmedia 575d5e8e57 Updated ext.js. Closes #227 2010-03-10 13:38:07 -08:00
visionmedia 14ceb8c046 Release 0.5.0 2010-03-10 13:17:57 -08:00
visionmedia c6c29ca505 Styling 2010-03-10 13:07:04 -08:00
visionmedia c551226504 More refactoring 2010-03-10 13:06:10 -08:00
visionmedia fcbc09543c More refactoring 2010-03-10 13:04:12 -08:00
visionmedia 6d83bb0026 Misc refactoring 2010-03-10 13:00:43 -08:00
visionmedia 0784a513c9 configure() using each() 2010-03-10 12:48:48 -08:00
visionmedia ebcdec0860 Misc refactoring 2010-03-10 12:43:40 -08:00
visionmedia 6805e4f28f Kinda updated feature list a bit 2010-03-10 12:30:50 -08:00
visionmedia 962f5fa412 Removed extname() / basename() utils. Using path module 2010-03-10 12:27:49 -08:00
visionmedia 1385988ab8 Better escape() util 2010-03-10 12:24:08 -08:00
visionmedia 6cc80f8c54 Removed toArray() util. use arguments.values 2010-03-10 12:23:45 -08:00
visionmedia d6c843962d Removed escapeRegexp() util 2010-03-10 12:22:25 -08:00
visionmedia 247e6ad9ab Removed process.mixin() dependency 2010-03-10 12:17:10 -08:00
visionmedia 364c131a4e Merge branch 'ext' 2010-03-10 12:04:38 -08:00
visionmedia b047325033 Updated ext and removed Collection 2010-03-10 12:03:26 -08:00
visionmedia 0894cfe058 Removed more Collection usage 2010-03-10 11:21:29 -08:00
visionmedia f4a9d7e70b Removed more Collection usage 2010-03-10 11:18:14 -08:00
visionmedia 593634fb5d Started removing usage of Collection 2010-03-10 11:16:26 -08:00
visionmedia 2932bf5006 make test / make init distinction 2010-03-10 11:12:12 -08:00
visionmedia 4b1c39fe41 Removed Collection specs 2010-03-10 11:10:12 -08:00
visionmedia ee91e3a139 Started removal of Collection 2010-03-10 11:08:20 -08:00
visionmedia e287b854a2 Added ext.js submodule 2010-03-09 08:31:17 -08:00
visionmedia 5458e5dd00 Misc refactoring 2010-03-09 08:07:55 -08:00
visionmedia ed30f37ca9 Fixing some comments 2010-03-09 08:02:44 -08:00
visionmedia 9e495f6bb8 Misc refactoring to multi-part handling 2010-03-09 07:57:57 -08:00
Aaron Heckmann 21566c49f0 update node version in readme
push the stream.part bugfix from previous commit
2010-03-09 07:54:50 -08:00
Aaron Heckmann 0a225c13a4 refactor run callback
add Server.error
fix bug in run callback (accepts not defined)
fix bug in stream.body event (part is undefined)
2010-03-09 07:54:46 -08:00
Aaron Heckmann 680c07a030 ensure uploaded files close before routing 2010-03-09 07:54:41 -08:00
visionmedia 8ee66dca22 Updated HTTP client. Closes #221
Merge branch 'update-http-client'
2010-03-08 18:43:38 -08:00
visionmedia 60393f07ef Removed debugging data 2010-03-08 18:43:05 -08:00
visionmedia 34418b03fb HTTP client is resolving callback function amoung other args 2010-03-08 18:42:28 -08:00
visionmedia ce2f161f08 Implemented max redirects option for http client. Closes #204 2010-03-08 18:33:23 -08:00
visionmedia d5ca1ea152 Started fixing HTTP client 2010-03-08 18:08:09 -08:00
visionmedia c3fec8225a Removed http client allowData 2010-03-08 17:51:32 -08:00
visionmedia bfff00826e Styling 2010-03-08 17:11:16 -08:00
visionmedia 61cb50b2bd Styling 2010-03-08 17:09:36 -08:00
visionmedia c8d3bfabc7 Styling 2010-03-08 17:01:35 -08:00
visionmedia 1ce212d33d Styling 2010-03-08 17:00:56 -08:00
visionmedia 3682f4f06a Styling 2010-03-08 16:57:49 -08:00
visionmedia 0f74408b0e Styling 2010-03-08 16:56:31 -08:00
visionmedia f7d7c4a8e0 Merge branch 'node-0.1.30' 2010-03-08 16:42:41 -08:00
visionmedia 0cb8d12796 Removed ElementCollection support
this will become another library
2010-03-08 16:40:23 -08:00
ciaranj 9586ecfd58 Multipart form-data / File uploading now works again
Haven't re-implemented a timeout, wasn't sure what behaviour was wanted here...should
be easy enough to do, wish I could get local tests working again :(
2010-03-09 00:13:00 +00:00
ciaranj 86217867f9 Now working on node 0.1.30 but using custom mixin 2010-03-08 22:00:09 +00:00
Aaron Heckmann 496de51a11 Common log client address instead of server address 2010-03-05 07:38:08 -08:00
visionmedia 38591d06a0 Deep copy request 2010-03-05 07:32:57 -08:00
visionmedia 91805f7da4 Shameless self promotion of ebook 2010-02-22 14:48:43 -08:00
visionmedia 7bd8340a8b Fixed Collection#clone() 2010-02-22 13:30:46 -08:00
visionmedia 4817007097 Re-throwing errors 2010-02-22 13:26:35 -08:00
visionmedia d5003feb39 Fixed mocks to match node api 2010-02-22 08:08:51 -08:00
visionmedia f03e460ca5 Started converting fs module 2010-02-22 08:05:13 -08:00
visionmedia 347c8847b0 Removed addErrback() from render()
throws with latest node
2010-02-12 10:36:23 -08:00
visionmedia 9f48b32329 Benchmarks link 2010-02-12 09:34:40 -08:00
visionmedia 2f6dfbc165 Release 0.4.0 2010-02-11 17:02:30 -08:00
visionmedia 49cb53d735 Merge branch 'route-http-client-security' 2010-02-11 16:36:47 -08:00
visionmedia 54f1a51a10 Throwing error when routes are added at runtime
Since it doubles as an http client, without this
someone could arbitrarily create routes.. haha not good!
2010-02-11 16:36:38 -08:00
visionmedia c6a2674c2b Merge branch 'http' 2010-02-11 16:15:42 -08:00
visionmedia 282a10ec83 RESTful route functions double as HTTP clients. Closes #69
For example:
  get("http://google.com").addCallback(function(content){
    puts(content)
  })
2010-02-11 16:15:37 -08:00
visionmedia 50276a06df Merge branch 'http-client' 2010-02-11 16:11:00 -08:00
visionmedia f452250f88 Added high level restful http client 2010-02-11 16:10:43 -08:00
visionmedia 9d44e237a5 Added status code string to error 2010-02-11 15:30:16 -08:00
visionmedia 9f0e5899c2 Fixed Host header issue 2010-02-11 15:11:06 -08:00
visionmedia e351a02a06 Merge branch 'flash' 2010-02-11 14:22:59 -08:00
visionmedia cd167ec777 Added flash() example to sample upload app 2010-02-11 14:22:55 -08:00
visionmedia 3290412477 Updated haml 2010-02-11 14:02:26 -08:00
visionmedia acf0128fb4 Merge branch 'view-context' 2010-02-11 13:57:33 -08:00
visionmedia e91ee22a89 Defaulting render() context to the current Request. Closes #197 2010-02-11 13:57:26 -08:00
visionmedia 8e91d2039a Started high level HTTP api 2010-02-05 15:16:48 -08:00
174 arquivos alterados com 8062 adições e 8744 exclusões
+8
Ver Arquivo
@@ -1 +1,9 @@
.DS_Store
lib-cov
*.seed
*.log
*.csv
*.dat
*.out
*.pid
benchmarks/graphs
+18 -12
Ver Arquivo
@@ -1,12 +1,18 @@
[submodule "spec/support/libxmljs"]
path = spec/support/libxmljs
url = git://github.com/sprsquish/libxmljs.git
[submodule "lib/support/haml"]
path = lib/support/haml
url = git://github.com/creationix/haml-js.git
[submodule "lib/support/js-oo"]
path = lib/support/js-oo
url = git://github.com/visionmedia/js-oo.git
[submodule "lib/support/sass"]
path = lib/support/sass
url = git://github.com/visionmedia/sass.js.git
[submodule "support/expresso"]
path = support/expresso
url = git://github.com/visionmedia/expresso.git
[submodule "support/jade"]
path = support/jade
url = git://github.com/visionmedia/jade.git
[submodule "support/haml"]
path = support/haml
url = git://github.com/visionmedia/haml.js.git
[submodule "support/ejs"]
path = support/ejs
url = http://github.com/visionmedia/ejs.git
[submodule "support/connect-form"]
path = support/connect-form
url = http://github.com/visionmedia/connect-form.git
[submodule "support/connect"]
path = support/connect
url = http://github.com/senchalabs/connect.git
+21
Ver Arquivo
@@ -0,0 +1,21 @@
---
- !ruby/object:Pomo::Task
complete: false
description:
length: 25
name: TM bundle
- !ruby/object:Pomo::Task
complete: false
description:
length: 25
name: blog
- !ruby/object:Pomo::Task
complete: false
description:
length: 25
name: release on nodejs group
- !ruby/object:Pomo::Task
complete: false
description:
length: 25
name: Beta
+217
Ver Arquivo
@@ -1,4 +1,221 @@
1.0.0beta / 2010-07-15
==================
* Re-write
- much faster
- much lighter
- Check [ExpressJS.com](http://expressjs.com) for migration guide and updated docs
0.14.0 / 2010-06-15
==================
* Utilize relative requires
* Added Static bufferSize option [aheckmann]
* Fixed caching of view and partial subdirectories [aheckmann]
* Fixed mime.type() comments now that ".ext" is not supported
* Updated haml submodule
* Updated class submodule
* Removed bin/express
0.13.0 / 2010-06-01
==================
* Added node v0.1.97 compatibility
* Added support for deleting cookies via Request#cookie('key', null)
* Updated haml submodule
* Fixed not-found page, now using using charset utf-8
* Fixed show-exceptions page, now using using charset utf-8
* Fixed view support due to fs.readFile Buffers
* Changed; mime.type() no longer accepts ".type" due to node extname() changes
0.12.0 / 2010-05-22
==================
* Added node v0.1.96 compatibility
* Added view `helpers` export which act as additional local variables
* Updated haml submodule
* Changed ETag; removed inode, modified time only
* Fixed LF to CRLF for setting multiple cookies
* Fixed cookie complation; values are now urlencoded
* Fixed cookies parsing; accepts quoted values and url escaped cookies
0.11.0 / 2010-05-06
==================
* Added support for layouts using different engines
- this.render('page.html.haml', { layout: 'super-cool-layout.html.ejs' })
- this.render('page.html.haml', { layout: 'foo' }) // assumes 'foo.html.haml'
- this.render('page.html.haml', { layout: false }) // no layout
* Updated ext submodule
* Updated haml submodule
* Fixed EJS partial support by passing along the context. Issue #307
0.10.1 / 2010-05-03
==================
* Fixed binary uploads.
0.10.0 / 2010-04-30
==================
* Added charset support via Request#charset (automatically assigned to 'UTF-8' when respond()'s
encoding is set to 'utf8' or 'utf-8'.
* Added "encoding" option to Request#render(). Closes #299
* Added "dump exceptions" setting, which is enabled by default.
* Added simple ejs template engine support
* Added error reponse support for text/plain, application/json. Closes #297
* Added callback function param to Request#error()
* Added Request#sendHead()
* Added Request#stream()
* Added support for Request#respond(304, null) for empty response bodies
* Added ETag support to Request#sendfile()
* Added options to Request#sendfile(), passed to fs.createReadStream()
* Added filename arg to Request#download()
* Performance enhanced due to pre-reversing plugins so that plugins.reverse() is not called on each request
* Performance enhanced by preventing several calls to toLowerCase() in Router#match()
* Changed; Request#sendfile() now streams
* Changed; Renamed Request#halt() to Request#respond(). Closes #289
* Changed; Using sys.inspect() instead of JSON.encode() for error output
* Changed; run() returns the http.Server instance. Closes #298
* Changed; Defaulting Server#host to null (INADDR_ANY)
* Changed; Logger "common" format scale of 0.4f
* Removed Logger "request" format
* Fixed; Catching ENOENT in view caching, preventing error when "views/partials" is not found
* Fixed several issues with http client
* Fixed Logger Content-Length output
* Fixed bug preventing Opera from retaining the generated session id. Closes #292
0.9.0 / 2010-04-14
==================
* Added DSL level error() route support
* Added DSL level notFound() route support
* Added Request#error()
* Added Request#notFound()
* Added Request#render() callback function. Closes #258
* Added "max upload size" setting
* Added "magic" variables to collection partials (\_\_index\_\_, \_\_length\_\_, \_\_isFirst\_\_, \_\_isLast\_\_). Closes #254
* Added [haml.js](http://github.com/visionmedia/haml.js) submodule; removed haml-js
* Added callback function support to Request#halt() as 3rd/4th arg
* Added preprocessing of route param wildcards using param(). Closes #251
* Added view partial support (with collections etc)
* Fixed bug preventing falsey params (such as ?page=0). Closes #286
* Fixed setting of multiple cookies. Closes #199
* Changed; view naming convention is now NAME.TYPE.ENGINE (for example page.html.haml)
* Changed; session cookie is now httpOnly
* Changed; Request is no longer global
* Changed; Event is no longer global
* Changed; "sys" module is no longer global
* Changed; moved Request#download to Static plugin where it belongs
* Changed; Request instance created before body parsing. Closes #262
* Changed; Pre-caching views in memory when "cache view contents" is enabled. Closes #253
* Changed; Pre-caching view partials in memory when "cache view partials" is enabled
* Updated support to node --version 0.1.90
* Updated dependencies
* Removed set("session cookie") in favour of use(Session, { cookie: { ... }})
* Removed utils.mixin(); use Object#mergeDeep()
0.8.0 / 2010-03-19
==================
* Added coffeescript example app. Closes #242
* Changed; cache api now async friendly. Closes #240
* Removed deprecated 'express/static' support. Use 'express/plugins/static'
0.7.6 / 2010-03-19
==================
* Added Request#isXHR. Closes #229
* Added `make install` (for the executable)
* Added `express` executable for setting up simple app templates
* Added "GET /public/*" to Static plugin, defaulting to <root>/public
* Added Static plugin
* Fixed; Request#render() only calls cache.get() once
* Fixed; Namespacing View caches with "view:"
* Fixed; Namespacing Static caches with "static:"
* Fixed; Both example apps now use the Static plugin
* Fixed set("views"). Closes #239
* Fixed missing space for combined log format
* Deprecated Request#sendfile() and 'express/static'
* Removed Server#running
0.7.5 / 2010-03-16
==================
* Added Request#flash() support without args, now returns all flashes
* Updated ext submodule
0.7.4 / 2010-03-16
==================
* Fixed session reaper
* Changed; class.js replacing js-oo Class implementation (quite a bit faster, no browser cruft)
0.7.3 / 2010-03-16
==================
* Added package.json
* Fixed requiring of haml / sass due to kiwi removal
0.7.2 / 2010-03-16
==================
* Fixed GIT submodules (HAH!)
0.7.1 / 2010-03-16
==================
* Changed; Express now using submodules again until a PM is adopted
* Changed; chat example using millisecond conversions from ext
0.7.0 / 2010-03-15
==================
* Added Request#pass() support (finds the next matching route, or the given path)
* Added Logger plugin (default "common" format replaces CommonLogger)
* Removed Profiler plugin
* Removed CommonLogger plugin
0.6.0 / 2010-03-11
==================
* Added seed.yml for kiwi package management support
* Added HTTP client query string support when method is GET. Closes #205
* Added support for arbitrary view engines.
For example "foo.engine.html" will now require('engine'),
the exports from this module are cached after the first require().
* Added async plugin support
* Removed usage of RESTful route funcs as http client
get() etc, use http.get() and friends
* Removed custom exceptions
0.5.0 / 2010-03-10
==================
* Added ext dependency (library of js extensions)
* Removed extname() / basename() utils. Use path module
* Removed toArray() util. Use arguments.values
* Removed escapeRegexp() util. Use RegExp.escape()
* Removed process.mixin() dependency. Use utils.mixin()
* Removed Collection
* Removed ElementCollection
* Shameless self promotion of ebook "Advanced JavaScript" (http://dev-mag.com) ;)
0.4.0 / 2010-02-11
==================
* Added flash() example to sample upload app
* Added high level restful http client module (express/http)
* Changed; RESTful route functions double as HTTP clients. Closes #69
* Changed; throwing error when routes are added at runtime
* Changed; defaulting render() context to the current Request. Closes #197
* Updated haml submodule
0.3.0 / 2010-02-11
==================
+68 -29
Ver Arquivo
@@ -1,33 +1,72 @@
NODE = node
PREFIX = /usr/local
LIB_PREFIX = ~/.node_libraries
all: test
DOCS = docs/index.md \
docs/executable.md \
docs/contrib.md \
docs/guide.md \
docs/migrate.md
init:
@git submodule init && git submodule update
MANPAGES =$(DOCS:.md=.1)
HTMLDOCS =$(DOCS:.md=.html)
test: init spec/support/libxmljs/libxmljs.node
@$(NODE) spec/node.js all
test-independant: init
@$(NODE) spec/node.js independant
test-dependant: init spec/support/libxmljs/libxmljs.node
@$(NODE) spec/node.js dependant
app: app-chat
app-chat:
@$(NODE) examples/chat/app.js
app-upload:
@$(NODE) examples/upload/app.js
benchmark:
@$(NODE) benchmarks/collection.js
@$(NODE) benchmarks/views.js
spec/support/libxmljs/libxmljs.node:
@scons -C spec/support/libxmljs libxmljs.node
.PHONY: init test benchmark app
install: install-docs
@mkdir -p $(PREFIX)/bin
cp -f bin/express $(PREFIX)/bin/express
cp -fr lib/express $(LIB_PREFIX)/express
uninstall: uninstall-docs
rm -f $(PREFIX)/bin/express
rm -fr $(LIB_PREFIX)/express
install-support:
cd support/connect && $(MAKE) install
cd support/jade && $(MAKE) install
uninstall-support:
cd support/connect && $(MAKE) uninstall
cd support/jade && $(MAKE) uninstall
install-docs:
cp -f docs/executable.1 $(PREFIX)/share/man/man1/express.1
uninstall-docs:
rm -f $(PREFIX)/share/man/man1/express.1
test:
@CONNECT_ENV=test ./support/expresso/bin/expresso \
-I lib \
-I support/connect/lib \
-I support/haml/lib \
-I support/jade/lib \
-I support/ejs/lib \
$(TESTFLAGS) \
test/*.test.js
test-cov:
@TESTFLAGS=--cov $(MAKE) test
docs: docs/api.html $(MANPAGES) $(HTMLDOCS)
@ echo "... generating TOC"
@./support/toc.js docs/guide.html
docs/api.html: lib/express/*.js
dox --title Express \
--desc "High performance web framework for [node](http://nodejs.org)." \
$(shell find lib/express/* -type f) > $@
%.1: %.md
@echo "... $< -> $@"
@ronn -r --pipe $< > $@
%.html: %.md
@echo "... $< -> $@"
@ronn -5 --pipe --fragment $< \
| cat docs/layout/head.html - docs/layout/foot.html \
| sed 's/NAME/Express/g' \
> $@
docclean:
rm -f docs/*.{1,html}
.PHONY: install uninstall install-docs install-support uninstall-support install-docs uninstall-docs test test-cov docs docclean
+62 -101
Ver Arquivo
@@ -2,128 +2,89 @@
# Express
Insanely fast (and small) server-side JavaScript web development framework
built on **node.js** and the **V8 JavaScript engine**.
* Visit the [Wiki](http://wiki.github.com/visionmedia/express) for documentation
* Visit the [Google Group](http://groups.google.com/group/express-js) for discussion
## Features (so far)
* Sexy DSL with robust sinatra-like routing
* High performance
* Session support
* Mime helpers
* Redirection helpers
* Nested parameter parsing
* Full test coverage
* Extremely readable specs
* Test helpers (mock requests etc)
* Environment based configuration
* Light-weight JavaScript class implementation via js-oo
* Collections and chainable iterators
* ElementCollections / markup parsing via libxmljs and css selector traversal support via css2xpath
* View support (ejs, haml, sass, etc)
built on [node](http://nodejs.org) and [Connect](http://github.com/extjs/Connect).
var app = express.createServer();
app.get('/', function(req, res){
res.send('Hello World');
});
app.listen(3000);
## Installation
Currently Express must be cloned (or downloaded), you can use the following command to
get rolling and initialize the submodule dependencies:
npm:
$ git clone git://github.com/visionmedia/express.git && cd express && git submodule update --init && make app
Or with the [gh](http://github.com/visionmedia/gh) utility:
$ npm install connect
$ npm install express
$ gh clone visionmedia express && cd express && git submodule update --init && make app
curl (or similar):
## Performance
$ curl -# http://github.com/visionmedia/express/raw/master/install.sh | sh
Extensive benchmarking will wait until a development version
has been released.
Currently Express can chew through a request with a two Haml views (*page and layout*)
requested **2000** times with concurrency of **80** in **2.4** seconds and **814**
requests per second. With no caching involved.
An identical Sinatra application was served with the **Thin** HTTP server
and scored **8.3** seconds and **238** requests per second. In this situation
Express is currently **3.5** times faster than Sinatra.
git clone, first update the submodules:
## Examples
$ git submodule update --init
$ make install
$ make install-support
Below is a minimal app example when express is already within your load path.
## Features
* Robust routing
* Redirection helpers
* Focus on high performance
* View rendering and partials support
* Environment based configuration
* Session based flash notifications
* Built on [Connect](http://extjs.github.com/Connect)
* Executable for generating applications quickly
Via Connect:
* Session support
* Cache API
* Mime helpers
* ETag support
* Persistent flash notifications
* Cookie support
* JSON-RPC
* Logging
* and _much_ more!
## Contributors
The following are the major contributors of Express (in no specific order).
* TJ Holowaychuk ([visionmedia](http://github.com/visionmedia))
* Ciaran Jessup ([ciaranj](http://github.com/ciaranj))
* Aaron Heckmann ([aheckmann](http://github.com/aheckmann))
## More Information
* Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) on twitter for updates
* [Google Group](http://groups.google.com/group/express-js) for discussion
* [JavaScript Extensions &amp; Utilities](http://github.com/visionmedia/ext.js)
* [JavaScript Sass](http://github.com/visionmedia/sass.js)
* [JavaScript Haml](http://github.com/visionmedia/haml.js)
* [JavaScript Jade](http://github.com/visionmedia/jade) spiritual successor of Haml
require('express')
require('express/plugins')
configure(function(){
use(MethodOverride)
use(ContentLength)
set('root', __dirname)
})
get('/hello', function(){
this.contentType('html')
return '<h1>World<h1>'
})
get('/user/:id?', function(id) {
this.render('user.haml.html', {
locals: {
name: id ? 'User ' + id : 'You'
}
})
})
run()
## Running Tests
Express uses the [JSpec](http://jspec.info) BDD JavaScript testing
framework to write and run elegant spec suites. JSpec is frozen
to spec/lib and does not require separate installation.
To run all specifications run the following command. This will ensure
git submodules are initialized and updated, as well as building test
related dependencies such as libxmljs.
Express uses the [Expresso](http://github.com/visionmedia/expresso) TDD
framework to write and run elegant test suites extremely fast. First `$ git submodule update --init`, then run:
$ make test
To run independent specs (which do not require building of external apis etc) use:
The latest release of Express is compatible with node --version:
$ make test-independant
To run dependent specs (which require building of external apis etc) use:
$ make test-dependant
Run individual suites:
$ node spec/node.js core
$ node spec/node.js mime
$ node spec/node.js routing
...
Express is currently being developed with node --version:
v0.1.27
## More Information
* [JavaScript Extensions &amp; Utilities](http://github.com/visionmedia/ext.js)
* [JavaScript Sass](http://github.com/visionmedia/sass.js)
* [Scons Build System](http://www.scons.org/) (some development dependencies rely on this, ex libxmljs)
## Contributors
* TJ Holowaychuk (visionmedia) &lt;tj@vision-media.ca&gt;
* Aaron Heckmann (aheckmann) &lt;aaron.heckmann+github@gmail.com&gt;
* Ciaran Jessup (ciaranj) &lt;ciaranj@gmail.com&gt;
* Gareth Jones (csausdev) &lt;gareth.jones@sensis.com.au&gt;
v0.1.100
## License
(The MIT License)
Copyright (c) 2009 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
Copyright (c) 2009-2010 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
-83
Ver Arquivo
@@ -1,83 +0,0 @@
;(function(){
var currentSuite
/**
* Contents of _fn_. Strips function literal and signature.
*
* @param {function} fn
* @return {string}
* @api private
*/
function contentsOf(fn) {
return fn.toString().match(/^[^\{]*{((.*\n*)*)}/m)[1]
}
/**
* Pad _str_ to _len_.
*
* @param {string} str
* @param {integer} len
* @return {string}
* @api private
*/
function pad(str, len) {
return str + (new Array(len - str.length)).join(' ')
}
/**
* Time the execution of _fn_
*
* @param {function} fn
* @return {float}
* @api private
*/
function time(fn) {
var start = Number(new Date)
fn()
return (Number(new Date) - start) / 1000
}
/**
* Benchmark _fn_ with the given _label_.
*
* @param {string} label
* @param {function} fn
* @api public
*/
function benchmark(label, fn) {
var duration = time(function(){
for (var i = 0; i < currentSuite.times; ++i)
fn()
}).toFixed(3)
print(pad(' ' + label, 50 - duration.toString().length) + duration + ' |')
}
/**
* Create a benchmark suite with the given _label_, which
* will run each benchmark n _times_. If _times_ is omitted
* then it defaults to 1.
*
* @param {string} label
* @param {integer, function} times
* @param {function} fn
* @api public
*/
suite = function(label, times, fn) {
currentSuite = this
if (typeof times == 'function')
this.times = 1, fn = times
else
this.times = times
print('\n ' + pad(label, 42 - this.times.toString().length) + this.times + ' time(s)')
print(' -------------------------------------------------')
eval(contentsOf(fn))
print('')
}
})()
-111
Ver Arquivo
@@ -1,111 +0,0 @@
require.paths.unshift('lib')
require.paths.unshift('benchmarks')
process.mixin(GLOBAL, require('sys'))
process.mixin(GLOBAL, require('benchmark'))
require('express')
print = puts
range = function(a, b) {
var array = []
while (a++ < b)
array.push(a-1)
return array
}
suite('Collection with [0..10,000]', 100, function(){
array = range(0, 10000)
benchmark('for', function(){
for (var i = 0, len = array.length; i < len; ++i) ;
})
benchmark('for uncached', function(){
for (var i = 0; i < array.length; ++i) ;
})
benchmark('forEach()', function(){
array.forEach(function(){})
})
benchmark('#each()', function(){
$(array).each(function(){})
})
benchmark('#map()', function(){
$(array).map(function(n){ return n += 1 })
})
benchmark('#map() with shorthand', function(){
$(array).map('a += 1')
})
benchmark('#find()', function(){
$(array).find(function(n){ return n > 5000 })
})
benchmark('#select()', function(){
$(array).select(function(n){ return n % 2 })
})
benchmark('#first()', function(){
$(array).first(5000)
})
benchmark('#slice()', function(){
$(array).slice(100, 5000)
})
benchmark('#drop()', function(){
$(array).drop(5000)
})
benchmark('#length()', function(){
$(array).length()
})
benchmark('#keys()', function(){
$(array).keys()
})
benchmark('#toArray()', function(){
$(array).toArray()
})
benchmark('#min()', function(){
$(array).min()
})
benchmark('#max()', function(){
$(array).max()
})
benchmark('#sum()', function(){
$(array).sum()
})
benchmark('#avg()', function(){
$(array).avg()
})
benchmark('#clone()', function(){
$(array).clone()
})
benchmark('#merge()', function(){
$(array).merge({ foo: 'bar' })
})
benchmark('#sample()', function(){
$(array).sample()
})
benchmark('#chunk()', function(){
$(array).chunk(5)
})
benchmark('#at()', function(){
$(array).at(5000)
})
})
-56
Ver Arquivo
@@ -1,56 +0,0 @@
require.paths.unshift('lib')
require.paths.unshift('benchmarks')
process.mixin(GLOBAL, require('sys'))
process.mixin(GLOBAL, require('benchmark'))
require('express')
print = puts
engine = {
ejs: require('ejs'),
haml: require('haml'),
sass: require('sass')
}
options = { locals: { article: { title: 'Foo', body: 'bar' }}}
ejs = ' \n\
<div id="primary"> \n\
<div class="block first"> \n\
<h1><%= article.title %></h1> \n\
<p><%= article.body %></p> \n\
</div> \n\
</div> \n\
'
haml = ' \n\
#primary \n\
.block.first \n\
%h1= article.title \n\
%p= article.body \n\
'
sass = ' \n\
red: #ff0000 \n\
body \n\
ul \n\
li \n\
a \n\
:color !red \n\
:list-style none \n\
'
suite('Template Engines', 1000, function(){
benchmark('ejs', function(){
engine.ejs.render(ejs, options)
})
benchmark('haml', function(){
engine.haml.render(haml, options)
})
benchmark('sass', function(){
engine.sass.render(sass)
})
})
Arquivo executável
+183
Ver Arquivo
@@ -0,0 +1,183 @@
#!/usr/bin/env node
/**
* Module dependencies.
*/
var sys = require('sys'),
fs = require('fs'),
childProcess = require('child_process');
/**
* Framework version.
*/
var version = '1.0.0beta';
/**
* Usage documentation.
*/
var usage = ''
+ '\x1b[1mUsage\x1b[0m: express [options] [PATH]\n'
+ '\n'
+ '\x1b[1mOptions\x1b[0m:\n'
+ ' -v, --version Output framework version\n'
+ ' -h, --help Output help information\n';
/**
* Jade layout template.
*/
var jadeLayout = [
'!!!',
'html',
' head',
' title= title',
' link(rel=\'stylesheet\', href=\'/stylesheets/style.css\')',
' body!= body'
].join('\n');
/**
* Default sass template.
*/
var sass = [
'body',
' :padding 50px',
' :font 14px "Lucida Grande", "Helvetica Nueue", Arial, sans-serif'
].join('\n');
/**
* Jade index template.
*/
var jadeIndex = [
'h1= title',
'p Welcome to #{title}'
].join('\n');
/**
* App template.
*/
var app = [
'',
'/**',
' * Module dependencies.',
' */',
'',
'var express = require(\'express\'),',
' connect = require(\'connect\');',
'',
'// Create and export Express app',
'',
'var app = express.createServer();',
'',
'// Configuration',
'',
'app.configure(function(){',
' app.set(\'views\', __dirname + \'/views\');',
' app.use(\'/\', connect.bodyDecoder());',
' app.use(\'/\', connect.methodOverride());',
' app.use(\'/\', connect.compiler({ src: __dirname + \'/public\', enable: [\'sass\'] }));',
' app.use(\'/\', connect.staticProvider(__dirname + \'/public\'));',
'});',
'',
'app.configure(\'development\', function(){',
' app.set(\'reload views\', 1000);',
' app.use(\'/\', connect.errorHandler({ dumpExceptions: true, showStack: true })); ',
'});',
'',
'app.configure(\'production\', function(){',
' app.use(\'/\', connect.errorHandler()); ',
'});',
'',
'// Routes',
'',
'app.get(\'/\', function(req, res){',
' res.render(\'index.jade\', {',
' locals: {',
' title: \'Express\'',
' }',
' });',
'});',
'',
'app.listen(3000);',
''
].join('\n');
// Parse arguments
var args = process.argv.slice(2),
path = '.';
while (args.length) {
var arg = args.shift();
switch (arg) {
case '-h':
case '--help':
abort(usage);
break;
case '-v':
case '--version':
abort(version);
break;
default:
path = arg;
}
}
// Generate application
(function createApplication(path) {
mkdir(path, function(){
mkdir(path + '/pids');
mkdir(path + '/logs');
mkdir(path + '/public/{javascripts,stylesheets,images}', function(){
write(path + '/public/stylesheets/style.sass', sass);
});
mkdir(path + '/views/partials', function(){
write(path + '/views/layout.jade', jadeLayout);
write(path + '/views/index.jade', jadeIndex);
});
write(path + '/app.js', app);
});
})(path);
/**
* echo str > path.
*
* @param {String} path
* @param {String} str
*/
function write(path, str) {
fs.writeFile(path, str);
sys.puts(' create : ' + path);
}
/**
* Mkdir -p.
*
* @param {String} path
* @param {Function} fn
*/
function mkdir(path, fn) {
childProcess.exec('mkdir -p ' + path, function(err){
if (err) throw err;
sys.puts(' create : ' + path);
fn && fn();
});
}
/**
* Exit with the given `str`.
*
* @param {String} str
*/
function abort(str) {
sys.error(str);
process.exit(1);
}
+1032
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+64
Ver Arquivo
@@ -0,0 +1,64 @@
.\" generated with Ronn/v0.6.6
.\" http://github.com/rtomayko/ronn/
.
.TH "CONTRIB" "" "July 2010" "" ""
.
.SS "Development Dependencies"
Express development dependencies are stored within the \fI\./support\fR directory\. To update them execute:
.
.IP "" 4
.
.nf
$ git submodule update \-\-init
.
.fi
.
.IP "" 0
.
.SS "Running Tests"
Express uses the Expresso \fIhttp://github\.com/visionmedia/expresso\fR TDD framework to write and run elegant test suites extremely fast\. To run all test suites simply execute:
.
.IP "" 4
.
.nf
$ make test
.
.fi
.
.IP "" 0
.
.P
To target specific suites we may specify the files via:
.
.IP "" 4
.
.nf
$ make test TESTS=test/view\.test\.js
.
.fi
.
.IP "" 0
.
.SS "Contributions"
To accept a contribution, you should follow these guidelines:
.
.IP "\(bu" 4
All tests \fImust\fR pass
.
.IP "\(bu" 4
Your alterations or additions \fImust\fR include tests
.
.IP "\(bu" 4
Your commit(s) should be \fIfocused\fR, do not commit once for several changes
.
.IP "\(bu" 4
Do \fInot\fR alter release information such as the \fIversion\fR, or \fIHistory\.md\fR
.
.IP "\(bu" 4
Indents are \fI4\fR spaces\.
.
.IP "" 0
+220
Ver Arquivo
@@ -0,0 +1,220 @@
<html>
<head>
<title>Express - node web framework</title>
<style>
#header {
position: absolute;
top: 10px;
left: 0;
padding: 12px 0;
text-indent: 40px;
width: 100%;
border-top: 1px solid rgba(0,0,0,0.7);
border-bottom: 1px solid rgba(0,0,0,0.7);
background: rgba(255,255,255,0.1) url(http://www.sencha.com/favicon.ico) no-repeat 15px 50%;
text-align: left;
color: #fff;
}
#tagline {
margin-left: 75px;
margin-bottom: 30px;
color: rgba(255,255,255,0.7); }
html {
background: #1c1c1c url(images/bg.tile.jpg); }
body {
margin: 0;
padding-bottom: 30px;
font: 14px/1.4 "Helvetica Neue", "Lucida Grande", "Arial";
font-size: 14px;
line-height: 1.5;
-webkit-text-stroke: 1px rgba(0, 0, 0, 0.1);
-moz-text-stroke: 1px rgba(0, 0, 0, 0.1);
background: url(images/bg.jpg) 50% 0 no-repeat;
color: #8b8b8b; }
* {
outline: none; }
em {
color: white; }
a img {
border: none !important; }
a {
font-weight: bold;
text-decoration: none;
color: white;
-webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow;
-webkit-transition-duration: 0.15s;
-webkit-transition-timing-function: ease-out; }
a:hover {
opacity: 0.8; }
h1, h2, h3 {
margin: 45px 0 0 0;
color: white;
text-shadow: 1px 2px 2px rgba(0,0,0,0.6); }
h3 {
font-size: 18px; }
pre {
margin: 20px 10px;
padding: 25px 20px;
background: rgba(0,0,0,0.5);
border: 1px solid #323232;
-webkit-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-moz-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-webkit-border-radius: 5px;
-moz-border-radius: 5px; }
code {
font-family: "Helvetica Neue", "Lucida Grande", "Arial"; }
ul {
margin: 15px 0;
padding: 0 0 0 35px; }
ul li {
margin: 0;
padding: 2px 0;
list-style: square; }
.sect {
margin-left: 40px; }
#logo {
display: block;
margin-left: 30%;
margin-bottom: 30px;
width: 194px;
height: 51px;
background: url(images/logo.png) 0 0 no-repeat;
text-indent: -99999px; }
#logo:hover {
opacity: 0.7; }
#logo:active {
opacity: 0.3; }
#ribbon {
position: fixed;
top: 0;
right: 0;
z-index: 2; }
#wrapper {
width: 100%;
min-height: 800px;
background: url(images/top.png) 0 0 repeat-x; }
#container {
margin: 0 auto;
padding-top: 110px;
width: 550px; }
#toc {
position: fixed;
top: 60px;
left: 0;
margin: 0 0 0 15px;
padding: 15px;
height: 100%;
background: rgba(0,0,0,0.2);
border-right: 1px solid rgba(255,255,255,0.05);
}
#toc li {
padding: 1px 0;
list-style: none;
}
#toc li a {
font-size: 11px;
}
#menu {
margin-left: 65px;
padding: 0;
padding-bottom: 30px; }
#menu li {
display: inline;
list-style: none; }
#menu li a {
display: block;
float: left;
margin: 0 2px;
padding: 3px 15px;
background: rgba(0,0,0,0.2);
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
-webkit-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-moz-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-webkit-transition-property: opacity, -webkit-transform, color, background-color, -webkit-box-shadow;
-webkit-transition-duration: 0.15s;
-webkit-transition-timing-function: ease-out; }
#menu li a:hover,
#menu li a.active {
background: rgba(0,0,0,0.5); }
#menu li a:active {
background: rgba(0,0,0,0.1);
-webkit-box-shadow: 1px 1px 1px rgba(0,0,0,0.4);
-moz-box-shadow: 1px 1px 1px rgba(0,0,0,0.4); }
</style>
</head>
<body>
<a href='http://github.com/visionmedia/express'>
<img alt='Fork me on GitHub' id='ribbon' src='http://s3.amazonaws.com/github/ribbons/forkme_right_white_ffffff.png' />
</a>
<div id="header"><strong>Sencha</strong> labs</div>
<div id="wrapper">
<div id="container">
<a href='http://github.com/visionmedia/express' id='logo'>Express</a>
<p id="tagline">
High performance, high class web development for
<a href="http://nodejs.org">Node.js</a>
</p>
<ul id="menu">
<li><a href="index.html">Home</a></li>
<li><a href="guide.html">Guide</a></li>
<li><a href="contrib.html">Contributing</a></li>
<li><a href="migrate.html">1.x Migration</a></li>
</ul>
<div class='mp'>
<h3 id="Development-Dependencies">Development Dependencies</h3>
<p>Express development dependencies are stored within the <em>./support</em> directory. To
update them execute:</p>
<pre><code>$ git submodule update --init
</code></pre>
<h3 id="Running-Tests">Running Tests</h3>
<p>Express uses the <a href="http://github.com/visionmedia/expresso">Expresso</a> TDD
framework to write and run elegant test suites extremely fast. To run all test suites
simply execute:</p>
<pre><code>$ make test
</code></pre>
<p>To target specific suites we may specify the files via:</p>
<pre><code>$ make test TESTS=test/view.test.js
</code></pre>
<h3 id="Contributions">Contributions</h3>
<p>To accept a contribution, you should follow these guidelines:</p>
<ul>
<li>All tests <em>must</em> pass</li>
<li>Your alterations or additions <em>must</em> include tests</li>
<li>Your commit(s) should be <em>focused</em>, do not commit once for several changes</li>
<li>Do <em>not</em> alter release information such as the <em>version</em>, or <em>History.md</em></li>
<li>Indents are <em>4</em> spaces.</li>
</ul>
</div>
</div>
</div>
</body>
</html>
+29
Ver Arquivo
@@ -0,0 +1,29 @@
### Development Dependencies
Express development dependencies are stored within the _./support_ directory. To
update them execute:
$ git submodule update --init
### Running Tests
Express uses the [Expresso](http://github.com/visionmedia/expresso) TDD
framework to write and run elegant test suites extremely fast. To run all test suites
simply execute:
$ make test
To target specific suites we may specify the files via:
$ make test TESTS=test/view.test.js
### Contributions
To accept a contribution, you should follow these guidelines:
* All tests _must_ pass
* Your alterations or additions _must_ include tests
* Your commit(s) should be _focused_, do not commit once for several changes
* Do _not_ alter release information such as the _version_, or _History.md_
* Indents are _4_ spaces.
+25
Ver Arquivo
@@ -0,0 +1,25 @@
.\" generated with Ronn/v0.6.6
.\" http://github.com/rtomayko/ronn/
.
.TH "EXECUTABLE" "" "July 2010" "" ""
.
.SH "Synopsis"
.
.nf
express [\-h|\-\-help] [\-v|\-\-version] [PATH]
.
.fi
.
.SH "Description"
The \fBexpress\fR executable generates apps at the given \fBPATH\fR or the current working directory\. Although Express is not bound to a specific application structure, this executable creates a maintainable base app\.
.
.SH "Options"
.
.nf
\-v, \-\-version Output framework version
\-h, \-\-help Display help information
.
.fi
+202
Ver Arquivo
@@ -0,0 +1,202 @@
<html>
<head>
<title>Express - node web framework</title>
<style>
#header {
position: absolute;
top: 10px;
left: 0;
padding: 12px 0;
text-indent: 40px;
width: 100%;
border-top: 1px solid rgba(0,0,0,0.7);
border-bottom: 1px solid rgba(0,0,0,0.7);
background: rgba(255,255,255,0.1) url(http://www.sencha.com/favicon.ico) no-repeat 15px 50%;
text-align: left;
color: #fff;
}
#tagline {
margin-left: 75px;
margin-bottom: 30px;
color: rgba(255,255,255,0.7); }
html {
background: #1c1c1c url(images/bg.tile.jpg); }
body {
margin: 0;
padding-bottom: 30px;
font: 14px/1.4 "Helvetica Neue", "Lucida Grande", "Arial";
font-size: 14px;
line-height: 1.5;
-webkit-text-stroke: 1px rgba(0, 0, 0, 0.1);
-moz-text-stroke: 1px rgba(0, 0, 0, 0.1);
background: url(images/bg.jpg) 50% 0 no-repeat;
color: #8b8b8b; }
* {
outline: none; }
em {
color: white; }
a img {
border: none !important; }
a {
font-weight: bold;
text-decoration: none;
color: white;
-webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow;
-webkit-transition-duration: 0.15s;
-webkit-transition-timing-function: ease-out; }
a:hover {
opacity: 0.8; }
h1, h2, h3 {
margin: 45px 0 0 0;
color: white;
text-shadow: 1px 2px 2px rgba(0,0,0,0.6); }
h3 {
font-size: 18px; }
pre {
margin: 20px 10px;
padding: 25px 20px;
background: rgba(0,0,0,0.5);
border: 1px solid #323232;
-webkit-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-moz-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-webkit-border-radius: 5px;
-moz-border-radius: 5px; }
code {
font-family: "Helvetica Neue", "Lucida Grande", "Arial"; }
ul {
margin: 15px 0;
padding: 0 0 0 35px; }
ul li {
margin: 0;
padding: 2px 0;
list-style: square; }
.sect {
margin-left: 40px; }
#logo {
display: block;
margin-left: 30%;
margin-bottom: 30px;
width: 194px;
height: 51px;
background: url(images/logo.png) 0 0 no-repeat;
text-indent: -99999px; }
#logo:hover {
opacity: 0.7; }
#logo:active {
opacity: 0.3; }
#ribbon {
position: fixed;
top: 0;
right: 0;
z-index: 2; }
#wrapper {
width: 100%;
min-height: 800px;
background: url(images/top.png) 0 0 repeat-x; }
#container {
margin: 0 auto;
padding-top: 110px;
width: 550px; }
#toc {
position: fixed;
top: 60px;
left: 0;
margin: 0 0 0 15px;
padding: 15px;
height: 100%;
background: rgba(0,0,0,0.2);
border-right: 1px solid rgba(255,255,255,0.05);
}
#toc li {
padding: 1px 0;
list-style: none;
}
#toc li a {
font-size: 11px;
}
#menu {
margin-left: 65px;
padding: 0;
padding-bottom: 30px; }
#menu li {
display: inline;
list-style: none; }
#menu li a {
display: block;
float: left;
margin: 0 2px;
padding: 3px 15px;
background: rgba(0,0,0,0.2);
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
-webkit-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-moz-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-webkit-transition-property: opacity, -webkit-transform, color, background-color, -webkit-box-shadow;
-webkit-transition-duration: 0.15s;
-webkit-transition-timing-function: ease-out; }
#menu li a:hover,
#menu li a.active {
background: rgba(0,0,0,0.5); }
#menu li a:active {
background: rgba(0,0,0,0.1);
-webkit-box-shadow: 1px 1px 1px rgba(0,0,0,0.4);
-moz-box-shadow: 1px 1px 1px rgba(0,0,0,0.4); }
</style>
</head>
<body>
<a href='http://github.com/visionmedia/express'>
<img alt='Fork me on GitHub' id='ribbon' src='http://s3.amazonaws.com/github/ribbons/forkme_right_white_ffffff.png' />
</a>
<div id="header"><strong>Sencha</strong> labs</div>
<div id="wrapper">
<div id="container">
<a href='http://github.com/visionmedia/express' id='logo'>Express</a>
<p id="tagline">
High performance, high class web development for
<a href="http://nodejs.org">Node.js</a>
</p>
<ul id="menu">
<li><a href="index.html">Home</a></li>
<li><a href="guide.html">Guide</a></li>
<li><a href="contrib.html">Contributing</a></li>
<li><a href="migrate.html">1.x Migration</a></li>
</ul>
<div class='mp'>
<h2 id="Synopsis">Synopsis</h2>
<pre><code>express [-h|--help] [-v|--version] [PATH]
</code></pre>
<h2 id="Description">Description</h2>
<p>The <code>express</code> executable generates apps at the given <strong>PATH</strong> or the
current working directory. Although Express is not bound to a specific
application structure, this executable creates a maintainable base app.</p>
<h2 id="Options">Options</h2>
<pre><code>-v, --version Output framework version
-h, --help Display help information
</code></pre>
</div>
</div>
</div>
</body>
</html>
+16
Ver Arquivo
@@ -0,0 +1,16 @@
## Synopsis
express [-h|--help] [-v|--version] [PATH]
## Description
The `express` executable generates apps at the given **PATH** or the
current working directory. Although Express is not bound to a specific
application structure, this executable creates a maintainable base app.
## Options
-v, --version Output framework version
-h, --help Display help information
+860
Ver Arquivo
@@ -0,0 +1,860 @@
.\" generated with Ronn/v0.6.6
.\" http://github.com/rtomayko/ronn/
.
.TH "GUIDE" "" "July 2010" "" ""
.
.SS "Installation"
npm:
.
.IP "" 4
.
.nf
$ npm install connect
$ npm install express
.
.fi
.
.IP "" 0
.
.P
curl (or similar):
.
.IP "" 4
.
.nf
$ curl \-# http://github\.com/visionmedia/express/raw/master/install\.sh | sh
.
.fi
.
.IP "" 0
.
.P
git clone, first update the submodules:
.
.IP "" 4
.
.nf
$ git submodule update \-\-init
$ make install
$ make install\-support
.
.fi
.
.IP "" 0
.
.SS "Creating An Application"
The \fIexpress\.Server\fR now inherits from \fIhttp\.Server\fR, however follows the same idiom by providing \fIexpress\.createServer()\fR as shown below\. This means that you can utilize Express server\'s transparently with other libraries\.
.
.IP "" 4
.
.nf
var app = require(\'express\')\.createServer();
app\.get(\'/\', function(req, res){
res\.send(\'hello world\');
});
app\.listen(3000);
.
.fi
.
.IP "" 0
.
.SS "Configuration"
Express supports arbitrary environments, such as \fIproduction\fR and \fIdevelopment\fR\. Developers can use the \fIconfigure()\fR method to setup needs required by the current environment\. When \fIconfigure()\fR is called without an environment name it will be run in \fIevery\fR environment prior to the environment specific callback\.
.
.P
In the example below we only \fIdumpExceptions\fR, and respond with exception stack traces in \fIdevelopment\fR mode, however for both environments we utilize \fImethodOverride\fR and \fIbodyDecoder\fR\.
.
.IP "" 4
.
.nf
app\.configure(function(){
app\.use(\'/\', connect\.methodOverride());
app\.use(\'/\', connect\.bodyDecoder());
});
app\.configure(\'development\', function(){
app\.use(\'/\', connect\.errorHandler({ dumpExceptions: true, showStack: true }));
});
app\.configure(\'production\', function(){
app\.use(\'/\', connect\.errorHandler());
});
.
.fi
.
.IP "" 0
.
.P
For internal and arbitrary settings Express provides the \fIset(key[, val])\fR, \fIenable(key)\fR, \fIdisable(key)\fR methods:
.
.IP "" 4
.
.nf
app\.configure(function(){
app\.set(\'views\', __dirname + \'/views\');
app\.set(\'views\');
// => \"\.\.\. views directory \.\.\.\"
app\.enable(\'some feature\');
// same as app\.set(\'some feature\', true);
app\.disable(\'some feature\');
// same as app\.set(\'some feature\', false);
});
.
.fi
.
.IP "" 0
.
.P
To alter the environment we can set the \fICONNECT_ENV\fR environment variable, or more specifically \fIEXPRESS_ENV\fR, for example:
.
.IP "" 4
.
.nf
$ EXPRESS_ENV=production node app\.js
.
.fi
.
.IP "" 0
.
.SS "Settings"
Express supports the following settings out of the box:
.
.IP "\(bu" 4
\fIenv\fR Application environment set internally, use \fIapp\.set(\'env\')\fR to utilize
.
.IP "\(bu" 4
\fIhome\fR Application base path used with \fIres\.redirect()\fR
.
.IP "\(bu" 4
\fIviews\fR Root views directory defaulting to \fBCWD/views\fR
.
.IP "\(bu" 4
\fIview engine\fR Default view engine name for views rendered without extensions
.
.IP "\(bu" 4
\fIreload views\fR Reloads altered views, by default watches for \fImtime\fR changes with with a 5 minute interval\. Example: \fIapp\.set(\'reload views\', 60000);\fR
.
.IP "" 0
.
.SS "Routing"
Express utilizes the HTTP verbs to provide a meaningful, expressive routing API\. For example we may want to render a user\'s account for the path \fI/user/12\fR, this can be done by defining the route below\. The values associated to the named placeholders, are passed as the \fIthird\fR argument, which here we name \fIparams\fR\.
.
.IP "" 4
.
.nf
app\.get(\'/user/:id\', function(req, res, params){
res\.send(\'user \' + params\.id);
});
.
.fi
.
.IP "" 0
.
.P
A route is simple a string which is compiled to a \fIRegExp\fR internally\. For example when \fI/user/:id\fR is compiled, a simplified version of the regexp may look similar to:
.
.IP "" 4
.
.nf
\\/user\\/([^\\/]+)\\/?
.
.fi
.
.IP "" 0
.
.P
Literal regular expressions may also be passed for complex uses:
.
.IP "" 4
.
.nf
app\.get(/^\\/foo(bar)?$/, function(){});
.
.fi
.
.IP "" 0
.
.P
Below are some route examples, and the associated paths that they may consume:
.
.IP "" 4
.
.nf
\"/user/:id\"
/user/12
\"/users/:id?\"
/users/5
/users
\"/files/*\"
/files/jquery\.js
/files/javascripts/jquery\.js
\"/file/*\.*\"
/files/jquery\.js
/files/javascripts/jquery\.js
\"/user/:id/:operation?\"
/user/1
/user/1/edit
\"/products\.:format\"
/products\.json
/products\.xml
\"/products\.:format?\"
/products\.json
/products\.xml
/products
.
.fi
.
.IP "" 0
.
.SS "Passing Route Control"
We may pass control to the next \fImatching\fR route, by calling the \fIfourth\fR parameter, the \fInext()\fR function\. When a match cannot be made, control is passed back to Connect\.
.
.IP "" 4
.
.nf
app\.get(\'/users/:id?\', function(req, res, params){
if (params\.id) {
// do something
} else {
next();
}
});
app\.get(\'/users\', function(req, res, params){
// do something else
});
.
.fi
.
.IP "" 0
.
.SS "Middleware"
The Express \fIPlugin\fR is no more! middleware via Connect \fIhttp://github\.com/extjs/Connect\fR can be passed to \fIexpress\.createServer()\fR as you would with a regular Connect server\. For example:
.
.IP "" 4
.
.nf
var connect = require(\'connect\'),
express = require(\'express\');
var app = express\.createServer(
connect\.logger(),
connect\.bodyDecoder()
);
.
.fi
.
.IP "" 0
.
.P
Alternatively we can \fIuse()\fR them which is useful when adding middleware within \fIconfigure()\fR blocks:
.
.IP "" 4
.
.nf
app\.use(\'/\', connect\.logger({ format: \':method :uri\' }));
.
.fi
.
.IP "" 0
.
.SS "Error Handling"
Express provides the \fIapp\.error()\fR method which receives exceptions thrown within a route, or passed to \fInext(err)\fR\. Below is an example which serves different pages based on our ad\-hoc \fINotFound\fR exception:
.
.IP "" 4
.
.nf
function NotFound(msg){
this\.name = \'NotFound\';
Error\.call(this, msg);
Error\.captureStackTrace(this, arguments\.callee);
}
sys\.inherits(NotFound, Error);
app\.get(\'/404\', function(req, res){
throw new NotFound;
});
app\.get(\'/500\', function(req, res){
throw new Error(\'keyboard cat!\');
});
.
.fi
.
.IP "" 0
.
.P
We can call \fIapp\.error()\fR several times as shown below\. Here we check for an instanceof \fINotFound\fR and show the 404 page, or we pass on to the next error handler\.
.
.IP "" 4
.
.nf
app\.error(function(err, req, res, next){
if (err instanceof NotFound) {
res\.render(\'404\.jade\');
} else {
next(err);
}
});
.
.fi
.
.IP "" 0
.
.P
Here we assume all errors as 500 for the simplicity of this demo, however you can choose whatever you like
.
.IP "" 4
.
.nf
app\.error(function(err, req, res){
res\.render(\'500\.jade\', {
locals: {
error: err
}
});
});
.
.fi
.
.IP "" 0
.
.P
Our apps could also utilize the Connect \fIerrorHandler\fR middleware to report on exceptions\. For example if we wish to output exceptions in \"development\" mode to \fIstderr\fR we can use:
.
.IP "" 4
.
.nf
app\.use(\'/\', connect\.errorHandler({ dumpExceptions: true }));
.
.fi
.
.IP "" 0
.
.P
Also during development we may want fancy html pages to show exceptions that are passed or thrown, so we can set \fIshowStack\fR to true:
.
.IP "" 4
.
.nf
app\.use(\'/\', connect\.errorHandler({ showStack: true, dumpExceptions: true }));
.
.fi
.
.IP "" 0
.
.P
The \fIerrorHandler\fR middleware also responds with \fIjson\fR if \fIAccept: application/json\fR is present, which is useful for developing apps that rely heavily on client\-side JavaScript\.
.
.SS "View Rendering"
View filenames take the form \fINAME\fR\.\fIENGINE\fR, where \fIENGINE\fR is the name of the module that will be required\. For example the view \fIlayout\.ejs\fR will tell the view system to \fIrequire(\'ejs\')\fR, the module being loaded must (currently) export the method \fIexports\.render(str, options)\fR to comply with Express, however with will likely be extensible in the future\.
.
.P
Below is an example using Haml\.js \fIhttp://github\.com/visionmedia/haml\.js\fR to render \fIindex\.html\fR, and since we do not use \fIlayout: false\fR the rendered contents of \fIindex\.html\fR will be passed as the \fIbody\fR local variable in \fIlayout\.haml\fR\.
.
.IP "" 4
.
.nf
app\.get(\'/\', function(req, res){
res\.render(\'index\.haml\', {
locals: { title: \'My Site\' }
});
});
.
.fi
.
.IP "" 0
.
.SS "View Partials"
The Express view system has built\-in support for partials and collections, which are sort of \"mini\" views representing a document fragment\. For example rather than iterating in a view to display comments, we would use a partial with collection support:
.
.IP "" 4
.
.nf
partial(\'comment\.haml\', { collection: comments });
.
.fi
.
.IP "" 0
.
.P
To make things even less verbose we can assume the extension as \fI\.haml\fR when omitted, however if we wished we could use an ejs partial, within a haml view for example\.
.
.IP "" 4
.
.nf
partial(\'comment\', { collection: comments });
.
.fi
.
.IP "" 0
.
.P
And once again even further, when rendering a collection we can simply pass an array, if no other options are desired:
.
.IP "" 4
.
.nf
partial(\'comments\', comments);
.
.fi
.
.IP "" 0
.
.SS "Template Engines"
Below are a few template engines commonly used with Express:
.
.IP "\(bu" 4
Jade \fIhttp://github\.com/visionmedia/jade\fR haml\.js successor
.
.IP "\(bu" 4
Haml \fIhttp://github\.com/visionmedia/haml\.js\fR indented templates
.
.IP "\(bu" 4
EJS \fIhttp://github\.com/visionmedia/ejs\fR Embedded JavaScript
.
.IP "" 0
.
.SS "req\.header(key[, defaultValue])"
Get the case\-insensitive request header \fIkey\fR, with optional \fIdefaultValue\fR:
.
.IP "" 4
.
.nf
req\.header(\'Host\');
req\.header(\'host\');
req\.header(\'Accept\', \'*/*\');
.
.fi
.
.IP "" 0
.
.SS "req\.accepts(type)"
Check if the \fIAccept\fR header is present, and includes the given \fItype\fR\.
.
.P
When the \fIAccept\fR header is not present \fItrue\fR is returned\. Otherwise the given \fItype\fR is matched by an exact match, and then subtypes\. You may pass the subtype such as \"html\" which is then converted internally to \"text/html\" using the mime lookup table\.
.
.IP "" 4
.
.nf
// Accept: text/html
req\.accepts(\'html\');
// => true
// Accept: text/*; application/json
req\.accepts(\'html\');
req\.accepts(\'text/html\');
req\.accepts(\'text/plain\');
req\.accepts(\'application/json\');
// => true
req\.accepts(\'image/png\');
req\.accepts(\'png\');
// => false
.
.fi
.
.IP "" 0
.
.SS "req\.param(name)"
Return the value of param \fIname\fR when present\.
.
.IP "\(bu" 4
Checks route placeholders, ex: /user/:id
.
.IP "\(bu" 4
Checks query string params, ex: ?id=12
.
.IP "\(bu" 4
Checks urlencoded body params, ex: id=12
.
.IP "" 0
.
.P
To utilize urlencoded request bodies, \fIreq\.body\fR should be an object\. This can be done by using the \fIconnect\.bodyDecoder\fR middleware\.
.
.SS "req\.flash(type[, msg])"
Queue flash \fImsg\fR of the given \fItype\fR\.
.
.IP "" 4
.
.nf
req\.flash(\'info\', \'email sent\');
req\.flash(\'error\', \'email delivery failed\');
req\.flash(\'info\', \'email re\-sent\');
// => 2
req\.flash(\'info\');
// => [\'email sent\', \'email re\-sent\']
req\.flash(\'info\');
// => []
req\.flash();
// => { error: [\'email delivery failed\'], info: [] }
.
.fi
.
.IP "" 0
.
.SS "req\.isXMLHttpRequest"
Also aliased as \fIreq\.xhr\fR, this getter checks the \fIX\-Requested\-With\fR header to see if it was issued by an \fIXMLHttpRequest\fR:
.
.IP "" 4
.
.nf
req\.xhr
req\.isXMLHttpRequest
.
.fi
.
.IP "" 0
.
.SS "res\.header(key[, val])"
Get or set the response header \fIkey\fR\.
.
.IP "" 4
.
.nf
res\.header(\'Content\-Length\');
// => undefined
res\.header(\'Content\-Length\', 123);
// => 123
res\.header(\'Content\-Length\');
// => 123
.
.fi
.
.IP "" 0
.
.SS "res\.contentType(type)"
Sets the \fIContent\-Type\fR response header to the given \fItype\fR\.
.
.IP "" 4
.
.nf
var filename = \'path/to/image\.png\';
res\.contentType(filename);
// res\.headers[\'Content\-Type\'] is now \"image/png\"
.
.fi
.
.IP "" 0
.
.SS "res\.attachment([filename])"
Sets the \fIContent\-Disposition\fR response header to \"attachment\", with optional \fIfilename\fR\.
.
.IP "" 4
.
.nf
res\.attachment(\'path/to/my/image\.png\');
.
.fi
.
.IP "" 0
.
.SS "res\.sendfile(path)"
Used by \fBres\.download()\fR to transfer an arbitrary file\.
.
.IP "" 4
.
.nf
res\.sendfile(\'path/to/my\.file\');
.
.fi
.
.IP "" 0
.
.P
\fBNOTE\fR: this is \fInot\fR a replacement for Connect\'s \fIstaticProvider\fR middleware, nor does it perform any security checks, use with caution when using in a dynamic manor\.
.
.SS "res\.download(file[, filename])"
Transfer the given \fIfile\fR as an attachment with optional alternative \fIfilename\fR\.
.
.IP "" 4
.
.nf
res\.download(\'path/to/image\.png\');
res\.download(\'path/to/image\.png\', \'foo\.png\');
.
.fi
.
.IP "" 0
.
.P
This is equivalent to:
.
.IP "" 4
.
.nf
res\.attachment(file);
res\.sendfile(file);
.
.fi
.
.IP "" 0
.
.SS "res\.send(body|status[, headers|status[, status]])"
The \fBres\.send()\fR method is a high level response utility allowing you to pass objects to respond with json, strings for html, arbitrary _Buffer_s or numbers for status code based responses\. The following are all valid uses:
.
.IP "" 4
.
.nf
res\.send(new Buffer(\'wahoo\'));
res\.send({ some: \'json\' });
res\.send(\'<p>some html</p>\');
res\.send(\'Sorry, cant find that\', 404);
res\.send(\'text\', { \'Content\-Type\': \'text/plain\' }, 201);
res\.send(404);
.
.fi
.
.IP "" 0
.
.P
By default the \fIContent\-Type\fR response header is set, however if explicitly assigned through \fBres\.send()\fR or previously with \fBres\.header()\fR or \fBres\.contentType()\fR it will not be set again\.
.
.SS "res\.redirect(url[, status])"
Redirect to the given \fIurl\fR with a default response \fIstatus\fR of 302\.
.
.IP "" 4
.
.nf
res\.redirect(\'/\', 301);
res\.redirect(\'/account\');
res\.redirect(\'http://google\.com\');
res\.redirect(\'home\');
res\.redirect(\'back\');
.
.fi
.
.IP "" 0
.
.P
Express supports \"redirect mapping\", which by default provides \fIhome\fR, and \fIback\fR\. The \fIback\fR map checks the \fIReferrer\fR and \fIReferer\fR headers, while \fIhome\fR utilizes the \"home\" setting and defaults to \"/\"\.
.
.SS "app\.set(name[, val])"
Apply an application level setting \fIname\fR to \fIval\fR, or get the value of \fIname\fR when \fIval\fR is not present:
.
.IP "" 4
.
.nf
app\.set(\'reload views\', 200);
app\.set(\'reload views\');
// => 200
.
.fi
.
.IP "" 0
.
.SS "app\.enable(name)"
Enable the given setting \fIname\fR:
.
.IP "" 4
.
.nf
app\.enable(\'some arbitrary setting\');
app\.set(\'some arbitrary setting\');
// => true
.
.fi
.
.IP "" 0
.
.SS "app\.disable(name)"
Disable the given setting \fIname\fR:
.
.IP "" 4
.
.nf
app\.disable(\'some setting\');
app\.set(\'some setting\');
// => false
.
.fi
.
.IP "" 0
.
.SS "app\.configure(env|function[, function])"
Define a callback function for the given \fIenv\fR (or all environments) with callback \fIfunction\fR:
.
.IP "" 4
.
.nf
app\.configure(function(){
// executed for each env
});
app\.configure(\'development\', function(){
// executed for \'development\' only
});
.
.fi
.
.IP "" 0
.
.SS "app\.redirect(name, val)"
For use with \fBres\.redirect()\fR we can map redirects at the application level as shown below:
.
.IP "" 4
.
.nf
app\.redirect(\'google\', \'http://google\.com\');
.
.fi
.
.IP "" 0
.
.P
Now in a route we may call:
.
.P
res\.redirect(\'google\');
.
.P
We may also map dynamic redirects:
.
.IP "" 4
.
.nf
app\.redirect(\'comments\', function(req, res, params){
return \'/post/\' + params\.id + \'/comments\';
});
.
.fi
.
.IP "" 0
.
.P
So now we may do the following, and the redirect will dynamically adjust to the context of the request\. If we called this route with \fIGET /post/12\fR our redirect \fILocation\fR would be \fI/post/12/comments\fR\.
.
.IP "" 4
.
.nf
app\.get(\'/post/:id\', function(req, res){
res\.redirect(\'comments\');
});
.
.fi
.
.IP "" 0
.
.SS "app\.error(function)"
Adds an error handler \fIfunction\fR which will receive the exception as the first parameter as shown below\. Note that we may set several error handlers by making several calls to this method, however the handler should call \fInext(err)\fR if it does not wish to deal with the exception:
.
.IP "" 4
.
.nf
app\.error(function(err, req, res, next){
res\.send(err\.message, 500);
});
.
.fi
.
.IP "" 0
.
.SS "app\.listen([port[, host]])"
Bind the app server to the given \fIport\fR, which defaults to 3000\. When \fIhost\fR is omitted all connections will be accepted via \fIINADDR_ANY\fR\.
.
.IP "" 4
.
.nf
app\.listen();
app\.listen(3000);
app\.listen(3000, \'n\.n\.n\.n\');
.
.fi
.
.IP "" 0
.
.P
The \fIport\fR argument may also be a string representing the path to a unix domain socket:
.
.IP "" 4
.
.nf
app\.listen(\'/tmp/express\.sock\');
.
.fi
.
.IP "" 0
.
.P
Then try it out:
.
.IP "" 4
.
.nf
$ telnet /tmp/express\.sock
GET / HTTP/1\.1
HTTP/1\.1 200 OK
Content\-Type: text/plain
Content\-Length: 11
Hello World
.
.fi
.
.IP "" 0
+787
Ver Arquivo
@@ -0,0 +1,787 @@
<html>
<head>
<title>Express - node web framework</title>
<style>
#header {
position: absolute;
top: 10px;
left: 0;
padding: 12px 0;
text-indent: 40px;
width: 100%;
border-top: 1px solid rgba(0,0,0,0.7);
border-bottom: 1px solid rgba(0,0,0,0.7);
background: rgba(255,255,255,0.1) url(http://www.sencha.com/favicon.ico) no-repeat 15px 50%;
text-align: left;
color: #fff;
}
#tagline {
margin-left: 75px;
margin-bottom: 30px;
color: rgba(255,255,255,0.7); }
html {
background: #1c1c1c url(images/bg.tile.jpg); }
body {
margin: 0;
padding-bottom: 30px;
font: 14px/1.4 "Helvetica Neue", "Lucida Grande", "Arial";
font-size: 14px;
line-height: 1.5;
-webkit-text-stroke: 1px rgba(0, 0, 0, 0.1);
-moz-text-stroke: 1px rgba(0, 0, 0, 0.1);
background: url(images/bg.jpg) 50% 0 no-repeat;
color: #8b8b8b; }
* {
outline: none; }
em {
color: white; }
a img {
border: none !important; }
a {
font-weight: bold;
text-decoration: none;
color: white;
-webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow;
-webkit-transition-duration: 0.15s;
-webkit-transition-timing-function: ease-out; }
a:hover {
opacity: 0.8; }
h1, h2, h3 {
margin: 45px 0 0 0;
color: white;
text-shadow: 1px 2px 2px rgba(0,0,0,0.6); }
h3 {
font-size: 18px; }
pre {
margin: 20px 10px;
padding: 25px 20px;
background: rgba(0,0,0,0.5);
border: 1px solid #323232;
-webkit-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-moz-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-webkit-border-radius: 5px;
-moz-border-radius: 5px; }
code {
font-family: "Helvetica Neue", "Lucida Grande", "Arial"; }
ul {
margin: 15px 0;
padding: 0 0 0 35px; }
ul li {
margin: 0;
padding: 2px 0;
list-style: square; }
.sect {
margin-left: 40px; }
#logo {
display: block;
margin-left: 30%;
margin-bottom: 30px;
width: 194px;
height: 51px;
background: url(images/logo.png) 0 0 no-repeat;
text-indent: -99999px; }
#logo:hover {
opacity: 0.7; }
#logo:active {
opacity: 0.3; }
#ribbon {
position: fixed;
top: 0;
right: 0;
z-index: 2; }
#wrapper {
width: 100%;
min-height: 800px;
background: url(images/top.png) 0 0 repeat-x; }
#container {
margin: 0 auto;
padding-top: 110px;
width: 550px; }
#toc {
position: fixed;
top: 60px;
left: 0;
margin: 0 0 0 15px;
padding: 15px;
height: 100%;
background: rgba(0,0,0,0.2);
border-right: 1px solid rgba(255,255,255,0.05);
}
#toc li {
padding: 1px 0;
list-style: none;
}
#toc li a {
font-size: 11px;
}
#menu {
margin-left: 65px;
padding: 0;
padding-bottom: 30px; }
#menu li {
display: inline;
list-style: none; }
#menu li a {
display: block;
float: left;
margin: 0 2px;
padding: 3px 15px;
background: rgba(0,0,0,0.2);
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
-webkit-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-moz-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-webkit-transition-property: opacity, -webkit-transform, color, background-color, -webkit-box-shadow;
-webkit-transition-duration: 0.15s;
-webkit-transition-timing-function: ease-out; }
#menu li a:hover,
#menu li a.active {
background: rgba(0,0,0,0.5); }
#menu li a:active {
background: rgba(0,0,0,0.1);
-webkit-box-shadow: 1px 1px 1px rgba(0,0,0,0.4);
-moz-box-shadow: 1px 1px 1px rgba(0,0,0,0.4); }
</style>
</head>
<body>
<a href='http://github.com/visionmedia/express'>
<img alt='Fork me on GitHub' id='ribbon' src='http://s3.amazonaws.com/github/ribbons/forkme_right_white_ffffff.png' />
</a>
<div id="header"><strong>Sencha</strong> labs</div>
<div id="wrapper">
<div id="container"><ul id="toc">
<li><a href="#Installation">Installation</a></li>
<li><a href="#Creating-An-Application">Creating An Application</a></li>
<li><a href="#Configuration">Configuration</a></li>
<li><a href="#Settings">Settings</a></li>
<li><a href="#Routing">Routing</a></li>
<li><a href="#Passing-Route-Control">Passing Route Control</a></li>
<li><a href="#Middleware">Middleware</a></li>
<li><a href="#Error-Handling">Error Handling</a></li>
<li><a href="#View-Rendering">View Rendering</a></li>
<li><a href="#View-Partials">View Partials</a></li>
<li><a href="#Template-Engines">Template Engines</a></li>
<li><a href="#req-header-key-defaultValue-">req.header()</a></li>
<li><a href="#req-accepts-type-">req.accepts()</a></li>
<li><a href="#req-param-name-">req.param()</a></li>
<li><a href="#req-flash-type-msg-">req.flash()</a></li>
<li><a href="#req-isXMLHttpRequest">req.isXMLHttpRequest</a></li>
<li><a href="#res-header-key-val-">res.header()</a></li>
<li><a href="#res-contentType-type-">res.contentType()</a></li>
<li><a href="#res-attachment-filename-">res.attachment()</a></li>
<li><a href="#res-sendfile-path-">res.sendfile()</a></li>
<li><a href="#res-download-file-filename-">res.download()</a></li>
<li><a href="#res-send-body-status-headers-status-status-">res.send()</a></li>
<li><a href="#res-redirect-url-status-">res.redirect()</a></li>
<li><a href="#app-set-name-val-">app.set()</a></li>
<li><a href="#app-enable-name-">app.enable()</a></li>
<li><a href="#app-disable-name-">app.disable()</a></li>
<li><a href="#app-configure-env-function-function-">app.configure()</a></li>
<li><a href="#app-redirect-name-val-">app.redirect()</a></li>
<li><a href="#app-error-function-">app.error()</a></li>
<li><a href="#app-listen-port-host-">app.listen()</a></li>
</ul>
<a href='http://github.com/visionmedia/express' id='logo'>Express</a>
<p id="tagline">
High performance, high class web development for
<a href="http://nodejs.org">Node.js</a>
</p>
<ul id="menu">
<li><a href="index.html">Home</a></li>
<li><a href="guide.html">Guide</a></li>
<li><a href="contrib.html">Contributing</a></li>
<li><a href="migrate.html">1.x Migration</a></li>
</ul>
<div class='mp'>
<h3 id="Installation">Installation</h3>
<p>npm:</p>
<pre><code>$ npm install connect
$ npm install express
</code></pre>
<p>curl (or similar):</p>
<pre><code>$ curl -# http://github.com/visionmedia/express/raw/master/install.sh | sh
</code></pre>
<p>git clone, first update the submodules:</p>
<pre><code>$ git submodule update --init
$ make install
$ make install-support
</code></pre>
<h3 id="Creating-An-Application">Creating An Application</h3>
<p>The <em>express.Server</em> now inherits from <em>http.Server</em>, however
follows the same idiom by providing <em>express.createServer()</em> as shown below. This means
that you can utilize Express server's transparently with other libraries.</p>
<pre><code>var app = require('express').createServer();
app.get('/', function(req, res){
res.send('hello world');
});
app.listen(3000);
</code></pre>
<h3 id="Configuration">Configuration</h3>
<p>Express supports arbitrary environments, such as <em>production</em> and <em>development</em>. Developers
can use the <em>configure()</em> method to setup needs required by the current environment. When
<em>configure()</em> is called without an environment name it will be run in <em>every</em> environment
prior to the environment specific callback.</p>
<p>In the example below we only <em>dumpExceptions</em>, and respond with exception stack traces
in <em>development</em> mode, however for both environments we utilize <em>methodOverride</em> and <em>bodyDecoder</em>.</p>
<pre><code>app.configure(function(){
app.use('/', connect.methodOverride());
app.use('/', connect.bodyDecoder());
});
app.configure('development', function(){
app.use('/', connect.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use('/', connect.errorHandler());
});
</code></pre>
<p>For internal and arbitrary settings Express provides the <em>set(key[, val])</em>, <em>enable(key)</em>, <em>disable(key)</em> methods:</p>
<pre><code>app.configure(function(){
app.set('views', __dirname + '/views');
app.set('views');
// =&gt; "... views directory ..."
app.enable('some feature');
// same as app.set('some feature', true);
app.disable('some feature');
// same as app.set('some feature', false);
});
</code></pre>
<p>To alter the environment we can set the <em>CONNECT_ENV</em> environment variable,
or more specifically <em>EXPRESS_ENV</em>, for example:</p>
<pre><code>$ EXPRESS_ENV=production node app.js
</code></pre>
<h3 id="Settings">Settings</h3>
<p>Express supports the following settings out of the box:</p>
<ul>
<li><em>env</em> Application environment set internally, use <em>app.set('env')</em> to utilize</li>
<li><em>home</em> Application base path used with <em>res.redirect()</em></li>
<li><em>views</em> Root views directory defaulting to <strong>CWD/views</strong></li>
<li><em>view engine</em> Default view engine name for views rendered without extensions</li>
<li><em>reload views</em> Reloads altered views, by default watches for <em>mtime</em> changes with
with a 5 minute interval. Example: <em>app.set('reload views', 60000);</em></li>
</ul>
<h3 id="Routing">Routing</h3>
<p>Express utilizes the HTTP verbs to provide a meaningful, expressive routing API.
For example we may want to render a user's account for the path <em>/user/12</em>, this
can be done by defining the route below. The values associated to the named placeholders,
are passed as the <em>third</em> argument, which here we name <em>params</em>.</p>
<pre><code>app.get('/user/:id', function(req, res, params){
res.send('user ' + params.id);
});
</code></pre>
<p>A route is simple a string which is compiled to a <em>RegExp</em> internally. For example
when <em>/user/:id</em> is compiled, a simplified version of the regexp may look similar to:</p>
<pre><code>\/user\/([^\/]+)\/?
</code></pre>
<p>Literal regular expressions may also be passed for complex uses:</p>
<pre><code>app.get(/^\/foo(bar)?$/, function(){});
</code></pre>
<p>Below are some route examples, and the associated paths that they
may consume:</p>
<pre><code> "/user/:id"
/user/12
"/users/:id?"
/users/5
/users
"/files/*"
/files/jquery.js
/files/javascripts/jquery.js
"/file/*.*"
/files/jquery.js
/files/javascripts/jquery.js
"/user/:id/:operation?"
/user/1
/user/1/edit
"/products.:format"
/products.json
/products.xml
"/products.:format?"
/products.json
/products.xml
/products
</code></pre>
<h3 id="Passing-Route-Control">Passing Route Control</h3>
<p>We may pass control to the next <em>matching</em> route, by calling the <em>fourth</em> parameter,
the <em>next()</em> function. When a match cannot be made, control is passed back to Connect.</p>
<pre><code>app.get('/users/:id?', function(req, res, params){
if (params.id) {
// do something
} else {
next();
}
});
app.get('/users', function(req, res, params){
// do something else
});
</code></pre>
<h3 id="Middleware">Middleware</h3>
<p>The Express <em>Plugin</em> is no more! middleware via <a href="http://github.com/extjs/Connect">Connect</a> can be
passed to <em>express.createServer()</em> as you would with a regular Connect server. For example:</p>
<pre><code>var connect = require('connect'),
express = require('express');
var app = express.createServer(
connect.logger(),
connect.bodyDecoder()
);
</code></pre>
<p>Alternatively we can <em>use()</em> them which is useful when adding middleware within <em>configure()</em> blocks:</p>
<pre><code>app.use('/', connect.logger({ format: ':method :uri' }));
</code></pre>
<h3 id="Error-Handling">Error Handling</h3>
<p>Express provides the <em>app.error()</em> method which receives exceptions thrown within a route,
or passed to <em>next(err)</em>. Below is an example which serves different pages based on our
ad-hoc <em>NotFound</em> exception:</p>
<pre><code>function NotFound(msg){
this.name = 'NotFound';
Error.call(this, msg);
Error.captureStackTrace(this, arguments.callee);
}
sys.inherits(NotFound, Error);
app.get('/404', function(req, res){
throw new NotFound;
});
app.get('/500', function(req, res){
throw new Error('keyboard cat!');
});
</code></pre>
<p>We can call <em>app.error()</em> several times as shown below.
Here we check for an instanceof <em>NotFound</em> and show the
404 page, or we pass on to the next error handler.</p>
<pre><code>app.error(function(err, req, res, next){
if (err instanceof NotFound) {
res.render('404.jade');
} else {
next(err);
}
});
</code></pre>
<p>Here we assume all errors as 500 for the simplicity of
this demo, however you can choose whatever you like</p>
<pre><code>app.error(function(err, req, res){
res.render('500.jade', {
locals: {
error: err
}
});
});
</code></pre>
<p>Our apps could also utilize the Connect <em>errorHandler</em> middleware
to report on exceptions. For example if we wish to output exceptions
in "development" mode to <em>stderr</em> we can use:</p>
<pre><code>app.use('/', connect.errorHandler({ dumpExceptions: true }));
</code></pre>
<p>Also during development we may want fancy html pages to show exceptions
that are passed or thrown, so we can set <em>showStack</em> to true:</p>
<pre><code>app.use('/', connect.errorHandler({ showStack: true, dumpExceptions: true }));
</code></pre>
<p>The <em>errorHandler</em> middleware also responds with <em>json</em> if <em>Accept: application/json</em>
is present, which is useful for developing apps that rely heavily on client-side JavaScript.</p>
<h3 id="View-Rendering">View Rendering</h3>
<p>View filenames take the form <em>Express</em>.<em>ENGINE</em>, where <em>ENGINE</em> is the name
of the module that will be required. For example the view <em>layout.ejs</em> will
tell the view system to <em>require('ejs')</em>, the module being loaded must (currently)
export the method <em>exports.render(str, options)</em> to comply with Express, however
with will likely be extensible in the future.</p>
<p>Below is an example using <a href="http://github.com/visionmedia/haml.js">Haml.js</a> to render <em>index.html</em>,
and since we do not use <em>layout: false</em> the rendered contents of <em>index.html</em> will be passed as
the <em>body</em> local variable in <em>layout.haml</em>.</p>
<pre><code>app.get('/', function(req, res){
res.render('index.haml', {
locals: { title: 'My Site' }
});
});
</code></pre>
<h3 id="View-Partials">View Partials</h3>
<p>The Express view system has built-in support for partials and collections, which are
sort of "mini" views representing a document fragment. For example rather than iterating
in a view to display comments, we would use a partial with collection support:</p>
<pre><code>partial('comment.haml', { collection: comments });
</code></pre>
<p>To make things even less verbose we can assume the extension as <em>.haml</em> when omitted,
however if we wished we could use an ejs partial, within a haml view for example.</p>
<pre><code>partial('comment', { collection: comments });
</code></pre>
<p>And once again even further, when rendering a collection we can simply pass
an array, if no other options are desired:</p>
<pre><code>partial('comments', comments);
</code></pre>
<h3 id="Template-Engines">Template Engines</h3>
<p>Below are a few template engines commonly used with Express:</p>
<ul>
<li><a href="http://github.com/visionmedia/jade">Jade</a> haml.js successor</li>
<li><a href="http://github.com/visionmedia/haml.js">Haml</a> indented templates</li>
<li><a href="http://github.com/visionmedia/ejs">EJS</a> Embedded JavaScript</li>
</ul>
<h3 id="req-header-key-defaultValue-">req.header(key[, defaultValue])</h3>
<p>Get the case-insensitive request header <em>key</em>, with optional <em>defaultValue</em>:</p>
<pre><code>req.header('Host');
req.header('host');
req.header('Accept', '*/*');
</code></pre>
<h3 id="req-accepts-type-">req.accepts(type)</h3>
<p>Check if the <em>Accept</em> header is present, and includes the given <em>type</em>.</p>
<p>When the <em>Accept</em> header is not present <em>true</em> is returned. Otherwise
the given <em>type</em> is matched by an exact match, and then subtypes. You
may pass the subtype such as "html" which is then converted internally
to "text/html" using the mime lookup table.</p>
<pre><code>// Accept: text/html
req.accepts('html');
// =&gt; true
// Accept: text/*; application/json
req.accepts('html');
req.accepts('text/html');
req.accepts('text/plain');
req.accepts('application/json');
// =&gt; true
req.accepts('image/png');
req.accepts('png');
// =&gt; false
</code></pre>
<h3 id="req-param-name-">req.param(name)</h3>
<p>Return the value of param <em>name</em> when present.</p>
<ul>
<li>Checks route placeholders, ex: /user/:id</li>
<li>Checks query string params, ex: ?id=12</li>
<li>Checks urlencoded body params, ex: id=12</li>
</ul>
<p>To utilize urlencoded request bodies, <em>req.body</em>
should be an object. This can be done by using
the <em>connect.bodyDecoder</em> middleware.</p>
<h3 id="req-flash-type-msg-">req.flash(type[, msg])</h3>
<p>Queue flash <em>msg</em> of the given <em>type</em>.</p>
<pre><code>req.flash('info', 'email sent');
req.flash('error', 'email delivery failed');
req.flash('info', 'email re-sent');
// =&gt; 2
req.flash('info');
// =&gt; ['email sent', 'email re-sent']
req.flash('info');
// =&gt; []
req.flash();
// =&gt; { error: ['email delivery failed'], info: [] }
</code></pre>
<h3 id="req-isXMLHttpRequest">req.isXMLHttpRequest</h3>
<p>Also aliased as <em>req.xhr</em>, this getter checks the <em>X-Requested-With</em> header
to see if it was issued by an <em>XMLHttpRequest</em>:</p>
<pre><code>req.xhr
req.isXMLHttpRequest
</code></pre>
<h3 id="res-header-key-val-">res.header(key[, val])</h3>
<p>Get or set the response header <em>key</em>.</p>
<pre><code>res.header('Content-Length');
// =&gt; undefined
res.header('Content-Length', 123);
// =&gt; 123
res.header('Content-Length');
// =&gt; 123
</code></pre>
<h3 id="res-contentType-type-">res.contentType(type)</h3>
<p>Sets the <em>Content-Type</em> response header to the given <em>type</em>.</p>
<pre><code> var filename = 'path/to/image.png';
res.contentType(filename);
// res.headers['Content-Type'] is now "image/png"
</code></pre>
<h3 id="res-attachment-filename-">res.attachment([filename])</h3>
<p>Sets the <em>Content-Disposition</em> response header to "attachment", with optional <em>filename</em>.</p>
<pre><code> res.attachment('path/to/my/image.png');
</code></pre>
<h3 id="res-sendfile-path-">res.sendfile(path)</h3>
<p>Used by <code>res.download()</code> to transfer an arbitrary file.</p>
<pre><code>res.sendfile('path/to/my.file');
</code></pre>
<p><strong>NOTE</strong>: this is <em>not</em> a replacement for Connect's <em>staticProvider</em> middleware,
nor does it perform any security checks, use with caution when using in a dynamic manor.</p>
<h3 id="res-download-file-filename-">res.download(file[, filename])</h3>
<p>Transfer the given <em>file</em> as an attachment with optional alternative <em>filename</em>.</p>
<pre><code>res.download('path/to/image.png');
res.download('path/to/image.png', 'foo.png');
</code></pre>
<p>This is equivalent to:</p>
<pre><code>res.attachment(file);
res.sendfile(file);
</code></pre>
<h3 id="res-send-body-status-headers-status-status-">res.send(body|status[, headers|status[, status]])</h3>
<p>The <code>res.send()</code> method is a high level response utility allowing you to pass
objects to respond with json, strings for html, arbitrary _Buffer_s or numbers for status
code based responses. The following are all valid uses:</p>
<pre><code> res.send(new Buffer('wahoo'));
res.send({ some: 'json' });
res.send('&lt;p&gt;some html&lt;/p&gt;');
res.send('Sorry, cant find that', 404);
res.send('text', { 'Content-Type': 'text/plain' }, 201);
res.send(404);
</code></pre>
<p>By default the <em>Content-Type</em> response header is set, however if explicitly
assigned through <code>res.send()</code> or previously with <code>res.header()</code> or <code>res.contentType()</code>
it will not be set again.</p>
<h3 id="res-redirect-url-status-">res.redirect(url[, status])</h3>
<p>Redirect to the given <em>url</em> with a default response <em>status</em> of 302.</p>
<pre><code>res.redirect('/', 301);
res.redirect('/account');
res.redirect('http://google.com');
res.redirect('home');
res.redirect('back');
</code></pre>
<p>Express supports "redirect mapping", which by default provides <em>home</em>, and <em>back</em>.
The <em>back</em> map checks the <em>Referrer</em> and <em>Referer</em> headers, while <em>home</em> utilizes
the "home" setting and defaults to "/".</p>
<h3 id="app-set-name-val-">app.set(name[, val])</h3>
<p>Apply an application level setting <em>name</em> to <em>val</em>, or
get the value of <em>name</em> when <em>val</em> is not present:</p>
<pre><code>app.set('reload views', 200);
app.set('reload views');
// =&gt; 200
</code></pre>
<h3 id="app-enable-name-">app.enable(name)</h3>
<p>Enable the given setting <em>name</em>:</p>
<pre><code>app.enable('some arbitrary setting');
app.set('some arbitrary setting');
// =&gt; true
</code></pre>
<h3 id="app-disable-name-">app.disable(name)</h3>
<p>Disable the given setting <em>name</em>:</p>
<pre><code>app.disable('some setting');
app.set('some setting');
// =&gt; false
</code></pre>
<h3 id="app-configure-env-function-function-">app.configure(env|function[, function])</h3>
<p>Define a callback function for the given <em>env</em> (or all environments) with callback <em>function</em>:</p>
<pre><code>app.configure(function(){
// executed for each env
});
app.configure('development', function(){
// executed for 'development' only
});
</code></pre>
<h3 id="app-redirect-name-val-">app.redirect(name, val)</h3>
<p>For use with <code>res.redirect()</code> we can map redirects at the application level as shown below:</p>
<pre><code>app.redirect('google', 'http://google.com');
</code></pre>
<p>Now in a route we may call:</p>
<p> res.redirect('google');</p>
<p>We may also map dynamic redirects:</p>
<pre><code>app.redirect('comments', function(req, res, params){
return '/post/' + params.id + '/comments';
});
</code></pre>
<p>So now we may do the following, and the redirect will dynamically adjust to
the context of the request. If we called this route with <em>GET /post/12</em> our
redirect <em>Location</em> would be <em>/post/12/comments</em>.</p>
<pre><code>app.get('/post/:id', function(req, res){
res.redirect('comments');
});
</code></pre>
<h3 id="app-error-function-">app.error(function)</h3>
<p>Adds an error handler <em>function</em> which will receive the exception as the first parameter as shown below.
Note that we may set several error handlers by making several calls to this method, however the handler
should call <em>next(err)</em> if it does not wish to deal with the exception:</p>
<pre><code>app.error(function(err, req, res, next){
res.send(err.message, 500);
});
</code></pre>
<h3 id="app-listen-port-host-">app.listen([port[, host]])</h3>
<p>Bind the app server to the given <em>port</em>, which defaults to 3000. When <em>host</em> is omitted all
connections will be accepted via <em>INADDR_ANY</em>.</p>
<pre><code>app.listen();
app.listen(3000);
app.listen(3000, 'n.n.n.n');
</code></pre>
<p>The <em>port</em> argument may also be a string representing the path to a unix domain socket:</p>
<pre><code>app.listen('/tmp/express.sock');
</code></pre>
<p>Then try it out:</p>
<pre><code>$ telnet /tmp/express.sock
GET / HTTP/1.1
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 11
Hello World
</code></pre>
</div>
</div>
</div>
</body>
</html>
+516
Ver Arquivo
@@ -0,0 +1,516 @@
### Installation
npm:
$ npm install connect
$ npm install express
curl (or similar):
$ curl -# http://github.com/visionmedia/express/raw/master/install.sh | sh
git clone, first update the submodules:
$ git submodule update --init
$ make install
$ make install-support
### Creating An Application
The _express.Server_ now inherits from _http.Server_, however
follows the same idiom by providing _express.createServer()_ as shown below. This means
that you can utilize Express server's transparently with other libraries.
var app = require('express').createServer();
app.get('/', function(req, res){
res.send('hello world');
});
app.listen(3000);
### Configuration
Express supports arbitrary environments, such as _production_ and _development_. Developers
can use the _configure()_ method to setup needs required by the current environment. When
_configure()_ is called without an environment name it will be run in _every_ environment
prior to the environment specific callback.
In the example below we only _dumpExceptions_, and respond with exception stack traces
in _development_ mode, however for both environments we utilize _methodOverride_ and _bodyDecoder_.
app.configure(function(){
app.use('/', connect.methodOverride());
app.use('/', connect.bodyDecoder());
});
app.configure('development', function(){
app.use('/', connect.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use('/', connect.errorHandler());
});
For internal and arbitrary settings Express provides the _set(key[, val])_, _enable(key)_, _disable(key)_ methods:
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('views');
// => "... views directory ..."
app.enable('some feature');
// same as app.set('some feature', true);
app.disable('some feature');
// same as app.set('some feature', false);
});
To alter the environment we can set the _CONNECT_ENV_ environment variable,
or more specifically _EXPRESS_ENV_, for example:
$ EXPRESS_ENV=production node app.js
### Settings
Express supports the following settings out of the box:
* _env_ Application environment set internally, use _app.set('env')_ to utilize
* _home_ Application base path used with _res.redirect()_
* _views_ Root views directory defaulting to **CWD/views**
* _view engine_ Default view engine name for views rendered without extensions
* _reload views_ Reloads altered views, by default watches for _mtime_ changes with
with a 5 minute interval. Example: _app.set('reload views', 60000);_
### Routing
Express utilizes the HTTP verbs to provide a meaningful, expressive routing API.
For example we may want to render a user's account for the path _/user/12_, this
can be done by defining the route below. The values associated to the named placeholders,
are passed as the _third_ argument, which here we name _params_.
app.get('/user/:id', function(req, res, params){
res.send('user ' + params.id);
});
A route is simple a string which is compiled to a _RegExp_ internally. For example
when _/user/:id_ is compiled, a simplified version of the regexp may look similar to:
\/user\/([^\/]+)\/?
Literal regular expressions may also be passed for complex uses:
app.get(/^\/foo(bar)?$/, function(){});
Below are some route examples, and the associated paths that they
may consume:
"/user/:id"
/user/12
"/users/:id?"
/users/5
/users
"/files/*"
/files/jquery.js
/files/javascripts/jquery.js
"/file/*.*"
/files/jquery.js
/files/javascripts/jquery.js
"/user/:id/:operation?"
/user/1
/user/1/edit
"/products.:format"
/products.json
/products.xml
"/products.:format?"
/products.json
/products.xml
/products
### Passing Route Control
We may pass control to the next _matching_ route, by calling the _fourth_ parameter,
the _next()_ function. When a match cannot be made, control is passed back to Connect.
app.get('/users/:id?', function(req, res, params){
if (params.id) {
// do something
} else {
next();
}
});
app.get('/users', function(req, res, params){
// do something else
});
### Middleware
The Express _Plugin_ is no more! middleware via [Connect](http://github.com/extjs/Connect) can be
passed to _express.createServer()_ as you would with a regular Connect server. For example:
var connect = require('connect'),
express = require('express');
var app = express.createServer(
connect.logger(),
connect.bodyDecoder()
);
Alternatively we can _use()_ them which is useful when adding middleware within _configure()_ blocks:
app.use('/', connect.logger({ format: ':method :uri' }));
### Error Handling
Express provides the _app.error()_ method which receives exceptions thrown within a route,
or passed to _next(err)_. Below is an example which serves different pages based on our
ad-hoc _NotFound_ exception:
function NotFound(msg){
this.name = 'NotFound';
Error.call(this, msg);
Error.captureStackTrace(this, arguments.callee);
}
sys.inherits(NotFound, Error);
app.get('/404', function(req, res){
throw new NotFound;
});
app.get('/500', function(req, res){
throw new Error('keyboard cat!');
});
We can call _app.error()_ several times as shown below.
Here we check for an instanceof _NotFound_ and show the
404 page, or we pass on to the next error handler.
app.error(function(err, req, res, next){
if (err instanceof NotFound) {
res.render('404.jade');
} else {
next(err);
}
});
Here we assume all errors as 500 for the simplicity of
this demo, however you can choose whatever you like
app.error(function(err, req, res){
res.render('500.jade', {
locals: {
error: err
}
});
});
Our apps could also utilize the Connect _errorHandler_ middleware
to report on exceptions. For example if we wish to output exceptions
in "development" mode to _stderr_ we can use:
app.use('/', connect.errorHandler({ dumpExceptions: true }));
Also during development we may want fancy html pages to show exceptions
that are passed or thrown, so we can set _showStack_ to true:
app.use('/', connect.errorHandler({ showStack: true, dumpExceptions: true }));
The _errorHandler_ middleware also responds with _json_ if _Accept: application/json_
is present, which is useful for developing apps that rely heavily on client-side JavaScript.
### View Rendering
View filenames take the form _NAME_._ENGINE_, where _ENGINE_ is the name
of the module that will be required. For example the view _layout.ejs_ will
tell the view system to _require('ejs')_, the module being loaded must (currently)
export the method _exports.render(str, options)_ to comply with Express, however
with will likely be extensible in the future.
Below is an example using [Haml.js](http://github.com/visionmedia/haml.js) to render _index.html_,
and since we do not use _layout: false_ the rendered contents of _index.html_ will be passed as
the _body_ local variable in _layout.haml_.
app.get('/', function(req, res){
res.render('index.haml', {
locals: { title: 'My Site' }
});
});
### View Partials
The Express view system has built-in support for partials and collections, which are
sort of "mini" views representing a document fragment. For example rather than iterating
in a view to display comments, we would use a partial with collection support:
partial('comment.haml', { collection: comments });
To make things even less verbose we can assume the extension as _.haml_ when omitted,
however if we wished we could use an ejs partial, within a haml view for example.
partial('comment', { collection: comments });
And once again even further, when rendering a collection we can simply pass
an array, if no other options are desired:
partial('comments', comments);
### Template Engines
Below are a few template engines commonly used with Express:
* [Jade](http://github.com/visionmedia/jade) haml.js successor
* [Haml](http://github.com/visionmedia/haml.js) indented templates
* [EJS](http://github.com/visionmedia/ejs) Embedded JavaScript
### req.header(key[, defaultValue])
Get the case-insensitive request header _key_, with optional _defaultValue_:
req.header('Host');
req.header('host');
req.header('Accept', '*/*');
### req.accepts(type)
Check if the _Accept_ header is present, and includes the given _type_.
When the _Accept_ header is not present _true_ is returned. Otherwise
the given _type_ is matched by an exact match, and then subtypes. You
may pass the subtype such as "html" which is then converted internally
to "text/html" using the mime lookup table.
// Accept: text/html
req.accepts('html');
// => true
// Accept: text/*; application/json
req.accepts('html');
req.accepts('text/html');
req.accepts('text/plain');
req.accepts('application/json');
// => true
req.accepts('image/png');
req.accepts('png');
// => false
### req.param(name)
Return the value of param _name_ when present.
- Checks route placeholders, ex: /user/:id
- Checks query string params, ex: ?id=12
- Checks urlencoded body params, ex: id=12
To utilize urlencoded request bodies, _req.body_
should be an object. This can be done by using
the _connect.bodyDecoder_ middleware.
### req.flash(type[, msg])
Queue flash _msg_ of the given _type_.
req.flash('info', 'email sent');
req.flash('error', 'email delivery failed');
req.flash('info', 'email re-sent');
// => 2
req.flash('info');
// => ['email sent', 'email re-sent']
req.flash('info');
// => []
req.flash();
// => { error: ['email delivery failed'], info: [] }
### req.isXMLHttpRequest
Also aliased as _req.xhr_, this getter checks the _X-Requested-With_ header
to see if it was issued by an _XMLHttpRequest_:
req.xhr
req.isXMLHttpRequest
### res.header(key[, val])
Get or set the response header _key_.
res.header('Content-Length');
// => undefined
res.header('Content-Length', 123);
// => 123
res.header('Content-Length');
// => 123
### res.contentType(type)
Sets the _Content-Type_ response header to the given _type_.
var filename = 'path/to/image.png';
res.contentType(filename);
// res.headers['Content-Type'] is now "image/png"
### res.attachment([filename])
Sets the _Content-Disposition_ response header to "attachment", with optional _filename_.
res.attachment('path/to/my/image.png');
### res.sendfile(path)
Used by `res.download()` to transfer an arbitrary file.
res.sendfile('path/to/my.file');
**NOTE**: this is _not_ a replacement for Connect's _staticProvider_ middleware,
nor does it perform any security checks, use with caution when using in a dynamic manor.
### res.download(file[, filename])
Transfer the given _file_ as an attachment with optional alternative _filename_.
res.download('path/to/image.png');
res.download('path/to/image.png', 'foo.png');
This is equivalent to:
res.attachment(file);
res.sendfile(file);
### res.send(body|status[, headers|status[, status]])
The `res.send()` method is a high level response utility allowing you to pass
objects to respond with json, strings for html, arbitrary _Buffer_s or numbers for status
code based responses. The following are all valid uses:
res.send(new Buffer('wahoo'));
res.send({ some: 'json' });
res.send('<p>some html</p>');
res.send('Sorry, cant find that', 404);
res.send('text', { 'Content-Type': 'text/plain' }, 201);
res.send(404);
By default the _Content-Type_ response header is set, however if explicitly
assigned through `res.send()` or previously with `res.header()` or `res.contentType()`
it will not be set again.
### res.redirect(url[, status])
Redirect to the given _url_ with a default response _status_ of 302.
res.redirect('/', 301);
res.redirect('/account');
res.redirect('http://google.com');
res.redirect('home');
res.redirect('back');
Express supports "redirect mapping", which by default provides _home_, and _back_.
The _back_ map checks the _Referrer_ and _Referer_ headers, while _home_ utilizes
the "home" setting and defaults to "/".
### app.set(name[, val])
Apply an application level setting _name_ to _val_, or
get the value of _name_ when _val_ is not present:
app.set('reload views', 200);
app.set('reload views');
// => 200
### app.enable(name)
Enable the given setting _name_:
app.enable('some arbitrary setting');
app.set('some arbitrary setting');
// => true
### app.disable(name)
Disable the given setting _name_:
app.disable('some setting');
app.set('some setting');
// => false
### app.configure(env|function[, function])
Define a callback function for the given _env_ (or all environments) with callback _function_:
app.configure(function(){
// executed for each env
});
app.configure('development', function(){
// executed for 'development' only
});
### app.redirect(name, val)
For use with `res.redirect()` we can map redirects at the application level as shown below:
app.redirect('google', 'http://google.com');
Now in a route we may call:
res.redirect('google');
We may also map dynamic redirects:
app.redirect('comments', function(req, res, params){
return '/post/' + params.id + '/comments';
});
So now we may do the following, and the redirect will dynamically adjust to
the context of the request. If we called this route with _GET /post/12_ our
redirect _Location_ would be _/post/12/comments_.
app.get('/post/:id', function(req, res){
res.redirect('comments');
});
### app.error(function)
Adds an error handler _function_ which will receive the exception as the first parameter as shown below.
Note that we may set several error handlers by making several calls to this method, however the handler
should call _next(err)_ if it does not wish to deal with the exception:
app.error(function(err, req, res, next){
res.send(err.message, 500);
});
### app.listen([port[, host]])
Bind the app server to the given _port_, which defaults to 3000. When _host_ is omitted all
connections will be accepted via _INADDR_ANY_.
app.listen();
app.listen(3000);
app.listen(3000, 'n.n.n.n');
The _port_ argument may also be a string representing the path to a unix domain socket:
app.listen('/tmp/express.sock');
Then try it out:
$ telnet /tmp/express.sock
GET / HTTP/1.1
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 11
Hello World
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 108 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 7.0 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 7.2 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 143 B

+85
Ver Arquivo
@@ -0,0 +1,85 @@
.\" generated with Ronn/v0.6.6
.\" http://github.com/rtomayko/ronn/
.
.TH "INDEX" "" "July 2010" "" ""
.
.IP "" 4
.
.nf
var app = express\.createServer();
app\.get(\'/\', function(req, res){
res\.send(\'Hello World\');
});
app\.listen(3000);
.
.fi
.
.IP "" 0
.
.SH "Features"
.
.IP "\(bu" 4
Robust routing
.
.IP "\(bu" 4
Redirection helpers
.
.IP "\(bu" 4
Focus on high performance
.
.IP "\(bu" 4
View rendering and partials support
.
.IP "\(bu" 4
Environment based configuration
.
.IP "\(bu" 4
Session based flash notifications
.
.IP "\(bu" 4
Built on Connect \fIhttp://extjs\.github\.com/Connect\fR
.
.IP "\(bu" 4
Executable \fIexecutable\.html\fR for generating applications quickly
.
.IP "" 0
.
.SH "Contributors"
The following are the major contributors of Express (in no specific order)\.
.
.IP "\(bu" 4
TJ Holowaychuk (visionmedia \fIhttp://github\.com/visionmedia\fR)
.
.IP "\(bu" 4
Ciaran Jessup (ciaranj \fIhttp://github\.com/ciaranj\fR)
.
.IP "\(bu" 4
Aaron Heckmann (aheckmann \fIhttp://github\.com/aheckmann\fR)
.
.IP "" 0
.
.SH "More Information"
.
.IP "\(bu" 4
Google Group \fIhttp://groups\.google\.com/group/express\-js\fR for discussion
.
.IP "\(bu" 4
Follow tjholowaychuk \fIhttp://twitter\.com/tjholowaychuk\fR on twitter for updates
.
.IP "\(bu" 4
Annotated source documentation \fIapi\.html\fR
.
.IP "\(bu" 4
View the source \fIhttp://github\.com/visionmedia/express\fR
.
.IP "\(bu" 4
View the Connect \fIhttp://github\.com/extjs/Connect\fR repo for middleware usage
.
.IP "\(bu" 4
View the Connect Wiki \fIhttp://wiki\.github\.com/extjs/Connect/\fR for contrib middleware
.
.IP "" 0
+231
Ver Arquivo
@@ -0,0 +1,231 @@
<html>
<head>
<title>Express - node web framework</title>
<style>
#header {
position: absolute;
top: 10px;
left: 0;
padding: 12px 0;
text-indent: 40px;
width: 100%;
border-top: 1px solid rgba(0,0,0,0.7);
border-bottom: 1px solid rgba(0,0,0,0.7);
background: rgba(255,255,255,0.1) url(http://www.sencha.com/favicon.ico) no-repeat 15px 50%;
text-align: left;
color: #fff;
}
#tagline {
margin-left: 75px;
margin-bottom: 30px;
color: rgba(255,255,255,0.7); }
html {
background: #1c1c1c url(images/bg.tile.jpg); }
body {
margin: 0;
padding-bottom: 30px;
font: 14px/1.4 "Helvetica Neue", "Lucida Grande", "Arial";
font-size: 14px;
line-height: 1.5;
-webkit-text-stroke: 1px rgba(0, 0, 0, 0.1);
-moz-text-stroke: 1px rgba(0, 0, 0, 0.1);
background: url(images/bg.jpg) 50% 0 no-repeat;
color: #8b8b8b; }
* {
outline: none; }
em {
color: white; }
a img {
border: none !important; }
a {
font-weight: bold;
text-decoration: none;
color: white;
-webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow;
-webkit-transition-duration: 0.15s;
-webkit-transition-timing-function: ease-out; }
a:hover {
opacity: 0.8; }
h1, h2, h3 {
margin: 45px 0 0 0;
color: white;
text-shadow: 1px 2px 2px rgba(0,0,0,0.6); }
h3 {
font-size: 18px; }
pre {
margin: 20px 10px;
padding: 25px 20px;
background: rgba(0,0,0,0.5);
border: 1px solid #323232;
-webkit-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-moz-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-webkit-border-radius: 5px;
-moz-border-radius: 5px; }
code {
font-family: "Helvetica Neue", "Lucida Grande", "Arial"; }
ul {
margin: 15px 0;
padding: 0 0 0 35px; }
ul li {
margin: 0;
padding: 2px 0;
list-style: square; }
.sect {
margin-left: 40px; }
#logo {
display: block;
margin-left: 30%;
margin-bottom: 30px;
width: 194px;
height: 51px;
background: url(images/logo.png) 0 0 no-repeat;
text-indent: -99999px; }
#logo:hover {
opacity: 0.7; }
#logo:active {
opacity: 0.3; }
#ribbon {
position: fixed;
top: 0;
right: 0;
z-index: 2; }
#wrapper {
width: 100%;
min-height: 800px;
background: url(images/top.png) 0 0 repeat-x; }
#container {
margin: 0 auto;
padding-top: 110px;
width: 550px; }
#toc {
position: fixed;
top: 60px;
left: 0;
margin: 0 0 0 15px;
padding: 15px;
height: 100%;
background: rgba(0,0,0,0.2);
border-right: 1px solid rgba(255,255,255,0.05);
}
#toc li {
padding: 1px 0;
list-style: none;
}
#toc li a {
font-size: 11px;
}
#menu {
margin-left: 65px;
padding: 0;
padding-bottom: 30px; }
#menu li {
display: inline;
list-style: none; }
#menu li a {
display: block;
float: left;
margin: 0 2px;
padding: 3px 15px;
background: rgba(0,0,0,0.2);
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
-webkit-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-moz-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-webkit-transition-property: opacity, -webkit-transform, color, background-color, -webkit-box-shadow;
-webkit-transition-duration: 0.15s;
-webkit-transition-timing-function: ease-out; }
#menu li a:hover,
#menu li a.active {
background: rgba(0,0,0,0.5); }
#menu li a:active {
background: rgba(0,0,0,0.1);
-webkit-box-shadow: 1px 1px 1px rgba(0,0,0,0.4);
-moz-box-shadow: 1px 1px 1px rgba(0,0,0,0.4); }
</style>
</head>
<body>
<a href='http://github.com/visionmedia/express'>
<img alt='Fork me on GitHub' id='ribbon' src='http://s3.amazonaws.com/github/ribbons/forkme_right_white_ffffff.png' />
</a>
<div id="header"><strong>Sencha</strong> labs</div>
<div id="wrapper">
<div id="container">
<a href='http://github.com/visionmedia/express' id='logo'>Express</a>
<p id="tagline">
High performance, high class web development for
<a href="http://nodejs.org">Node.js</a>
</p>
<ul id="menu">
<li><a href="index.html">Home</a></li>
<li><a href="guide.html">Guide</a></li>
<li><a href="contrib.html">Contributing</a></li>
<li><a href="migrate.html">1.x Migration</a></li>
</ul>
<div class='mp'>
<pre><code>var app = express.createServer();
app.get('/', function(req, res){
res.send('Hello World');
});
app.listen(3000);
</code></pre>
<h2 id="Features">Features</h2>
<ul>
<li>Robust routing</li>
<li>Redirection helpers</li>
<li>Focus on high performance</li>
<li>View rendering and partials support</li>
<li>Environment based configuration</li>
<li>Session based flash notifications</li>
<li>Built on <a href="http://extjs.github.com/Connect">Connect</a></li>
<li><a href="executable.html">Executable</a> for generating applications quickly</li>
</ul>
<h2 id="Contributors">Contributors</h2>
<p>The following are the major contributors of Express (in no specific order).</p>
<ul>
<li>TJ Holowaychuk (<a href="http://github.com/visionmedia">visionmedia</a>)</li>
<li>Ciaran Jessup (<a href="http://github.com/ciaranj">ciaranj</a>)</li>
<li>Aaron Heckmann (<a href="http://github.com/aheckmann">aheckmann</a>)</li>
</ul>
<h2 id="More-Information">More Information</h2>
<ul>
<li><a href="http://groups.google.com/group/express-js">Google Group</a> for discussion</li>
<li>Follow <a href="http://twitter.com/tjholowaychuk">tjholowaychuk</a> on twitter for updates</li>
<li>Annotated source <a href="api.html">documentation</a></li>
<li>View the <a href="http://github.com/visionmedia/express">source</a></li>
<li>View the <a href="http://github.com/extjs/Connect">Connect</a> repo for middleware usage</li>
<li>View the <a href="http://wiki.github.com/extjs/Connect/">Connect Wiki</a> for contrib middleware</li>
</ul>
</div>
</div>
</div>
</body>
</html>
+36
Ver Arquivo
@@ -0,0 +1,36 @@
var app = express.createServer();
app.get('/', function(req, res){
res.send('Hello World');
});
app.listen(3000);
## Features
* Robust routing
* Redirection helpers
* Focus on high performance
* View rendering and partials support
* Environment based configuration
* Session based flash notifications
* Built on [Connect](http://extjs.github.com/Connect)
* [Executable](executable.html) for generating applications quickly
## Contributors
The following are the major contributors of Express (in no specific order).
* TJ Holowaychuk ([visionmedia](http://github.com/visionmedia))
* Ciaran Jessup ([ciaranj](http://github.com/ciaranj))
* Aaron Heckmann ([aheckmann](http://github.com/aheckmann))
## More Information
* [Google Group](http://groups.google.com/group/express-js) for discussion
* Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) on twitter for updates
* Annotated source [documentation](api.html)
* View the [source](http://github.com/visionmedia/express)
* View the [Connect](http://github.com/extjs/Connect) repo for middleware usage
* View the [Connect Wiki](http://wiki.github.com/extjs/Connect/) for contrib middleware
+4
Ver Arquivo
@@ -0,0 +1,4 @@
</div>
</div>
</body>
</html>
+179
Ver Arquivo
@@ -0,0 +1,179 @@
<html>
<head>
<title>Express - node web framework</title>
<style>
#header {
position: absolute;
top: 10px;
left: 0;
padding: 12px 0;
text-indent: 40px;
width: 100%;
border-top: 1px solid rgba(0,0,0,0.7);
border-bottom: 1px solid rgba(0,0,0,0.7);
background: rgba(255,255,255,0.1) url(http://www.sencha.com/favicon.ico) no-repeat 15px 50%;
text-align: left;
color: #fff;
}
#tagline {
margin-left: 75px;
margin-bottom: 30px;
color: rgba(255,255,255,0.7); }
html {
background: #1c1c1c url(images/bg.tile.jpg); }
body {
margin: 0;
padding-bottom: 30px;
font: 14px/1.4 "Helvetica Neue", "Lucida Grande", "Arial";
font-size: 14px;
line-height: 1.5;
-webkit-text-stroke: 1px rgba(0, 0, 0, 0.1);
-moz-text-stroke: 1px rgba(0, 0, 0, 0.1);
background: url(images/bg.jpg) 50% 0 no-repeat;
color: #8b8b8b; }
* {
outline: none; }
em {
color: white; }
a img {
border: none !important; }
a {
font-weight: bold;
text-decoration: none;
color: white;
-webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow;
-webkit-transition-duration: 0.15s;
-webkit-transition-timing-function: ease-out; }
a:hover {
opacity: 0.8; }
h1, h2, h3 {
margin: 45px 0 0 0;
color: white;
text-shadow: 1px 2px 2px rgba(0,0,0,0.6); }
h3 {
font-size: 18px; }
pre {
margin: 20px 10px;
padding: 25px 20px;
background: rgba(0,0,0,0.5);
border: 1px solid #323232;
-webkit-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-moz-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-webkit-border-radius: 5px;
-moz-border-radius: 5px; }
code {
font-family: "Helvetica Neue", "Lucida Grande", "Arial"; }
ul {
margin: 15px 0;
padding: 0 0 0 35px; }
ul li {
margin: 0;
padding: 2px 0;
list-style: square; }
.sect {
margin-left: 40px; }
#logo {
display: block;
margin-left: 30%;
margin-bottom: 30px;
width: 194px;
height: 51px;
background: url(images/logo.png) 0 0 no-repeat;
text-indent: -99999px; }
#logo:hover {
opacity: 0.7; }
#logo:active {
opacity: 0.3; }
#ribbon {
position: fixed;
top: 0;
right: 0;
z-index: 2; }
#wrapper {
width: 100%;
min-height: 800px;
background: url(images/top.png) 0 0 repeat-x; }
#container {
margin: 0 auto;
padding-top: 110px;
width: 550px; }
#toc {
position: fixed;
top: 60px;
left: 0;
margin: 0 0 0 15px;
padding: 15px;
height: 100%;
background: rgba(0,0,0,0.2);
border-right: 1px solid rgba(255,255,255,0.05);
}
#toc li {
padding: 1px 0;
list-style: none;
}
#toc li a {
font-size: 11px;
}
#menu {
margin-left: 65px;
padding: 0;
padding-bottom: 30px; }
#menu li {
display: inline;
list-style: none; }
#menu li a {
display: block;
float: left;
margin: 0 2px;
padding: 3px 15px;
background: rgba(0,0,0,0.2);
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
-webkit-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-moz-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-webkit-transition-property: opacity, -webkit-transform, color, background-color, -webkit-box-shadow;
-webkit-transition-duration: 0.15s;
-webkit-transition-timing-function: ease-out; }
#menu li a:hover,
#menu li a.active {
background: rgba(0,0,0,0.5); }
#menu li a:active {
background: rgba(0,0,0,0.1);
-webkit-box-shadow: 1px 1px 1px rgba(0,0,0,0.4);
-moz-box-shadow: 1px 1px 1px rgba(0,0,0,0.4); }
</style>
</head>
<body>
<a href='http://github.com/visionmedia/express'>
<img alt='Fork me on GitHub' id='ribbon' src='http://s3.amazonaws.com/github/ribbons/forkme_right_white_ffffff.png' />
</a>
<div id="header"><strong>Sencha</strong> labs</div>
<div id="wrapper">
<div id="container">
<a href='http://github.com/visionmedia/express' id='logo'>Express</a>
<p id="tagline">
High performance, high class web development for
<a href="http://nodejs.org">Node.js</a>
</p>
<ul id="menu">
<li><a href="index.html">Home</a></li>
<li><a href="guide.html">Guide</a></li>
<li><a href="contrib.html">Contributing</a></li>
<li><a href="migrate.html">1.x Migration</a></li>
</ul>
+347
Ver Arquivo
@@ -0,0 +1,347 @@
.\" generated with Ronn/v0.6.6
.\" http://github.com/rtomayko/ronn/
.
.TH "MIGRATE" "" "July 2010" "" ""
.
.SS "Built On Connect"
Express 1\.x is written to run on\-top of the Connect \fIhttp://extjs\.github\.com/Connect\fR middlware framework, thus the \fIPlugin\fR has been replaced by Connect\'s middleware\. By abstracting our middleware to Connect we allow additional community frameworks to develop robust, high\-level frameworks using the same technologies as Express\.
.
.SS "Creating Applications"
Previously due to legacy code implemented in the early days of node, Express unfortunately had some globals\. The DSL would previously be accessed as shown below:
.
.IP "" 4
.
.nf
require(\'express\');
configure(function(){
// app configuration
});
get(\'/\', function(){
return \'hello world\';
});
.
.fi
.
.IP "" 0
.
.P
Now we utilize the CommonJS module system appropriately, and introduce \fIexpress\.createServer()\fR which accepts the same arguments as \fIhttp\.createServer()\fR:
.
.IP "" 4
.
.nf
var express = require(\'express\'),
app = express\.createServer();
app\.configure(function(){
// app configuration
});
app\.get(\'/\', function(req, res){
res\.send(\'hello world\');
});
.
.fi
.
.IP "" 0
.
.P
Express 1\.x does \fInot\fR currently allow returning of a string\.
.
.SS "Plugins vs Middleware"
Previously Express was bundled with plugins, which were essentially what are now Connect middleware\. Previously plugins would be utilized in a manor similar to below:
.
.IP "" 4
.
.nf
use(Logger);
use(MethodOverride);
use(Cookie);
.
.fi
.
.IP "" 0
.
.P
Which we can now \fIuse()\fR within our app, or pass to the \fIexpress\.createServer()\fR method:
.
.IP "" 4
.
.nf
var connect = require(\'connect\');
var app = express\.createServer(
connect\.logger(),
connect\.methodOverride(),
connect\.cookie()
);
.
.fi
.
.IP "" 0
.
.P
or:
.
.IP "" 4
.
.nf
var connect = require(\'connect\');
var app = express\.createServer();
app\.use(\'/\', connect\.logger());
app\.use(\'/\', connect\.methodOverride());
app\.use(\'/\', connect\.cookieDecoder());
.
.fi
.
.IP "" 0
.
.P
For documentation on creating Connect middleware visit Middleware Authoring \fIhttp://extjs\.github\.com/Connect/#Middleware\-Authoring\fR\.
.
.SS "Running Applications"
Previously a global function \fIrun()\fR, was available:
.
.IP "" 4
.
.nf
run();
.
.fi
.
.IP "" 0
.
.P
The new \fIexpress\.Server\fR has the same API as \fIhttp\.Server\fR, so we can do things like:
.
.IP "" 4
.
.nf
app\.listen();
app\.listen(3000);
.
.fi
.
.IP "" 0
.
.SS "Route Parameters"
Previously we could use \fIthis\.param()\fR to attempt fetching a route, query string, or request body parameter:
.
.IP "" 4
.
.nf
get(\'/user/:id\', function(){
this\.param(\'id\');
});
.
.fi
.
.IP "" 0
.
.P
Polymorphic parameter access can be done using \fBreq\.param()\fR:
.
.IP "" 4
.
.nf
app\.get(\'/user/:id\', function(){
req\.param(\'id\');
});
.
.fi
.
.IP "" 0
.
.P
Route parameters are also passed as the third argument:
.
.IP "" 4
.
.nf
app\.get(\'/user/:id\', function(req, res, params){
params\.id;
});
.
.fi
.
.IP "" 0
.
.SS "Passing Route Control"
Old express had a weak notion of route passing, which did not support async, and was never properly implemented for practical use:
.
.IP "" 4
.
.nf
get(\'/\', function(){
this\.pass(\'/foobar\');
});
.
.fi
.
.IP "" 0
.
.P
Now Express has access to Connect\'s \fInext()\fR function, which is passed as the fourth and final argument\. Calling \fInext()\fR will pass control to the next \fImatching route\fR, or continue down the stack of Connect middleware\.
.
.IP "" 4
.
.nf
app\.get(\'/user/:id?\', function(req, res, params, next){
next();
});
app\.get(\'/user\', function(){
// \.\.\. respond
});
.
.fi
.
.IP "" 0
.
.SS "View Rendering"
View filenames no longer take the form \fINAME\fR\.\fITYPE\fR\.\fIENGINE\fR, the \fIContent\-Type\fR can be set via \fIres\.contentType()\fR or \fIres\.header()\fR\. For example what was previously \fIlayout\.html\.haml\fR, should now be \fIlayout\.haml\fR\.
.
.P
Previously a view render looked something like this:
.
.IP "" 4
.
.nf
get(\'/\', function(){
this\.render(\'index\.html\.haml\', {
locals: { title: \'My Site\' }
});
});
.
.fi
.
.IP "" 0
.
.P
We now have \fIres\.render()\fR, however the options passed to haml \fIhttp://github\.com/visionmedia/haml\.js\fR, jade \fIhttp://github\.com/visionmedia/jade\fR, and others remain the same\.
.
.IP "" 4
.
.nf
app\.get(\'/\', function(req, res){
res\.render(\'index\.haml\', {
locals: { title: \'My Site\' }
});
});
.
.fi
.
.IP "" 0
.
.P
Previously rendering of a collection via \fIpartial()\fR would look something like this:
.
.IP "" 4
.
.nf
this\.partial(\'comment\.html\.haml\', { collection: comments });
.
.fi
.
.IP "" 0
.
.P
Although this worked just fine, it was generally to verbose, the similar but new API looks like this, as \fIpartial()\fR is \fIalways\fR passed as a local variable:
.
.IP "" 4
.
.nf
partial(\'comment\.haml\', { collection: comments });
.
.fi
.
.IP "" 0
.
.P
To make things even less verbose we can assume the extension when omitted:
.
.IP "" 4
.
.nf
partial(\'comment\', { collection: comments });
.
.fi
.
.IP "" 0
.
.P
And once again even further, when rendering a collection we can simply pass an array, if no other options are desired:
.
.IP "" 4
.
.nf
partial(\'comments\', comments);
.
.fi
.
.IP "" 0
.
.SS "Redirecting"
Previously you would
.
.IP "" 4
.
.nf
this\.redirect(\'/somewhere\');
.
.fi
.
.IP "" 0
.
.P
However you would now:
.
.IP "" 4
.
.nf
res\.redirect(\'/somewhere\');
res\.redirect(\'/somewhere\', 301);
.
.fi
.
.IP "" 0
.
.SS "HTTP Client"
Previously Express provided a high level http client, this library is no more as it does not belong in Express, however it may be resurrected as a separate module\.
.
.SS "Core Extensions"
Express is no longer dependent on the JavaScript Extensions \fIhttp://github\.com/visionmedia/ext\.js\fR library, so those of you using the methods provided by it such as \fBObject\.merge(a, b)\fR will need to roll your own, or install the module via:
.
.IP "" 4
.
.nf
$ npm install ext
.
.fi
.
.IP "" 0
+398
Ver Arquivo
@@ -0,0 +1,398 @@
<html>
<head>
<title>Express - node web framework</title>
<style>
#header {
position: absolute;
top: 10px;
left: 0;
padding: 12px 0;
text-indent: 40px;
width: 100%;
border-top: 1px solid rgba(0,0,0,0.7);
border-bottom: 1px solid rgba(0,0,0,0.7);
background: rgba(255,255,255,0.1) url(http://www.sencha.com/favicon.ico) no-repeat 15px 50%;
text-align: left;
color: #fff;
}
#tagline {
margin-left: 75px;
margin-bottom: 30px;
color: rgba(255,255,255,0.7); }
html {
background: #1c1c1c url(images/bg.tile.jpg); }
body {
margin: 0;
padding-bottom: 30px;
font: 14px/1.4 "Helvetica Neue", "Lucida Grande", "Arial";
font-size: 14px;
line-height: 1.5;
-webkit-text-stroke: 1px rgba(0, 0, 0, 0.1);
-moz-text-stroke: 1px rgba(0, 0, 0, 0.1);
background: url(images/bg.jpg) 50% 0 no-repeat;
color: #8b8b8b; }
* {
outline: none; }
em {
color: white; }
a img {
border: none !important; }
a {
font-weight: bold;
text-decoration: none;
color: white;
-webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow;
-webkit-transition-duration: 0.15s;
-webkit-transition-timing-function: ease-out; }
a:hover {
opacity: 0.8; }
h1, h2, h3 {
margin: 45px 0 0 0;
color: white;
text-shadow: 1px 2px 2px rgba(0,0,0,0.6); }
h3 {
font-size: 18px; }
pre {
margin: 20px 10px;
padding: 25px 20px;
background: rgba(0,0,0,0.5);
border: 1px solid #323232;
-webkit-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-moz-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-webkit-border-radius: 5px;
-moz-border-radius: 5px; }
code {
font-family: "Helvetica Neue", "Lucida Grande", "Arial"; }
ul {
margin: 15px 0;
padding: 0 0 0 35px; }
ul li {
margin: 0;
padding: 2px 0;
list-style: square; }
.sect {
margin-left: 40px; }
#logo {
display: block;
margin-left: 30%;
margin-bottom: 30px;
width: 194px;
height: 51px;
background: url(images/logo.png) 0 0 no-repeat;
text-indent: -99999px; }
#logo:hover {
opacity: 0.7; }
#logo:active {
opacity: 0.3; }
#ribbon {
position: fixed;
top: 0;
right: 0;
z-index: 2; }
#wrapper {
width: 100%;
min-height: 800px;
background: url(images/top.png) 0 0 repeat-x; }
#container {
margin: 0 auto;
padding-top: 110px;
width: 550px; }
#toc {
position: fixed;
top: 60px;
left: 0;
margin: 0 0 0 15px;
padding: 15px;
height: 100%;
background: rgba(0,0,0,0.2);
border-right: 1px solid rgba(255,255,255,0.05);
}
#toc li {
padding: 1px 0;
list-style: none;
}
#toc li a {
font-size: 11px;
}
#menu {
margin-left: 65px;
padding: 0;
padding-bottom: 30px; }
#menu li {
display: inline;
list-style: none; }
#menu li a {
display: block;
float: left;
margin: 0 2px;
padding: 3px 15px;
background: rgba(0,0,0,0.2);
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
-webkit-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-moz-box-shadow: 1px 2px 2px rgba(0,0,0,0.6);
-webkit-transition-property: opacity, -webkit-transform, color, background-color, -webkit-box-shadow;
-webkit-transition-duration: 0.15s;
-webkit-transition-timing-function: ease-out; }
#menu li a:hover,
#menu li a.active {
background: rgba(0,0,0,0.5); }
#menu li a:active {
background: rgba(0,0,0,0.1);
-webkit-box-shadow: 1px 1px 1px rgba(0,0,0,0.4);
-moz-box-shadow: 1px 1px 1px rgba(0,0,0,0.4); }
</style>
</head>
<body>
<a href='http://github.com/visionmedia/express'>
<img alt='Fork me on GitHub' id='ribbon' src='http://s3.amazonaws.com/github/ribbons/forkme_right_white_ffffff.png' />
</a>
<div id="header"><strong>Sencha</strong> labs</div>
<div id="wrapper">
<div id="container">
<a href='http://github.com/visionmedia/express' id='logo'>Express</a>
<p id="tagline">
High performance, high class web development for
<a href="http://nodejs.org">Node.js</a>
</p>
<ul id="menu">
<li><a href="index.html">Home</a></li>
<li><a href="guide.html">Guide</a></li>
<li><a href="contrib.html">Contributing</a></li>
<li><a href="migrate.html">1.x Migration</a></li>
</ul>
<div class='mp'>
<h3 id="Built-On-Connect">Built On Connect</h3>
<p>Express 1.x is written to run on-top of the <a href="http://extjs.github.com/Connect">Connect</a> middlware
framework, thus the <em>Plugin</em> has been replaced by Connect's middleware. By abstracting our middleware
to Connect we allow additional community frameworks to develop robust, high-level frameworks using
the same technologies as Express.</p>
<h3 id="Creating-Applications">Creating Applications</h3>
<p>Previously due to legacy code implemented in the early days of node,
Express unfortunately had some globals. The DSL would previously be
accessed as shown below:</p>
<pre><code>require('express');
configure(function(){
// app configuration
});
get('/', function(){
return 'hello world';
});
</code></pre>
<p>Now we utilize the CommonJS module system appropriately, and
introduce <em>express.createServer()</em> which accepts the same arguments
as <em>http.createServer()</em>:</p>
<pre><code>var express = require('express'),
app = express.createServer();
app.configure(function(){
// app configuration
});
app.get('/', function(req, res){
res.send('hello world');
});
</code></pre>
<p>Express 1.x does <em>not</em> currently allow returning of a string.</p>
<h3 id="Plugins-vs-Middleware">Plugins vs Middleware</h3>
<p>Previously Express was bundled with plugins, which were essentially what
are now Connect middleware. Previously plugins would be utilized in a manor
similar to below:</p>
<pre><code>use(Logger);
use(MethodOverride);
use(Cookie);
</code></pre>
<p>Which we can now <em>use()</em> within our app, or pass to the <em>express.createServer()</em> method:</p>
<pre><code>var connect = require('connect');
var app = express.createServer(
connect.logger(),
connect.methodOverride(),
connect.cookie()
);
</code></pre>
<p>or:</p>
<pre><code>var connect = require('connect');
var app = express.createServer();
app.use('/', connect.logger());
app.use('/', connect.methodOverride());
app.use('/', connect.cookieDecoder());
</code></pre>
<p>For documentation on creating Connect middleware visit <a href="http://extjs.github.com/Connect/#Middleware-Authoring">Middleware Authoring</a>.</p>
<h3 id="Running-Applications">Running Applications</h3>
<p>Previously a global function <em>run()</em>, was available:</p>
<pre><code>run();
</code></pre>
<p>The new <em>express.Server</em> has the same API as <em>http.Server</em>,
so we can do things like:</p>
<pre><code>app.listen();
app.listen(3000);
</code></pre>
<h3 id="Route-Parameters">Route Parameters</h3>
<p>Previously we could use <em>this.param()</em> to attempt
fetching a route, query string, or request body parameter:</p>
<pre><code>get('/user/:id', function(){
this.param('id');
});
</code></pre>
<p>Polymorphic parameter access can be done using <code>req.param()</code>:</p>
<pre><code>app.get('/user/:id', function(){
req.param('id');
});
</code></pre>
<p>Route parameters are also passed as the third argument:</p>
<pre><code>app.get('/user/:id', function(req, res, params){
params.id;
});
</code></pre>
<h3 id="Passing-Route-Control">Passing Route Control</h3>
<p>Old express had a weak notion of route passing,
which did not support async, and was never properly
implemented for practical use:</p>
<pre><code>get('/', function(){
this.pass('/foobar');
});
</code></pre>
<p>Now Express has access to Connect's <em>next()</em> function,
which is passed as the fourth and final argument. Calling <em>next()</em> will
pass control to the next <em>matching route</em>, or continue down the stack
of Connect middleware.</p>
<pre><code>app.get('/user/:id?', function(req, res, params, next){
next();
});
app.get('/user', function(){
// ... respond
});
</code></pre>
<h3 id="View-Rendering">View Rendering</h3>
<p>View filenames no longer take the form <em>Express</em>.<em>TYPE</em>.<em>ENGINE</em>,
the <em>Content-Type</em> can be set via <em>res.contentType()</em> or
<em>res.header()</em>. For example what was previously <em>layout.html.haml</em>,
should now be <em>layout.haml</em>.</p>
<p>Previously a view render looked something like this:</p>
<pre><code>get('/', function(){
this.render('index.html.haml', {
locals: { title: 'My Site' }
});
});
</code></pre>
<p>We now have <em>res.render()</em>, however the options passed to <a href="http://github.com/visionmedia/haml.js">haml</a>, <a href="http://github.com/visionmedia/jade">jade</a>, and others
remain the same.</p>
<pre><code>app.get('/', function(req, res){
res.render('index.haml', {
locals: { title: 'My Site' }
});
});
</code></pre>
<p>Previously rendering of a collection via <em>partial()</em> would look something like this:</p>
<pre><code>this.partial('comment.html.haml', { collection: comments });
</code></pre>
<p>Although this worked just fine, it was generally to verbose, the similar but new API
looks like this, as <em>partial()</em> is <em>always</em> passed as a local variable:</p>
<pre><code>partial('comment.haml', { collection: comments });
</code></pre>
<p>To make things even less verbose we can assume the extension when omitted:</p>
<pre><code>partial('comment', { collection: comments });
</code></pre>
<p>And once again even further, when rendering a collection we can simply pass
an array, if no other options are desired:</p>
<pre><code>partial('comments', comments);
</code></pre>
<h3 id="Redirecting">Redirecting</h3>
<p>Previously you would</p>
<pre><code>this.redirect('/somewhere');
</code></pre>
<p>However you would now:</p>
<pre><code>res.redirect('/somewhere');
res.redirect('/somewhere', 301);
</code></pre>
<h3 id="HTTP-Client">HTTP Client</h3>
<p>Previously Express provided a high level http client, this library is no more
as it does not belong in Express, however it may be resurrected as a separate module.</p>
<h3 id="Core-Extensions">Core Extensions</h3>
<p>Express is no longer dependent on the <a href="http://github.com/visionmedia/ext.js">JavaScript Extensions</a> library, so those of you using the methods provided by it such as <code>Object.merge(a, b)</code> will need to
roll your own, or install the module via:</p>
<pre><code>$ npm install ext
</code></pre>
</div>
</div>
</div>
</body>
</html>
+192
Ver Arquivo
@@ -0,0 +1,192 @@
### Built On Connect
Express 1.x is written to run on-top of the [Connect](http://extjs.github.com/Connect) middlware
framework, thus the _Plugin_ has been replaced by Connect's middleware. By abstracting our middleware
to Connect we allow additional community frameworks to develop robust, high-level frameworks using
the same technologies as Express.
### Creating Applications
Previously due to legacy code implemented in the early days of node,
Express unfortunately had some globals. The DSL would previously be
accessed as shown below:
require('express');
configure(function(){
// app configuration
});
get('/', function(){
return 'hello world';
});
Now we utilize the CommonJS module system appropriately, and
introduce _express.createServer()_ which accepts the same arguments
as _http.createServer()_:
var express = require('express'),
app = express.createServer();
app.configure(function(){
// app configuration
});
app.get('/', function(req, res){
res.send('hello world');
});
Express 1.x does _not_ currently allow returning of a string.
### Plugins vs Middleware
Previously Express was bundled with plugins, which were essentially what
are now Connect middleware. Previously plugins would be utilized in a manor
similar to below:
use(Logger);
use(MethodOverride);
use(Cookie);
Which we can now _use()_ within our app, or pass to the _express.createServer()_ method:
var connect = require('connect');
var app = express.createServer(
connect.logger(),
connect.methodOverride(),
connect.cookie()
);
or:
var connect = require('connect');
var app = express.createServer();
app.use('/', connect.logger());
app.use('/', connect.methodOverride());
app.use('/', connect.cookieDecoder());
For documentation on creating Connect middleware visit [Middleware Authoring](http://extjs.github.com/Connect/#Middleware-Authoring).
### Running Applications
Previously a global function _run()_, was available:
run();
The new _express.Server_ has the same API as _http.Server_,
so we can do things like:
app.listen();
app.listen(3000);
### Route Parameters
Previously we could use _this.param()_ to attempt
fetching a route, query string, or request body parameter:
get('/user/:id', function(){
this.param('id');
});
Polymorphic parameter access can be done using `req.param()`:
app.get('/user/:id', function(){
req.param('id');
});
Route parameters are also passed as the third argument:
app.get('/user/:id', function(req, res, params){
params.id;
});
### Passing Route Control
Old express had a weak notion of route passing,
which did not support async, and was never properly
implemented for practical use:
get('/', function(){
this.pass('/foobar');
});
Now Express has access to Connect's _next()_ function,
which is passed as the fourth and final argument. Calling _next()_ will
pass control to the next _matching route_, or continue down the stack
of Connect middleware.
app.get('/user/:id?', function(req, res, params, next){
next();
});
app.get('/user', function(){
// ... respond
});
### View Rendering
View filenames no longer take the form _NAME_._TYPE_._ENGINE_,
the _Content-Type_ can be set via _res.contentType()_ or
_res.header()_. For example what was previously _layout.html.haml_,
should now be _layout.haml_.
Previously a view render looked something like this:
get('/', function(){
this.render('index.html.haml', {
locals: { title: 'My Site' }
});
});
We now have _res.render()_, however the options passed to [haml](http://github.com/visionmedia/haml.js), [jade](http://github.com/visionmedia/jade), and others
remain the same.
app.get('/', function(req, res){
res.render('index.haml', {
locals: { title: 'My Site' }
});
});
Previously rendering of a collection via _partial()_ would look something like this:
this.partial('comment.html.haml', { collection: comments });
Although this worked just fine, it was generally to verbose, the similar but new API
looks like this, as _partial()_ is _always_ passed as a local variable:
partial('comment.haml', { collection: comments });
To make things even less verbose we can assume the extension when omitted:
partial('comment', { collection: comments });
And once again even further, when rendering a collection we can simply pass
an array, if no other options are desired:
partial('comments', comments);
### Redirecting
Previously you would
this.redirect('/somewhere');
However you would now:
res.redirect('/somewhere');
res.redirect('/somewhere', 301);
### HTTP Client
Previously Express provided a high level http client, this library is no more
as it does not belong in Express, however it may be resurrected as a separate module.
### Core Extensions
Express is no longer dependent on the [JavaScript Extensions](http://github.com/visionmedia/ext.js) library, so those of you using the methods provided by it such as `Object.merge(a, b)` will need to
roll your own, or install the module via:
$ npm install ext
-81
Ver Arquivo
@@ -1,81 +0,0 @@
require.paths.unshift('lib')
require('express')
require('express/plugins')
configure(function(){
var fiveMinutes = 300000,
oneMinute = 60000
use(MethodOverride)
use(ContentLength)
use(CommonLogger)
use(Cookie)
use(Cache, { lifetime: fiveMinutes, reapInterval: oneMinute })
use(Session, { lifetime: fiveMinutes, reapInterval: oneMinute })
set('root', __dirname)
})
var messages = [],
utils = require('express/utils')
get('/', function(){
this.redirect('/chat')
})
get('/chat', function(){
this.render('chat.haml.html', {
locals: {
title: 'Chat',
messages: messages,
name: this.session.name,
usersOnline: Session.store.length()
}
})
})
post('/chat', function(){
this.session.name = this.param('name')
messages
.push(utils.escape(this.param('name')) + ': ' + utils.escape(this.param('message'))
.replace(/(http:\/\/[^\s]+)/g, '<a href="$1" target="express-chat">$1</a>')
.replace(/:\)/g, '<img src="http://icons3.iconfinder.netdna-cdn.com/data/icons/ledicons/emoticon_smile.png">'))
this.halt(200)
})
get('/chat/messages', function(){
var self = this,
previousLength = messages.length,
timer = setInterval(function(){
if (messages.length > previousLength)
self.contentType('json'),
previousLength = messages.length,
self.halt(200, JSON.encode(messages)),
clearInterval(timer)
}, 100)
})
get('/public/*', function(file){
this.sendfile(__dirname + '/public/' + file)
})
get('/*.css', function(file){
this.render(file + '.sass.css', { layout: false })
})
get('/error/view', function(){
this.render('does.not.exist')
})
get('/error', function(){
throw new Error('oh noes!')
})
get('/simple', function(){
return 'Hello :)'
})
get('/favicon.ico', function(){
this.halt()
})
run()
Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 5.2 KiB

-28
Ver Arquivo
@@ -1,28 +0,0 @@
$(function(){
// Send message
$('form').submit(function(){
var message = $('input[name=message]'),
name = $('input[name=name]')
if (message.val())
$.post('/chat', { name: name.val(), message: message.val() }, function(){
message.val('')
})
else
message.css('border', '1px solid red')
return false
})
// Longpoll
;(function poll(){
$.getJSON('/chat/messages', function(messages){
$('#messages').empty()
$.each(messages, function(i, msg){
$('#messages')
.append('<li>' + msg + '</li>')
.get(0).scrollTop = $('#messages').get(0).scrollHeight
})
poll()
})
})()
})
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
-10
Ver Arquivo
@@ -1,10 +0,0 @@
%h1 Chat
%img.bubble{ src: '/public/images/bubble.png' }
%ul#messages
:each msg in messages
%li= msg
%form{ method: 'post' }
%input{ type: 'hidden', name: '_method', value: 'put' }
%input{ type: 'text', name: 'name', value: name || 'guest' }
%input{ type: 'text', name: 'message' }
%input{ type: 'submit', value: 'Send' }
-11
Ver Arquivo
@@ -1,11 +0,0 @@
%html
%head
%title= title
%script{ src: '/public/javascripts/jquery.js' }
%script{ src: '/public/javascripts/app.js' }
%link{ rel: 'stylesheet', href: '/style.css' }
%body
#wrapper= body
#online
Online:
%strong= usersOnline
-81
Ver Arquivo
@@ -1,81 +0,0 @@
body
:font-family "Helvetica Neue", "Lucida Grande", "Arial"
:font-size 13px
:text-align center
=text-stroke 1px rgba(255, 255, 255, 0.1)
:color #555
h1, h2
:margin 0
:font-size 22px
:color #343434
h1
:text-shadow 1px 2px 2px #ddd
:font-size 60px
img.bubble
:position absolute
:top -25px
:left 120px
#wrapper
:position relative
:margin 100px auto
:width 500px
:text-align left
ul
:margin 0
:padding 0
:max-height 300px
:overflow-x hidden
li
:margin 5px 0
:padding 3px 8px
:list-style none
:border 1px solid #eee
=border-radius 3px
=border-radius 3px
li:hover
:cursor pointer
:color #2E2E2E
input[type=text]
:padding 5px
:border 1px solid #ddd
:outline none
=border-radius 2px
input[type=text]:focus
:border-color #00C3FF
input[type=submit]
=border-radius 2px
=box-shadow 0 1px 2px #ddd
:padding 6px 10px
:border solid 1px #999
:background -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ddd))
:color #333
:text-decoration none
:cursor pointer
:display inline-block
:text-align center
:text-shadow 0px 1px 1px #fff
:line-height 1
input[type=submit]:hover
:background -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#E6E4E4))
input[type=submit]:active
:background -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#c7c7c7))
input[name=name]
:width 80px
a
:color #1ABFF1
=transition-property padding
=transition-duration 0.15s
a:hover
:padding 0 5px
a:hover:before
:content 'visit: '
#online
:font-size 12px
+29
Ver Arquivo
@@ -0,0 +1,29 @@
/**
* Module dependencies.
*/
var express = require('./../../lib/express');
var app = express.createServer();
// Optional since express defaults to CWD/views
app.set('views', __dirname + '/views');
// Dummy users
var users = [
{ name: 'tj', email: 'tj@sencha.com' },
{ name: 'ciaran', email: 'ciaranj@gmail.com' },
{ name: 'aaron', email: 'aaron.heckmann+github@gmail.com' }
];
app.get('/', function(req, res){
res.render('users.ejs', {
locals: {
users: users
}
});
});
app.listen(3000);
+6
Ver Arquivo
@@ -0,0 +1,6 @@
<html>
<body>
<h1>Users</h1>
<%- body %>
</body>
</html>
+1
Ver Arquivo
@@ -0,0 +1 @@
<li><%= user.name %> &lt;<%= user.email %>&gt;</li>
+3
Ver Arquivo
@@ -0,0 +1,3 @@
<ul id="users">
<%- partial('user', users) %>
</ul>
+26
Ver Arquivo
@@ -0,0 +1,26 @@
/**
* Module dependencies.
*/
var express = require('./../../lib/express'),
connect = require('connect');
var app = express.createServer();
app.get('/', function(req, res){
// Caught and passed down to the errorHandler middleware
throw new Error('something broke!');
});
app.get('/next', function(req, res, params, next){
// We can also pass exceptions to next()
next(new Error('oh no!'))
});
// The errorHandler middleware in this case will dump exceptions to stderr
// as well as show the stack trace in responses, currently handles text/plain,
// text/html, and application/json responses to aid in development
app.use('/', connect.errorHandler({ dumpExceptions: true, showStack: true }));
app.listen(3000);
+50
Ver Arquivo
@@ -0,0 +1,50 @@
/**
* Module dependencies.
*/
var express = require('./../../lib/express'),
connect = require('connect'),
sys = require('sys');
var app = express.createServer(
// Here we use the bodyDecoder middleware
// to parse urlencoded request bodies
// which populates req.body
connect.bodyDecoder(),
// The methodOverride middleware allows us
// to set a hidden input of _method to an arbitrary
// HTTP method to support app.put(), app.del() etc
connect.methodOverride()
);
app.get('/', function(req, res){
// get ?name=foo
var name = req.param('name') || '';
// Switch the button label based if we have a name
var label = name ? 'Update' : 'Save';
// If we have a name, we are updating,
// so add the hidden _method input
res.send('<form method="post">'
+ (name ? '<input type="hidden" value="put" name="_method" />' : '')
+ 'Name: <input type="text" name="name" value="' + name + '" />'
+ '<input type="submit" value="' + label + '" />'
+ '</form>');
});
app.post('/', function(req, res){
// Typically here we would create a resource
sys.puts('saved ' + req.body.name);
res.redirect('/?name=' + req.body.name);
});
app.put('/', function(req, res){
// Typically here we would update a resource
sys.puts('updated ' + req.body.name);
res.redirect('/?name=' + req.body.name);
});
app.listen(3000);
+103
Ver Arquivo
@@ -0,0 +1,103 @@
/**
* Module dependencies.
*/
var express = require('./../../lib/express'),
connect = require('connect'),
http = require('http');
var app = express.createServer();
// Expose our views
app.set('views', __dirname + '/views');
/**
* Request github json api `path`.
*
* @param {String} path
* @param {Function} fn
* @api public
*/
function request(path, fn){
var client = http.createClient(80, 'github.com'),
req = client.request('GET', '/api/v2/json' + path, { Host: 'github.com' });
req.addListener('response', function(res){
res.body = '';
res.addListener('data', function(chunk){ res.body += chunk; });
res.addListener('end', function(){
try {
fn(null, JSON.parse(res.body));
} catch (err) {
fn(err);
}
});
});
req.end();
}
/**
* Sort repositories by watchers desc.
*
* @param {Array} repos
* @api public
*/
function sort(repos){
return repos.sort(function(a, b){
if (a.watchers == b.watchers) return 0;
if (a.watchers > b.watchers) return -1;
if (a.watchers < b.watchers) return 1;
});
}
/**
* Tally up total watchers.
*
* @param {Array} repos
* @return {Number}
* @api public
*/
function totalWatchers(repos) {
return repos.reduce(function(sum, repo){
return sum + repo.watchers;
}, 0);
}
/**
* Default to my user name :)
*/
app.get('/', function(req, res){
res.redirect('/repos/visionmedia');
});
/**
* Display repos.
*/
app.get('/repos/:user', function(req, res, params, next){
var name = params.user;
request('/repos/show/' + name, function(err, user){
if (err) {
next(err)
} else {
res.render('index.jade', {
locals: {
totalWatchers: totalWatchers(user.repositories),
repos: sort(user.repositories),
name: name
}
});
}
});
});
// Serve statics from ./public
app.use('/', connect.staticProvider(__dirname + '/public'));
// Listen on port 3000
app.listen(3000);
+11
Ver Arquivo
@@ -0,0 +1,11 @@
body {
padding: 30px 50px;
font: 12px/1.4 "Lucida Grande", "Helvetica Nueue", Arial, sans-serif;
}
a {
color: #00AAFF;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
+5
Ver Arquivo
@@ -0,0 +1,5 @@
h1= name
p.summary
| <a href="http://github.com/#{name}">#{name}</a> has <strong>#{repos.length}</strong> repositories
| with a total of <strong>#{totalWatchers}</strong> watchers.
table#repos!= partial('repo', repos)
+7
Ver Arquivo
@@ -0,0 +1,7 @@
!!!
html
head
title Github Example
link(rel="stylesheet", href="/style.css")
body
#container!= body
+5
Ver Arquivo
@@ -0,0 +1,5 @@
tr.repo
td.name
a(href: repo.homepage || repo.url)= repo.name
td.watchers
= repo.watchers
+14
Ver Arquivo
@@ -0,0 +1,14 @@
/**
* Module dependencies.
*/
var express = require('./../../lib/express');
var app = express.createServer();
app.get('/', function(req, res){
res.send('Hello World');
});
app.listen(3000);
+50
Ver Arquivo
@@ -0,0 +1,50 @@
/**
* Module dependencies.
*/
var express = require('./../../lib/express'),
connect = require('connect');
// Path to our public directory
var pub = __dirname + '/public';
// Auto-compile sass to css with "compiler"
// and then serve with connect's staticProvider
var app = express.createServer(
connect.compiler({ src: pub, enable: ['sass'] }),
connect.staticProvider(pub)
);
// Optional since express defaults to CWD/views
app.set('views', __dirname + '/views');
// Enable auto-reloading of view contents when changed
// with an interval of 1000 milliseconds. Start the app
// with $ node examples/jade/app.js
// then alter some views :)
app.set('reload views', 1000);
// or app.enable('reload views'); for defaults
// Re-compile
// Dummy users
var users = [
{ name: 'tj', email: 'tj@sencha.com' },
{ name: 'ciaran', email: 'ciaranj@gmail.com' },
{ name: 'aaron', email: 'aaron.heckmann+github@gmail.com' }
];
app.get('/', function(req, res){
res.render('users.jade', {
locals: {
users: users
}
});
});
app.listen(3000);
+3
Ver Arquivo
@@ -0,0 +1,3 @@
body {
padding: 50px 80px;
font: 14px "Helvetica Nueue", "Lucida Grande", Arial, sans-serif;}
@@ -0,0 +1,3 @@
body
:padding 50px 80px
:font 14px "Helvetica Nueue", "Lucida Grande", Arial, sans-serif
+6
Ver Arquivo
@@ -0,0 +1,6 @@
!!!
html
head
title Jade Example
link(rel="stylesheet", href="/stylesheets/style.css")
body!= body
+3
Ver Arquivo
@@ -0,0 +1,3 @@
.user
h2= user.name
.email= user.email
+3
Ver Arquivo
@@ -0,0 +1,3 @@
- if (users.length)
h1 Users
#users!= partial('user', users)
+47
Ver Arquivo
@@ -0,0 +1,47 @@
/**
* Module dependencies.
*/
var express = require('./../../lib/express'),
form = require('./../../support/connect-form'),
connect = require('connect'),
sys = require('sys');
var app = express.createServer(
// connect-form (http://github.com/visionmedia/connect-form)
// middleware uses the formidable middleware to parse urlencoded
// and multipart form data
form()
);
app.get('/', function(req, res){
res.send('<form method="post" enctype="form-data/multipart">'
+ '<p>Image: <input type="file" name="image" /></p>'
+ '<p><input type="submit" value="Upload" /></p>'
+ '</form>');
});
app.post('/', function(req, res, params, next){
// connect-form adds the req.form object
// we can (optionally) define onComplete, passing
// the exception (if any) fields parsed, and files parsed
req.form.complete(function(err, fields, files){
if (err) {
next(err);
} else {
sys.puts('\nuploaded ' + files.image.filename);
res.redirect('back');
}
});
// We can add listeners for several form
// events such as "progress"
req.form.addListener('progress', function(bytesReceived, bytesExpected){
var percent = (bytesReceived / bytesExpected * 100) | 0;
sys.print('Uploading: %' + percent + '\r');
});
});
app.listen(3000);
+58
Ver Arquivo
@@ -0,0 +1,58 @@
/**
* Module dependencies.
*/
var express = require('./../../lib/express');
var app = express.createServer(),
sys = require('sys');
app.set('views', __dirname + '/views');
// Provide our app with the notion of NotFound exceptions
function NotFound(msg){
this.name = 'NotFound';
Error.call(this, msg);
Error.captureStackTrace(this, arguments.callee);
}
sys.inherits(NotFound, Error);
app.get('/', function(req, res){
res.render('index.jade');
});
app.get('/404', function(req, res){
throw new NotFound;
});
app.get('/500', function(req, res){
throw new Error('keyboard cat!');
});
// We can call app.error() several times as shown below.
// Here we check for an instanceof NotFound and show the
// 404 page, or we pass on to the next error handler.
app.error(function(err, req, res, next){
if (err instanceof NotFound) {
res.render('404.jade');
} else {
next(err);
}
});
// Here we assume all errors as 500 for the simplicity of
// this demo, however you can choose whatever you like
app.error(function(err, req, res){
res.render('500.jade', {
locals: {
error: err
}
});
});
app.listen(3000);
+1
Ver Arquivo
@@ -0,0 +1 @@
h2 Page Not Found
+2
Ver Arquivo
@@ -0,0 +1,2 @@
h1 Error: #{error.message}
pre= error.stack
+8
Ver Arquivo
@@ -0,0 +1,8 @@
h2 Pages Example
ul
li
| visit
a(href="/500") 500
li
| visit
a(href="/404") 404
+6
Ver Arquivo
@@ -0,0 +1,6 @@
html
head
title Custom Pages Example
body
h1 My Site
!= body
-36
Ver Arquivo
@@ -1,36 +0,0 @@
require.paths.unshift('lib')
require('express')
require('express/plugins')
configure(function(){
use(MethodOverride)
use(ContentLength)
use(CommonLogger)
set('root', __dirname)
})
get('/', function(){
this.redirect('/upload')
})
get('/upload', function(){
this.render('upload.haml.html')
})
post('/upload', function(){
$(this.param('images')).each(function(image){
puts('uploaded ' + image.filename + ' to ' + image.tempfile)
})
this.redirect('/upload')
})
get('/public/*', function(file){
this.sendfile(__dirname + '/public/' + file)
})
get('/*.css', function(file){
this.render(file + '.sass.css', { layout: false })
})
run()
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
-8
Ver Arquivo
@@ -1,8 +0,0 @@
%html
%head
%title Upload
%script{ src: '/public/javascripts/jquery.js' }
%script{ src: '/public/javascripts/app.js' }
%link{ rel: 'stylesheet', href: '/style.css' }
%body
#wrapper= body
-59
Ver Arquivo
@@ -1,59 +0,0 @@
body
:font-family "Helvetica Neue", "Lucida Grande", "Arial"
:font-size 13px
:text-align center
:-webkit-text-stroke 1px rgba(255, 255, 255, 0.1)
:color #555
h1, h2
:margin 0 0 15px 0
:font-size 22px
:color #343434
h1
:text-shadow 1px 2px 2px #ddd
:font-size 60px
h2
:margin-top 15px
#wrapper
:position relative
:margin 100px auto
:width 500px
:text-align left
input[type=file]
:padding 5px
:border 1px solid #ddd
:outline none
:-webkit-border-radius 2px
:-moz-border-radius 2px
input[type=file]:focus
:border-color #00C3FF
input[type=submit]
:-webkit-border-radius 2px
:-moz-border-radius 2px
:-webkit-box-shadow 0 1px 2px #ddd
:-moz-box-shadow 0 1px 2px #ddd
:padding 6px 10px
:border solid 1px #999
:background -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ddd))
:color #333
:text-decoration none
:cursor pointer
:display inline-block
:text-align center
:text-shadow 0px 1px 1px #fff
:line-height 1
input[type=submit]:hover
:background -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#E6E4E4))
input[type=submit]:active
:background -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#c7c7c7))
input[name=name]
:width 80px
form
.panel
:float left
:width 100%
:margin-bottom 15px
-19
Ver Arquivo
@@ -1,19 +0,0 @@
%h1 Upload
:if typeof images !== 'undefined'
.images
:each img in images
%img{ src: img }
%h2 Singles
%form{ method: 'post', enctype: 'multipart/form-data' }
%input{ type: 'file', name: 'images[0]' }
%input{ type: 'file', name: 'images[1]' }
%input{ type: 'file', name: 'images[2]' }
.panel
%input{ type: 'submit', value: 'Upload' }
%h2 Multiple
%form{ method: 'post', enctype: 'multipart/form-data' }
%input{ type: 'file', name: 'images[]', multiple: 'multiple' }
.panel
%input{ type: 'submit', value: 'Upload' }
+2
Ver Arquivo
@@ -0,0 +1,2 @@
module.exports = require('./lib/express');
Arquivo executável
+14
Ver Arquivo
@@ -0,0 +1,14 @@
install() {
mkdir -p /tmp/$2 \
&& cd /tmp/$2 \
&& echo "... installing $2" \
&& curl -# -L "http://github.com/$1/$2/tarball/master" \
| tar xz --strip 1 \
&& cp -fr lib/$2 ~/.node_libraries/$2
}
install visionmedia express \
&& install senchalabs connect \
&& cp -f /tmp/express/bin/express /usr/local/bin/express \
&& echo "... installation complete"
-7
Ver Arquivo
@@ -1,7 +0,0 @@
require.paths.unshift(__dirname + '/support/js-oo/lib')
require.paths.unshift(__dirname + '/support/ejs/lib')
require.paths.unshift(__dirname + '/support/haml/lib')
require.paths.unshift(__dirname + '/support/sass/lib')
require('oo')
require('express/core')
-543
Ver Arquivo
@@ -1,543 +0,0 @@
// Express - Collection - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
/**
* Throw $break in order to stop iteration.
*/
$break = '__break__'
var property = /^\w+$/,
method = /^\w+\(/
/**
* Normalize callback _fn_. When a string is
* passed convert the shorthand expr to a function.
*
* - Functions are passed through un-touched
* - Strings with length of < 4 are considered operators between a and b
* - Single words are considered properties on a
* - Single functions are considered method calls on a
* - Larger strings are considered return expressions
*
* @param {string, function} fn
* @return {function}
* @api private
*/
function callback(fn) {
if (fn === undefined) return
if (fn instanceof Function) return fn
if (fn.length < 4) return Function('a, b, c', 'return a ' + fn + ' b')
if (property.test(fn) || method.test(fn)) fn = 'a.' + fn
return Function('a, b, c', 'return ' + fn)
}
// --- Collection
Collection = Class({
/**
* Initialize collection with an array-like object.
*
* @param {object} arr
* @api private
*/
init: function(arr) {
this.arr = arr || []
},
/**
* Return the value of _index_ or null.
*
* @param {int} index
* @return {mixed}
* @api public
*/
at: function(index) {
if ('length' in this.arr)
return this.arr[index]
var result, i = 0
this.each(function(val){
if (i++ == index) {
result = val
throw $break
}
})
return result
},
/**
* Iterate collection using callback _fn_,
* passing both the value and index.
*
* @param {function} fn
* @return {Collection}
* @api public
*/
each: function(fn) {
try {
if (this.arr.forEach)
this.arr.forEach(fn)
else
for (var key in this.arr)
if (this.arr.hasOwnProperty(key))
fn(this.arr[key], key)
}
catch (e) {
if (e != $break) throw e
}
return this
},
/**
* Reverse a collection.
*
* @return {Collection}
* @api public
*/
reverse: function() {
if (this.arr.reverse)
return $(this.arr.reverse())
return this
},
/**
* Join a collection with the given _str_ or ''.
*
* @param {string} str
* @return {string}
* @api public
*/
join: function(str) {
return this.toArray().join(str || '')
},
/**
* Sort collection with optional _fn_.
*
* @param {function} fn
* @return {Collection}
* @warn converts to array
* @api public
*/
sort: function(fn) {
fn = callback(fn)
return $(this.toArray().sort(fn))
},
/**
* Iterate with _memo_ using callback _fn_.
* The _memo_ object is passed as the first
* argument, and the return value of _fn_ becomes
* the value of _memo_ providing a functional
* approach to reducing a collection.
*
* @param {mixed} memo
* @param {function} fn
* @return {mixed}
* @api public
*/
reduce: function(memo, fn) {
fn = callback(fn)
if (this.arr.reduce)
return this.arr.reduce(fn, memo)
this.each(function(val, key){
memo = fn(memo, val, key)
})
return memo
},
/**
* Map using callback _fn_, returning a
* new collection of return values.
*
* @param {function} fn
* @return {Collection}
* @api public
*/
map: function(fn) {
fn = callback(fn)
if (this.arr.map)
return $(this.arr.map(fn))
return $(this.reduce([], function(array, val, key){
array.push(fn(val, key))
return array
}))
},
/**
* Return collection of values when _fn_ evaluates
* to true.
*
* @param {function} fn
* @return {Collection}
* @api public
*/
select: function(fn) {
fn = callback(fn)
return $(this.reduce([], function(array, val, key){
if (fn(val, key))
array.push(val)
return array
}))
},
/**
* Return collection of values when _fn_ evaluates
* to false.
*
* @param {function} fn
* @return {Collection}
* @api public
*/
reject: function(fn) {
fn = callback(fn)
return $(this.reduce([], function(array, val, key){
if (!fn(val, key))
array.push(val)
return array
}))
},
/**
* Check if all arguments passed are found within
* the collection using the === operator.
*
* @return {bool}
* @api public
*/
includes: function() {
var self = this
return $(arguments).all(function(arg){
return self.any(function(val){
return val === arg
})
})
},
/**
* Return the first _n_ value(s), defaults to 1.
*
* @param {int} n
* @return {mixed}
* @api public
*/
first: function(n) {
return n ?
this.slice(0, n) :
this.at(0)
},
/**
* Return the last _n_ value(s), defaults to -1.
*
* @param {int} n
* @return {mixed}
* @api public
*/
last: function(n) {
var len = this.length()
return n ?
this.slice(len - n, len) :
this.at(--len)
},
/**
* Drop the first _n_ values, returning the others.
*
* @param {int} n
* @return {Collection}
* @api public
*/
drop: function(n) {
return this.slice(n, this.length())
},
/**
* Return a slice of values from _start_ to _end_.
*
* @param {int} start
* @param {int} end
* @return {Collection}
* @api public
*/
slice: function(start, end) {
if (this.arr.slice)
return $(this.arr.slice(start, end))
var i = 0
return $(this.reduce([], function(array, val){
if (i++ >= start)
if (i <= end)
array.push(val)
else
throw $break
return array
}))
},
/**
* Iterate until _fn_ evaluates to true, then
* return the matching value.
*
* @param {function} fn
* @return {mixed}
* @api public
*/
find: function(fn) {
var result, fn = callback(fn)
this.each(function(val, key){
if (fn(val, key)) {
result = val
throw $break
}
})
return result
},
/**
* Return true if _fn_ ever evaluates to true, otherwise
* returns false.
*
* @param {function} fn
* @return {bool}
* @api public
*/
any: function(fn) {
fn = callback(fn)
if (this.arr.some)
return this.arr.some(fn)
return !! this.find(fn)
},
/**
* Returns true if _fn_ always evaluates to true, otherwise
* returns false.
*
* @param {function} fn
* @return {bool}
* @api public
*/
all: function(fn) {
fn = callback(fn)
if (this.arr.every)
return this.arr.every(fn)
return this.reduce(true, function(state, val, key){
if (!state) throw $break
return !! fn(val, key)
})
},
/**
* Select values matching _pattern_
*
* @param {regexp} pattern
* @return {Collection}
* @api public
*/
grep: function(pattern) {
return this.select(function(val){
return pattern.exec(val)
})
},
/**
* Return keys as a collection.
*
* @return {Collection}
* @api public
*/
keys: function() {
return $(Object.keys(this.arr))
},
/**
* Convert a collection to a true array.
* Works recursively
*
* @return {array}
* @api public
*/
toArray: function() {
return this.reduce([], function(array, val){
val instanceof Collection ?
array.push(val.toArray()) :
array.push(val)
return array
})
},
/**
* Return the lowest number in the collection.
*
* @return {number}
* @api public
*/
min: function() {
return this.reduce(null, function(min, val){
return min === null ? val :
val < min ? val :
min
})
},
/**
* Return the largest number in the collection.
*
* @return {number}
* @api public
*/
max: function() {
return this.reduce(null, function(max, val){
return max === null ? val :
val > max ? val :
max
})
},
/**
* Group collection into several collections grouped by _size_.
*
* @param {int} size
* @return {Collection}
* @api public
*/
chunk: function(size) {
var len = this.arr.length,
chunks = [], chunk = [], i = 0
this.each(function(val, key){
chunk.push(val)
if (i++ > 0 && (i % size == 0 || i == len))
chunks.push($(chunk)),
chunk = []
})
return $(chunks)
},
/**
* Return the length of this collection.
*
* @return {int}
* @api public
*/
length: function() {
if ('length' in this.arr)
return this.arr.length
return this.reduce(0, function(len){
return ++len
})
},
/**
* Return the sum of numeric values in this collection.
*
* @return {number}
* @api public
*/
sum: function() {
return this.reduce(0, function(sum, n){
return sum + n
})
},
/**
* Return the average of numeric values in this collection.
*
* @return {number}
* @api public
*/
avg: function() {
return this.sum() / this.length()
},
/**
* Merge _other_ with this collection.
*
* @param {mixed} other
* @return {Collection}
* @api public
*/
merge: function(other) {
if (this.arr instanceof Array)
return $($(other).reduce(this.arr, function(array, val){
array.push(val)
return array
}))
else
return $(process.mixin(this.arr, $(other).arr))
},
/**
* Clone the collection.
*
* @return {Collection}
* @api public
*/
clone: function() {
return this.merge({})
},
/**
* Return the value of a random index.
*
* @return {mixed}
* @api public
*/
sample: function() {
return this.at(Math.floor(Math.random() * this.length()))
},
/**
* Convert collection to a string.
*
* @return {string}
* @api public
*/
toString: function() {
return '[Collection ' + this.arr + ']'
}
})
/**
* Create a new collection from an array-like object.
*
* @param {object} arr
* @return {Collection}
* @api public
*/
var $ = exports.$ = function(arr) {
if (arr instanceof Collection) return arr
return new Collection(arr)
}
-322
Ver Arquivo
@@ -1,322 +0,0 @@
// Express - Core - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
process.mixin(require('sys'))
process.mixin(require('express/exceptions'))
process.mixin(require('express/collection'))
process.mixin(require('express/event'))
process.mixin(require('express/request'))
process.mixin(require('express/plugin'))
process.mixin(require('express/dsl'))
/**
* Module dependencies.
*/
var multipart = require('multipart'),
events = require('events'),
File = require('file').File,
utils = require('express/utils')
// --- Route
Route = Class({
/**
* Initialize a route with the given _method_,
* _path_, and callback _fn_.
*
* The given _path_ becomes #originalPath,
* #path is then a normalized version converted
* to a regular expression for routing.
*
* @param {string} method
* @param {string} path
* @param {function} fn
* @param {hash} options
* @api private
*/
init: function(method, path, fn, options){
this.method = method
this.originalPath = path
this.path = this.normalize(path)
this.fn = fn
},
/**
* Normalize _path_. When a RegExp it is simply returned,
* otherwise a string is converted to a regular expression
* surrounded by ^$. So /user/:id/edit would become:
*
* /^\/user\/([^\/]+)\/edit$/i
*
* Each param key (:id) will be captured and placed in the
* params array, so param('id') would give the string captured.
*
* The following are valid routes:
*
* - /user/:id Ex: '/user/12'
* - /user/:id? Ex: '/user', '/user/12'
* - /report.:format Ex: '/report.pdf', 'report.csv'
* - /public/* Ex: '/public/app.js', '/public/javascripts/app.js'
* - /public/*.* Ex: '/public/app.js', '/public/javascripts/app.js'
*
* @param {string} path
* @return {regexp}
* @api private
*/
normalize: function(path) {
var self = this
this.keys = []
if (path instanceof RegExp) return path
return new RegExp('^' + utils.escapeRegexp(normalizePath(path), '.')
.replace(/\*/g, '(.+)')
.replace(/(\/|\\\.):(\w+)\?/g, function(_, c, key){
self.keys.push(key)
return '(?:' + c + '([^\/]+))?'
})
.replace(/:(\w+)/g, function(_, key){
self.keys.push(key)
return '([^\/]+)'
}) + '$', 'i')
}
})
// --- Router
Router = Class({
/**
* Initialize with _request_ and parse url.
*
* @param {Request} request
* @api private
*/
init: function(request) {
this.request = request
},
/**
* Evaluate the matched route against #request.
*
* @return {mixed}
* @api private
*/
route: function(){
var route = this.matchingRoute()
if (route)
return route.fn.apply(this.request, this.request.captures.slice(1))
else if (this.request.accepts('html') && set('helpful 404'))
this.request.halt(404, require('express/pages/not-found').render(this.request))
else
this.request.halt()
},
/**
* Attempt to match a route from Express.routes.
*
* @return {Route}
* @api private
*/
matchingRoute: function(){
var self = this
return $(Express.routes).find(function(route){
return self.match(route)
})
},
/**
* Check if _route_ matches the current request.
* If so populate #captures and #params.
*
* @param {object} route
* @return {bool}
* @api private
*/
match: function(route) {
if (this.request.method.toLowerCase() == route.method)
if (this.request.captures = this.request.url.pathname.match(route.path)) {
this.mapParams(route)
return true
}
},
/**
* Map #request.captures to #request.params.path based on the
* given _route_ keys.
*
* @param {Route} route
* @api private
*/
mapParams: function(route) {
var self = this
$(route.keys).each(function(key, i){
self.request.params.path[key] = self.request.captures[++i]
})
}
})
// --- Server
Server = Class({
/**
* Default port number.
*/
port: 3000,
/**
* Default host ip, when null node will accept requests on
* all network addresses.
*/
host: 'localhost',
/**
* Maximum number of queued connections.
*/
backlog: 128,
/**
* Run Express.
*
* - Buffers request bodies
* - Calls #route() once the request is complete
*
* @param {int} port
* @param {string} host
* @param {int} backlog
* @see run()
* @api private
*/
run: function(port, host, backlog){
var self = this
if (host !== undefined) this.host = host
if (port !== undefined) this.port = port
if (backlog !== undefined) this.backlog = backlog
require('http')
.createServer(function(request, response){
request.body = ''
request.setBodyEncoding('binary')
if (request.headers['content-type'] &&
request.headers['content-type'].indexOf('multipart/form-data') !== -1) {
var stream = new multipart.Stream(request),
promise = new events.Promise,
pendingFiles = 0
request.params = { post: {}}
promise.timeout(set('upload timeout') || 5000)
stream.addListener('part', function(part){
if (part.filename) {
var file = new File(part.tempfile = '/tmp/express-' + Number(new Date) + utils.uid(), 'w', { encoding: 'binary' })
++pendingFiles
part.pos = 0
part.addListener('body', function(chunk){
file.write(chunk, part.pos, 'binary').addErrback(function(){
promise.emitError.apply(promise, arguments)
})
part.pos += chunk.length
})
.addListener('complete', function(){
file.close().addCallback(function(){
if (!--pendingFiles)
promise.emitSuccess()
}).addErrback(function(){
promise.emitError.apply(promise, arguments)
})
utils.mergeParam(part.name, part, request.params.post)
})
}
else
part.buf = '',
part
.addListener('body', function(chunk){ part.buf += chunk })
.addListener('complete', function(){
if (part.buf.length)
utils.mergeParam(part.name, part.buf, request.params.post)
})
}).addListener('complete', function(){
if (!pendingFiles) promise.emitSuccess()
promise.addCallback(function(){ self.route(request, response) })
})
}
else
request
.addListener('body', function(chunk){ request.body += chunk })
.addListener('complete', function(){ self.route(request, response) })
})
.listen(this.port, this.host, this.backlog)
puts('Express started at http://' + this.host + ':' + this.port + '/ in ' + Express.environment + ' mode')
},
/**
* Route the given _request_ and _response_.
*
* @param {object} request
* @param {object} response
* @api private
*/
route: function(request, response){
request = new Request(request, response)
request.trigger('request')
if (request.response.finished) return
try {
if (typeof (body = (new Router(request)).route()) == 'string')
request.halt(200, body)
}
catch (e) {
if (e instanceof ExpressError)
throw e
if (request.accepts('html') && set('show exceptions'))
request.halt(500, require('express/pages/show-exceptions').render(request, e))
else
request.halt(500)
if (set('throw exceptions'))
throw e
}
}
})
// --- Express
Express = {
version: '0.3.0',
config: [],
routes: [],
plugins: [],
settings: {},
server: new Server
}
// --- Defaults
configure(function(){
use(require('express/plugins/view').View)
use(require('express/plugins/cache').Cache)
use(require('express/plugins/redirect').Redirect)
use(require('express/plugins/body-decoder').BodyDecoder)
})
configure('development', function(){
enable('helpful 404')
enable('show exceptions')
})
configure('test', function(){
enable('throw exceptions')
})
configure('production', function(){
enable('cache view contents')
enable('cache static files')
})
-122
Ver Arquivo
@@ -1,122 +0,0 @@
// Express - DSL - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
/**
* Return a routing function for _method_.
*
* @param {string} method
* @return {function}
* @api private
*/
function route(method) {
return function(path, options, fn){
if (options instanceof Function)
fn = options, options = {}
Express.routes.push(new Route(method, path, fn, options))
}
}
/**
* Set _option_ to _val_. When only _option_ is
* present its current value will be returned.
*
* @param {string} option
* @param {mixed} val
* @return {mixed}
* @api public
*/
exports.set = function(option, val) {
return val === undefined ?
Express.settings[option] instanceof Function ?
Express.settings[option]() :
Express.settings[option] :
Express.settings[option] = val
}
/**
* Enable _options_.
*
* @param {string} option
* @api public
*/
exports.enable = function(option) {
set(option, true)
}
/**
* Disable _option_.
*
* @param {string} option
* @api public
*/
exports.disable = function(option) {
set(option, false)
}
/**
* Run Express, view Server#run() for parameters.
*
* All configuration handlers for EXPRESS_ENV or 'development'
* are called before starting the server.
*
* @see Server#run()
* @api public
*/
exports.run = function() {
configure(Express.environment = process.ENV.EXPRESS_ENV || 'development')
$(Express.plugins).each(function(plugin){
if ('init' in plugin.klass)
plugin.klass.init(plugin.options)
})
Express.server.run.apply(Express.server, arguments)
}
/**
* Configure _environment_ with _fn_.
*
* Global configuration, disregards which
* environment is active:
*
* configure(function(){
* // ...
* })
*
* Environment specific configuration:
*
* configure('development', function(){
* // ...
* })
*
* Running configurations:
*
* configure('development')
*
* @param {string, function} environment
* @param {function} fn
* @api public
*/
exports.configure = function(environment, fn) {
if (environment instanceof Function)
fn = environment, environment = 'all'
if (fn instanceof Function)
return Express.config.push([environment, fn])
if (typeof environment != 'string')
throw new Error('environment required')
for (var i = 0, len = Express.config.length; i < len; ++i)
if (Express.config[i][0] == environment ||
Express.config[i][0] == 'all')
Express.config[i][1].call(Express)
}
// --- Routing API
exports.get = exports.view = route('get')
exports.post = exports.create = route('post')
exports.del = exports.destroy = route('delete')
exports.put = exports.update = route('put')
-179
Ver Arquivo
@@ -1,179 +0,0 @@
// Express - ElementCollection - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
/**
* Module dependencies.
*/
var libxml = require('libxmljs')
// --- css2xpath
/** version 0.1 2009-04-30
* @author Andrea Giammarchi
* @license Mit Style License
* @project http://code.google.com/p/css2xpath/
*/
var css2xpath=(function(){var b=[/\[([^\]~\$\*\^\|\!]+)(=[^\]]+)?\]/g,"[@$1$2]",/\s*,\s*/g,"|",/\s*(\+|~|>)\s*/g,"$1",/([a-zA-Z0-9\_\-\*])~([a-zA-Z0-9\_\-\*])/g,"$1/following-sibling::$2",/([a-zA-Z0-9\_\-\*])\+([a-zA-Z0-9\_\-\*])/g,"$1/following-sibling::*[1]/self::$2",/([a-zA-Z0-9\_\-\*])>([a-zA-Z0-9\_\-\*])/g,"$1/$2",/\[([^=]+)=([^'|"][^\]]*)\]/g,"[$1='$2']",/(^|[^a-zA-Z0-9\_\-\*])(#|\.)([a-zA-Z0-9\_\-]+)/g,"$1*$2$3",/([\>\+\|\~\,\s])([a-zA-Z\*]+)/g,"$1//$2",/\s+\/\//g,"//",/([a-zA-Z0-9\_\-\*]+):first-child/g,"*[1]/self::$1",/([a-zA-Z0-9\_\-\*]+):last-child/g,"$1[not(following-sibling::*)]",/([a-zA-Z0-9\_\-\*]+):only-child/g,"*[last()=1]/self::$1",/([a-zA-Z0-9\_\-\*]+):empty/g,"$1[not(*) and not(normalize-space())]",/([a-zA-Z0-9\_\-\*]+):not\(([^\)]*)\)/g,function(f,e,d){return e.concat("[not(",a(d).replace(/^[^\[]+\[([^\]]*)\].*$/g,"$1"),")]")},/([a-zA-Z0-9\_\-\*]+):nth-child\(([^\)]*)\)/g,function(f,e,d){switch(d){case"n":return e;case"even":return"*[position() mod 2=0 and position()>=0]/self::"+e;case"odd":return e+"[(count(preceding-sibling::*) + 1) mod 2=1]";default:d=(d||"0").replace(/^([0-9]*)n.*?([0-9]*)$/,"$1+$2").split("+");d[1]=d[1]||"0";return"*[(position()-".concat(d[1],") mod ",d[0],"=0 and position()>=",d[1],"]/self::",e)}},/:contains\(([^\)]*)\)/g,function(e,d){return"[contains(string(.),'"+d+"')]"},/\[([a-zA-Z0-9\_\-]+)\|=([^\]]+)\]/g,"[@$1=$2 or starts-with(@$1,concat($2,'-'))]",/\[([a-zA-Z0-9\_\-]+)\*=([^\]]+)\]/g,"[contains(@$1,$2)]",/\[([a-zA-Z0-9\_\-]+)~=([^\]]+)\]/g,"[contains(concat(' ',normalize-space(@$1),' '),concat(' ',$2,' '))]",/\[([a-zA-Z0-9\_\-]+)\^=([^\]]+)\]/g,"[starts-with(@$1,$2)]",/\[([a-zA-Z0-9\_\-]+)\$=([^\]]+)\]/g,function(f,e,d){return"[substring(@".concat(e,",string-length(@",e,")-",d.length-3,")=",d,"]")},/\[([a-zA-Z0-9\_\-]+)\!=([^\]]+)\]/g,"[not(@$1) or @$1!=$2]",/#([a-zA-Z0-9\_\-]+)/g,"[@id='$1']",/\.([a-zA-Z0-9\_\-]+)/g,"[contains(concat(' ',normalize-space(@class),' '),' $1 ')]",/\]\[([^\]]+)/g," and ($1)"],c=b.length;return function a(e){var d=0;while(d<c){e=e.replace(b[d++],b[d++])}return"//"+e}})();
// --- ElementCollection
ElementCollection = Collection.extend({
/**
* Initialize with string of _markup_.
*
* @param {string} markup
* @api private
*/
init: function(markup) {
if (typeof markup != 'string')
return this.__super__(markup)
if (!(/<html>/.test(markup)))
markup = '<html><body>' + markup + '</body></html>'
this.document = libxml.parseHtmlString(markup)
this.arr = [this.document.root()]
},
/**
* Return the first element's name.
*
* @return {string}
* @api public
*/
name: function() {
return this.at(0).name()
},
/**
* Search child elements with the given _xpath_.
*
* @param {string} xpath
* @return {ElementCollection}
* @api public
*/
xpath: function(xpath) {
// TODO: refactor with flatten()
return $(this.reduce([], function(array, e){
$(e.find(xpath)).each(function(child){
array.push(child)
})
return array
}))
},
/**
* Search child elements with the given css _selector_
*
* @param {string} selector
* @return {ElementCollection}
* @api public
*/
search: function(selector) {
return this.xpath(css2xpath(selector))
},
/**
* Return collection of children.
*
* @return {ElementCollection}
* @api public
*/
children: function() {
// TODO: refactor with flatten()
return $(this.reduce([], function(array, e){
$(e.children()).each(function(child){
array.push(child)
})
return array
}))
},
/**
* Return collection of parents.
*
* @return {ElementCollection}
* @api public
*/
parents: function() {
return this.map(function(e){
return e.parent()
})
},
/**
* Return the first element's parent.
*
* @return {ElementCollection}
* @api public
*/
parent: function() {
return $([this.at(0).parent()])
},
/**
* Return the prev element.
*
* @return {ElementCollection}
* @api public
*/
prev: function() {
return $([this.at(0).prevSibling()])
},
/**
* Return the next element.
*
* @return {ElementCollection}
* @api public
*/
next: function() {
return $([this.at(0).nextSibling()])
},
/**
* Return the first element's text content.
*
* @return {string}
* @api public
*/
text: function() {
return this.at(0).text()
},
/**
* Convert collection to a string.
*
* @return {string}
* @api public
*/
toString: function() {
if (this.at(0) && this.at(0).doc)
return '[Collection <elements>]'
return this.__super__()
}
})
/**
* Add markup support to $().
*
* @param {object} arr
* @return {Collection, ElementCollection}
* @api public
*/
var $ = exports.$ = function(arr) {
if (arr instanceof Collection) return arr
return new ElementCollection(arr)
}
-29
Ver Arquivo
@@ -1,29 +0,0 @@
// Express - Event - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
exports.Event = Class({
/**
* Initialize with event _name_ and optional _data_.
*
* @param {string} name
* @param {hash} data
* @api private
*/
init: function(name, data) {
this.name = name
process.mixin(this, data)
},
/**
* Return event string.
*
* @return {string}
* @api public
*/
toString: function() {
return '[Event ' + this.name + ']'
}
})
-14
Ver Arquivo
@@ -1,14 +0,0 @@
// Express - Exceptions - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
// --- ExpressError
ExpressError = Class({
name: 'ExpressError',
init: function(message) {
this.message = message
},
toString: function() {
return this.name + ': ' + this.message
}
})
+38
Ver Arquivo
@@ -0,0 +1,38 @@
/*!
* Express
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
* MIT Licensed
*/
/**
* Framework version.
*/
exports.version = '1.0.0beta';
/**
* Module dependencies.
*/
var Server = require('./server');
/**
* Shortcut for `new Server(...)`.
*
* @param {Function} ...
* @return {Server}
* @api public
*/
exports.createServer = function(){
return new Server(Array.prototype.slice.call(arguments));
};
/**
* View extensions.
*/
require('./view');
require('./request');
require('./response');
-370
Ver Arquivo
@@ -1,370 +0,0 @@
// Express - Mime - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
/**
* Module dependencies.
*/
var utils = require('express/utils')
/**
* Mime type lookup table.
*/
exports.types = {
'323' : 'text/h323',
'3gp' : 'video/3gpp',
'a' : 'application/octet-stream',
'acx' : 'application/internet-property-stream',
'ai' : 'application/postscript',
'aif' : 'audio/x-aiff',
'aifc' : 'audio/x-aiff',
'aiff' : 'audio/x-aiff',
'asc' : 'application/pgp-signature',
'asf' : 'video/x-ms-asf',
'asr' : 'video/x-ms-asf',
'asm' : 'text/x-asm',
'asx' : 'video/x-ms-asf',
'atom' : 'application/atom+xml',
'au' : 'audio/basic',
'avi' : 'video/x-msvideo',
'axs' : 'application/olescript',
'bas' : 'text/plain',
'bat' : 'application/x-msdownload',
'bcpio' : 'application/x-bcpio',
'bin' : 'application/octet-stream',
'bmp' : 'image/bmp',
'bz2' : 'application/x-bzip2',
'c' : 'text/x-c',
'cab' : 'application/vnd.ms-cab-compressed',
'cat' : 'application/vnd.ms-pkiseccat',
'cc' : 'text/x-c',
'cdf' : 'application/x-netcdf',
'cer' : 'application/x-x509-ca-cert',
'cgm' : 'image/cgm',
'chm' : 'application/vnd.ms-htmlhelp',
'class' : 'application/octet-stream',
'clp' : 'application/x-msclip',
'cmx' : 'image/x-cmx',
'cod' : 'image/cis-cod',
'com' : 'application/x-msdownload',
'conf' : 'text/plain',
'cpio' : 'application/x-cpio',
'cpp' : 'text/x-c',
'cpt' : 'application/mac-compactpro',
'crd' : 'application/x-mscardfile',
'crl' : 'application/pkix-crl',
'crt' : 'application/x-x509-ca-cert',
'csh' : 'application/x-csh',
'css' : 'text/css',
'csv' : 'text/csv',
'cxx' : 'text/x-c',
'dcr' : 'application/x-director',
'deb' : 'application/x-debian-package',
'der' : 'application/x-x509-ca-cert',
'diff' : 'text/x-diff',
'dir' : 'application/x-director',
'djv' : 'image/vnd.djvu',
'djvu' : 'image/vnd.djvu',
'dll' : 'application/x-msdownload',
'dmg' : 'application/octet-stream',
'dms' : 'application/octet-stream',
'doc' : 'application/msword',
'dot' : 'application/msword',
'dtd' : 'application/xml-dtd',
'dv' : 'video/x-dv',
'dvi' : 'application/x-dvi',
'dxr' : 'application/x-director',
'ear' : 'application/java-archive',
'eml' : 'message/rfc822',
'eps' : 'application/postscript',
'etx' : 'text/x-setext',
'evy' : 'application/envoy',
'exe' : 'application/x-msdownload',
'ez' : 'application/andrew-inset',
'f' : 'text/x-fortran',
'f77' : 'text/x-fortran',
'f90' : 'text/x-fortran',
'fif' : 'application/fractals',
'flr' : 'x-world/x-vrml',
'flv' : 'video/x-flv',
'for' : 'text/x-fortran',
'gem' : 'application/octet-stream',
'gemspec' : 'text/x-script.ruby',
'gif' : 'image/gif',
'gram' : 'application/srgs',
'grxml' : 'application/srgs+xml',
'gtar' : 'application/x-gtar',
'gz' : 'application/x-gzip',
'h' : 'text/x-c',
'hdf' : 'application/x-hdf',
'hh' : 'text/x-c',
'hlp' : 'application/winhlp',
'hqx' : 'application/mac-binhex40',
'hta' : 'application/hta',
'htc' : 'text/x-component',
'htm' : 'text/html',
'html' : 'text/html',
'htt' : 'text/webviewhtml',
'ice' : 'x-conference/x-cooltalk',
'ico' : 'image/vnd.microsoft.icon',
'ics' : 'text/calendar',
'ief' : 'image/ief',
'ifb' : 'text/calendar',
'iges' : 'model/iges',
'igs' : 'model/iges',
'iii' : 'application/x-iphone',
'ins' : 'application/x-internet-signup',
'isp' : 'application/x-internet-signup',
'iso' : 'application/octet-stream',
'jar' : 'application/java-archive',
'java' : 'text/x-java-source',
'jfif' : 'image/pipeg',
'jnlp' : 'application/x-java-jnlp-file',
'jp2' : 'image/jp2',
'jpe' : 'image/jpeg',
'jpeg' : 'image/jpeg',
'jpg' : 'image/jpeg',
'js' : 'application/javascript',
'json' : 'application/json',
'kar' : 'audio/midi',
'latex' : 'application/x-latex',
'lha' : 'application/octet-stream',
'lsf' : 'video/x-la-asf',
'lsx' : 'video/x-la-asf',
'lzh' : 'application/octet-stream',
'log' : 'text/plain',
'm13' : 'application/x-msmediaview',
'm14' : 'application/x-msmediaview',
'm3u' : 'audio/x-mpegurl',
'm4a' : 'audio/mp4a-latm',
'm4b' : 'audio/mp4a-latm',
'm4p' : 'audio/mp4a-latm',
'm4u' : 'video/vnd.mpegurl',
'm4v' : 'video/mp4',
'mac' : 'image/x-macpaint',
'man' : 'text/troff',
'mathml' : 'application/mathml+xml',
'mbox' : 'application/mbox',
'mdb' : 'application/x-msaccess',
'mdoc' : 'text/troff',
'me' : 'text/troff',
'mesh' : 'model/mesh',
'mht' : 'message/rfc822',
'mhtml' : 'message/rfc822',
'mid' : 'audio/midi',
'midi' : 'audio/midi',
'mif' : 'application/vnd.mif',
'mime' : 'message/rfc822',
'mml' : 'application/mathml+xml',
'mng' : 'video/x-mng',
'mny' : 'application/x-msmoney',
'mov' : 'video/quicktime',
'movie' : 'video/x-sgi-movie',
'mp2' : 'video/mpeg',
'mp3' : 'audio/mpeg',
'mp4' : 'video/mp4',
'mp4v' : 'video/mp4',
'mpa' : 'video/mpeg',
'mpe' : 'video/mpeg',
'mpeg' : 'video/mpeg',
'mpg' : 'video/mpeg',
'mpga' : 'audio/mpeg',
'mpp' : 'application/vnd.ms-project',
'mpv2' : 'video/mpeg',
'ms' : 'text/troff',
'msh' : 'model/mesh',
'msi' : 'application/x-msdownload',
'mvb' : 'application/x-msmediaview',
'mxu' : 'video/vnd.mpegurl',
'nc' : 'application/x-netcdf',
'nws' : 'message/rfc822',
'oda' : 'application/oda',
'odp' : 'application/vnd.oasis.opendocument.presentation',
'ods' : 'application/vnd.oasis.opendocument.spreadsheet',
'odt' : 'application/vnd.oasis.opendocument.text',
'ogg' : 'application/ogg',
'p' : 'text/x-pascal',
'p10' : 'application/pkcs10',
'p12' : 'application/x-pkcs12',
'p7b' : 'application/x-pkcs7-certificates',
'p7c' : 'application/x-pkcs7-mime',
'p7m' : 'application/x-pkcs7-mime',
'p7r' : 'application/x-pkcs7-certreqresp',
'p7s' : 'application/x-pkcs7-signature',
'pas' : 'text/x-pascal',
'pbm' : 'image/x-portable-bitmap',
'pct' : 'image/pict',
'pdb' : 'chemical/x-pdb',
'pdf' : 'application/pdf',
'pem' : 'application/x-x509-ca-cert',
'pfx' : 'application/x-pkcs12',
'pgm' : 'image/x-portable-graymap',
'pgn' : 'application/x-chess-pgn',
'pgp' : 'application/pgp-encrypted',
'pic' : 'image/pict',
'pict' : 'image/pict',
'pkg' : 'application/octet-stream',
'pko' : 'application/ynd.ms-pkipko',
'pl' : 'text/x-script.perl',
'pm' : 'text/x-script.perl-module',
'pma' : 'application/x-perfmon',
'pmc' : 'application/x-perfmon',
'pml' : 'application/x-perfmon',
'pmr' : 'application/x-perfmon',
'pmw' : 'application/x-perfmon',
'png' : 'image/png',
'pnm' : 'image/x-portable-anymap',
'pnt' : 'image/x-macpaint',
'pntg' : 'image/x-macpaint',
'pot' : 'application/vnd.ms-powerpoint',
'ppm' : 'image/x-portable-pixmap',
'pps' : 'application/vnd.ms-powerpoint',
'ppt' : 'application/vnd.ms-powerpoint',
'prf' : 'application/pics-rules',
'ps' : 'application/postscript',
'psd' : 'image/vnd.adobe.photoshop',
'pub' : 'application/x-mspublisher',
'py' : 'text/x-script.python',
'qt' : 'video/quicktime',
'qti' : 'image/x-quicktime',
'qtif' : 'image/x-quicktime',
'ra' : 'audio/x-pn-realaudio',
'rake' : 'text/x-script.ruby',
'ram' : 'audio/x-pn-realaudio',
'rar' : 'application/x-rar-compressed',
'ras' : 'image/x-cmu-raster',
'rb' : 'text/x-script.ruby',
'rdf' : 'application/rdf+xml',
'rgb' : 'image/x-rgb',
'rm' : 'application/vnd.rn-realmedia',
'rmi' : 'audio/mid',
'roff' : 'text/troff',
'rpm' : 'application/x-redhat-package-manager',
'rss' : 'application/rss+xml',
'rtf' : 'application/rtf',
'rtx' : 'text/richtext',
'ru' : 'text/x-script.ruby',
's' : 'text/x-asm',
'scd' : 'application/x-msschedule',
'sct' : 'text/scriptlet',
'setpay' : 'application/set-payment-initiation',
'setreg' : 'application/set-registration-initiation',
'sgm' : 'text/sgml',
'sgml' : 'text/sgml',
'sh' : 'application/x-sh',
'shar' : 'application/x-shar',
'sig' : 'application/pgp-signature',
'silo' : 'model/mesh',
'sit' : 'application/x-stuffit',
'skd' : 'application/x-koan',
'skm' : 'application/x-koan',
'skp' : 'application/x-koan',
'skt' : 'application/x-koan',
'smi' : 'application/smil',
'smil' : 'application/smil',
'snd' : 'audio/basic',
'so' : 'application/octet-stream',
'spc' : 'application/x-pkcs7-certificates',
'spl' : 'application/x-futuresplash',
'src' : 'application/x-wais-source',
'sst' : 'application/vnd.ms-pkicertstore',
'stl' : 'application/vnd.ms-pkistl',
'stm' : 'text/html',
'sv4cpio' : 'application/x-sv4cpio',
'sv4crc' : 'application/x-sv4crc',
'svg' : 'image/svg+xml',
'svgz' : 'image/svg+xml',
'swf' : 'application/x-shockwave-flash',
't' : 'text/troff',
'tar' : 'application/x-tar',
'tbz' : 'application/x-bzip-compressed-tar',
'tcl' : 'application/x-tcl',
'tex' : 'application/x-tex',
'texi' : 'application/x-texinfo',
'texinfo' : 'application/x-texinfo',
'text' : 'text/plain',
'tgz' : 'application/x-compressed',
'tif' : 'image/tiff',
'tiff' : 'image/tiff',
'torrent' : 'application/x-bittorrent',
'tr' : 'text/troff',
'trm' : 'application/x-msterminal',
'tsv' : 'text/tab-seperated-values',
'txt' : 'text/plain',
'uls' : 'text/iuls',
'ustar' : 'application/x-ustar',
'vcd' : 'application/x-cdlink',
'vcf' : 'text/x-vcard',
'vcs' : 'text/x-vcalendar',
'vrml' : 'model/vrml',
'vxml' : 'application/voicexml+xml',
'war' : 'application/java-archive',
'wav' : 'audio/x-wav',
'wbmp' : 'image/vnd.wap.wbmp',
'wbxml' : 'application/vnd.wap.wbxml',
'wcm' : 'application/vnd.ms-works',
'wdb' : 'application/vnd.ms-works',
'wks' : 'application/vnd.ms-works',
'wma' : 'audio/x-ms-wma',
'wmf' : 'application/x-msmetafile',
'wml' : 'text/vnd.wap.wml',
'wmls' : 'text/vnd.wap.wmlscript',
'wmlsc' : 'application/vnd.wap.wmlscriptc',
'wmv' : 'video/x-ms-wmv',
'wmx' : 'video/x-ms-wmx',
'wps' : 'application/vnd.ms-works',
'wri' : 'application/x-mswrite',
'wrl' : 'model/vrml',
'wrz' : 'x-world/x-vrml',
'wsdl' : 'application/wsdl+xml',
'xaf' : 'x-world/x-vrml',
'xbm' : 'image/x-xbitmap',
'xht' : 'application/xhtml+xml',
'xhtml' : 'application/xhtml+xml',
'xla' : 'application/vnd.ms-excel',
'xlc' : 'application/vnd.ms-excel',
'xlm' : 'application/vnd.ms-excel',
'xls' : 'application/vnd.ms-excel',
'xlt' : 'application/vnd.ms-excel',
'xml' : 'application/xml',
'xof' : 'x-world/x-vrml',
'xpm' : 'image/x-xpixmap',
'xsl' : 'application/xml',
'xslt' : 'application/xslt+xml',
'xul' : 'application/vnd.mozilla.xul+xml',
'xwd' : 'image/x-xwindowdump',
'xyz' : 'chemical/x-xyz',
'yaml' : 'text/yaml',
'yml' : 'text/yaml',
'z' : 'application/x-compress',
'zip' : 'application/zip'
}
/**
* Return the mime type associated with _path_,
* where _path_ may be an extension, or full
* file path.
*
* By default 'application/octet-stream' is returned,
* however this can be altered using the 'default mime type'
* setting.
*
* var mime = require('express/mime')
* mime.type('png') // => 'image/png'
* mime.type('.png') // => 'image/png'
* mime.type('image.png') // => 'image/png'
* mime.type('path/to/image.png') // => 'image/png'
*
* @param {string} path
* @return {string}
* @settings 'default mime type'
* @api public
*/
exports.type = function(path) {
return exports.types[path] ||
exports.types[utils.extname(path)] ||
set('default mime type') ||
'application/octet-stream'
}
-29
Ver Arquivo
@@ -1,29 +0,0 @@
// Express - Pages - Not Found - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
var style = require('express/pages/style').style
exports.render = function(request) {
request.contentType('html')
var method = request.method.toLowerCase(),
path = request.url.pathname || '/'
return '<html> \n\
<head> \n\
<title>Express -- Not Found</title> \n\
' + style + ' \n\
</head> \n\
<body> \n\
<div id="wrapper"> \n\
  <h1>Express</h1> \n\
  <h2><em>404</em> Not Found</h2> \n\
<p>No routes were matched, try the route below.\n\
For restful services ensure that you use(<strong>MethodOverride</strong>).</p> \n\
  <pre><code> \n\
' + method + '(\'' + path + '\', function(){ \n\
// Response logic \n\
}) \n\
  </code></pre> \n\
</div> \n\
</body> \n\
</html>'
}
-78
Ver Arquivo
@@ -1,78 +0,0 @@
// Express - Pages - Show Exceptions - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
var style = require('express/pages/style').style
/**
* Return list items for exception _e_'s stack.
*
* @param {object} e
* @return {string}
* @api private
*/
function stack(e) {
if (e.stack)
return $(e.stack.split('\n').slice(1)).map(function(val, i){
if (!i)
return '<li>' + val.replace(/^(.*?):/, '<span class="path">$1</span>:') + '</li>'
return '<li>' + val
.replace(/\(([^:]+)/, '(<span class="path">$1</span>')
.replace(/(:\d+:\d+)/, '<span class="line">$1</span>') +
'</li>'
}).join('\n')
}
/**
* Return table rows for _hash_.
*
* @param {hash} hash
* @return {string}
* @api private
*/
function hash(hash) {
if (!$(hash).length()) return '<tr><td class="empty" colspan="2">Empty</td></tr>'
return $(hash).map(function(val, key){
return '<tr><td>' + key + ':</td><td>' + JSON.encode(val) + '</td></tr>'
}).join('\n')
}
exports.render = function(request, e) {
request.contentType('html')
return '<html> \n\
<head> \n\
<title>Express -- ' + e + '</title> \n\
' + style + ' \n\
</head> \n\
<body> \n\
<div id="wrapper"> \n\
  <h1>Express</h1> \n\
  <h2><em>500</em> ' + e + '</h2> \n\
  <ul id="stacktrace"> \n\
  ' + stack(e) + ' \n\
  </ul> \n\
<h3>Request</h3> \n\
<table id="request-headers"> \n\
' + hash(request.headers) + ' \n\
</table> \n\
<h3>Response</h3> \n\
<table id="response-headers"> \n\
' + hash(request.response.headers) + ' \n\
</table> \n\
<h3>Params</h3> \n\
<table id="route-params"> \n\
' + hash(request.params) + ' \n\
</table> \n\
<h3>GET</h3> \n\
<table id="get-params"> \n\
' + hash(request.url.params) + ' \n\
</table> \n\
<h3>POST</h3> \n\
<table id="post-params"> \n\
' + hash(request.url.post) + ' \n\
</table> \n\
</div> \n\
</body> \n\
</html>'
}
-99
Ver Arquivo
@@ -1,99 +0,0 @@
// Express - Pages - Style - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
exports.style = '<style> \n\
body { \n\
font-family: "Helvetica Neue", "Lucida Grande", "Arial"; \n\
font-size: 13px; \n\
text-align: center; \n\
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ECE9E9)); \n\
color: #555; \n\
-webkit-text-stroke: 1px rgba(255, 255, 255, 0.1); \n\
} \n\
h1, h2, h3 { \n\
margin: 0; \n\
font-size: 22px; \n\
color: #343434; \n\
} \n\
h1 em, h2 em { \n\
padding: 0 5px; \n\
font-weight: normal; \n\
} \n\
h1 { \n\
text-shadow: 1px 2px 2px #ddd; \n\
font-size: 60px; \n\
} \n\
h3 { \n\
margin: 5px 0 10px 0; \n\
padding-bottom: 5px; \n\
border-bottom: 1px solid #eee; \n\
font-size: 18px; \n\
} \n\
#wrapper { \n\
margin: 50px auto; \n\
width: 750px; \n\
text-align: left; \n\
} \n\
ul { \n\
margin: 0; \n\
padding: 0; \n\
} \n\
ul li { \n\
margin: 5px 0; \n\
padding: 3px 8px; \n\
list-style: none; \n\
border: 1px solid #eee; \n\
-webkit-border-radius: 3px; \n\
-mox-border-radius: 3px; \n\
-webkit-transition-property: color, padding; \n\
-webkit-transition-duration: 0.1s; \n\
} \n\
ul li:hover { \n\
padding: 3px 20px; \n\
cursor: pointer; \n\
color: #2E2E2E; \n\
} \n\
ul li .path { \n\
padding-left: 5px; \n\
font-weight: bold; \n\
} \n\
ul li .line { \n\
padding-right: 5px; \n\
font-style: italic; \n\
} \n\
ul li:first-child .path { \n\
padding-left: 0; \n\
} \n\
p { \n\
line-height: 1.5; \n\
} \n\
pre { \n\
margin: 0; \n\
padding: 10px; \n\
border: 1px solid #eee; \n\
-webkit-border-radius: 10px; \n\
-moz-border-radius: 10px; \n\
-webkit-box-shadow: 1px 1px 6px #ddd; \n\
-moz-box-shadow: 1px 1px 6px #ddd; \n\
} \n\
table { \n\
margin-bottom: 35px; \n\
width: 100%; \n\
border-collapse: collapse; \n\
} \n\
table td { \n\
padding: 5px 10px; \n\
font-size: 14px; \n\
} \n\
table tr { \n\
border-bottom: 1px solid #fff; \n\
} \n\
table tr:last-child { \n\
border-bottom: none; \n\
} \n\
table td:first-child { \n\
width: 150px; \n\
color: #343434; \n\
} \n\
</style> \n\
'
-55
Ver Arquivo
@@ -1,55 +0,0 @@
// Express - Plugin - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
/**
* Push _plugin_ with _options_ to the plugin stack.
* If _plugin_ has already been pushed, then it's options
* will override any previously set.
*
* @param {Plugin} plugin
* @param {hash} options
* @api public
*/
exports.use = function(plugin, options) {
if (Express.environment === 'test' && 'init' in plugin)
plugin.init(options)
$(Express.plugins).each(function(other, i){
if (other.klass === plugin)
delete Express.plugins[i]
})
Express.plugins.push({
klass: plugin,
options: options
})
}
// --- Plugin
exports.Plugin = Class({
/**
* Initialize with _options_.
*
* @param {hash} options
* @api private
*/
init: function(options) {
if (options)
process.mixin(this, options)
},
/**
* Trigger handler for the given _event_.
*
* @param {Event} event
* @api private
*/
trigger: function(event) {
if ('on' in this)
if (event.name in this.on)
this.on[event.name].call(this, event)
}
})
-12
Ver Arquivo
@@ -1,12 +0,0 @@
// Express - Plugins - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
process.mixin(require('express/plugins/hooks'))
process.mixin(require('express/plugins/flash'))
process.mixin(require('express/plugins/cache'))
process.mixin(require('express/plugins/cookie'))
process.mixin(require('express/plugins/session'))
process.mixin(require('express/plugins/profiler'))
process.mixin(require('express/plugins/common-logger'))
process.mixin(require('express/plugins/content-length'))
process.mixin(require('express/plugins/method-override'))
-22
Ver Arquivo
@@ -1,22 +0,0 @@
// Express - BodyDecoder - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
var queryString = require('querystring')
exports.BodyDecoder = Plugin.extend({
on: {
/**
* Decodes common content-types, currently handles:
*
* - application/x-www-form-urlencoded
*/
request: function(event) {
var request = event.request
if (request.header('content-type') &&
request.header('content-type').indexOf('application/x-www-form-urlencoded') > -1)
request.params.post = queryString.parseQuery(request.body)
}
}
})
-218
Ver Arquivo
@@ -1,218 +0,0 @@
// Express - Cache - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
// --- Cache
var Cache = Class({
/**
* Initialize cache with _key_ and _val_.
*/
init: function(key, val) {
this.key = key
this.val = val
this.created = Number(new Date)
}
})
// --- Store
exports.Store = Class({
/**
* Ensure that the given _key_ is a string.
* Override in subclass to provide data-store specific functionality.
*
* @param {string} key
* @param {string} val
* @api public
*/
set: function(key, val) {
if (typeof key !== 'string') throw new Error(this.name + ' store #set() key must be a string')
},
/**
* Ensure that the given _key_ is a string.
* Override in subclass to provide data-store specific functionality.
*
* @param {string} key
* @api public
*/
get: function(key) {
if (typeof key !== 'string') throw new Error(this.name + 'store #get() key must be a string')
},
/**
* Convert to '[NAME Store]'.
*
* @return {string}
* @api public
*/
toString: function() {
return '[' + this.name + ' Store]'
}
})
// --- Store.Memory
exports.Store.Memory = exports.Store.extend({
/**
* Datastore name.
*/
name: 'Memory',
/**
* Initialize data.
*/
init: function() {
this.data = {}
},
/**
* Set the given _key_ to _val_, returning _val_.
*
* @param {string} key
* @param {string} val
* @return {string}
* @api public
*/
set: function(key, val) {
this.__super__(key, val)
return this.data[key] = new Cache(key, val), val
},
/**
* Get data found matching the given _key_.
*
* Examples:
*
* cache.get('page:front')
* // => '<html>...</html>'
*
* cache.get('page:*')
* // => { 'page:front': '<html>...</html>',
* 'page:users': '<html>...</html>',
* ... }
*
* @param {string} key
* @return {mixed}
* @api public
*/
get: function(key) {
this.__super__(key)
if (key.indexOf('*') === -1)
return this.data[key] instanceof Cache ?
this.data[key].val :
null
var regexp = this.normalize(key)
return $(this.data).reduce({}, function(vals, cache){
if (regexp.test(cache.key))
vals[cache.key] = cache.val
return vals
})
},
/**
* Clear data matching the given _key_.
*
* Examples:
*
* cache.clear('page:front')
* cache.clear('page:*')
*
* @param {string} key
* @api public
*/
clear: function(key) {
if (key.indexOf('*') === -1)
return delete this.data[key]
var regexp = this.normalize(key)
for (var key in this.data)
if (this.data.hasOwnProperty(key))
if (regexp.test(key))
delete this.data[key]
},
/**
* Reap caches older than _ms_.
*
* @param {int} ms
* @api private
*/
reap: function(ms) {
var self = this,
threshold = Number(new Date(Number(new Date) - ms))
$(this.data).each(function(cache){
if (cache.created < threshold)
self.clear(cache.key)
})
},
/**
* Convert the given key matching _pattern_
* into a RegExp.
*
* - * is converted to (.*?)
*
* @param {string} pattern
* @return {regexp}
* @api private
*/
normalize: function(pattern) {
return new RegExp('^' + pattern.replace(/[*]/g, '(.*?)') + '$')
}
})
// --- Cache
exports.Cache = Plugin.extend({
extend: {
/**
* Initialize memory store and start reaper.
*
* Options:
*
* - dataStore constructor name of cache data store, defaults to Store.Memory
* - lifetime lifetime of cache in milliseconds, defaults to one day
* - reapInterval, reapEvery interval in milliseconds in which to reap old caches, defaults to one hour
*
* @param {hash} options
* @api private
*/
init: function(options) {
process.mixin(this, options)
this.store = new (this.dataStore || exports.Store.Memory)(options)
Request.include({ cache: this.store })
this.startReaper()
},
/**
* Start reaper.
*
* @api private
*/
startReaper: function() {
var self = this,
oneDay = 86400000,
oneHour = 3600000
setInterval(function(){
self.store.reap(self.lifetime || oneDay)
}, self.reapInterval || self.reapEvery || oneHour)
}
}
})
-50
Ver Arquivo
@@ -1,50 +0,0 @@
// Express - CommonLogger - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
/**
* Months.
*/
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
/**
* Format _date_.
*
* @param {Date} date
* @return {string}
* @api private
*/
function format(date) {
var d = date.getDate(),
m = months[date.getMonth()],
y = date.getFullYear(),
h = date.getHours(),
mi = date.getMinutes(),
s = date.getSeconds()
return (d < 10 ? '0' : '') + d + '/' + m + '/' + y + ' ' +
(h < 10 ? '0' : '') + h + ':' + (mi < 10 ? '0' : '') +
mi + ':' + (s < 10 ? '0' : '') + s
}
// --- CommonLogger
exports.CommonLogger = Plugin.extend({
on: {
/**
* Output log data.
*/
response: function(event) {
puts([event.request.headers.host,
'-',
'-',
'[' + format(new Date) + ']',
'"' + event.request.method.toUpperCase() + ' ' + (event.request.url.pathname || '/') +
' HTTP/' + event.request.httpVersion + '"',
event.request.response.status,
event.request.response.headers['content-length'] || 0].join(' '))
}
}
})
-18
Ver Arquivo
@@ -1,18 +0,0 @@
// Express - ContentLength - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
exports.ContentLength = Plugin.extend({
on: {
/**
* Assign Content-Length header unless present.
*/
response: function(event) {
var response = event.request.response
response.headers['content-length'] =
response.headers['content-length'] ||
response.body.length
}
}
})
-110
Ver Arquivo
@@ -1,110 +0,0 @@
// Express - Cookie - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
/**
* Parse an HTTP _cookie_ string into a hash.
*
* @param {string} cookie
* @return {hash}
* @api public
*/
exports.parseCookie = function(cookie) {
return $(cookie.replace(/^ *| *$/g, '').split(/ *; */)).reduce({}, function(hash, pair){
var parts = pair.split(/ *= */)
hash[parts[0]] = parts[1]
return hash
})
}
/**
* Compile cookie _name_, _val_ and _options_ to a string.
*
* @param {string} name
* @param {string} val
* @param {hash} options
* @return {string}
* @api public
*/
exports.compileCookie = function(name, val, options) {
if (!options) return name + '=' + val
return name + '=' + val + '; ' + $(options).map(function(val, key){
if (val instanceof Date)
val = val.toString()
.replace(/^(\w+)/, '$1,')
.replace(/(\w+) (\d+) (\d+)/, '$2-$1-$3')
.replace(/GMT.*$/, 'GMT')
return val === true ? key : key + '=' + val
}).toArray().join('; ')
}
// --- Cookie
exports.Cookie = Plugin.extend({
extend: {
/**
* Initialize extensions.
*/
init: function() {
Request.include({
/**
* Get or set cookie values.
*
* Options:
*
* - path Cookie path, defaults to '/'
* - domain Tail matched domain name such as 'vision-media.ca' or 'blog.vision-media.ca' etc
* - expires Date object converted to 'Wdy, DD-Mon-YYYY HH:MM:SS GMT'
* when undefined the cookie will last the duration of a the
* client's session.
* - secure When true the cookie will be sent by the client only when transfering data via HTTPS
* - httpOnly When true the cookie will be sent to the server only and will not be accessable via
* client-side scripting.
*
* @param {string} name
* @param {string} val
* @param {hash} options
* @return {string}
* @api public
*/
cookie: function(name, val, options) {
options = options || {}
options.path = options.path || '/'
return val ?
this.response.cookies.push(exports.compileCookie(name, val, options)) :
this.cookies[name]
}
})
}
},
// --- Events
on: {
/**
* Parse request cookie data.
*/
request: function(event) {
event.request.response.cookies = []
event.request.cookies = event.request.headers.cookie ?
exports.parseCookie(event.request.headers.cookie) :
{}
},
/**
* Set the Set-Cookie header when response cookies are available.
*/
response: function(event) {
if (event.response.cookies.length)
event.request.header('set-cookie', event.response.cookies.join(', '))
}
}
})
-51
Ver Arquivo
@@ -1,51 +0,0 @@
// Express - Flash - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
exports.Flash = Plugin.extend({
extend: {
/**
* Initialize extensions.
*/
init: function(){
Request.include({
/**
* Get / set flash _key_ and _val_.
*
* When a flash _key_ and _val_ are present,
* it will persist in the session until outputted.
* The _val_ pushed is returned.
*
* Example:
*
* this.flash('info', 'email sent')
* this.flash('info', 'email received')
* this.flash('info')
* // => ['email sent', 'email received']
*
* this.flash('info')
* // => null
*
* @param {string} key
* @param {string} val
* @return {string}
* @api public
*/
flash: function(key, val) {
if (!this.session.flash) this.session.flash = {}
if (!(key in this.session.flash)) this.session.flash[key] = []
if (val)
return this.session.flash[key].push(val), val
else if (key) {
var vals = this.session.flash[key]
delete this.session.flash[key]
if (vals.length) return vals
}
}
})
}
}
})
-67
Ver Arquivo
@@ -1,67 +0,0 @@
// Express - Hooks - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
exports.callbacks = { before: [], after: [] }
/**
* Add a _fn_ to be excuted before a request.
*
* @param {function} fn
* @api public
*/
exports.before = function(fn) {
exports.callbacks.before.push(fn)
}
/**
* Add a _fn_ to be excuted after a request.
*
* @param {function} fn
* @api public
*/
exports.after = function(fn) {
exports.callbacks.after.push(fn)
}
// --- Hooks
exports.Hooks = Plugin.extend({
extend: {
/**
* Initialize extensions.
*/
init: function() {
process.mixin(GLOBAL, { before: exports.before,
after: exports.after })
}
},
// --- Events
on: {
/**
* Invoke all before handlers.
*/
request: function(event) {
$(exports.callbacks.before).each(function(fn){
fn.call(event.request, event.request)
})
},
/**
* Invoke all after handlers.
*/
response: function(event) {
$(exports.callbacks.after).each(function(fn){
fn.call(event.request, event.request)
})
}
}
})
-16
Ver Arquivo
@@ -1,16 +0,0 @@
// Express - MethodOverride - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
exports.MethodOverride = Plugin.extend({
on: {
/**
* Set request method to _method param when present.
*/
request: function(event) {
if (event.request.param('_method'))
event.request.method = event.request.param('_method').toLowerCase()
}
}
})
-51
Ver Arquivo
@@ -1,51 +0,0 @@
// Express - Profiler - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
var n = 0
exports.Profiler = Plugin.extend({
extend: {
/**
* Initialize profiler options.
*
* Options:
*
* - format 'plot' outputs request duration in milliseconds only
*
* @param {hash} options
* @api private
*/
init: function(options) {
process.mixin(this, options)
}
},
// --- Events
on: {
/**
* Start timer.
*/
request: function(event) {
this.start = Number(new Date)
},
/**
* Output duration.
*/
response: function(event) {
if (exports.Profiler.format === 'plot')
puts(Number(new Date) - this.start)
else
puts(event.request.method + ' ' +
event.request.url.pathname + ': ' +
(Number(new Date) - this.start) + ' ms' +
' #' + ++n)
}
}
})
-57
Ver Arquivo
@@ -1,57 +0,0 @@
// Express - Redirect - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
exports.Redirect = Plugin.extend({
extend: {
/**
* Initialize extensions.
*/
init: function() {
Request.include({
/**
* Redirect to _url_ with optional status _code_,
* defaulting to 303 "See Other".
*
* When using redirect('home') the resolution
* is as follows:
*
* - set('home')
* - set('basepath')
* - '/'
*
* When using redirect('back') the HTTP referrer
* header is used. Commonly misspelled as 'referer'
* which is supported as well.
*
* @param {string} url
* @settings 'home', 'basepath'
* @api public
*/
redirect: function(url, code) {
if (url == 'back' || url == 'home') url = this[url]
this.header('location', url)
this.halt(code || 303)
}
})
}
},
// --- Events
on: {
/**
* Assign home to 'home', 'basepath' or '/'.
* Assign back to 'referrer' or 'referer' headers.
*/
request: function(event) {
event.request.home = set('home') || set('basepath') || '/'
event.request.back = event.request.header('referrer') || event.request.header('referer')
}
}
})
-205
Ver Arquivo
@@ -1,205 +0,0 @@
// Express - Session - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
/**
* Module dependencies.
*/
var utils = require('express/utils')
// --- Session
var Session = Class({
/**
* Initialize session _sid_.
*/
init: function(sid) {
this.id = sid
this.touch()
},
/**
* Update last access time.
*
* @api private
*/
touch: function() {
this.lastAccess = Number(new Date)
}
})
// --- Store
exports.Store = Class({
/**
* Convert to '[NAME Store]'.
*
* @return {string}
* @api public
*/
toString: function() {
return '[' + this.name + ' Store]'
}
})
// --- Store.Memory
exports.Store.Memory = exports.Store.extend({
/**
* Datastore name.
*/
name: 'Memory',
/**
* Initialize in-memory session store.
*/
init: function() {
this.store = {}
},
/**
* Fetch session with the given _sid_ or
* a new Session is returned.
*
* @param {int} sid
* @return {Session}
* @api private
*/
fetch: function(sid) {
return this.store[sid] || new Session(sid)
},
/**
* Commit _session_ data.
*
* @param {Session} session
* @api private
*/
commit: function(session) {
return this.store[session.id] = session
},
/**
* Clear all sessions.
*
* @api public
*/
clear: function() {
this.store = {}
},
/**
* Destroy session using the given _sid_.
*
* @param {int} sid
* @api public
*/
destroy: function(sid) {
delete this.store[sid]
},
/**
* Return the number of sessions currently stored.
*
* @return {int}
* @api public
*/
length: function() {
return $(this.store).length()
},
/**
* Reap sessions older than _ms_.
*
* @param {int} ms
* @api private
*/
reap: function(ms) {
var self = this,
threshold = Number(new Date(Number(new Date) - ms))
$(this.store).each(function(session, sid){
if (session.lastAccess < threshold)
self.destroy(sid)
})
}
})
// --- Session
exports.Session = Plugin.extend({
extend: {
/**
* Initialize memory store and start reaper.
*
* Options:
*
* - dataStore   constructor name of session data store, defaults to Store.Memory
* - lifetime lifetime of session in milliseconds, defaults to one day
* - reapInterval, reapEvery interval in milliseconds in which to reap old sessions, defaults to one hour
*
* @param {hash} options
* @api private
*/
init: function(options) {
process.mixin(this, options)
this.store = new (this.dataStore || exports.Store.Memory)(options)
this.startReaper()
},
/**
* Start reaper.
*
* @api private
*/
startReaper: function() {
var self = this,
oneDay = 86400000,
oneHour = 3600000
setInterval(function(){
self.store.reap(self.lifetime || oneDay)
}, self.reapInterval || self.reapEvery || oneHour)
}
},
// --- Events
on: {
/**
* Create session id when not found; delegate to store.
*/
request: function(event) {
var sid
if (!(sid = event.request.cookie('sid')))
event.request.cookie('sid', sid = utils.uid(), set('session cookie'))
event.request.session = exports.Session.store.fetch(sid)
event.request.session.touch()
},
/**
* Delegate to store, allowing it to save sessions changes.
*/
response: function(event) {
exports.Session.store.commit(event.request.session)
}
}
})
-99
Ver Arquivo
@@ -1,99 +0,0 @@
// Express - View - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
/**
* Module dependencies.
*/
var posix = require('posix'),
utils = require('express/utils')
/**
* Supported template engines.
*/
var engine = {
ejs: require('ejs'),
haml: require('haml'),
sass: require('sass')
}
// --- View
exports.View = Plugin.extend({
extend: {
/**
* Initialize extensions.
*/
init: function() {
// Settings
set('views', function(){ return set('root') + '/views' })
// Request
Request.include({
/**
* Render _view_ with _options_.
*
* Views are looked up relative to the'views' path setting.
* View filenames should conform to ANY.ENGINE.TYPE so for example
* 'layout.ejs.html', 'ejs' represents the template engine, 'html'
* represents the type of content being rendered, which is then passed
* to contentType().
*
* Engines must export a render() method accepting the template string
* and a hash of options.
*
* Options:
*
* - layout: The layout to use, none when falsey. Defaults to 'layout'
* - context: Most engines support an evaluation context (the 'this' keyword)
* - locals: Most engines support a hash of local variable names / values.
*
* @param {string} view
* @param {hash} options
* @settings 'views', 'cache view contents'
* @api public
*/
render: function(view, options) {
var self = this,
options = options || {},
path = set('views') + '/' + view,
type = path.split('.').slice(-2)[0],
ext = utils.extname(path),
layout = options.layout === undefined ? 'layout' : options.layout
self.contentType(ext)
function render(content) {
content = engine[type].render(content, options)
if (layout)
self.render(layout + '.' + type + '.' + ext, process.mixin(true, options, {
layout: false,
locals: {
body: content
}
}))
else
self.halt(200, content)
}
if (set('cache view contents') && self.cache.get(path))
render(self.cache.get(path))
else
posix.cat(path).addCallback(function(content){
set('cache view contents') ?
render(self.cache.set(path, content)) :
render(content)
}).addErrback(function(e){
throw e
})
}
})
}
}
})
+165 -259
Ver Arquivo
@@ -1,274 +1,180 @@
// Express - Request - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
/*!
* Express - request
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var StaticFile = require('express/static').File,
statusBodies = require('http').STATUS_CODES,
queryString = require('querystring'),
mime = require('express/mime'),
url = require('url')
// --- InvalidStatusCode
InvalidStatusCode = ExpressError.extend({
name: 'InvalidStatusCode',
init: function(status) {
this.message = status + ' is an invalid HTTP response code'
}
})
// --- InvalidResponseBody
InvalidResponseBody = ExpressError.extend({
name: 'InvalidResponseBody',
init: function(request) {
this.message = request.method + ' ' + JSON.encode(request.url.pathname) + ' did not respond with a body string'
}
})
// --- Helpers
var http = require('http'),
utils = require('./utils'),
mime = require('connect/utils').mime;
/**
* Normalize the given _path_.
* Strips trailing slashes and whitespace.
* Return request header or optional default.
*
* @param {string} path
* @return {string}
* Examples:
*
* req.header('Content-Type');
* // => "text/plain"
*
* req.header('content-type');
* // => "text/plain"
*
* req.header('Accept');
* // => undefined
*
* req.header('Accept', 'text/html');
* // => "text/html"
*
* @param {String} name
* @param {String} defaultValue
* @return {String}
* @api public
*/
exports.normalizePath = function(path) {
return path.replace(/[\s\/]*$/g, '')
http.IncomingMessage.prototype.header = function(name, defaultValue){
return this.headers[name.toLowerCase()] || defaultValue;
};
/**
* Check if the _Accept_ header is present, and includes the given `type`.
*
* When the _Accept_ header is not present `true` is returned. Otherwise
* the given `type` is matched by an exact match, and then subtypes. You
* may pass the subtype such as "html" which is then converted internally
* to "text/html" using the mime lookup table.
*
* Examples:
*
* // Accept: text/html
* req.accepts('html');
* // => true
*
* // Accept: text/*; application/json
* req.accepts('html');
* req.accepts('text/html');
* req.accepts('text/plain');
* req.accepts('application/json');
* // => true
*
* req.accepts('image/png');
* req.accepts('png');
* // => false
*
* @param {String} type
* @return {Boolean}
* @api public
*/
http.IncomingMessage.prototype.accepts = function(type){
var accept = this.header('Accept');
if (!accept || accept === '*/*') {
return true;
} else if (type) {
// Allow "html" vs "text/html" etc
if (type.indexOf('/') < 0) {
type = mime.types['.' + type];
}
// Check if we have a direct match
if (accept.indexOf(type) >= 0) {
return true;
// Check if we have type/*
} else {
type = type.split('/')[0] + '/*';
return accept.indexOf(type) >= 0;
}
} else {
return false;
}
};
/**
* Return the value of param `name` when present.
*
* - Checks route placeholders, ex: _/user/:id_
* - Checks query string params, ex: ?id=12
* - Checks urlencoded body params, ex: id=12
*
* To utilize urlencoded request bodies, `req.body`
* should be an object. This can be done by using
* the `connect.bodyDecoder` middleware.
*
* @param {String} name
* @return {String}
* @api public
*/
http.IncomingMessage.prototype.param = function(name){
// Route params like /user/:id
if (this.params.path[name] !== undefined) {
return this.params.path[name];
}
// Query string params
if (this.params.get[name] !== undefined) {
return this.params.get[name];
}
// Request body params via connect.bodyDecoder
if (this.body && this.body[name] !== undefined) {
return this.body[name];
}
};
/**
* Queue flash `msg` of the given `type`.
*
* Examples:
*
* req.flash('info', 'email sent');
* req.flash('error', 'email delivery failed');
* req.flash('info', 'email re-sent');
* // => 2
*
* req.flash('info');
* // => ['email sent', 'email re-sent']
*
* req.flash('info');
* // => []
*
* req.flash();
* // => { error: ['email delivery failed'], info: [] }
*
* @param {String} type
* @param {String} msg
* @return {Array|Object|Number}
* @api public
*/
http.IncomingMessage.prototype.flash = function(type, msg){
var msgs = this.session.flash = this.session.flash || {};
if (type && msg) {
msg = utils.miniMarkdown(utils.htmlEscape(msg));
return (msgs[type] = msgs[type] || []).push(msg);
} else if (type) {
var arr = msgs[type];
delete msgs[type];
return arr || [];
} else {
this.session.flash = {};
return msgs;
}
};
// Callback for isXMLHttpRequest / xhr
function isxhr() {
return this.header('X-Requested-With', '').toLowerCase() === 'xmlhttprequest';
}
// --- Request
/**
* Check if the request was an _XMLHttpRequest_.
*
* @return {Boolean}
* @api public
*/
exports.Request = Class({
/**
* Initialize with node's _request_ and _response_ objects.
*
* - Defaults headers to {}
* - Parses request url
* - Normalizes url pathname
* - Parses GET params when available
* - Initializes plugins
*
* @param {object} request
* @param {object} response
* @api private
*/
init: function(request, response) {
process.mixin(true, this, request)
response.headers = {}
this.response = response
this.url = url.parse(this.url)
this.url.pathname = exports.normalizePath(this.url.pathname)
this.params = this.params || {}
this.params.path = {}
this.params.get = this.url.query ? queryString.parseQuery(this.url.query) : {}
this.params.post = this.params.post || {}
this.plugins = $(Express.plugins).map(function(plugin){
return new plugin.klass(plugin.options)
})
},
/**
* Set response header _key_ and _val_ or get
* request header value by _key_.
*
* @param {string} key
* @param {string} val
* @return {string}
* @api public
*/
header: function(key, val) {
return val === undefined ?
this.headers[key.toLowerCase()] :
this.response.headers[key.toLowerCase()] = val
},
/**
* Return a param _key_ value or null.
*
* - Checks route populated path parameters
* - Checks POST parameters
* - Checks GET parameters
*
* @param {string} key
* @return {string}
* @api public
*/
param: function(key) {
return this.params.get[key] ||
this.params.post[key] ||
this.params.path[key]
},
/**
* Check if Accept header includes the mime type
* for any of the given paths, which calls mime.type().
*
* When no Accept header is present true will be
* returned as stated in the HTTP specification.
*
* Example:
*
* this.accepts('png')
* this.accepts('png', 'jpg', 'gif')
* this.accepts('image.png')
* this.accepts('path/to/image.png')
*
* @param {mixed} ...
* @return {bool}
* @api public
*/
accepts: function() {
var accept = this.header('accept')
return accept ?
$(arguments).any(function(path){
var type = mime.type(path)
return accept.indexOf(type) !== -1 ||
accept.indexOf(type.split('/')[0]+'/*') !== -1
}) :
true
},
/**
* Set response status to _code_.
*
* @param {int} code
* @return {Request)
* @api public
*/
status: function(code) {
this.response.status = code
return this
},
/**
* Immediately respond with response _code_, _body_ and optional _encoding_.
* The status _code_ defaults to to 404, and _body_ will
* default to the default body associated with the response
* _code_.
*
* When an invalid status _code_ is passed, InvalidStatusCode
* will be thrown.
*
* @param {int} code
* @param {string} body
* @param {string} encoding
* @see statusBodies
* @api public
*/
halt: function(code, body, encoding) {
this.status(code = code || 404)
if (body = body || statusBodies[code])
return this.respond(body, encoding)
throw new InvalidStatusCode(code)
},
/**
* Respond with _body_ and optional _encoding_.
*
* @param {string} body
* @param {string} encoding
* @see Request#halt()
* @api private
*/
respond: function(body, encoding) {
this.response.body = body
this.trigger('response')
if (typeof this.response.body != 'string') throw new InvalidResponseBody(this)
if (typeof this.response.status != 'number') throw new InvalidStatusCode(this.response.status)
this.response.sendHeader(this.response.status, this.response.headers)
this.response.sendBody(this.response.body, encoding)
this.response.finish()
},
/**
* Set Content-Type header to the mime type
* for the given _path_, which calls mime.type().
*
* @param {string} path
* @return {Request}
* @api public
*/
contentType: function(path) {
this.header('content-type', mime.type(path))
return this
},
/**
* Trigger even _name_ with optional _data_.
*
* @param {string} name
* @param {hash} data
* @return {Request}
* @api public
*/
trigger: function(name, data) {
data = process.mixin(data || {}, {
request: this,
response: this.response
})
this.plugins.each(function(plugin){
plugin.trigger(new Event(name, data))
})
return this
},
/**
* Transfer static file at the given _path_ as an attachment.
* The basename of _path_ is used as the attachment filename.
*
* @param {string} path
* @return {Request}
* @api public
*/
download: function(path) {
return this.attachment(basename(path)).sendfile(path)
},
/**
* Set Content-Disposition header to 'attachment',
* with optional file _path_.
*
* @param {string} path
* @return {Request}
* @api public
*/
attachment: function(path) {
this.header('content-disposition', path ?
'attachment; filename="' + path + '"' :
'attachment')
return this
},
/**
* Transfer static file at the given _path_.
*
* @param {string} path
* @return {Request}
* @api public
*/
sendfile: function(path) {
(new StaticFile(path)).send(this)
return this
}
})
http.IncomingMessage.prototype.__defineGetter__('isXMLHttpRequest', isxhr);
http.IncomingMessage.prototype.__defineGetter__('xhr', isxhr);
+235
Ver Arquivo
@@ -0,0 +1,235 @@
/*!
* Express - response
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var fs = require('fs'),
http = require('http'),
path = require('path'),
utils = require('connect/utils'),
mime = require('connect/utils').mime,
Buffer = require('buffer').Buffer;
/**
* Send a response with the given `body` and optional `headers` and `status` code.
*
* Examples:
*
* res.send(new Buffer('wahoo'));
* res.send({ some: 'json' });
* res.send('<p>some html</p>');
* res.send('Sorry, cant find that', 404);
* res.send('text', { 'Content-Type': 'text/plain' }, 201);
* res.send(404);
*
* @param {String|Object|Number|Buffer} body or status
* @param {Object|Number} headers or status
* @param {Number} status
* @return {ServerResponse}
* @api public
*/
http.ServerResponse.prototype.send = function(body, headers, status){
// Allow status as second arg
if (typeof headers === 'number') {
status = headers,
headers = null;
}
// Defaults
status = status || 200;
headers = headers || {};
// Determine content type
switch (typeof body) {
case 'number':
if (!this.headers['Content-Type']) {
this.contentType('.txt');
}
body = http.STATUS_CODES[status = body];
break;
case 'string':
if (!this.headers['Content-Type']) {
this.contentType('.html');
}
break;
case 'object':
if (body instanceof Buffer) {
if (!this.headers['Content-Type']) {
this.contentType('.bin');
}
} else {
if (!this.headers['Content-Type']) {
this.contentType('.json');
}
body = JSON.stringify(body);
}
break;
}
// Populate Content-Length
if (!this.headers['Content-Length']) {
this.header('Content-Length', body instanceof Buffer
? body.length
: Buffer.byteLength(body));
}
// Merge headers passed
utils.merge(this.headers, headers);
// Respond
this.writeHead(status, this.headers);
this.end(body);
};
/**
* Transfer the given `file`. Automatically sets the _Content-Type_
* response header, and responds with 404 / 500 appropriately.
*
* @param {String} file
* @api public
*/
http.ServerResponse.prototype.sendfile = function(file){
var self = this;
fs.readFile(file, function(err, buf){
if (err) {
self.send(err.errno === process.ENOENT
? 404
: 500);
} else {
self.contentType(file);
self.send(buf);
}
});
};
/**
* Set _Content-Type_ response header passed through `mime.type()`.
*
* Examples:
*
* var filename = 'path/to/image.png';
* res.contentType(filename);
* // res.headers['Content-Type'] is now "image/png"
*
* @param {String} type
* @return {String} the resolved mime type
* @api public
*/
http.ServerResponse.prototype.contentType = function(type){
return this.header('Content-Type', mime.type(type));
};
/**
* Set _Content-Disposition_ header to _attachment_ with optional `filename`.
*
* @param {String} filename
* @return {ServerResponse}
* @api public
*/
http.ServerResponse.prototype.attachment = function(filename){
this.header('Content-Disposition', filename
? 'attachment; filename="' + path.basename(filename) + '"'
: 'attachment');
return this;
};
/**
* Transfer the given `file` with optional `filename` as an attachment.
*
* @param {String} file
* @param {String} filename
* @return {Type}
* @api public
*/
http.ServerResponse.prototype.download = function(file, filename){
this.attachment(filename || file).sendfile(file);
};
/**
* Set or get response header `name` with optional `val`.
*
* @param {String} name
* @param {String} val
* @return {String}
* @api public
*/
http.ServerResponse.prototype.header = function(name, val){
return val === undefined
? this.headers[name]
: this.headers[name] = val;
};
/**
* Redirect to the given `url` with optional response `status`
* defauling to 302.
*
* The given `url` can also be the name of a mapped url, for
* example by default express supports "back" which redirects
* to the _Referrer_ or _Referer_ headers or the application's
* "home" setting. Express also supports "home" out of the box,
* which can be set via `app.set('home', '/blog');`, and defaults
* to '/'.
*
* Redirect Mapping:
*
* To extend the redirect mapping capabilities that Express provides,
* we may use the `app.redirect()` method:
*
* app.redirect('google', 'http://google.com');
*
* Now in a route we may call:
*
* res.redirect('google');
*
* We may also map dynamic redirects:
*
* app.redirect('comments', function(req, res, params){
* return '/post/' + params.id + '/comments';
* });
*
* So now we may do the following, and the redirect will dynamically adjust to
* the context of the request. If we called this route with _GET /post/12_ our
* redirect _Location_ would be _/post/12/comments_.
*
* app.get('/post/:id', function(req, res){
* res.redirect('comments');
* });
*
* @param {String} url
* @param {Number} code
* @api public
*/
http.ServerResponse.prototype.redirect = function(url, status){
var basePath = this.app.set('home') || '/';
// Setup redirect map
var map = {
back: this.req.headers.referrer || this.req.headers.referer || basePath,
home: basePath
};
// Support custom redirect map
map.__proto__ = this.app.redirects;
// Attempt mapped redirect
var mapped = typeof map[url] === 'function'
? map[url](this.req, this, this.req.params.path)
: map[url];
// Perform redirect
this.writeHead(status || 302, { 'Location': mapped || url });
this.end();
};
+196
Ver Arquivo
@@ -0,0 +1,196 @@
/*!
* Express - Server
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var sys = require('sys'),
url = require('url'),
view = require('./view'),
connect = require('connect'),
queryString = require('querystring'),
router = require('connect/middleware/router');
/**
* Initialize a new `Server` with optional `middleware`.
*
* @param {Array} middleware
* @api public
*/
var Server = exports = module.exports = function Server(middleware){
var self = this;
this.config = {};
this.settings = {};
this.redirects = {};
connect.Server.call(this, middleware || []);
// Expose objects to each other
this.use('/', function(req, res, next){
req.params = req.params || {};
req.params.get = {};
res.headers = {};
req.app = res.app = self;
req.res = res;
res.req = req;
// Assign req.params.get
if (req.url.indexOf('?') > 0) {
// TODO: consider simple substr to increase performance
var query = url.parse(req.url).query;
req.params.get = queryString.parse(query);
}
next();
});
// Use router, expose as app.get(), etc
this.use('/', router(function(app){
self.routes = app;
}));
};
/**
* Inherit from `connect.Server`.
*/
sys.inherits(Server, connect.Server);
/**
* Start listening on the given `port` / `host`.
*
* @param {Number} port
* @param {String} host
* @api public
*/
Server.prototype.listen = function(port, host){
this.set('env', process.env.EXPRESS_ENV || process.connectEnv.name);
this.runConfig('any', this.set('env'));
// Setup view reloading
if (this.set('reload views')) {
view.watcher.call(this, this.set('reload views'));
}
connect.Server.prototype.listen.call(this, port, host);
};
/**
* Run config callbacks for the given environment(s);
*
* @param {String} env ...
* @return {Server} for chaining
* @api private
*/
Server.prototype.runConfig = function(){
for (var i = 0, len = arguments.length; i < len; ++i) {
var env = arguments[i];
if (env in this.config) {
var config = this.config[env];
config.forEach(function(fn){
fn.call(this);
}, this);
}
}
return this;
};
/**
* Assign a custom exception handler callback `fn`.
*
* @param {Function} fn
* @return {Server} for chaining
* @api public
*/
Server.prototype.error = function(fn){
this.use('/', function(err, req, res, next){
fn.apply(this, arguments);
});
return this;
};
/**
* Assign `setting` to `val`, or return `setting`'s value.
*
* @param {String} setting
* @param {String} val
* @return {Server|Mixed} for chaining, or the setting value
* @api public
*/
Server.prototype.set = function(setting, val){
if (val === undefined) {
return this.settings[setting];
} else {
this.settings[setting] = val;
return this;
}
};
/**
* Enable `setting`.
*
* @param {String} setting
* @return {Server} for chaining
* @api public
*/
Server.prototype.enable = function(setting){
return this.set(setting, true);
};
/**
* Disable `setting`.
*
* @param {String} setting
* @return {Server} for chaining
* @api public
*/
Server.prototype.disable = function(setting){
return this.set(setting, false);
};
/**
* Redirect `key` to `url`.
*
* @param {String} key
* @param {String} url
* @return {Server} for chaining
* @api public
*/
Server.prototype.redirect = function(key, url){
this.redirects[key] = url;
return this;
};
/**
* Disable `setting`.
*
* @param {String} setting
* @return {Server} for chaining
* @api public
*/
Server.prototype.configure = function(env, fn){
if (typeof env === 'function') fn = env, env = 'any';
(this.config[env] = this.config[env] || []).push(fn);
return this;
};
// Generate routing methods
(function(method){
Server.prototype[method] = function(path, fn){
this.routes[method](path, fn);
return this;
};
return arguments.callee;
})('get')('post')('put')('del');

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