Compare commits
	
		
			226 Commits
		
	
	
		
			no_npm
			...
			9b59c4c89b
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 9b59c4c89b | |||
|  | 00d84614c2 | ||
|  | 52e7cef7ef | ||
|  | fbff1bc201 | ||
|  | 7af15cc32d | ||
|  | 7f397ce753 | ||
|  | 8f8b039f65 | ||
|  | eeaf2d7b18 | ||
|  | db0b7d6444 | ||
|  | db6e7603f9 | ||
| 20fb7f9bc2 | |||
|  | ad5d7549d7 | ||
| 991f26e871 | |||
| e2293900de | |||
|  | 5d2965ffc5 | ||
|  | f255928af7 | ||
|  | a108dbadc5 | ||
|  | c409aca080 | ||
|  | 219424550b | ||
|  | f147acb51c | ||
|  | 9a692ed652 | ||
|  | 3a17c86a0f | ||
|  | 677a22987a | ||
|  | 89d912c6ff | ||
|  | 4cac6713ef | ||
|  | f3b0de745b | ||
|  | cc8a99752f | ||
|  | 6853d077e7 | ||
|  | 80a2b6f0dd | ||
|  | 4f68b3d7d6 | ||
|  | ef0ca40533 | ||
|  | f372ef18de | ||
|  | 181a3a2bfa | ||
|  | 61d08afb3b | ||
|  | 1ba025328d | ||
|  | a79fb39f54 | ||
|  | 3a72d74537 | ||
|  | e9ae74b7a9 | ||
|  | c305e9a83d | ||
|  | 16bce4c83d | ||
|  | 661997cd73 | ||
|  | 159f989d08 | ||
|  | 139df62ec4 | ||
|  | bae6387bb7 | ||
|  | bb7b9571a7 | ||
|  | a4dc29fb2b | ||
|  | 342f56ce1a | ||
|  | 05ecc90764 | ||
|  | 69cf505a90 | ||
|  | 9f41993566 | ||
|  | 5c9311fb85 | ||
|  | 5a8d52a5e3 | ||
|  | 0f145b4444 | ||
|  | aef4bb5edb | ||
|  | 36c854ef1b | ||
|  | edd428ff37 | ||
|  | 0612ba001e | ||
|  | 064680003d | ||
|  | 655f2af45a | ||
|  | ce03749c2f | ||
| 24ed412f50 | |||
| 7bd0fcc621 | |||
| e718672b58 | |||
|  | f6084b4339 | ||
|  | 9b0a5ff0a3 | ||
| a4ad0e1fa6 | |||
| af28e0c5d9 | |||
| 240a9f7fde | |||
| dca3237a71 | |||
| a541630848 | |||
| e067323714 | |||
|  | 1fff48568f | ||
|  | b4c666fbcf | ||
|  | b866c33c93 | ||
|  | 035cf0e91e | ||
|  | f3838ab4a8 | ||
|  | bf2b1c957a | ||
|  | 86bbc1899d | ||
|  | d41d7491d4 | ||
|  | 5fb43eb67c | ||
|  | 1eeef4ede4 | ||
|  | ebc749c5e0 | ||
|  | b0bbb72f35 | ||
|  | 2213c3874a | ||
|  | 6ebd72a86c | ||
|  | b6814a1445 | ||
|  | e3d18efdc6 | ||
|  | 869fb65738 | ||
|  | 56b939124e | ||
|  | ee1c1c0856 | ||
|  | b087ac8dd1 | ||
|  | d922667f56 | ||
|  | 5f6fefa7a6 | ||
|  | faa7e679ca | ||
|  | cd3bf26dbe | ||
|  | 830dc1bc43 | ||
|  | dc0f151a7f | ||
|  | 7f625e22f7 | ||
|  | 528b7b07a8 | ||
|  | 2b81e67ce7 | ||
|  | 827e7b51b5 | ||
|  | 16d529e935 | ||
|  | ad7702aaf4 | ||
|  | f5fbc8d19e | ||
|  | 0a8923bf12 | ||
|  | 4d572a2ec0 | ||
|  | d9a53d3e6e | ||
|  | 8da37ea5de | ||
|  | ff0fccd6c2 | ||
|  | 63c4576633 | ||
|  | b31d143bcd | ||
|  | 0d8aec8d61 | ||
|  | 1f9fdd205d | ||
|  | cdd0cf3739 | ||
|  | ba5c6b8d16 | ||
|  | cfef588283 | ||
|  | 318c5f7ba6 | ||
|  | ee03e7cd78 | ||
|  | 3b6934e348 | ||
|  | f161cc33b4 | ||
|  | 40f1f2588e | ||
|  | e4e025f67e | ||
|  | e12805a8aa | ||
|  | e76c845f16 | ||
|  | 072418695e | ||
|  | 584b66bc66 | ||
|  | f8db455f74 | ||
|  | f19c5d1049 | ||
|  | c5b859ec98 | ||
|  | 2ee93a7409 | ||
|  | bf1dbb68b8 | ||
|  | cf28e23d8e | ||
|  | 5939dec185 | ||
|  | 3ed1d775ac | ||
|  | 87b1c76aaf | ||
|  | 4599203bdf | ||
|  | d66bc9a6c4 | ||
|  | 80f0618736 | ||
|  | ac2bceefbb | ||
|  | dbf4f6b5dd | ||
|  | 8e9205cecc | ||
|  | e54a860172 | ||
|  | 5a8697cdd8 | ||
|  | 091ea973a8 | ||
|  | 939b7221ab | ||
|  | 934aaf7f51 | ||
|  | 930e21ccb7 | ||
|  | eb5c8eef6a | ||
|  | 03dd611a86 | ||
|  | f24376b192 | ||
|  | eea359d0ec | ||
|  | af9a71549b | ||
|  | 3178676fba | ||
|  | 3bdfab8219 | ||
|  | a3a24d9765 | ||
|  | 8afb53e77e | ||
|  | d6d9cf40f9 | ||
|  | 1010a142e2 | ||
|  | d3db5e2a5d | ||
|  | 0209375865 | ||
|  | 00a9d9c312 | ||
|  | 6835eef468 | ||
|  | 4626fd9c8d | ||
|  | fbb6e63c37 | ||
|  | 84c909a5db | ||
|  | 45e19bc7cc | ||
|  | 233bc6ff16 | ||
|  | 360b325ced | ||
|  | e93f98112b | ||
|  | 05cb051bc8 | ||
|  | 031cdd738a | ||
|  | c92ab077c0 | ||
|  | 6c31389327 | ||
|  | a8d4f3c300 | ||
|  | ab029eae2f | ||
|  | 447d0aae76 | ||
|  | 4870158430 | ||
|  | 0471b059a0 | ||
|  | 5bbe50b481 | ||
|  | bda2749879 | ||
|  | 028aa96b13 | ||
|  | 2deda5b68a | ||
|  | ee7098457e | ||
|  | 7a08960414 | ||
|  | 89909747f1 | ||
|  | 202e695e07 | ||
|  | 48e8e79659 | ||
|  | abb49f2cf3 | ||
|  | d1cd2a5213 | ||
|  | 27317844e0 | ||
|  | ee74e2fa90 | ||
|  | 5d8bd2e6f8 | ||
|  | cd4c7aeab8 | ||
|  | e37c3cf1b9 | ||
|  | 8858bab985 | ||
|  | afb0c332cc | ||
|  | 82c58c5c0c | ||
|  | 46bdd27431 | ||
|  | 1adfba1a37 | ||
|  | 54e55b1b0d | ||
|  | 08d37cc7f7 | ||
|  | aa781957e8 | ||
|  | c00477c93c | ||
|  | 035f09ac05 | ||
|  | 36e00bb29e | ||
|  | 10623873e8 | ||
|  | e536ba1019 | ||
|  | 85fc36d710 | ||
|  | 5d5ae164f3 | ||
|  | 79309c75df | ||
|  | 4b58c8d356 | ||
|  | 8f0d6260b0 | ||
|  | 93a83a35da | ||
|  | 4efc5d47d9 | ||
|  | ff8ef54e34 | ||
|  | 814a49812a | ||
|  | e0610bc1be | ||
|  | 962976c204 | ||
|  | 16080bdc16 | ||
|  | 20ce741341 | ||
|  | 13bb094fb3 | ||
|  | b43a55ffda | ||
|  | 45cbdcce70 | ||
|  | 1950cc8db0 | ||
|  | 90cfe0ec57 | ||
|  | 87e28548b9 | 
							
								
								
									
										8
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,8 @@ | |||||||
|  | Dockerfile | ||||||
|  | .git | ||||||
|  | npm-debug.log | ||||||
|  | node_modules | ||||||
|  | *.swp | ||||||
|  | *.swo | ||||||
|  | data | ||||||
|  | *.DS_Store | ||||||
							
								
								
									
										2
									
								
								.eslintignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,2 @@ | |||||||
