Comparar commits
1620 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 82a9817061 | |||
| 685eec0149 | |||
| 910dae16ab | |||
| fd53197b46 | |||
| d84d0b69ef | |||
| b694ba27be | |||
| e3cbac2d77 | |||
| bbaa295ee2 | |||
| 1150a88001 | |||
| 58cfd60000 | |||
| fcf268742d | |||
| 30d71c8f8f | |||
| c3f9398b12 | |||
| f1ac6ab764 | |||
| d6ca5f71bc | |||
| cdca9cf88f | |||
| 5840b42f4a | |||
| a5be68b5b2 | |||
| 9fda13bc25 | |||
| 125dd7a594 | |||
| df2584cc3b | |||
| 4de95c0e7b | |||
| 9ed1f2a446 | |||
| 833a4873a4 | |||
| 6ca1807372 | |||
| 9da3e9ccc7 | |||
| 5f65c36171 | |||
| d64bb2f886 | |||
| fc179c8fc3 | |||
| 8235af47fe | |||
| 908f3da3da | |||
| 64aac199de | |||
| 503c45840f | |||
| 6f102ff40f | |||
| 6e26a8d366 | |||
| d9aea70ccc | |||
| dd33ef2eb6 | |||
| f3a32f2e29 | |||
| 1a3e40d818 | |||
| 18cdb3d845 | |||
| 0fca62c037 | |||
| e9cd82b72d | |||
| 4d9ad21047 | |||
| 1cc2dc7150 | |||
| 3dc88b2c0c | |||
| 53f1ffb4e7 | |||
| 579a1be7c8 | |||
| c0a68fcd0d | |||
| b79853e9bd | |||
| f86838ceab | |||
| 809e0b8c92 | |||
| a58e3deac2 | |||
| 430699c082 | |||
| b04233981f | |||
| de10194f33 | |||
| 7c2e1ad0ed | |||
| 67ddb429e3 | |||
| a169cc7119 | |||
| 9719b58575 | |||
| 13c18fa363 | |||
| c17ad6ef65 | |||
| 2c14d0c966 | |||
| 2cd1783613 | |||
| 06db11cd61 | |||
| 125421ec45 | |||
| cc84f40d61 | |||
| c130918135 | |||
| babeb4633e | |||
| 30167356f2 | |||
| 441b309959 | |||
| b7b032f8e0 | |||
| 50f43462ae | |||
| bd2a972dba | |||
| 3c162ae030 | |||
| 3c12757d9e | |||
| fa746cc027 | |||
| 1e85178c73 | |||
| d0bc0ad2ca | |||
| c33f1bac08 | |||
| 58d522d824 | |||
| 858e4dccdc | |||
| c2054077f4 | |||
| 754dd320ff | |||
| a376980a69 | |||
| cf7d710bc1 | |||
| 8f8740028c | |||
| b0e03eb8a8 | |||
| 929dc703ca | |||
| 18a6bbfd80 | |||
| 73092c9898 | |||
| b739126707 | |||
| c39cf1ef84 | |||
| 861f6baa66 | |||
| 25fe426266 | |||
| 85fc586ee5 | |||
| 2a951e961b | |||
| 42aeab500b | |||
| 808a8a314a | |||
| b809041894 | |||
| 1ddf0c8a42 | |||
| d8caf209e3 | |||
| 22668555ad | |||
| 0f585931a4 | |||
| d03386571d | |||
| 72948068e2 | |||
| 97808383ed | |||
| de6f30042f | |||
| b5cee82604 | |||
| fab3e91973 | |||
| c937c797c2 | |||
| 0ddc40ad7f | |||
| e3f6faa350 | |||
| cc69d50c60 | |||
| b55eb5acf5 | |||
| ebabce9982 | |||
| 037d3490ca | |||
| ba7bcbb0d6 | |||
| 79ce6eda6f | |||
| 9f7c9cfc4c | |||
| 5dcc4f46db | |||
| 2f54201774 | |||
| e8eef64601 | |||
| 27b1b5e3b3 | |||
| 5fa2f89542 | |||
| c998b91c09 | |||
| 5be2395170 | |||
| b4cd6bb8f0 | |||
| 7e81cad0bf | |||
| 856f3b3be6 | |||
| 785ac87846 | |||
| 75c29bd42a | |||
| 221a46a396 | |||
| abe5cc7184 | |||
| 12ada75cad | |||
| 5a74d94558 | |||
| d1d3f310e9 | |||
| 089a83363f | |||
| c28e6db428 | |||
| 05253272cb | |||
| 12e087820c | |||
| 8dc001567b | |||
| 9af3256f72 | |||
| cdd333a2e0 | |||
| aa4ec8f3e2 | |||
| 5ea78cf259 | |||
| 600eaea2d1 | |||
| 81b15833f7 | |||
| 9abc221559 | |||
| 7048be2830 | |||
| 91eb27513a | |||
| 04f0682439 | |||
| 36bab5408d | |||
| c483dab4b8 | |||
| f1d759f279 | |||
| 4c1afb2984 | |||
| db9b2bfbe1 | |||
| 377677cf30 | |||
| 24a4e95ffe | |||
| 8fdd9e967a | |||
| acfa6a692e | |||
| 67ca22b6e4 | |||
| ba413ee98d | |||
| acc0e934cb | |||
| 1d485840fd | |||
| dcb147608a | |||
| ddf24d1fd6 | |||
| 886d7e6903 | |||
| 2079ccbf42 | |||
| 5ec88b0f6c | |||
| b0bcd27124 | |||
| 4dfee21e91 | |||
| 18fa2c9c7d | |||
| 04d43d60b7 | |||
| 419731ec41 | |||
| 082ba88084 | |||
| 09a8474521 | |||
| 6d323d3ff7 | |||
| c4e003518a | |||
| 9e251d14af | |||
| 9abba7d69a | |||
| 0377540e2d | |||
| e6a15f66fc | |||
| 1787fd1b52 | |||
| 54c3d5c113 | |||
| 6d0f9a37a2 | |||
| 60dac4d2ff | |||
| dd468fbe9a | |||
| 04ecf04832 | |||
| 6d45616a7a | |||
| 06d2016ee7 | |||
| 984bfadcdd | |||
| f79f3f8b22 | |||
| ba570a9842 | |||
| 365a98d00f | |||
| 4e2677fe2c | |||
| d6d16b7899 | |||
| 86a9e0803a | |||
| fdf96922b5 | |||
| d396761f76 | |||
| 711519361c | |||
| e4827b8d89 | |||
| 7ec7cb94f9 | |||
| 298899d02c | |||
| 43b35a4ae0 | |||
| a7a8dcd617 | |||
| bdf0b26a12 | |||
| 73e87b6a2e | |||
| ac3d002cb2 | |||
| ada2d0c627 | |||
| 286d3a1ff8 | |||
| 937f01a225 | |||
| c9559e03da | |||
| d115798d5b | |||
| b6ee5fafd0 | |||
| 533b31237c | |||
| 812a470122 | |||
| eb3105ef25 | |||
| ffcaa04d2c | |||
| a47660ba67 | |||
| e2291184dc | |||
| 4e332452b7 | |||
| e2f43df5e9 | |||
| 141929cd6e | |||
| ec03968bd4 | |||
| a21435cb05 | |||
| bdfa6d1fe7 | |||
| b565e258cb | |||
| 892b605ab5 | |||
| 4d99352526 | |||
| cbf0eaa429 | |||
| 80e16c8ca3 | |||
| 0ae024afa8 | |||
| 73caacbd42 | |||
| b667bda8f2 | |||
| 463e38cf67 | |||
| 83c8d65e3d | |||
| 9548e7d1e2 | |||
| ee290d82d1 | |||
| b75bb003bd | |||
| 6c2194fdb4 | |||
| da61d8b639 | |||
| 863ba199f6 | |||
| 161ebb354f | |||
| 1516ebf7f9 | |||
| 2820f2227d | |||
| a078f5f5c1 | |||
| d0a83053d3 | |||
| b6bc01abde | |||
| 196a1eb6ad | |||
| 593271f536 | |||
| 0f24f715ba | |||
| bb9bfa5618 | |||
| 8120a06cd6 | |||
| a153082120 | |||
| 970031e267 | |||
| a819856f3f | |||
| 4dbaaa2855 | |||
| 0593cf4379 | |||
| cd0e5dbb4c | |||
| 7cb1c3cabb | |||
| 550b9101b8 | |||
| 9d9564568b | |||
| 7ea7a53e7c | |||
| ac387caf21 | |||
| ad3f1e84aa | |||
| 2432a0dda5 | |||
| 03e5919910 | |||
| 277e35f8c8 | |||
| 0dd5836f3f | |||
| 9290f0d407 | |||
| 9bd3ad846e | |||
| a8c73649ce | |||
| 6368ab49b4 | |||
| 16b6a64ef9 | |||
| e46431ee0e | |||
| 2e4cf0aa5c | |||
| 3f8a7f05e8 | |||
| 3360613bcd | |||
| f8a9cbe074 | |||
| 15f2e0c899 | |||
| 6518e746c1 | |||
| 38b046d6ad | |||
| 28d7750eda | |||
| e5fc85bddc | |||
| 2a40571118 | |||
| f1aa57c57e | |||
| 0b876ece41 | |||
| ca0bd1a0b5 | |||
| 2d31b5df34 | |||
| 10f7ca0ebf | |||
| 85d6964874 | |||
| 76fd462bcc | |||
| c44f01879f | |||
| fe27989a69 | |||
| b04f3eeede | |||
| 6ab61d023f | |||
| 4d87efc771 | |||
| e47d368239 | |||
| 5b1235addc | |||
| 8c2c1240e1 | |||
| 27e696b7b1 | |||
| bfba98f532 | |||
| 8de3ad50b2 | |||
| 2ba343d2b5 | |||
| ff92afa557 | |||
| c3c0fb95a8 | |||
| bb56a094bb | |||
| 2211943170 | |||
| 4eb8bc0857 | |||
| fa51cb8d63 | |||
| 706dec93a4 | |||
| 7a32920448 | |||
| 57a3899c1d | |||
| 374d159e0e | |||
| 4f5a41b84f | |||
| a2f380fdd6 | |||
| 301085e510 | |||
| af5b64a434 | |||
| fa088e37bc | |||
| 613bdc91e5 | |||
| edfe50e713 | |||
| 26fb403ced | |||
| 014fb46449 | |||
| 144a88b109 | |||
| 34c0d2509a | |||
| a12a9e3fd9 | |||
| 8df73f3d83 | |||
| 6dac874ff4 | |||
| 81d25f6861 | |||
| c0c1975da6 | |||
| dd7af29103 | |||
| 85ea5f67f4 | |||
| 8e3cb6174d | |||
| 6c01e9a43a | |||
| 6061670161 | |||
| 7c66db2c45 | |||
| 05e95ae55a | |||
| 416ad564d0 | |||
| 55f8f9bc42 | |||
| 386a9e88b4 | |||
| f6ca25edbe | |||
| 1ea221aa4e | |||
| d72a6666a1 | |||
| b69199f884 | |||
| 65042c86a6 | |||
| d7dccfd56d | |||
| e60f4a5e1e | |||
| fa3d4cbb23 | |||
| 56d303ec09 | |||
| 4600548b4d | |||
| 7d24c2ba40 | |||
| b4ce57caec | |||
| 43c09b2eaa | |||
| b32fd0bee4 | |||
| 3b6e96efa9 | |||
| 29ef828b9c | |||
| 39ae443433 | |||
| c30c2f8d38 | |||
| 5757f875f2 | |||
| e49c482a3f | |||
| a592d6c1aa | |||
| 88f154fecd | |||
| d7dfe3e812 | |||
| 489265e3ca | |||
| 3212a70a0c | |||
| 1cda0a96ca | |||
| 83fb9f7548 | |||
| 43295289bf | |||
| 0f72ca823b | |||
| 41786bc776 | |||
| cca5d7ebbf | |||
| 43c8764465 | |||
| a1e325a2d9 | |||
| 17a831e32f | |||
| 2a13db3bb8 | |||
| eb5a73538a | |||
| 006a6c787b | |||
| c3d96df0f0 | |||
| 15e7218bc4 | |||
| 28f32b9b8e | |||
| 1d0a56b673 | |||
| ad1424681b | |||
| 87b991c076 | |||
| 5d593f26af | |||
| 853c270fce | |||
| fcf34e0587 | |||
| b6611c8a3b | |||
| aab08d774b | |||
| 321aa52384 | |||
| 1334a74ef1 | |||
| 19e3384bb1 | |||
| 6ae32fd596 | |||
| 4c316ba4ce | |||
| f2719411b7 | |||
| 11faf6684e | |||
| 547d18ce46 | |||
| f183a81289 | |||
| e44c874cab | |||
| 9c7380efe4 | |||
| 5e071a2e4b | |||
| ff9b82c4f6 | |||
| a0d0ac6cff | |||
| b605a5de87 | |||
| 36be2b0688 | |||
| 376a5da705 | |||
| c25258b75c | |||
| c685f3a294 | |||
| f63767af0e | |||
| 4fa9a2e54b | |||
| 68bc592a05 | |||
| 543fe2f2a4 | |||
| be52f38d8f | |||
| 722a92f374 | |||
| d771d06e19 | |||
| a5227191b5 | |||
| 499d3d6d78 | |||
| 2adf020753 | |||
| e8c373694c | |||
| a8fd8cb645 | |||
| fd06084106 | |||
| 285500488d | |||
| 29d4ffd089 | |||
| fe5efa597b | |||
| b93629a903 | |||
| 0c72940933 | |||
| 96f5279e3e | |||
| 821fa10203 | |||
| 9082e74971 | |||
| 7a7d77e7bd | |||
| ce2ec94e96 | |||
| d56e5d6923 | |||
| 5221ecc055 | |||
| 6ac2c6f578 | |||
| 772b752fa5 | |||
| 3c002d08c2 | |||
| 2876424240 | |||
| 74a0177ec9 | |||
| da96844e9a | |||
| 81652c8244 | |||
| f17434c95b | |||
| 01e854b5d2 | |||
| 42953c7c44 | |||
| 5e56446d26 | |||
| 61652f4ad9 | |||
| fc1e84941d | |||
| 953eba0376 | |||
| 5c032269e3 | |||
| 1322d5a2c1 | |||
| 114f272906 | |||
| 1286bbb982 | |||
| 9141c649e7 | |||
| ff2242da31 | |||
| 730a419984 | |||
| 25bd7d7997 | |||
| 77c9d9207d | |||
| 1e77629f1f | |||
| 76f65456ab | |||
| 26e20e7ae5 | |||
| 96217cf3fe | |||
| e9c96d8ccd | |||
| 7ae2b968bb | |||
| 83ea42afe5 | |||
| 16587fcce1 | |||
| ffded44f32 | |||
| 92c5284b80 | |||
| f96102224c | |||
| bf87d626eb | |||
| e21a79dc61 | |||
| caec590fe1 | |||
| 61ce6c59c2 | |||
| 205a1a14c7 | |||
| 6709ab5f27 | |||
| 2d77279c94 | |||
| e9d7b6fbad | |||
| 3e6171c7ff | |||
| 04389fd6ff | |||
| a47b599048 | |||
| 58eddd5ab4 | |||
| 7ac857acef | |||
| e27b224933 | |||
| 4f087df286 | |||
| 87f6f6a3e3 | |||
| 94d1e94cf2 | |||
| d249868e07 | |||
| 429e48d873 | |||
| abb414c702 | |||
| 8f45dd4190 | |||
| d9098c5fcd | |||
| b9dee730a8 | |||
| 26c62a667f | |||
| 7d42ad00ff | |||
| 4a5776b513 | |||
| f68ba2ef35 | |||
| a95a0ab5f9 | |||
| 30911f4a75 | |||
| c9f184c8d5 | |||
| 545f1fd07d | |||
| 2f762265a8 | |||
| 7e6d8f39b4 | |||
| bea74b7711 | |||
| 10e8dc57eb | |||
| f7b6dde086 | |||
| 2fa36fa721 | |||
| 40f8202402 | |||
| 4b0b55c1b7 | |||
| 0e395973c9 | |||
| 1f53cdb62d | |||
| c32023d8ed | |||
| d2f98940d8 | |||
| 536b16c7a9 | |||
| 9bfeae2df1 | |||
| 4d450ea25e | |||
| 84f01d1e30 | |||
| 1a5636b199 | |||
| af46df7eae | |||
| 801a1791d6 | |||
| 333cf0b280 | |||
| 52e26697a9 | |||
| fdf620b688 | |||
| 66f8ca52d6 | |||
| f98c1127a6 | |||
| 7e352fe28d | |||
| d3b48e2fd5 | |||
| 23159c094d | |||
| 2e22887f71 | |||
| c9b04b8be7 | |||
| 2c0e13b513 | |||
| 2937309f00 | |||
| 377056a33c | |||
| f42ce5be2b | |||
| ddeee9b6db | |||
| 6bee32c174 | |||
| 11f55a06dd | |||
| 6a2d6b872b | |||
| d8787867c4 | |||
| 43d9f6ea17 | |||
| 1faba1302f | |||
| 55ee0a0934 | |||
| 0653f73779 | |||
| 7a24021dc9 | |||
| 9f2fe94484 | |||
| a3950b5638 | |||
| 8c03428279 | |||
| f4d7ea386d | |||
| bee0496cb1 | |||
| 5960b90efe | |||
| 0f2f3d4e29 | |||
| bc673bef79 | |||
| 3fb7391b97 | |||
| 442cd7515d | |||
| a013ffe547 | |||
| 835558229f | |||
| dce23c79a1 | |||
| 4106bae79e | |||
| b756474d9d | |||
| b0c9209726 | |||
| c96b778771 | |||
| d0d721d80b | |||
| 7b50a78662 | |||
| aa869c637a | |||
| f467fe1cbf | |||
| 15fd639cd9 | |||
| f96f2cf56e | |||
| b0f6278cea | |||
| ae7bac9a6b | |||
| c8997204d4 | |||
| a2c51984a8 | |||
| ed93e33d59 | |||
| 6e15b1cd20 | |||
| cc2513facf | |||
| e303dcc915 | |||
| 8ad17abb7b | |||
| 5b296b5257 | |||
| 1a5c32f3ef | |||
| a15e745d42 | |||
| d17dd3e3d8 | |||
| 51a5c829bb | |||
| 8a91749e12 | |||
| 42fc0f9ee8 | |||
| 17ccd55d11 | |||
| b8a589d76f | |||
| becf6d9413 | |||
| 9efc4b23dc | |||
| 6b1dc31759 | |||
| 9205d632cc | |||
| a751346b20 | |||
| 8111a19307 | |||
| 860b4f1a3b | |||
| a5b1aa9ca7 | |||
| 62257bce18 | |||
| 0ed74aa68b | |||
| e0bd0d6470 | |||
| b433550556 | |||
| 04ebd8875b | |||
| 1a1ed0ae45 | |||
| d6fabb6f8e | |||
| 08e8194db1 | |||
| 0e4e050b21 | |||
| de17b285b1 | |||
| f640d0973d | |||
| 47ff0dc0cc | |||
| 965e1d63dc | |||
| 73f1da2ff7 | |||
| 0f6ad43e91 | |||
| 8d804a6c4a | |||
| 02f48aabbf | |||
| d4b08e9566 | |||
| 9f1f58fd4b | |||
| 4ed92d50e0 | |||
| 8848004cb7 | |||
| 371b381074 | |||
| 6d47011dcf | |||
| 705cdb6368 | |||
| 90fc80fd87 | |||
| 041974ee01 | |||
| 7369d861ca | |||
| e1da383aed | |||
| 6bcf29152f | |||
| 8a38211bd9 | |||
| cb2b9feb5f | |||
| c2d5d5619b | |||
| 76b7d6975f | |||
| 7e9186d1ae | |||
| d1ce4c9923 | |||
| fed7fa4cd2 | |||
| 0d0125fc29 | |||
| 98e2c0522f | |||
| 294bc8c1d7 | |||
| ae11d83684 | |||
| aab9b08ec2 | |||
| 31ff7db019 | |||
| c40c54fbee | |||
| cecbaf2efe | |||
| e90413243e | |||
| a9396efeaf | |||
| 60353c6d05 | |||
| 7b5ed50786 | |||
| 02baa2b17c | |||
| d0585bd910 | |||
| adf7124446 | |||
| 7710db4591 | |||
| ce03cf49d8 | |||
| 65c0d14a4e | |||
| 667ed6fcf5 | |||
| d7da40642d | |||
| d6b5047511 | |||
| 3b5a751b25 | |||
| 8a7491c97a | |||
| b3cab31cf7 | |||
| 021655a10a | |||
| e301d43704 | |||
| 54c1a208c3 | |||
| ad9bbda708 | |||
| 341e167eab | |||
| fb031d1ad5 | |||
| d3937b9a61 | |||
| 2c734e2e4c | |||
| 77d8823261 | |||
| 6f85c14738 | |||
| edb1dc067a | |||
| 6b161d5389 | |||
| c21e3feaa6 | |||
| a25ef01da3 | |||
| 0534266490 | |||
| 71aca3c199 | |||
| 72fab80a74 | |||
| c8ab058842 | |||
| b166fd7d6e | |||
| 9545face97 | |||
| 6dacd51b81 | |||
| 571a182712 | |||
| e3aabdc2bc | |||
| 4d8d5b12f2 | |||
| 5785e7e2e5 | |||
| 81f311105c | |||
| ad3679fcb8 | |||
| 29508f1cc7 | |||
| 426ba62348 | |||
| d2df055abe | |||
| d3ccdbcf72 | |||
| 7a476fc964 | |||
| 5da28be2b2 | |||
| 0932bdea30 | |||
| 75054e17cf | |||
| 664907f02e | |||
| f977272732 | |||
| d10b7b43ea | |||
| e9abe1b846 | |||
| cc21f38664 | |||
| 34606c26f0 | |||
| be9d66a574 | |||
| ed9fcde499 | |||
| 3c2139b0c3 | |||
| 7eeec91ab5 | |||
| fdd43ee448 | |||
| ca75492512 | |||
| a2a7644794 | |||
| 91aebc758c | |||
| ca0d29d811 | |||
| c8c6aa2a1f | |||
| 19a1a22e63 | |||
| c729d62f89 | |||
| 1793b50e6b | |||
| 23dbe6a5f0 | |||
| 509601e617 | |||
| d58beed752 | |||
| fd5d1076dc | |||
| 05b76a1f93 | |||
| f84ec803a4 | |||
| c35cd7fcb7 | |||
| bb9d50579b | |||
| 54d37512f5 | |||
| c516be8c4b | |||
| 82c78ec8f9 | |||
| b1d4b71609 | |||
| 7440c7ddc7 | |||
| 624dad5a78 | |||
| f4080210bd | |||
| c631eb43e3 | |||
| 376bedf624 | |||
| 36e9c02f6f | |||
| 8f798569a8 | |||
| 8c0e47baf9 | |||
| 461473e48e | |||
| 8b1f109c1d | |||
| e005cb31d8 | |||
| 579836e221 | |||
| b977ee6160 | |||
| ddce65b9dd | |||
| e0e1105965 | |||
| 1f520f9f99 | |||
| 05a929deb6 | |||
| 5ac5352e33 | |||
| 787a555253 | |||
| 388b84e858 | |||
| 7ffd17254a | |||
| 00affe187c | |||
| 05844efbd6 | |||
| 3ab37028fc | |||
| 3a04888c5f | |||
| 6bd518241a | |||
| a3cddb856f | |||
| 4b8e08d202 | |||
| 9413d30396 | |||
| 5982fa63c6 | |||
| a4621a6418 | |||
| 7eec21a5e6 | |||
| 96b72fe2f7 | |||
| c7c9606e87 | |||
| 772c135d98 | |||
| 365b3a76ba | |||
| 41568b7f2a | |||
| d853f6cf0e | |||
| bcfcce32d3 | |||
| 986916cf3e | |||
| d689656775 | |||
| 8c56df7322 | |||
| 1dc87761a0 | |||
| cd88b92587 | |||
| eab03fdfc4 | |||
| 9a8b86872d | |||
| 04ce039ba4 | |||
| 9605cbda45 | |||
| 3ec2739925 | |||
| d250bf9b56 | |||
| 6ebccb0518 | |||
| b30efe4e2f | |||
| c275d279fc | |||
| 7237a3c3b6 | |||
| f98896f6d7 | |||
| bcb2cdae4c | |||
| 08159211a3 | |||
| 232b6ab7ef | |||
| 3d2676d013 | |||
| 477d06f990 | |||
| ed19885ba1 | |||
| 297ae6fdb4 | |||
| 456a985666 | |||
| 261203d6c1 | |||
| 31262d2ea9 | |||
| c72abc5293 | |||
| 93189ad0b6 | |||
| a8930b161e | |||
| fa31d45285 | |||
| 914e4a4cf7 | |||
| f36d079f28 | |||
| 17ddeef3ba | |||
| f0c90ce668 | |||
| f19b312c48 | |||
| e899a54ba7 | |||
| a4db994c2f | |||
| f98f46c836 | |||
| 336aaaec9a | |||
| b13ec8526e | |||
| 541020ff1b | |||
| 9c153737b4 | |||
| 7d53bb4064 | |||
| 4670751479 | |||
| 8e058f16e4 | |||
| f519f0a5b3 | |||
| bb61304a49 | |||
| 781d991eac | |||
| d04c1f93a3 | |||
| c0aab36187 | |||
| 5ae994ee8f | |||
| 60d16eab77 | |||
| fc60dfc1a6 | |||
| 45d149c146 | |||
| 4dfc1a69c3 | |||
| 0ae18bca60 | |||
| 2aaf0defe7 | |||
| 73ea5cd7ee | |||
| e7f2d229ec | |||
| 87bc265817 | |||
| 796aaff295 | |||
| 8f87c50320 | |||
| ee4471b345 | |||
| 6815feb8cf | |||
| dbbe7be891 | |||
| 09c9452e5c | |||
| b0e669ba00 | |||
| f46ae9f3b2 | |||
| 9f2b344be8 | |||
| 6b47271679 | |||
| 6f7075be74 | |||
| 4b9cc3d698 | |||
| 3faa790b53 | |||
| 9477c9b516 | |||
| b04be51848 | |||
| 9e4020efd3 | |||
| 6db19db665 | |||
| 1386f80ae5 | |||
| e4342a7097 | |||
| fda31b75f9 | |||
| 8ca0a45b33 | |||
| ce2bcaef68 | |||
| 0db7f26ad3 | |||
| 35370da458 | |||
| fe6c5832c2 | |||
| e8c32df79c | |||
| 652e166462 | |||
| af6385f8e4 | |||
| f0277d3777 | |||
| 6bb100d7fa | |||
| f13ea34de3 | |||
| 48a14a443a | |||
| 1820ea6f59 | |||
| 4d9647923e | |||
| 943e9b3a28 | |||
| 6b2ec50a0b | |||
| 7b813b95b6 | |||
| cdaa2e78d7 | |||
| add53d3222 | |||
| f4f79d2217 | |||
| aa36bc4516 | |||
| 9028cacfd1 | |||
| 40ccb595cd | |||
| 5606d08ecb | |||
| 1888d6fca1 | |||
| 5d16e6b302 | |||
| 96f7574bc1 | |||
| 490584c8bc | |||
| 0cbb1f661c | |||
| 3dc53e105a | |||
| e2cdd760d8 | |||
| 4169202a41 | |||
| 835982c561 | |||
| b67bacea18 | |||
| 3205ee7d75 | |||
| ff7d5ff4e5 | |||
| 723774af27 | |||
| c3fbd3fe10 | |||
| d1d3871550 | |||
| 5462c8c7ec | |||
| 9536341e30 | |||
| 1bb798d963 | |||
| 91997e9c53 | |||
| 1393187040 | |||
| 6e69c880d9 | |||
| 59dcd03972 | |||
| 11482546a2 | |||
| 1ce43dd347 | |||
| d1bfe137d4 | |||
| 9d7452cdc2 | |||
| d9cee90efc | |||
| 175aa08500 | |||
| c9ff6198d3 | |||
| f026218c82 | |||
| 5bc86b9e29 | |||
| 5830ac9936 | |||
| d7c6c9a9f9 | |||
| 9c87eed60e | |||
| f15eb6d5ef | |||
| 5b33788359 | |||
| 11ec3ccd48 | |||
| 9d498ba3f1 | |||
| 15d4047180 | |||
| 44eae73843 | |||
| d5b1c70731 | |||
| e78dc18cfd | |||
| 4d122923e9 | |||
| b1a7310263 | |||
| d6ef90d98d | |||
| 85df59ac31 | |||
| b789a28581 | |||
| 4068e7f444 | |||
| 80e9ffbf5d | |||
| 610fc92ca3 | |||
| 0f5dc9bdb2 | |||
| c24b2faec5 | |||
| c407f58dc2 | |||
| 380da0e202 | |||
| 9e5e7a1526 | |||
| 9016b5aaae | |||
| 45f168e873 | |||
| 799938683d | |||
| 7128f2d11f | |||
| 0634bf0b0d | |||
| f9e48c2972 | |||
| 909960c0b3 | |||
| 8a7876f4d1 | |||
| 286c92b13b | |||
| b9872a278f | |||
| 1b34fd7efa | |||
| f05c351762 | |||
| 8323f19e96 | |||
| 565eda9ee5 | |||
| 7aea7194d1 | |||
| 2f68957c8c | |||
| 4ca848e526 | |||
| 31a8c7c19c | |||
| f1c435e050 | |||
| fac75a9bff | |||
| 4fe03ab223 | |||
| c6122da59b | |||
| 131f658779 | |||
| 127f77964e | |||
| 9f2bd30dc7 | |||
| 6e633b31b4 | |||
| 1c65643488 | |||
| 388ad9067a | |||
| f470f0bdc5 | |||
| 72384b0523 | |||
| 1b199b7d98 | |||
| 09b384ea44 | |||
| 56ae55f987 | |||
| 1c360a89ba | |||
| 8636dee13e | |||
| 70e6baf6fc | |||
| 3588c1eedc | |||
| 8d6f167a81 | |||
| 6106188347 | |||
| eeb77541cd | |||
| 99b244b47c | |||
| 3043672448 | |||
| 0477a53c9f | |||
| d9aa7c3bc9 | |||
| 986fac583b | |||
| c6d76086e2 | |||
| e2771364eb | |||
| 0d5a63798b | |||
| 7d15e2bf52 | |||
| 31fef407b6 | |||
| 6bef3ef891 | |||
| b806846049 | |||
| bc16020976 | |||
| 8afb905a43 | |||
| 53667728a8 | |||
| 5f0a854e29 | |||
| e9ef3dd9cd | |||
| f702884704 | |||
| 0cb866845d | |||
| 26483029db | |||
| d2adcbdf67 | |||
| d2f963db2a | |||
| fc2bc1362f | |||
| 6ae45d0fd3 | |||
| cc185a8c0e | |||
| ae1078944c | |||
| 385a05dd10 | |||
| 2572a78648 | |||
| 470774cfba | |||
| 351f6abe4c | |||
| 53a16e1795 | |||
| ff77c8b205 | |||
| b33f38b109 | |||
| b9596d7ce8 | |||
| 251175c025 | |||
| fda1bc4630 | |||
| 83c2c176a9 | |||
| 9be5992f22 | |||
| d8d23c0bf8 | |||
| b2689fc40e | |||
| a4cfde350f | |||
| 7374027457 | |||
| 63328c2177 | |||
| c4e2ce23e5 | |||
| dacad53b2e | |||
| 4ffd5280a7 | |||
| 74310fb464 | |||
| 8b2268cf38 | |||
| fb655f4981 | |||
| 7208c33d72 | |||
| 4efb25d048 | |||
| a3678cd7f6 | |||
| 393d38f1ab | |||
| 805b9ac3a9 | |||
| 379b9812be | |||
| a9992b5647 | |||
| b6c0a9b1b5 | |||
| 1d2dd2a375 | |||
| 63db694aa2 | |||
| b6aca36ad9 | |||
| 8420ae93fd | |||
| 6722716fa7 | |||
| 658e064220 | |||
| 66b472e567 | |||
| 3d242a607e | |||
| bc68e5e7a3 | |||
| aa6858189c | |||
| 06fda62c9e | |||
| 5688ea650d | |||
| f5c4e9d612 | |||
| b9eda2a59d | |||
| 8c168b0971 | |||
| 9c20a50ee2 | |||
| eac666574e | |||
| e4c840f6b8 | |||
| 3afbcd0acf | |||
| 8f054dbcaf | |||
| ccc39e5aa2 | |||
| 53d4da2a9c | |||
| d9e7153fc9 | |||
| dc02b0d5ae | |||
| e0bc5711b8 | |||
| 957cf45fa1 | |||
| f4487343df | |||
| ca1bdb31e3 | |||
| 236a412459 | |||
| 759a57bdb6 | |||
| 1abb674a07 | |||
| 961146a287 | |||
| 573f940985 | |||
| 882916bb2e | |||
| 47d1c62732 | |||
| d39293c025 | |||
| 2942dafdfd | |||
| 4e1aefa5b5 | |||
| 89383ecc57 | |||
| 08046f7692 | |||
| 885fb1fa92 | |||
| 6a58c71528 | |||
| 371d66ba2a | |||
| 25bddf3fb5 | |||
| f6e9fb13f8 | |||
| f0df8434e7 | |||
| e4d3f239e5 | |||
| bcc22dfa6f | |||
| f614709a01 | |||
| 11250d22c9 | |||
| 4b4de29725 | |||
| 99b49d2718 | |||
| 6230ec55be | |||
| 0733d3c585 | |||
| 6f8370ff0e | |||
| bc244ed07e | |||
| 41266aa8e4 | |||
| 45faee3e5b | |||
| 74ff735e10 | |||
| 97879f2b16 | |||
| 1a338251ad | |||
| 354dc768c1 | |||
| 8a0796cd94 | |||
| cbc3b26584 | |||
| d628583db8 | |||
| 058777be1e | |||
| 260d03a0c4 | |||
| 6dcf6f41cc | |||
| 799f790886 | |||
| cb3c4b0ea9 | |||
| 798d255ba6 | |||
| 28ba9e8ac5 | |||
| 7888cb0506 | |||
| 5e284a20cc | |||
| 770357e727 | |||
| 673ba22555 | |||
| fb38d9cfb7 | |||
| dda89a57ec | |||
| 62df63d3a0 | |||
| e71696cf34 | |||
| b5d8d58670 | |||
| 14e6a667f5 | |||
| 0c324783ae | |||
| 5d6ce251ca | |||
| 92c04cee1d | |||
| 7fdf587a7b | |||
| 1e46218b09 | |||
| c56fcd8fb9 | |||
| 319fbf7f64 | |||
| bf06d9077c | |||
| 9d2bd29ee1 | |||
| d11fa1f74e | |||
| c824da0dab | |||
| 9362c83a33 | |||
| 0c38098f02 | |||
| be7068f569 | |||
| b122bf22e3 | |||
| b7232f38f3 | |||
| c1b72ac1b7 | |||
| b9e0d15878 | |||
| cf26cf7afc | |||
| a75e60ae47 | |||
| 187dc5dd03 | |||
| 9c9e2afade | |||
| fae1ba98c1 | |||
| c3e632620a | |||
| dd7158ac46 | |||
| eefe51c7a7 | |||
| bf596dc023 | |||
| 220d88d654 | |||
| a254e64bdb | |||
| 1555b92fb8 | |||
| d5b7a40b39 | |||
| bd1ab7ab96 | |||
| 2ff991bfcf | |||
| 0b1378a539 | |||
| 723c908bd7 | |||
| 4874404701 | |||
| 4c1374840a | |||
| 5da01633fd | |||
| cdbd8af527 | |||
| a6fdc1bfd2 | |||
| 20b8facb05 | |||
| 909914f7af | |||
| 3f31ebc676 | |||
| f3c068a90c | |||
| 90d7e193d1 | |||
| c9f5bb6f17 | |||
| 9865a4c4f2 | |||
| f12baf32d4 | |||
| 80f4d08e8b | |||
| 07c9cae923 | |||
| d867cc9271 | |||
| 3a1fe1e295 | |||
| 3cacf050df | |||
| 1536d73d1b | |||
| 55143a9d44 | |||
| c92e193916 | |||
| d12452fc49 | |||
| 3d8400a40c | |||
| 1fe0aea0b0 | |||
| 5df2544883 | |||
| acbf224277 | |||
| d0d17a0d35 | |||
| f7b53d33bc | |||
| 92be06874b | |||
| f327455d9d | |||
| 54415bf2af | |||
| bac62dfcd9 | |||
| 820b43c1f3 | |||
| a5b69290d5 | |||
| 5c7a9c86f6 | |||
| 7f83f916f6 | |||
| c15a949cc3 | |||
| ce47f96570 | |||
| 57b035cd94 | |||
| f1f126171c | |||
| 71e1bcd855 | |||
| b5579b6307 | |||
| 110b0fe14a | |||
| d7488bbb62 | |||
| 2007407e7b | |||
| d152e7e780 | |||
| d4f4b6682d | |||
| 7f4a12f4cd | |||
| 07d06adf86 | |||
| 47dc188d57 | |||
| 85d22541d2 | |||
| 90ec1031f9 | |||
| 9bc9ad13a4 | |||
| 1782c7d778 | |||
| e85752c527 | |||
| dfdbbb514f | |||
| 976f5ca93e | |||
| 2086f8d34c | |||
| 6873a68216 | |||
| 9eb2c61760 | |||
| 543e791206 | |||
| b6e8b3fa84 | |||
| 6f8e406b7b | |||
| 93bc54b65c | |||
| 3bf0ac4a36 | |||
| bc01bfff21 | |||
| 0d4eaf03fc | |||
| 2bb0412473 | |||
| 07ce5d3158 | |||
| 131970b3e5 | |||
| 00e1dbfbd9 | |||
| 4c274c524d | |||
| 5581ca2751 | |||
| 5cd9a9540f | |||
| 1db2efa75a | |||
| c1a82bf3ea | |||
| 7705042cac | |||
| b9e311e893 | |||
| 460998497d | |||
| 022c5e1411 | |||
| 60daf0d6c7 | |||
| 0b6a941624 | |||
| 1fc520b45a | |||
| cbbee38be8 | |||
| 2dae6d8285 | |||
| 65c8a956f1 | |||
| 2b907e9a8c | |||
| 25e520c243 | |||
| 2124c8465a | |||
| a49e1f4f3d | |||
| 32be4a7812 | |||
| 92967d3457 | |||
| d70fee7432 | |||
| 97b8e75932 | |||
| 8a62f8cef0 | |||
| 10f4f523fa | |||
| 1e392d2628 | |||
| eb6ff62113 | |||
| 64da2621da | |||
| 61aec6e961 | |||
| 42f3ad436d | |||
| 2f7b78c03a | |||
| 402d37d613 | |||
| 96327c979c | |||
| 9d1b3f59d5 | |||
| 14bd50efe4 | |||
| 631c1f95e7 | |||
| 50006f7e43 | |||
| 4c9503158b | |||
| 6c8e461db5 | |||
| aaa8415169 | |||
| 51e964498c | |||
| 0cddc70ff5 | |||
| 99dcf7508f | |||
| 7822d1f148 | |||
| a572a7126c | |||
| a1609faba0 | |||
| 9bf823d893 | |||
| ca184e7725 | |||
| 5054507487 | |||
| ab93be0178 | |||
| 8b0993bb10 | |||
| 0a034bb3ea | |||
| 4ce815a3ed | |||
| 4da860eae1 | |||
| 27e4bdb814 | |||
| dd9406cd52 | |||
| 509312773d | |||
| 42d2758c36 | |||
| ef1c858ffc | |||
| 7fd47c0ac6 | |||
| a63b232ef1 | |||
| acb502e5e3 | |||
| 3661922bb0 | |||
| 0704f149be | |||
| 334604de5d | |||
| 530328ac15 | |||
| 9914a1eb3f | |||
| 5db5710d3f | |||
| 9e9f55a8e3 | |||
| 0800141a9d | |||
| dc6d469f0c | |||
| 89299d77e4 | |||
| 27d8bf6311 | |||
| 8c229a8560 | |||
| 29eed65a67 | |||
| f0e0073a09 | |||
| b70bde58be | |||
| 635fac776d | |||
| 7753d4e91d | |||
| 66a6214216 | |||
| 6cae1f09f1 | |||
| c4432ee827 | |||
| 80a5bf2063 | |||
| 5b3d5fc431 | |||
| cd38fb4177 | |||
| 9b1cc75b36 | |||
| db8b2883e2 | |||
| 59a74ecce4 | |||
| 9099c61df9 | |||
| 50521281ce | |||
| 0cc6abf741 | |||
| fe266ae4fe | |||
| 7c15cdeb69 | |||
| 848086947c | |||
| 5ec4ea754c | |||
| 41467d54df | |||
| 8261437764 | |||
| 54eac368d0 | |||
| 72511ea1e9 | |||
| da7921f2c6 | |||
| cd519e97e7 | |||
| 2a7a5aeefe | |||
| bdbacb41da | |||
| 2dd736a201 | |||
| ec3c797105 | |||
| 770f05c060 | |||
| 6993a27d8e | |||
| 68fd658536 | |||
| 9fc349965d | |||
| 0a667ff741 | |||
| d37ad85f72 | |||
| 2b63568611 | |||
| fcf9f93825 | |||
| 07efc0b73b | |||
| 6813b48c7e | |||
| d58444c6d2 | |||
| dd8a0bd30f | |||
| b65b0636aa | |||
| 9ec6321261 | |||
| 07eb66c205 | |||
| 0e790e6fb5 | |||
| 08186924a4 | |||
| e9faf5cf94 | |||
| 8c0efe09e5 | |||
| 32d2c96d22 | |||
| e958988989 | |||
| 131f10bd80 | |||
| a61615a196 | |||
| 4fdb6910a5 | |||
| 67c4c90351 | |||
| 16f7288b19 | |||
| 36a7e87ae4 | |||
| 16badda118 | |||
| 99820e7edc | |||
| 6a03a92f5f | |||
| 80c3b98a84 | |||
| afd2b4b387 | |||
| df49769f3d | |||
| 05c2946322 | |||
| 2ed392edbf | |||
| 3d597a554d | |||
| 42af4e40ae | |||
| 242efc7219 | |||
| a6bacb857d | |||
| eab54724a1 | |||
| 49885cfeff | |||
| 4330f49011 | |||
| 7687299275 | |||
| 79ba787b03 | |||
| 5a184a205f | |||
| 4b5a6b597a | |||
| 9e9c3eeb79 | |||
| cd996f9dbf | |||
| ab4c91158a | |||
| 1130a23e5b | |||
| 9ac6943220 | |||
| 0f55284b77 | |||
| c75046de3f | |||
| e7df82f110 | |||
| ee4c7d3007 | |||
| 2895303421 | |||
| 3f16f05525 | |||
| fb33671923 | |||
| 482fb5b6e2 | |||
| b1004b61f9 | |||
| 27af9b2605 | |||
| e28ac866f8 | |||
| 5e0a80f227 | |||
| ec0982ca1f | |||
| e7c442d21c | |||
| a9db47fdd3 | |||
| b856a72886 | |||
| 03da0d31f9 | |||
| 1c40e4374b | |||
| d7df1426f2 | |||
| 5035e86f59 | |||
| 0af91265ab | |||
| 8e63d04e66 | |||
| 5ac0c6deb0 | |||
| 6b0d82fb0c | |||
| 2bfdfe366c | |||
| 898fb0f320 | |||
| f53686a2f3 | |||
| eae1670f54 | |||
| 544d68833c | |||
| c24a6b2359 | |||
| b720b57d1d | |||
| 365b7fe90a | |||
| c7ab833e66 | |||
| 9536f288e9 | |||
| e64d4039d0 | |||
| 5f077e56f0 | |||
| a9253a24e0 | |||
| 749136b526 | |||
| 36a8b7b7f3 | |||
| a29908c865 | |||
| 57d87c27cd | |||
| 1c2e9a476c | |||
| 5d87133df0 | |||
| fd2f67b73f | |||
| d3abcaf67b | |||
| 14dce5ac2b | |||
| abd002071a | |||
| 77add42eeb | |||
| bba049b4bf | |||
| 4e41c3520c | |||
| 4144af3351 | |||
| 30f749a2a2 | |||
| 6e9f282af7 | |||
| 4491be01dd | |||
| 8c163fd980 | |||
| 9f6a158fc2 | |||
| 19965fa3c8 | |||
| 6bb42ffafc | |||
| 4a1edc0720 | |||
| a5a016bf33 | |||
| 4be4f597a3 | |||
| dfbbd4f784 | |||
| 2662dae560 | |||
| 6f6f9f08f8 | |||
| a76fba57c4 | |||
| 680766f29b | |||
| adcfd4ca4d | |||
| e276a49a91 | |||
| 5995f763b1 | |||
| a123639b5c | |||
| 8a118d53c8 | |||
| d572391532 | |||
| 58ae7a0402 | |||
| f843093a8c | |||
| 3e06586f81 | |||
| 60f148326a | |||
| 02e1413ca5 | |||
| 7b4b85ee54 | |||
| 6c0a416f16 | |||
| 23cc88bf92 | |||
| 5528f0ddf2 | |||
| 8d3296fb1b | |||
| 136f9209a3 | |||
| a290134fd2 | |||
| a54e59666a | |||
| 42ea6af1eb | |||
| f9b741766b | |||
| 09359329a0 | |||
| 647bb41ddf | |||
| f25c14d48d | |||
| 81a3d559f5 | |||
| 4e0ee7a5da | |||
| 1c80a258d2 | |||
| 129ed6a07b | |||
| df09a0c73b | |||
| ff5c958354 | |||
| 4f90c89db6 | |||
| 524b515fdb | |||
| 163256b001 | |||
| 05bbc65dcc | |||
| 6624f6b7f9 | |||
| f32279dec5 | |||
| a90fd85907 | |||
| 9815b27e94 | |||
| ebbe481fe7 | |||
| 9e337faa33 | |||
| 37826e0261 | |||
| 20e4342796 | |||
| 51be16950d | |||
| be866a78ff | |||
| f9d2432c69 | |||
| 6543a3d75a | |||
| a77936981e | |||
| 6f2120bb59 | |||
| 98e18239fd | |||
| 3d159015be | |||
| f5af66a1ab | |||
| 540192ff96 | |||
| c1cfd4a8c6 | |||
| 322300c329 | |||
| 1ac18f7903 | |||
| 4f4987e9ea | |||
| 65bf562ff4 | |||
| f47032e7e9 | |||
| 379f3ec8dd | |||
| 8d7e35b723 | |||
| 1349eea0d0 | |||
| bed5157f32 | |||
| 12c7f51a1e | |||
| 7e32c8de4d | |||
| 3a42350c21 | |||
| 1a54597202 | |||
| 39f4eb9940 | |||
| 4b996651af | |||
| 884d40f321 | |||
| 3d2b41da08 | |||
| 1bf2dbb7df | |||
| e0dfb77dd1 | |||
| 578fddc1b7 | |||
| 089355d706 | |||
| 6b2c3caf03 | |||
| 065c37cb28 | |||
| 3a40025fd3 | |||
| 8dc341d868 | |||
| 0ed121ddbd | |||
| 969f4229dc | |||
| 27a940184e | |||
| 77fa09a506 | |||
| 8836104ab2 | |||
| 396837517d | |||
| 38b3f1bde2 | |||
| 4780168ba8 | |||
| d1a790d103 | |||
| 3ad6ab8c6a | |||
| 1e189da85e | |||
| a094c50873 | |||
| ad324410c6 | |||
| 9f4b7368a0 | |||
| c8ddedb8d0 | |||
| 7deab2826b | |||
| 643879f779 | |||
| ce2a18f483 | |||
| 487d067f75 | |||
| c4d5e1b4f3 | |||
| 0e0cc30039 | |||
| a766cc791b | |||
| d017c3e248 | |||
| cc27ee04a8 | |||
| 87459bf24b | |||
| 5091c9e10f | |||
| 14a22d9033 | |||
| 7ded5a2de5 | |||
| 6b436a0192 | |||
| 52343686f5 | |||
| eec9d05b19 | |||
| 89703fd430 | |||
| dc246946a7 | |||
| 944e1120cb | |||
| cccda60df8 | |||
| e338e748eb | |||
| 0526a24cf3 | |||
| c4ba1b025a | |||
| 252f330658 | |||
| 45590415a6 | |||
| e562adc752 | |||
| 1e2fd44a6b | |||
| 1c903320be | |||
| 74eaf3a268 | |||
| 6fcd74c713 | |||
| 33136c6553 | |||
| cb225db203 | |||
| 0dbd5006ea | |||
| 08b3677ce8 | |||
| b08549a25b | |||
| 221bc4cb5d | |||
| b655b8e97b | |||
| 03e7b5dcc6 | |||
| 5f09e829df | |||
| e6759919dc | |||
| 6c65a3fc74 | |||
| e0ffd31123 | |||
| 4c1597113a | |||
| 4006506b64 | |||
| 14facdbcd2 | |||
| 726ace49d8 | |||
| f45d383367 | |||
| 3a32e2b53a | |||
| dc45e93cea | |||
| c0f9642719 | |||
| da8d036997 | |||
| 3c911cc785 | |||
| 4071f15f27 | |||
| 90de7923db | |||
| c28f1535a3 | |||
| 704e9c132e | |||
| 713d6f5f76 | |||
| 1a6d245eae | |||
| d909dd2a32 | |||
| 7bb466dd86 | |||
| e09bf5cc40 | |||
| 129e21e7c3 | |||
| 87dcd2909d | |||
| e47ec4f551 | |||
| d6cfcbe149 | |||
| 7a713807e9 | |||
| 6e49b5bc30 | |||
| adbc5b86f5 | |||
| 071ea955af | |||
| 806aefa966 | |||
| 5b7d23186d | |||
| 0cb4677e80 | |||
| bd65ecf17b | |||
| 9da2adff4c | |||
| a2a1aad109 | |||
| dcc530a389 | |||
| 97037a87f3 | |||
| 4e67efc0d6 | |||
| 7cbb73719e | |||
| d3f139c31e | |||
| 8940b6e5a3 | |||
| 1c9831a9f4 | |||
| 7da27435cc | |||
| bd18f86517 | |||
| 41f66b435b | |||
| 48481a7230 | |||
| dde6bc1f80 | |||
| e39fd1de0e | |||
| 2fc9a81e9e | |||
| f65874d751 | |||
| 3914895784 | |||
| 0bc7e24d0a | |||
| 2a40ceced7 | |||
| d4868f2cc2 | |||
| e87d63779d | |||
| 6672d65018 | |||
| 1f78c520f5 | |||
| 687e435a38 | |||
| b3222dc107 | |||
| ebba6caa3d | |||
| 88bbef9003 | |||
| 712771a139 | |||
| 9033b0ded7 | |||
| 877cfe9393 | |||
| 347aa56acb | |||
| 0fc410139c | |||
| 51528235db |
+10
-1
@@ -1,3 +1,4 @@
|
||||
coverage.html
|
||||
.DS_Store
|
||||
lib-cov
|
||||
*.seed
|
||||
@@ -6,4 +7,12 @@ lib-cov
|
||||
*.dat
|
||||
*.out
|
||||
*.pid
|
||||
benchmarks/graphs
|
||||
*.swp
|
||||
*.swo
|
||||
benchmarks/graphs
|
||||
testing
|
||||
node_modules/
|
||||
testing
|
||||
.coverage_data
|
||||
cover_html
|
||||
test.js
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
[submodule "support/expresso"]
|
||||
path = support/expresso
|
||||
url = git://github.com/visionmedia/expresso.git
|
||||
[submodule "support/haml"]
|
||||
path = support/haml
|
||||
url = git://github.com/visionmedia/haml.js.git
|
||||
[submodule "support/ejs"]
|
||||
path = support/ejs
|
||||
url = git://github.com/visionmedia/ejs.git
|
||||
[submodule "support/connect-form"]
|
||||
path = support/connect-form
|
||||
url = git://github.com/visionmedia/connect-form.git
|
||||
[submodule "support/connect"]
|
||||
path = support/connect
|
||||
url = git://github.com/senchalabs/connect.git
|
||||
[submodule "support/jade"]
|
||||
path = support/jade
|
||||
url = git://github.com/visionmedia/jade.git
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
.git*
|
||||
docs/
|
||||
examples/
|
||||
support/
|
||||
test/
|
||||
testing.js
|
||||
.DS_Store
|
||||
coverage.html
|
||||
lib-cov
|
||||
@@ -0,0 +1,3 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.6
|
||||
+531
@@ -1,4 +1,535 @@
|
||||
|
||||
3.0.0alpha5 / 2012-05-30
|
||||
==================
|
||||
|
||||
* Added `req.ip`
|
||||
* Added `{ signed: true }` option to `res.cookie()`
|
||||
* Removed `res.signedCookie()`
|
||||
* Changed: dont reverse `req.ips`
|
||||
* Fixed "trust proxy" setting check for `req.ips`
|
||||
|
||||
3.0.0alpha4 / 2012-05-09
|
||||
==================
|
||||
|
||||
* Added: allow `[]` in jsonp callback. Closes #1128
|
||||
* Added `PORT` env var support in generated template. Closes #1118 [benatkin]
|
||||
* Updated: connect 2.2.2
|
||||
|
||||
3.0.0alpha3 / 2012-05-04
|
||||
==================
|
||||
|
||||
* Added public `app.routes`. Closes #887
|
||||
* Added _view-locals_ example
|
||||
* Added _mvc_ example
|
||||
* Added `res.locals.use()`. Closes #1120
|
||||
* Added conditional-GET support to `res.send()`
|
||||
* Added: coerce `res.set()` values to strings
|
||||
* Changed: moved `static()` in generated apps below router
|
||||
* Changed: `res.send()` only set ETag when not previously set
|
||||
* Changed connect 2.2.1 dep
|
||||
* Changed: `make test` now runs unit / acceptance tests
|
||||
* Fixed req/res proto inheritance
|
||||
|
||||
3.0.0alpha2 / 2012-04-26
|
||||
==================
|
||||
|
||||
* Added `make benchmark` back
|
||||
* Added `res.send()` support for `String` objects
|
||||
* Added client-side data exposing example
|
||||
* Added `res.header()` and `req.header()` aliases for BC
|
||||
* Added `express.createServer()` for BC
|
||||
* Perf: memoize parsed urls
|
||||
* Perf: connect 2.2.0 dep
|
||||
* Changed: make `expressInit()` middleware self-aware
|
||||
* Fixed: use app.get() for all core settings
|
||||
* Fixed redis session example
|
||||
* Fixed session example. Closes #1105
|
||||
* Fixed generated express dep. Closes #1078
|
||||
|
||||
3.0.0alpha1 / 2012-04-15
|
||||
==================
|
||||
|
||||
* Added `app.locals.use(callback)`
|
||||
* Added `app.locals` object
|
||||
* Added `app.locals(obj)`
|
||||
* Added `res.locals` object
|
||||
* Added `res.locals(obj)`
|
||||
* Added `res.format()` for content-negotiation
|
||||
* Added `app.engine()`
|
||||
* Added `res.cookie()` JSON cookie support
|
||||
* Added "trust proxy" setting
|
||||
* Added `req.subdomains`
|
||||
* Added `req.protocol`
|
||||
* Added `req.secure`
|
||||
* Added `req.path`
|
||||
* Added `req.ips`
|
||||
* Added `req.fresh`
|
||||
* Added `req.stale`
|
||||
* Added comma-delmited / array support for `req.accepts()`
|
||||
* Added debug instrumentation
|
||||
* Added `res.set(obj)`
|
||||
* Added `res.set(field, value)`
|
||||
* Added `res.get(field)`
|
||||
* Added `app.get(setting)`. Closes #842
|
||||
* Added `req.acceptsLanguage()`
|
||||
* Added `req.acceptsCharset()`
|
||||
* Added `req.accepted`
|
||||
* Added `req.acceptedLanguages`
|
||||
* Added `req.acceptedCharsets`
|
||||
* Added "json replacer" setting
|
||||
* Added "json spaces" setting
|
||||
* Added X-Forwarded-Proto support to `res.redirect()`. Closes #92
|
||||
* Added `--less` support to express(1)
|
||||
* Added `express.response` prototype
|
||||
* Added `express.request` prototype
|
||||
* Added `express.application` prototype
|
||||
* Added `app.path()`
|
||||
* Added `app.render()`
|
||||
* Added `res.type()` to replace `res.contentType()`
|
||||
* Changed: `res.redirect()` to add relative support
|
||||
* Changed: enable "jsonp callback" by default
|
||||
* Changed: renamed "case sensitive routes" to "case sensitive routing"
|
||||
* Rewrite of all tests with mocha
|
||||
* Removed "root" setting
|
||||
* Removed `res.redirect('home')` support
|
||||
* Removed `req.notify()`
|
||||
* Removed `app.register()`
|
||||
* Removed `app.redirect()`
|
||||
* Removed `app.is()`
|
||||
* Removed `app.helpers()`
|
||||
* Removed `app.dynamicHelpers()`
|
||||
* Fixed `res.sendfile()` with non-GET. Closes #723
|
||||
* Fixed express(1) public dir for windows. Closes #866
|
||||
|
||||
2.5.9/ 2012-04-02
|
||||
==================
|
||||
|
||||
* Added support for PURGE request method [pbuyle]
|
||||
* Fixed `express(1)` generated app `app.address()` before `listening` [mmalecki]
|
||||
|
||||
2.5.8 / 2012-02-08
|
||||
==================
|
||||
|
||||
* Update mkdirp dep. Closes #991
|
||||
|
||||
2.5.7 / 2012-02-06
|
||||
==================
|
||||
|
||||
* Fixed `app.all` duplicate DELETE requests [mscdex]
|
||||
|
||||
2.5.6 / 2012-01-13
|
||||
==================
|
||||
|
||||
* Updated hamljs dev dep. Closes #953
|
||||
|
||||
2.5.5 / 2012-01-08
|
||||
==================
|
||||
|
||||
* Fixed: set `filename` on cached templates [matthewleon]
|
||||
|
||||
2.5.4 / 2012-01-02
|
||||
==================
|
||||
|
||||
* Fixed `express(1)` eol on 0.4.x. Closes #947
|
||||
|
||||
2.5.3 / 2011-12-30
|
||||
==================
|
||||
|
||||
* Fixed `req.is()` when a charset is present
|
||||
|
||||
2.5.2 / 2011-12-10
|
||||
==================
|
||||
|
||||
* Fixed: express(1) LF -> CRLF for windows
|
||||
|
||||
2.5.1 / 2011-11-17
|
||||
==================
|
||||
|
||||
* Changed: updated connect to 1.8.x
|
||||
* Removed sass.js support from express(1)
|
||||
|
||||
2.5.0 / 2011-10-24
|
||||
==================
|
||||
|
||||
* Added ./routes dir for generated app by default
|
||||
* Added npm install reminder to express(1) app gen
|
||||
* Added 0.5.x support
|
||||
* Removed `make test-cov` since it wont work with node 0.5.x
|
||||
* Fixed express(1) public dir for windows. Closes #866
|
||||
|
||||
2.4.7 / 2011-10-05
|
||||
==================
|
||||
|
||||
* Added mkdirp to express(1). Closes #795
|
||||
* Added simple _json-config_ example
|
||||
* Added shorthand for the parsed request's pathname via `req.path`
|
||||
* Changed connect dep to 1.7.x to fix npm issue...
|
||||
* Fixed `res.redirect()` __HEAD__ support. [reported by xerox]
|
||||
* Fixed `req.flash()`, only escape args
|
||||
* Fixed absolute path checking on windows. Closes #829 [reported by andrewpmckenzie]
|
||||
|
||||
2.4.6 / 2011-08-22
|
||||
==================
|
||||
|
||||
* Fixed multiple param callback regression. Closes #824 [reported by TroyGoode]
|
||||
|
||||
2.4.5 / 2011-08-19
|
||||
==================
|
||||
|
||||
* Added support for routes to handle errors. Closes #809
|
||||
* Added `app.routes.all()`. Closes #803
|
||||
* Added "basepath" setting to work in conjunction with reverse proxies etc.
|
||||
* Refactored `Route` to use a single array of callbacks
|
||||
* Added support for multiple callbacks for `app.param()`. Closes #801
|
||||
Closes #805
|
||||
* Changed: removed .call(self) for route callbacks
|
||||
* Dependency: `qs >= 0.3.1`
|
||||
* Fixed `res.redirect()` on windows due to `join()` usage. Closes #808
|
||||
|
||||
2.4.4 / 2011-08-05
|
||||
==================
|
||||
|
||||
* Fixed `res.header()` intention of a set, even when `undefined`
|
||||
* Fixed `*`, value no longer required
|
||||
* Fixed `res.send(204)` support. Closes #771
|
||||
|
||||
2.4.3 / 2011-07-14
|
||||
==================
|
||||
|
||||
* Added docs for `status` option special-case. Closes #739
|
||||
* Fixed `options.filename`, exposing the view path to template engines
|
||||
|
||||
2.4.2. / 2011-07-06
|
||||
==================
|
||||
|
||||
* Revert "removed jsonp stripping" for XSS
|
||||
|
||||
2.4.1 / 2011-07-06
|
||||
==================
|
||||
|
||||
* Added `res.json()` JSONP support. Closes #737
|
||||
* Added _extending-templates_ example. Closes #730
|
||||
* Added "strict routing" setting for trailing slashes
|
||||
* Added support for multiple envs in `app.configure()` calls. Closes #735
|
||||
* Changed: `res.send()` using `res.json()`
|
||||
* Changed: when cookie `path === null` don't default it
|
||||
* Changed; default cookie path to "home" setting. Closes #731
|
||||
* Removed _pids/logs_ creation from express(1)
|
||||
|
||||
2.4.0 / 2011-06-28
|
||||
==================
|
||||
|
||||
* Added chainable `res.status(code)`
|
||||
* Added `res.json()`, an explicit version of `res.send(obj)`
|
||||
* Added simple web-service example
|
||||
|
||||
2.3.12 / 2011-06-22
|
||||
==================
|
||||
|
||||
* \#express is now on freenode! come join!
|
||||
* Added `req.get(field, param)`
|
||||
* Added links to Japanese documentation, thanks @hideyukisaito!
|
||||
* Added; the `express(1)` generated app outputs the env
|
||||
* Added `content-negotiation` example
|
||||
* Dependency: connect >= 1.5.1 < 2.0.0
|
||||
* Fixed view layout bug. Closes #720
|
||||
* Fixed; ignore body on 304. Closes #701
|
||||
|
||||
2.3.11 / 2011-06-04
|
||||
==================
|
||||
|
||||
* Added `npm test`
|
||||
* Removed generation of dummy test file from `express(1)`
|
||||
* Fixed; `express(1)` adds express as a dep
|
||||
* Fixed; prune on `prepublish`
|
||||
|
||||
2.3.10 / 2011-05-27
|
||||
==================
|
||||
|
||||
* Added `req.route`, exposing the current route
|
||||
* Added _package.json_ generation support to `express(1)`
|
||||
* Fixed call to `app.param()` function for optional params. Closes #682
|
||||
|
||||
2.3.9 / 2011-05-25
|
||||
==================
|
||||
|
||||
* Fixed bug-ish with `../' in `res.partial()` calls
|
||||
|
||||
2.3.8 / 2011-05-24
|
||||
==================
|
||||
|
||||
* Fixed `app.options()`
|
||||
|
||||
2.3.7 / 2011-05-23
|
||||
==================
|
||||
|
||||
* Added route `Collection`, ex: `app.get('/user/:id').remove();`
|
||||
* Added support for `app.param(fn)` to define param logic
|
||||
* Removed `app.param()` support for callback with return value
|
||||
* Removed module.parent check from express(1) generated app. Closes #670
|
||||
* Refactored router. Closes #639
|
||||
|
||||
2.3.6 / 2011-05-20
|
||||
==================
|
||||
|
||||
* Changed; using devDependencies instead of git submodules
|
||||
* Fixed redis session example
|
||||
* Fixed markdown example
|
||||
* Fixed view caching, should not be enabled in development
|
||||
|
||||
2.3.5 / 2011-05-20
|
||||
==================
|
||||
|
||||
* Added export `.view` as alias for `.View`
|
||||
|
||||
2.3.4 / 2011-05-08
|
||||
==================
|
||||
|
||||
* Added `./examples/say`
|
||||
* Fixed `res.sendfile()` bug preventing the transfer of files with spaces
|
||||
|
||||
2.3.3 / 2011-05-03
|
||||
==================
|
||||
|
||||
* Added "case sensitive routes" option.
|
||||
* Changed; split methods supported per rfc [slaskis]
|
||||
* Fixed route-specific middleware when using the same callback function several times
|
||||
|
||||
2.3.2 / 2011-04-27
|
||||
==================
|
||||
|
||||
* Fixed view hints
|
||||
|
||||
2.3.1 / 2011-04-26
|
||||
==================
|
||||
|
||||
* Added `app.match()` as `app.match.all()`
|
||||
* Added `app.lookup()` as `app.lookup.all()`
|
||||
* Added `app.remove()` for `app.remove.all()`
|
||||
* Added `app.remove.VERB()`
|
||||
* Fixed template caching collision issue. Closes #644
|
||||
* Moved router over from connect and started refactor
|
||||
|
||||
2.3.0 / 2011-04-25
|
||||
==================
|
||||
|
||||
* Added options support to `res.clearCookie()`
|
||||
* Added `res.helpers()` as alias of `res.locals()`
|
||||
* Added; json defaults to UTF-8 with `res.send()`. Closes #632. [Daniel * Dependency `connect >= 1.4.0`
|
||||
* Changed; auto set Content-Type in res.attachement [Aaron Heckmann]
|
||||
* Renamed "cache views" to "view cache". Closes #628
|
||||
* Fixed caching of views when using several apps. Closes #637
|
||||
* Fixed gotcha invoking `app.param()` callbacks once per route middleware.
|
||||
Closes #638
|
||||
* Fixed partial lookup precedence. Closes #631
|
||||
Shaw]
|
||||
|
||||
2.2.2 / 2011-04-12
|
||||
==================
|
||||
|
||||
* Added second callback support for `res.download()` connection errors
|
||||
* Fixed `filename` option passing to template engine
|
||||
|
||||
2.2.1 / 2011-04-04
|
||||
==================
|
||||
|
||||
* Added `layout(path)` helper to change the layout within a view. Closes #610
|
||||
* Fixed `partial()` collection object support.
|
||||
Previously only anything with `.length` would work.
|
||||
When `.length` is present one must still be aware of holes,
|
||||
however now `{ collection: {foo: 'bar'}}` is valid, exposes
|
||||
`keyInCollection` and `keysInCollection`.
|
||||
|
||||
* Performance improved with better view caching
|
||||
* Removed `request` and `response` locals
|
||||
* Changed; errorHandler page title is now `Express` instead of `Connect`
|
||||
|
||||
2.2.0 / 2011-03-30
|
||||
==================
|
||||
|
||||
* Added `app.lookup.VERB()`, ex `app.lookup.put('/user/:id')`. Closes #606
|
||||
* Added `app.match.VERB()`, ex `app.match.put('/user/12')`. Closes #606
|
||||
* Added `app.VERB(path)` as alias of `app.lookup.VERB()`.
|
||||
* Dependency `connect >= 1.2.0`
|
||||
|
||||
2.1.1 / 2011-03-29
|
||||
==================
|
||||
|
||||
* Added; expose `err.view` object when failing to locate a view
|
||||
* Fixed `res.partial()` call `next(err)` when no callback is given [reported by aheckmann]
|
||||
* Fixed; `res.send(undefined)` responds with 204 [aheckmann]
|
||||
|
||||
2.1.0 / 2011-03-24
|
||||
==================
|
||||
|
||||
* Added `<root>/_?<name>` partial lookup support. Closes #447
|
||||
* Added `request`, `response`, and `app` local variables
|
||||
* Added `settings` local variable, containing the app's settings
|
||||
* Added `req.flash()` exception if `req.session` is not available
|
||||
* Added `res.send(bool)` support (json response)
|
||||
* Fixed stylus example for latest version
|
||||
* Fixed; wrap try/catch around `res.render()`
|
||||
|
||||
2.0.0 / 2011-03-17
|
||||
==================
|
||||
|
||||
* Fixed up index view path alternative.
|
||||
* Changed; `res.locals()` without object returns the locals
|
||||
|
||||
2.0.0rc3 / 2011-03-17
|
||||
==================
|
||||
|
||||
* Added `res.locals(obj)` to compliment `res.local(key, val)`
|
||||
* Added `res.partial()` callback support
|
||||
* Fixed recursive error reporting issue in `res.render()`
|
||||
|
||||
2.0.0rc2 / 2011-03-17
|
||||
==================
|
||||
|
||||
* Changed; `partial()` "locals" are now optional
|
||||
* Fixed `SlowBuffer` support. Closes #584 [reported by tyrda01]
|
||||
* Fixed .filename view engine option [reported by drudge]
|
||||
* Fixed blog example
|
||||
* Fixed `{req,res}.app` reference when mounting [Ben Weaver]
|
||||
|
||||
2.0.0rc / 2011-03-14
|
||||
==================
|
||||
|
||||
* Fixed; expose `HTTPSServer` constructor
|
||||
* Fixed express(1) default test charset. Closes #579 [reported by secoif]
|
||||
* Fixed; default charset to utf-8 instead of utf8 for lame IE [reported by NickP]
|
||||
|
||||
2.0.0beta3 / 2011-03-09
|
||||
==================
|
||||
|
||||
* Added support for `res.contentType()` literal
|
||||
The original `res.contentType('.json')`,
|
||||
`res.contentType('application/json')`, and `res.contentType('json')`
|
||||
will work now.
|
||||
* Added `res.render()` status option support back
|
||||
* Added charset option for `res.render()`
|
||||
* Added `.charset` support (via connect 1.0.4)
|
||||
* Added view resolution hints when in development and a lookup fails
|
||||
* Added layout lookup support relative to the page view.
|
||||
For example while rendering `./views/user/index.jade` if you create
|
||||
`./views/user/layout.jade` it will be used in favour of the root layout.
|
||||
* Fixed `res.redirect()`. RFC states absolute url [reported by unlink]
|
||||
* Fixed; default `res.send()` string charset to utf8
|
||||
* Removed `Partial` constructor (not currently used)
|
||||
|
||||
2.0.0beta2 / 2011-03-07
|
||||
==================
|
||||
|
||||
* Added res.render() `.locals` support back to aid in migration process
|
||||
* Fixed flash example
|
||||
|
||||
2.0.0beta / 2011-03-03
|
||||
==================
|
||||
|
||||
* Added HTTPS support
|
||||
* Added `res.cookie()` maxAge support
|
||||
* Added `req.header()` _Referrer_ / _Referer_ special-case, either works
|
||||
* Added mount support for `res.redirect()`, now respects the mount-point
|
||||
* Added `union()` util, taking place of `merge(clone())` combo
|
||||
* Added stylus support to express(1) generated app
|
||||
* Added secret to session middleware used in examples and generated app
|
||||
* Added `res.local(name, val)` for progressive view locals
|
||||
* Added default param support to `req.param(name, default)`
|
||||
* Added `app.disabled()` and `app.enabled()`
|
||||
* Added `app.register()` support for omitting leading ".", either works
|
||||
* Added `res.partial()`, using the same interface as `partial()` within a view. Closes #539
|
||||
* Added `app.param()` to map route params to async/sync logic
|
||||
* Added; aliased `app.helpers()` as `app.locals()`. Closes #481
|
||||
* Added extname with no leading "." support to `res.contentType()`
|
||||
* Added `cache views` setting, defaulting to enabled in "production" env
|
||||
* Added index file partial resolution, eg: partial('user') may try _views/user/index.jade_.
|
||||
* Added `req.accepts()` support for extensions
|
||||
* Changed; `res.download()` and `res.sendfile()` now utilize Connect's
|
||||
static file server `connect.static.send()`.
|
||||
* Changed; replaced `connect.utils.mime()` with npm _mime_ module
|
||||
* Changed; allow `req.query` to be pre-defined (via middleware or other parent
|
||||
* Changed view partial resolution, now relative to parent view
|
||||
* Changed view engine signature. no longer `engine.render(str, options, callback)`, now `engine.compile(str, options) -> Function`, the returned function accepts `fn(locals)`.
|
||||
* Fixed `req.param()` bug returning Array.prototype methods. Closes #552
|
||||
* Fixed; using `Stream#pipe()` instead of `sys.pump()` in `res.sendfile()`
|
||||
* Fixed; using _qs_ module instead of _querystring_
|
||||
* Fixed; strip unsafe chars from jsonp callbacks
|
||||
* Removed "stream threshold" setting
|
||||
|
||||
1.0.8 / 2011-03-01
|
||||
==================
|
||||
|
||||
* Allow `req.query` to be pre-defined (via middleware or other parent app)
|
||||
* "connect": ">= 0.5.0 < 1.0.0". Closes #547
|
||||
* Removed the long deprecated __EXPRESS_ENV__ support
|
||||
|
||||
1.0.7 / 2011-02-07
|
||||
==================
|
||||
|
||||
* Fixed `render()` setting inheritance.
|
||||
Mounted apps would not inherit "view engine"
|
||||
|
||||
1.0.6 / 2011-02-07
|
||||
==================
|
||||
|
||||
* Fixed `view engine` setting bug when period is in dirname
|
||||
|
||||
1.0.5 / 2011-02-05
|
||||
==================
|
||||
|
||||
* Added secret to generated app `session()` call
|
||||
|
||||
1.0.4 / 2011-02-05
|
||||
==================
|
||||
|
||||
* Added `qs` dependency to _package.json_
|
||||
* Fixed namespaced `require()`s for latest connect support
|
||||
|
||||
1.0.3 / 2011-01-13
|
||||
==================
|
||||
|
||||
* Remove unsafe characters from JSONP callback names [Ryan Grove]
|
||||
|
||||
1.0.2 / 2011-01-10
|
||||
==================
|
||||
|
||||
* Removed nested require, using `connect.router`
|
||||
|
||||
1.0.1 / 2010-12-29
|
||||
==================
|
||||
|
||||
* Fixed for middleware stacked via `createServer()`
|
||||
previously the `foo` middleware passed to `createServer(foo)`
|
||||
would not have access to Express methods such as `res.send()`
|
||||
or props like `req.query` etc.
|
||||
|
||||
1.0.0 / 2010-11-16
|
||||
==================
|
||||
|
||||
* Added; deduce partial object names from the last segment.
|
||||
For example by default `partial('forum/post', postObject)` will
|
||||
give you the _post_ object, providing a meaningful default.
|
||||
* Added http status code string representation to `res.redirect()` body
|
||||
* Added; `res.redirect()` supporting _text/plain_ and _text/html_ via __Accept__.
|
||||
* Added `req.is()` to aid in content negotiation
|
||||
* Added partial local inheritance [suggested by masylum]. Closes #102
|
||||
providing access to parent template locals.
|
||||
* Added _-s, --session[s]_ flag to express(1) to add session related middleware
|
||||
* Added _--template_ flag to express(1) to specify the
|
||||
template engine to use.
|
||||
* Added _--css_ flag to express(1) to specify the
|
||||
stylesheet engine to use (or just plain css by default).
|
||||
* Added `app.all()` support [thanks aheckmann]
|
||||
* Added partial direct object support.
|
||||
You may now `partial('user', user)` providing the "user" local,
|
||||
vs previously `partial('user', { object: user })`.
|
||||
* Added _route-separation_ example since many people question ways
|
||||
to do this with CommonJS modules. Also view the _blog_ example for
|
||||
an alternative.
|
||||
* Performance; caching view path derived partial object names
|
||||
* Fixed partial local inheritance precedence. [reported by Nick Poulden] Closes #454
|
||||
* Fixed jsonp support; _text/javascript_ as per mailinglist discussion
|
||||
|
||||
1.0.0rc4 / 2010-10-14
|
||||
==================
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2009-2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
Copyright (c) 2009-2011 TJ Holowaychuk <tj@vision-media.ca>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
+24
-65
@@ -1,77 +1,36 @@
|
||||
|
||||
PREFIX = /usr/local
|
||||
LIB_PREFIX = ~/.node_libraries
|
||||
REPORTER = dot
|
||||
|
||||
DOCS = docs/index.md \
|
||||
docs/executable.md \
|
||||
docs/contrib.md \
|
||||
docs/guide.md \
|
||||
docs/migrate.md
|
||||
docs: docs/express.md
|
||||
|
||||
MANPAGES =$(DOCS:.md=.1)
|
||||
HTMLDOCS =$(DOCS:.md=.html)
|
||||
docs/express.md: docs/application.md docs/request.md docs/response.md
|
||||
cat $^ > $@
|
||||
|
||||
install: install-docs
|
||||
@mkdir -p $(PREFIX)/bin
|
||||
@mkdir -p $(LIB_PREFIX)
|
||||
cp -f bin/express $(PREFIX)/bin/express
|
||||
cp -fr lib/express $(LIB_PREFIX)/express
|
||||
docs/%.md: lib/%.js
|
||||
@mkdir -p docs
|
||||
dox --raw < $< | ./support/docs > $@
|
||||
|
||||
uninstall: uninstall-docs
|
||||
rm -f $(PREFIX)/bin/express
|
||||
rm -fr $(LIB_PREFIX)/express
|
||||
test: test-unit test-acceptance
|
||||
|
||||
install-support:
|
||||
cd support/connect && $(MAKE) install
|
||||
cd support/jade && $(MAKE) install
|
||||
test-unit:
|
||||
@NODE_ENV=test ./node_modules/.bin/mocha \
|
||||
--reporter $(REPORTER)
|
||||
|
||||
uninstall-support:
|
||||
cd support/connect && $(MAKE) uninstall
|
||||
cd support/jade && $(MAKE) uninstall
|
||||
test-acceptance:
|
||||
@NODE_ENV=test ./node_modules/.bin/mocha \
|
||||
--reporter $(REPORTER) \
|
||||
test/acceptance/*.js
|
||||
|
||||
install-docs:
|
||||
@mkdir -p $(PREFIX)/share/man/man1
|
||||
cp -f docs/executable.1 $(PREFIX)/share/man/man1/express.1
|
||||
test-cov: lib-cov
|
||||
@EXPRESS_COV=1 $(MAKE) test REPORTER=html-cov > coverage.html
|
||||
|
||||
uninstall-docs:
|
||||
rm -f $(PREFIX)/share/man/man1/express.1
|
||||
|
||||
test:
|
||||
@NODE_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 \
|
||||
--private \
|
||||
--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' \
|
||||
> $@
|
||||
lib-cov:
|
||||
@jscoverage lib lib-cov
|
||||
|
||||
docclean:
|
||||
rm -f docs/*.{1,html}
|
||||
rm -fr docs
|
||||
|
||||
.PHONY: install uninstall install-docs install-support uninstall-support install-docs uninstall-docs test test-cov docs docclean
|
||||
benchmark:
|
||||
@./support/bench
|
||||
|
||||
.PHONY: docs docclean test test-unit test-acceptance benchmark
|
||||
|
||||
+130
-54
@@ -1,91 +1,167 @@
|
||||
|
||||
# Express
|
||||
|
||||
Insanely fast (and small) server-side JavaScript web development framework
|
||||
built on [node](http://nodejs.org) and [Connect](http://github.com/senchalabs/connect).
|
||||
|
||||
var app = express.createServer();
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.send('Hello World');
|
||||
});
|
||||

|
||||
|
||||
app.listen(3000);
|
||||
Fast, unopinionated, minimalist web framework for [node](http://nodejs.org). [](http://travis-ci.org/visionmedia/express)
|
||||
|
||||
```js
|
||||
var express = require('express');
|
||||
var app = express();
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.send('Hello World');
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
npm:
|
||||
$ npm install -g express
|
||||
|
||||
$ npm install express
|
||||
To install the 3.0 alpha:
|
||||
|
||||
$ npm install -g express@3.0
|
||||
|
||||
curl:
|
||||
## Quick Start
|
||||
|
||||
$ curl -# http://expressjs.com/install.sh | sh
|
||||
The quickest way to get started with express is to utilize the executable `express(1)` to generate an application as shown below:
|
||||
|
||||
git clone, first update the submodules:
|
||||
Create the app:
|
||||
|
||||
$ git submodule update --init
|
||||
$ make install
|
||||
$ make install-support
|
||||
$ npm install -g express
|
||||
$ express /tmp/foo && cd /tmp/foo
|
||||
|
||||
Install dependencies:
|
||||
|
||||
$ npm install
|
||||
|
||||
Start the server:
|
||||
|
||||
$ node app
|
||||
|
||||
## Features
|
||||
|
||||
* Built on [Connect](http://github.com/senchalabs/connect)
|
||||
* Robust routing
|
||||
* Redirection helpers
|
||||
* Dynamic view helpers
|
||||
* HTTP helpers (redirection, caching, etc)
|
||||
* View system supporting 14+ template engines
|
||||
* Content negotiation
|
||||
* Focus on high performance
|
||||
* View rendering and partials support
|
||||
* Environment based configuration
|
||||
* Session based flash notifications
|
||||
* Built on [Connect](http://github.com/senchalabs/connect)
|
||||
* High test coverage
|
||||
* Executable for generating applications quickly
|
||||
* Application level view options
|
||||
* High test coverage
|
||||
|
||||
Via Connect:
|
||||
## Philosophy
|
||||
|
||||
* 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))
|
||||
* Guillermo Rauch ([guille](http://github.com/guille))
|
||||
The Express philosophy is to provide small, robust tooling for HTTP servers. Making
|
||||
it a great solution for single page applications, web sites, hybrids, or public
|
||||
HTTP APIs.
|
||||
|
||||
Built on Connect you can use _only_ what you need, and nothing more, applications
|
||||
can be as big or as small as you like, even a single file. Express does
|
||||
not force you to use any specific ORM or template engine. With support for over
|
||||
14 template engines via [Consolidate.js](http://github.com/visionmedia/consolidate.js)
|
||||
you can quickly craft your perfect framework.
|
||||
|
||||
## More Information
|
||||
|
||||
* Express [Contrib](http://github.com/visionmedia/express-contrib) repo for additional functionality
|
||||
* Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) on twitter for updates
|
||||
* Join #express on freenode
|
||||
* [Google Group](http://groups.google.com/group/express-js) for discussion
|
||||
* Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) on twitter for updates
|
||||
* Visit the [Wiki](http://github.com/visionmedia/express/wiki)
|
||||
* [日本語ドキュメンテーション](http://hideyukisaito.com/doc/expressjs/) by [hideyukisaito](https://github.com/hideyukisaito)
|
||||
* [Русскоязычная документация](http://express-js.ru/)
|
||||
|
||||
## Node Compatibility
|
||||
|
||||
The latest release of Express is compatible with node --version:
|
||||
## Viewing Examples
|
||||
|
||||
v0.2.3
|
||||
First install the dev dependencies to install all the example / test suite deps:
|
||||
|
||||
and connect --version:
|
||||
$ cd express
|
||||
$ npm install -d
|
||||
|
||||
0.2.6
|
||||
then run whichever tests you want:
|
||||
|
||||
$ node examples/content-negotiation
|
||||
|
||||
## Running Tests
|
||||
|
||||
To run the test suite first invoke the following command within the repo, installing the development dependencies:
|
||||
|
||||
$ npm install
|
||||
|
||||
then run the tests:
|
||||
|
||||
$ make test
|
||||
|
||||
## Contributors
|
||||
|
||||
```
|
||||
project: express
|
||||
commits: 3559
|
||||
active : 468 days
|
||||
files : 237
|
||||
authors:
|
||||
1891 Tj Holowaychuk 53.1%
|
||||
1285 visionmedia 36.1%
|
||||
182 TJ Holowaychuk 5.1%
|
||||
54 Aaron Heckmann 1.5%
|
||||
34 csausdev 1.0%
|
||||
26 ciaranj 0.7%
|
||||
21 Robert Sköld 0.6%
|
||||
6 Guillermo Rauch 0.2%
|
||||
3 Dav Glass 0.1%
|
||||
3 Nick Poulden 0.1%
|
||||
2 Randy Merrill 0.1%
|
||||
2 Benny Wong 0.1%
|
||||
2 Hunter Loftis 0.1%
|
||||
2 Jake Gordon 0.1%
|
||||
2 Brian McKinney 0.1%
|
||||
2 Roman Shtylman 0.1%
|
||||
2 Ben Weaver 0.1%
|
||||
2 Dave Hoover 0.1%
|
||||
2 Eivind Fjeldstad 0.1%
|
||||
2 Daniel Shaw 0.1%
|
||||
1 Matt Colyer 0.0%
|
||||
1 Pau Ramon 0.0%
|
||||
1 Pero Pejovic 0.0%
|
||||
1 Peter Rekdal Sunde 0.0%
|
||||
1 Raynos 0.0%
|
||||
1 Teng Siong Ong 0.0%
|
||||
1 Viktor Kelemen 0.0%
|
||||
1 ctide 0.0%
|
||||
1 8bitDesigner 0.0%
|
||||
1 isaacs 0.0%
|
||||
1 mgutz 0.0%
|
||||
1 pikeas 0.0%
|
||||
1 shuwatto 0.0%
|
||||
1 tstrimple 0.0%
|
||||
1 ewoudj 0.0%
|
||||
1 Adam Sanderson 0.0%
|
||||
1 Andrii Kostenko 0.0%
|
||||
1 Andy Hiew 0.0%
|
||||
1 Arpad Borsos 0.0%
|
||||
1 Ashwin Purohit 0.0%
|
||||
1 Benjen 0.0%
|
||||
1 Darren Torpey 0.0%
|
||||
1 Greg Ritter 0.0%
|
||||
1 Gregory Ritter 0.0%
|
||||
1 James Herdman 0.0%
|
||||
1 Jim Snodgrass 0.0%
|
||||
1 Joe McCann 0.0%
|
||||
1 Jonathan Dumaine 0.0%
|
||||
1 Jonathan Palardy 0.0%
|
||||
1 Jonathan Zacsh 0.0%
|
||||
1 Justin Lilly 0.0%
|
||||
1 Ken Sato 0.0%
|
||||
1 Maciej Małecki 0.0%
|
||||
1 Masahiro Hayashi 0.0%
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2009-2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
Copyright (c) 2009-2012 TJ Holowaychuk <tj@vision-media.ca>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
+293
-202
@@ -4,181 +4,223 @@
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var sys = require('sys'),
|
||||
fs = require('fs'),
|
||||
childProcess = require('child_process');
|
||||
var exec = require('child_process').exec
|
||||
, program = require('commander')
|
||||
, mkdirp = require('mkdirp')
|
||||
, pkg = require('../package.json')
|
||||
, version = pkg.version
|
||||
, os = require('os')
|
||||
, fs = require('fs');
|
||||
|
||||
// CLI
|
||||
|
||||
program
|
||||
.version(version)
|
||||
.option('-s, --sessions', 'add session support')
|
||||
.option('-e, --ejs', 'add ejs engine support (defaults to jade)')
|
||||
.option('-J, --jshtml', 'add jshtml engine support (defaults to jade)')
|
||||
.option('-c, --css <engine>', 'add stylesheet <engine> support (less|stylus) (defaults to plain css)')
|
||||
.option('-f, --force', 'force on non-empty directory')
|
||||
.parse(process.argv);
|
||||
|
||||
// Path
|
||||
|
||||
var path = program.args.shift() || '.';
|
||||
|
||||
// end-of-line code
|
||||
|
||||
var eol = 'win32' == os.platform() ? '\r\n' : '\n'
|
||||
|
||||
// Template engine
|
||||
|
||||
program.template = 'jade';
|
||||
if (program.ejs) program.template = 'ejs';
|
||||
if (program.jshtml) program.template = 'jshtml';
|
||||
|
||||
/**
|
||||
* Framework version.
|
||||
* Routes index template.
|
||||
*/
|
||||
|
||||
var version = '1.0.0rc4';
|
||||
|
||||
/**
|
||||
* stdin stream.
|
||||
*/
|
||||
|
||||
var stdin;
|
||||
|
||||
/**
|
||||
* 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';
|
||||
var index = [
|
||||
''
|
||||
, '/*'
|
||||
, ' * GET home page.'
|
||||
, ' */'
|
||||
, ''
|
||||
, 'exports.index = function(req, res){'
|
||||
, ' res.render(\'index\', { title: \'Express\' });'
|
||||
, '};'
|
||||
].join(eol);
|
||||
|
||||
/**
|
||||
* Jade layout template.
|
||||
*/
|
||||
|
||||
var jadeLayout = [
|
||||
'!!!',
|
||||
'html',
|
||||
' head',
|
||||
' title= title',
|
||||
' link(rel=\'stylesheet\', href=\'/stylesheets/style.css\')',
|
||||
' body!= body'
|
||||
].join('\n');
|
||||
|
||||
/**
|
||||
* Default less template.
|
||||
*/
|
||||
|
||||
var less = [
|
||||
'body {',
|
||||
' padding: 50px;',
|
||||
' font: 14px "Lucida Grande", "Helvetica Nueue", Arial, sans-serif;',
|
||||
'}'
|
||||
].join('\n');
|
||||
'doctype 5'
|
||||
, 'html'
|
||||
, ' head'
|
||||
, ' title= title'
|
||||
, ' link(rel=\'stylesheet\', href=\'/stylesheets/style.css\')'
|
||||
, ' body'
|
||||
, ' block content'
|
||||
].join(eol);
|
||||
|
||||
/**
|
||||
* Jade index template.
|
||||
*/
|
||||
|
||||
var jadeIndex = [
|
||||
'h1= title',
|
||||
'p Welcome to #{title}'
|
||||
].join('\n');
|
||||
'extends layout'
|
||||
, ''
|
||||
, 'block content'
|
||||
, ' h1= title'
|
||||
, ' p Welcome to #{title}'
|
||||
].join(eol);
|
||||
|
||||
/**
|
||||
* App test template.
|
||||
* EJS index template.
|
||||
*/
|
||||
|
||||
var appTest = [
|
||||
"",
|
||||
"// Run $ expresso",
|
||||
"",
|
||||
"/**",
|
||||
" * Module dependencies.",
|
||||
" */",
|
||||
"",
|
||||
"var app = require('../app');",
|
||||
"",
|
||||
"module.exports = {",
|
||||
" 'GET /': function(assert){",
|
||||
" assert.response(app,",
|
||||
" { url: '/' },",
|
||||
" { status: 200, headers: { 'Content-Type': 'text/html; charset=utf-8' }},",
|
||||
" function(res){",
|
||||
" assert.includes(res.body, '<title>Express</title>');",
|
||||
" });",
|
||||
" }",
|
||||
"};",
|
||||
].join('\n');
|
||||
var ejsIndex = [
|
||||
'<!DOCTYPE html>'
|
||||
, '<html>'
|
||||
, ' <head>'
|
||||
, ' <title><%= title %></title>'
|
||||
, ' <link rel=\'stylesheet\' href=\'/stylesheets/style.css\' />'
|
||||
, ' </head>'
|
||||
, ' <body>'
|
||||
, ' <h1><%= title %></h1>'
|
||||
, ' <p>Welcome to <%= title %></p>'
|
||||
, ' </body>'
|
||||
, '</html>'
|
||||
].join(eol);
|
||||
|
||||
/**
|
||||
* JSHTML layout template.
|
||||
*/
|
||||
|
||||
var jshtmlLayout = [
|
||||
'<!DOCTYPE html>'
|
||||
, '<html>'
|
||||
, ' <head>'
|
||||
, ' <title> @write(title) </title>'
|
||||
, ' <link rel=\'stylesheet\' href=\'/stylesheets/style.css\' />'
|
||||
, ' </head>'
|
||||
, ' <body>'
|
||||
, ' @write(body)'
|
||||
, ' </body>'
|
||||
, '</html>'
|
||||
].join(eol);
|
||||
|
||||
/**
|
||||
* JSHTML index template.
|
||||
*/
|
||||
|
||||
var jshtmlIndex = [
|
||||
'<h1>@write(title)</h1>'
|
||||
, '<p>Welcome to @write(title)</p>'
|
||||
].join(eol);
|
||||
|
||||
/**
|
||||
* Default css template.
|
||||
*/
|
||||
|
||||
var css = [
|
||||
'body {'
|
||||
, ' padding: 50px;'
|
||||
, ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;'
|
||||
, '}'
|
||||
, ''
|
||||
, 'a {'
|
||||
, ' color: #00B7FF;'
|
||||
, '}'
|
||||
].join(eol);
|
||||
|
||||
/**
|
||||
* Default less template.
|
||||
*/
|
||||
|
||||
var less = [
|
||||
'body {'
|
||||
, ' padding: 50px;'
|
||||
, ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;'
|
||||
, '}'
|
||||
, ''
|
||||
, 'a {'
|
||||
, ' color: #00B7FF;'
|
||||
, '}'
|
||||
].join(eol);
|
||||
|
||||
/**
|
||||
* Default stylus template.
|
||||
*/
|
||||
|
||||
var stylus = [
|
||||
'body'
|
||||
, ' padding: 50px'
|
||||
, ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif'
|
||||
, 'a'
|
||||
, ' color: #00B7FF'
|
||||
].join(eol);
|
||||
|
||||
/**
|
||||
* App template.
|
||||
*/
|
||||
|
||||
var app = [
|
||||
'',
|
||||
'/**',
|
||||
' * Module dependencies.',
|
||||
' */',
|
||||
'',
|
||||
'var express = require(\'express\');',
|
||||
'',
|
||||
'var app = module.exports = express.createServer();',
|
||||
'',
|
||||
'// Configuration',
|
||||
'',
|
||||
'app.configure(function(){',
|
||||
' app.set(\'views\', __dirname + \'/views\');',
|
||||
' app.use(express.bodyDecoder());',
|
||||
' app.use(express.methodOverride());',
|
||||
' app.use(express.compiler({ src: __dirname + \'/public\', enable: [\'less\'] }));',
|
||||
' app.use(app.router);',
|
||||
' app.use(express.staticProvider(__dirname + \'/public\'));',
|
||||
'});',
|
||||
'',
|
||||
'app.configure(\'development\', function(){',
|
||||
' app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); ',
|
||||
'});',
|
||||
'',
|
||||
'app.configure(\'production\', function(){',
|
||||
' app.use(express.errorHandler()); ',
|
||||
'});',
|
||||
'',
|
||||
'// Routes',
|
||||
'',
|
||||
'app.get(\'/\', function(req, res){',
|
||||
' res.render(\'index.jade\', {',
|
||||
' locals: {',
|
||||
' title: \'Express\'',
|
||||
' }',
|
||||
' });',
|
||||
'});',
|
||||
'',
|
||||
'// Only listen on $ node app.js',
|
||||
'',
|
||||
'if (!module.parent) {',
|
||||
' app.listen(3000);',
|
||||
' console.log("Express server listening on port %d", app.address().port)',
|
||||
'}',
|
||||
''
|
||||
].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;
|
||||
}
|
||||
}
|
||||
, '/**'
|
||||
, ' * Module dependencies.'
|
||||
, ' */'
|
||||
, ''
|
||||
, 'var express = require(\'express\')'
|
||||
, ' , routes = require(\'./routes\')'
|
||||
, ' , http = require(\'http\');'
|
||||
, ''
|
||||
, 'var app = express();'
|
||||
, ''
|
||||
, 'app.configure(function(){'
|
||||
, ' app.set(\'port\', process.env.PORT || 3000);'
|
||||
, ' app.set(\'views\', __dirname + \'/views\');'
|
||||
, ' app.set(\'view engine\', \':TEMPLATE\');'
|
||||
, ' app.use(express.favicon());'
|
||||
, ' app.use(express.logger(\'dev\'));'
|
||||
, ' app.use(express.bodyParser());'
|
||||
, ' app.use(express.methodOverride());{sess}'
|
||||
, ' app.use(app.router);{css}'
|
||||
, ' app.use(express.static(__dirname + \'/public\'));'
|
||||
, '});'
|
||||
, ''
|
||||
, 'app.configure(\'development\', function(){'
|
||||
, ' app.use(express.errorHandler());'
|
||||
, '});'
|
||||
, ''
|
||||
, 'app.get(\'/\', routes.index);'
|
||||
, ''
|
||||
, 'http.createServer(app).listen(app.get(\'port\'), function(){'
|
||||
, ' console.log("Express server listening on port " + app.get(\'port\'));'
|
||||
, '});'
|
||||
, ''
|
||||
].join(eol);
|
||||
|
||||
// Generate application
|
||||
|
||||
(function createApplication(path) {
|
||||
emptyDirectory(path, function(empty){
|
||||
if (empty) {
|
||||
createApplicationAt(path);
|
||||
emptyDirectory(path, function(empty){
|
||||
if (empty || program.force) {
|
||||
createApplicationAt(path);
|
||||
} else {
|
||||
program.confirm('destination is not empty, continue? ', function(ok){
|
||||
if (ok) {
|
||||
process.stdin.destroy();
|
||||
createApplicationAt(path);
|
||||
} else {
|
||||
confirm('destination is not empty, continue? ', function(ok){
|
||||
if (ok) {
|
||||
stdin.destroy();
|
||||
createApplicationAt(path);
|
||||
} else {
|
||||
abort('aborting');
|
||||
}
|
||||
});
|
||||
abort('aborting');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
})(path);
|
||||
|
||||
/**
|
||||
@@ -188,23 +230,102 @@ while (args.length) {
|
||||
*/
|
||||
|
||||
function createApplicationAt(path) {
|
||||
mkdir(path, function(){
|
||||
mkdir(path + '/pids');
|
||||
mkdir(path + '/logs');
|
||||
mkdir(path + '/public/javascripts');
|
||||
mkdir(path + '/public/images');
|
||||
mkdir(path + '/public/stylesheets', function(){
|
||||
write(path + '/public/stylesheets/style.less', less);
|
||||
});
|
||||
mkdir(path + '/views/partials', function(){
|
||||
write(path + '/views/layout.jade', jadeLayout);
|
||||
write(path + '/views/index.jade', jadeIndex);
|
||||
});
|
||||
mkdir(path + '/test', function(){
|
||||
write(path + '/test/app.test.js', appTest);
|
||||
});
|
||||
write(path + '/app.js', app);
|
||||
console.log();
|
||||
process.on('exit', function(){
|
||||
console.log();
|
||||
console.log(' install dependencies:');
|
||||
console.log(' $ cd %s && npm install', path);
|
||||
console.log();
|
||||
console.log(' run the app:');
|
||||
console.log(' $ node app');
|
||||
console.log();
|
||||
});
|
||||
|
||||
mkdir(path, function(){
|
||||
mkdir(path + '/public');
|
||||
mkdir(path + '/public/javascripts');
|
||||
mkdir(path + '/public/images');
|
||||
mkdir(path + '/public/stylesheets', function(){
|
||||
switch (program.css) {
|
||||
case 'less':
|
||||
write(path + '/public/stylesheets/style.less', less);
|
||||
break;
|
||||
case 'stylus':
|
||||
write(path + '/public/stylesheets/style.styl', stylus);
|
||||
break;
|
||||
default:
|
||||
write(path + '/public/stylesheets/style.css', css);
|
||||
}
|
||||
});
|
||||
|
||||
mkdir(path + '/routes', function(){
|
||||
write(path + '/routes/index.js', index);
|
||||
});
|
||||
|
||||
mkdir(path + '/views', function(){
|
||||
switch (program.template) {
|
||||
case 'ejs':
|
||||
write(path + '/views/index.ejs', ejsIndex);
|
||||
break;
|
||||
case 'jade':
|
||||
write(path + '/views/layout.jade', jadeLayout);
|
||||
write(path + '/views/index.jade', jadeIndex);
|
||||
break;
|
||||
case 'jshtml':
|
||||
write(path + '/views/layout.jshtml', jshtmlLayout);
|
||||
write(path + '/views/index.jshtml', jshtmlIndex);
|
||||
break;
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// CSS Engine support
|
||||
switch (program.css) {
|
||||
case 'less':
|
||||
app = app.replace('{css}', eol + ' app.use(require(\'less-middleware\')({ src: __dirname + \'/public\' }));');
|
||||
break;
|
||||
case 'stylus':
|
||||
app = app.replace('{css}', eol + ' app.use(require(\'stylus\').middleware(__dirname + \'/public\'));');
|
||||
break;
|
||||
default:
|
||||
app = app.replace('{css}', '');
|
||||
}
|
||||
|
||||
// Session support
|
||||
app = app.replace('{sess}', program.sessions
|
||||
? eol + ' app.use(express.cookieParser(\'your secret here\'));' + eol + ' app.use(express.session());'
|
||||
: '');
|
||||
|
||||
// Template support
|
||||
app = app.replace(':TEMPLATE', program.template);
|
||||
|
||||
// package.json
|
||||
var pkg = {
|
||||
name: 'application-name'
|
||||
, version: '0.0.1'
|
||||
, private: true
|
||||
, scripts: { start: 'node app' }
|
||||
, dependencies: {
|
||||
express: version
|
||||
}
|
||||
}
|
||||
|
||||
if (program.template) pkg.dependencies[program.template] = '*';
|
||||
|
||||
// CSS Engine support
|
||||
switch (program.css) {
|
||||
case 'less':
|
||||
pkg.dependencies['less-middleware'] = '*';
|
||||
break;
|
||||
default:
|
||||
if (program.css) {
|
||||
pkg.dependencies[program.css] = '*';
|
||||
}
|
||||
}
|
||||
|
||||
write(path + '/package.json', JSON.stringify(pkg, null, 2));
|
||||
write(path + '/app.js', app);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,10 +336,10 @@ function createApplicationAt(path) {
|
||||
*/
|
||||
|
||||
function emptyDirectory(path, fn) {
|
||||
fs.readdir(path, function(err, files){
|
||||
if (err && err.errno !== process.ENOENT) throw err;
|
||||
fn(!files || !files.length);
|
||||
});
|
||||
fs.readdir(path, function(err, files){
|
||||
if (err && 'ENOENT' != err.code) throw err;
|
||||
fn(!files || !files.length);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,38 +350,8 @@ function emptyDirectory(path, fn) {
|
||||
*/
|
||||
|
||||
function write(path, str) {
|
||||
fs.writeFile(path, str);
|
||||
sys.puts(' create : ' + path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompt confirmation with the given `msg`.
|
||||
*
|
||||
* @param {String} msg
|
||||
* @param {Function} fn
|
||||
*/
|
||||
|
||||
function confirm(msg, fn) {
|
||||
prompt(msg, function(val){
|
||||
fn(/^ *y(es)?/i.test(val));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompt input with the given `msg` and callback `fn`.
|
||||
*
|
||||
* @param {String} msg
|
||||
* @param {Function} fn
|
||||
*/
|
||||
|
||||
function prompt(msg, fn) {
|
||||
stdin = stdin || process.openStdin();
|
||||
sys[msg[msg.length - 1] == ' ' ? 'print' : 'puts'](msg);
|
||||
stdin.setEncoding('ascii');
|
||||
stdin.addListener('data', function(data){
|
||||
fn(data);
|
||||
stdin.removeListener('data', arguments.callee);
|
||||
});
|
||||
fs.writeFile(path, str);
|
||||
console.log(' \x1b[36mcreate\x1b[0m : ' + path);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -271,11 +362,11 @@ function prompt(msg, fn) {
|
||||
*/
|
||||
|
||||
function mkdir(path, fn) {
|
||||
childProcess.exec('mkdir -p ' + path, function(err){
|
||||
if (err) throw err;
|
||||
sys.puts(' create : ' + path);
|
||||
fn && fn();
|
||||
});
|
||||
mkdirp(path, 0755, function(err){
|
||||
if (err) throw err;
|
||||
console.log(' \033[36mcreate\033[0m : ' + path);
|
||||
fn && fn();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -285,6 +376,6 @@ function mkdir(path, fn) {
|
||||
*/
|
||||
|
||||
function abort(str) {
|
||||
sys.error(str);
|
||||
process.exit(1);
|
||||
}
|
||||
console.error(str);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
|
||||
var http = require('http');
|
||||
|
||||
var times = 50;
|
||||
|
||||
while (times--) {
|
||||
var req = http.request({
|
||||
port: 3000
|
||||
, method: 'POST'
|
||||
, headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
||||
});
|
||||
|
||||
req.on('response', function(res){
|
||||
console.log(res.statusCode);
|
||||
});
|
||||
|
||||
var n = 500000;
|
||||
while (n--) {
|
||||
req.write('foo=bar&bar=baz&');
|
||||
}
|
||||
|
||||
req.write('foo=bar&bar=baz');
|
||||
|
||||
req.end();
|
||||
}
|
||||
-1518
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -0,0 +1,181 @@
|
||||
|
||||
# app
|
||||
|
||||
Application prototype.
|
||||
|
||||
# app.use()
|
||||
|
||||
Proxy `connect#use()` to apply settings to
|
||||
mounted applications.
|
||||
|
||||
# app.engine()
|
||||
|
||||
Register the given template engine callback `fn`
|
||||
as `ext`.
|
||||
|
||||
By default will `require()` the engine based on the
|
||||
file extension. For example if you try to render
|
||||
a "foo.jade" file Express will invoke the following internally:
|
||||
|
||||
app.engine('jade', require('jade').__express);
|
||||
|
||||
For engines that do not provide `.__express` out of the box,
|
||||
or if you wish to "map" a different extension to the template engine
|
||||
you may use this method. For example mapping the EJS template engine to
|
||||
".html" files
|
||||
|
||||
app.engine('html', require('ejs').renderFile);
|
||||
|
||||
In this case EJS provides a `.renderFile()` method with
|
||||
the same signature that Express expects: `(path, options, callback)`,
|
||||
though note that it aliases this method as `ejs.__express` internally
|
||||
so if you're using ".ejs" extensions you dont need to do anything.
|
||||
|
||||
Some template engines do not follow this convention, the
|
||||
[Consolidate.js](https://github.com/visionmedia/consolidate.js)
|
||||
library was created to map all of node's popular template
|
||||
engines to follow this convention, thus allowing them to
|
||||
work seemlessly within Express.
|
||||
|
||||
# app.param()
|
||||
|
||||
Map the given param placeholder `name`(s) to the given callback(s).
|
||||
|
||||
Parameter mapping is used to provide pre-conditions to routes
|
||||
which use normalized placeholders. For example a _:user_id_ parameter
|
||||
could automatically load a user's information from the database without
|
||||
any additional code,
|
||||
|
||||
The callback uses the samesignature as middleware, the only differencing
|
||||
being that the value of the placeholder is passed, in this case the _id_
|
||||
of the user. Once the `next()` function is invoked, just like middleware
|
||||
it will continue on to execute the route, or subsequent parameter functions.
|
||||
|
||||
app.param('user_id', function(req, res, next, id){
|
||||
User.find(id, function(err, user){
|
||||
if (err) {
|
||||
next(err);
|
||||
} else if (user) {
|
||||
req.user = user;
|
||||
next();
|
||||
} else {
|
||||
next(new Error('failed to load user'));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
# app.set()
|
||||
|
||||
Assign `setting` to `val`, or return `setting`'s value.
|
||||
|
||||
app.set('foo', 'bar');
|
||||
app.get('foo');
|
||||
// => "bar"
|
||||
|
||||
Mounted servers inherit their parent server's settings.
|
||||
|
||||
# app.enabled()
|
||||
|
||||
Check if `setting` is enabled (truthy).
|
||||
|
||||
app.enabled('foo')
|
||||
// => false
|
||||
|
||||
app.enable('foo')
|
||||
app.enabled('foo')
|
||||
// => true
|
||||
|
||||
# app.disabled()
|
||||
|
||||
Check if `setting` is disabled.
|
||||
|
||||
app.disabled('foo')
|
||||
// => true
|
||||
|
||||
app.enable('foo')
|
||||
app.disabled('foo')
|
||||
// => false
|
||||
|
||||
# app.enable()
|
||||
|
||||
Enable `setting`.
|
||||
|
||||
# app.disable()
|
||||
|
||||
Disable `setting`.
|
||||
|
||||
# app.configure()
|
||||
|
||||
Configure callback for zero or more envs,
|
||||
when no `env` is specified that callback will
|
||||
be invoked for all environments. Any combination
|
||||
can be used multiple times, in any order desired.
|
||||
|
||||
## Examples
|
||||
|
||||
app.configure(function(){
|
||||
// executed for all envs
|
||||
});
|
||||
|
||||
app.configure('stage', function(){
|
||||
// executed staging env
|
||||
});
|
||||
|
||||
app.configure('stage', 'production', function(){
|
||||
// executed for stage and production
|
||||
});
|
||||
|
||||
## Note
|
||||
|
||||
These callbacks are invoked immediately, and
|
||||
are effectively sugar for the following.
|
||||
|
||||
var env = process.env.NODE_ENV || 'development';
|
||||
|
||||
switch (env) {
|
||||
case 'development':
|
||||
...
|
||||
break;
|
||||
case 'stage':
|
||||
...
|
||||
break;
|
||||
case 'production':
|
||||
...
|
||||
break;
|
||||
}
|
||||
|
||||
# app.all()
|
||||
|
||||
Special-cased "all" method, applying the given route `path`,
|
||||
middleware, and callback to _every_ HTTP method.
|
||||
|
||||
# app.render()
|
||||
|
||||
Render the given view `name` name with `options`
|
||||
and a callback accepting an error and the
|
||||
rendered template string.
|
||||
|
||||
## Example
|
||||
|
||||
app.render('email', { name: 'Tobi' }, function(err, html){
|
||||
// ...
|
||||
})
|
||||
|
||||
# app.listen()
|
||||
|
||||
Listen for connections.
|
||||
|
||||
A node `http.Server` is returned, with this
|
||||
application (which is a `Function`) as its
|
||||
callback. If you wish to create both an HTTP
|
||||
and HTTPS server you may do so with the "http"
|
||||
and "https" modules as shown here.
|
||||
|
||||
var http = require('http')
|
||||
, https = require('https')
|
||||
, express = require('express')
|
||||
, app = express();
|
||||
|
||||
http.createServer(app).listen(80);
|
||||
http.createServer({ ... }, app).listen(443);
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
.\" generated with Ronn/v0.7.3
|
||||
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
||||
.
|
||||
.TH "CONTRIB" "" "July 2010" "" ""
|
||||
.
|
||||
.SH "NAME"
|
||||
\fBcontrib\fR
|
||||
.
|
||||
.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
|
||||
.
|
||||
.P
|
||||
To check test coverage run:
|
||||
.
|
||||
.IP "" 4
|
||||
.
|
||||
.nf
|
||||
|
||||
$ make test\-cov
|
||||
.
|
||||
.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
|
||||
.
|
||||
.SS "Documentation"
|
||||
To contribute documentation edit the markdown files in \fI\./docs\fR, however do \fInot\fR run \fImake docs\fR, as they will be re\-built and published with each release\.
|
||||
@@ -1,243 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Express - node web framework</title>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
|
||||
<style>
|
||||
#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-font-smoothing: antialiased;
|
||||
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, h4 {
|
||||
margin: 45px 0 0 0;
|
||||
color: white;
|
||||
text-shadow: 1px 2px 2px rgba(0,0,0,0.6); }
|
||||
|
||||
h3 {
|
||||
font-size: 18px; }
|
||||
h4 {
|
||||
margin-left: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
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; }
|
||||
ul li ul {
|
||||
margin: 0;
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.man-name, #Express { display:none; }
|
||||
|
||||
.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: 80px;
|
||||
width: 550px; }
|
||||
|
||||
#toc {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0 0 0 15px;
|
||||
padding: 15px;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.2);
|
||||
overflow: auto;
|
||||
border-right: 1px solid rgba(255,255,255,0.05);
|
||||
}
|
||||
#toc li {
|
||||
padding: 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>
|
||||
<script>
|
||||
$(function(){
|
||||
$('.section').hide();
|
||||
$('.toggle, a.section-title').toggle(function(){
|
||||
$(this).siblings('ul').fadeIn(300);
|
||||
return false;
|
||||
}, function(){
|
||||
$(this).siblings('ul').fadeOut(300);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</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="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="Express">Express</h2>
|
||||
<p class="man-name">
|
||||
<code>contrib</code>
|
||||
</p>
|
||||
<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>
|
||||
|
||||
<p>To check test coverage run:</p>
|
||||
|
||||
<pre><code>$ make test-cov
|
||||
</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>
|
||||
|
||||
|
||||
<h3 id="Documentation">Documentation</h3>
|
||||
|
||||
<p>To contribute documentation edit the markdown files in <em>./docs</em>, however
|
||||
do <em>not</em> run <em>make docs</em>, as they will be re-built and published with each release.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,38 +0,0 @@
|
||||
|
||||
### 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
|
||||
|
||||
To check test coverage run:
|
||||
|
||||
$ make test-cov
|
||||
|
||||
### 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.
|
||||
|
||||
### Documentation
|
||||
|
||||
To contribute documentation edit the markdown files in _./docs_, however
|
||||
do _not_ run _make docs_, as they will be re-built and published with each release.
|
||||
@@ -1,28 +0,0 @@
|
||||
.\" generated with Ronn/v0.7.3
|
||||
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
||||
.
|
||||
.TH "EXECUTABLE" "" "July 2010" "" ""
|
||||
.
|
||||
.SH "NAME"
|
||||
\fBexecutable\fR
|
||||
.
|
||||
.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
|
||||
|
||||
@@ -1,215 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Express - node web framework</title>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
|
||||
<style>
|
||||
#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-font-smoothing: antialiased;
|
||||
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, h4 {
|
||||
margin: 45px 0 0 0;
|
||||
color: white;
|
||||
text-shadow: 1px 2px 2px rgba(0,0,0,0.6); }
|
||||
|
||||
h3 {
|
||||
font-size: 18px; }
|
||||
h4 {
|
||||
margin-left: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
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; }
|
||||
ul li ul {
|
||||
margin: 0;
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.man-name, #Express { display:none; }
|
||||
|
||||
.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: 80px;
|
||||
width: 550px; }
|
||||
|
||||
#toc {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0 0 0 15px;
|
||||
padding: 15px;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.2);
|
||||
overflow: auto;
|
||||
border-right: 1px solid rgba(255,255,255,0.05);
|
||||
}
|
||||
#toc li {
|
||||
padding: 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>
|
||||
<script>
|
||||
$(function(){
|
||||
$('.section').hide();
|
||||
$('.toggle, a.section-title').toggle(function(){
|
||||
$(this).siblings('ul').fadeIn(300);
|
||||
return false;
|
||||
}, function(){
|
||||
$(this).siblings('ul').fadeOut(300);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</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="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="Express">Express</h2>
|
||||
<p class="man-name">
|
||||
<code>executable</code>
|
||||
</p>
|
||||
<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>
|
||||
@@ -1,16 +0,0 @@
|
||||
|
||||
## 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
|
||||
|
||||
@@ -0,0 +1,511 @@
|
||||
|
||||
# app
|
||||
|
||||
Application prototype.
|
||||
|
||||
# app.use()
|
||||
|
||||
Proxy `connect#use()` to apply settings to
|
||||
mounted applications.
|
||||
|
||||
# app.engine()
|
||||
|
||||
Register the given template engine callback `fn`
|
||||
as `ext`.
|
||||
|
||||
By default will `require()` the engine based on the
|
||||
file extension. For example if you try to render
|
||||
a "foo.jade" file Express will invoke the following internally:
|
||||
|
||||
app.engine('jade', require('jade').__express);
|
||||
|
||||
For engines that do not provide `.__express` out of the box,
|
||||
or if you wish to "map" a different extension to the template engine
|
||||
you may use this method. For example mapping the EJS template engine to
|
||||
".html" files
|
||||
|
||||
app.engine('html', require('ejs').renderFile);
|
||||
|
||||
In this case EJS provides a `.renderFile()` method with
|
||||
the same signature that Express expects: `(path, options, callback)`,
|
||||
though note that it aliases this method as `ejs.__express` internally
|
||||
so if you're using ".ejs" extensions you dont need to do anything.
|
||||
|
||||
Some template engines do not follow this convention, the
|
||||
[Consolidate.js](https://github.com/visionmedia/consolidate.js)
|
||||
library was created to map all of node's popular template
|
||||
engines to follow this convention, thus allowing them to
|
||||
work seemlessly within Express.
|
||||
|
||||
# app.param()
|
||||
|
||||
Map the given param placeholder `name`(s) to the given callback(s).
|
||||
|
||||
Parameter mapping is used to provide pre-conditions to routes
|
||||
which use normalized placeholders. For example a _:user_id_ parameter
|
||||
could automatically load a user's information from the database without
|
||||
any additional code,
|
||||
|
||||
The callback uses the samesignature as middleware, the only differencing
|
||||
being that the value of the placeholder is passed, in this case the _id_
|
||||
of the user. Once the `next()` function is invoked, just like middleware
|
||||
it will continue on to execute the route, or subsequent parameter functions.
|
||||
|
||||
app.param('user_id', function(req, res, next, id){
|
||||
User.find(id, function(err, user){
|
||||
if (err) {
|
||||
next(err);
|
||||
} else if (user) {
|
||||
req.user = user;
|
||||
next();
|
||||
} else {
|
||||
next(new Error('failed to load user'));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
# app.set()
|
||||
|
||||
Assign `setting` to `val`, or return `setting`'s value.
|
||||
|
||||
app.set('foo', 'bar');
|
||||
app.get('foo');
|
||||
// => "bar"
|
||||
|
||||
Mounted servers inherit their parent server's settings.
|
||||
|
||||
# app.enabled()
|
||||
|
||||
Check if `setting` is enabled (truthy).
|
||||
|
||||
app.enabled('foo')
|
||||
// => false
|
||||
|
||||
app.enable('foo')
|
||||
app.enabled('foo')
|
||||
// => true
|
||||
|
||||
# app.disabled()
|
||||
|
||||
Check if `setting` is disabled.
|
||||
|
||||
app.disabled('foo')
|
||||
// => true
|
||||
|
||||
app.enable('foo')
|
||||
app.disabled('foo')
|
||||
// => false
|
||||
|
||||
# app.enable()
|
||||
|
||||
Enable `setting`.
|
||||
|
||||
# app.disable()
|
||||
|
||||
Disable `setting`.
|
||||
|
||||
# app.configure()
|
||||
|
||||
Configure callback for zero or more envs,
|
||||
when no `env` is specified that callback will
|
||||
be invoked for all environments. Any combination
|
||||
can be used multiple times, in any order desired.
|
||||
|
||||
## Examples
|
||||
|
||||
app.configure(function(){
|
||||
// executed for all envs
|
||||
});
|
||||
|
||||
app.configure('stage', function(){
|
||||
// executed staging env
|
||||
});
|
||||
|
||||
app.configure('stage', 'production', function(){
|
||||
// executed for stage and production
|
||||
});
|
||||
|
||||
## Note
|
||||
|
||||
These callbacks are invoked immediately, and
|
||||
are effectively sugar for the following.
|
||||
|
||||
var env = process.env.NODE_ENV || 'development';
|
||||
|
||||
switch (env) {
|
||||
case 'development':
|
||||
...
|
||||
break;
|
||||
case 'stage':
|
||||
...
|
||||
break;
|
||||
case 'production':
|
||||
...
|
||||
break;
|
||||
}
|
||||
|
||||
# app.all()
|
||||
|
||||
Special-cased "all" method, applying the given route `path`,
|
||||
middleware, and callback to _every_ HTTP method.
|
||||
|
||||
# app.render()
|
||||
|
||||
Render the given view `name` name with `options`
|
||||
and a callback accepting an error and the
|
||||
rendered template string.
|
||||
|
||||
## Example
|
||||
|
||||
app.render('email', { name: 'Tobi' }, function(err, html){
|
||||
// ...
|
||||
})
|
||||
|
||||
# app.listen()
|
||||
|
||||
Listen for connections.
|
||||
|
||||
A node `http.Server` is returned, with this
|
||||
application (which is a `Function`) as its
|
||||
callback. If you wish to create both an HTTP
|
||||
and HTTPS server you may do so with the "http"
|
||||
and "https" modules as shown here.
|
||||
|
||||
var http = require('http')
|
||||
, https = require('https')
|
||||
, express = require('express')
|
||||
, app = express();
|
||||
|
||||
http.createServer(app).listen(80);
|
||||
http.createServer({ ... }, app).listen(443);
|
||||
|
||||
|
||||
# req
|
||||
|
||||
Request prototype.
|
||||
|
||||
# req.get
|
||||
|
||||
Return request header.
|
||||
|
||||
The `Referrer` header field is special-cased,
|
||||
both `Referrer` and `Referer` are interchangeable.
|
||||
|
||||
## Examples
|
||||
|
||||
req.get('Content-Type');
|
||||
// => "text/plain"
|
||||
|
||||
req.get('content-type');
|
||||
// => "text/plain"
|
||||
|
||||
req.get('Something');
|
||||
// => undefined
|
||||
|
||||
Aliased as `req.header()`.
|
||||
|
||||
# req.accepts()
|
||||
|
||||
Check if the given `type(s)` is acceptable, returning
|
||||
the best match when true, otherwise `undefined`, in which
|
||||
case you should respond with 406 "Not Acceptable".
|
||||
|
||||
The `type` value may be a single mime type string
|
||||
such as "application/json", the extension name
|
||||
such as "json", a comma-delimted list such as "json, html, text/plain",
|
||||
or an array `["json", "html", "text/plain"]`. When a list
|
||||
or array is given the _best_ match, if any is returned.
|
||||
|
||||
## Examples
|
||||
|
||||
// Accept: text/html
|
||||
req.accepts('html');
|
||||
// => "html"
|
||||
|
||||
// Accept: text/*, application/json
|
||||
req.accepts('html');
|
||||
// => "html"
|
||||
req.accepts('text/html');
|
||||
// => "text/html"
|
||||
req.accepts('json, text');
|
||||
// => "json"
|
||||
req.accepts('application/json');
|
||||
// => "application/json"
|
||||
|
||||
// Accept: text/*, application/json
|
||||
req.accepts('image/png');
|
||||
req.accepts('png');
|
||||
// => undefined
|
||||
|
||||
// Accept: text/*;q=.5, application/json
|
||||
req.accepts(['html', 'json']);
|
||||
req.accepts('html, json');
|
||||
// => "json"
|
||||
|
||||
# req.acceptsCharset()
|
||||
|
||||
Check if the given `charset` is acceptable,
|
||||
otherwise you should respond with 406 "Not Acceptable".
|
||||
|
||||
# req.acceptsLanguage()
|
||||
|
||||
Check if the given `lang` is acceptable,
|
||||
otherwise you should respond with 406 "Not Acceptable".
|
||||
|
||||
# req.param()
|
||||
|
||||
Return the value of param `name` when present or `defaultValue`.
|
||||
|
||||
- Checks body params, ex: id=12, {"id":12}
|
||||
- Checks route placeholders, ex: _/user/:id_
|
||||
- Checks query string params, ex: ?id=12
|
||||
|
||||
To utilize request bodies, `req.body`
|
||||
should be an object. This can be done by using
|
||||
the `connect.bodyParser()` middleware.
|
||||
|
||||
# req.is()
|
||||
|
||||
Check if the incoming request contains the "Content-Type"
|
||||
header field, and it contains the give mime `type`.
|
||||
|
||||
## Examples
|
||||
|
||||
// With Content-Type: text/html; charset=utf-8
|
||||
req.is('html');
|
||||
req.is('text/html');
|
||||
req.is('text/*');
|
||||
// => true
|
||||
|
||||
// When Content-Type is application/json
|
||||
req.is('json');
|
||||
req.is('application/json');
|
||||
req.is('application/*');
|
||||
// => true
|
||||
|
||||
req.is('html');
|
||||
// => false
|
||||
|
||||
Now within our route callbacks, we can use to to assert content types
|
||||
such as "image/jpeg", "image/png", etc.
|
||||
|
||||
app.post('/image/upload', function(req, res, next){
|
||||
if (req.is('image/*')) {
|
||||
// do something
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
# res
|
||||
|
||||
Response prototype.
|
||||
|
||||
# res.status()
|
||||
|
||||
Set status `code`.
|
||||
|
||||
# res.send()
|
||||
|
||||
Send a response.
|
||||
|
||||
## Examples
|
||||
|
||||
res.send(new Buffer('wahoo'));
|
||||
res.send({ some: 'json' });
|
||||
res.send('<p>some html</p>');
|
||||
res.send(404, 'Sorry, cant find that');
|
||||
res.send(404);
|
||||
|
||||
# res.json()
|
||||
|
||||
Send JSON response.
|
||||
|
||||
## Examples
|
||||
|
||||
res.json(null);
|
||||
res.json({ user: 'tj' });
|
||||
res.json(500, 'oh noes!');
|
||||
res.json(404, 'I dont have that');
|
||||
|
||||
# res.sendfile()
|
||||
|
||||
Transfer the file at the given `path`.
|
||||
|
||||
Automatically sets the _Content-Type_ response header field.
|
||||
The callback `fn(err)` is invoked when the transfer is complete
|
||||
or when an error occurs. Be sure to check `res.sentHeader`
|
||||
if you wish to attempt responding, as the header and some data
|
||||
may have already been transferred.
|
||||
|
||||
## Options
|
||||
|
||||
- `maxAge` defaulting to 0
|
||||
- `root` root directory for relative filenames
|
||||
|
||||
## Examples
|
||||
|
||||
The following example illustrates how `res.sendfile()` may
|
||||
be used as an alternative for the `static()` middleware for
|
||||
dynamic situations. The code backing `res.sendfile()` is actually
|
||||
the same code, so HTTP cache support etc is identical.
|
||||
|
||||
app.get('/user/:uid/photos/:file', function(req, res){
|
||||
var uid = req.params.uid
|
||||
, file = req.params.file;
|
||||
|
||||
req.user.mayViewFilesFrom(uid, function(yes){
|
||||
if (yes) {
|
||||
res.sendfile('/uploads/' + uid + '/' + file);
|
||||
} else {
|
||||
res.send(403, 'Sorry! you cant see that.');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
# res.download()
|
||||
|
||||
Transfer the file at the given `path` as an attachment.
|
||||
|
||||
Optionally providing an alternate attachment `filename`,
|
||||
and optional callback `fn(err)`. The callback is invoked
|
||||
when the data transfer is complete, or when an error has
|
||||
ocurred. Be sure to check `res.headerSent` if you plan to respond.
|
||||
|
||||
# res.format()
|
||||
|
||||
Respond to the Acceptable formats using an `obj`
|
||||
of mime-type callbacks.
|
||||
|
||||
This method uses `req.accepted`, an array of
|
||||
acceptable types ordered by their quality values.
|
||||
When "Accept" is not present the _first_ callback
|
||||
is invoked, otherwise the first match is used. When
|
||||
no match is performed the server responds with
|
||||
406 "Not Acceptable".
|
||||
|
||||
Content-Type is set for you, however if you choose
|
||||
you may alter this within the callback using `res.type()`
|
||||
or `res.set('Content-Type', ...)`.
|
||||
|
||||
res.format({
|
||||
'text/plain': function(){
|
||||
res.send('hey');
|
||||
},
|
||||
|
||||
'text/html': function(){
|
||||
res.send('<p>hey</p>');
|
||||
},
|
||||
|
||||
'appliation/json': function(){
|
||||
res.send({ message: 'hey' });
|
||||
}
|
||||
});
|
||||
|
||||
In addition to canonicalized MIME types you may
|
||||
## also use extnames mapped to these types
|
||||
|
||||
res.format({
|
||||
text: function(){
|
||||
res.send('hey');
|
||||
},
|
||||
|
||||
html: function(){
|
||||
res.send('<p>hey</p>');
|
||||
},
|
||||
|
||||
json: function(){
|
||||
res.send({ message: 'hey' });
|
||||
}
|
||||
});
|
||||
|
||||
# res.attachment()
|
||||
|
||||
Set _Content-Disposition_ header to _attachment_ with optional `filename`.
|
||||
|
||||
# res.set()
|
||||
|
||||
Set header `field` to `val`, or pass
|
||||
an object of of header fields.
|
||||
|
||||
## Examples
|
||||
|
||||
res.set('Accept', 'application/json');
|
||||
res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' });
|
||||
|
||||
# res.get()
|
||||
|
||||
Get value for header `field`.
|
||||
|
||||
# res.clearCookie()
|
||||
|
||||
Clear cookie `name`.
|
||||
|
||||
# res.signedCookie()
|
||||
|
||||
Set a signed cookie with the given `name` and `val`.
|
||||
See `res.cookie()` for details.
|
||||
|
||||
# res.cookie()
|
||||
|
||||
Set cookie `name` to `val`, with the given `options`.
|
||||
|
||||
## Options
|
||||
|
||||
- `maxAge` max-age in milliseconds, converted to `expires`
|
||||
- `path` defaults to "/"
|
||||
|
||||
## Examples
|
||||
|
||||
// "Remember Me" for 15 minutes
|
||||
res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
|
||||
|
||||
// save as above
|
||||
res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true })
|
||||
|
||||
# res.redirect()
|
||||
|
||||
Redirect to the given `url` with optional response `status`
|
||||
defaulting 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 "/".
|
||||
|
||||
## Examples
|
||||
|
||||
res.redirect('/foo/bar');
|
||||
res.redirect('http://example.com');
|
||||
res.redirect(301, 'http://example.com');
|
||||
res.redirect('../login'); // /blog/post/1 -> /blog/login
|
||||
|
||||
## Mounting
|
||||
|
||||
When an application is mounted, and `res.redirect()`
|
||||
is given a path that does _not_ lead with "/". For
|
||||
example suppose a "blog" app is mounted at "/blog",
|
||||
the following redirect would result in "/blog/login":
|
||||
|
||||
res.redirect('login');
|
||||
|
||||
While the leading slash would result in a redirect to "/login":
|
||||
|
||||
res.redirect('/login');
|
||||
|
||||
# res.render()
|
||||
|
||||
Render `view` with the given `options` and optional callback `fn`.
|
||||
When a callback function is given a response will _not_ be made
|
||||
automatically, otherwise a response of _200_ and _text/html_ is given.
|
||||
|
||||
## Options
|
||||
|
||||
- `status` Response status code (`res.statusCode`)
|
||||
- `charset` Set the charset (`res.charset`)
|
||||
|
||||
## Reserved locals
|
||||
|
||||
- `cache` boolean hinting to the engine it should cache
|
||||
- `filename` filename of the view being rendered
|
||||
|
||||
-1645
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
-1269
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
-913
@@ -1,913 +0,0 @@
|
||||
|
||||
### Installation
|
||||
|
||||
curl:
|
||||
|
||||
$ curl -# http://expressjs.com/install.sh | sh
|
||||
|
||||
npm:
|
||||
|
||||
$ npm install express
|
||||
|
||||
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_.
|
||||
Note the use of _app.router_, which can (optionally) be used to mount the application routes,
|
||||
otherwise the first call to _app.{get,put,del,post}()_ will mount the routes.
|
||||
|
||||
app.configure(function(){
|
||||
app.use(express.methodOverride());
|
||||
app.use(express.bodyDecoder());
|
||||
app.use(app.router);
|
||||
app.use(express.staticProvider(__dirname + '/public'));
|
||||
});
|
||||
|
||||
app.configure('development', function(){
|
||||
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
|
||||
});
|
||||
|
||||
app.configure('production', function(){
|
||||
app.use(express.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 _NODE_ENV_ environment variable, for example:
|
||||
|
||||
$ NODE_ENV=production node app.js
|
||||
|
||||
### Settings
|
||||
|
||||
Express supports the following settings out of the box:
|
||||
|
||||
* _env_ Application environment set internally, use _app.set('env')_ on _Server#listen()_
|
||||
* _home_ Application base path used for _res.redirect()_ and transparently handling mounted apps.
|
||||
* _views_ Root views directory defaulting to **CWD/views**
|
||||
* _view engine_ Default view engine name for views rendered without extensions
|
||||
* _view options_ An object specifying global view options
|
||||
* _partials_ Root view partials directory defaulting to _views_/partials.
|
||||
* _stream threshold_ Bytesize indicating when a file should be streamed for _res.sendfile()_ using _fs.ReadStream()_ and _sys.pump()_.
|
||||
|
||||
### 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 available as `req.params`.
|
||||
|
||||
app.get('/user/:id', function(req, res){
|
||||
res.send('user ' + req.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\/([^\/]+)\/?
|
||||
|
||||
Regular expression literals may also be passed for complex uses. Since capture
|
||||
groups with literal _RegExp_'s are anonymous we can access them directly `req.params`.
|
||||
|
||||
app.get(/^\/users?(?:\/(\d+)(?:\.\.(\d+))?)?/, function(req, res){
|
||||
res.send(req.params);
|
||||
});
|
||||
|
||||
Curl requests against the previously defined route:
|
||||
|
||||
$ curl http://dev:3000/user
|
||||
[null,null]
|
||||
$ curl http://dev:3000/users
|
||||
[null,null]
|
||||
$ curl http://dev:3000/users/1
|
||||
["1",null]
|
||||
$ curl http://dev:3000/users/1..15
|
||||
["1","15"]
|
||||
|
||||
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 _third_ argument,
|
||||
the _next()_ function. When a match cannot be made, control is passed back to Connect,
|
||||
and middleware continue to be invoked. The same is true for several routes which have the same path defined, they will simply be executed in order until one does _not_ call _next()_.
|
||||
|
||||
app.get('/users/:id?', function(req, res, next){
|
||||
var id = req.params.id;
|
||||
if (id) {
|
||||
// do something
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/users', function(req, res){
|
||||
// do something else
|
||||
});
|
||||
|
||||
### Middleware
|
||||
|
||||
Middleware via [Connect](http://github.com/senchalabs/connect) can be
|
||||
passed to _express.createServer()_ as you would with a regular Connect server. For example:
|
||||
|
||||
var express = require('express');
|
||||
|
||||
var app = express.createServer(
|
||||
express.logger(),
|
||||
express.bodyDecoder()
|
||||
);
|
||||
|
||||
Alternatively we can _use()_ them which is useful when adding middleware within _configure()_ blocks:
|
||||
|
||||
app.use(express.logger({ format: ':method :uri' }));
|
||||
|
||||
Typically with connect middleware you would _require('connect')_ like so:
|
||||
|
||||
var connect = require('connect');
|
||||
app.use(connect.logger());
|
||||
|
||||
This is somewhat annoying, so express re-exports these middleware properties, however they are _identical_:
|
||||
|
||||
app.use(express.logger());
|
||||
|
||||
### Route Middleware
|
||||
|
||||
Routes may utilize route-specific middleware by passing one or more additional callbacks (or arrays) to the method. This feature is extremely useful for restricting access, loading data used by the route etc.
|
||||
|
||||
Typically async data retrieval might look similar to below, where we take the _:id_ parameter, and attempt loading a user.
|
||||
|
||||
app.get('/user/:id', function(req, res, next){
|
||||
loadUser(req.params.id, function(err, user){
|
||||
if (err) return next(err);
|
||||
res.send('Viewing user ' + user.name);
|
||||
});
|
||||
});
|
||||
|
||||
To keep things DRY and to increase readability we can apply this logic within a middleware. As you can see below, abstracting this logic into middleware allows us to reuse it, and clean up our route at the same time.
|
||||
|
||||
function loadUser(req, res, next) {
|
||||
// You would fetch your user from the db
|
||||
var user = users[req.params.id];
|
||||
if (user) {
|
||||
req.user = user;
|
||||
next();
|
||||
} else {
|
||||
next(new Error('Failed to load user ' + req.params.id));
|
||||
}
|
||||
}
|
||||
|
||||
app.get('/user/:id', loadUser, function(req, res){
|
||||
res.send('Viewing user ' + req.user.name);
|
||||
});
|
||||
|
||||
Multiple route middleware can be applied, and will be executed sequentially to apply further logic such as restricting access to a user account. In the example below only the authenticated user may edit his/her account.
|
||||
|
||||
function andRestrictToSelf(req, res, next) {
|
||||
req.authenticatedUser.id == req.user.id
|
||||
? next()
|
||||
: next(new Error('Unauthorized'));
|
||||
}
|
||||
|
||||
app.get('/user/:id/edit', loadUser, andRestrictToSelf, function(req, res){
|
||||
res.send('Editing user ' + req.user.name);
|
||||
});
|
||||
|
||||
Keeping in mind that middleware are simply functions, we can define function that _returns_ the middleware in order to create a more expressive and flexible solution as shown below.
|
||||
|
||||
function andRestrictTo(role) {
|
||||
return function(req, res, next) {
|
||||
req.authenticatedUser.role == role
|
||||
? next()
|
||||
: next(new Error('Unauthorized'));
|
||||
}
|
||||
}
|
||||
|
||||
app.del('/user/:id', loadUser, andRestrictTo('admin'), function(req, res){
|
||||
res.send('Deleted user ' + req.user.name);
|
||||
});
|
||||
|
||||
Commonly used "stacks" of middleware can be passed as an array (_applied recursively_), which can be mixed and matched to any degree.
|
||||
|
||||
var a = [middleware1, middleware2]
|
||||
, b = [middleware3, middleware4]
|
||||
, all = [a, b];
|
||||
|
||||
app.get('/foo', a, function(){});
|
||||
app.get('/bar', a, function(){});
|
||||
|
||||
app.get('/', a, middleware3, middleware4, function(){});
|
||||
app.get('/', a, b, function(){});
|
||||
app.get('/', all, function(){});
|
||||
|
||||
For this example in full, view the [route middleware example](http://github.com/visionmedia/express/blob/master/examples/route-middleware/app.js) in the repository.
|
||||
|
||||
### HTTP Methods
|
||||
|
||||
We have seen _app.get()_ a few times, however Express also exposes other familiar HTTP verbs in the same manor, such as _app.post()_, _app.del()_, etc.
|
||||
|
||||
A common example for _POST_ usage, is when "submitting" a form. Below we simply set our form method to "post" in our html, and control will be given to the route we have defined below it.
|
||||
|
||||
<form method="post" action="/">
|
||||
<input type="text" name="user[name]" />
|
||||
<input type="text" name="user[email]" />
|
||||
<input type="submit" value="Submit" />
|
||||
</form>
|
||||
|
||||
By default Express does not know what to do with this request body, so we should add the _bodyDecoder_ middleware, which will parse _application/x-www-form-urlencoded_ request bodies and place the variables in _req.body_. We can do this by "using" the middleware as shown below:
|
||||
|
||||
app.use(express.bodyDecoder());
|
||||
|
||||
Our route below will now have access to the _req.body.user_ object which will contain the _name_ and _email_ properties when defined.
|
||||
|
||||
app.post('/', function(req, res){
|
||||
console.log(req.body.user);
|
||||
res.redirect('back');
|
||||
});
|
||||
|
||||
When using methods such as _PUT_ with a form, we can utilize a hidden input named _\_method_, which can be used to alter the HTTP method. To do so we first need the _methodOverride_ middleware, which should be placed below _bodyDecoder_ so that it can utilize it's _req.body_ containing the form values.
|
||||
|
||||
app.use(express.bodyDecoder());
|
||||
app.use(express.methodOverride());
|
||||
|
||||
The reason that these are not always defaults, is simply because these are not required for Express to be fully functional. Depending on the needs of your application, you may not need these at all, your methods such as _PUT_ and _DELETE_ can still be accessed by clients which can use them directly, although _methodOverride_ provides a great solution for forms. Below shows what the usage of _PUT_ might look like:
|
||||
|
||||
<form method="post" action="/">
|
||||
<input type="hidden" name="_method" value="put" />
|
||||
<input type="text" name="user[name]" />
|
||||
<input type="text" name="user[email]" />
|
||||
<input type="submit" value="Submit" />
|
||||
</form>
|
||||
|
||||
app.put('/', function(){
|
||||
console.log(req.body.user);
|
||||
res.redirect('back');
|
||||
});
|
||||
|
||||
### 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.
|
||||
|
||||
Note that these handlers can be defined anywhere, as they
|
||||
will be placed below the route handlers on _listen()_. This
|
||||
allows for definition within _configure()_ blocks so we can
|
||||
handle exceptions in different ways based on the environment.
|
||||
|
||||
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(express.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(express.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 export the method _exports.render(str, options)_ to comply with Express, however
|
||||
_app.register()_ can be used to map engines to file extensions, so that for example "foo.html" can be rendered by jade.
|
||||
|
||||
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' }
|
||||
});
|
||||
});
|
||||
|
||||
The new _view engine_ setting allows us to specify our default template engine,
|
||||
so for example when using [Jade](http://github.com/visionmedia/jade) we could set:
|
||||
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
Allowing us to render with:
|
||||
|
||||
res.render('index');
|
||||
|
||||
vs:
|
||||
|
||||
res.render('index.jade');
|
||||
|
||||
When _view engine_ is set, extensions are entirely optional, however we can still
|
||||
mix and match template engines:
|
||||
|
||||
res.render('another-page.ejs');
|
||||
|
||||
Express also provides the _view options_ setting, which is applied each time a view is rendered, so for example if you rarely use layouts you may set:
|
||||
|
||||
app.set('view options', {
|
||||
layout: false
|
||||
});
|
||||
|
||||
Which can then be overridden within the `res.render()` call if need be:
|
||||
|
||||
res.render('myview.ejs', { layout: true });
|
||||
|
||||
When an alternate layout is required, we may also specify a path. For example if we have _view engine_ set to _jade_ and a file named _./views/mylayout.jade_ we can simply pass:
|
||||
|
||||
res.render('page', { layout: 'mylayout' });
|
||||
|
||||
Otherwise we must specify the extension:
|
||||
|
||||
res.render('page', { layout: 'mylayout.jade' });
|
||||
|
||||
These paths may also be absolute:
|
||||
|
||||
res.render('page', { layout: __dirname + '/../../mylayout.jade' });
|
||||
|
||||
A good example of this is specifying custom _ejs_ opening and closing tags:
|
||||
|
||||
app.set('view options', {
|
||||
open: '{{',
|
||||
close: '}}'
|
||||
});
|
||||
|
||||
### 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);
|
||||
|
||||
When using the partial collection support a few "magic" variables are provided
|
||||
for free:
|
||||
|
||||
* _firstInCollection_ True if this is the first object
|
||||
* _indexInCollection_ Index of the object in the collection
|
||||
* _lastInCollection_ True if this is the last object
|
||||
|
||||
### Template Engines
|
||||
|
||||
Below are a few template engines commonly used with Express:
|
||||
|
||||
* [Jade](http://jade-lang.com) haml.js successor
|
||||
* [Haml](http://github.com/visionmedia/haml.js) pythonic indented templates
|
||||
* [EJS](http://github.com/visionmedia/ejs) Embedded JavaScript
|
||||
|
||||
### Session Support
|
||||
|
||||
Sessions support can be added by using Connect's _session_ middleware. To do so we also need the _cookieDecoder_ middleware place above it, which will parse and populate cookie data to _req.cookies_.
|
||||
|
||||
app.use(express.cookieDecoder());
|
||||
app.use(express.session());
|
||||
|
||||
By default the _session_ middleware uses the memory store bundled with Connect, however many implementations exist. For example [connect-redis](http://github.com/visionmedia/connect-redis) supplies a [Redis](http://code.google.com/p/redis/) session store and can be used as shown below:
|
||||
|
||||
var RedisStore = require('connect-redis');
|
||||
app.use(express.cookieDecoder());
|
||||
app.use(express.session({ store: new RedisStore }));
|
||||
|
||||
Now the _req.session_ and _req.sessionStore_ properties will be accessible to all routes and subsequent middleware. Properties on _req.session_ are automatically saved on a response, so for example if we wish to shopping cart data:
|
||||
|
||||
var RedisStore = require('connect-redis');
|
||||
app.use(express.cookieDecoder());
|
||||
app.use(express.session({ store: new RedisStore }));
|
||||
app.use(express.bodyDecoder());
|
||||
|
||||
app.post('/add-to-cart', function(req, res){
|
||||
// Perhaps we posted several items with a form
|
||||
// (use the bodyDecoder() middleware for this)
|
||||
var items = req.body.items;
|
||||
req.session.items = items;
|
||||
res.redirect('back');
|
||||
});
|
||||
|
||||
app.get('/add-to-cart', function(req, res){
|
||||
// When redirected back to GET /add-to-cart
|
||||
// we could check req.session.items && req.session.items.length
|
||||
// to print out a message
|
||||
if (req.session.items && req.session.items.length) {
|
||||
req.flash('info', 'You have %s items in your cart', req.session.items.length);
|
||||
}
|
||||
res.render('shopping-cart');
|
||||
});
|
||||
|
||||
The _req.session_ object also has methods such as _Session#touch()_, _Session#destroy()_, _Session#regenerate()_ among others to maintain and manipulate sessions. For more information view the [Connect Session](http://senchalabs.github.com/connect/session.html) documentation.
|
||||
|
||||
### 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 (_req.params_), ex: /user/:id
|
||||
- Checks query string params (_req.query_), ex: ?id=12
|
||||
- Checks urlencoded body params (_req.body_), ex: id=12
|
||||
|
||||
To utilize urlencoded request bodies, _req.body_
|
||||
should be an object. This can be done by using
|
||||
the _express.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: [] }
|
||||
|
||||
Flash notification message may also utilize formatters, by default only the %s string formatter is available:
|
||||
|
||||
req.flash('info', 'email delivery to _%s_ from _%s_ failed.', toUser, fromUser);
|
||||
|
||||
### 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');
|
||||
|
||||
This method accepts a callback which when given will be called on an exception, as well as when the transfer has completed. When a callback is not given, and the file has __not__ been streamed, _next(err)_ will be called on an exception.
|
||||
|
||||
res.sendfile(path, function(err, path){
|
||||
if (err) {
|
||||
// handle the error
|
||||
} else {
|
||||
console.log('transferred %s', path);
|
||||
}
|
||||
});
|
||||
|
||||
When the filesize exceeds the _stream threshold_ (defaulting to 32k), the file will be streamed using _fs.ReadStream_ and _sys.pump()_.
|
||||
|
||||
### 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(); // 204
|
||||
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 "/".
|
||||
|
||||
### res.cookie(name, val[, options])
|
||||
|
||||
Sets the given cookie _name_ to _val_, with _options_ such as "httpOnly: true", "expires", "secure" etc.
|
||||
|
||||
// "Remember me" for 15 minutes
|
||||
res.cookie('rememberme', 'yes', { expires: new Date(Date.now() + 900000), httpOnly: true });
|
||||
|
||||
To parse incoming _Cookie_ headers, use the _cookieDecoder_ middleware, which provides the _req.cookies_ object:
|
||||
|
||||
app.use(express.cookieDecoder());
|
||||
|
||||
app.get('/', function(req, res){
|
||||
// use req.cookies.rememberme
|
||||
});
|
||||
|
||||
### res.clearCookie(name)
|
||||
|
||||
Clear cookie _name_ by setting "expires" far in the past.
|
||||
|
||||
res.clearCookie('rememberme');
|
||||
|
||||
### res.render(view[, options[, fn]])
|
||||
|
||||
Render _view_ with the given _options_ and optional callback _fn_.
|
||||
When a callback function is given a response will _not_ be made
|
||||
automatically, however otherwise a response of _200_ and _text/html_ is given.
|
||||
|
||||
Most engines accept one or more of the following options,
|
||||
both [haml](http://github.com/visionmedia/haml.js) and [jade](http://github.com/visionmedia/jade) accept all:
|
||||
|
||||
- _scope_ Template evaluation context (value of _this_)
|
||||
- _locals_ Object containing local variables
|
||||
- _debug_ Output debugging information
|
||||
- _status_ Response status code, defaults to 200
|
||||
- _headers_ Response headers object
|
||||
|
||||
### res.partial(view[, options])
|
||||
|
||||
Render _view_ partial with the given _options_. This method is always available
|
||||
to the view as a local variable.
|
||||
|
||||
- _as_ Variable name for each _collection_ value, defaults to the view name.
|
||||
* as: 'something' will add the _something_ local variable
|
||||
* as: this will use the collection value as the template context
|
||||
* as: global will merge the collection value's properties with _locals_
|
||||
|
||||
- _collection_ Array of objects, the name is derived from the view name itself.
|
||||
For example _video.html_ will have a object _video_ available to it.
|
||||
|
||||
The following are equivalent, and the name of collection value when passed
|
||||
to the partial will be _movie_ as derived from the name.
|
||||
|
||||
partial('movie.jade', { collection: movies });
|
||||
partial('movie.jade', movies);
|
||||
partial('movie', movies);
|
||||
// In view: movie.director
|
||||
|
||||
To change the local from _movie_ to _video_ we can use the "as" option:
|
||||
|
||||
partial('movie', { collection: movies, as: 'video' });
|
||||
// In view: video.director
|
||||
|
||||
Also we can make our movie the value of _this_ within our view so that instead
|
||||
of _movie.director_ we could use _this.director_.
|
||||
|
||||
partial('movie', { collection: movies, as: this });
|
||||
// In view: this.director
|
||||
|
||||
Another alternative is to "explode" the properties of the collection item into
|
||||
pseudo globals (local variables) by using _as: global_, which again is syntactic sugar:
|
||||
|
||||
partials('movie', { collection: movies, as: global });
|
||||
// In view: director
|
||||
|
||||
### 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('views', __dirname + '/views');
|
||||
app.set('views');
|
||||
// => ...path...
|
||||
|
||||
### 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){
|
||||
return '/post/' + req.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.helpers(obj)
|
||||
|
||||
Registers static view helpers.
|
||||
|
||||
app.helpers({
|
||||
name: function(first, last){ return first + ', ' + last },
|
||||
firstName: 'tj',
|
||||
lastName: 'holowaychuk'
|
||||
});
|
||||
|
||||
Our view could now utilize the _firstName_ and _lastName_ variables,
|
||||
as well as the _name()_ function exposed.
|
||||
|
||||
<%= name(firstName, lastName) %>
|
||||
|
||||
### app.dynamicHelpers(obj)
|
||||
|
||||
Registers dynamic view helpers. Dynamic view helpers
|
||||
are simply functions which accept _req_, _res_, and are
|
||||
evaluated against the _Server_ instance before a view is rendered. The _return value_ of this function
|
||||
becomes the local variable it is associated with.
|
||||
|
||||
app.dynamicHelpers({
|
||||
session: function(req, res){
|
||||
return req.session;
|
||||
}
|
||||
});
|
||||
|
||||
All views would now have _session_ available so that session data can be accessed via _session.name_ etc:
|
||||
|
||||
<%= session.name %>
|
||||
|
||||
### app.mounted(fn)
|
||||
|
||||
Assign a callback _fn_ which is called when this _Server_ is passed to _Server#use()_.
|
||||
|
||||
var app = express.createServer(),
|
||||
blog = express.createServer();
|
||||
|
||||
blog.mounted(function(parent){
|
||||
// parent is app
|
||||
// "this" is blog
|
||||
});
|
||||
|
||||
app.use(blog);
|
||||
|
||||
### app.register(ext, exports)
|
||||
|
||||
Register the given template engine _exports_
|
||||
as _ext_. For example we may wish to map ".html"
|
||||
files to jade:
|
||||
|
||||
app.register('.html', require('jade'));
|
||||
|
||||
This is also useful for libraries that may not
|
||||
match extensions correctly. For example my haml.js
|
||||
library is installed from npm as "hamljs" so instead
|
||||
of layout.hamljs, we can register the engine as ".haml":
|
||||
|
||||
app.register('.haml', require('haml-js'));
|
||||
|
||||
For engines that do not comply with the Express
|
||||
specification, we can also wrap their api this way.
|
||||
|
||||
app.register('.foo', {
|
||||
render: function(str, options) {
|
||||
// perhaps their api is
|
||||
// return foo.toHTML(str, options);
|
||||
}
|
||||
});
|
||||
|
||||
### 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.
|
Antes Largura: | Altura: | Tamanho: 108 KiB |
Arquivo binário não exibido.
|
Antes Largura: | Altura: | Tamanho: 7.0 KiB |
Arquivo binário não exibido.
|
Antes Largura: | Altura: | Tamanho: 7.2 KiB |
Arquivo binário não exibido.
|
Antes Largura: | Altura: | Tamanho: 143 B |
-143
@@ -1,143 +0,0 @@
|
||||
.\" generated with Ronn/v0.7.3
|
||||
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
||||
.
|
||||
.TH "INDEX" "" "October 2010" "" ""
|
||||
.
|
||||
.SH "NAME"
|
||||
\fBindex\fR
|
||||
.
|
||||
.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
|
||||
Dynamic view helpers
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
Application level view options
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
Content negotiation
|
||||
.
|
||||
.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://github\.com/senchalabs/connect\fR
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
Executable \fIexecutable\.html\fR for generating applications quickly
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
High test coverage
|
||||
.
|
||||
.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 "\(bu" 4
|
||||
Guillermo Rauch (guille \fIhttp://github\.com/guille\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 Connect \fIhttp://github\.com/senchalabs/connect\fR repo for middleware usage
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
View the Connect Wiki \fIhttp://wiki\.github\.com/senchalabs/connect/\fR for contrib middleware
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
View the examples \fIhttp://github\.com/visionmedia/express/tree/master/examples/\fR
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
View the source \fIhttp://github\.com/visionmedia/express\fR
|
||||
.
|
||||
.IP "" 0
|
||||
.
|
||||
.SH "Apps Using Express"
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
LearnBoost \fIhttp://learnboost\.com\fR \- Online gradebook software
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
Markup\.IO \fIhttp://markup\.io/\fR \- Draw on any website to share ideas
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
wtfjs \fIhttp://wtfjs\.com/\fR \- JavaScript WTFs :)
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
Node Knockout \fIhttp://nodeknockout\.com/\fR \- node knockout competition site
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
Node News \fIhttp://nodejs\.se/\fR \- node news aggregator
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
Code Shelver \fIhttp://codeshelver\.com/\fR \- GitHub watch list app
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
Clickdummy \fIhttp://clickdummy\.net/\fR \- Fast prototyping for designers
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
E\-Resistible \fIhttp://e\-resistible\.co\.uk\fR \- Online takeaway ordering app
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
Storify \fIhttp://storify\.com\fR \- The future of publishing
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
Ogre \fIhttp://ogre\.adc4gis\.com/\fR \- Translates spatial files into GeoJSON
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
Widescript \fIhttp://widescript\.com/\fR \- A digital reading app targeted to people who study or make use of reference material
|
||||
.
|
||||
.IP "" 0
|
||||
|
||||
@@ -1,267 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Express - node web framework</title>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
|
||||
<style>
|
||||
#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-font-smoothing: antialiased;
|
||||
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, h4 {
|
||||
margin: 45px 0 0 0;
|
||||
color: white;
|
||||
text-shadow: 1px 2px 2px rgba(0,0,0,0.6); }
|
||||
|
||||
h3 {
|
||||
font-size: 18px; }
|
||||
h4 {
|
||||
margin-left: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
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; }
|
||||
ul li ul {
|
||||
margin: 0;
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.man-name, #Express { display:none; }
|
||||
|
||||
.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: 80px;
|
||||
width: 550px; }
|
||||
|
||||
#toc {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0 0 0 15px;
|
||||
padding: 15px;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.2);
|
||||
overflow: auto;
|
||||
border-right: 1px solid rgba(255,255,255,0.05);
|
||||
}
|
||||
#toc li {
|
||||
padding: 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>
|
||||
<script>
|
||||
$(function(){
|
||||
$('.section').hide();
|
||||
$('.toggle, a.section-title').toggle(function(){
|
||||
$(this).siblings('ul').fadeIn(300);
|
||||
return false;
|
||||
}, function(){
|
||||
$(this).siblings('ul').fadeOut(300);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</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="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="Express">Express</h2>
|
||||
<p class="man-name">
|
||||
<code>index</code>
|
||||
</p>
|
||||
<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>Dynamic view helpers</li>
|
||||
<li>Application level view options</li>
|
||||
<li>Content negotiation</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://github.com/senchalabs/connect">Connect</a></li>
|
||||
<li><a href="executable.html">Executable</a> for generating applications quickly</li>
|
||||
<li>High test coverage</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>
|
||||
<li>Guillermo Rauch (<a href="http://github.com/guille">guille</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/senchalabs/connect">Connect</a> repo for middleware usage</li>
|
||||
<li>View the <a href="http://wiki.github.com/senchalabs/connect/">Connect Wiki</a> for contrib middleware</li>
|
||||
<li>View the <a href="http://github.com/visionmedia/express/tree/master/examples/">examples</a></li>
|
||||
<li>View the <a href="http://github.com/visionmedia/express">source</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2 id="Apps-Using-Express">Apps Using Express</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="http://learnboost.com">LearnBoost</a> - Online gradebook software</li>
|
||||
<li><a href="http://markup.io/">Markup.IO</a> - Draw on any website to share ideas</li>
|
||||
<li><a href="http://wtfjs.com/">wtfjs</a> - JavaScript WTFs :)</li>
|
||||
<li><a href="http://nodeknockout.com/">Node Knockout</a> - node knockout competition site</li>
|
||||
<li><a href="http://nodejs.se/">Node News</a> - node news aggregator</li>
|
||||
<li><a href="http://codeshelver.com/">Code Shelver</a> - GitHub watch list app</li>
|
||||
<li><a href="http://clickdummy.net/">Clickdummy</a> - Fast prototyping for designers</li>
|
||||
<li><a href="http://e-resistible.co.uk">E-Resistible</a> - Online takeaway ordering app</li>
|
||||
<li><a href="http://storify.com">Storify</a> - The future of publishing</li>
|
||||
<li><a href="http://ogre.adc4gis.com/">Ogre</a> - Translates spatial files into GeoJSON</li>
|
||||
<li><a href="http://widescript.com/">Widescript</a> - A digital reading app targeted to people who study or make use of reference material</li>
|
||||
</ul>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,56 +0,0 @@
|
||||
|
||||
var app = express.createServer();
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.send('Hello World');
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
|
||||
## Features
|
||||
|
||||
* Robust routing
|
||||
* Redirection helpers
|
||||
* Dynamic view helpers
|
||||
* Application level view options
|
||||
* Content negotiation
|
||||
* Focus on high performance
|
||||
* View rendering and partials support
|
||||
* Environment based configuration
|
||||
* Session based flash notifications
|
||||
* Built on [Connect](http://github.com/senchalabs/connect)
|
||||
* [Executable](executable.html) for generating applications quickly
|
||||
* High test coverage
|
||||
|
||||
## 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))
|
||||
* Guillermo Rauch ([guille](http://github.com/guille))
|
||||
|
||||
## 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 [Connect](http://github.com/senchalabs/connect) repo for middleware usage
|
||||
* View the [Connect Wiki](http://wiki.github.com/senchalabs/connect/) for contrib middleware
|
||||
* View the [examples](http://github.com/visionmedia/express/tree/master/examples/)
|
||||
* View the [source](http://github.com/visionmedia/express)
|
||||
|
||||
## Apps Using Express
|
||||
|
||||
* [LearnBoost](http://learnboost.com) - Online gradebook software
|
||||
* [Markup.IO](http://markup.io/) - Draw on any website to share ideas
|
||||
* [wtfjs](http://wtfjs.com/) - JavaScript WTFs :)
|
||||
* [Node Knockout](http://nodeknockout.com/) - node knockout competition site
|
||||
* [Node News](http://nodejs.se/) - node news aggregator
|
||||
* [Code Shelver](http://codeshelver.com/) - GitHub watch list app
|
||||
* [Clickdummy](http://clickdummy.net/) - Fast prototyping for designers
|
||||
* [E-Resistible](http://e-resistible.co.uk) - Online takeaway ordering app
|
||||
* [Storify](http://storify.com) - The future of publishing
|
||||
* [Ogre](http://ogre.adc4gis.com/) - Translates spatial files into GeoJSON
|
||||
* [Widescript](http://widescript.com/) - A digital reading app targeted to people who study or make use of reference material
|
||||
@@ -1,4 +0,0 @@
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,188 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Express - node web framework</title>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
|
||||
<style>
|
||||
#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-font-smoothing: antialiased;
|
||||
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, h4 {
|
||||
margin: 45px 0 0 0;
|
||||
color: white;
|
||||
text-shadow: 1px 2px 2px rgba(0,0,0,0.6); }
|
||||
|
||||
h3 {
|
||||
font-size: 18px; }
|
||||
h4 {
|
||||
margin-left: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
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; }
|
||||
ul li ul {
|
||||
margin: 0;
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.man-name, #Express { display:none; }
|
||||
|
||||
.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: 80px;
|
||||
width: 550px; }
|
||||
|
||||
#toc {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0 0 0 15px;
|
||||
padding: 15px;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.2);
|
||||
overflow: auto;
|
||||
border-right: 1px solid rgba(255,255,255,0.05);
|
||||
}
|
||||
#toc li {
|
||||
padding: 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>
|
||||
<script>
|
||||
$(function(){
|
||||
$('.section').hide();
|
||||
$('.toggle, a.section-title').toggle(function(){
|
||||
$(this).siblings('ul').fadeIn(300);
|
||||
return false;
|
||||
}, function(){
|
||||
$(this).siblings('ul').fadeOut(300);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</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="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>
|
||||
@@ -1,347 +0,0 @@
|
||||
.\" generated with Ronn/v0.7.3
|
||||
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
||||
.
|
||||
.TH "MIGRATE" "" "October 2010" "" ""
|
||||
.
|
||||
.SH "NAME"
|
||||
\fBmigrate\fR
|
||||
.
|
||||
.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 app = express\.createServer(
|
||||
express\.logger(),
|
||||
express\.methodOverride(),
|
||||
express\.cookieDecoder()
|
||||
);
|
||||
.
|
||||
.fi
|
||||
.
|
||||
.IP "" 0
|
||||
.
|
||||
.P
|
||||
or:
|
||||
.
|
||||
.IP "" 4
|
||||
.
|
||||
.nf
|
||||
|
||||
var app = express\.createServer();
|
||||
|
||||
app\.use(express\.logger());
|
||||
app\.use(express\.methodOverride());
|
||||
app\.use(express\.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, res){
|
||||
req\.param(\'id\');
|
||||
});
|
||||
.
|
||||
.fi
|
||||
.
|
||||
.IP "" 0
|
||||
.
|
||||
.P
|
||||
Route parameters are available via \fBreq\.params\fR:
|
||||
.
|
||||
.IP "" 4
|
||||
.
|
||||
.nf
|
||||
|
||||
app\.get(\'/user/:id\', function(req, res){
|
||||
req\.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 third 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, 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
|
||||
|
||||
@@ -1,408 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Express - node web framework</title>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
|
||||
<style>
|
||||
#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-font-smoothing: antialiased;
|
||||
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, h4 {
|
||||
margin: 45px 0 0 0;
|
||||
color: white;
|
||||
text-shadow: 1px 2px 2px rgba(0,0,0,0.6); }
|
||||
|
||||
h3 {
|
||||
font-size: 18px; }
|
||||
h4 {
|
||||
margin-left: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
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; }
|
||||
ul li ul {
|
||||
margin: 0;
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.man-name, #Express { display:none; }
|
||||
|
||||
.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: 80px;
|
||||
width: 550px; }
|
||||
|
||||
#toc {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0 0 0 15px;
|
||||
padding: 15px;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.2);
|
||||
overflow: auto;
|
||||
border-right: 1px solid rgba(255,255,255,0.05);
|
||||
}
|
||||
#toc li {
|
||||
padding: 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>
|
||||
<script>
|
||||
$(function(){
|
||||
$('.section').hide();
|
||||
$('.toggle, a.section-title').toggle(function(){
|
||||
$(this).siblings('ul').fadeIn(300);
|
||||
return false;
|
||||
}, function(){
|
||||
$(this).siblings('ul').fadeOut(300);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</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="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="Express">Express</h2>
|
||||
<p class="man-name">
|
||||
<code>migrate</code>
|
||||
</p>
|
||||
<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 app = express.createServer(
|
||||
express.logger(),
|
||||
express.methodOverride(),
|
||||
express.cookieDecoder()
|
||||
);
|
||||
</code></pre>
|
||||
|
||||
<p>or:</p>
|
||||
|
||||
<pre><code>var app = express.createServer();
|
||||
|
||||
app.use(express.logger());
|
||||
app.use(express.methodOverride());
|
||||
app.use(express.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, res){
|
||||
req.param('id');
|
||||
});
|
||||
</code></pre>
|
||||
|
||||
<p>Route parameters are available via <code>req.params</code>:</p>
|
||||
|
||||
<pre><code>app.get('/user/:id', function(req, res){
|
||||
req.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 third 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, 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>
|
||||
@@ -1,189 +0,0 @@
|
||||
|
||||
### 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 app = express.createServer(
|
||||
express.logger(),
|
||||
express.methodOverride(),
|
||||
express.cookieDecoder()
|
||||
);
|
||||
|
||||
or:
|
||||
|
||||
var app = express.createServer();
|
||||
|
||||
app.use(express.logger());
|
||||
app.use(express.methodOverride());
|
||||
app.use(express.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, res){
|
||||
req.param('id');
|
||||
});
|
||||
|
||||
Route parameters are available via `req.params`:
|
||||
|
||||
app.get('/user/:id', function(req, res){
|
||||
req.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 third 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, 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
|
||||
@@ -0,0 +1,118 @@
|
||||
|
||||
# req
|
||||
|
||||
Request prototype.
|
||||
|
||||
# req.get
|
||||
|
||||
Return request header.
|
||||
|
||||
The `Referrer` header field is special-cased,
|
||||
both `Referrer` and `Referer` are interchangeable.
|
||||
|
||||
## Examples
|
||||
|
||||
req.get('Content-Type');
|
||||
// => "text/plain"
|
||||
|
||||
req.get('content-type');
|
||||
// => "text/plain"
|
||||
|
||||
req.get('Something');
|
||||
// => undefined
|
||||
|
||||
Aliased as `req.header()`.
|
||||
|
||||
# req.accepts()
|
||||
|
||||
Check if the given `type(s)` is acceptable, returning
|
||||
the best match when true, otherwise `undefined`, in which
|
||||
case you should respond with 406 "Not Acceptable".
|
||||
|
||||
The `type` value may be a single mime type string
|
||||
such as "application/json", the extension name
|
||||
such as "json", a comma-delimted list such as "json, html, text/plain",
|
||||
or an array `["json", "html", "text/plain"]`. When a list
|
||||
or array is given the _best_ match, if any is returned.
|
||||
|
||||
## Examples
|
||||
|
||||
// Accept: text/html
|
||||
req.accepts('html');
|
||||
// => "html"
|
||||
|
||||
// Accept: text/*, application/json
|
||||
req.accepts('html');
|
||||
// => "html"
|
||||
req.accepts('text/html');
|
||||
// => "text/html"
|
||||
req.accepts('json, text');
|
||||
// => "json"
|
||||
req.accepts('application/json');
|
||||
// => "application/json"
|
||||
|
||||
// Accept: text/*, application/json
|
||||
req.accepts('image/png');
|
||||
req.accepts('png');
|
||||
// => undefined
|
||||
|
||||
// Accept: text/*;q=.5, application/json
|
||||
req.accepts(['html', 'json']);
|
||||
req.accepts('html, json');
|
||||
// => "json"
|
||||
|
||||
# req.acceptsCharset()
|
||||
|
||||
Check if the given `charset` is acceptable,
|
||||
otherwise you should respond with 406 "Not Acceptable".
|
||||
|
||||
# req.acceptsLanguage()
|
||||
|
||||
Check if the given `lang` is acceptable,
|
||||
otherwise you should respond with 406 "Not Acceptable".
|
||||
|
||||
# req.param()
|
||||
|
||||
Return the value of param `name` when present or `defaultValue`.
|
||||
|
||||
- Checks body params, ex: id=12, {"id":12}
|
||||
- Checks route placeholders, ex: _/user/:id_
|
||||
- Checks query string params, ex: ?id=12
|
||||
|
||||
To utilize request bodies, `req.body`
|
||||
should be an object. This can be done by using
|
||||
the `connect.bodyParser()` middleware.
|
||||
|
||||
# req.is()
|
||||
|
||||
Check if the incoming request contains the "Content-Type"
|
||||
header field, and it contains the give mime `type`.
|
||||
|
||||
## Examples
|
||||
|
||||
// With Content-Type: text/html; charset=utf-8
|
||||
req.is('html');
|
||||
req.is('text/html');
|
||||
req.is('text/*');
|
||||
// => true
|
||||
|
||||
// When Content-Type is application/json
|
||||
req.is('json');
|
||||
req.is('application/json');
|
||||
req.is('application/*');
|
||||
// => true
|
||||
|
||||
req.is('html');
|
||||
// => false
|
||||
|
||||
Now within our route callbacks, we can use to to assert content types
|
||||
such as "image/jpeg", "image/png", etc.
|
||||
|
||||
app.post('/image/upload', function(req, res, next){
|
||||
if (req.is('image/*')) {
|
||||
// do something
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
|
||||
# res
|
||||
|
||||
Response prototype.
|
||||
|
||||
# res.status()
|
||||
|
||||
Set status `code`.
|
||||
|
||||
# res.send()
|
||||
|
||||
Send a response.
|
||||
|
||||
## Examples
|
||||
|
||||
res.send(new Buffer('wahoo'));
|
||||
res.send({ some: 'json' });
|
||||
res.send('<p>some html</p>');
|
||||
res.send(404, 'Sorry, cant find that');
|
||||
res.send(404);
|
||||
|
||||
# res.json()
|
||||
|
||||
Send JSON response.
|
||||
|
||||
## Examples
|
||||
|
||||
res.json(null);
|
||||
res.json({ user: 'tj' });
|
||||
res.json(500, 'oh noes!');
|
||||
res.json(404, 'I dont have that');
|
||||
|
||||
# res.sendfile()
|
||||
|
||||
Transfer the file at the given `path`.
|
||||
|
||||
Automatically sets the _Content-Type_ response header field.
|
||||
The callback `fn(err)` is invoked when the transfer is complete
|
||||
or when an error occurs. Be sure to check `res.sentHeader`
|
||||
if you wish to attempt responding, as the header and some data
|
||||
may have already been transferred.
|
||||
|
||||
## Options
|
||||
|
||||
- `maxAge` defaulting to 0
|
||||
- `root` root directory for relative filenames
|
||||
|
||||
## Examples
|
||||
|
||||
The following example illustrates how `res.sendfile()` may
|
||||
be used as an alternative for the `static()` middleware for
|
||||
dynamic situations. The code backing `res.sendfile()` is actually
|
||||
the same code, so HTTP cache support etc is identical.
|
||||
|
||||
app.get('/user/:uid/photos/:file', function(req, res){
|
||||
var uid = req.params.uid
|
||||
, file = req.params.file;
|
||||
|
||||
req.user.mayViewFilesFrom(uid, function(yes){
|
||||
if (yes) {
|
||||
res.sendfile('/uploads/' + uid + '/' + file);
|
||||
} else {
|
||||
res.send(403, 'Sorry! you cant see that.');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
# res.download()
|
||||
|
||||
Transfer the file at the given `path` as an attachment.
|
||||
|
||||
Optionally providing an alternate attachment `filename`,
|
||||
and optional callback `fn(err)`. The callback is invoked
|
||||
when the data transfer is complete, or when an error has
|
||||
ocurred. Be sure to check `res.headerSent` if you plan to respond.
|
||||
|
||||
# res.format()
|
||||
|
||||
Respond to the Acceptable formats using an `obj`
|
||||
of mime-type callbacks.
|
||||
|
||||
This method uses `req.accepted`, an array of
|
||||
acceptable types ordered by their quality values.
|
||||
When "Accept" is not present the _first_ callback
|
||||
is invoked, otherwise the first match is used. When
|
||||
no match is performed the server responds with
|
||||
406 "Not Acceptable".
|
||||
|
||||
Content-Type is set for you, however if you choose
|
||||
you may alter this within the callback using `res.type()`
|
||||
or `res.set('Content-Type', ...)`.
|
||||
|
||||
res.format({
|
||||
'text/plain': function(){
|
||||
res.send('hey');
|
||||
},
|
||||
|
||||
'text/html': function(){
|
||||
res.send('<p>hey</p>');
|
||||
},
|
||||
|
||||
'appliation/json': function(){
|
||||
res.send({ message: 'hey' });
|
||||
}
|
||||
});
|
||||
|
||||
In addition to canonicalized MIME types you may
|
||||
## also use extnames mapped to these types
|
||||
|
||||
res.format({
|
||||
text: function(){
|
||||
res.send('hey');
|
||||
},
|
||||
|
||||
html: function(){
|
||||
res.send('<p>hey</p>');
|
||||
},
|
||||
|
||||
json: function(){
|
||||
res.send({ message: 'hey' });
|
||||
}
|
||||
});
|
||||
|
||||
# res.attachment()
|
||||
|
||||
Set _Content-Disposition_ header to _attachment_ with optional `filename`.
|
||||
|
||||
# res.set()
|
||||
|
||||
Set header `field` to `val`, or pass
|
||||
an object of of header fields.
|
||||
|
||||
## Examples
|
||||
|
||||
res.set('Accept', 'application/json');
|
||||
res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' });
|
||||
|
||||
# res.get()
|
||||
|
||||
Get value for header `field`.
|
||||
|
||||
# res.clearCookie()
|
||||
|
||||
Clear cookie `name`.
|
||||
|
||||
# res.signedCookie()
|
||||
|
||||
Set a signed cookie with the given `name` and `val`.
|
||||
See `res.cookie()` for details.
|
||||
|
||||
# res.cookie()
|
||||
|
||||
Set cookie `name` to `val`, with the given `options`.
|
||||
|
||||
## Options
|
||||
|
||||
- `maxAge` max-age in milliseconds, converted to `expires`
|
||||
- `path` defaults to "/"
|
||||
|
||||
## Examples
|
||||
|
||||
// "Remember Me" for 15 minutes
|
||||
res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
|
||||
|
||||
// save as above
|
||||
res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true })
|
||||
|
||||
# res.redirect()
|
||||
|
||||
Redirect to the given `url` with optional response `status`
|
||||
defaulting 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 "/".
|
||||
|
||||
## Examples
|
||||
|
||||
res.redirect('/foo/bar');
|
||||
res.redirect('http://example.com');
|
||||
res.redirect(301, 'http://example.com');
|
||||
res.redirect('../login'); // /blog/post/1 -> /blog/login
|
||||
|
||||
## Mounting
|
||||
|
||||
When an application is mounted, and `res.redirect()`
|
||||
is given a path that does _not_ lead with "/". For
|
||||
example suppose a "blog" app is mounted at "/blog",
|
||||
the following redirect would result in "/blog/login":
|
||||
|
||||
res.redirect('login');
|
||||
|
||||
While the leading slash would result in a redirect to "/login":
|
||||
|
||||
res.redirect('/login');
|
||||
|
||||
# res.render()
|
||||
|
||||
Render `view` with the given `options` and optional callback `fn`.
|
||||
When a callback function is given a response will _not_ be made
|
||||
automatically, otherwise a response of _200_ and _text/html_ is given.
|
||||
|
||||
## Options
|
||||
|
||||
- `status` Response status code (`res.statusCode`)
|
||||
- `charset` Set the charset (`res.charset`)
|
||||
|
||||
## Reserved locals
|
||||
|
||||
- `cache` boolean hinting to the engine it should cache
|
||||
- `filename` filename of the view being rendered
|
||||
|
||||
+76
-81
@@ -1,65 +1,63 @@
|
||||
|
||||
// Expose modules in ./support for demo purposes
|
||||
require.paths.unshift(__dirname + '/../../support');
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('../../lib/express'),
|
||||
crypto = require('crypto');
|
||||
var express = require('../../lib/express')
|
||||
, crypto = require('crypto');
|
||||
|
||||
var app = express.createServer();
|
||||
var app = module.exports = express();
|
||||
|
||||
app.set('views', __dirname + '/views');
|
||||
app.set('view engine', 'ejs');
|
||||
|
||||
app.use(express.bodyDecoder());
|
||||
app.use(express.cookieDecoder());
|
||||
app.use(express.bodyParser());
|
||||
app.use(express.cookieParser('shhhh, very secret'));
|
||||
app.use(express.session());
|
||||
|
||||
// Message helper, ideally we would use req.flash()
|
||||
// however this is more light-weight for an example
|
||||
app.set('view engine', 'ejs');
|
||||
app.set('views', __dirname + '/views');
|
||||
|
||||
app.dynamicHelpers({
|
||||
message: function(req){
|
||||
var err = req.session.error,
|
||||
msg = req.session.success;
|
||||
delete req.session.error;
|
||||
delete req.session.success;
|
||||
if (err) return '<p class="msg error">' + err + '</p>';
|
||||
if (msg) return '<p class="msg success">' + msg + '</p>';
|
||||
}
|
||||
});
|
||||
// Session-persisted message middleware
|
||||
|
||||
app.locals.use(function(req,res){
|
||||
var err = req.session.error
|
||||
, msg = req.session.success;
|
||||
delete req.session.error;
|
||||
delete req.session.success;
|
||||
res.locals.message = '';
|
||||
if (err) res.locals.message = '<p class="msg error">' + err + '</p>';
|
||||
if (msg) res.locals.message = '<p class="msg success">' + msg + '</p>';
|
||||
})
|
||||
|
||||
// Generate a salt for the user to prevent rainbow table attacks
|
||||
|
||||
// for better security take a look at the bcrypt c++ addon:
|
||||
// https://github.com/ncb000gt/node.bcrypt.js
|
||||
var users = {
|
||||
tj: {
|
||||
name: 'tj',
|
||||
salt: 'randomly-generated-salt',
|
||||
pass: md5('foobar' + 'randomly-generated-salt')
|
||||
}
|
||||
tj: {
|
||||
name: 'tj'
|
||||
, salt: 'randomly-generated-salt'
|
||||
, pass: hash('foobar', 'randomly-generated-salt')
|
||||
}
|
||||
};
|
||||
|
||||
// Used to generate a hash of the plain-text password + salt
|
||||
|
||||
function md5(str) {
|
||||
return crypto.createHash('md5').update(str).digest('hex');
|
||||
function hash(msg, key) {
|
||||
return crypto
|
||||
.createHmac('sha256', key)
|
||||
.update(msg)
|
||||
.digest('hex');
|
||||
}
|
||||
|
||||
// Authenticate using our plain-object database of doom!
|
||||
|
||||
function authenticate(name, pass, fn) {
|
||||
var user = users[name];
|
||||
// query the db for the given username
|
||||
if (!user) return fn(new Error('cannot find user'));
|
||||
// apply the same algorithm to the POSTed password, applying
|
||||
// the md5 against the pass / salt, if there is a match we
|
||||
// found the user
|
||||
if (user.pass == md5(pass + user.salt)) return fn(null, user);
|
||||
// Otherwise password is invalid
|
||||
fn(new Error('invalid password'));
|
||||
if (!module.parent) console.log('authenticating %s:%s', name, pass);
|
||||
var user = users[name];
|
||||
// query the db for the given username
|
||||
if (!user) return fn(new Error('cannot find user'));
|
||||
// apply the same algorithm to the POSTed password, applying
|
||||
// the hash against the pass / salt, if there is a match we
|
||||
// found the user
|
||||
if (user.pass == hash(pass, user.salt)) return fn(null, user);
|
||||
// Otherwise password is invalid
|
||||
fn(new Error('invalid password'));
|
||||
}
|
||||
|
||||
function restrict(req, res, next) {
|
||||
@@ -71,56 +69,53 @@ function restrict(req, res, next) {
|
||||
}
|
||||
}
|
||||
|
||||
function accessLogger(req, res, next) {
|
||||
console.log('/restricted accessed by %s', req.session.user.name);
|
||||
next();
|
||||
}
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.redirect('/login');
|
||||
res.redirect('login');
|
||||
});
|
||||
|
||||
app.get('/restricted', restrict, accessLogger, function(req, res){
|
||||
res.send('Wahoo! restricted area');
|
||||
app.get('/restricted', restrict, function(req, res){
|
||||
res.send('Wahoo! restricted area');
|
||||
});
|
||||
|
||||
app.get('/logout', function(req, res){
|
||||
// destroy the user's session to log them out
|
||||
// will be re-created next request
|
||||
req.session.destroy(function(){
|
||||
res.redirect('home');
|
||||
});
|
||||
// destroy the user's session to log them out
|
||||
// will be re-created next request
|
||||
req.session.destroy(function(){
|
||||
res.redirect('/');
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/login', function(req, res){
|
||||
if (req.session.user) {
|
||||
req.session.success = 'Authenticated as ' + req.session.user.name
|
||||
+ ' click to <a href="/logout">logout</a>. '
|
||||
+ ' You may now access <a href="/restricted">/restricted</a>.';
|
||||
}
|
||||
res.render('login');
|
||||
if (req.session.user) {
|
||||
req.session.success = 'Authenticated as ' + req.session.user.name
|
||||
+ ' click to <a href="/logout">logout</a>. '
|
||||
+ ' You may now access <a href="/restricted">/restricted</a>.';
|
||||
}
|
||||
res.render('login');
|
||||
});
|
||||
|
||||
app.post('/login', function(req, res){
|
||||
authenticate(req.body.username, req.body.password, function(err, user){
|
||||
if (user) {
|
||||
// Regenerate session when signing in
|
||||
// to prevent fixation
|
||||
req.session.regenerate(function(){
|
||||
// Store the user's primary key
|
||||
// in the session store to be retrieved,
|
||||
// or in this case the entire user object
|
||||
req.session.user = user;
|
||||
res.redirect('back');
|
||||
});
|
||||
} else {
|
||||
req.session.error = 'Authentication failed, please check your '
|
||||
+ ' username and password.'
|
||||
+ ' (use "tj" and "foobar")';
|
||||
res.redirect('back');
|
||||
}
|
||||
});
|
||||
authenticate(req.body.username, req.body.password, function(err, user){
|
||||
if (user) {
|
||||
// Regenerate session when signing in
|
||||
// to prevent fixation
|
||||
req.session.regenerate(function(){
|
||||
// Store the user's primary key
|
||||
// in the session store to be retrieved,
|
||||
// or in this case the entire user object
|
||||
req.session.user = user;
|
||||
res.redirect('back');
|
||||
});
|
||||
} else {
|
||||
req.session.error = 'Authentication failed, please check your '
|
||||
+ ' username and password.'
|
||||
+ ' (use "tj" and "foobar")';
|
||||
res.redirect('login');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
console.log('Express started on port 3000');
|
||||
if (!module.parent) {
|
||||
app.listen(3000);
|
||||
console.log('Express started on port 3000');
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<h1>Login</h1>
|
||||
<%- message %>
|
||||
Try accessing <a href="/restricted">/restricted</a>.
|
||||
Try accessing <a href="/restricted">/restricted</a>, then authenticate with "tj" and "foobar".
|
||||
<form method="post" action="/login">
|
||||
<p>
|
||||
<label>Username:</label>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
var express = require('../..')
|
||||
, app = express();
|
||||
|
||||
app.set('views', __dirname);
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
var pets = [];
|
||||
|
||||
var n = 1000;
|
||||
while (n--) {
|
||||
pets.push({ name: 'Tobi', age: 2, species: 'ferret' });
|
||||
pets.push({ name: 'Loki', age: 1, species: 'ferret' });
|
||||
pets.push({ name: 'Jane', age: 6, species: 'ferret' });
|
||||
}
|
||||
|
||||
app.use(express.logger('dev'));
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('pets', { pets: pets });
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
console.log('Express listening on port 3000');
|
||||
@@ -0,0 +1,12 @@
|
||||
style
|
||||
body {
|
||||
padding: 50px;
|
||||
font: 16px "Helvetica Neue", Helvetica;
|
||||
}
|
||||
|
||||
table
|
||||
for pet in pets
|
||||
tr
|
||||
td= pet.name
|
||||
td= pet.age
|
||||
td= pet.species
|
||||
@@ -1,25 +0,0 @@
|
||||
|
||||
// Expose modules in ./support for demo purposes
|
||||
require.paths.unshift(__dirname + '/../../support');
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('./../../lib/express');
|
||||
|
||||
// Our app IS the exports, this prevents require('./app').app,
|
||||
// instead it is require('./app');
|
||||
var app = module.exports = express.createServer();
|
||||
|
||||
// Illustrates that an app can be broken into
|
||||
// several files, but yet extend the same app
|
||||
require('./main');
|
||||
require('./contact');
|
||||
|
||||
// Illustrates that one app (Server instance) can
|
||||
// be "mounted" to another at the given route.
|
||||
app.use('/blog', require('./blog'));
|
||||
|
||||
app.listen(3000);
|
||||
console.log('Express started on port 3000');
|
||||
@@ -1,45 +0,0 @@
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('./../../../lib/express'),
|
||||
fs = require('fs');
|
||||
|
||||
// Export our app as the module
|
||||
var app = module.exports = express.createServer();
|
||||
|
||||
// Set views directory
|
||||
app.set('views', __dirname + '/views');
|
||||
|
||||
// Load our posts
|
||||
var posts = JSON.parse(fs.readFileSync(__dirname + '/posts.json', 'utf8'));
|
||||
|
||||
// Set our default view engine to "ejs"
|
||||
app.set('view engine', 'ejs');
|
||||
|
||||
app.dynamicHelpers({
|
||||
basepath: function(){
|
||||
// "this" is the app, we can
|
||||
// dynamically provide the "home"
|
||||
// setting to all views
|
||||
return this.set('home');
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('index', {
|
||||
locals: {
|
||||
posts: posts
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/post/:id', function(req, res){
|
||||
var id = req.params.id;
|
||||
res.render('post', {
|
||||
locals: {
|
||||
post: posts[id]
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,4 +0,0 @@
|
||||
[
|
||||
{ "id": 0, "title": "Post one", "body": "Just some lame post" },
|
||||
{ "id": 1, "title": "Post two", "body": "Just another lame post" }
|
||||
]
|
||||
@@ -1,2 +0,0 @@
|
||||
<h2>Posts</h2>
|
||||
<%- partial('post', { collection: posts, as: global }) %>
|
||||
@@ -1,9 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Blog Example</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Best Blog Ever</h1>
|
||||
<%- body %>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,2 +0,0 @@
|
||||
<h3><a href="<%= basepath %>/post/<%= id %>"><%= title %></a></h3>
|
||||
<p><%= body %></p>
|
||||
@@ -1 +0,0 @@
|
||||
<%- partial('post', { object: post, as: global }) %>
|
||||
@@ -1,9 +0,0 @@
|
||||
|
||||
// in ./app.js we did "module.exports", allowing
|
||||
// us to grab the app from the parent module (the one
|
||||
// which required it)
|
||||
var app = module.parent.exports;
|
||||
|
||||
app.get('/contact', function(req, res){
|
||||
res.send('<p>Wahoo contact page</p>');
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
// in ./app.js we did "module.exports", allowing
|
||||
// us to grab the app from the parent module (the one
|
||||
// which required it)
|
||||
var app = module.parent.exports;
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.send('<p>Visit <a href="/blog">/blog</a>'
|
||||
+ ' or <a href="/contact">/contact</a></p>');
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
var express = require('../../')
|
||||
, app = module.exports = express();
|
||||
|
||||
var users = [];
|
||||
|
||||
users.push({ name: 'Tobi' });
|
||||
users.push({ name: 'Loki' });
|
||||
users.push({ name: 'Jane' });
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.format({
|
||||
html: function(){
|
||||
res.send('<ul>' + users.map(function(user){
|
||||
return '<li>' + user.name + '</li>';
|
||||
}).join('') + '</ul>');
|
||||
},
|
||||
|
||||
text: function(){
|
||||
res.send(users.map(function(user){
|
||||
return ' - ' + user.name + '\n';
|
||||
}).join(''));
|
||||
},
|
||||
|
||||
json: function(){
|
||||
res.json(users);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
if (!module.parent) {
|
||||
app.listen(3000);
|
||||
console.log('listening on port 3000');
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('../../');
|
||||
|
||||
var app = module.exports = express();
|
||||
|
||||
// ignore GET /favicon.ico
|
||||
app.use(express.favicon());
|
||||
|
||||
// pass a secret to cookieParser() for signed cookies
|
||||
app.use(express.cookieParser('manny is cool'));
|
||||
|
||||
// add req.session cookie support
|
||||
app.use(express.cookieSession());
|
||||
|
||||
// do something with the session
|
||||
app.use(count);
|
||||
|
||||
// custom middleware
|
||||
function count(req, res) {
|
||||
req.session.count = req.session.count || 0;
|
||||
var n = req.session.count++;
|
||||
res.send('viewed ' + n + ' times\n');
|
||||
}
|
||||
|
||||
if (!module.parent) {
|
||||
app.listen(3000);
|
||||
console.log('Express server listening on port 3000');
|
||||
}
|
||||
+35
-27
@@ -3,44 +3,52 @@
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('./../../lib/express');
|
||||
var express = require('../../')
|
||||
, app = module.exports = express();
|
||||
|
||||
var app = express.createServer(
|
||||
// Place default Connect favicon above logger so it is not in
|
||||
// the logging output
|
||||
express.favicon(),
|
||||
|
||||
// Custom logger format
|
||||
express.logger({ format: '\x1b[1m:method\x1b[0m \x1b[33m:url\x1b[0m :response-time' }),
|
||||
// add favicon() before logger() so
|
||||
// GET /favicon.ico requests are not
|
||||
// logged, because this middleware
|
||||
// reponds to /favicon.ico and does not
|
||||
// call next()
|
||||
app.use(express.favicon());
|
||||
|
||||
// Provides req.cookies
|
||||
express.cookieDecoder(),
|
||||
// custom log format
|
||||
if ('test' != process.env.NODE_ENV)
|
||||
app.use(express.logger(':method :url'));
|
||||
|
||||
// Parses x-www-form-urlencoded request bodies (and json)
|
||||
express.bodyDecoder()
|
||||
);
|
||||
// parses request cookies, populating
|
||||
// req.cookies and req.signedCookies
|
||||
// when the secret is passed, used
|
||||
// for signing the cookies.
|
||||
app.use(express.cookieParser('my secret here'));
|
||||
|
||||
// parses json, x-www-form-urlencoded, and multipart/form-data
|
||||
app.use(express.bodyParser());
|
||||
|
||||
app.get('/', function(req, res){
|
||||
if (req.cookies.remember) {
|
||||
res.send('Remembered :). Click to <a href="/forget">forget</a>!.');
|
||||
} else {
|
||||
res.send('<form method="post"><p>Check to <label>'
|
||||
+ '<input type="checkbox" name="remember"/> remember me</label> '
|
||||
+ '<input type="submit" value="Submit"/>.</p></form>');
|
||||
}
|
||||
if (req.cookies.remember) {
|
||||
res.send('Remembered :). Click to <a href="/forget">forget</a>!.');
|
||||
} else {
|
||||
res.send('<form method="post"><p>Check to <label>'
|
||||
+ '<input type="checkbox" name="remember"/> remember me</label> '
|
||||
+ '<input type="submit" value="Submit"/>.</p></form>');
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/forget', function(req, res){
|
||||
res.clearCookie('remember');
|
||||
res.redirect('back');
|
||||
res.clearCookie('remember');
|
||||
res.redirect('back');
|
||||
});
|
||||
|
||||
app.post('/', function(req, res){
|
||||
if (req.body.remember) {
|
||||
res.cookie('remember', '1', { path: '/', expires: new Date(Date.now() + 900000), httpOnly: true });
|
||||
}
|
||||
res.redirect('back');
|
||||
var minute = 60000;
|
||||
if (req.body.remember) res.cookie('remember', 1, { maxAge: minute });
|
||||
res.redirect('back');
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
console.log('Express started on port 3000');
|
||||
if (!module.parent){
|
||||
app.listen(3000);
|
||||
console.log('Express started on port 3000');
|
||||
}
|
||||
+31
-19
@@ -3,30 +3,42 @@
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('./../../lib/express');
|
||||
|
||||
var app = express.createServer();
|
||||
var express = require('../../')
|
||||
, app = module.exports = express();
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.send('<ul>'
|
||||
+ '<li>Download <a href="/files/amazing.txt">amazing.txt</a>.</li>'
|
||||
+ '<li>Download <a href="/files/missing.txt">missing.txt</a>.</li>'
|
||||
+ '</ul>');
|
||||
res.send('<ul>'
|
||||
+ '<li>Download <a href="/files/amazing.txt">amazing.txt</a>.</li>'
|
||||
+ '<li>Download <a href="/files/missing.txt">missing.txt</a>.</li>'
|
||||
+ '</ul>');
|
||||
});
|
||||
|
||||
app.get('/files/*', function(req, res){
|
||||
var file = req.params[0];
|
||||
res.download(__dirname + '/files/' + file);
|
||||
// /files/* is accessed via req.params[0]
|
||||
// but here we name it :file
|
||||
app.get('/files/:file(*)', function(req, res, next){
|
||||
var file = req.params.file
|
||||
, path = __dirname + '/files/' + file;
|
||||
|
||||
res.download(path);
|
||||
});
|
||||
|
||||
app.error(function(err, req, res, next){
|
||||
if (process.ENOENT == err.errno) {
|
||||
res.send('Cant find that file, sorry!');
|
||||
} else {
|
||||
// Not a 404
|
||||
next(err);
|
||||
}
|
||||
// error handling middleware. Because it's
|
||||
// below our routes, you will be able to
|
||||
// "intercept" errors, otherwise Connect
|
||||
// will respond with 500 "Internal Server Error".
|
||||
app.use(function(err, req, res, next){
|
||||
// special-case 404s,
|
||||
// remember you could
|
||||
// render a 404 template here
|
||||
if (404 == err.status) {
|
||||
res.statusCode = 404;
|
||||
res.send('Cant find that file, sorry!');
|
||||
} else {
|
||||
next(err);
|
||||
}
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
console.log('Express started on port 3000');
|
||||
if (!module.parent) {
|
||||
app.listen(3000);
|
||||
console.log('Express started on port 3000');
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
wow supes cool are you glad you downloaded this?
|
||||
what an amazing download
|
||||
@@ -1,32 +0,0 @@
|
||||
|
||||
// Expose modules in ./support for demo purposes
|
||||
require.paths.unshift(__dirname + '/../../support');
|
||||
|
||||
/**
|
||||
* 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);
|
||||
@@ -0,0 +1,46 @@
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('../../');
|
||||
|
||||
var app = module.exports = express();
|
||||
|
||||
// Register ejs as .html. If we did
|
||||
// not call this, we would need to
|
||||
// name our views foo.ejs instead
|
||||
// of foo.html. The __express method
|
||||
// is simply a function that engines
|
||||
// use to hook into the Express view
|
||||
// system by default, so if we want
|
||||
// to change "foo.ejs" to "foo.html"
|
||||
// we simply pass _any_ function, in this
|
||||
// case `ejs.__express`.
|
||||
|
||||
app.engine('.html', require('ejs').__express);
|
||||
|
||||
// Optional since express defaults to CWD/views
|
||||
|
||||
app.set('views', __dirname + '/views');
|
||||
|
||||
// Without this you would need to
|
||||
// supply the extension to res.render()
|
||||
// ex: res.render('users.html').
|
||||
app.set('view engine', 'html');
|
||||
|
||||
// Dummy users
|
||||
var users = [
|
||||
{ name: 'tobi', email: 'tobi@learnboost.com' }
|
||||
, { name: 'loki', email: 'loki@learnboost.com' }
|
||||
, { name: 'jane', email: 'jane@learnboost.com' }
|
||||
];
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('users', { users: users });
|
||||
});
|
||||
|
||||
if (!module.parent) {
|
||||
app.listen(3000);
|
||||
console.log('Express app started on port 3000');
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
<h1>Users</h1>
|
||||
<%- body %>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1 +0,0 @@
|
||||
<li><%= user.name %> <<%= user.email %>></li>
|
||||
@@ -1,3 +0,0 @@
|
||||
<ul id="users">
|
||||
<%- partial('user', users) %>
|
||||
</ul>
|
||||
@@ -0,0 +1,6 @@
|
||||
<h1>Users</h1>
|
||||
<ul id="users">
|
||||
<% users.forEach(function(user){ %>
|
||||
<li><%= user.name %> <%= user.email %></li>
|
||||
<% }) %>
|
||||
</ul>
|
||||
@@ -0,0 +1,95 @@
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('../../')
|
||||
, app = module.exports = express()
|
||||
, silent = 'test' == process.env.NODE_ENV;
|
||||
|
||||
app.set('views', __dirname + '/views');
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
app.use(express.favicon());
|
||||
|
||||
silent || app.use(express.logger('dev'));
|
||||
|
||||
// "app.router" positions our routes
|
||||
// above the middleware defined below,
|
||||
// this means that Express will attempt
|
||||
// to match & call routes _before_ continuing
|
||||
// on, at which point we assume it's a 404 because
|
||||
// no route has handled the request.
|
||||
|
||||
app.use(app.router);
|
||||
|
||||
// Since this is the last non-error-handling
|
||||
// middleware use()d, we assume 404, as nothing else
|
||||
// responded.
|
||||
|
||||
// $ curl http://localhost:3000/notfound
|
||||
// $ curl http://localhost:3000/notfound -H "Accept: application/json"
|
||||
// $ curl http://localhost:3000/notfound -H "Accept: text/plain"
|
||||
|
||||
app.use(function(req, res, next){
|
||||
// respond with html page
|
||||
if (req.accepts('html')) {
|
||||
res.status(404);
|
||||
res.render('404', { url: req.url });
|
||||
return;
|
||||
}
|
||||
|
||||
// respond with json
|
||||
if (req.accepts('json')) {
|
||||
res.send({ error: 'Not found' });
|
||||
return;
|
||||
}
|
||||
|
||||
// default to plain-text. send()
|
||||
res.type('txt').send('Not found');
|
||||
});
|
||||
|
||||
// error-handling middleware, take the same form
|
||||
// as regular middleware, however they require an
|
||||
// arity of 4, aka the signature (err, req, res, next).
|
||||
// when connect has an error, it will invoke ONLY error-handling
|
||||
// middleware.
|
||||
|
||||
// If we were to next() here any remaining non-error-handling
|
||||
// middleware would then be executed, or if we next(err) to
|
||||
// continue passing the error, only error-handling middleware
|
||||
// would remain being executed, however here
|
||||
// we simply respond with an error page.
|
||||
|
||||
app.use(function(err, req, res, next){
|
||||
// we may use properties of the error object
|
||||
// here and next(err) appropriately, or if
|
||||
// we possibly recovered from the error, simply next().
|
||||
res.status(err.status || 500);
|
||||
res.render('500', { error: err });
|
||||
});
|
||||
|
||||
// Routes
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('index.jade');
|
||||
});
|
||||
|
||||
app.get('/404', function(req, res, next){
|
||||
next();
|
||||
});
|
||||
|
||||
app.get('/403', function(req, res, next){
|
||||
var err = new Error('not allowed!');
|
||||
err.status = 403;
|
||||
next(err);
|
||||
});
|
||||
|
||||
app.get('/500', function(req, res, next){
|
||||
next(new Error('keyboard cat!'));
|
||||
});
|
||||
|
||||
if (!module.parent) {
|
||||
app.listen(3000);
|
||||
silent || console.log('Express started on port 3000');
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
extends error
|
||||
|
||||
block content
|
||||
h2 Cannot find #{url}
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
// note that we extend a different
|
||||
// layout with jade for 4xx & 5xx
|
||||
// responses
|
||||
|
||||
extends error
|
||||
|
||||
block content
|
||||
h1 Error: #{error.message}
|
||||
pre= error.stack
|
||||
@@ -0,0 +1,6 @@
|
||||
html
|
||||
head
|
||||
title Error
|
||||
body
|
||||
h1 An error occurred!
|
||||
block content
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
extends layout
|
||||
|
||||
block content
|
||||
h2 Pages Example
|
||||
ul
|
||||
li
|
||||
| visit
|
||||
a(href="/500") 500
|
||||
li
|
||||
| visit
|
||||
a(href="/404") 404
|
||||
li
|
||||
| visit
|
||||
a(href='/403') 403
|
||||
@@ -3,4 +3,4 @@ html
|
||||
title Custom Pages Example
|
||||
body
|
||||
h1 My Site
|
||||
!= body
|
||||
block content
|
||||
@@ -1,25 +0,0 @@
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('./../../lib/express');
|
||||
|
||||
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, 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('/', express.errorHandler({ dumpExceptions: true, showStack: true }));
|
||||
|
||||
app.listen(3000);
|
||||
@@ -0,0 +1,48 @@
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('../../')
|
||||
, app = module.exports = express()
|
||||
, test = app.get('env') == 'test';
|
||||
|
||||
if (!test) app.use(express.logger('dev'));
|
||||
app.use(app.router);
|
||||
|
||||
// the error handler is strategically
|
||||
// placed *below* the app.router; if it
|
||||
// were above it would not receive errors
|
||||
// from app.get() etc
|
||||
app.use(error);
|
||||
|
||||
// error handling middleware have an arity of 4
|
||||
// instead of the typical (req, res, next),
|
||||
// otherwise they behave exactly like regular
|
||||
// middleware, you may have several of them,
|
||||
// in different orders etc.
|
||||
|
||||
function error(err, req, res, next) {
|
||||
// log it
|
||||
if (!test) console.error(err.stack);
|
||||
|
||||
// respond with 500 "Internal Server Error".
|
||||
res.send(500);
|
||||
}
|
||||
|
||||
app.get('/', function(req, res){
|
||||
// Caught and passed down to the errorHandler middleware
|
||||
throw new Error('something broke!');
|
||||
});
|
||||
|
||||
app.get('/next', function(req, res, next){
|
||||
// We can also pass exceptions to next()
|
||||
process.nextTick(function(){
|
||||
next(new Error('oh no!'));
|
||||
});
|
||||
});
|
||||
|
||||
if (!module.parent) {
|
||||
app.listen(3000);
|
||||
console.log('Express started on port 3000');
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
|
||||
var express = require('../..')
|
||||
, app = express();
|
||||
|
||||
app.set('view engine', 'jade');
|
||||
app.set('views', __dirname + '/views');
|
||||
|
||||
function User(name) {
|
||||
this.private = 'heyyyy';
|
||||
this.secret = 'something';
|
||||
this.name = name;
|
||||
this.id = 123;
|
||||
}
|
||||
|
||||
// You'll probably want to do
|
||||
// something like this so you
|
||||
// dont expose "secret" data.
|
||||
|
||||
User.prototype.toJSON = function(){
|
||||
return {
|
||||
id: this.id,
|
||||
name: this.name
|
||||
}
|
||||
};
|
||||
|
||||
app.use(express.logger('dev'));
|
||||
|
||||
// earlier on expose an object
|
||||
// that we can tack properties on.
|
||||
// all res.locals props are exposed
|
||||
// to the templates, so "expose" will
|
||||
// be present.
|
||||
|
||||
app.use(function(req, res, next){
|
||||
res.locals.expose = {};
|
||||
// you could alias this as req or res.expose
|
||||
// to make it shorter and less annoying
|
||||
next();
|
||||
});
|
||||
|
||||
// pretend we loaded a user
|
||||
|
||||
app.use(function(req, res, next){
|
||||
req.user = new User('Tobi');
|
||||
next();
|
||||
});
|
||||
|
||||
// if you wanted to _always_ expose
|
||||
// the user you might do something like this:
|
||||
/*
|
||||
app.locals.use(function(req, res){
|
||||
if (req.user) res.locals.expose.user = req.user;
|
||||
})
|
||||
*/
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.redirect('/user');
|
||||
});
|
||||
|
||||
app.get('/user', function(req, res){
|
||||
// we only want to expose the user
|
||||
// to the client for this route:
|
||||
res.locals.expose.user = req.user;
|
||||
res.render('page');
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
console.log('app listening on port 3000');
|
||||
@@ -0,0 +1,14 @@
|
||||
html
|
||||
head
|
||||
title Express
|
||||
script
|
||||
// call this whatever you like,
|
||||
// or dump them into individual
|
||||
// props like "var user ="
|
||||
var data = !{JSON.stringify(expose)}
|
||||
body
|
||||
h1 Expose client data
|
||||
p The following was exposed to the client:
|
||||
pre
|
||||
script
|
||||
document.write(JSON.stringify(data, null, 2))
|
||||
@@ -1,78 +0,0 @@
|
||||
|
||||
// Expose modules in ./support for demo purposes
|
||||
require.paths.unshift(__dirname + '/../../support');
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('../../lib/express');
|
||||
|
||||
// App with session support
|
||||
|
||||
var app = express.createServer(
|
||||
express.cookieDecoder(),
|
||||
express.session()
|
||||
);
|
||||
|
||||
// View settings
|
||||
|
||||
app.set('views', __dirname + '/views');
|
||||
app.set('view engine', 'ejs');
|
||||
|
||||
// Dynamic helpers are functions which are executed
|
||||
// on each view render, unless dynamicHelpers is false.
|
||||
|
||||
// So for example we do not need to call messages() in our
|
||||
// template, "messages" will be populated with the return
|
||||
// value of this function.
|
||||
|
||||
app.dynamicHelpers({
|
||||
messages: function(req, res){
|
||||
// In the case of flash messages
|
||||
// we return a function, allowing
|
||||
// flash messages to only be flushed
|
||||
// when called, otherwise every request
|
||||
// will flush flash messages regardless.
|
||||
return function(){
|
||||
// Grab the flash messages
|
||||
var messages = req.flash();
|
||||
// We will render the "messages.ejs" partial
|
||||
return res.partial('messages', {
|
||||
// Our target object is our messages
|
||||
object: messages,
|
||||
// We want it to be named "types" in the partial
|
||||
// since they are keyed like this:
|
||||
// { info: ['foo'], error: ['bar']}
|
||||
as: 'types',
|
||||
// Pass a local named "hasMessages" so we can easily
|
||||
// check if we have any messages at all
|
||||
locals: { hasMessages: Object.keys(messages).length },
|
||||
// We dont want dynamicHelpers in this partial, as
|
||||
// it would cause infinite recursion
|
||||
dynamicHelpers: false
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
app.dynamicHelpers({
|
||||
// Another dynamic helper example. Since dynamic
|
||||
// helpers resolve at view rendering time, we can
|
||||
// "inject" the "page" local variable per request
|
||||
// providing us with the request url.
|
||||
page: function(req, res){
|
||||
return req.url;
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/', function(req, res){
|
||||
// Not very realistic notifications but illustrates usage
|
||||
req.flash('info', 'email queued');
|
||||
req.flash('info', 'email sent');
|
||||
req.flash('error', 'delivery failed');
|
||||
res.render('index');
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
console.log('Express app started on port 3000');
|
||||
@@ -1,3 +0,0 @@
|
||||
<h1>Flash Message Example</h1>
|
||||
<p>on page <%- page %></p>
|
||||
<%- messages() %>
|
||||
@@ -1,5 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
<%- body %>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,12 +0,0 @@
|
||||
<% if (hasMessages) { %>
|
||||
<div id="messages">
|
||||
<% for (var type in types) { %>
|
||||
<h2><%= type %> messages</h2>
|
||||
<ul id="<%= type %>">
|
||||
<% types[type].forEach(function(msg){ %>
|
||||
<li><%= msg %></li>
|
||||
<% }) %>
|
||||
</ul>
|
||||
<% } %>
|
||||
</div>
|
||||
<% } %>
|
||||
@@ -1,79 +0,0 @@
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('./../../lib/express'),
|
||||
sys = require('sys');
|
||||
|
||||
var app = express.createServer();
|
||||
|
||||
// Here we use the bodyDecoder middleware
|
||||
// to parse urlencoded request bodies
|
||||
// which populates req.body
|
||||
app.use(express.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
|
||||
app.use(express.methodOverride());
|
||||
|
||||
// Required by session
|
||||
app.use(express.cookieDecoder());
|
||||
|
||||
// Required by req.flash() for persistent
|
||||
// notifications
|
||||
app.use(express.session());
|
||||
|
||||
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';
|
||||
|
||||
// Buffer all flash messages.
|
||||
// Typically this would all be done in a template
|
||||
// however for illustration purposes we iterate
|
||||
// here.
|
||||
|
||||
// The messages in req.flash() persist until called,
|
||||
// at which time they are flushed from the session
|
||||
var msgs = '<ul>',
|
||||
flash = req.flash();
|
||||
Object.keys(flash).forEach(function(type){
|
||||
flash[type].forEach(function(msg){
|
||||
msgs += '<li class="' + type + '">' + msg + '</li>';
|
||||
});
|
||||
});
|
||||
msgs += '</ul>';
|
||||
|
||||
// If we have a name, we are updating,
|
||||
// so add the hidden _method input
|
||||
res.send(msgs
|
||||
+ '<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){
|
||||
if (req.body.name) {
|
||||
// Typically here we would create a resource
|
||||
req.flash('info', 'Saved ' + req.body.name);
|
||||
res.redirect('/?name=' + req.body.name);
|
||||
} else {
|
||||
req.flash('error', 'Error: name required');
|
||||
res.redirect('/');
|
||||
}
|
||||
});
|
||||
|
||||
app.put('/', function(req, res){
|
||||
// Typically here we would update a resource
|
||||
req.flash('info', 'Updated ' + req.body.name);
|
||||
res.redirect('/?name=' + req.body.name);
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
console.log('Express app started on port 3000');
|
||||
@@ -1,63 +0,0 @@
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('../../lib/express');
|
||||
|
||||
var app = express.createServer();
|
||||
|
||||
// Fake items
|
||||
|
||||
var items = [
|
||||
{ name: 'foo' },
|
||||
{ name: 'bar' },
|
||||
{ name: 'baz' }
|
||||
];
|
||||
|
||||
// Routes
|
||||
|
||||
app.get('/', function(req, res, next){
|
||||
res.send('Visit /item/2');
|
||||
});
|
||||
|
||||
app.get('/item/:id.:format?', function(req, res, next){
|
||||
var id = req.params.id,
|
||||
format = req.params.format,
|
||||
item = items[id];
|
||||
// Ensure item exists
|
||||
if (item) {
|
||||
// Serve the format
|
||||
switch (format) {
|
||||
case 'json':
|
||||
// Detects json
|
||||
res.send(item);
|
||||
break;
|
||||
case 'xml':
|
||||
// Set contentType as xml then sends
|
||||
// the string
|
||||
var xml = ''
|
||||
+ '<items>'
|
||||
+ '<item>' + item.name + '</item>'
|
||||
+ '</items>';
|
||||
res.contentType('.xml');
|
||||
res.send(xml);
|
||||
break;
|
||||
case 'html':
|
||||
default:
|
||||
// By default send some hmtl
|
||||
res.send('<h1>' + item.name + '</h1>');
|
||||
}
|
||||
} else {
|
||||
// We could simply pass route control and potentially 404
|
||||
// by calling next(), or pass an exception like below.
|
||||
next(new Error('Item ' + id + ' does not exist'));
|
||||
}
|
||||
});
|
||||
|
||||
// Middleware
|
||||
|
||||
app.use(express.errorHandler({ showStack: true }));
|
||||
|
||||
app.listen(3000);
|
||||
console.log('Express app started on port 3000');
|
||||
@@ -1,119 +0,0 @@
|
||||
|
||||
// Expose modules in ./support for demo purposes
|
||||
require.paths.unshift(__dirname + '/../../support');
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('./../../lib/express'),
|
||||
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/*', function(req, res, next){
|
||||
var names = req.params[0].split('/'),
|
||||
users = [];
|
||||
(function fetchData(name){
|
||||
// We have a user name
|
||||
if (name) {
|
||||
console.log('... fetching \x1b[33m%s\x1b[0m', name);
|
||||
request('/repos/show/' + name, function(err, user){
|
||||
if (err) {
|
||||
next(err)
|
||||
} else {
|
||||
user.totalWatchers = totalWatchers(user.repositories);
|
||||
user.repos = sort(user.repositories);
|
||||
user.name = name;
|
||||
users.push(user);
|
||||
fetchData(names.shift());
|
||||
}
|
||||
});
|
||||
// No more users
|
||||
} else {
|
||||
console.log('... done');
|
||||
res.render('index.jade', {
|
||||
locals: {
|
||||
users: users
|
||||
}
|
||||
});
|
||||
}
|
||||
})(names.shift());
|
||||
});
|
||||
|
||||
// Serve statics from ./public
|
||||
app.use(express.staticProvider(__dirname + '/public'));
|
||||
|
||||
// Listen on port 3000
|
||||
app.listen(3000);
|
||||
console.log('Express app started on port 3000');
|
||||
@@ -1,19 +0,0 @@
|
||||
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;
|
||||
}
|
||||
.user {
|
||||
margin: 0 10px;
|
||||
float: left;
|
||||
width: 30%;
|
||||
}
|
||||
table td:nth-child(2) {
|
||||
padding: 0 5px;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
- each user in users
|
||||
.user
|
||||
h2= user.name
|
||||
p.summary
|
||||
| <a href="http://github.com/#{user.name}">#{user.name}</a> has
|
||||
| <strong>#{user.repos.length}</strong> repositories
|
||||
| with a total of <strong>#{user.totalWatchers}</strong> watchers.
|
||||
table#repos!= partial('repo', user.repos)
|
||||
@@ -1,7 +0,0 @@
|
||||
!!!
|
||||
html
|
||||
head
|
||||
title Github Example
|
||||
link(rel="stylesheet", href="/style.css")
|
||||
body
|
||||
#container!= body
|
||||
@@ -1,5 +0,0 @@
|
||||
tr.repo
|
||||
td.name
|
||||
a(href: repo.homepage || repo.url)= repo.name
|
||||
td.watchers
|
||||
= repo.watchers
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
var express = require('../../');
|
||||
|
||||
var app = express();
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.send('Hello World');
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
console.log('Express started on port 3000');
|
||||
@@ -1,14 +0,0 @@
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('./../../lib/express');
|
||||
|
||||
var app = express.createServer();
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.send('Hello World');
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
@@ -1,47 +0,0 @@
|
||||
|
||||
// Expose modules in ./support for demo purposes
|
||||
require.paths.unshift(__dirname + '/../../support');
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('./../../lib/express');
|
||||
|
||||
// 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(
|
||||
express.compiler({ src: pub, enable: ['sass'] }),
|
||||
express.staticProvider(pub)
|
||||
);
|
||||
|
||||
// Optional since express defaults to CWD/views
|
||||
|
||||
app.set('views', __dirname + '/views');
|
||||
|
||||
// Set our default template engine to "jade"
|
||||
// which prevents the need for extensions (although you can still mix and match)
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
// 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', {
|
||||
locals: {
|
||||
users: users
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
console.log('Express app started on port 3000');
|
||||
@@ -0,0 +1,46 @@
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('../../lib/express');
|
||||
|
||||
// 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();
|
||||
app.use(app.router);
|
||||
app.use(express.static(pub));
|
||||
app.use(express.errorHandler());
|
||||
|
||||
// Optional since express defaults to CWD/views
|
||||
|
||||
app.set('views', __dirname + '/views');
|
||||
|
||||
// Set our default template engine to "jade"
|
||||
// which prevents the need for extensions
|
||||
// (although you can still mix and match)
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
function User(name, email) {
|
||||
this.name = name;
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
// Dummy users
|
||||
var users = [
|
||||
new User('tj', 'tj@vision-media.ca')
|
||||
, new User('ciaran', 'ciaranj@gmail.com')
|
||||
, new User('aaron', 'aaron.heckmann+github@gmail.com')
|
||||
];
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('users', { users: users });
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
console.log('Express app started on port 3000');
|
||||
@@ -1,3 +0,0 @@
|
||||
body
|
||||
:padding 50px 80px
|
||||
:font 14px "Helvetica Nueue", "Lucida Grande", Arial, sans-serif
|
||||
@@ -0,0 +1,3 @@
|
||||
head
|
||||
title Jade Example
|
||||
link(rel="stylesheet", href="/stylesheets/style.css")
|
||||
@@ -1,6 +1,5 @@
|
||||
!!!
|
||||
!!! 5
|
||||
html
|
||||
head
|
||||
title Jade Example
|
||||
link(rel="stylesheet", href="/stylesheets/style.css")
|
||||
body!= body
|
||||
include header
|
||||
body
|
||||
block content
|
||||
@@ -1,3 +0,0 @@
|
||||
- if (users.length)
|
||||
h1 Users
|
||||
#users!= partial('user', users)
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
extends ../layout
|
||||
|
||||
block content
|
||||
h1 Users
|
||||
#users
|
||||
for user in users
|
||||
include user
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('../../')
|
||||
, fs = require('fs')
|
||||
, md = require('github-flavored-markdown').parse;
|
||||
|
||||
var app = module.exports = express();
|
||||
|
||||
// register .md as an engine in express view system
|
||||
|
||||
app.engine('md', function(path, options, fn){
|
||||
fs.readFile(path, 'utf8', function(err, str){
|
||||
if (err) return fn(err);
|
||||
try {
|
||||
var html = md(str);
|
||||
html = html.replace(/\{([^}]+)\}/g, function(_, name){
|
||||
return options[name] || '';
|
||||
})
|
||||
fn(null, html);
|
||||
} catch(err) {
|
||||
fn(err);
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
app.set('views', __dirname + '/views');
|
||||
|
||||
// make it the default so we dont need .md
|
||||
app.set('view engine', 'md');
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('index', { title: 'Markdown Example' });
|
||||
})
|
||||
|
||||
app.get('/fail', function(req, res){
|
||||
res.render('missing', { title: 'Markdown Example' });
|
||||
})
|
||||
|
||||
if (!module.parent) {
|
||||
app.listen(3000);
|
||||
console.log('Express started on port 3000');
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
# {title}
|
||||
|
||||
Just an example view rendered with _markdown_.
|
||||
+23
-39
@@ -1,52 +1,36 @@
|
||||
|
||||
// Expose modules in ./support for demo purposes
|
||||
require.paths.unshift(__dirname + '/../../support');
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('../../lib/express'),
|
||||
form = require('connect-form'),
|
||||
sys = require('sys');
|
||||
var express = require('../../')
|
||||
, format = require('util').format;
|
||||
|
||||
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({ keepExtensions: true })
|
||||
);
|
||||
var app = module.exports = express()
|
||||
|
||||
// bodyParser in connect 2.x uses node-formidable to parse
|
||||
// the multipart form data.
|
||||
app.use(express.bodyParser())
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.send('<form method="post" enctype="multipart/form-data">'
|
||||
+ '<p>Image: <input type="file" name="image" /></p>'
|
||||
+ '<p><input type="submit" value="Upload" /></p>'
|
||||
+ '</form>');
|
||||
res.send('<form method="post" enctype="multipart/form-data">'
|
||||
+ '<p>Title: <input type="text" name="title" /></p>'
|
||||
+ '<p>Image: <input type="file" name="image" /></p>'
|
||||
+ '<p><input type="submit" value="Upload" /></p>'
|
||||
+ '</form>');
|
||||
});
|
||||
|
||||
app.post('/', function(req, res, 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 {
|
||||
console.log('\nuploaded %s to %s',
|
||||
files.image.filename,
|
||||
files.image.path);
|
||||
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');
|
||||
});
|
||||
// the uploaded file can be found as `req.files.image` and the
|
||||
// title field as `req.body.title`
|
||||
res.send(format('\nuploaded %s (%d Kb) to %s as %s'
|
||||
, req.files.image.name
|
||||
, req.files.image.size / 1024 | 0
|
||||
, req.files.image.path
|
||||
, req.body.title));
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
console.log('Express app started on port 3000');
|
||||
if (!module.parent) {
|
||||
app.listen(3000);
|
||||
console.log('Express started on port 3000');
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
|
||||
// Expose modules in ./support for demo purposes
|
||||
require.paths.unshift(__dirname + '/../../support');
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('../../lib/express');
|
||||
|
||||
var app = express.createServer();
|
||||
|
||||
require('./mvc').boot(app);
|
||||
|
||||
app.listen(3000);
|
||||
console.log('Express app started on port 3000');
|
||||
@@ -1,9 +0,0 @@
|
||||
|
||||
module.exports = {
|
||||
|
||||
// /
|
||||
|
||||
index: function(req, res){
|
||||
res.render();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
exports.index = function(req, res){
|
||||
res.redirect('/users');
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
var db = require('../../db');
|
||||
|
||||
exports.engine = 'jade';
|
||||
|
||||
exports.before = function(req, res, next){
|
||||
var pet = db.pets[req.params.pet_id];
|
||||
if (!pet) return next(new Error('Pet not found'));
|
||||
req.pet = pet;
|
||||
next();
|
||||
};
|
||||
|
||||
exports.show = function(req, res, next){
|
||||
res.render('show', { pet: req.pet });
|
||||
};
|
||||
|
||||
exports.edit = function(req, res, next){
|
||||
res.render('edit', { pet: req.pet });
|
||||
};
|
||||
|
||||
exports.update = function(req, res, next){
|
||||
var body = req.body;
|
||||
req.pet.name = body.user.name;
|
||||
res.message('Information updated!');
|
||||
res.redirect('/pet/' + req.pet.id);
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
link(rel='stylesheet', href='/style.css')
|
||||
h1= pet.name
|
||||
form(action='/pet/#{pet.id}', method='post')
|
||||
input(type='hidden', name='_method', value='put')
|
||||
label Name:
|
||||
input(type='text', name='user[name]', value=pet.name)
|
||||
input(type='submit', value='Update')
|
||||
@@ -0,0 +1,6 @@
|
||||
link(rel='stylesheet', href='/style.css')
|
||||
|
||||
h1= pet.name
|
||||
a(href='/pet/#{pet.id}/edit') edit
|
||||
|
||||
p You are viewing #{pet.name}
|
||||
Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais
Referência em uma Nova Issue
Bloquear um usuário