|  | **/*.min.js | ||||||
|  | config.js | ||||||
							
								
								
									
										25
									
								
								.eslintrc.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,25 @@ | |||||||
|  | { | ||||||
|  |     "env": { | ||||||
|  |         "es6": true, | ||||||
|  |         "node": true | ||||||
|  |     }, | ||||||
|  |     "extends": "eslint:recommended", | ||||||
|  |     "rules": { | ||||||
|  |         "indent": [ | ||||||
|  |             "error", | ||||||
|  |             2 | ||||||
|  |         ], | ||||||
|  |         "linebreak-style": [ | ||||||
|  |             "error", | ||||||
|  |             "unix" | ||||||
|  |         ], | ||||||
|  |         "quotes": [ | ||||||
|  |             "error", | ||||||
|  |             "single" | ||||||
|  |         ], | ||||||
|  |         "semi": [ | ||||||
|  |             "error", | ||||||
|  |             "always" | ||||||
|  |         ] | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,5 +1,7 @@ | |||||||
| npm-debug.log | npm-debug.log | ||||||
|  | node_modules | ||||||
| *.swp | *.swp | ||||||
| *.swo | *.swo | ||||||
| data | data | ||||||
| *.DS_Store | *.DS_Store | ||||||
|  | config.json | ||||||
|   | |||||||
							
								
								
									
										68
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,68 @@ | |||||||
|  | FROM node:14.8.0-stretch | ||||||
|  |  | ||||||
|  | RUN mkdir -p /usr/src/app && \ | ||||||
|  |     chown node:node /usr/src/app | ||||||
|  |  | ||||||
|  | USER node:node | ||||||
|  |  | ||||||
|  | WORKDIR /usr/src/app | ||||||
|  |  | ||||||
|  | COPY --chown=node:node . . | ||||||
|  |  | ||||||
|  | RUN npm install && \ | ||||||
|  |     npm install redis@0.8.1 && \ | ||||||
|  |     npm install pg@4.1.1 && \ | ||||||
|  |     npm install memcached@2.2.2 && \ | ||||||
|  |     npm install aws-sdk@2.738.0 && \ | ||||||
|  |     npm install rethinkdbdash@2.3.31 | ||||||
|  |  | ||||||
|  | ENV STORAGE_TYPE=memcached \ | ||||||
|  |     STORAGE_HOST=127.0.0.1 \ | ||||||
|  |     STORAGE_PORT=11211\ | ||||||
|  |     STORAGE_EXPIRE_SECONDS=2592000\ | ||||||
|  |     STORAGE_DB=2 \ | ||||||
|  |     STORAGE_AWS_BUCKET= \ | ||||||
|  |     STORAGE_AWS_REGION= \ | ||||||
|  |     STORAGE_USENAME= \ | ||||||
|  |     STORAGE_PASSWORD= \ | ||||||
|  |     STORAGE_FILEPATH= | ||||||
|  |  | ||||||
|  | ENV LOGGING_LEVEL=verbose \ | ||||||
|  |     LOGGING_TYPE=Console \ | ||||||
|  |     LOGGING_COLORIZE=true | ||||||
|  |  | ||||||
|  | ENV HOST=0.0.0.0\ | ||||||
|  |     PORT=7777\ | ||||||
|  |     KEY_LENGTH=10\ | ||||||
|  |     MAX_LENGTH=400000\ | ||||||
|  |     STATIC_MAX_AGE=86400\ | ||||||
|  |     RECOMPRESS_STATIC_ASSETS=true | ||||||
|  |  | ||||||
|  | ENV KEYGENERATOR_TYPE=phonetic \ | ||||||
|  |     KEYGENERATOR_KEYSPACE= | ||||||
|  |  | ||||||
|  | ENV RATELIMITS_NORMAL_TOTAL_REQUESTS=500\ | ||||||
|  |     RATELIMITS_NORMAL_EVERY_MILLISECONDS=60000 \ | ||||||
|  |     RATELIMITS_WHITELIST_TOTAL_REQUESTS= \ | ||||||
|  |     RATELIMITS_WHITELIST_EVERY_MILLISECONDS=  \ | ||||||
|  |     # comma separated list for the whitelisted \ | ||||||
|  |     RATELIMITS_WHITELIST=example1.whitelist,example2.whitelist \ | ||||||
|  |     \ | ||||||
|  |     RATELIMITS_BLACKLIST_TOTAL_REQUESTS= \ | ||||||
|  |     RATELIMITS_BLACKLIST_EVERY_MILLISECONDS= \ | ||||||
|  |     # comma separated list for the blacklisted \ | ||||||
|  |     RATELIMITS_BLACKLIST=example1.blacklist,example2.blacklist | ||||||
|  | ENV DOCUMENTS=about=./about.md | ||||||
|  |  | ||||||
|  | EXPOSE ${PORT} | ||||||
|  | STOPSIGNAL SIGINT | ||||||
|  | ENTRYPOINT [ "bash", "docker-entrypoint.sh" ] | ||||||
|  |  | ||||||
|  | HEALTHCHECK --interval=30s --timeout=30s --start-period=5s \ | ||||||
|  |     --retries=3 CMD [ "sh", "-c", "echo -n 'curl localhost:7777... '; \ | ||||||
|  |     (\ | ||||||
|  |         curl -sf localhost:7777 > /dev/null\ | ||||||
|  |     ) && echo OK || (\ | ||||||
|  |         echo Fail && exit 2\ | ||||||
|  |     )"] | ||||||
|  | CMD ["npm", "start"] | ||||||
							
								
								
									
										235
									
								
								README.md
									
									
									
									
									
								
							
							
						
						| @@ -31,21 +31,31 @@ STDOUT.  Check the README there for more details and usages. | |||||||
| 1.  Download the package, and expand it | 1.  Download the package, and expand it | ||||||
| 2.  Explore the settings inside of config.js, but the defaults should be good | 2.  Explore the settings inside of config.js, but the defaults should be good | ||||||
| 3.  `npm install` | 3.  `npm install` | ||||||
| 4.  `npm start` | 4.  `npm start` (you may specify an optional `<config-path>` as well) | ||||||
|  |  | ||||||
| ## Settings | ## Settings | ||||||
|  |  | ||||||
| * `host` - the host the server runs on (default localhost) | * `host` - the host the server runs on (default localhost) | ||||||
| * `port` - the port the server runs on (default 7777) | * `port` - the port the server runs on (default 7777) | ||||||
| * `keyLength` - the length of the keys to user (default 10) | * `keyLength` - the length of the keys to user (default 10) | ||||||
| * `maxLength` - maximum length of a paste (default none) | * `maxLength` - maximum length of a paste (default 400000) | ||||||
| * `staticMaxAge` - max age for static assets (86400) | * `staticMaxAge` - max age for static assets (86400) | ||||||
| * `recompressStatisAssets` - whether or not to compile static js assets (true) | * `recompressStaticAssets` - whether or not to compile static js assets (true) | ||||||
| * `documents` - static documents to serve (ex: http://hastebin.com/about.com) | * `documents` - static documents to serve (ex: http://hastebin.com/about.com) | ||||||
|   in addition to static assets.  These will never expire. |   in addition to static assets.  These will never expire. | ||||||
| * `storage` - storage options (see below) | * `storage` - storage options (see below) | ||||||
| * `logging` - logging preferences | * `logging` - logging preferences | ||||||
| * `keyGenerator` - key generator options (see below) | * `keyGenerator` - key generator options (see below) | ||||||
|  | * `rateLimits` - settings for rate limiting (see below) | ||||||
|  |  | ||||||
|  | ## Rate Limiting | ||||||
|  |  | ||||||
|  | When present, the `rateLimits` option enables built-in rate limiting courtesy | ||||||
|  | of `connect-ratelimit`.  Any of the options supported by that library can be | ||||||
|  | used and set in `config.js`. | ||||||
|  |  | ||||||
|  | See the README for [connect-ratelimit](https://github.com/dharmafly/connect-ratelimit) | ||||||
|  | for more information! | ||||||
|  |  | ||||||
| ## Key Generation | ## Key Generation | ||||||
|  |  | ||||||
| @@ -87,11 +97,14 @@ something like: | |||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| Where `path` represents where you want the files stored | where `path` represents where you want the files stored. | ||||||
|  |  | ||||||
|  | File storage currently does not support paste expiration, you can follow [#191](https://github.com/seejohnrun/haste-server/issues/191) for status updates. | ||||||
|  |  | ||||||
| ### Redis | ### Redis | ||||||
|  |  | ||||||
| To use redis storage you must install the redis package in npm | To use redis storage you must install the `redis` package in npm, and have | ||||||
|  | `redis-server` running on the machine. | ||||||
|  |  | ||||||
| `npm install redis` | `npm install redis` | ||||||
|  |  | ||||||
| @@ -112,11 +125,62 @@ or post. | |||||||
|  |  | ||||||
| All of which are optional except `type` with very logical default values. | All of which are optional except `type` with very logical default values. | ||||||
|  |  | ||||||
|  | If your Redis server is configured for password authentification, use the `password` field. | ||||||
|  |  | ||||||
|  | ### Postgres | ||||||
|  |  | ||||||
|  | To use postgres storage you must install the `pg` package in npm | ||||||
|  |  | ||||||
|  | `npm install pg` | ||||||
|  |  | ||||||
|  | Once you've done that, your config section should look like: | ||||||
|  |  | ||||||
|  | ``` json | ||||||
|  | { | ||||||
|  |   "type": "postgres", | ||||||
|  |   "connectionUrl": "postgres://user:password@host:5432/database" | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | You can also just set the environment variable for `DATABASE_URL` to your database connection url. | ||||||
|  |  | ||||||
|  | You will have to manually add a table to your postgres database: | ||||||
|  |  | ||||||
|  | `create table entries (id serial primary key, key varchar(255) not null, value text not null, expiration int, unique(key));` | ||||||
|  |  | ||||||
|  | You can also set an `expire` option to the number of seconds to expire keys in. | ||||||
|  | This is off by default, but will constantly kick back expirations on each view | ||||||
|  | or post. | ||||||
|  |  | ||||||
|  | All of which are optional except `type` with very logical default values. | ||||||
|  |  | ||||||
|  | ### MongoDB | ||||||
|  |  | ||||||
|  | To use mongodb storage you must install the 'mongodb' package in npm | ||||||
|  |  | ||||||
|  | `npm install mongodb` | ||||||
|  |  | ||||||
|  | Once you've done that, your config section should look like: | ||||||
|  |  | ||||||
|  | ``` json | ||||||
|  | { | ||||||
|  |   "type": "mongo", | ||||||
|  |   "connectionUrl": "mongodb://localhost:27017/database" | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | You can also just set the environment variable for `DATABASE_URL` to your database connection url. | ||||||
|  |  | ||||||
|  | Unlike with postgres you do NOT have to create the table in your mongo database prior to running. | ||||||
|  |  | ||||||
|  | You can also set an `expire` option to the number of seconds to expire keys in. | ||||||
|  | This is off by default, but will constantly kick back expirations on each view or post. | ||||||
|  |  | ||||||
| ### Memcached | ### Memcached | ||||||
|  |  | ||||||
| To use memcached storage you must install the `memcache` package via npm | To use memcache storage you must install the `memcached` package via npm | ||||||
|  |  | ||||||
| `npm install memcache` | `npm install memcached` | ||||||
|  |  | ||||||
| Once you've done that, your config section should look like: | Once you've done that, your config section should look like: | ||||||
|  |  | ||||||
| @@ -134,6 +198,161 @@ forward on GETs. | |||||||
|  |  | ||||||
| All of which are optional except `type` with very logical default values. | All of which are optional except `type` with very logical default values. | ||||||
|  |  | ||||||
|  | ### RethinkDB | ||||||
|  |  | ||||||
|  | To use the RethinkDB storage system, you must install the `rethinkdbdash` package via npm | ||||||
|  |  | ||||||
|  | `npm install rethinkdbdash` | ||||||
|  |  | ||||||
|  | Once you've done that, your config section should look like this: | ||||||
|  |  | ||||||
|  | ``` json | ||||||
|  | { | ||||||
|  |   "type": "rethinkdb", | ||||||
|  |   "host": "127.0.0.1", | ||||||
|  |   "port": 28015, | ||||||
|  |   "db": "haste" | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | In order for this to work, the database must be pre-created before the script is ran. | ||||||
|  | Also, you must create an `uploads` table, which will store all the data for uploads. | ||||||
|  |  | ||||||
|  | You can optionally add the `user` and `password` properties to use a user system. | ||||||
|  |  | ||||||
|  | ### Google Datastore | ||||||
|  |  | ||||||
|  | To use the Google Datastore storage system, you must install the `@google-cloud/datastore` package via npm | ||||||
|  |  | ||||||
|  | `npm install @google-cloud/datastore` | ||||||
|  |  | ||||||
|  | Once you've done that, your config section should look like this: | ||||||
|  |  | ||||||
|  | ``` json | ||||||
|  | { | ||||||
|  |   "type": "google-datastore" | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Authentication is handled automatically by [Google Cloud service account credentials](https://cloud.google.com/docs/authentication/getting-started), by providing authentication details to the GOOGLE_APPLICATION_CREDENTIALS environmental variable. | ||||||
|  |  | ||||||
|  | ### Amazon S3 | ||||||
|  |  | ||||||
|  | To use [Amazon S3](https://aws.amazon.com/s3/) as a storage system, you must | ||||||
|  | install the `aws-sdk` package via npm: | ||||||
|  |  | ||||||
|  | `npm install aws-sdk` | ||||||
|  |  | ||||||
|  | Once you've done that, your config section should look like this: | ||||||
|  |  | ||||||
|  | ```json | ||||||
|  | { | ||||||
|  |   "type": "amazon-s3", | ||||||
|  |   "bucket": "your-bucket-name", | ||||||
|  |   "region": "us-east-1" | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Authentication is handled automatically by the client. Check | ||||||
|  | [Amazon's documentation](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials-node.html) | ||||||
|  | for more information. You will need to grant your role these permissions to | ||||||
|  | your bucket: | ||||||
|  |  | ||||||
|  | ```json | ||||||
|  | { | ||||||
|  |     "Version": "2012-10-17", | ||||||
|  |     "Statement": [ | ||||||
|  |         { | ||||||
|  |             "Action": [ | ||||||
|  |                 "s3:GetObject", | ||||||
|  |                 "s3:PutObject" | ||||||
|  |             ], | ||||||
|  |             "Effect": "Allow", | ||||||
|  |             "Resource": "arn:aws:s3:::your-bucket-name-goes-here/*" | ||||||
|  |         } | ||||||
|  |     ] | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Docker | ||||||
|  |  | ||||||
|  | ### Build image | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | docker build --tag haste-server . | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### Run container | ||||||
|  |  | ||||||
|  | For this example we will run haste-server, and connect it to a redis server | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | docker run --name haste-server-container --env STORAGE_TYPE=redis --env STORAGE_HOST=redis-server --env STORAGE_PORT=6379 haste-server | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### Use docker-compose example | ||||||
|  |  | ||||||
|  | There is an example `docker-compose.yml` which runs haste-server together with memcached | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | docker-compose up | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### Configuration | ||||||
|  |  | ||||||
|  | The docker image is configured using environmental variables as you can see in the example above. | ||||||
|  |  | ||||||
|  | Here is a list of all the environment variables | ||||||
|  |  | ||||||
|  | ### Storage | ||||||
|  |  | ||||||
|  | |          Name          | Default value |                                                  Description                                                  | | ||||||
|  | | :--------------------: | :-----------: | :-----------------------------------------------------------------------------------------------------------: | | ||||||
|  | |      STORAGE_TYPE      |   memcached   |    Type of storage . Accepted values: "memcached","redis","postgres","rethinkdb", "amazon-s3", and "file"     | | ||||||
|  | |      STORAGE_HOST      |   127.0.0.1   |                 Storage host. Applicable for types: memcached, redis, postgres, and rethinkdb                 | | ||||||
|  | |      STORAGE_PORT      |     11211     |           Port on the storage host. Applicable for types: memcached, redis, postgres, and rethinkdb           | | ||||||
|  | | STORAGE_EXPIRE_SECONDS |    2592000    | Number of seconds to expire keys in. Applicable for types. Redis, postgres, memcached. `expire` option to the | | ||||||
|  | |       STORAGE_DB       |       2       |                    The name of the database. Applicable for redis, postgres, and rethinkdb                    | | ||||||
|  | |    STORAGE_PASSWORD    |               |                       Password for database. Applicable for redis, postges, rethinkdb .                       | | ||||||
|  | |    STORAGE_USERNAME    |               |                           Database username. Applicable for postgres, and rethinkdb                           | | ||||||
|  | |   STORAGE_AWS_BUCKET   |               |                          Applicable for amazon-s3. This is the name of the S3 bucket                          | | ||||||
|  | |   STORAGE_AWS_REGION   |               |                      Applicable for amazon-s3. The region in which the bucket is located                      | | ||||||
|  | |    STORAGE_FILEPATH    |               |                            Path to file to save data to. Applicable for type file                             | | ||||||
|  |  | ||||||
|  | ### Logging | ||||||
|  |  | ||||||
|  | |       Name        | Default value | Description | | ||||||
|  | | :---------------: | :-----------: | :---------: | | ||||||
|  | |   LOGGING_LEVEL   |    verbose    |             | | ||||||
|  | |   LOGGING_TYPE=   |    Console    | | ||||||
|  | | LOGGING_COLORIZE= |     true      | | ||||||
|  |  | ||||||
|  | ### Basics | ||||||
|  |  | ||||||
|  | |           Name           |  Default value   |                                        Description                                        | | ||||||
|  | | :----------------------: | :--------------: | :---------------------------------------------------------------------------------------: | | ||||||
|  | |           HOST           |     0.0.0.0      |                         The hostname which the server answers on                          | | ||||||
|  | |           PORT           |       7777       |                          The port on which the server is running                          | | ||||||
|  | |        KEY_LENGTH        |        10        |                              the length of the keys to user                               | | ||||||
|  | |        MAX_LENGTH        |      400000      |                                 maximum length of a paste                                 | | ||||||
|  | |      STATIC_MAX_AGE      |      86400       |                                 max age for static assets                                 | | ||||||
|  | | RECOMPRESS_STATIC_ASSETS |       true       |                        whether or not to compile static js assets                         | | ||||||
|  | |    KEYGENERATOR_TYPE     |     phonetic     |             Type of key generator. Acceptable values: "phonetic", or "random"             | | ||||||
|  | |  KEYGENERATOR_KEYSPACE   |                  |                  keySpace argument is a string of acceptable characters                   | | ||||||
|  | |        DOCUMENTS         | about=./about.md | Comma separated list of static documents to serve. ex: \n about=./about.md,home=./home.md | | ||||||
|  |  | ||||||
|  | ### Rate limits | ||||||
|  |  | ||||||
|  | |                 Name                 |             Default value             |                                       Description                                        | | ||||||
|  | | :----------------------------------: | :-----------------------------------: | :--------------------------------------------------------------------------------------: | | ||||||
|  | |   RATELIMITS_NORMAL_TOTAL_REQUESTS   |                  500                  | By default anyone uncategorized will be subject to 500 requests in the defined timespan. | | ||||||
|  | | RATELIMITS_NORMAL_EVERY_MILLISECONDS |                 60000                 |             The timespan to allow the total requests for uncategorized users             | | ||||||
|  | | RATELIMITS_WHITELIST_TOTAL_REQUESTS  |                                       |      By default client names in the whitelist will not have their requests limited.      | | ||||||
|  | |  RATELIMITS_WHITELIST_EVERY_SECONDS  |                                       |      By default client names in the whitelist will not have their requests limited.      | | ||||||
|  | |         RATELIMITS_WHITELIST         | example1.whitelist,example2.whitelist |           Comma separated list of the clients which are in the whitelist pool            | | ||||||
|  | | RATELIMITS_BLACKLIST_TOTAL_REQUESTS  |                                       |    By default client names in the blacklist will be subject to 0 requests per hours.     | | ||||||
|  | |  RATELIMITS_BLACKLIST_EVERY_SECONDS  |                                       |     By default client names in the blacklist will be subject to 0 requests per hours     | | ||||||
|  | |         RATELIMITS_BLACKLIST         | example1.blacklist,example2.blacklist |           Comma separated list of the clients which are in the blacklistpool.            | | ||||||
|  |  | ||||||
| ## Author | ## Author | ||||||
|  |  | ||||||
| @@ -143,7 +362,7 @@ John Crepezzi <john.crepezzi@gmail.com> | |||||||
|  |  | ||||||
| (The MIT License) | (The MIT License) | ||||||
|  |  | ||||||
| Copyright © 2011 John Crepezzi | Copyright © 2011-2012 John Crepezzi | ||||||
|  |  | ||||||
| Permission is hereby granted, free of charge, to any person obtaining a copy of | Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||||
| this software and associated documentation files (the ‘Software’), to deal in | this software and associated documentation files (the ‘Software’), to deal in | ||||||
|   | |||||||
							
								
								
									
										41
									
								
								about.md
									
									
									
									
									
								
							
							
						
						| @@ -15,44 +15,19 @@ To make a new entry, click "New" (or type 'control + n') | |||||||
|  |  | ||||||
| ## From the Console | ## From the Console | ||||||
|  |  | ||||||
| Most of the time I want to show you some text, its coming from my current | [bin-client](git.webionite.com/ceda_ei/bin-client) | ||||||
| console session.  We should make it really easy to take code from the console |  | ||||||
| and send it to people. |  | ||||||
|  |  | ||||||
| `cat something | haste` # http://hastebin.com/1238193 | Add the following to your bashrc/zshrc | ||||||
|  | ``` | ||||||
| You can even take this a step further, and cut out the last step of copying the | export MKR_BIN='https://bin.webionite.com/' | ||||||
| URL with: | export HASTEBIN=1 | ||||||
|  | ``` | ||||||
| * osx: `cat something | haste | pbcopy` |  | ||||||
| * linux: `cat something | haste | xsel` |  | ||||||
| * windows: check out [WinHaste](https://github.com/ajryan/WinHaste) |  | ||||||
|  |  | ||||||
| After running that, the STDOUT output of `cat something` will show up at a URL |  | ||||||
| which has been conveniently copied to your clipboard. |  | ||||||
|  |  | ||||||
| That's all there is to that, and you can install it with `gem install haste` |  | ||||||
| right now. |  | ||||||
|   * osx: you will need to have an up to date version of Xcode |  | ||||||
|   * linux: you will need to have rubygems and ruby-devel installed |  | ||||||
|  |  | ||||||
| ## Duration |  | ||||||
|  |  | ||||||
| Pastes will stay for 30 days from their last view. |  | ||||||
|  |  | ||||||
| ## Privacy |  | ||||||
|  |  | ||||||
| While the contents of hastebin.com are not directly crawled by any search robot |  | ||||||
| that obeys "robots.txt", there should be no great expectation of privacy.  Post |  | ||||||
| things at your own risk. Not responsible for any loss of data or removed |  | ||||||
| pastes. |  | ||||||
|  |  | ||||||
| ## Open Source | ## Open Source | ||||||
|  |  | ||||||
| Haste can easily be installed behind your network, and its all open source! | Haste can easily be installed behind your network, and it's all open source! | ||||||
|  |  | ||||||
| * [haste-client](https://github.com/seejohnrun/haste-client) | * [haste-server](https://git.webionite.com/Webionite/haste-server) | ||||||
| * [haste-server](https://github.com/seejohnrun/haste-server) |  | ||||||
|  |  | ||||||
| ## Author | ## Author | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								docker-compose.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,19 @@ | |||||||
|  | version: '3.0' | ||||||
|  | services: | ||||||
|  |   haste-server: | ||||||
|  |     build: . | ||||||
|  |     networks: | ||||||
|  |       - db-network | ||||||
|  |     environment: | ||||||
|  |       - STORAGE_TYPE=memcached | ||||||
|  |       - STORAGE_HOST=memcached | ||||||
|  |       - STORAGE_PORT=11211 | ||||||
|  |     ports: | ||||||
|  |       - 7777:7777 | ||||||
|  |   memcached: | ||||||
|  |     image: memcached:latest | ||||||
|  |     networks: | ||||||
|  |       - db-network | ||||||
|  |  | ||||||
|  | networks: | ||||||
|  |   db-network: | ||||||
							
								
								
									
										108
									
								
								docker-entrypoint.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,108 @@ | |||||||
|  | const { | ||||||
|  |   HOST, | ||||||
|  |   PORT, | ||||||
|  |   KEY_LENGTH, | ||||||
|  |   MAX_LENGTH, | ||||||
|  |   STATIC_MAX_AGE, | ||||||
|  |   RECOMPRESS_STATIC_ASSETS, | ||||||
|  |   STORAGE_TYPE, | ||||||
|  |   STORAGE_HOST, | ||||||
|  |   STORAGE_PORT, | ||||||
|  |   STORAGE_EXPIRE_SECONDS, | ||||||
|  |   STORAGE_DB, | ||||||
|  |   STORAGE_AWS_BUCKET, | ||||||
|  |   STORAGE_AWS_REGION, | ||||||
|  |   STORAGE_PASSWORD, | ||||||
|  |   STORAGE_USERNAME, | ||||||
|  |   STORAGE_FILEPATH, | ||||||
|  |   LOGGING_LEVEL, | ||||||
|  |   LOGGING_TYPE, | ||||||
|  |   LOGGING_COLORIZE, | ||||||
|  |   KEYGENERATOR_TYPE, | ||||||
|  |   KEY_GENERATOR_KEYSPACE, | ||||||
|  |   RATE_LIMITS_NORMAL_TOTAL_REQUESTS, | ||||||
|  |   RATE_LIMITS_NORMAL_EVERY_MILLISECONDS, | ||||||
|  |   RATE_LIMITS_WHITELIST_TOTAL_REQUESTS, | ||||||
|  |   RATE_LIMITS_WHITELIST_EVERY_MILLISECONDS, | ||||||
|  |   RATE_LIMITS_WHITELIST, | ||||||
|  |   RATE_LIMITS_BLACKLIST_TOTAL_REQUESTS, | ||||||
|  |   RATE_LIMITS_BLACKLIST_EVERY_MILLISECONDS, | ||||||
|  |   RATE_LIMITS_BLACKLIST, | ||||||
|  |   DOCUMENTS, | ||||||
|  | } = process.env; | ||||||
|  |  | ||||||
|  | const config = { | ||||||
|  |   host: HOST, | ||||||
|  |   port: PORT, | ||||||
|  |  | ||||||
|  |   keyLength: KEY_LENGTH, | ||||||
|  |  | ||||||
|  |   maxLength: MAX_LENGTH, | ||||||
|  |  | ||||||
|  |   staticMaxAge: STATIC_MAX_AGE, | ||||||
|  |  | ||||||
|  |   recompressStaticAssets: RECOMPRESS_STATIC_ASSETS, | ||||||
|  |  | ||||||
|  |   logging: [ | ||||||
|  |     { | ||||||
|  |       level: LOGGING_LEVEL, | ||||||
|  |       type: LOGGING_TYPE, | ||||||
|  |       colorize: LOGGING_COLORIZE, | ||||||
|  |     }, | ||||||
|  |   ], | ||||||
|  |  | ||||||
|  |   keyGenerator: { | ||||||
|  |     type: KEYGENERATOR_TYPE, | ||||||
|  |     keyspace: KEY_GENERATOR_KEYSPACE, | ||||||
|  |   }, | ||||||
|  |  | ||||||
|  |   rateLimits: { | ||||||
|  |     whitelist: RATE_LIMITS_WHITELIST ? RATE_LIMITS_WHITELIST.split(",") : [], | ||||||
|  |     blacklist: RATE_LIMITS_BLACKLIST ? RATE_LIMITS_BLACKLIST.split(",") : [], | ||||||
|  |     categories: { | ||||||
|  |       normal: { | ||||||
|  |         totalRequests: RATE_LIMITS_NORMAL_TOTAL_REQUESTS, | ||||||
|  |         every: RATE_LIMITS_NORMAL_EVERY_MILLISECONDS, | ||||||
|  |       }, | ||||||
|  |       whitelist: | ||||||
|  |         RATE_LIMITS_WHITELIST_EVERY_MILLISECONDS || | ||||||
|  |         RATE_LIMITS_WHITELIST_TOTAL_REQUESTS | ||||||
|  |           ? { | ||||||
|  |               totalRequests: RATE_LIMITS_WHITELIST_TOTAL_REQUESTS, | ||||||
|  |               every: RATE_LIMITS_WHITELIST_EVERY_MILLISECONDS, | ||||||
|  |             } | ||||||
|  |           : null, | ||||||
|  |       blacklist: | ||||||
|  |         RATE_LIMITS_BLACKLIST_EVERY_MILLISECONDS || | ||||||
|  |         RATE_LIMITS_BLACKLIST_TOTAL_REQUESTS | ||||||
|  |           ? { | ||||||
|  |               totalRequests: RATE_LIMITS_WHITELIST_TOTAL_REQUESTS, | ||||||
|  |               every: RATE_LIMITS_BLACKLIST_EVERY_MILLISECONDS, | ||||||
|  |             } | ||||||
|  |           : null, | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |  | ||||||
|  |   storage: { | ||||||
|  |     type: STORAGE_TYPE, | ||||||
|  |     host: STORAGE_HOST, | ||||||
|  |     port: STORAGE_PORT, | ||||||
|  |     expire: STORAGE_EXPIRE_SECONDS, | ||||||
|  |     bucket: STORAGE_AWS_BUCKET, | ||||||
|  |     region: STORAGE_AWS_REGION, | ||||||
|  |     connectionUrl: `postgres://${STORAGE_USERNAME}:${STORAGE_PASSWORD}@${STORAGE_HOST}:${STORAGE_PORT}/${STORAGE_DB}`, | ||||||
|  |     db: STORAGE_DB, | ||||||
|  |     user: STORAGE_USERNAME, | ||||||
|  |     password: STORAGE_PASSWORD, | ||||||
|  |     path: STORAGE_FILEPATH, | ||||||
|  |   }, | ||||||
|  |  | ||||||
|  |   documents: DOCUMENTS | ||||||
|  |     ? DOCUMENTS.split(",").reduce((acc, item) => { | ||||||
|  |         const keyAndValueArray = item.replace(/\s/g, "").split("="); | ||||||
|  |         return { ...acc, [keyAndValueArray[0]]: keyAndValueArray[1] }; | ||||||
|  |       }, {}) | ||||||
|  |     : null, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | console.log(JSON.stringify(config)); | ||||||
							
								
								
									
										9
									
								
								docker-entrypoint.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,9 @@ | |||||||
|  | #!/bin/bash | ||||||
|  |  | ||||||
|  | # We use this file to translate environmental variables to .env files used by the application | ||||||
|  |  | ||||||
|  | set -e | ||||||
|  |  | ||||||
|  | node ./docker-entrypoint.js > ./config.js | ||||||
|  |  | ||||||
|  | exec "$@" | ||||||
| @@ -1,4 +1,5 @@ | |||||||
| var winston = require('winston'); | var winston = require('winston'); | ||||||
|  | var Busboy = require('busboy'); | ||||||
|  |  | ||||||
| // For handling serving stored documents | // For handling serving stored documents | ||||||
|  |  | ||||||
| @@ -15,34 +16,56 @@ var DocumentHandler = function(options) { | |||||||
| DocumentHandler.defaultKeyLength = 10; | DocumentHandler.defaultKeyLength = 10; | ||||||
|  |  | ||||||
| // Handle retrieving a document | // Handle retrieving a document | ||||||
| DocumentHandler.prototype.handleGet = function(key, response, skipExpire) { | DocumentHandler.prototype.handleGet = function(request, response, config) { | ||||||
|  |   const key = request.params.id.split('.')[0]; | ||||||
|  |   const skipExpire = !!config.documents[key]; | ||||||
|  |  | ||||||
|   this.store.get(key, function(ret) { |   this.store.get(key, function(ret) { | ||||||
|     if (ret) { |     if (ret) { | ||||||
|       winston.verbose('retrieved document', { key: key }); |       winston.verbose('retrieved document', { key: key }); | ||||||
|       response.writeHead(200, { 'content-type': 'application/json' }); |       response.writeHead(200, { 'content-type': 'application/json' }); | ||||||
|  |       if (request.method === 'HEAD') { | ||||||
|  |         response.end(); | ||||||
|  |       } else { | ||||||
|         response.end(JSON.stringify({ data: ret, key: key })); |         response.end(JSON.stringify({ data: ret, key: key })); | ||||||
|       } |       } | ||||||
|  |     } | ||||||
|     else { |     else { | ||||||
|       winston.warn('document not found', { key: key }); |       winston.warn('document not found', { key: key }); | ||||||
|       response.writeHead(404, { 'content-type': 'application/json' }); |       response.writeHead(404, { 'content-type': 'application/json' }); | ||||||
|  |       if (request.method === 'HEAD') { | ||||||
|  |         response.end(); | ||||||
|  |       } else { | ||||||
|         response.end(JSON.stringify({ message: 'Document not found.' })); |         response.end(JSON.stringify({ message: 'Document not found.' })); | ||||||
|       } |       } | ||||||
|  |     } | ||||||
|   }, skipExpire); |   }, skipExpire); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // Handle retrieving the raw version of a document | // Handle retrieving the raw version of a document | ||||||
| DocumentHandler.prototype.handleRawGet = function(key, response, skipExpire) { | DocumentHandler.prototype.handleRawGet = function(request, response, config) { | ||||||
|  |   const key = request.params.id.split('.')[0]; | ||||||
|  |   const skipExpire = !!config.documents[key]; | ||||||
|  |  | ||||||
|   this.store.get(key, function(ret) { |   this.store.get(key, function(ret) { | ||||||
|     if (ret) { |     if (ret) { | ||||||
|       winston.verbose('retrieved raw document', { key: key }); |       winston.verbose('retrieved raw document', { key: key }); | ||||||
|       response.writeHead(200, { 'content-type': 'text/plain' }); |       response.writeHead(200, { 'content-type': 'text/plain; charset=UTF-8' }); | ||||||
|  |       if (request.method === 'HEAD') { | ||||||
|  |         response.end(); | ||||||
|  |       } else { | ||||||
|         response.end(ret); |         response.end(ret); | ||||||
|       } |       } | ||||||
|  |     } | ||||||
|     else { |     else { | ||||||
|       winston.warn('raw document not found', { key: key }); |       winston.warn('raw document not found', { key: key }); | ||||||
|       response.writeHead(404, { 'content-type': 'application/json' }); |       response.writeHead(404, { 'content-type': 'application/json' }); | ||||||
|  |       if (request.method === 'HEAD') { | ||||||
|  |         response.end(); | ||||||
|  |       } else { | ||||||
|         response.end(JSON.stringify({ message: 'Document not found.' })); |         response.end(JSON.stringify({ message: 'Document not found.' })); | ||||||
|       } |       } | ||||||
|  |     } | ||||||
|   }, skipExpire); |   }, skipExpire); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -51,11 +74,10 @@ DocumentHandler.prototype.handlePost = function(request, response) { | |||||||
|   var _this = this; |   var _this = this; | ||||||
|   var buffer = ''; |   var buffer = ''; | ||||||
|   var cancelled = false; |   var cancelled = false; | ||||||
|   request.on('data', function(data) { |  | ||||||
|     if (!buffer) { |   // What to do when done | ||||||
|       response.writeHead(200, { 'content-type': 'application/json' }); |   var onSuccess = function () { | ||||||
|     } |     // Check length | ||||||
|     buffer += data.toString(); |  | ||||||
|     if (_this.maxLength && buffer.length > _this.maxLength) { |     if (_this.maxLength && buffer.length > _this.maxLength) { | ||||||
|       cancelled = true; |       cancelled = true; | ||||||
|       winston.warn('document >maxLength', { maxLength: _this.maxLength }); |       winston.warn('document >maxLength', { maxLength: _this.maxLength }); | ||||||
| @@ -63,14 +85,14 @@ DocumentHandler.prototype.handlePost = function(request, response) { | |||||||
|       response.end( |       response.end( | ||||||
|         JSON.stringify({ message: 'Document exceeds maximum length.' }) |         JSON.stringify({ message: 'Document exceeds maximum length.' }) | ||||||
|       ); |       ); | ||||||
|  |       return; | ||||||
|     } |     } | ||||||
|   }); |     // And then save if we should | ||||||
|   request.on('end', function(end) { |  | ||||||
|     if (cancelled) return; |  | ||||||
|     _this.chooseKey(function (key) { |     _this.chooseKey(function (key) { | ||||||
|       _this.store.set(key, buffer, function (res) { |       _this.store.set(key, buffer, function (res) { | ||||||
|         if (res) { |         if (res) { | ||||||
|           winston.verbose('added document', { key: key }); |           winston.verbose('added document', { key: key }); | ||||||
|  |           response.writeHead(200, { 'content-type': 'application/json' }); | ||||||
|           response.end(JSON.stringify({ key: key })); |           response.end(JSON.stringify({ key: key })); | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
| @@ -80,12 +102,37 @@ DocumentHandler.prototype.handlePost = function(request, response) { | |||||||
|         } |         } | ||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   // If we should, parse a form to grab the data | ||||||
|  |   var ct = request.headers['content-type']; | ||||||
|  |   if (ct && ct.split(';')[0] === 'multipart/form-data') { | ||||||
|  |     var busboy = new Busboy({ headers: request.headers }); | ||||||
|  |     busboy.on('field', function (fieldname, val) { | ||||||
|  |       if (fieldname === 'data') { | ||||||
|  |         buffer = val; | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |     busboy.on('finish', function () { | ||||||
|  |       onSuccess(); | ||||||
|  |     }); | ||||||
|  |     request.pipe(busboy); | ||||||
|  |   // Otherwise, use our own and just grab flat data from POST body | ||||||
|  |   } else { | ||||||
|  |     request.on('data', function (data) { | ||||||
|  |       buffer += data.toString(); | ||||||
|  |     }); | ||||||
|  |     request.on('end', function () { | ||||||
|  |       if (cancelled) { return; } | ||||||
|  |       onSuccess(); | ||||||
|     }); |     }); | ||||||
|     request.on('error', function (error) { |     request.on('error', function (error) { | ||||||
|       winston.error('connection error: ' + error.message); |       winston.error('connection error: ' + error.message); | ||||||
|       response.writeHead(500, { 'content-type': 'application/json' }); |       response.writeHead(500, { 'content-type': 'application/json' }); | ||||||
|       response.end(JSON.stringify({ message: 'Connection error.' })); |       response.end(JSON.stringify({ message: 'Connection error.' })); | ||||||
|  |       cancelled = true; | ||||||
|     }); |     }); | ||||||
|  |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // Keep choosing keys until one isn't taken | // Keep choosing keys until one isn't taken | ||||||
| @@ -98,7 +145,7 @@ DocumentHandler.prototype.chooseKey = function(callback) { | |||||||
|     } else { |     } else { | ||||||
|       callback(key); |       callback(key); | ||||||
|     } |     } | ||||||
|   }); |   }, true); // Don't bump expirations when key searching | ||||||
| }; | }; | ||||||
|  |  | ||||||
| DocumentHandler.prototype.acceptableKey = function() { | DocumentHandler.prototype.acceptableKey = function() { | ||||||
|   | |||||||
							
								
								
									
										56
									
								
								lib/document_stores/amazon-s3.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,56 @@ | |||||||
|  | /*global require,module,process*/ | ||||||
|  |  | ||||||
|  | var AWS = require('aws-sdk'); | ||||||
|  | var winston = require('winston'); | ||||||
|  |  | ||||||
|  | var AmazonS3DocumentStore = function(options) { | ||||||
|  |   this.expire = options.expire; | ||||||
|  |   this.bucket = options.bucket; | ||||||
|  |   this.client = new AWS.S3({region: options.region}); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | AmazonS3DocumentStore.prototype.get = function(key, callback, skipExpire) { | ||||||
|  |   var _this = this; | ||||||
|  |  | ||||||
|  |   var req = { | ||||||
|  |     Bucket: _this.bucket, | ||||||
|  |     Key: key | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   _this.client.getObject(req, function(err, data) { | ||||||
|  |     if(err) { | ||||||
|  |       callback(false); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       callback(data.Body.toString('utf-8')); | ||||||
|  |       if (_this.expire && !skipExpire) { | ||||||
|  |         winston.warn('amazon s3 store cannot set expirations on keys'); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AmazonS3DocumentStore.prototype.set = function(key, data, callback, skipExpire) { | ||||||
|  |   var _this = this; | ||||||
|  |  | ||||||
|  |   var req = { | ||||||
|  |     Bucket: _this.bucket, | ||||||
|  |     Key: key, | ||||||
|  |     Body: data, | ||||||
|  |     ContentType: 'text/plain' | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   _this.client.putObject(req, function(err, data) { | ||||||
|  |     if (err) { | ||||||
|  |       callback(false); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       callback(true); | ||||||
|  |       if (_this.expire && !skipExpire) { | ||||||
|  |         winston.warn('amazon s3 store cannot set expirations on keys'); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module.exports = AmazonS3DocumentStore; | ||||||
							
								
								
									
										89
									
								
								lib/document_stores/google-datastore.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,89 @@ | |||||||
|  | /*global require,module,process*/ | ||||||
|  |  | ||||||
|  | const Datastore = require('@google-cloud/datastore'); | ||||||
|  | const winston = require('winston'); | ||||||
|  |  | ||||||
|  | class GoogleDatastoreDocumentStore { | ||||||
|  |  | ||||||
|  |   // Create a new store with options | ||||||
|  |   constructor(options) { | ||||||
|  |     this.kind = "Haste"; | ||||||
|  |     this.expire = options.expire; | ||||||
|  |     this.datastore = new Datastore(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Save file in a key | ||||||
|  |   set(key, data, callback, skipExpire) { | ||||||
|  |     var expireTime = (skipExpire || this.expire === undefined) ? null : new Date(Date.now() + this.expire * 1000); | ||||||
|  |  | ||||||
|  |     var taskKey = this.datastore.key([this.kind, key]) | ||||||
|  |     var task = { | ||||||
|  |       key: taskKey, | ||||||
|  |       data: [ | ||||||
|  |         { | ||||||
|  |           name: 'value', | ||||||
|  |           value: data, | ||||||
|  |           excludeFromIndexes: true | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           name: 'expiration', | ||||||
|  |           value: expireTime | ||||||
|  |         } | ||||||
|  |       ] | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     this.datastore.insert(task).then(() => { | ||||||
|  |       callback(true); | ||||||
|  |     }) | ||||||
|  |     .catch(err => { | ||||||
|  |       callback(false); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Get a file from a key | ||||||
|  |   get(key, callback, skipExpire) { | ||||||
|  |     var taskKey = this.datastore.key([this.kind, key]) | ||||||
|  |  | ||||||
|  |     this.datastore.get(taskKey).then((entity) => { | ||||||
|  |       if (skipExpire || entity[0]["expiration"] == null) { | ||||||
|  |         callback(entity[0]["value"]); | ||||||
|  |       } | ||||||
|  |       else { | ||||||
|  |         // check for expiry | ||||||
|  |         if (entity[0]["expiration"] < new Date()) { | ||||||
|  |           winston.info("document expired", {key: key, expiration: entity[0]["expiration"], check: new Date(null)}); | ||||||
|  |           callback(false); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |           // update expiry | ||||||
|  |           var task = { | ||||||
|  |             key: taskKey, | ||||||
|  |             data: [ | ||||||
|  |               { | ||||||
|  |                 name: 'value', | ||||||
|  |                 value: entity[0]["value"], | ||||||
|  |                 excludeFromIndexes: true | ||||||
|  |               }, | ||||||
|  |               { | ||||||
|  |                 name: 'expiration', | ||||||
|  |                 value: new Date(Date.now() + this.expire * 1000) | ||||||
|  |               } | ||||||
|  |             ] | ||||||
|  |           }; | ||||||
|  |           this.datastore.update(task).then(() => { | ||||||
|  |           }) | ||||||
|  |           .catch(err => { | ||||||
|  |             winston.error("failed to update expiration", {error: err}); | ||||||
|  |           }); | ||||||
|  |           callback(entity[0]["value"]); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }) | ||||||
|  |     .catch(err => { | ||||||
|  |         winston.error("Error retrieving value from Google Datastore", {error: err}); | ||||||
|  |         callback(false); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module.exports = GoogleDatastoreDocumentStore; | ||||||
| @@ -1,45 +1,54 @@ | |||||||
| var memcached = require('memcache'); | const memcached = require('memcached'); | ||||||
| var winston = require('winston'); | const winston = require('winston'); | ||||||
|  |  | ||||||
|  | class MemcachedDocumentStore { | ||||||
|  |  | ||||||
|   // Create a new store with options |   // Create a new store with options | ||||||
| var MemcachedDocumentStore = function(options) { |   constructor(options) { | ||||||
|     this.expire = options.expire; |     this.expire = options.expire; | ||||||
|   if (!MemcachedDocumentStore.client) { |  | ||||||
|     MemcachedDocumentStore.connect(options); |     const host = options.host || '127.0.0.1'; | ||||||
|  |     const port = options.port || 11211; | ||||||
|  |     const url = `${host}:${port}`; | ||||||
|  |     this.connect(url); | ||||||
|   } |   } | ||||||
| }; |  | ||||||
|  |  | ||||||
|   // Create a connection |   // Create a connection | ||||||
| MemcachedDocumentStore.connect = function(options) { |   connect(url) { | ||||||
|   var host = options.host || '127.0.0.1'; |     this.client = new memcached(url); | ||||||
|   var port = options.port || 11211; |  | ||||||
|   this.client = new memcached.Client(port, host); |     winston.info(`connecting to memcached on ${url}`); | ||||||
|   this.client.connect(); |  | ||||||
|   this.client.on('connect', function() { |     this.client.on('failure', function(error) { | ||||||
|     winston.info('connected to memcached on ' + host + ':' + port); |       winston.info('error connecting to memcached', {error}); | ||||||
|     }); |     }); | ||||||
|   this.client.on('error', function(e) { |   } | ||||||
|     winston.info('error connecting to memcached', { error: e }); |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
|   // Save file in a key |   // Save file in a key | ||||||
| MemcachedDocumentStore.prototype.set = |   set(key, data, callback, skipExpire) { | ||||||
| function(key, data, callback, skipExpire) { |     this.client.set(key, data, skipExpire ? 0 : this.expire || 0, (error) => { | ||||||
|   MemcachedDocumentStore.client.set(key, data, function(err, reply) { |       callback(!error); | ||||||
|     err ? callback(false) : callback(true); |     }); | ||||||
|   }, skipExpire ? 0 : this.expire); |   } | ||||||
| }; |  | ||||||
|  |  | ||||||
|   // Get a file from a key |   // Get a file from a key | ||||||
| MemcachedDocumentStore.prototype.get = function(key, callback, skipExpire) { |   get(key, callback, skipExpire) { | ||||||
|   var _this = this; |     this.client.get(key, (error, data) => { | ||||||
|   MemcachedDocumentStore.client.get(key, function(err, reply) { |       const value = error ? false : data; | ||||||
|     callback(err ? false : reply); |  | ||||||
|     if (_this.expire && !skipExpire) { |       callback(value); | ||||||
|       winston.warn('store does not currently push forward expirations on GET'); |  | ||||||
|  |       // Update the key so that the expiration is pushed forward | ||||||
|  |       if (value && !skipExpire) { | ||||||
|  |         this.set(key, data, (updateSucceeded) => { | ||||||
|  |           if (!updateSucceeded) { | ||||||
|  |             winston.error('failed to update expiration on GET', {key}); | ||||||
|  |           } | ||||||
|  |         }, skipExpire); | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
| }; |   } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
| module.exports = MemcachedDocumentStore; | module.exports = MemcachedDocumentStore; | ||||||
|   | |||||||
							
								
								
									
										88
									
								
								lib/document_stores/mongo.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,88 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
|  | var MongoClient = require('mongodb').MongoClient, | ||||||
|  |     winston = require('winston'); | ||||||
|  |  | ||||||
|  | var MongoDocumentStore = function (options) { | ||||||
|  |     this.expire = options.expire; | ||||||
|  |     this.connectionUrl = process.env.DATABASE_URl || options.connectionUrl; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | MongoDocumentStore.prototype.set = function (key, data, callback, skipExpire) { | ||||||
|  |     var now = Math.floor(new Date().getTime() / 1000), | ||||||
|  |         that = this; | ||||||
|  |  | ||||||
|  |     this.safeConnect(function (err, db) { | ||||||
|  |         if (err) | ||||||
|  |             return callback(false); | ||||||
|  |          | ||||||
|  |         db.collection('entries').update({ | ||||||
|  |             'entry_id': key, | ||||||
|  |             $or: [ | ||||||
|  |                 { expiration: -1 }, | ||||||
|  |                 { expiration: { $gt: now } } | ||||||
|  |             ] | ||||||
|  |         }, { | ||||||
|  |             'entry_id': key, | ||||||
|  |             'value': data, | ||||||
|  |             'expiration': that.expire && !skipExpire ? that.expire + now : -1 | ||||||
|  |         }, { | ||||||
|  |             upsert: true | ||||||
|  |         }, function (err, existing) { | ||||||
|  |             if (err) { | ||||||
|  |                 winston.error('error persisting value to mongodb', { error: err }); | ||||||
|  |                 return callback(false); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             callback(true); | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | MongoDocumentStore.prototype.get = function (key, callback, skipExpire) { | ||||||
|  |     var now = Math.floor(new Date().getTime() / 1000), | ||||||
|  |         that = this; | ||||||
|  |  | ||||||
|  |     this.safeConnect(function (err, db) { | ||||||
|  |         if (err) | ||||||
|  |             return callback(false); | ||||||
|  |          | ||||||
|  |         db.collection('entries').findOne({ | ||||||
|  |             'entry_id': key, | ||||||
|  |             $or: [ | ||||||
|  |                 { expiration: -1 }, | ||||||
|  |                 { expiration: { $gt: now } } | ||||||
|  |             ] | ||||||
|  |         }, function (err, entry) { | ||||||
|  |             if (err) { | ||||||
|  |                 winston.error('error persisting value to mongodb', { error: err }); | ||||||
|  |                 return callback(false); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             callback(entry === null ? false : entry.value); | ||||||
|  |  | ||||||
|  |             if (entry !== null && entry.expiration !== -1 && that.expire && !skipExpire) { | ||||||
|  |                 db.collection('entries').update({ | ||||||
|  |                     'entry_id': key | ||||||
|  |                 }, { | ||||||
|  |                     $set: { | ||||||
|  |                         'expiration': that.expire + now | ||||||
|  |                     } | ||||||
|  |                 }, function (err, result) { }); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | MongoDocumentStore.prototype.safeConnect = function (callback) { | ||||||
|  |     MongoClient.connect(this.connectionUrl, function (err, db) { | ||||||
|  |         if (err) { | ||||||
|  |             winston.error('error connecting to mongodb', { error: err }); | ||||||
|  |             callback(err); | ||||||
|  |         } else { | ||||||
|  |             callback(undefined, db); | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | module.exports = MongoDocumentStore; | ||||||
							
								
								
									
										80
									
								
								lib/document_stores/postgres.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,80 @@ | |||||||
|  | /*global require,module,process*/ | ||||||
|  |  | ||||||
|  | var winston = require('winston'); | ||||||
|  | const {Pool} = require('pg'); | ||||||
|  |  | ||||||
|  | // create table entries (id serial primary key, key varchar(255) not null, value text not null, expiration int, unique(key)); | ||||||
|  |  | ||||||
|  | // A postgres document store | ||||||
|  | var PostgresDocumentStore = function (options) { | ||||||
|  |   this.expireJS = options.expire; | ||||||
|  |  | ||||||
|  |   const connectionString = process.env.DATABASE_URL || options.connectionUrl; | ||||||
|  |   this.pool = new Pool({connectionString}); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | PostgresDocumentStore.prototype = { | ||||||
|  |  | ||||||
|  |   // Set a given key | ||||||
|  |   set: function (key, data, callback, skipExpire) { | ||||||
|  |     var now = Math.floor(new Date().getTime() / 1000); | ||||||
|  |     var that = this; | ||||||
|  |     this.safeConnect(function (err, client, done) { | ||||||
|  |       if (err) { return callback(false); } | ||||||
|  |       client.query('INSERT INTO entries (key, value, expiration) VALUES ($1, $2, $3)', [ | ||||||
|  |         key, | ||||||
|  |         data, | ||||||
|  |         that.expireJS && !skipExpire ? that.expireJS + now : null | ||||||
|  |       ], function (err) { | ||||||
|  |         if (err) { | ||||||
|  |           winston.error('error persisting value to postgres', { error: err }); | ||||||
|  |           return callback(false); | ||||||
|  |         } | ||||||
|  |         callback(true); | ||||||
|  |         done(); | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  |   }, | ||||||
|  |  | ||||||
|  |   // Get a given key's data | ||||||
|  |   get: function (key, callback, skipExpire) { | ||||||
|  |     var now = Math.floor(new Date().getTime() / 1000); | ||||||
|  |     var that = this; | ||||||
|  |     this.safeConnect(function (err, client, done) { | ||||||
|  |       if (err) { return callback(false); } | ||||||
|  |       client.query('SELECT id,value,expiration from entries where KEY = $1 and (expiration IS NULL or expiration > $2)', [key, now], function (err, result) { | ||||||
|  |         if (err) { | ||||||
|  |           winston.error('error retrieving value from postgres', { error: err }); | ||||||
|  |           return callback(false); | ||||||
|  |         } | ||||||
|  |         callback(result.rows.length ? result.rows[0].value : false); | ||||||
|  |         if (result.rows.length && that.expireJS && !skipExpire) { | ||||||
|  |           client.query('UPDATE entries SET expiration = $1 WHERE ID = $2', [ | ||||||
|  |             that.expireJS + now, | ||||||
|  |             result.rows[0].id | ||||||
|  |           ], function (err) { | ||||||
|  |             if (!err) { | ||||||
|  |               done(); | ||||||
|  |             } | ||||||
|  |           }); | ||||||
|  |         } else { | ||||||
|  |           done(); | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  |   }, | ||||||
|  |  | ||||||
|  |   // A connection wrapper | ||||||
|  |   safeConnect: function (callback) { | ||||||
|  |     this.pool.connect((error, client, done) => { | ||||||
|  |       if (error) { | ||||||
|  |         winston.error('error connecting to postgres', {error}); | ||||||
|  |         callback(error); | ||||||
|  |       } else { | ||||||
|  |         callback(undefined, client, done); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | module.exports = PostgresDocumentStore; | ||||||
| @@ -8,9 +8,13 @@ var winston = require('winston'); | |||||||
| // options[db] - The db to use (default 0) | // options[db] - The db to use (default 0) | ||||||
| // options[expire] - The time to live for each key set (default never) | // options[expire] - The time to live for each key set (default never) | ||||||
|  |  | ||||||
| var RedisDocumentStore = function(options) { | var RedisDocumentStore = function(options, client) { | ||||||
|   this.expire = options.expire; |   this.expire = options.expire; | ||||||
|   if (!RedisDocumentStore.client) { |   if (client) { | ||||||
|  |     winston.info('using predefined redis client'); | ||||||
|  |     RedisDocumentStore.client = client; | ||||||
|  |   } else if (!RedisDocumentStore.client) { | ||||||
|  |     winston.info('configuring redis'); | ||||||
|     RedisDocumentStore.connect(options); |     RedisDocumentStore.connect(options); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| @@ -21,11 +25,20 @@ RedisDocumentStore.connect = function(options) { | |||||||
|   var port = options.port || 6379; |   var port = options.port || 6379; | ||||||
|   var index = options.db || 0; |   var index = options.db || 0; | ||||||
|   RedisDocumentStore.client = redis.createClient(port, host); |   RedisDocumentStore.client = redis.createClient(port, host); | ||||||
|   RedisDocumentStore.client.select(index, function(err, reply) { |   // authenticate if password is provided | ||||||
|  |   if (options.password) { | ||||||
|  |     RedisDocumentStore.client.auth(options.password); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   RedisDocumentStore.client.on('error', function(err) { | ||||||
|  |     winston.error('redis disconnected', err); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   RedisDocumentStore.client.select(index, function(err) { | ||||||
|     if (err) { |     if (err) { | ||||||
|       winston.error( |       winston.error( | ||||||
|         'error connecting to redis index ' + index, |         'error connecting to redis index ' + index, | ||||||
|         { error: err.message } |         { error: err } | ||||||
|       ); |       ); | ||||||
|       process.exit(1); |       process.exit(1); | ||||||
|     } |     } | ||||||
| @@ -38,7 +51,7 @@ RedisDocumentStore.connect = function(options) { | |||||||
| // Save file in a key | // Save file in a key | ||||||
| RedisDocumentStore.prototype.set = function(key, data, callback, skipExpire) { | RedisDocumentStore.prototype.set = function(key, data, callback, skipExpire) { | ||||||
|   var _this = this; |   var _this = this; | ||||||
|   RedisDocumentStore.client.set(key, data, function(err, reply) { |   RedisDocumentStore.client.set(key, data, function(err) { | ||||||
|     if (err) { |     if (err) { | ||||||
|       callback(false); |       callback(false); | ||||||
|     } |     } | ||||||
| @@ -54,7 +67,7 @@ RedisDocumentStore.prototype.set = function(key, data, callback, skipExpire) { | |||||||
| // Expire a key in expire time if set | // Expire a key in expire time if set | ||||||
| RedisDocumentStore.prototype.setExpiration = function(key) { | RedisDocumentStore.prototype.setExpiration = function(key) { | ||||||
|   if (this.expire) { |   if (this.expire) { | ||||||
|     RedisDocumentStore.client.expire(key, this.expire, function(err, reply) { |     RedisDocumentStore.client.expire(key, this.expire, function(err) { | ||||||
|       if (err) { |       if (err) { | ||||||
|         winston.error('failed to set expiry on key: ' + key); |         winston.error('failed to set expiry on key: ' + key); | ||||||
|       } |       } | ||||||
|   | |||||||
							
								
								
									
										46
									
								
								lib/document_stores/rethinkdb.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,46 @@ | |||||||
|  | const crypto = require('crypto'); | ||||||
|  | const rethink = require('rethinkdbdash'); | ||||||
|  | const winston = require('winston'); | ||||||
|  |  | ||||||
|  | const md5 = (str) => { | ||||||
|  |   const md5sum = crypto.createHash('md5'); | ||||||
|  |   md5sum.update(str); | ||||||
|  |   return md5sum.digest('hex'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | class RethinkDBStore { | ||||||
|  |   constructor(options) { | ||||||
|  |     this.client = rethink({ | ||||||
|  |       silent: true, | ||||||
|  |       host: options.host || '127.0.0.1', | ||||||
|  |       port: options.port || 28015, | ||||||
|  |       db: options.db || 'haste', | ||||||
|  |       user: options.user || 'admin', | ||||||
|  |       password: options.password || '' | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   set(key, data, callback) { | ||||||
|  |     this.client.table('uploads').insert({ id: md5(key), data: data }).run((error) => { | ||||||
|  |       if (error) { | ||||||
|  |         callback(false); | ||||||
|  |         winston.error('failed to insert to table', error); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       callback(true); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   get(key, callback) { | ||||||
|  |     this.client.table('uploads').get(md5(key)).run((error, result) => { | ||||||
|  |       if (error || !result) { | ||||||
|  |         callback(false); | ||||||
|  |         if (error) winston.error('failed to insert to table', error); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       callback(result.data); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module.exports = RethinkDBStore; | ||||||
							
								
								
									
										32
									
								
								lib/key_generators/dictionary.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,32 @@ | |||||||
|  | const fs = require('fs'); | ||||||
|  |  | ||||||
|  | module.exports = class DictionaryGenerator { | ||||||
|  |  | ||||||
|  |   constructor(options, readyCallback) { | ||||||
|  |     // Check options format | ||||||
|  |     if (!options)      throw Error('No options passed to generator'); | ||||||
|  |     if (!options.path) throw Error('No dictionary path specified in options'); | ||||||
|  |  | ||||||
|  |     // Load dictionary | ||||||
|  |     fs.readFile(options.path, 'utf8', (err, data) => { | ||||||
|  |       if (err) throw err; | ||||||
|  |  | ||||||
|  |       this.dictionary = data.split(/[\n\r]+/); | ||||||
|  |  | ||||||
|  |       if (readyCallback) readyCallback(); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Generates a dictionary-based key, of keyLength words | ||||||
|  |   createKey(keyLength) { | ||||||
|  |     let text = ''; | ||||||
|  |  | ||||||
|  |     for (let i = 0; i < keyLength; i++) { | ||||||
|  |       const index = Math.floor(Math.random() * this.dictionary.length); | ||||||
|  |       text += this.dictionary[index]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return text; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | }; | ||||||
| @@ -1,32 +1,27 @@ | |||||||
| // Draws inspiration from pwgen and http://tools.arantius.com/password | // Draws inspiration from pwgen and http://tools.arantius.com/password | ||||||
| var PhoneticKeyGenerator = function(options) { |  | ||||||
|   // No options | const randOf = (collection) => { | ||||||
|  |   return () => { | ||||||
|  |     return collection[Math.floor(Math.random() * collection.length)]; | ||||||
|  |   }; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // Generate a phonetic key | // Helper methods to get an random vowel or consonant | ||||||
| PhoneticKeyGenerator.prototype.createKey = function(keyLength) { | const randVowel = randOf('aeiou'); | ||||||
|   var text = ''; | const randConsonant = randOf('bcdfghjklmnpqrstvwxyz'); | ||||||
|   for (var i = 0; i < keyLength; i++) { |  | ||||||
|     text += (i % 2 == 0) ? this.randConsonant() : this.randVowel(); | module.exports = class PhoneticKeyGenerator { | ||||||
|  |  | ||||||
|  |   // Generate a phonetic key of alternating consonant & vowel | ||||||
|  |   createKey(keyLength) { | ||||||
|  |     let text = ''; | ||||||
|  |     const start = Math.round(Math.random()); | ||||||
|  |  | ||||||
|  |     for (let i = 0; i < keyLength; i++) { | ||||||
|  |       text += (i % 2 == start) ? randConsonant() : randVowel(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return text; |     return text; | ||||||
|  |   } | ||||||
|  |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| PhoneticKeyGenerator.consonants = 'bcdfghjklmnpqrstvwxy'; |  | ||||||
| PhoneticKeyGenerator.vowels = 'aeiou'; |  | ||||||
|  |  | ||||||
| // Get an random vowel |  | ||||||
| PhoneticKeyGenerator.prototype.randVowel = function() { |  | ||||||
|   return PhoneticKeyGenerator.vowels[ |  | ||||||
|     Math.floor(Math.random() * PhoneticKeyGenerator.vowels.length) |  | ||||||
|   ]; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| // Get an random consonant |  | ||||||
| PhoneticKeyGenerator.prototype.randConsonant = function() { |  | ||||||
|   return PhoneticKeyGenerator.consonants[ |  | ||||||
|     Math.floor(Math.random() * PhoneticKeyGenerator.consonants.length) |  | ||||||
|   ]; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| module.exports = PhoneticKeyGenerator; |  | ||||||
|   | |||||||
| @@ -1,19 +1,20 @@ | |||||||
| var RandomKeyGenerator = function(options) { | module.exports = class RandomKeyGenerator { | ||||||
|   if (!options) { |  | ||||||
|     options = {}; |  | ||||||
|   } |  | ||||||
|   this.keyspace = options.keyspace || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| // Generate a random key |   // Initialize a new generator with the given keySpace | ||||||
| RandomKeyGenerator.prototype.createKey = function(keyLength) { |   constructor(options = {}) { | ||||||
|  |     this.keyspace = options.keyspace || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Generate a key of the given length | ||||||
|  |   createKey(keyLength) { | ||||||
|     var text = ''; |     var text = ''; | ||||||
|   var index; |  | ||||||
|     for (var i = 0; i < keyLength; i++) { |     for (var i = 0; i < keyLength; i++) { | ||||||
|     index = Math.floor(Math.random() * this.keyspace.length); |       const index = Math.floor(Math.random() * this.keyspace.length); | ||||||
|       text += this.keyspace.charAt(index); |       text += this.keyspace.charAt(index); | ||||||
|     } |     } | ||||||
|   return text; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| module.exports = RandomKeyGenerator; |     return text; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | }; | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								node_modules/.bin/_mocha
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1 +0,0 @@ | |||||||
| ../mocha/bin/_mocha |  | ||||||
							
								
								
									
										1
									
								
								node_modules/.bin/mocha
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1 +0,0 @@ | |||||||
| ../mocha/bin/mocha |  | ||||||
							
								
								
									
										1
									
								
								node_modules/.bin/uglifyjs
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1 +0,0 @@ | |||||||
| ../uglify-js/bin/uglifyjs |  | ||||||
							
								
								
									
										11
									
								
								node_modules/connect/.npmignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,11 +0,0 @@ | |||||||
| *.markdown |  | ||||||
| *.md |  | ||||||
| .git* |  | ||||||
| Makefile |  | ||||||
| benchmarks/ |  | ||||||
| docs/ |  | ||||||
| examples/ |  | ||||||
| install.sh |  | ||||||
| support/ |  | ||||||
| test/ |  | ||||||
| .DS_Store |  | ||||||
							
								
								
									
										24
									
								
								node_modules/connect/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,24 +0,0 @@ | |||||||
| (The MIT License) |  | ||||||
|  |  | ||||||
| Copyright (c) 2010 Sencha Inc. |  | ||||||
| Copyright (c) 2011 LearnBoost |  | ||||||
| Copyright (c) 2011 TJ Holowaychuk |  | ||||||
|  |  | ||||||
| Permission is hereby granted, free of charge, to any person obtaining |  | ||||||
| a copy of this software and associated documentation files (the |  | ||||||
| 'Software'), to deal in the Software without restriction, including |  | ||||||
| without limitation the rights to use, copy, modify, merge, publish, |  | ||||||
| distribute, sublicense, and/or sell copies of the Software, and to |  | ||||||
| permit persons to whom the Software is furnished to do so, subject to |  | ||||||
| the following conditions: |  | ||||||
|  |  | ||||||
| The above copyright notice and this permission notice shall be |  | ||||||
| included in all copies or substantial portions of the Software. |  | ||||||
|  |  | ||||||
| THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, |  | ||||||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |  | ||||||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |  | ||||||
| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |  | ||||||
| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |  | ||||||
| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |  | ||||||
| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |  | ||||||
							
								
								
									
										2
									
								
								node_modules/connect/index.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,2 +0,0 @@ | |||||||
|  |  | ||||||
| module.exports = require('./lib/connect'); |  | ||||||
							
								
								
									
										81
									
								
								node_modules/connect/lib/cache.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,81 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - Cache |  | ||||||
|  * Copyright(c) 2011 Sencha Inc. |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Expose `Cache`. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| module.exports = Cache; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * LRU cache store. |  | ||||||
|  * |  | ||||||
|  * @param {Number} limit |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function Cache(limit) { |  | ||||||
|   this.store = {}; |  | ||||||
|   this.keys = []; |  | ||||||
|   this.limit = limit; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Touch `key`, promoting the object. |  | ||||||
|  * |  | ||||||
|  * @param {String} key |  | ||||||
|  * @param {Number} i |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Cache.prototype.touch = function(key, i){ |  | ||||||
|   this.keys.splice(i,1); |  | ||||||
|   this.keys.push(key); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Remove `key`. |  | ||||||
|  * |  | ||||||
|  * @param {String} key |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Cache.prototype.remove = function(key){ |  | ||||||
|   delete this.store[key]; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Get the object stored for `key`. |  | ||||||
|  * |  | ||||||
|  * @param {String} key |  | ||||||
|  * @return {Array} |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Cache.prototype.get = function(key){ |  | ||||||
|   return this.store[key]; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Add a cache `key`. |  | ||||||
|  * |  | ||||||
|  * @param {String} key |  | ||||||
|  * @return {Array} |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Cache.prototype.add = function(key){ |  | ||||||
|   // initialize store |  | ||||||
|   var len = this.keys.push(key); |  | ||||||
|  |  | ||||||
|   // limit reached, invalid LRU |  | ||||||
|   if (len > this.limit) this.remove(this.keys.shift()); |  | ||||||
|  |  | ||||||
|   var arr = this.store[key] = []; |  | ||||||
|   arr.createdAt = new Date; |  | ||||||
|   return arr; |  | ||||||
| }; |  | ||||||
							
								
								
									
										106
									
								
								node_modules/connect/lib/connect.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,106 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var HTTPServer = require('./http').Server |  | ||||||
|   , HTTPSServer = require('./https').Server |  | ||||||
|   , fs = require('fs'); |  | ||||||
|  |  | ||||||
| // node patches |  | ||||||
|  |  | ||||||
| require('./patch'); |  | ||||||
|  |  | ||||||
| // expose createServer() as the module |  | ||||||
|  |  | ||||||
| exports = module.exports = createServer; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Framework version. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports.version = '1.8.5'; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Initialize a new `connect.HTTPServer` with the middleware |  | ||||||
|  * passed to this function. When an object is passed _first_, |  | ||||||
|  * we assume these are the tls options, and return a `connect.HTTPSServer`. |  | ||||||
|  * |  | ||||||
|  * Examples: |  | ||||||
|  * |  | ||||||
|  * An example HTTP server, accepting several middleware. |  | ||||||
|  * |  | ||||||
|  *     var server = connect.createServer( |  | ||||||
|  *         connect.logger() |  | ||||||
|  *       , connect.static(__dirname + '/public') |  | ||||||
|  *     ); |  | ||||||
|  * |  | ||||||
|  * An HTTPS server, utilizing the same middleware as above. |  | ||||||
|  * |  | ||||||
|  *     var server = connect.createServer( |  | ||||||
|  *         { key: key, cert: cert } |  | ||||||
|  *       , connect.logger() |  | ||||||
|  *       , connect.static(__dirname + '/public') |  | ||||||
|  *     ); |  | ||||||
|  * |  | ||||||
|  * Alternatively with connect 1.0 we may omit `createServer()`. |  | ||||||
|  * |  | ||||||
|  *     connect( |  | ||||||
|  *         connect.logger() |  | ||||||
|  *       , connect.static(__dirname + '/public') |  | ||||||
|  *     ).listen(3000); |  | ||||||
|  * |  | ||||||
|  * @param  {Object|Function} ... |  | ||||||
|  * @return {Server} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function createServer() { |  | ||||||
|   if ('object' == typeof arguments[0]) { |  | ||||||
|     return new HTTPSServer(arguments[0], Array.prototype.slice.call(arguments, 1)); |  | ||||||
|   } else { |  | ||||||
|     return new HTTPServer(Array.prototype.slice.call(arguments)); |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| // support connect.createServer() |  | ||||||
|  |  | ||||||
| exports.createServer = createServer; |  | ||||||
|  |  | ||||||
| // auto-load getters |  | ||||||
|  |  | ||||||
| exports.middleware = {}; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Auto-load bundled middleware with getters. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| fs.readdirSync(__dirname + '/middleware').forEach(function(filename){ |  | ||||||
|   if (/\.js$/.test(filename)) { |  | ||||||
|     var name = filename.substr(0, filename.lastIndexOf('.')); |  | ||||||
|     exports.middleware.__defineGetter__(name, function(){ |  | ||||||
|       return require('./middleware/' + name); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // expose utils |  | ||||||
|  |  | ||||||
| exports.utils = require('./utils'); |  | ||||||
|  |  | ||||||
| // expose getters as first-class exports |  | ||||||
|  |  | ||||||
| exports.utils.merge(exports, exports.middleware); |  | ||||||
|  |  | ||||||
| // expose constructors |  | ||||||
|  |  | ||||||
| exports.HTTPServer = HTTPServer; |  | ||||||
| exports.HTTPSServer = HTTPSServer; |  | ||||||
|  |  | ||||||
							
								
								
									
										217
									
								
								node_modules/connect/lib/http.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,217 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - HTTPServer |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var http = require('http') |  | ||||||
|   , parse = require('url').parse |  | ||||||
|   , assert = require('assert'); |  | ||||||
|  |  | ||||||
| // environment |  | ||||||
|  |  | ||||||
| var env = process.env.NODE_ENV || 'development'; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Initialize a new `Server` with the given `middleware`. |  | ||||||
|  * |  | ||||||
|  * Examples: |  | ||||||
|  * |  | ||||||
|  *     var server = connect.createServer( |  | ||||||
|  *         connect.favicon() |  | ||||||
|  *       , connect.logger() |  | ||||||
|  *       , connect.static(__dirname + '/public') |  | ||||||
|  *     ); |  | ||||||
|  * |  | ||||||
|  * @params {Array} middleware  |  | ||||||
|  * @return {Server} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var Server = exports.Server = function HTTPServer(middleware) { |  | ||||||
|   this.stack = []; |  | ||||||
|   middleware.forEach(function(fn){ |  | ||||||
|     this.use(fn); |  | ||||||
|   }, this); |  | ||||||
|   http.Server.call(this, this.handle); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Inherit from `http.Server.prototype`. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Server.prototype.__proto__ = http.Server.prototype; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Utilize the given middleware `handle` to the given `route`, |  | ||||||
|  * defaulting to _/_. This "route" is the mount-point for the |  | ||||||
|  * middleware, when given a value other than _/_ the middleware |  | ||||||
|  * is only effective when that segment is present in the request's |  | ||||||
|  * pathname. |  | ||||||
|  * |  | ||||||
|  * For example if we were to mount a function at _/admin_, it would |  | ||||||
|  * be invoked on _/admin_, and _/admin/settings_, however it would |  | ||||||
|  * not be invoked for _/_, or _/posts_. |  | ||||||
|  * |  | ||||||
|  * This is effectively the same as passing middleware to `connect.createServer()`, |  | ||||||
|  * however provides a progressive api. |  | ||||||
|  * |  | ||||||
|  * Examples: |  | ||||||
|  * |  | ||||||
|  *      var server = connect.createServer(); |  | ||||||
|  *      server.use(connect.favicon()); |  | ||||||
|  *      server.use(connect.logger()); |  | ||||||
|  *      server.use(connect.static(__dirname + '/public')); |  | ||||||
|  * |  | ||||||
|  * If we wanted to prefix static files with _/public_, we could |  | ||||||
|  * "mount" the `static()` middleware: |  | ||||||
|  * |  | ||||||
|  *      server.use('/public', connect.static(__dirname + '/public')); |  | ||||||
|  * |  | ||||||
|  * This api is chainable, meaning the following is valid: |  | ||||||
|  * |  | ||||||
|  *      connect.createServer() |  | ||||||
|  *        .use(connect.favicon()) |  | ||||||
|  *        .use(connect.logger()) |  | ||||||
|  *        .use(connect.static(__dirname + '/public')) |  | ||||||
|  *        .listen(3000); |  | ||||||
|  * |  | ||||||
|  * @param {String|Function} route or handle |  | ||||||
|  * @param {Function} handle |  | ||||||
|  * @return {Server} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Server.prototype.use = function(route, handle){ |  | ||||||
|   this.route = '/'; |  | ||||||
|  |  | ||||||
|   // default route to '/' |  | ||||||
|   if ('string' != typeof route) { |  | ||||||
|     handle = route; |  | ||||||
|     route = '/'; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // wrap sub-apps |  | ||||||
|   if ('function' == typeof handle.handle) { |  | ||||||
|     var server = handle; |  | ||||||
|     server.route = route; |  | ||||||
|     handle = function(req, res, next) { |  | ||||||
|       server.handle(req, res, next); |  | ||||||
|     }; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // wrap vanilla http.Servers |  | ||||||
|   if (handle instanceof http.Server) { |  | ||||||
|     handle = handle.listeners('request')[0]; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // normalize route to not trail with slash |  | ||||||
|   if ('/' == route[route.length - 1]) { |  | ||||||
|     route = route.substr(0, route.length - 1); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // add the middleware |  | ||||||
|   this.stack.push({ route: route, handle: handle }); |  | ||||||
|  |  | ||||||
|   // allow chaining |  | ||||||
|   return this; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Handle server requests, punting them down |  | ||||||
|  * the middleware stack. |  | ||||||
|  * |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Server.prototype.handle = function(req, res, out) { |  | ||||||
|   var writeHead = res.writeHead |  | ||||||
|     , stack = this.stack |  | ||||||
|     , removed = '' |  | ||||||
|     , index = 0; |  | ||||||
|  |  | ||||||
|   function next(err) { |  | ||||||
|     var layer, path, c; |  | ||||||
|     req.url = removed + req.url; |  | ||||||
|     req.originalUrl = req.originalUrl || req.url; |  | ||||||
|     removed = ''; |  | ||||||
|  |  | ||||||
|     layer = stack[index++]; |  | ||||||
|  |  | ||||||
|     // all done |  | ||||||
|     if (!layer || res.headerSent) { |  | ||||||
|       // but wait! we have a parent |  | ||||||
|       if (out) return out(err); |  | ||||||
|  |  | ||||||
|       // error |  | ||||||
|       if (err) { |  | ||||||
|         var msg = 'production' == env |  | ||||||
|           ? 'Internal Server Error' |  | ||||||
|           : err.stack || err.toString(); |  | ||||||
|  |  | ||||||
|         // output to stderr in a non-test env |  | ||||||
|         if ('test' != env) console.error(err.stack || err.toString()); |  | ||||||
|  |  | ||||||
|         // unable to respond |  | ||||||
|         if (res.headerSent) return req.socket.destroy(); |  | ||||||
|  |  | ||||||
|         res.statusCode = 500; |  | ||||||
|         res.setHeader('Content-Type', 'text/plain'); |  | ||||||
|         if ('HEAD' == req.method) return res.end(); |  | ||||||
|         res.end(msg); |  | ||||||
|       } else { |  | ||||||
|         res.statusCode = 404; |  | ||||||
|         res.setHeader('Content-Type', 'text/plain'); |  | ||||||
|         if ('HEAD' == req.method) return res.end(); |  | ||||||
|         res.end('Cannot ' + req.method + ' ' + req.url); |  | ||||||
|       } |  | ||||||
|       return; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     try { |  | ||||||
|       path = parse(req.url).pathname; |  | ||||||
|       if (undefined == path) path = '/'; |  | ||||||
|  |  | ||||||
|       // skip this layer if the route doesn't match. |  | ||||||
|       if (0 != path.indexOf(layer.route)) return next(err); |  | ||||||
|  |  | ||||||
|       c = path[layer.route.length]; |  | ||||||
|       if (c && '/' != c && '.' != c) return next(err); |  | ||||||
|  |  | ||||||
|       // Call the layer handler |  | ||||||
|       // Trim off the part of the url that matches the route |  | ||||||
|       removed = layer.route; |  | ||||||
|       req.url = req.url.substr(removed.length); |  | ||||||
|  |  | ||||||
|       // Ensure leading slash |  | ||||||
|       if ('/' != req.url[0]) req.url = '/' + req.url; |  | ||||||
|  |  | ||||||
|       var arity = layer.handle.length; |  | ||||||
|       if (err) { |  | ||||||
|         if (arity === 4) { |  | ||||||
|           layer.handle(err, req, res, next); |  | ||||||
|         } else { |  | ||||||
|           next(err); |  | ||||||
|         } |  | ||||||
|       } else if (arity < 4) { |  | ||||||
|         layer.handle(req, res, next); |  | ||||||
|       } else { |  | ||||||
|         next(); |  | ||||||
|       } |  | ||||||
|     } catch (e) { |  | ||||||
|       if (e instanceof assert.AssertionError) { |  | ||||||
|         console.error(e.stack + '\n'); |  | ||||||
|         next(e); |  | ||||||
|       } else { |  | ||||||
|         next(e); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   next(); |  | ||||||
| }; |  | ||||||
							
								
								
									
										47
									
								
								node_modules/connect/lib/https.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,47 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - HTTPServer |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var HTTPServer = require('./http').Server |  | ||||||
|   , https = require('https'); |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Initialize a new `Server` with the given |  | ||||||
|  *`options` and `middleware`. The HTTPS api |  | ||||||
|  * is identical to the [HTTP](http.html) server, |  | ||||||
|  * however TLS `options` must be provided before |  | ||||||
|  * passing in the optional middleware. |  | ||||||
|  * |  | ||||||
|  * @params {Object} options |  | ||||||
|  * @params {Array} middleawre |  | ||||||
|  * @return {Server} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var Server = exports.Server = function HTTPSServer(options, middleware) { |  | ||||||
|   this.stack = []; |  | ||||||
|   middleware.forEach(function(fn){ |  | ||||||
|     this.use(fn); |  | ||||||
|   }, this); |  | ||||||
|   https.Server.call(this, options, this.handle); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Inherit from `http.Server.prototype`. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Server.prototype.__proto__ = https.Server.prototype; |  | ||||||
|  |  | ||||||
| // mixin HTTPServer methods |  | ||||||
|  |  | ||||||
| Object.keys(HTTPServer.prototype).forEach(function(method){ |  | ||||||
|   Server.prototype[method] = HTTPServer.prototype[method]; |  | ||||||
| }); |  | ||||||
							
								
								
									
										46
									
								
								node_modules/connect/lib/index.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,46 +0,0 @@ | |||||||
|  |  | ||||||
| /** |  | ||||||
|  * # Connect |  | ||||||
|  * |  | ||||||
|  * Connect is a middleware framework for node, |  | ||||||
|  * shipping with over 11 bundled middleware and a rich choice of |  | ||||||
|  * [3rd-party middleware](https://github.com/senchalabs/connect/wiki). |  | ||||||
|  * |  | ||||||
|  * Installation: |  | ||||||
|  *  |  | ||||||
|  *     $ npm install connect |  | ||||||
|  *  |  | ||||||
|  * API: |  | ||||||
|  * |  | ||||||
|  *  - [connect](connect.html) general |  | ||||||
|  *  - [http](http.html) http server |  | ||||||
|  *  - [https](https.html) https server |  | ||||||
|  * |  | ||||||
|  * Middleware: |  | ||||||
|  * |  | ||||||
|  *  - [logger](middleware-logger.html) request logger with custom format support |  | ||||||
|  *  - [csrf](middleware-csrf.html) Cross-site request forgery protection |  | ||||||
|  *  - [basicAuth](middleware-basicAuth.html) basic http authentication |  | ||||||
|  *  - [bodyParser](middleware-bodyParser.html) extensible request body parser |  | ||||||
|  *  - [cookieParser](middleware-cookieParser.html) cookie parser |  | ||||||
|  *  - [session](middleware-session.html) session management support with bundled [MemoryStore](middleware-session-memory.html) |  | ||||||
|  *  - [compiler](middleware-compiler.html) static asset compiler (sass, less, coffee-script, etc) |  | ||||||
|  *  - [methodOverride](middleware-methodOverride.html) faux HTTP method support |  | ||||||
|  *  - [responseTime](middleware-responseTime.html) calculates response-time and exposes via X-Response-Time |  | ||||||
|  *  - [router](middleware-router.html) provides rich Sinatra / Express-like routing |  | ||||||
|  *  - [staticCache](middleware-staticCache.html) memory cache layer for the static() middleware |  | ||||||
|  *  - [static](middleware-static.html) streaming static file server supporting `Range` and more |  | ||||||
|  *  - [directory](middleware-directory.html) directory listing middleware |  | ||||||
|  *  - [vhost](middleware-vhost.html) virtual host sub-domain mapping middleware |  | ||||||
|  *  - [favicon](middleware-favicon.html) efficient favicon server (with default icon) |  | ||||||
|  *  - [limit](middleware-limit.html) limit the bytesize of request bodies |  | ||||||
|  *  - [profiler](middleware-profiler.html) request profiler reporting response-time, memory usage, etc |  | ||||||
|  *  - [query](middleware-query.html) automatic querystring parser, populating `req.query` |  | ||||||
|  *  - [errorHandler](middleware-errorHandler.html) flexible error handler |  | ||||||
|  * |  | ||||||
|  * Internals: |  | ||||||
|  * |  | ||||||
|  *  - connect [utilities](utils.html) |  | ||||||
|  *  - node monkey [patches](patch.html) |  | ||||||
|  * |  | ||||||
|  */ |  | ||||||
							
								
								
									
										93
									
								
								node_modules/connect/lib/middleware/basicAuth.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,93 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - basicAuth |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var utils = require('../utils') |  | ||||||
|   , unauthorized = utils.unauthorized |  | ||||||
|   , badRequest = utils.badRequest; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Enfore basic authentication by providing a `callback(user, pass)`, |  | ||||||
|  * which must return `true` in order to gain access. Alternatively an async |  | ||||||
|  * method is provided as well, invoking `callback(user, pass, callback)`. Populates |  | ||||||
|  * `req.remoteUser`. The final alternative is simply passing username / password |  | ||||||
|  * strings. |  | ||||||
|  * |  | ||||||
|  * Examples: |  | ||||||
|  * |  | ||||||
|  *     connect(connect.basicAuth('username', 'password')); |  | ||||||
|  * |  | ||||||
|  *     connect( |  | ||||||
|  *       connect.basicAuth(function(user, pass){ |  | ||||||
|  *         return 'tj' == user & 'wahoo' == pass; |  | ||||||
|  *       }) |  | ||||||
|  *     ); |  | ||||||
|  * |  | ||||||
|  *     connect( |  | ||||||
|  *       connect.basicAuth(function(user, pass, fn){ |  | ||||||
|  *         User.authenticate({ user: user, pass: pass }, fn); |  | ||||||
|  *       }) |  | ||||||
|  *     ); |  | ||||||
|  * |  | ||||||
|  * @param {Function|String} callback or username |  | ||||||
|  * @param {String} realm |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| module.exports = function basicAuth(callback, realm) { |  | ||||||
|   var username, password; |  | ||||||
|  |  | ||||||
|   // user / pass strings |  | ||||||
|   if ('string' == typeof callback) { |  | ||||||
|     username = callback; |  | ||||||
|     password = realm; |  | ||||||
|     if ('string' != typeof password) throw new Error('password argument required'); |  | ||||||
|     realm = arguments[2]; |  | ||||||
|     callback = function(user, pass){ |  | ||||||
|       return user == username && pass == password; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   realm = realm || 'Authorization Required'; |  | ||||||
|  |  | ||||||
|   return function(req, res, next) { |  | ||||||
|     var authorization = req.headers.authorization; |  | ||||||
|  |  | ||||||
|     if (req.remoteUser) return next(); |  | ||||||
|     if (!authorization) return unauthorized(res, realm); |  | ||||||
|  |  | ||||||
|     var parts = authorization.split(' ') |  | ||||||
|       , scheme = parts[0] |  | ||||||
|       , credentials = new Buffer(parts[1], 'base64').toString().split(':'); |  | ||||||
|  |  | ||||||
|     if ('Basic' != scheme) return badRequest(res); |  | ||||||
|  |  | ||||||
|     // async |  | ||||||
|     if (callback.length >= 3) { |  | ||||||
|       var pause = utils.pause(req); |  | ||||||
|       callback(credentials[0], credentials[1], function(err, user){ |  | ||||||
|         if (err || !user)  return unauthorized(res, realm); |  | ||||||
|         req.remoteUser = user; |  | ||||||
|         next(); |  | ||||||
|         pause.resume(); |  | ||||||
|       }); |  | ||||||
|     // sync |  | ||||||
|     } else { |  | ||||||
|       if (callback(credentials[0], credentials[1])) { |  | ||||||
|         req.remoteUser = credentials[0]; |  | ||||||
|         next(); |  | ||||||
|       } else { |  | ||||||
|         unauthorized(res, realm); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
|  |  | ||||||
							
								
								
									
										196
									
								
								node_modules/connect/lib/middleware/bodyParser.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,196 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - bodyParser |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var qs = require('qs') |  | ||||||
|   , formidable = require('formidable'); |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Extract the mime type from the given request's |  | ||||||
|  * _Content-Type_ header. |  | ||||||
|  * |  | ||||||
|  * @param  {IncomingMessage} req |  | ||||||
|  * @return {String} |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function mime(req) { |  | ||||||
|   var str = req.headers['content-type'] || ''; |  | ||||||
|   return str.split(';')[0]; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Parse request bodies. |  | ||||||
|  * |  | ||||||
|  * By default _application/json_, _application/x-www-form-urlencoded_, |  | ||||||
|  * and _multipart/form-data_ are supported, however you may map `connect.bodyParser.parse[contentType]` |  | ||||||
|  * to a function receiving `(req, options, callback)`. |  | ||||||
|  * |  | ||||||
|  * Examples: |  | ||||||
|  * |  | ||||||
|  *      connect.createServer( |  | ||||||
|  *          connect.bodyParser() |  | ||||||
|  *        , function(req, res) { |  | ||||||
|  *          res.end('viewing user ' + req.body.user.name); |  | ||||||
|  *        } |  | ||||||
|  *      ); |  | ||||||
|  * |  | ||||||
|  *      $ curl -d 'user[name]=tj' http://localhost/ |  | ||||||
|  *      $ curl -d '{"user":{"name":"tj"}}' -H "Content-Type: application/json" http://localhost/ |  | ||||||
|  * |  | ||||||
|  * Multipart req.files: |  | ||||||
|  * |  | ||||||
|  *   As a security measure files are stored in a separate object, stored |  | ||||||
|  *   as `req.files`. This prevents attacks that may potentially alter |  | ||||||
|  *   filenames, and depending on the application gain access to restricted files. |  | ||||||
|  * |  | ||||||
|  * Multipart configuration: |  | ||||||
|  * |  | ||||||
|  *  The `options` passed are provided to each parser function. |  | ||||||
|  *  The _multipart/form-data_ parser merges these with formidable's |  | ||||||
|  *  IncomingForm object, allowing you to tweak the upload directory, |  | ||||||
|  *  size limits, etc. For example you may wish to retain the file extension |  | ||||||
|  *  and change the upload directory: |  | ||||||
|  * |  | ||||||
|  *      server.use(bodyParser({ uploadDir: '/www/mysite.com/uploads' })); |  | ||||||
|  * |  | ||||||
|  *  View [node-formidable](https://github.com/felixge/node-formidable) for more information. |  | ||||||
|  * |  | ||||||
|  *  If you wish to use formidable directly within your app, and do not |  | ||||||
|  *  desire this behaviour for multipart requests simply remove the |  | ||||||
|  *  parser:  |  | ||||||
|  * |  | ||||||
|  *     delete connect.bodyParser.parse['multipart/form-data']; |  | ||||||
|  * |  | ||||||
|  *  Or |  | ||||||
|  * |  | ||||||
|  *     delete express.bodyParser.parse['multipart/form-data']; |  | ||||||
|  * |  | ||||||
|  * @param {Object} options |  | ||||||
|  * @return {Function} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports = module.exports = function bodyParser(options){ |  | ||||||
|   options = options || {}; |  | ||||||
|   return function bodyParser(req, res, next) { |  | ||||||
|     if (req.body) return next(); |  | ||||||
|     req.body = {}; |  | ||||||
|  |  | ||||||
|     if ('GET' == req.method || 'HEAD' == req.method) return next(); |  | ||||||
|     var parser = exports.parse[mime(req)]; |  | ||||||
|     if (parser) { |  | ||||||
|       parser(req, options, next); |  | ||||||
|     } else { |  | ||||||
|       next(); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Parsers. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports.parse = {}; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Parse application/x-www-form-urlencoded. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports.parse['application/x-www-form-urlencoded'] = function(req, options, fn){ |  | ||||||
|   var buf = ''; |  | ||||||
|   req.setEncoding('utf8'); |  | ||||||
|   req.on('data', function(chunk){ buf += chunk }); |  | ||||||
|   req.on('end', function(){ |  | ||||||
|     try { |  | ||||||
|       req.body = buf.length |  | ||||||
|         ? qs.parse(buf) |  | ||||||
|         : {}; |  | ||||||
|       fn(); |  | ||||||
|     } catch (err){ |  | ||||||
|       fn(err); |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Parse application/json. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports.parse['application/json'] = function(req, options, fn){ |  | ||||||
|   var buf = ''; |  | ||||||
|   req.setEncoding('utf8'); |  | ||||||
|   req.on('data', function(chunk){ buf += chunk }); |  | ||||||
|   req.on('end', function(){ |  | ||||||
|     try { |  | ||||||
|       req.body = buf.length |  | ||||||
|         ? JSON.parse(buf) |  | ||||||
|         : {}; |  | ||||||
|       fn(); |  | ||||||
|     } catch (err){ |  | ||||||
|       fn(err); |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Parse multipart/form-data. |  | ||||||
|  * |  | ||||||
|  * TODO: make multiple support optional |  | ||||||
|  * TODO: revisit "error" flag if it's a formidable bug |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports.parse['multipart/form-data'] = function(req, options, fn){ |  | ||||||
|   var form = new formidable.IncomingForm |  | ||||||
|     , data = {} |  | ||||||
|     , files = {} |  | ||||||
|     , done; |  | ||||||
|  |  | ||||||
|   Object.keys(options).forEach(function(key){ |  | ||||||
|     form[key] = options[key]; |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   function ondata(name, val, data){ |  | ||||||
|     if (Array.isArray(data[name])) { |  | ||||||
|       data[name].push(val); |  | ||||||
|     } else if (data[name]) { |  | ||||||
|       data[name] = [data[name], val]; |  | ||||||
|     } else { |  | ||||||
|       data[name] = val; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   form.on('field', function(name, val){ |  | ||||||
|     ondata(name, val, data); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   form.on('file', function(name, val){ |  | ||||||
|     ondata(name, val, files); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   form.on('error', function(err){ |  | ||||||
|     fn(err); |  | ||||||
|     done = true; |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   form.on('end', function(){ |  | ||||||
|     if (done) return; |  | ||||||
|     try { |  | ||||||
|       req.body = qs.parse(data); |  | ||||||
|       req.files = qs.parse(files); |  | ||||||
|       fn(); |  | ||||||
|     } catch (err) { |  | ||||||
|       fn(err); |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   form.parse(req); |  | ||||||
| }; |  | ||||||
							
								
								
									
										163
									
								
								node_modules/connect/lib/middleware/compiler.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,163 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - compiler |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var fs = require('fs') |  | ||||||
|   , path = require('path') |  | ||||||
|   , parse = require('url').parse; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Require cache. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var cache = {}; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Setup compiler. |  | ||||||
|  * |  | ||||||
|  * Options: |  | ||||||
|  * |  | ||||||
|  *   - `src`     Source directory, defaults to **CWD**. |  | ||||||
|  *   - `dest`    Destination directory, defaults `src`. |  | ||||||
|  *   - `enable`  Array of enabled compilers. |  | ||||||
|  * |  | ||||||
|  * Compilers: |  | ||||||
|  * |  | ||||||
|  *   - `sass`   Compiles sass to css |  | ||||||
|  *   - `less`   Compiles less to css |  | ||||||
|  *   - `coffeescript`   Compiles coffee to js |  | ||||||
|  * |  | ||||||
|  * @param {Object} options |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports = module.exports = function compiler(options){ |  | ||||||
|   options = options || {}; |  | ||||||
|  |  | ||||||
|   var srcDir = options.src || process.cwd() |  | ||||||
|     , destDir = options.dest || srcDir |  | ||||||
|     , enable = options.enable; |  | ||||||
|  |  | ||||||
|   if (!enable || enable.length === 0) { |  | ||||||
|     throw new Error('compiler\'s "enable" option is not set, nothing will be compiled.'); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return function compiler(req, res, next){ |  | ||||||
|     if ('GET' != req.method) return next(); |  | ||||||
|     var pathname = parse(req.url).pathname; |  | ||||||
|     for (var i = 0, len = enable.length; i < len; ++i) { |  | ||||||
|       var name = enable[i] |  | ||||||
|         , compiler = compilers[name]; |  | ||||||
|       if (compiler.match.test(pathname)) { |  | ||||||
|         var src = (srcDir + pathname).replace(compiler.match, compiler.ext) |  | ||||||
|           , dest = destDir + pathname; |  | ||||||
|  |  | ||||||
|         // Compare mtimes |  | ||||||
|         fs.stat(src, function(err, srcStats){ |  | ||||||
|           if (err) { |  | ||||||
|             if ('ENOENT' == err.code) { |  | ||||||
|               next(); |  | ||||||
|             } else { |  | ||||||
|               next(err); |  | ||||||
|             } |  | ||||||
|           } else { |  | ||||||
|             fs.stat(dest, function(err, destStats){ |  | ||||||
|               if (err) { |  | ||||||
|                 // Oh snap! it does not exist, compile it |  | ||||||
|                 if ('ENOENT' == err.code) { |  | ||||||
|                   compile(); |  | ||||||
|                 } else { |  | ||||||
|                   next(err); |  | ||||||
|                 } |  | ||||||
|               } else { |  | ||||||
|                 // Source has changed, compile it |  | ||||||
|                 if (srcStats.mtime > destStats.mtime) { |  | ||||||
|                   compile(); |  | ||||||
|                 } else { |  | ||||||
|                   // Defer file serving |  | ||||||
|                   next(); |  | ||||||
|                 } |  | ||||||
|               } |  | ||||||
|             }); |  | ||||||
|           } |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         // Compile to the destination |  | ||||||
|         function compile() { |  | ||||||
|           fs.readFile(src, 'utf8', function(err, str){ |  | ||||||
|             if (err) { |  | ||||||
|               next(err); |  | ||||||
|             } else { |  | ||||||
|               compiler.compile(str, function(err, str){ |  | ||||||
|                 if (err) { |  | ||||||
|                   next(err); |  | ||||||
|                 } else { |  | ||||||
|                   fs.writeFile(dest, str, 'utf8', function(err){ |  | ||||||
|                     next(err); |  | ||||||
|                   }); |  | ||||||
|                 } |  | ||||||
|               }); |  | ||||||
|             } |  | ||||||
|           }); |  | ||||||
|         } |  | ||||||
|         return; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     next(); |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Bundled compilers: |  | ||||||
|  * |  | ||||||
|  *  - [sass](http://github.com/visionmedia/sass.js) to _css_ |  | ||||||
|  *  - [less](http://github.com/cloudhead/less.js) to _css_ |  | ||||||
|  *  - [coffee](http://github.com/jashkenas/coffee-script) to _js_ |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var compilers = exports.compilers = { |  | ||||||
|   sass: { |  | ||||||
|     match: /\.css$/, |  | ||||||
|     ext: '.sass', |  | ||||||
|     compile: function(str, fn){ |  | ||||||
|       var sass = cache.sass || (cache.sass = require('sass')); |  | ||||||
|       try { |  | ||||||
|         fn(null, sass.render(str)); |  | ||||||
|       } catch (err) { |  | ||||||
|         fn(err); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
|   less: { |  | ||||||
|     match: /\.css$/, |  | ||||||
|     ext: '.less', |  | ||||||
|     compile: function(str, fn){ |  | ||||||
|       var less = cache.less || (cache.less = require('less')); |  | ||||||
|       try { |  | ||||||
|         less.render(str, fn); |  | ||||||
|       } catch (err) { |  | ||||||
|         fn(err); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
|   coffeescript: { |  | ||||||
|     match: /\.js$/, |  | ||||||
|     ext: '.coffee', |  | ||||||
|     compile: function(str, fn){ |  | ||||||
|       var coffee = cache.coffee || (cache.coffee = require('coffee-script')); |  | ||||||
|       try { |  | ||||||
|         fn(null, coffee.compile(str)); |  | ||||||
|       } catch (err) { |  | ||||||
|         fn(err); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
							
								
								
									
										46
									
								
								node_modules/connect/lib/middleware/cookieParser.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,46 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - cookieParser |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var utils = require('./../utils'); |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Parse _Cookie_ header and populate `req.cookies` |  | ||||||
|  * with an object keyed by the cookie names. |  | ||||||
|  * |  | ||||||
|  * Examples: |  | ||||||
|  * |  | ||||||
|  *     connect.createServer( |  | ||||||
|  *         connect.cookieParser() |  | ||||||
|  *       , function(req, res, next){ |  | ||||||
|  *         res.end(JSON.stringify(req.cookies)); |  | ||||||
|  *       } |  | ||||||
|  *     ); |  | ||||||
|  * |  | ||||||
|  * @return {Function} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| module.exports = function cookieParser(){ |  | ||||||
|   return function cookieParser(req, res, next) { |  | ||||||
|     var cookie = req.headers.cookie; |  | ||||||
|     if (req.cookies) return next(); |  | ||||||
|     req.cookies = {}; |  | ||||||
|     if (cookie) { |  | ||||||
|       try { |  | ||||||
|         req.cookies = utils.parseCookie(cookie); |  | ||||||
|       } catch (err) { |  | ||||||
|         return next(err); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     next(); |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
							
								
								
									
										105
									
								
								node_modules/connect/lib/middleware/csrf.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,105 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - csrf |  | ||||||
|  * Copyright(c) 2011 Sencha Inc. |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var utils = require('../utils') |  | ||||||
|   , crypto = require('crypto'); |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * CRSF protection middleware. |  | ||||||
|  * |  | ||||||
|  * By default this middleware generates a token named "_csrf" |  | ||||||
|  * which should be added to requests which mutate |  | ||||||
|  * state, within a hidden form field, query-string etc. This |  | ||||||
|  * token is validated against the visitor's `req.session._csrf` |  | ||||||
|  * property which is re-generated per request. |  | ||||||
|  * |  | ||||||
|  * The default `value` function checks `req.body` generated |  | ||||||
|  * by the `bodyParser()` middleware, `req.query` generated |  | ||||||
|  * by `query()`, and the "X-CSRF-Token" header field. |  | ||||||
|  * |  | ||||||
|  * This middleware requires session support, thus should be added |  | ||||||
|  * somewhere _below_ `session()` and `cookieParser()`. |  | ||||||
|  * |  | ||||||
|  * Examples: |  | ||||||
|  * |  | ||||||
|  *      var form = '\n\ |  | ||||||
|  *        <form action="/" method="post">\n\ |  | ||||||
|  *          <input type="hidden" name="_csrf" value="{token}" />\n\ |  | ||||||
|  *          <input type="text" name="user[name]" value="{user}" />\n\ |  | ||||||
|  *          <input type="password" name="user[pass]" />\n\ |  | ||||||
|  *          <input type="submit" value="Login" />\n\ |  | ||||||
|  *        </form>\n\ |  | ||||||
|  *      ';  |  | ||||||
|  *       |  | ||||||
|  *      connect( |  | ||||||
|  *          connect.cookieParser() |  | ||||||
|  *        , connect.session({ secret: 'keyboard cat' }) |  | ||||||
|  *        , connect.bodyParser() |  | ||||||
|  *        , connect.csrf() |  | ||||||
|  *       |  | ||||||
|  *        , function(req, res, next){ |  | ||||||
|  *          if ('POST' != req.method) return next(); |  | ||||||
|  *          req.session.user = req.body.user; |  | ||||||
|  *          next(); |  | ||||||
|  *        } |  | ||||||
|  *       |  | ||||||
|  *        , function(req, res){ |  | ||||||
|  *          res.setHeader('Content-Type', 'text/html'); |  | ||||||
|  *          var body = form |  | ||||||
|  *            .replace('{token}', req.session._csrf) |  | ||||||
|  *            .replace('{user}', req.session.user && req.session.user.name || ''); |  | ||||||
|  *          res.end(body); |  | ||||||
|  *        } |  | ||||||
|  *      ).listen(3000); |  | ||||||
|  * |  | ||||||
|  * Options: |  | ||||||
|  * |  | ||||||
|  *    - `value` a function accepting the request, returning the token  |  | ||||||
|  * |  | ||||||
|  * @param {Object} options |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| module.exports = function csrf(options) { |  | ||||||
|   var options = options || {} |  | ||||||
|     , value = options.value || defaultValue; |  | ||||||
|  |  | ||||||
|   return function(req, res, next){ |  | ||||||
|     // generate CSRF token |  | ||||||
|     var token = req.session._csrf || (req.session._csrf = utils.uid(24)); |  | ||||||
|  |  | ||||||
|     // ignore GET (for now) |  | ||||||
|     if ('GET' == req.method) return next(); |  | ||||||
|  |  | ||||||
|     // determine value |  | ||||||
|     var val = value(req); |  | ||||||
|  |  | ||||||
|     // check |  | ||||||
|     if (val != token) return utils.forbidden(res); |  | ||||||
|      |  | ||||||
|     next(); |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Default value function, checking the `req.body` |  | ||||||
|  * and `req.query` for the CSRF token. |  | ||||||
|  * |  | ||||||
|  * @param {IncomingMessage} req |  | ||||||
|  * @return {String} |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function defaultValue(req) { |  | ||||||
|   return (req.body && req.body._csrf) |  | ||||||
|     || (req.query && req.query._csrf) |  | ||||||
|     || (req.headers['x-csrf-token']); |  | ||||||
| } |  | ||||||
							
								
								
									
										222
									
								
								node_modules/connect/lib/middleware/directory.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,222 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - directory |  | ||||||
|  * Copyright(c) 2011 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| // TODO: icon / style for directories |  | ||||||
| // TODO: arrow key navigation |  | ||||||
| // TODO: make icons extensible |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var fs = require('fs') |  | ||||||
|   , parse = require('url').parse |  | ||||||
|   , utils = require('../utils') |  | ||||||
|   , path = require('path') |  | ||||||
|   , normalize = path.normalize |  | ||||||
|   , extname = path.extname |  | ||||||
|   , join = path.join; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Icon cache. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var cache = {}; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Serve directory listings with the given `root` path. |  | ||||||
|  * |  | ||||||
|  * Options: |  | ||||||
|  * |  | ||||||
|  *  - `hidden` display hidden (dot) files. Defaults to false. |  | ||||||
|  *  - `icons`  display icons. Defaults to false. |  | ||||||
|  *  - `filter` Apply this filter function to files. Defaults to false. |  | ||||||
|  * |  | ||||||
|  * @param {String} root |  | ||||||
|  * @param {Object} options |  | ||||||
|  * @return {Function} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports = module.exports = function directory(root, options){ |  | ||||||
|   options = options || {}; |  | ||||||
|  |  | ||||||
|   // root required |  | ||||||
|   if (!root) throw new Error('directory() root path required'); |  | ||||||
|   var hidden = options.hidden |  | ||||||
|     , icons = options.icons |  | ||||||
|     , filter = options.filter |  | ||||||
|     , root = normalize(root); |  | ||||||
|  |  | ||||||
|   return function directory(req, res, next) { |  | ||||||
|     var accept = req.headers.accept || 'text/plain' |  | ||||||
|       , url = parse(req.url) |  | ||||||
|       , dir = decodeURIComponent(url.pathname) |  | ||||||
|       , path = normalize(join(root, dir)) |  | ||||||
|       , originalUrl = parse(req.originalUrl) |  | ||||||
|       , originalDir = decodeURIComponent(originalUrl.pathname) |  | ||||||
|       , showUp = path != root && path != root + '/'; |  | ||||||
|  |  | ||||||
|     // null byte(s) |  | ||||||
|     if (~path.indexOf('\0')) return utils.badRequest(res); |  | ||||||
|  |  | ||||||
|     // malicious path |  | ||||||
|     if (0 != path.indexOf(root)) return utils.forbidden(res); |  | ||||||
|  |  | ||||||
|     // check if we have a directory |  | ||||||
|     fs.stat(path, function(err, stat){ |  | ||||||
|       if (err) return 'ENOENT' == err.code |  | ||||||
|         ? next() |  | ||||||
|         : next(err); |  | ||||||
|  |  | ||||||
|       if (!stat.isDirectory()) return next(); |  | ||||||
|  |  | ||||||
|       // fetch files |  | ||||||
|       fs.readdir(path, function(err, files){ |  | ||||||
|         if (err) return next(err); |  | ||||||
|         if (!hidden) files = removeHidden(files); |  | ||||||
|         if (filter) files = files.filter(filter); |  | ||||||
|         files.sort(); |  | ||||||
|         // content-negotiation |  | ||||||
|         for (var key in exports) { |  | ||||||
|           if (~accept.indexOf(key) || ~accept.indexOf('*/*')) { |  | ||||||
|             exports[key](req, res, files, next, originalDir, showUp, icons); |  | ||||||
|             return; |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|         utils.notAcceptable(res); |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Respond with text/html. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports.html = function(req, res, files, next, dir, showUp, icons){ |  | ||||||
|   fs.readFile(__dirname + '/../public/directory.html', 'utf8', function(err, str){ |  | ||||||
|     if (err) return next(err); |  | ||||||
|     fs.readFile(__dirname + '/../public/style.css', 'utf8', function(err, style){ |  | ||||||
|       if (err) return next(err); |  | ||||||
|       if (showUp) files.unshift('..'); |  | ||||||
|       str = str |  | ||||||
|         .replace('{style}', style) |  | ||||||
|         .replace('{files}', html(files, dir, icons)) |  | ||||||
|         .replace('{directory}', dir) |  | ||||||
| 		.replace('{linked-path}', htmlPath(dir)); |  | ||||||
|       res.setHeader('Content-Type', 'text/html'); |  | ||||||
|       res.setHeader('Content-Length', str.length); |  | ||||||
|       res.end(str); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Respond with application/json. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports.json = function(req, res, files){ |  | ||||||
|   files = JSON.stringify(files); |  | ||||||
|   res.setHeader('Content-Type', 'application/json'); |  | ||||||
|   res.setHeader('Content-Length', files.length); |  | ||||||
|   res.end(files); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Respond with text/plain. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports.plain = function(req, res, files){ |  | ||||||
|   files = files.join('\n') + '\n'; |  | ||||||
|   res.setHeader('Content-Type', 'text/plain'); |  | ||||||
|   res.setHeader('Content-Length', files.length); |  | ||||||
|   res.end(files); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Map html `dir`, returning a linked path. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function htmlPath(dir) { |  | ||||||
|   var curr = []; |  | ||||||
|   return dir.split('/').map(function(part){ |  | ||||||
|     curr.push(part); |  | ||||||
|     return '<a href="' + curr.join('/') + '">' + part + '</a>'; |  | ||||||
|   }).join(' / '); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Map html `files`, returning an html unordered list. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function html(files, dir, useIcons) { |  | ||||||
|   return '<ul id="files">' + files.map(function(file){ |  | ||||||
|     var icon = '' |  | ||||||
|       , classes = []; |  | ||||||
|  |  | ||||||
|     if (useIcons && '..' != file) { |  | ||||||
|       icon = icons[extname(file)] || icons.default; |  | ||||||
|       icon = '<img src="data:image/png;base64,' + load(icon) + '" />'; |  | ||||||
|       classes.push('icon'); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return '<li><a href="' |  | ||||||
|       + join(dir, file) |  | ||||||
|       + '" class="' |  | ||||||
|       + classes.join(' ') + '"' |  | ||||||
|       + ' title="' + file + '">' |  | ||||||
|       + icon + file + '</a></li>'; |  | ||||||
|  |  | ||||||
|   }).join('\n') + '</ul>'; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Load and cache the given `icon`. |  | ||||||
|  * |  | ||||||
|  * @param {String} icon |  | ||||||
|  * @return {String} |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function load(icon) { |  | ||||||
|   if (cache[icon]) return cache[icon]; |  | ||||||
|   return cache[icon] = fs.readFileSync(__dirname + '/../public/icons/' + icon, 'base64'); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Filter "hidden" `files`, aka files |  | ||||||
|  * beginning with a `.`. |  | ||||||
|  * |  | ||||||
|  * @param {Array} files |  | ||||||
|  * @return {Array} |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function removeHidden(files) { |  | ||||||
|   return files.filter(function(file){ |  | ||||||
|     return '.' != file[0]; |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Icon map. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var icons = { |  | ||||||
|     '.js': 'page_white_code_red.png' |  | ||||||
|   , '.c': 'page_white_c.png' |  | ||||||
|   , '.h': 'page_white_h.png' |  | ||||||
|   , '.cc': 'page_white_cplusplus.png' |  | ||||||
|   , '.php': 'page_white_php.png' |  | ||||||
|   , '.rb': 'page_white_ruby.png' |  | ||||||
|   , '.cpp': 'page_white_cplusplus.png' |  | ||||||
|   , '.swf': 'page_white_flash.png' |  | ||||||
|   , '.pdf': 'page_white_acrobat.png' |  | ||||||
|   , 'default': 'page_white.png' |  | ||||||
| }; |  | ||||||
							
								
								
									
										100
									
								
								node_modules/connect/lib/middleware/errorHandler.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,100 +0,0 @@ | |||||||
| /*! |  | ||||||
|  * Connect - errorHandler |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var utils = require('../utils') |  | ||||||
|   , url = require('url') |  | ||||||
|   , fs = require('fs'); |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Flexible error handler, providing (_optional_) stack traces |  | ||||||
|  * and error message responses for requests accepting text, html, |  | ||||||
|  * or json. |  | ||||||
|  * |  | ||||||
|  * Options: |  | ||||||
|  * |  | ||||||
|  *   - `showStack`, `stack` respond with both the error message and stack trace. Defaults to `false` |  | ||||||
|  *   - `showMessage`, `message`, respond with the exception message only. Defaults to `false` |  | ||||||
|  *   - `dumpExceptions`, `dump`, dump exceptions to stderr (without terminating the process). Defaults to `false` |  | ||||||
|  * |  | ||||||
|  * Text: |  | ||||||
|  * |  | ||||||
|  *   By default, and when _text/plain_ is accepted a simple stack trace |  | ||||||
|  *   or error message will be returned. |  | ||||||
|  * |  | ||||||
|  * JSON: |  | ||||||
|  * |  | ||||||
|  *   When _application/json_ is accepted, connect will respond with |  | ||||||
|  *   an object in the form of `{ "error": error }`.  |  | ||||||
|  * |  | ||||||
|  * HTML: |  | ||||||
|  * |  | ||||||
|  *   When accepted connect will output a nice html stack trace. |  | ||||||
|  * |  | ||||||
|  * @param {Object} options |  | ||||||
|  * @return {Function} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports = module.exports = function errorHandler(options){ |  | ||||||
|   options = options || {}; |  | ||||||
|  |  | ||||||
|   // defaults |  | ||||||
|   var showStack = options.showStack || options.stack |  | ||||||
|     , showMessage = options.showMessage || options.message |  | ||||||
|     , dumpExceptions = options.dumpExceptions || options.dump |  | ||||||
|     , formatUrl = options.formatUrl; |  | ||||||
|  |  | ||||||
|   return function errorHandler(err, req, res, next){ |  | ||||||
|     res.statusCode = 500; |  | ||||||
|     if (dumpExceptions) console.error(err.stack); |  | ||||||
|     if (showStack) { |  | ||||||
|       var accept = req.headers.accept || ''; |  | ||||||
|       // html |  | ||||||
|       if (~accept.indexOf('html')) { |  | ||||||
|         fs.readFile(__dirname + '/../public/style.css', 'utf8', function(e, style){ |  | ||||||
|           fs.readFile(__dirname + '/../public/error.html', 'utf8', function(e, html){ |  | ||||||
|             var stack = (err.stack || '') |  | ||||||
|               .split('\n').slice(1) |  | ||||||
|               .map(function(v){ return '<li>' + v + '</li>'; }).join(''); |  | ||||||
|               html = html |  | ||||||
|                 .replace('{style}', style) |  | ||||||
|                 .replace('{stack}', stack) |  | ||||||
|                 .replace('{title}', exports.title) |  | ||||||
|                 .replace(/\{error\}/g, utils.escape(err.toString())); |  | ||||||
|               res.setHeader('Content-Type', 'text/html'); |  | ||||||
|               res.end(html); |  | ||||||
|           }); |  | ||||||
|         }); |  | ||||||
|       // json |  | ||||||
|       } else if (~accept.indexOf('json')) { |  | ||||||
|         var json = JSON.stringify({ error: err }); |  | ||||||
|         res.setHeader('Content-Type', 'application/json'); |  | ||||||
|         res.end(json); |  | ||||||
|       // plain text |  | ||||||
|       } else { |  | ||||||
|         res.writeHead(500, { 'Content-Type': 'text/plain' }); |  | ||||||
|         res.end(err.stack); |  | ||||||
|       } |  | ||||||
|     } else { |  | ||||||
|       var body = showMessage |  | ||||||
|         ? err.toString() |  | ||||||
|         : 'Internal Server Error'; |  | ||||||
|       res.setHeader('Content-Type', 'text/plain'); |  | ||||||
|       res.end(body); |  | ||||||
|     } |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Template title. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports.title = 'Connect'; |  | ||||||
							
								
								
									
										76
									
								
								node_modules/connect/lib/middleware/favicon.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,76 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - favicon |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var fs = require('fs') |  | ||||||
|   , utils = require('../utils'); |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Favicon cache. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var icon; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * By default serves the connect favicon, or the favicon |  | ||||||
|  * located by the given `path`. |  | ||||||
|  * |  | ||||||
|  * Options: |  | ||||||
|  * |  | ||||||
|  *   - `maxAge`  cache-control max-age directive, defaulting to 1 day |  | ||||||
|  * |  | ||||||
|  * Examples: |  | ||||||
|  * |  | ||||||
|  *     connect.createServer( |  | ||||||
|  *       connect.favicon()     |  | ||||||
|  *     ); |  | ||||||
|  * |  | ||||||
|  *     connect.createServer( |  | ||||||
|  *       connect.favicon(__dirname + '/public/favicon.ico')     |  | ||||||
|  *     ); |  | ||||||
|  * |  | ||||||
|  * @param {String} path |  | ||||||
|  * @param {Object} options |  | ||||||
|  * @return {Function} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| module.exports = function favicon(path, options){ |  | ||||||
|   var options = options || {} |  | ||||||
|     , path = path || __dirname + '/../public/favicon.ico' |  | ||||||
|     , maxAge = options.maxAge || 86400000; |  | ||||||
|  |  | ||||||
|   return function favicon(req, res, next){ |  | ||||||
|     if ('/favicon.ico' == req.url) { |  | ||||||
|       if (icon) { |  | ||||||
|         res.writeHead(200, icon.headers); |  | ||||||
|         res.end(icon.body); |  | ||||||
|       } else { |  | ||||||
|         fs.readFile(path, function(err, buf){ |  | ||||||
|           if (err) return next(err); |  | ||||||
|           icon = { |  | ||||||
|             headers: { |  | ||||||
|                 'Content-Type': 'image/x-icon' |  | ||||||
|               , 'Content-Length': buf.length |  | ||||||
|               , 'ETag': '"' + utils.md5(buf) + '"' |  | ||||||
|               , 'Cache-Control': 'public, max-age=' + (maxAge / 1000) |  | ||||||
|             }, |  | ||||||
|             body: buf |  | ||||||
|           }; |  | ||||||
|           res.writeHead(200, icon.headers); |  | ||||||
|           res.end(icon.body); |  | ||||||
|         }); |  | ||||||
|       } |  | ||||||
|     } else { |  | ||||||
|       next(); |  | ||||||
|     } |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
							
								
								
									
										82
									
								
								node_modules/connect/lib/middleware/limit.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,82 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - limit |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Limit request bodies to the given size in `bytes`. |  | ||||||
|  * |  | ||||||
|  * A string representation of the bytesize may also be passed, |  | ||||||
|  * for example "5mb", "200kb", "1gb", etc. |  | ||||||
|  * |  | ||||||
|  * Examples: |  | ||||||
|  * |  | ||||||
|  *     var server = connect( |  | ||||||
|  *       connect.limit('5.5mb') |  | ||||||
|  *     ).listen(3000); |  | ||||||
|  * |  | ||||||
|  * TODO: pause EV_READ |  | ||||||
|  * |  | ||||||
|  * @param {Number|String} bytes |  | ||||||
|  * @return {Function} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| module.exports = function limit(bytes){ |  | ||||||
|   if ('string' == typeof bytes) bytes = parse(bytes); |  | ||||||
|   if ('number' != typeof bytes) throw new Error('limit() bytes required'); |  | ||||||
|   return function limit(req, res, next){ |  | ||||||
|     var received = 0 |  | ||||||
|       , len = req.headers['content-length'] |  | ||||||
|         ? parseInt(req.headers['content-length'], 10) |  | ||||||
|         : null; |  | ||||||
|  |  | ||||||
|     // deny the request |  | ||||||
|     function deny() { |  | ||||||
|       req.destroy(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // self-awareness |  | ||||||
|     if (req._limit) return next(); |  | ||||||
|     req._limit = true; |  | ||||||
|  |  | ||||||
|     // limit by content-length |  | ||||||
|     if (len && len > bytes) { |  | ||||||
|       res.statusCode = 413; |  | ||||||
|       res.end('Request Entity Too Large'); |  | ||||||
|       return; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // limit |  | ||||||
|     req.on('data', function(chunk){ |  | ||||||
|       received += chunk.length; |  | ||||||
|       if (received > bytes) deny(); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     next(); |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Parse byte `size` string. |  | ||||||
|  * |  | ||||||
|  * @param {String} size |  | ||||||
|  * @return {Number} |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function parse(size) { |  | ||||||
|   var parts = size.match(/^(\d+(?:\.\d+)?) *(kb|mb|gb)$/) |  | ||||||
|     , n = parseFloat(parts[1]) |  | ||||||
|     , type = parts[2]; |  | ||||||
|  |  | ||||||
|   var map = { |  | ||||||
|       kb: 1024 |  | ||||||
|     , mb: 1024 * 1024 |  | ||||||
|     , gb: 1024 * 1024 * 1024 |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   return map[type] * n; |  | ||||||
| } |  | ||||||
							
								
								
									
										299
									
								
								node_modules/connect/lib/middleware/logger.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,299 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - logger |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Log buffer. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var buf = []; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Default log buffer duration. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var defaultBufferDuration = 1000; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Log requests with the given `options` or a `format` string. |  | ||||||
|  * |  | ||||||
|  * Options: |  | ||||||
|  * |  | ||||||
|  *   - `format`  Format string, see below for tokens |  | ||||||
|  *   - `stream`  Output stream, defaults to _stdout_ |  | ||||||
|  *   - `buffer`  Buffer duration, defaults to 1000ms when _true_ |  | ||||||
|  *   - `immediate`  Write log line on request instead of response (for response times) |  | ||||||
|  * |  | ||||||
|  * Tokens: |  | ||||||
|  * |  | ||||||
|  *   - `:req[header]` ex: `:req[Accept]` |  | ||||||
|  *   - `:res[header]` ex: `:res[Content-Length]` |  | ||||||
|  *   - `:http-version` |  | ||||||
|  *   - `:response-time` |  | ||||||
|  *   - `:remote-addr` |  | ||||||
|  *   - `:date` |  | ||||||
|  *   - `:method` |  | ||||||
|  *   - `:url` |  | ||||||
|  *   - `:referrer` |  | ||||||
|  *   - `:user-agent` |  | ||||||
|  *   - `:status` |  | ||||||
|  * |  | ||||||
|  * Formats: |  | ||||||
|  * |  | ||||||
|  *   Pre-defined formats that ship with connect: |  | ||||||
|  * |  | ||||||
|  *    - `default` ':remote-addr - - [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"' |  | ||||||
|  *    - `short` ':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms' |  | ||||||
|  *    - `tiny`  ':method :url :status :res[content-length] - :response-time ms' |  | ||||||
|  *    - `dev` concise output colored by response status for development use |  | ||||||
|  * |  | ||||||
|  * Examples: |  | ||||||
|  * |  | ||||||
|  *      connect.logger() // default |  | ||||||
|  *      connect.logger('short') |  | ||||||
|  *      connect.logger('tiny') |  | ||||||
|  *      connect.logger('dev') |  | ||||||
|  *      connect.logger(':method :url - :referrer') |  | ||||||
|  *      connect.logger(':req[content-type] -> :res[content-type]') |  | ||||||
|  *      connect.logger(function(req, res){ return 'some format string' }) |  | ||||||
|  * |  | ||||||
|  * Defining Tokens: |  | ||||||
|  * |  | ||||||
|  *   To define a token, simply invoke `connect.logger.token()` with the |  | ||||||
|  *   name and a callback function. The value returned is then available |  | ||||||
|  *   as ":type" in this case. |  | ||||||
|  * |  | ||||||
|  *      connect.logger.token('type', function(req, res){ return req.headers['content-type']; }) |  | ||||||
|  * |  | ||||||
|  * Defining Formats: |  | ||||||
|  * |  | ||||||
|  *   All default formats are defined this way, however it's public API as well: |  | ||||||
|  * |  | ||||||
|  *       connect.logger.format('name', 'string or function') |  | ||||||
|  * |  | ||||||
|  * @param {String|Function|Object} format or options |  | ||||||
|  * @return {Function} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports = module.exports = function logger(options) { |  | ||||||
|   if ('object' == typeof options) { |  | ||||||
|     options = options || {}; |  | ||||||
|   } else if (options) { |  | ||||||
|     options = { format: options }; |  | ||||||
|   } else { |  | ||||||
|     options = {}; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // output on request instead of response |  | ||||||
|   var immediate = options.immediate; |  | ||||||
|  |  | ||||||
|   // format name |  | ||||||
|   var fmt = exports[options.format] || options.format || exports.default; |  | ||||||
|  |  | ||||||
|   // compile format |  | ||||||
|   if ('function' != typeof fmt) fmt = compile(fmt); |  | ||||||
|  |  | ||||||
|   // options |  | ||||||
|   var stream = options.stream || process.stdout |  | ||||||
|     , buffer = options.buffer; |  | ||||||
|  |  | ||||||
|   // buffering support |  | ||||||
|   if (buffer) { |  | ||||||
|     var realStream = stream |  | ||||||
|       , interval = 'number' == typeof buffer |  | ||||||
|         ? buffer |  | ||||||
|         : defaultBufferDuration; |  | ||||||
|  |  | ||||||
|     // flush interval |  | ||||||
|     setInterval(function(){ |  | ||||||
|       if (buf.length) { |  | ||||||
|         realStream.write(buf.join(''), 'ascii'); |  | ||||||
|         buf.length = 0; |  | ||||||
|       } |  | ||||||
|     }, interval);  |  | ||||||
|  |  | ||||||
|     // swap the stream |  | ||||||
|     stream = { |  | ||||||
|       write: function(str){ |  | ||||||
|         buf.push(str); |  | ||||||
|       } |  | ||||||
|     }; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return function logger(req, res, next) { |  | ||||||
|     req._startTime = new Date; |  | ||||||
|  |  | ||||||
|     // mount safety |  | ||||||
|     if (req._logging) return next(); |  | ||||||
|  |  | ||||||
|     // flag as logging |  | ||||||
|     req._logging = true; |  | ||||||
|  |  | ||||||
|     // immediate |  | ||||||
|     if (immediate) { |  | ||||||
|       var line = fmt(exports, req, res); |  | ||||||
|       if (null == line) return; |  | ||||||
|       stream.write(line + '\n', 'ascii'); |  | ||||||
|     } else { |  | ||||||
|       // proxy end to output loggging |  | ||||||
|       var end = res.end; |  | ||||||
|       res.end = function(chunk, encoding){ |  | ||||||
|         res.end = end; |  | ||||||
|         res.end(chunk, encoding); |  | ||||||
|         var line = fmt(exports, req, res); |  | ||||||
|         if (null == line) return; |  | ||||||
|         stream.write(line + '\n', 'ascii'); |  | ||||||
|       }; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     next(); |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Compile `fmt` into a function. |  | ||||||
|  * |  | ||||||
|  * @param {String} fmt |  | ||||||
|  * @return {Function} |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function compile(fmt) { |  | ||||||
|   fmt = fmt.replace(/"/g, '\\"'); |  | ||||||
|   var js = '  return "' + fmt.replace(/:([-\w]{2,})(?:\[([^\]]+)\])?/g, function(_, name, arg){ |  | ||||||
|     return '"\n    + (tokens["' + name + '"](req, res, "' + arg + '") || "-") + "'; |  | ||||||
|   }) + '";' |  | ||||||
|   return new Function('tokens, req, res', js); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Define a token function with the given `name`, |  | ||||||
|  * and callback `fn(req, res)`. |  | ||||||
|  * |  | ||||||
|  * @param {String} name |  | ||||||
|  * @param {Function} fn |  | ||||||
|  * @return {Object} exports for chaining |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports.token = function(name, fn) { |  | ||||||
|   exports[name] = fn; |  | ||||||
|   return this; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Define a `fmt` with the given `name`. |  | ||||||
|  * |  | ||||||
|  * @param {String} name |  | ||||||
|  * @param {String|Function} fmt |  | ||||||
|  * @return {Object} exports for chaining |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports.format = function(name, str){ |  | ||||||
|   exports[name] = str; |  | ||||||
|   return this; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| // default format |  | ||||||
|  |  | ||||||
| exports.format('default', ':remote-addr - - [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"'); |  | ||||||
|  |  | ||||||
| // short format |  | ||||||
|  |  | ||||||
| exports.format('short', ':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms'); |  | ||||||
|  |  | ||||||
| // tiny format |  | ||||||
|  |  | ||||||
| exports.format('tiny', ':method :url :status :res[content-length] - :response-time ms'); |  | ||||||
|  |  | ||||||
| // dev (colored) |  | ||||||
|  |  | ||||||
| exports.format('dev', function(tokens, req, res){ |  | ||||||
|   var status = res.statusCode |  | ||||||
|     , color = 32; |  | ||||||
|  |  | ||||||
|   if (status >= 500) color = 31 |  | ||||||
|   else if (status >= 400) color = 33 |  | ||||||
|   else if (status >= 300) color = 36; |  | ||||||
|  |  | ||||||
|   return '\033[90m' + req.method |  | ||||||
|     + ' ' + req.originalUrl + ' ' |  | ||||||
|     + '\033[' + color + 'm' + res.statusCode |  | ||||||
|     + ' \033[90m' |  | ||||||
|     + (new Date - req._startTime) |  | ||||||
|     + 'ms\033[0m'; |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // request url |  | ||||||
|  |  | ||||||
| exports.token('url', function(req){ |  | ||||||
|   return req.originalUrl; |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // request method |  | ||||||
|  |  | ||||||
| exports.token('method', function(req){ |  | ||||||
|   return req.method; |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // response time in milliseconds |  | ||||||
|  |  | ||||||
| exports.token('response-time', function(req){ |  | ||||||
|   return new Date - req._startTime; |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // UTC date |  | ||||||
|  |  | ||||||
| exports.token('date', function(){ |  | ||||||
|   return new Date().toUTCString(); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // response status code |  | ||||||
|  |  | ||||||
| exports.token('status', function(req, res){ |  | ||||||
|   return res.statusCode; |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // normalized referrer |  | ||||||
|  |  | ||||||
| exports.token('referrer', function(req){ |  | ||||||
|   return req.headers['referer'] || req.headers['referrer']; |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // remote address |  | ||||||
|  |  | ||||||
| exports.token('remote-addr', function(req){ |  | ||||||
|   return req.socket && (req.socket.remoteAddress || (req.socket.socket && req.socket.socket.remoteAddress)); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // HTTP version |  | ||||||
|  |  | ||||||
| exports.token('http-version', function(req){ |  | ||||||
|   return req.httpVersionMajor + '.' + req.httpVersionMinor; |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // UA string |  | ||||||
|  |  | ||||||
| exports.token('user-agent', function(req){ |  | ||||||
|   return req.headers['user-agent']; |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // request header |  | ||||||
|  |  | ||||||
| exports.token('req', function(req, res, field){ |  | ||||||
|   return req.headers[field.toLowerCase()]; |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // response header |  | ||||||
|  |  | ||||||
| exports.token('res', function(req, res, field){ |  | ||||||
|   return (res._headers || {})[field.toLowerCase()]; |  | ||||||
| }); |  | ||||||
|  |  | ||||||
							
								
								
									
										38
									
								
								node_modules/connect/lib/middleware/methodOverride.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,38 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - methodOverride |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Provides faux HTTP method support. |  | ||||||
|  *  |  | ||||||
|  * Pass an optional `key` to use when checking for |  | ||||||
|  * a method override, othewise defaults to _\_method_. |  | ||||||
|  * The original method is available via `req.originalMethod`. |  | ||||||
|  * |  | ||||||
|  * @param {String} key |  | ||||||
|  * @return {Function} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| module.exports = function methodOverride(key){ |  | ||||||
|   key = key || "_method"; |  | ||||||
|   return function methodOverride(req, res, next) { |  | ||||||
|     req.originalMethod = req.originalMethod || req.method; |  | ||||||
|  |  | ||||||
|     // req.body |  | ||||||
|     if (req.body && key in req.body) { |  | ||||||
|       req.method = req.body[key].toUpperCase(); |  | ||||||
|       delete req.body[key]; |  | ||||||
|     // check X-HTTP-Method-Override |  | ||||||
|     } else if (req.headers['x-http-method-override']) { |  | ||||||
|       req.method = req.headers['x-http-method-override'].toUpperCase(); |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     next(); |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
							
								
								
									
										100
									
								
								node_modules/connect/lib/middleware/profiler.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,100 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - profiler |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Profile the duration of a request. |  | ||||||
|  * |  | ||||||
|  * Typically this middleware should be utilized |  | ||||||
|  * _above_ all others, as it proxies the `res.end()` |  | ||||||
|  * method, being first allows it to encapsulate all |  | ||||||
|  * other middleware. |  | ||||||
|  * |  | ||||||
|  * Example Output: |  | ||||||
|  * |  | ||||||
|  *      GET / |  | ||||||
|  *      response time 2ms |  | ||||||
|  *      memory rss 52.00kb |  | ||||||
|  *      memory vsize 2.07mb |  | ||||||
|  *      heap before 3.76mb / 8.15mb |  | ||||||
|  *      heap after 3.80mb / 8.15mb |  | ||||||
|  * |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| module.exports = function profiler(){ |  | ||||||
|   return function(req, res, next){ |  | ||||||
|     var end = res.end |  | ||||||
|       , start = snapshot(); |  | ||||||
|  |  | ||||||
|     // state snapshot |  | ||||||
|     function snapshot() { |  | ||||||
|       return { |  | ||||||
|           mem: process.memoryUsage() |  | ||||||
|         , time: new Date |  | ||||||
|       }; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // proxy res.end() |  | ||||||
|     res.end = function(data, encoding){ |  | ||||||
|       res.end = end; |  | ||||||
|       res.end(data, encoding); |  | ||||||
|       compare(req, start, snapshot()) |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     next(); |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Compare `start` / `end` snapshots. |  | ||||||
|  * |  | ||||||
|  * @param {IncomingRequest} req |  | ||||||
|  * @param {Object} start |  | ||||||
|  * @param {Object} end |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function compare(req, start, end) { |  | ||||||
|   console.log(); |  | ||||||
|   row(req.method, req.url); |  | ||||||
|   row('response time:', (end.time - start.time) + 'ms'); |  | ||||||
|   row('memory rss:', formatBytes(end.mem.rss - start.mem.rss)); |  | ||||||
|   row('memory vsize:', formatBytes(end.mem.vsize - start.mem.vsize)); |  | ||||||
|   row('heap before:', formatBytes(start.mem.heapUsed) + ' / ' + formatBytes(start.mem.heapTotal)); |  | ||||||
|   row('heap after:', formatBytes(end.mem.heapUsed) + ' / ' + formatBytes(end.mem.heapTotal)); |  | ||||||
|   console.log(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Row helper |  | ||||||
|  * |  | ||||||
|  * @param {String} key |  | ||||||
|  * @param {String} val |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function row(key, val) { |  | ||||||
|   console.log('  \033[90m%s\033[0m \033[36m%s\033[0m', key, val); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Format byte-size. |  | ||||||
|  * |  | ||||||
|  * @param {Number} bytes |  | ||||||
|  * @return {String} |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function formatBytes(bytes) { |  | ||||||
|   var kb = 1024 |  | ||||||
|     , mb = 1024 * kb |  | ||||||
|     , gb = 1024 * mb; |  | ||||||
|   if (bytes < kb) return bytes + 'b'; |  | ||||||
|   if (bytes < mb) return (bytes / kb).toFixed(2) + 'kb'; |  | ||||||
|   if (bytes < gb) return (bytes / mb).toFixed(2) + 'mb'; |  | ||||||
|   return (bytes / gb).toFixed(2) + 'gb'; |  | ||||||
| }; |  | ||||||
							
								
								
									
										40
									
								
								node_modules/connect/lib/middleware/query.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,40 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - query |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * Copyright(c) 2011 Sencha Inc. |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var qs = require('qs') |  | ||||||
|   , parse = require('url').parse; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Automatically parse the query-string when available, |  | ||||||
|  * populating the `req.query` object. |  | ||||||
|  * |  | ||||||
|  * Examples: |  | ||||||
|  * |  | ||||||
|  *     connect( |  | ||||||
|  *         connect.query() |  | ||||||
|  *       , function(req, res){ |  | ||||||
|  *         res.end(JSON.stringify(req.query)); |  | ||||||
|  *       } |  | ||||||
|  *     ).listen(3000); |  | ||||||
|  * |  | ||||||
|  * @return {Function} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| module.exports = function query(){ |  | ||||||
|   return function query(req, res, next){ |  | ||||||
|     req.query = ~req.url.indexOf('?') |  | ||||||
|       ? qs.parse(parse(req.url).query) |  | ||||||
|       : {}; |  | ||||||
|     next(); |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
							
								
								
									
										34
									
								
								node_modules/connect/lib/middleware/responseTime.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,34 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - responseTime |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Adds the `X-Response-Time` header displaying the response |  | ||||||
|  * duration in milliseconds. |  | ||||||
|  * |  | ||||||
|  * @return {Function} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| module.exports = function responseTime(){ |  | ||||||
|   return function(req, res, next){ |  | ||||||
|     var writeHead = res.writeHead |  | ||||||
|       , start = new Date; |  | ||||||
|  |  | ||||||
|     if (res._responseTime) return next(); |  | ||||||
|     res._responseTime = true; |  | ||||||
|  |  | ||||||
|     // proxy writeHead to calculate duration |  | ||||||
|     res.writeHead = function(status, headers){ |  | ||||||
|       var duration = new Date - start; |  | ||||||
|       res.setHeader('X-Response-Time', duration + 'ms'); |  | ||||||
|       res.writeHead = writeHead; |  | ||||||
|       res.writeHead(status, headers); |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     next(); |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
							
								
								
									
										379
									
								
								node_modules/connect/lib/middleware/router.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,379 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - router |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var utils = require('../utils') |  | ||||||
|   , parse = require('url').parse; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Expose router. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports = module.exports = router; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Supported HTTP / WebDAV methods. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var _methods = exports.methods = [ |  | ||||||
|     'get' |  | ||||||
|   , 'post' |  | ||||||
|   , 'put' |  | ||||||
|   , 'delete' |  | ||||||
|   , 'connect' |  | ||||||
|   , 'options' |  | ||||||
|   , 'trace' |  | ||||||
|   , 'copy' |  | ||||||
|   , 'lock' |  | ||||||
|   , 'mkcol' |  | ||||||
|   , 'move' |  | ||||||
|   , 'propfind' |  | ||||||
|   , 'proppatch' |  | ||||||
|   , 'unlock' |  | ||||||
|   , 'report' |  | ||||||
|   , 'mkactivity' |  | ||||||
|   , 'checkout' |  | ||||||
|   , 'merge' |  | ||||||
| ]; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Provides Sinatra and Express-like routing capabilities. |  | ||||||
|  * |  | ||||||
|  * Examples: |  | ||||||
|  * |  | ||||||
|  *     connect.router(function(app){ |  | ||||||
|  *       app.get('/user/:id', function(req, res, next){ |  | ||||||
|  *         // populates req.params.id |  | ||||||
|  *       }); |  | ||||||
|  *       app.put('/user/:id', function(req, res, next){ |  | ||||||
|  *         // populates req.params.id |  | ||||||
|  *       }); |  | ||||||
|  *     }) |  | ||||||
|  * |  | ||||||
|  * @param {Function} fn |  | ||||||
|  * @return {Function} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function router(fn){ |  | ||||||
|   var self = this |  | ||||||
|     , methods = {} |  | ||||||
|     , routes = {} |  | ||||||
|     , params = {}; |  | ||||||
|  |  | ||||||
|   if (!fn) throw new Error('router provider requires a callback function'); |  | ||||||
|  |  | ||||||
|   // Generate method functions |  | ||||||
|   _methods.forEach(function(method){ |  | ||||||
|     methods[method] = generateMethodFunction(method.toUpperCase()); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   // Alias del -> delete |  | ||||||
|   methods.del = methods.delete; |  | ||||||
|  |  | ||||||
|   // Apply callback to all methods |  | ||||||
|   methods.all = function(){ |  | ||||||
|     var args = arguments; |  | ||||||
|     _methods.forEach(function(name){ |  | ||||||
|       methods[name].apply(this, args); |  | ||||||
|     }); |  | ||||||
|     return self; |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   // Register param callback |  | ||||||
|   methods.param = function(name, fn){ |  | ||||||
|     params[name] = fn; |  | ||||||
|   }; |  | ||||||
|        |  | ||||||
|   fn.call(this, methods); |  | ||||||
|  |  | ||||||
|   function generateMethodFunction(name) { |  | ||||||
|     var localRoutes = routes[name] = routes[name] || []; |  | ||||||
|     return function(path, fn){ |  | ||||||
|       var keys = [] |  | ||||||
|         , middleware = []; |  | ||||||
|  |  | ||||||
|       // slice middleware |  | ||||||
|       if (arguments.length > 2) { |  | ||||||
|         middleware = Array.prototype.slice.call(arguments, 1, arguments.length); |  | ||||||
|         fn = middleware.pop(); |  | ||||||
|         middleware = utils.flatten(middleware); |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       fn.middleware = middleware; |  | ||||||
|  |  | ||||||
|       if (!path) throw new Error(name + ' route requires a path'); |  | ||||||
|       if (!fn) throw new Error(name + ' route ' + path + ' requires a callback'); |  | ||||||
|       var regexp = path instanceof RegExp |  | ||||||
|         ? path |  | ||||||
|         : normalizePath(path, keys); |  | ||||||
|       localRoutes.push({ |  | ||||||
|           fn: fn |  | ||||||
|         , path: regexp |  | ||||||
|         , keys: keys |  | ||||||
|         , orig: path |  | ||||||
|         , method: name |  | ||||||
|       }); |  | ||||||
|       return self; |  | ||||||
|     }; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   function router(req, res, next){ |  | ||||||
|     var route |  | ||||||
|       , self = this; |  | ||||||
|  |  | ||||||
|     (function pass(i){ |  | ||||||
|       if (route = match(req, routes, i)) { |  | ||||||
|         var i = 0 |  | ||||||
|           , keys = route.keys; |  | ||||||
|  |  | ||||||
|         req.params = route.params; |  | ||||||
|  |  | ||||||
|         // Param preconditions |  | ||||||
|         (function param(err) { |  | ||||||
|           try { |  | ||||||
|             var key = keys[i++] |  | ||||||
|               , val = req.params[key] |  | ||||||
|               , fn = params[key]; |  | ||||||
|  |  | ||||||
|             if ('route' == err) { |  | ||||||
|               pass(req._route_index + 1); |  | ||||||
|             // Error |  | ||||||
|             } else if (err) { |  | ||||||
|               next(err); |  | ||||||
|             // Param has callback |  | ||||||
|             } else if (fn) { |  | ||||||
|               // Return style |  | ||||||
|               if (1 == fn.length) { |  | ||||||
|                 req.params[key] = fn(val); |  | ||||||
|                 param(); |  | ||||||
|               // Middleware style |  | ||||||
|               } else { |  | ||||||
|                 fn(req, res, param, val); |  | ||||||
|               } |  | ||||||
|             // Finished processing params |  | ||||||
|             } else if (!key) { |  | ||||||
|               // route middleware |  | ||||||
|               i = 0; |  | ||||||
|               (function nextMiddleware(err){ |  | ||||||
|                 var fn = route.middleware[i++]; |  | ||||||
|                 if ('route' == err) { |  | ||||||
|                   pass(req._route_index + 1); |  | ||||||
|                 } else if (err) { |  | ||||||
|                   next(err); |  | ||||||
|                 } else if (fn) { |  | ||||||
|                   fn(req, res, nextMiddleware); |  | ||||||
|                 } else { |  | ||||||
|                   route.call(self, req, res, function(err){ |  | ||||||
|                     if (err) { |  | ||||||
|                       next(err); |  | ||||||
|                     } else { |  | ||||||
|                       pass(req._route_index + 1); |  | ||||||
|                     } |  | ||||||
|                   }); |  | ||||||
|                 } |  | ||||||
|               })(); |  | ||||||
|             // More params |  | ||||||
|             } else { |  | ||||||
|               param(); |  | ||||||
|             } |  | ||||||
|           } catch (err) { |  | ||||||
|             next(err); |  | ||||||
|           } |  | ||||||
|         })(); |  | ||||||
|       } else if ('OPTIONS' == req.method) { |  | ||||||
|         options(req, res, routes); |  | ||||||
|       } else { |  | ||||||
|         next(); |  | ||||||
|       } |  | ||||||
|     })(); |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   router.remove = function(path, method){ |  | ||||||
|     var fns = router.lookup(path, method); |  | ||||||
|     fns.forEach(function(fn){ |  | ||||||
|       routes[fn.method].splice(fn.index, 1); |  | ||||||
|     }); |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   router.lookup = function(path, method, ret){ |  | ||||||
|     ret = ret || []; |  | ||||||
|  |  | ||||||
|     // method specific lookup |  | ||||||
|     if (method) { |  | ||||||
|       method = method.toUpperCase(); |  | ||||||
|       if (routes[method]) { |  | ||||||
|         routes[method].forEach(function(route, i){ |  | ||||||
|           if (path == route.orig) { |  | ||||||
|             var fn = route.fn; |  | ||||||
|             fn.regexp = route.path; |  | ||||||
|             fn.keys = route.keys; |  | ||||||
|             fn.path = route.orig; |  | ||||||
|             fn.method = route.method; |  | ||||||
|             fn.index = i; |  | ||||||
|             ret.push(fn); |  | ||||||
|           } |  | ||||||
|         }); |  | ||||||
|       } |  | ||||||
|     // global lookup |  | ||||||
|     } else { |  | ||||||
|       _methods.forEach(function(method){ |  | ||||||
|         router.lookup(path, method, ret); |  | ||||||
|       }); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return ret; |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   router.match = function(url, method, ret){ |  | ||||||
|     var ret = ret || [] |  | ||||||
|       , i = 0 |  | ||||||
|       , fn |  | ||||||
|       , req; |  | ||||||
|  |  | ||||||
|     // method specific matches |  | ||||||
|     if (method) { |  | ||||||
|       method = method.toUpperCase(); |  | ||||||
|       req = { url: url, method: method }; |  | ||||||
|       while (fn = match(req, routes, i)) { |  | ||||||
|         i = req._route_index + 1; |  | ||||||
|         ret.push(fn); |  | ||||||
|       }  |  | ||||||
|     // global matches |  | ||||||
|     } else { |  | ||||||
|       _methods.forEach(function(method){ |  | ||||||
|         router.match(url, method, ret); |  | ||||||
|       }); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return ret; |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   return router; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Respond to OPTIONS. |  | ||||||
|  * |  | ||||||
|  * @param {ServerRequest} req |  | ||||||
|  * @param {ServerResponse} req |  | ||||||
|  * @param {Array} routes |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function options(req, res, routes) { |  | ||||||
|   var pathname = parse(req.url).pathname |  | ||||||
|     , body = optionsFor(pathname, routes).join(','); |  | ||||||
|   res.writeHead(200, { |  | ||||||
|       'Content-Length': body.length |  | ||||||
|     , 'Allow': body |  | ||||||
|   }); |  | ||||||
|   res.end(body); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Return OPTIONS array for the given `path`, matching `routes`. |  | ||||||
|  * |  | ||||||
|  * @param {String} path |  | ||||||
|  * @param {Array} routes |  | ||||||
|  * @return {Array} |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function optionsFor(path, routes) { |  | ||||||
|   return _methods.filter(function(method){ |  | ||||||
|     var arr = routes[method.toUpperCase()]; |  | ||||||
|     for (var i = 0, len = arr.length; i < len; ++i) { |  | ||||||
|       if (arr[i].path.test(path)) return true; |  | ||||||
|     } |  | ||||||
|   }).map(function(method){ |  | ||||||
|     return method.toUpperCase(); |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Normalize the given path string, |  | ||||||
|  * returning a regular expression. |  | ||||||
|  * |  | ||||||
|  * An empty array should be passed, |  | ||||||
|  * which will contain the placeholder |  | ||||||
|  * key names. For example "/user/:id" will |  | ||||||
|  * then contain ["id"]. |  | ||||||
|  * |  | ||||||
|  * @param  {String} path |  | ||||||
|  * @param  {Array} keys |  | ||||||
|  * @return {RegExp} |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function normalizePath(path, keys) { |  | ||||||
|   path = path |  | ||||||
|     .concat('/?') |  | ||||||
|     .replace(/\/\(/g, '(?:/') |  | ||||||
|     .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?/g, function(_, slash, format, key, capture, optional){ |  | ||||||
|       keys.push(key); |  | ||||||
|       slash = slash || ''; |  | ||||||
|       return '' |  | ||||||
|         + (optional ? '' : slash) |  | ||||||
|         + '(?:' |  | ||||||
|         + (optional ? slash : '') |  | ||||||
|         + (format || '') + (capture || '([^/]+?)') + ')' |  | ||||||
|         + (optional || ''); |  | ||||||
|     }) |  | ||||||
|     .replace(/([\/.])/g, '\\$1') |  | ||||||
|     .replace(/\*/g, '(.+)'); |  | ||||||
|   return new RegExp('^' + path + '$', 'i'); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Attempt to match the given request to |  | ||||||
|  * one of the routes. When successful |  | ||||||
|  * a route function is returned. |  | ||||||
|  * |  | ||||||
|  * @param  {ServerRequest} req |  | ||||||
|  * @param  {Object} routes |  | ||||||
|  * @return {Function} |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function match(req, routes, i) { |  | ||||||
|   var captures |  | ||||||
|     , method = req.method |  | ||||||
|     , i = i || 0; |  | ||||||
|   if ('HEAD' == method) method = 'GET'; |  | ||||||
|   if (routes = routes[method]) { |  | ||||||
|     var url = parse(req.url) |  | ||||||
|       , pathname = url.pathname; |  | ||||||
|     for (var len = routes.length; i < len; ++i) { |  | ||||||
|       var route = routes[i] |  | ||||||
|         , fn = route.fn |  | ||||||
|         , path = route.path |  | ||||||
|         , keys = fn.keys = route.keys; |  | ||||||
|       if (captures = path.exec(pathname)) { |  | ||||||
|         fn.method = method; |  | ||||||
|         fn.params = []; |  | ||||||
|         for (var j = 1, len = captures.length; j < len; ++j) { |  | ||||||
|           var key = keys[j-1], |  | ||||||
|             val = typeof captures[j] === 'string' |  | ||||||
|               ? decodeURIComponent(captures[j]) |  | ||||||
|               : captures[j]; |  | ||||||
|           if (key) { |  | ||||||
|             fn.params[key] = val; |  | ||||||
|           } else { |  | ||||||
|             fn.params.push(val); |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|         req._route_index = i; |  | ||||||
|         return fn; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
							
								
								
									
										346
									
								
								node_modules/connect/lib/middleware/session.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,346 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - session |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var Session = require('./session/session') |  | ||||||
|   , MemoryStore = require('./session/memory') |  | ||||||
|   , Cookie = require('./session/cookie') |  | ||||||
|   , Store = require('./session/store') |  | ||||||
|   , utils = require('./../utils') |  | ||||||
|   , parse = require('url').parse |  | ||||||
|   , crypto = require('crypto'); |  | ||||||
|  |  | ||||||
| // environment |  | ||||||
|  |  | ||||||
| var env = process.env.NODE_ENV; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Expose the middleware. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports = module.exports = session; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Expose constructors. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports.Store = Store; |  | ||||||
| exports.Cookie = Cookie; |  | ||||||
| exports.Session = Session; |  | ||||||
| exports.MemoryStore = MemoryStore; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Warning message for `MemoryStore` usage in production. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var warning = 'Warning: connection.session() MemoryStore is not\n' |  | ||||||
|   + 'designed for a production environment, as it will leak\n' |  | ||||||
|   + 'memory, and obviously only work within a single process.'; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Default finger-printing function. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function defaultFingerprint(req) { |  | ||||||
|   var ua = req.headers['user-agent'] || ''; |  | ||||||
|   return ua.replace(/;?\schromeframe\/[\d\.]+/, ''); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Paths to ignore. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports.ignore = []; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Setup session store with the given `options`. |  | ||||||
|  * |  | ||||||
|  * Session data is _not_ saved in the cookie itself, however |  | ||||||
|  * cookies are used, so we must use the [cookieParser()](middleware-cookieParser.html) |  | ||||||
|  * middleware _before_ `session()`. |  | ||||||
|  * |  | ||||||
|  * Examples: |  | ||||||
|  * |  | ||||||
|  *     connect.createServer( |  | ||||||
|  *         connect.cookieParser() |  | ||||||
|  *       , connect.session({ secret: 'keyboard cat' }) |  | ||||||
|  *     ); |  | ||||||
|  * |  | ||||||
|  * Options: |  | ||||||
|  * |  | ||||||
|  *   - `key`           cookie name defaulting to `connect.sid` |  | ||||||
|  *   - `store`         Session store instance |  | ||||||
|  *   - `fingerprint`   Custom fingerprint generating function |  | ||||||
|  *   - `cookie`        Session cookie settings, defaulting to `{ path: '/', httpOnly: true, maxAge: 14400000 }` |  | ||||||
|  *   - `secret`        Secret string used to compute hash |  | ||||||
|  * |  | ||||||
|  * Ignore Paths: |  | ||||||
|  * |  | ||||||
|  *  By default `/favicon.ico` is the only ignored path, all others |  | ||||||
|  *  will utilize sessions, to manipulate the paths ignored, use |  | ||||||
|  * `connect.session.ignore.push('/my/path')`. This works for _full_ |  | ||||||
|  *  pathnames only, not segments nor substrings. |  | ||||||
|  * |  | ||||||
|  *     connect.session.ignore.push('/robots.txt'); |  | ||||||
|  * |  | ||||||
|  * ## req.session |  | ||||||
|  * |  | ||||||
|  *  To store or access session data, simply use the request property `req.session`, |  | ||||||
|  *  which is (generally) serialized as JSON by the store, so nested objects  |  | ||||||
|  *  are typically fine. For example below is a user-specific view counter: |  | ||||||
|  * |  | ||||||
|  *       connect( |  | ||||||
|  *           connect.cookieParser() |  | ||||||
|  *         , connect.session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }}) |  | ||||||
|  *         , connect.favicon() |  | ||||||
|  *         , function(req, res, next){ |  | ||||||
|  *           var sess = req.session; |  | ||||||
|  *           if (sess.views) { |  | ||||||
|  *             res.setHeader('Content-Type', 'text/html'); |  | ||||||
|  *             res.write('<p>views: ' + sess.views + '</p>'); |  | ||||||
|  *             res.write('<p>expires in: ' + (sess.cookie.maxAge / 1000) + 's</p>'); |  | ||||||
|  *             res.end(); |  | ||||||
|  *             sess.views++; |  | ||||||
|  *           } else { |  | ||||||
|  *             sess.views = 1; |  | ||||||
|  *             res.end('welcome to the session demo. refresh!'); |  | ||||||
|  *           } |  | ||||||
|  *         } |  | ||||||
|  *       ).listen(3000); |  | ||||||
|  * |  | ||||||
|  * ## Session#regenerate() |  | ||||||
|  * |  | ||||||
|  *  To regenerate the session simply invoke the method, once complete |  | ||||||
|  *  a new SID and `Session` instance will be initialized at `req.session`. |  | ||||||
|  * |  | ||||||
|  *      req.session.regenerate(function(err){ |  | ||||||
|  *        // will have a new session here |  | ||||||
|  *      }); |  | ||||||
|  * |  | ||||||
|  * ## Session#destroy() |  | ||||||
|  * |  | ||||||
|  *  Destroys the session, removing `req.session`, will be re-generated next request. |  | ||||||
|  * |  | ||||||
|  *      req.session.destroy(function(err){ |  | ||||||
|  *        // cannot access session here |  | ||||||
|  *      }); |  | ||||||
|  *  |  | ||||||
|  * ## Session#reload() |  | ||||||
|  * |  | ||||||
|  *  Reloads the session data. |  | ||||||
|  * |  | ||||||
|  *      req.session.reload(function(err){ |  | ||||||
|  *        // session updated |  | ||||||
|  *      }); |  | ||||||
|  * |  | ||||||
|  * ## Session#save() |  | ||||||
|  * |  | ||||||
|  *  Save the session. |  | ||||||
|  * |  | ||||||
|  *      req.session.save(function(err){ |  | ||||||
|  *        // session saved |  | ||||||
|  *      }); |  | ||||||
|  * |  | ||||||
|  * ## Session#touch() |  | ||||||
|  * |  | ||||||
|  *   Updates the `.maxAge`, and `.lastAccess` properties. Typically this is |  | ||||||
|  *   not necessary to call, as the session middleware does this for you. |  | ||||||
|  * |  | ||||||
|  * ## Session#cookie |  | ||||||
|  * |  | ||||||
|  *  Each session has a unique cookie object accompany it. This allows |  | ||||||
|  *  you to alter the session cookie per visitor. For example we can |  | ||||||
|  *  set `req.session.cookie.expires` to `false` to enable the cookie |  | ||||||
|  *  to remain for only the duration of the user-agent. |  | ||||||
|  * |  | ||||||
|  * ## Session#maxAge |  | ||||||
|  * |  | ||||||
|  *  Alternatively `req.session.cookie.maxAge` will return the time |  | ||||||
|  *  remaining in milliseconds, which we may also re-assign a new value |  | ||||||
|  *  to adjust the `.expires` property appropriately. The following |  | ||||||
|  *  are essentially equivalent |  | ||||||
|  * |  | ||||||
|  *     var hour = 3600000; |  | ||||||
|  *     req.session.cookie.expires = new Date(Date.now() + hour); |  | ||||||
|  *     req.session.cookie.maxAge = hour; |  | ||||||
|  * |  | ||||||
|  * For example when `maxAge` is set to `60000` (one minute), and 30 seconds |  | ||||||
|  * has elapsed it will return `30000` until the current request has completed, |  | ||||||
|  * at which time `req.session.touch()` is called to update `req.session.lastAccess`, |  | ||||||
|  * and reset `req.session.maxAge` to its original value. |  | ||||||
|  * |  | ||||||
|  *     req.session.cookie.maxAge; |  | ||||||
|  *     // => 30000 |  | ||||||
|  * |  | ||||||
|  * Session Store Implementation: |  | ||||||
|  * |  | ||||||
|  * Every session store _must_ implement the following methods |  | ||||||
|  * |  | ||||||
|  *    - `.get(sid, callback)` |  | ||||||
|  *    - `.set(sid, session, callback)` |  | ||||||
|  *    - `.destroy(sid, callback)` |  | ||||||
|  * |  | ||||||
|  * Recommended methods include, but are not limited to: |  | ||||||
|  * |  | ||||||
|  *    - `.length(callback)` |  | ||||||
|  *    - `.clear(callback)` |  | ||||||
|  * |  | ||||||
|  * For an example implementation view the [connect-redis](http://github.com/visionmedia/connect-redis) repo. |  | ||||||
|  * |  | ||||||
|  * @param {Object} options |  | ||||||
|  * @return {Function} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function session(options){ |  | ||||||
|   var options = options || {} |  | ||||||
|     , key = options.key || 'connect.sid' |  | ||||||
|     , secret = options.secret |  | ||||||
|     , store = options.store || new MemoryStore |  | ||||||
|     , fingerprint = options.fingerprint || defaultFingerprint |  | ||||||
|     , cookie = options.cookie; |  | ||||||
|  |  | ||||||
|   // notify user that this store is not |  | ||||||
|   // meant for a production environment |  | ||||||
|   if ('production' == env && store instanceof MemoryStore) { |  | ||||||
|     console.warn(warning); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // ensure secret is present |  | ||||||
|   if (!secret) { |  | ||||||
|     throw new Error('connect.session({ secret: "string" }) required for security'); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // session hashing function |  | ||||||
|   store.hash = function(req, base) { |  | ||||||
|     return crypto |  | ||||||
|       .createHmac('sha256', secret) |  | ||||||
|       .update(base + fingerprint(req)) |  | ||||||
|       .digest('base64') |  | ||||||
|       .replace(/=*$/, ''); |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   // generates the new session |  | ||||||
|   store.generate = function(req){ |  | ||||||
|     var base = utils.uid(24); |  | ||||||
|     var sessionID = base + '.' + store.hash(req, base); |  | ||||||
|     req.sessionID = sessionID; |  | ||||||
|     req.session = new Session(req); |  | ||||||
|     req.session.cookie = new Cookie(cookie); |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   return function session(req, res, next) { |  | ||||||
|     // self-awareness |  | ||||||
|     if (req.session) return next(); |  | ||||||
|  |  | ||||||
|     // parse url |  | ||||||
|     var url = parse(req.url) |  | ||||||
|       , path = url.pathname; |  | ||||||
|  |  | ||||||
|     // ignorable paths |  | ||||||
|     if (~exports.ignore.indexOf(path)) return next(); |  | ||||||
|  |  | ||||||
|     // expose store |  | ||||||
|     req.sessionStore = store; |  | ||||||
|  |  | ||||||
|     // proxy writeHead() to Set-Cookie |  | ||||||
|     var writeHead = res.writeHead; |  | ||||||
|     res.writeHead = function(status, headers){ |  | ||||||
|       if (req.session) { |  | ||||||
|         var cookie = req.session.cookie; |  | ||||||
|         // only send secure session cookies when there is a secure connection. |  | ||||||
|         // proxySecure is a custom attribute to allow for a reverse proxy |  | ||||||
|         // to handle SSL connections and to communicate to connect over HTTP that |  | ||||||
|         // the incoming connection is secure. |  | ||||||
|         var secured = cookie.secure && (req.connection.encrypted || req.connection.proxySecure); |  | ||||||
|         if (secured || !cookie.secure) { |  | ||||||
|           res.setHeader('Set-Cookie', cookie.serialize(key, req.sessionID)); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       res.writeHead = writeHead; |  | ||||||
|       return res.writeHead(status, headers); |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     // proxy end() to commit the session |  | ||||||
|     var end = res.end; |  | ||||||
|     res.end = function(data, encoding){ |  | ||||||
|       res.end = end; |  | ||||||
|       if (req.session) { |  | ||||||
|         // HACK: ensure Set-Cookie for implicit writeHead() |  | ||||||
|         if (!res._header) res._implicitHeader(); |  | ||||||
|         req.session.resetMaxAge(); |  | ||||||
|         req.session.save(function(){ |  | ||||||
|           res.end(data, encoding); |  | ||||||
|         }); |  | ||||||
|       } else { |  | ||||||
|         res.end(data, encoding); |  | ||||||
|       } |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     // session hashing |  | ||||||
|     function hash(base) { |  | ||||||
|       return store.hash(req, base); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // generate the session |  | ||||||
|     function generate() { |  | ||||||
|       store.generate(req); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // get the sessionID from the cookie |  | ||||||
|     req.sessionID = req.cookies[key]; |  | ||||||
|  |  | ||||||
|     // make a new session if the browser doesn't send a sessionID |  | ||||||
|     if (!req.sessionID) { |  | ||||||
|       generate(); |  | ||||||
|       next(); |  | ||||||
|       return; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // check the fingerprint |  | ||||||
|     var parts = req.sessionID.split('.'); |  | ||||||
|     if (parts[1] != hash(parts[0])) { |  | ||||||
|       generate(); |  | ||||||
|       next(); |  | ||||||
|       return; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // generate the session object |  | ||||||
|     var pause = utils.pause(req); |  | ||||||
|     store.get(req.sessionID, function(err, sess){ |  | ||||||
|       // proxy to resume() events |  | ||||||
|       var _next = next; |  | ||||||
|       next = function(err){ |  | ||||||
|         _next(err); |  | ||||||
|         pause.resume(); |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       // error handling |  | ||||||
|       if (err) { |  | ||||||
|         if ('ENOENT' == err.code) { |  | ||||||
|           generate(); |  | ||||||
|           next(); |  | ||||||
|         } else { |  | ||||||
|           next(err); |  | ||||||
|         } |  | ||||||
|       // no session |  | ||||||
|       } else if (!sess) { |  | ||||||
|         generate(); |  | ||||||
|         next(); |  | ||||||
|       // populate req.session |  | ||||||
|       } else { |  | ||||||
|         store.createSession(req, sess); |  | ||||||
|         next(); |  | ||||||
|       } |  | ||||||
|     }); |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
							
								
								
									
										126
									
								
								node_modules/connect/lib/middleware/session/cookie.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,126 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - session - Cookie |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var utils = require('../../utils'); |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Initialize a new `Cookie` with the given `options`. |  | ||||||
|  * |  | ||||||
|  * @param {Object} options |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var Cookie = module.exports = function Cookie(options) { |  | ||||||
|   this.path = '/'; |  | ||||||
|   this.httpOnly = true; |  | ||||||
|   this.maxAge = 14400000; |  | ||||||
|   if (options) utils.merge(this, options); |  | ||||||
|   this.originalMaxAge = undefined == this.originalMaxAge |  | ||||||
|     ? this.maxAge |  | ||||||
|     : this.originalMaxAge; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Prototype. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Cookie.prototype = { |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Set expires `date`. |  | ||||||
|    * |  | ||||||
|    * @param {Date} date |  | ||||||
|    * @api public |  | ||||||
|    */ |  | ||||||
|    |  | ||||||
|   set expires(date) { |  | ||||||
|     this._expires = date; |  | ||||||
|     this.originalMaxAge = this.maxAge; |  | ||||||
|   }, |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Get expires `date`. |  | ||||||
|    * |  | ||||||
|    * @return {Date} |  | ||||||
|    * @api public |  | ||||||
|    */ |  | ||||||
|  |  | ||||||
|   get expires() { |  | ||||||
|     return this._expires; |  | ||||||
|   }, |  | ||||||
|    |  | ||||||
|   /** |  | ||||||
|    * Set expires via max-age in `ms`. |  | ||||||
|    * |  | ||||||
|    * @param {Number} ms |  | ||||||
|    * @api public |  | ||||||
|    */ |  | ||||||
|    |  | ||||||
|   set maxAge(ms) { |  | ||||||
|     this.expires = 'number' == typeof ms |  | ||||||
|       ? new Date(Date.now() + ms) |  | ||||||
|       : ms; |  | ||||||
|   }, |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Get expires max-age in `ms`. |  | ||||||
|    * |  | ||||||
|    * @return {Number} |  | ||||||
|    * @api public |  | ||||||
|    */ |  | ||||||
|  |  | ||||||
|   get maxAge() { |  | ||||||
|     return this.expires instanceof Date |  | ||||||
|       ? this.expires.valueOf() - Date.now() |  | ||||||
|       : this.expires; |  | ||||||
|   }, |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Return cookie data object. |  | ||||||
|    * |  | ||||||
|    * @return {Object} |  | ||||||
|    * @api private |  | ||||||
|    */ |  | ||||||
|  |  | ||||||
|   get data() { |  | ||||||
|     return { |  | ||||||
|         originalMaxAge: this.originalMaxAge |  | ||||||
|       , expires: this._expires |  | ||||||
|       , secure: this.secure |  | ||||||
|       , httpOnly: this.httpOnly |  | ||||||
|       , domain: this.domain |  | ||||||
|       , path: this.path |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Return a serialized cookie string. |  | ||||||
|    * |  | ||||||
|    * @return {String} |  | ||||||
|    * @api public |  | ||||||
|    */ |  | ||||||
|  |  | ||||||
|   serialize: function(name, val){ |  | ||||||
|     return utils.serializeCookie(name, val, this.data); |  | ||||||
|   }, |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Return JSON representation of this cookie. |  | ||||||
|    * |  | ||||||
|    * @return {Object} |  | ||||||
|    * @api private |  | ||||||
|    */ |  | ||||||
|    |  | ||||||
|   toJSON: function(){ |  | ||||||
|     return this.data; |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
							
								
								
									
										131
									
								
								node_modules/connect/lib/middleware/session/memory.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,131 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - session - MemoryStore |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var Store = require('./store') |  | ||||||
|   , utils = require('../../utils') |  | ||||||
|   , Session = require('./session'); |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Initialize a new `MemoryStore`. |  | ||||||
|  * |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var MemoryStore = module.exports = function MemoryStore() { |  | ||||||
|   this.sessions = {}; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Inherit from `Store.prototype`. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| MemoryStore.prototype.__proto__ = Store.prototype; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Attempt to fetch session by the given `sid`. |  | ||||||
|  * |  | ||||||
|  * @param {String} sid |  | ||||||
|  * @param {Function} fn |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| MemoryStore.prototype.get = function(sid, fn){ |  | ||||||
|   var self = this; |  | ||||||
|   process.nextTick(function(){ |  | ||||||
|     var expires |  | ||||||
|       , sess = self.sessions[sid]; |  | ||||||
|     if (sess) { |  | ||||||
|       sess = JSON.parse(sess); |  | ||||||
|       expires = 'string' == typeof sess.cookie.expires |  | ||||||
|         ? new Date(sess.cookie.expires) |  | ||||||
|         : sess.cookie.expires; |  | ||||||
|       if (!expires || new Date < expires) { |  | ||||||
|         fn(null, sess); |  | ||||||
|       } else { |  | ||||||
|         self.destroy(sid, fn); |  | ||||||
|       } |  | ||||||
|     } else { |  | ||||||
|       fn(); |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Commit the given `sess` object associated with the given `sid`. |  | ||||||
|  * |  | ||||||
|  * @param {String} sid |  | ||||||
|  * @param {Session} sess |  | ||||||
|  * @param {Function} fn |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| MemoryStore.prototype.set = function(sid, sess, fn){ |  | ||||||
|   var self = this; |  | ||||||
|   process.nextTick(function(){ |  | ||||||
|     self.sessions[sid] = JSON.stringify(sess); |  | ||||||
|     fn && fn(); |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Destroy the session associated with the given `sid`. |  | ||||||
|  * |  | ||||||
|  * @param {String} sid |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| MemoryStore.prototype.destroy = function(sid, fn){ |  | ||||||
|   var self = this; |  | ||||||
|   process.nextTick(function(){ |  | ||||||
|     delete self.sessions[sid]; |  | ||||||
|     fn && fn(); |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Invoke the given callback `fn` with all active sessions. |  | ||||||
|  * |  | ||||||
|  * @param {Function} fn |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| MemoryStore.prototype.all = function(fn){ |  | ||||||
|   var arr = [] |  | ||||||
|     , keys = Object.keys(this.sessions); |  | ||||||
|   for (var i = 0, len = keys.length; i < len; ++i) { |  | ||||||
|     arr.push(this.sessions[keys[i]]); |  | ||||||
|   } |  | ||||||
|   fn(null, arr); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Clear all sessions. |  | ||||||
|  * |  | ||||||
|  * @param {Function} fn |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| MemoryStore.prototype.clear = function(fn){ |  | ||||||
|   this.sessions = {}; |  | ||||||
|   fn && fn(); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Fetch number of sessions. |  | ||||||
|  * |  | ||||||
|  * @param {Function} fn |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| MemoryStore.prototype.length = function(fn){ |  | ||||||
|   fn(null, Object.keys(this.sessions).length); |  | ||||||
| }; |  | ||||||
							
								
								
									
										137
									
								
								node_modules/connect/lib/middleware/session/session.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,137 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - session - Session |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var utils = require('../../utils') |  | ||||||
|   , Cookie = require('./cookie'); |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Create a new `Session` with the given request and `data`. |  | ||||||
|  * |  | ||||||
|  * @param {IncomingRequest} req |  | ||||||
|  * @param {Object} data |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var Session = module.exports = function Session(req, data) { |  | ||||||
|   Object.defineProperty(this, 'req', { value: req }); |  | ||||||
|   Object.defineProperty(this, 'id', { value: req.sessionID }); |  | ||||||
|   if ('object' == typeof data) { |  | ||||||
|     utils.merge(this, data); |  | ||||||
|   } else { |  | ||||||
|     this.lastAccess = Date.now(); |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Update `.lastAccess` timestamp, |  | ||||||
|  * and reset `.cookie.maxAge` to prevent |  | ||||||
|  * the cookie from expiring when the |  | ||||||
|  * session is still active. |  | ||||||
|  * |  | ||||||
|  * @return {Session} for chaining |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Session.prototype.touch = function(){ |  | ||||||
|   return this |  | ||||||
|     .resetLastAccess() |  | ||||||
|     .resetMaxAge(); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Update `.lastAccess` timestamp. |  | ||||||
|  * |  | ||||||
|  * @return {Session} for chaining |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Session.prototype.resetLastAccess = function(){ |  | ||||||
|   this.lastAccess = Date.now(); |  | ||||||
|   return this; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Reset `.maxAge` to `.originalMaxAge`. |  | ||||||
|  * |  | ||||||
|  * @return {Session} for chaining |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Session.prototype.resetMaxAge = function(){ |  | ||||||
|   this.cookie.maxAge = this.cookie.originalMaxAge; |  | ||||||
|   return this; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Save the session data with optional callback `fn(err)`. |  | ||||||
|  * |  | ||||||
|  * @param {Function} fn |  | ||||||
|  * @return {Session} for chaining |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Session.prototype.save = function(fn){ |  | ||||||
|   this.req.sessionStore.set(this.id, this, fn || function(){}); |  | ||||||
|   return this; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Re-loads the session data _without_ altering |  | ||||||
|  * the maxAge or lastAccess properties. Invokes the |  | ||||||
|  * callback `fn(err)`, after which time if no exception |  | ||||||
|  * has occurred the `req.session` property will be |  | ||||||
|  * a new `Session` object, although representing the |  | ||||||
|  * same session. |  | ||||||
|  * |  | ||||||
|  * @param {Function} fn |  | ||||||
|  * @return {Session} for chaining |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Session.prototype.reload = function(fn){ |  | ||||||
|   var req = this.req |  | ||||||
|     , store = this.req.sessionStore; |  | ||||||
|   store.get(this.id, function(err, sess){ |  | ||||||
|     if (err) return fn(err); |  | ||||||
|     if (!sess) return fn(new Error('failed to load session')); |  | ||||||
|     store.createSession(req, sess); |  | ||||||
|     fn(); |  | ||||||
|   }); |  | ||||||
|   return this; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Destroy `this` session. |  | ||||||
|  * |  | ||||||
|  * @param {Function} fn |  | ||||||
|  * @return {Session} for chaining |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Session.prototype.destroy = function(fn){ |  | ||||||
|   delete this.req.session; |  | ||||||
|   this.req.sessionStore.destroy(this.id, fn); |  | ||||||
|   return this; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Regenerate this request's session. |  | ||||||
|  * |  | ||||||
|  * @param {Function} fn |  | ||||||
|  * @return {Session} for chaining |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Session.prototype.regenerate = function(fn){ |  | ||||||
|   this.req.sessionStore.regenerate(this.req, fn); |  | ||||||
|   return this; |  | ||||||
| }; |  | ||||||
							
								
								
									
										87
									
								
								node_modules/connect/lib/middleware/session/store.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,87 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - session - Store |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var EventEmitter = require('events').EventEmitter |  | ||||||
|   , Session = require('./session') |  | ||||||
|   , Cookie = require('./cookie') |  | ||||||
|   , utils = require('../../utils'); |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Initialize abstract `Store`. |  | ||||||
|  * |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var Store = module.exports = function Store(options){}; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Inherit from `EventEmitter.prototype`. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Store.prototype.__proto__ = EventEmitter.prototype; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Re-generate the given requests's session. |  | ||||||
|  * |  | ||||||
|  * @param {IncomingRequest} req |  | ||||||
|  * @return {Function} fn |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Store.prototype.regenerate = function(req, fn){ |  | ||||||
|   var self = this; |  | ||||||
|   this.destroy(req.sessionID, function(err){ |  | ||||||
|     self.generate(req); |  | ||||||
|     fn(err); |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Load a `Session` instance via the given `sid` |  | ||||||
|  * and invoke the callback `fn(err, sess)`. |  | ||||||
|  * |  | ||||||
|  * @param {String} sid |  | ||||||
|  * @param {Function} fn |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Store.prototype.load = function(sid, fn){ |  | ||||||
|   var self = this; |  | ||||||
|   this.get(sid, function(err, sess){ |  | ||||||
|     if (err) return fn(err); |  | ||||||
|     if (!sess) return fn(); |  | ||||||
|     var req = { sessionID: sid, sessionStore: self }; |  | ||||||
|     sess = self.createSession(req, sess, false); |  | ||||||
|     fn(null, sess); |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Create session from JSON `sess` data. |  | ||||||
|  * |  | ||||||
|  * @param {IncomingRequest} req |  | ||||||
|  * @param {Object} sess |  | ||||||
|  * @return {Session} |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| Store.prototype.createSession = function(req, sess, update){ |  | ||||||
|   var expires = sess.cookie.expires |  | ||||||
|     , orig = sess.cookie.originalMaxAge |  | ||||||
|     , update = null == update ? true : false; |  | ||||||
|   sess.cookie = new Cookie(sess.cookie); |  | ||||||
|   if ('string' == typeof expires) sess.cookie.expires = new Date(expires); |  | ||||||
|   sess.cookie.originalMaxAge = orig; |  | ||||||
|   req.session = new Session(req, sess); |  | ||||||
|   if (update) req.session.resetLastAccess(); |  | ||||||
|   return req.session; |  | ||||||
| }; |  | ||||||
							
								
								
									
										225
									
								
								node_modules/connect/lib/middleware/static.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,225 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - staticProvider |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var fs = require('fs') |  | ||||||
|   , path = require('path') |  | ||||||
|   , join = path.join |  | ||||||
|   , basename = path.basename |  | ||||||
|   , normalize = path.normalize |  | ||||||
|   , utils = require('../utils') |  | ||||||
|   , Buffer = require('buffer').Buffer |  | ||||||
|   , parse = require('url').parse |  | ||||||
|   , mime = require('mime'); |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Static file server with the given `root` path. |  | ||||||
|  * |  | ||||||
|  * Examples: |  | ||||||
|  * |  | ||||||
|  *     var oneDay = 86400000; |  | ||||||
|  * |  | ||||||
|  *     connect( |  | ||||||
|  *       connect.static(__dirname + '/public') |  | ||||||
|  *     ).listen(3000); |  | ||||||
|  * |  | ||||||
|  *     connect( |  | ||||||
|  *       connect.static(__dirname + '/public', { maxAge: oneDay }) |  | ||||||
|  *     ).listen(3000); |  | ||||||
|  * |  | ||||||
|  * Options: |  | ||||||
|  * |  | ||||||
|  *    - `maxAge`   Browser cache maxAge in milliseconds. defaults to 0 |  | ||||||
|  *    - `hidden`   Allow transfer of hidden files. defaults to false |  | ||||||
|  *    - `redirect`   Redirect to trailing "/" when the pathname is a dir |  | ||||||
|  * |  | ||||||
|  * @param {String} root |  | ||||||
|  * @param {Object} options |  | ||||||
|  * @return {Function} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports = module.exports = function static(root, options){ |  | ||||||
|   options = options || {}; |  | ||||||
|  |  | ||||||
|   // root required |  | ||||||
|   if (!root) throw new Error('static() root path required'); |  | ||||||
|   options.root = root; |  | ||||||
|  |  | ||||||
|   return function static(req, res, next) { |  | ||||||
|     options.path = req.url; |  | ||||||
|     options.getOnly = true; |  | ||||||
|     send(req, res, next, options); |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Expose mime module. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| exports.mime = mime; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Respond with 416  "Requested Range Not Satisfiable" |  | ||||||
|  * |  | ||||||
|  * @param {ServerResponse} res |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function invalidRange(res) { |  | ||||||
|   var body = 'Requested Range Not Satisfiable'; |  | ||||||
|   res.setHeader('Content-Type', 'text/plain'); |  | ||||||
|   res.setHeader('Content-Length', body.length); |  | ||||||
|   res.statusCode = 416; |  | ||||||
|   res.end(body); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Attempt to tranfer the requseted file to `res`. |  | ||||||
|  * |  | ||||||
|  * @param {ServerRequest} |  | ||||||
|  * @param {ServerResponse} |  | ||||||
|  * @param {Function} next |  | ||||||
|  * @param {Object} options |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var send = exports.send = function(req, res, next, options){ |  | ||||||
|   options = options || {}; |  | ||||||
|   if (!options.path) throw new Error('path required'); |  | ||||||
|  |  | ||||||
|   // setup |  | ||||||
|   var maxAge = options.maxAge || 0 |  | ||||||
|     , ranges = req.headers.range |  | ||||||
|     , head = 'HEAD' == req.method |  | ||||||
|     , get = 'GET' == req.method |  | ||||||
|     , root = options.root ? normalize(options.root) : null |  | ||||||
|     , redirect = false === options.redirect ? false : true |  | ||||||
|     , getOnly = options.getOnly |  | ||||||
|     , fn = options.callback |  | ||||||
|     , hidden = options.hidden |  | ||||||
|     , done; |  | ||||||
|  |  | ||||||
|   // replace next() with callback when available |  | ||||||
|   if (fn) next = fn; |  | ||||||
|  |  | ||||||
|   // ignore non-GET requests |  | ||||||
|   if (getOnly && !get && !head) return next(); |  | ||||||
|  |  | ||||||
|   // parse url |  | ||||||
|   var url = parse(options.path) |  | ||||||
|     , path = decodeURIComponent(url.pathname) |  | ||||||
|     , type; |  | ||||||
|  |  | ||||||
|   // null byte(s) |  | ||||||
|   if (~path.indexOf('\0')) return utils.badRequest(res); |  | ||||||
|  |  | ||||||
|   // when root is not given, consider .. malicious |  | ||||||
|   if (!root && ~path.indexOf('..')) return utils.forbidden(res); |  | ||||||
|  |  | ||||||
|   // join / normalize from optional root dir |  | ||||||
|   path = normalize(join(root, path)); |  | ||||||
|  |  | ||||||
|   // malicious path |  | ||||||
|   if (root && 0 != path.indexOf(root)) return fn |  | ||||||
|     ? fn(new Error('Forbidden')) |  | ||||||
|     : utils.forbidden(res); |  | ||||||
|  |  | ||||||
|   // index.html support |  | ||||||
|   if (normalize('/') == path[path.length - 1]) path += 'index.html'; |  | ||||||
|  |  | ||||||
|   // "hidden" file |  | ||||||
|   if (!hidden && '.' == basename(path)[0]) return next(); |  | ||||||
|  |  | ||||||
|   fs.stat(path, function(err, stat){ |  | ||||||
|     // mime type |  | ||||||
|     type = mime.lookup(path); |  | ||||||
|  |  | ||||||
|     // ignore ENOENT |  | ||||||
|     if (err) { |  | ||||||
|       if (fn) return fn(err); |  | ||||||
|       return 'ENOENT' == err.code |  | ||||||
|         ? next() |  | ||||||
|         : next(err); |  | ||||||
|     // redirect directory in case index.html is present |  | ||||||
|     } else if (stat.isDirectory()) { |  | ||||||
|       if (!redirect) return next(); |  | ||||||
|       res.statusCode = 301; |  | ||||||
|       res.setHeader('Location', url.pathname + '/'); |  | ||||||
|       res.end('Redirecting to ' + url.pathname + '/'); |  | ||||||
|       return; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // header fields |  | ||||||
|     if (!res.getHeader('Date')) res.setHeader('Date', new Date().toUTCString()); |  | ||||||
|     if (!res.getHeader('Cache-Control')) res.setHeader('Cache-Control', 'public, max-age=' + (maxAge / 1000)); |  | ||||||
|     if (!res.getHeader('Last-Modified')) res.setHeader('Last-Modified', stat.mtime.toUTCString()); |  | ||||||
|     if (!res.getHeader('ETag')) res.setHeader('ETag', utils.etag(stat)); |  | ||||||
|     if (!res.getHeader('content-type')) { |  | ||||||
|       var charset = mime.charsets.lookup(type); |  | ||||||
|       res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : '')); |  | ||||||
|     } |  | ||||||
|     res.setHeader('Accept-Ranges', 'bytes'); |  | ||||||
|  |  | ||||||
|     // conditional GET support |  | ||||||
|     if (utils.conditionalGET(req)) { |  | ||||||
|       if (!utils.modified(req, res)) { |  | ||||||
|         req.emit('static'); |  | ||||||
|         return utils.notModified(res); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     var opts = {}; |  | ||||||
|     var chunkSize = stat.size; |  | ||||||
|  |  | ||||||
|     // we have a Range request |  | ||||||
|     if (ranges) { |  | ||||||
|       ranges = utils.parseRange(stat.size, ranges); |  | ||||||
|       // valid |  | ||||||
|       if (ranges) { |  | ||||||
|         // TODO: stream options |  | ||||||
|         // TODO: multiple support |  | ||||||
|         opts.start = ranges[0].start; |  | ||||||
|         opts.end = ranges[0].end; |  | ||||||
|         chunkSize = opts.end - opts.start + 1; |  | ||||||
|         res.statusCode = 206; |  | ||||||
|         res.setHeader('Content-Range', 'bytes ' |  | ||||||
|           + opts.start |  | ||||||
|           + '-' |  | ||||||
|           + opts.end |  | ||||||
|           + '/' |  | ||||||
|           + stat.size); |  | ||||||
|       // invalid |  | ||||||
|       } else { |  | ||||||
|         return fn |  | ||||||
|           ? fn(new Error('Requested Range Not Satisfiable')) |  | ||||||
|           : invalidRange(res); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     res.setHeader('Content-Length', chunkSize); |  | ||||||
|  |  | ||||||
|     // transfer |  | ||||||
|     if (head) return res.end(); |  | ||||||
|  |  | ||||||
|     // stream |  | ||||||
|     var stream = fs.createReadStream(path, opts); |  | ||||||
|     req.emit('static', stream); |  | ||||||
|     stream.pipe(res); |  | ||||||
|  |  | ||||||
|     // callback |  | ||||||
|     if (fn) { |  | ||||||
|       function callback(err) { done || fn(err); done = true } |  | ||||||
|       req.on('close', callback); |  | ||||||
|       stream.on('end', callback); |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
							
								
								
									
										175
									
								
								node_modules/connect/lib/middleware/staticCache.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,175 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - staticCache |  | ||||||
|  * Copyright(c) 2011 Sencha Inc. |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var http = require('http') |  | ||||||
|   , utils = require('../utils') |  | ||||||
|   , Cache = require('../cache') |  | ||||||
|   , url = require('url') |  | ||||||
|   , fs = require('fs'); |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Enables a memory cache layer on top of |  | ||||||
|  * the `static()` middleware, serving popular |  | ||||||
|  * static files. |  | ||||||
|  * |  | ||||||
|  * By default a maximum of 128 objects are |  | ||||||
|  * held in cache, with a max of 256k each, |  | ||||||
|  * totalling ~32mb. |  | ||||||
|  * |  | ||||||
|  * A Least-Recently-Used (LRU) cache algo |  | ||||||
|  * is implemented through the `Cache` object, |  | ||||||
|  * simply rotating cache objects as they are |  | ||||||
|  * hit. This means that increasingly popular |  | ||||||
|  * objects maintain their positions while |  | ||||||
|  * others get shoved out of the stack and |  | ||||||
|  * garbage collected. |  | ||||||
|  * |  | ||||||
|  * Benchmarks: |  | ||||||
|  * |  | ||||||
|  *     static(): 2700 rps |  | ||||||
|  *     node-static: 5300 rps |  | ||||||
|  *     static() + staticCache(): 7500 rps |  | ||||||
|  * |  | ||||||
|  * Options: |  | ||||||
|  * |  | ||||||
|  *   - `maxObjects`  max cache objects [128] |  | ||||||
|  *   - `maxLength`  max cache object length 256kb |  | ||||||
|  * |  | ||||||
|  * @param {Type} name |  | ||||||
|  * @return {Type} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| module.exports = function staticCache(options){ |  | ||||||
|   var options = options || {} |  | ||||||
|     , cache = new Cache(options.maxObjects || 128) |  | ||||||
|     , maxlen = options.maxLength || 1024 * 256; |  | ||||||
|  |  | ||||||
|   return function staticCache(req, res, next){ |  | ||||||
|     var path = url.parse(req.url).pathname |  | ||||||
|       , ranges = req.headers.range |  | ||||||
|       , hit = cache.get(path) |  | ||||||
|       , hitCC |  | ||||||
|       , uaCC |  | ||||||
|       , header |  | ||||||
|       , age; |  | ||||||
|  |  | ||||||
|     // cache static |  | ||||||
|     req.on('static', function(stream){ |  | ||||||
|       var headers = res._headers |  | ||||||
|         , cc = utils.parseCacheControl(headers['cache-control'] || '') |  | ||||||
|         , contentLength = headers['content-length'] |  | ||||||
|         , hit; |  | ||||||
|  |  | ||||||
|       // ignore larger files |  | ||||||
|       if (!contentLength || contentLength > maxlen) return; |  | ||||||
|  |  | ||||||
|       // dont cache items we shouldn't be |  | ||||||
|       if ( cc['no-cache'] |  | ||||||
|         || cc['no-store'] |  | ||||||
|         || cc['private'] |  | ||||||
|         || cc['must-revalidate']) return; |  | ||||||
|  |  | ||||||
|       // if already in cache then validate |  | ||||||
|       if (hit = cache.get(path)){ |  | ||||||
|         if (headers.etag == hit[0].etag) { |  | ||||||
|           hit[0].date = new Date; |  | ||||||
|           return; |  | ||||||
|         } else { |  | ||||||
|           cache.remove(path); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       // validation notifiactions don't contain a steam |  | ||||||
|       if (null == stream) return; |  | ||||||
|  |  | ||||||
|       // add the cache object |  | ||||||
|       var arr = cache.add(path); |  | ||||||
|       arr.push(headers); |  | ||||||
|  |  | ||||||
|       // store the chunks |  | ||||||
|       stream.on('data', function(chunk){ |  | ||||||
|         arr.push(chunk); |  | ||||||
|       }); |  | ||||||
|  |  | ||||||
|       // flag it as complete |  | ||||||
|       stream.on('end', function(){ |  | ||||||
|         arr.complete = true; |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     // cache hit, doesnt support range requests |  | ||||||
|     if (hit && hit.complete && !ranges) { |  | ||||||
|       header = utils.merge({}, hit[0]); |  | ||||||
|       header.Age = age = (new Date - new Date(header.date)) / 1000 | 0; |  | ||||||
|       header.date = new Date().toUTCString(); |  | ||||||
|  |  | ||||||
|       // parse cache-controls |  | ||||||
|       hitCC = utils.parseCacheControl(header['cache-control'] || ''); |  | ||||||
|       uaCC = utils.parseCacheControl(req.headers['cache-control'] || ''); |  | ||||||
|  |  | ||||||
|       // check if we must revalidate(bypass) |  | ||||||
|       if (hitCC['no-cache'] || uaCC['no-cache']) return next(); |  | ||||||
|  |  | ||||||
|       // check freshness of entity |  | ||||||
|       if (isStale(hitCC, age) || isStale(uaCC, age)) return next(); |  | ||||||
|  |  | ||||||
|       // conditional GET support |  | ||||||
|       if (utils.conditionalGET(req)) { |  | ||||||
|         if (!utils.modified(req, res, header)) { |  | ||||||
|           header['content-length'] = 0; |  | ||||||
|           res.writeHead(304, header); |  | ||||||
|           return res.end(); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       // HEAD support |  | ||||||
|       if ('HEAD' == req.method) { |  | ||||||
|         header['content-length'] = 0; |  | ||||||
|         res.writeHead(200, header); |  | ||||||
|         return res.end(); |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       // respond with cache |  | ||||||
|       res.writeHead(200, header); |  | ||||||
|  |  | ||||||
|       // backpressure |  | ||||||
|       function write(i) { |  | ||||||
|         var buf = hit[i]; |  | ||||||
|         if (!buf) return res.end(); |  | ||||||
|         if (false === res.write(buf)) { |  | ||||||
|           res.once('drain', function(){ |  | ||||||
|             write(++i); |  | ||||||
|           }); |  | ||||||
|         } else { |  | ||||||
|           write(++i); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       return write(1); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     next(); |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Check if cache item is stale |  | ||||||
|  * |  | ||||||
|  * @param {Object} cc |  | ||||||
|  * @param {Number} age |  | ||||||
|  * @return {Boolean} |  | ||||||
|  * @api private |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| function isStale(cc, age) { |  | ||||||
|   return cc['max-age'] && cc['max-age'] <= age; |  | ||||||
| } |  | ||||||
							
								
								
									
										44
									
								
								node_modules/connect/lib/middleware/vhost.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,44 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect - vhost |  | ||||||
|  * Copyright(c) 2010 Sencha Inc. |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Setup vhost for the given `hostname` and `server`. |  | ||||||
|  * |  | ||||||
|  * Examples: |  | ||||||
|  * |  | ||||||
|  *     connect( |  | ||||||
|  *       connect.vhost('foo.com', |  | ||||||
|  *         connect.createServer(...middleware...) |  | ||||||
|  *       ), |  | ||||||
|  *       connect.vhost('bar.com', |  | ||||||
|  *         connect.createServer(...middleware...) |  | ||||||
|  *       ) |  | ||||||
|  *     ); |  | ||||||
|  * |  | ||||||
|  * @param {String} hostname |  | ||||||
|  * @param {Server} server |  | ||||||
|  * @return {Function} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| module.exports = function vhost(hostname, server){ |  | ||||||
|   if (!hostname) throw new Error('vhost hostname required'); |  | ||||||
|   if (!server) throw new Error('vhost server required'); |  | ||||||
|   var regexp = new RegExp('^' + hostname.replace(/[*]/g, '(.*?)') + '$'); |  | ||||||
|   if (server.onvhost) server.onvhost(hostname); |  | ||||||
|   return function vhost(req, res, next){ |  | ||||||
|     if (!req.headers.host) return next(); |  | ||||||
|     var host = req.headers.host.split(':')[0]; |  | ||||||
|     if (req.subdomains = regexp.exec(host)) { |  | ||||||
|       req.subdomains = req.subdomains[0].split('.').slice(0, -1); |  | ||||||
|       server.emit("request", req, res); |  | ||||||
|     } else { |  | ||||||
|       next(); |  | ||||||
|     } |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
							
								
								
									
										79
									
								
								node_modules/connect/lib/patch.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,79 +0,0 @@ | |||||||
|  |  | ||||||
| /*! |  | ||||||
|  * Connect |  | ||||||
|  * Copyright(c) 2011 TJ Holowaychuk |  | ||||||
|  * MIT Licensed |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Module dependencies. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| var http = require('http') |  | ||||||
|   , res = http.OutgoingMessage.prototype; |  | ||||||
|  |  | ||||||
| // original setHeader() |  | ||||||
|  |  | ||||||
| var setHeader = res.setHeader; |  | ||||||
|  |  | ||||||
| // original _renderHeaders() |  | ||||||
|  |  | ||||||
| var _renderHeaders = res._renderHeaders; |  | ||||||
|  |  | ||||||
| if (res._hasConnectPatch) return; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Provide a public "header sent" flag |  | ||||||
|  * until node does. |  | ||||||
|  * |  | ||||||
|  * @return {Boolean} |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| res.__defineGetter__('headerSent', function(){ |  | ||||||
|   return this._headerSent; |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Set header `field` to `val`, special-casing |  | ||||||
|  * the `Set-Cookie` field for multiple support. |  | ||||||
|  * |  | ||||||
|  * @param {String} field |  | ||||||
|  * @param {String} val |  | ||||||
|  * @api public |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| res.setHeader = function(field, val){ |  | ||||||
|   var key = field.toLowerCase() |  | ||||||
|     , prev; |  | ||||||
|  |  | ||||||
|   // special-case Set-Cookie |  | ||||||
|   if (this._headers && 'set-cookie' == key) { |  | ||||||
|     if (prev = this.getHeader(field)) { |  | ||||||
|       val = Array.isArray(prev) |  | ||||||
|         ? prev.concat(val) |  | ||||||
|         : [prev, val]; |  | ||||||
|     } |  | ||||||
|   // charset |  | ||||||
|   } else if ('content-type' == key && this.charset) { |  | ||||||
|     val += '; charset=' + this.charset; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return setHeader.call(this, field, val); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Proxy `res.end()` to expose a 'header' event, |  | ||||||
|  * allowing arbitrary augmentation before the header |  | ||||||
|  * fields are written to the socket. |  | ||||||
|  * |  | ||||||
|  * NOTE: this _only_ supports node's progressive header |  | ||||||
|  * field API aka `res.setHeader()`. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| res._renderHeaders = function(){ |  | ||||||
|   this.emit('header'); |  | ||||||
|   return _renderHeaders.call(this); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| res._hasConnectPatch = true; |  | ||||||
							
								
								
									
										75
									
								
								node_modules/connect/lib/public/directory.html
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,75 +0,0 @@ | |||||||
| <html> |  | ||||||
|   <head> |  | ||||||
|     <title>listing directory {directory}</title> |  | ||||||
|     <style>{style}</style> |  | ||||||
|     <script> |  | ||||||
|       function $(id){ |  | ||||||
|         var el = 'string' == typeof id |  | ||||||
|           ? document.getElementById(id) |  | ||||||
|           : id; |  | ||||||
|  |  | ||||||
|         el.on = function(event, fn){ |  | ||||||
|           if ('content loaded' == event) event = 'DOMContentLoaded'; |  | ||||||
|           el.addEventListener(event, fn, false); |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         el.all = function(selector){ |  | ||||||
|           return $(el.querySelectorAll(selector)); |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         el.each = function(fn){ |  | ||||||
|           for (var i = 0, len = el.length; i < len; ++i) { |  | ||||||
|             fn($(el[i]), i); |  | ||||||
|           } |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         el.getClasses = function(){ |  | ||||||
|           return this.getAttribute('class').split(/\s+/); |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         el.addClass = function(name){ |  | ||||||
|           var classes = this.getAttribute('class'); |  | ||||||
|           el.setAttribute('class', classes |  | ||||||
|             ? classes + ' ' + name |  | ||||||
|             : name); |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         el.removeClass = function(name){ |  | ||||||
|           var classes = this.getClasses().filter(function(curr){ |  | ||||||
|             return curr != name; |  | ||||||
|           }); |  | ||||||
|           this.setAttribute('class', classes); |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         return el; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       function search() { |  | ||||||
|         var str = $('search').value |  | ||||||
|           , links = $('files').all('a'); |  | ||||||
|  |  | ||||||
|         links.each(function(link){ |  | ||||||
|           var text = link.textContent; |  | ||||||
|  |  | ||||||
|           if ('..' == text) return; |  | ||||||
|           if (str.length && ~text.indexOf(str)) { |  | ||||||
|             link.addClass('highlight'); |  | ||||||
|           } else { |  | ||||||
|             link.removeClass('highlight'); |  | ||||||
|           } |  | ||||||
|         }); |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       $(window).on('content loaded', function(){ |  | ||||||
|         $('search').on('keyup', search); |  | ||||||
|       }); |  | ||||||
|     </script> |  | ||||||
|   </head> |  | ||||||
|   <body class="directory"> |  | ||||||
|     <input id="search" type="text" placeholder="Search" autocomplete="off" /> |  | ||||||
|     <div id="wrapper"> |  | ||||||
|       <h1>{linked-path}</h1> |  | ||||||
|       {files} |  | ||||||
|     </div> |  | ||||||
|   </body> |  | ||||||
| </html> |  | ||||||
							
								
								
									
										13
									
								
								node_modules/connect/lib/public/error.html
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,13 +0,0 @@ | |||||||
| <html> |  | ||||||
|   <head> |  | ||||||
|     <title>{error}</title> |  | ||||||
|     <style>{style}</style> |  | ||||||
|   </head> |  | ||||||
|   <body> |  | ||||||
|     <div id="wrapper"> |  | ||||||
|       <h1>{title}</h1> |  | ||||||
|       <h2><em>500</em> {error}</h2> |  | ||||||
|       <ul id="stacktrace">{stack}</ul> |  | ||||||
|     </div> |  | ||||||
|   </body> |  | ||||||
| </html> |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/favicon.ico
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 1.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 635 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_add.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 739 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_attach.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 794 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_code.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 818 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_copy.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 663 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_delete.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 740 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_edit.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 807 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_error.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 793 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_excel.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 817 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_find.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 879 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_gear.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 833 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_go.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 779 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_green.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 621 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_key.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 801 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_lightning.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 839 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_link.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 830 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_paintbrush.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 813 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_paste.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 703 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_red.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 641 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_refresh.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 858 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_save.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 774 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 294 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white_acrobat.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 591 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white_actionscript.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 664 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white_add.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 512 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white_c.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 587 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white_camera.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 656 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white_cd.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 666 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white_code.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 603 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white_code_red.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 587 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white_coldfusion.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 592 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white_compressed.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 724 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white_copy.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 309 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white_cplusplus.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 621 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white_csharp.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 700 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white_cup.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 639 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white_database.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 579 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white_delete.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 536 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white_dvd.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 638 B | 
							
								
								
									
										
											BIN
										
									
								
								node_modules/connect/lib/public/icons/page_white_edit.png
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 618 B |