"
+ ],
+ "license": "MIT",
+ "repository": "jonathanong/ee-first",
+ "devDependencies": {
+ "istanbul": "0.3.9",
+ "mocha": "2.2.5"
+ },
+ "files": [
+ "index.js",
+ "LICENSE"
+ ],
+ "scripts": {
+ "test": "mocha --reporter spec --bail --check-leaks test/",
+ "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/",
+ "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/"
+ }
+}
diff --git a/服务器端/node_modules/encodeurl/HISTORY.md b/服务器端/node_modules/encodeurl/HISTORY.md
new file mode 100644
index 0000000..41313b2
--- /dev/null
+++ b/服务器端/node_modules/encodeurl/HISTORY.md
@@ -0,0 +1,14 @@
+1.0.2 / 2018-01-21
+==================
+
+ * Fix encoding `%` as last character
+
+1.0.1 / 2016-06-09
+==================
+
+ * Fix encoding unpaired surrogates at start/end of string
+
+1.0.0 / 2016-06-08
+==================
+
+ * Initial release
diff --git a/服务器端/node_modules/encodeurl/LICENSE b/服务器端/node_modules/encodeurl/LICENSE
new file mode 100644
index 0000000..8812229
--- /dev/null
+++ b/服务器端/node_modules/encodeurl/LICENSE
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2016 Douglas Christopher Wilson
+
+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.
diff --git a/服务器端/node_modules/encodeurl/README.md b/服务器端/node_modules/encodeurl/README.md
new file mode 100644
index 0000000..127c5a0
--- /dev/null
+++ b/服务器端/node_modules/encodeurl/README.md
@@ -0,0 +1,128 @@
+# encodeurl
+
+[![NPM Version][npm-image]][npm-url]
+[![NPM Downloads][downloads-image]][downloads-url]
+[![Node.js Version][node-version-image]][node-version-url]
+[![Build Status][travis-image]][travis-url]
+[![Test Coverage][coveralls-image]][coveralls-url]
+
+Encode a URL to a percent-encoded form, excluding already-encoded sequences
+
+## Installation
+
+This is a [Node.js](https://nodejs.org/en/) module available through the
+[npm registry](https://www.npmjs.com/). Installation is done using the
+[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
+
+```sh
+$ npm install encodeurl
+```
+
+## API
+
+```js
+var encodeUrl = require('encodeurl')
+```
+
+### encodeUrl(url)
+
+Encode a URL to a percent-encoded form, excluding already-encoded sequences.
+
+This function will take an already-encoded URL and encode all the non-URL
+code points (as UTF-8 byte sequences). This function will not encode the
+"%" character unless it is not part of a valid sequence (`%20` will be
+left as-is, but `%foo` will be encoded as `%25foo`).
+
+This encode is meant to be "safe" and does not throw errors. It will try as
+hard as it can to properly encode the given URL, including replacing any raw,
+unpaired surrogate pairs with the Unicode replacement character prior to
+encoding.
+
+This function is _similar_ to the intrinsic function `encodeURI`, except it
+will not encode the `%` character if that is part of a valid sequence, will
+not encode `[` and `]` (for IPv6 hostnames) and will replace raw, unpaired
+surrogate pairs with the Unicode replacement character (instead of throwing).
+
+## Examples
+
+### Encode a URL containing user-controled data
+
+```js
+var encodeUrl = require('encodeurl')
+var escapeHtml = require('escape-html')
+
+http.createServer(function onRequest (req, res) {
+ // get encoded form of inbound url
+ var url = encodeUrl(req.url)
+
+ // create html message
+ var body = 'Location ' + escapeHtml(url) + ' not found
'
+
+ // send a 404
+ res.statusCode = 404
+ res.setHeader('Content-Type', 'text/html; charset=UTF-8')
+ res.setHeader('Content-Length', String(Buffer.byteLength(body, 'utf-8')))
+ res.end(body, 'utf-8')
+})
+```
+
+### Encode a URL for use in a header field
+
+```js
+var encodeUrl = require('encodeurl')
+var escapeHtml = require('escape-html')
+var url = require('url')
+
+http.createServer(function onRequest (req, res) {
+ // parse inbound url
+ var href = url.parse(req)
+
+ // set new host for redirect
+ href.host = 'localhost'
+ href.protocol = 'https:'
+ href.slashes = true
+
+ // create location header
+ var location = encodeUrl(url.format(href))
+
+ // create html message
+ var body = 'Redirecting to new site: ' + escapeHtml(location) + '
'
+
+ // send a 301
+ res.statusCode = 301
+ res.setHeader('Content-Type', 'text/html; charset=UTF-8')
+ res.setHeader('Content-Length', String(Buffer.byteLength(body, 'utf-8')))
+ res.setHeader('Location', location)
+ res.end(body, 'utf-8')
+})
+```
+
+## Testing
+
+```sh
+$ npm test
+$ npm run lint
+```
+
+## References
+
+- [RFC 3986: Uniform Resource Identifier (URI): Generic Syntax][rfc-3986]
+- [WHATWG URL Living Standard][whatwg-url]
+
+[rfc-3986]: https://tools.ietf.org/html/rfc3986
+[whatwg-url]: https://url.spec.whatwg.org/
+
+## License
+
+[MIT](LICENSE)
+
+[npm-image]: https://img.shields.io/npm/v/encodeurl.svg
+[npm-url]: https://npmjs.org/package/encodeurl
+[node-version-image]: https://img.shields.io/node/v/encodeurl.svg
+[node-version-url]: https://nodejs.org/en/download
+[travis-image]: https://img.shields.io/travis/pillarjs/encodeurl.svg
+[travis-url]: https://travis-ci.org/pillarjs/encodeurl
+[coveralls-image]: https://img.shields.io/coveralls/pillarjs/encodeurl.svg
+[coveralls-url]: https://coveralls.io/r/pillarjs/encodeurl?branch=master
+[downloads-image]: https://img.shields.io/npm/dm/encodeurl.svg
+[downloads-url]: https://npmjs.org/package/encodeurl
diff --git a/服务器端/node_modules/encodeurl/index.js b/服务器端/node_modules/encodeurl/index.js
new file mode 100644
index 0000000..fc4906c
--- /dev/null
+++ b/服务器端/node_modules/encodeurl/index.js
@@ -0,0 +1,60 @@
+/*!
+ * encodeurl
+ * Copyright(c) 2016 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+'use strict'
+
+/**
+ * Module exports.
+ * @public
+ */
+
+module.exports = encodeUrl
+
+/**
+ * RegExp to match non-URL code points, *after* encoding (i.e. not including "%")
+ * and including invalid escape sequences.
+ * @private
+ */
+
+var ENCODE_CHARS_REGEXP = /(?:[^\x21\x25\x26-\x3B\x3D\x3F-\x5B\x5D\x5F\x61-\x7A\x7E]|%(?:[^0-9A-Fa-f]|[0-9A-Fa-f][^0-9A-Fa-f]|$))+/g
+
+/**
+ * RegExp to match unmatched surrogate pair.
+ * @private
+ */
+
+var UNMATCHED_SURROGATE_PAIR_REGEXP = /(^|[^\uD800-\uDBFF])[\uDC00-\uDFFF]|[\uD800-\uDBFF]([^\uDC00-\uDFFF]|$)/g
+
+/**
+ * String to replace unmatched surrogate pair with.
+ * @private
+ */
+
+var UNMATCHED_SURROGATE_PAIR_REPLACE = '$1\uFFFD$2'
+
+/**
+ * Encode a URL to a percent-encoded form, excluding already-encoded sequences.
+ *
+ * This function will take an already-encoded URL and encode all the non-URL
+ * code points. This function will not encode the "%" character unless it is
+ * not part of a valid sequence (`%20` will be left as-is, but `%foo` will
+ * be encoded as `%25foo`).
+ *
+ * This encode is meant to be "safe" and does not throw errors. It will try as
+ * hard as it can to properly encode the given URL, including replacing any raw,
+ * unpaired surrogate pairs with the Unicode replacement character prior to
+ * encoding.
+ *
+ * @param {string} url
+ * @return {string}
+ * @public
+ */
+
+function encodeUrl (url) {
+ return String(url)
+ .replace(UNMATCHED_SURROGATE_PAIR_REGEXP, UNMATCHED_SURROGATE_PAIR_REPLACE)
+ .replace(ENCODE_CHARS_REGEXP, encodeURI)
+}
diff --git a/服务器端/node_modules/encodeurl/package.json b/服务器端/node_modules/encodeurl/package.json
new file mode 100644
index 0000000..b9f25ef
--- /dev/null
+++ b/服务器端/node_modules/encodeurl/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "encodeurl",
+ "description": "Encode a URL to a percent-encoded form, excluding already-encoded sequences",
+ "version": "1.0.2",
+ "contributors": [
+ "Douglas Christopher Wilson "
+ ],
+ "license": "MIT",
+ "keywords": [
+ "encode",
+ "encodeurl",
+ "url"
+ ],
+ "repository": "pillarjs/encodeurl",
+ "devDependencies": {
+ "eslint": "3.19.0",
+ "eslint-config-standard": "10.2.1",
+ "eslint-plugin-import": "2.8.0",
+ "eslint-plugin-node": "5.2.1",
+ "eslint-plugin-promise": "3.6.0",
+ "eslint-plugin-standard": "3.0.1",
+ "istanbul": "0.4.5",
+ "mocha": "2.5.3"
+ },
+ "files": [
+ "LICENSE",
+ "HISTORY.md",
+ "README.md",
+ "index.js"
+ ],
+ "engines": {
+ "node": ">= 0.8"
+ },
+ "scripts": {
+ "lint": "eslint .",
+ "test": "mocha --reporter spec --bail --check-leaks test/",
+ "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/",
+ "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/"
+ }
+}
diff --git a/服务器端/node_modules/escape-html/LICENSE b/服务器端/node_modules/escape-html/LICENSE
new file mode 100644
index 0000000..2e70de9
--- /dev/null
+++ b/服务器端/node_modules/escape-html/LICENSE
@@ -0,0 +1,24 @@
+(The MIT License)
+
+Copyright (c) 2012-2013 TJ Holowaychuk
+Copyright (c) 2015 Andreas Lubbe
+Copyright (c) 2015 Tiancheng "Timothy" Gu
+
+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.
diff --git a/服务器端/node_modules/escape-html/Readme.md b/服务器端/node_modules/escape-html/Readme.md
new file mode 100644
index 0000000..653d9ea
--- /dev/null
+++ b/服务器端/node_modules/escape-html/Readme.md
@@ -0,0 +1,43 @@
+
+# escape-html
+
+ Escape string for use in HTML
+
+## Example
+
+```js
+var escape = require('escape-html');
+var html = escape('foo & bar');
+// -> foo & bar
+```
+
+## Benchmark
+
+```
+$ npm run-script bench
+
+> escape-html@1.0.3 bench nodejs-escape-html
+> node benchmark/index.js
+
+
+ http_parser@1.0
+ node@0.10.33
+ v8@3.14.5.9
+ ares@1.9.0-DEV
+ uv@0.10.29
+ zlib@1.2.3
+ modules@11
+ openssl@1.0.1j
+
+ 1 test completed.
+ 2 tests completed.
+ 3 tests completed.
+
+ no special characters x 19,435,271 ops/sec ±0.85% (187 runs sampled)
+ single special character x 6,132,421 ops/sec ±0.67% (194 runs sampled)
+ many special characters x 3,175,826 ops/sec ±0.65% (193 runs sampled)
+```
+
+## License
+
+ MIT
\ No newline at end of file
diff --git a/服务器端/node_modules/escape-html/index.js b/服务器端/node_modules/escape-html/index.js
new file mode 100644
index 0000000..bf9e226
--- /dev/null
+++ b/服务器端/node_modules/escape-html/index.js
@@ -0,0 +1,78 @@
+/*!
+ * escape-html
+ * Copyright(c) 2012-2013 TJ Holowaychuk
+ * Copyright(c) 2015 Andreas Lubbe
+ * Copyright(c) 2015 Tiancheng "Timothy" Gu
+ * MIT Licensed
+ */
+
+'use strict';
+
+/**
+ * Module variables.
+ * @private
+ */
+
+var matchHtmlRegExp = /["'&<>]/;
+
+/**
+ * Module exports.
+ * @public
+ */
+
+module.exports = escapeHtml;
+
+/**
+ * Escape special characters in the given string of html.
+ *
+ * @param {string} string The string to escape for inserting into HTML
+ * @return {string}
+ * @public
+ */
+
+function escapeHtml(string) {
+ var str = '' + string;
+ var match = matchHtmlRegExp.exec(str);
+
+ if (!match) {
+ return str;
+ }
+
+ var escape;
+ var html = '';
+ var index = 0;
+ var lastIndex = 0;
+
+ for (index = match.index; index < str.length; index++) {
+ switch (str.charCodeAt(index)) {
+ case 34: // "
+ escape = '"';
+ break;
+ case 38: // &
+ escape = '&';
+ break;
+ case 39: // '
+ escape = ''';
+ break;
+ case 60: // <
+ escape = '<';
+ break;
+ case 62: // >
+ escape = '>';
+ break;
+ default:
+ continue;
+ }
+
+ if (lastIndex !== index) {
+ html += str.substring(lastIndex, index);
+ }
+
+ lastIndex = index + 1;
+ html += escape;
+ }
+
+ return lastIndex !== index
+ ? html + str.substring(lastIndex, index)
+ : html;
+}
diff --git a/服务器端/node_modules/escape-html/package.json b/服务器端/node_modules/escape-html/package.json
new file mode 100644
index 0000000..57ec7bd
--- /dev/null
+++ b/服务器端/node_modules/escape-html/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "escape-html",
+ "description": "Escape string for use in HTML",
+ "version": "1.0.3",
+ "license": "MIT",
+ "keywords": [
+ "escape",
+ "html",
+ "utility"
+ ],
+ "repository": "component/escape-html",
+ "devDependencies": {
+ "benchmark": "1.0.0",
+ "beautify-benchmark": "0.2.4"
+ },
+ "files": [
+ "LICENSE",
+ "Readme.md",
+ "index.js"
+ ],
+ "scripts": {
+ "bench": "node benchmark/index.js"
+ }
+}
diff --git a/服务器端/node_modules/etag/HISTORY.md b/服务器端/node_modules/etag/HISTORY.md
new file mode 100644
index 0000000..222b293
--- /dev/null
+++ b/服务器端/node_modules/etag/HISTORY.md
@@ -0,0 +1,83 @@
+1.8.1 / 2017-09-12
+==================
+
+ * perf: replace regular expression with substring
+
+1.8.0 / 2017-02-18
+==================
+
+ * Use SHA1 instead of MD5 for ETag hashing
+ - Improves performance for larger entities
+ - Works with FIPS 140-2 OpenSSL configuration
+
+1.7.0 / 2015-06-08
+==================
+
+ * Always include entity length in ETags for hash length extensions
+ * Generate non-Stats ETags using MD5 only (no longer CRC32)
+ * Improve stat performance by removing hashing
+ * Remove base64 padding in ETags to shorten
+ * Use MD5 instead of MD4 in weak ETags over 1KB
+
+1.6.0 / 2015-05-10
+==================
+
+ * Improve support for JXcore
+ * Remove requirement of `atime` in the stats object
+ * Support "fake" stats objects in environments without `fs`
+
+1.5.1 / 2014-11-19
+==================
+
+ * deps: crc@3.2.1
+ - Minor fixes
+
+1.5.0 / 2014-10-14
+==================
+
+ * Improve string performance
+ * Slightly improve speed for weak ETags over 1KB
+
+1.4.0 / 2014-09-21
+==================
+
+ * Support "fake" stats objects
+ * Support Node.js 0.6
+
+1.3.1 / 2014-09-14
+==================
+
+ * Use the (new and improved) `crc` for crc32
+
+1.3.0 / 2014-08-29
+==================
+
+ * Default strings to strong ETags
+ * Improve speed for weak ETags over 1KB
+
+1.2.1 / 2014-08-29
+==================
+
+ * Use the (much faster) `buffer-crc32` for crc32
+
+1.2.0 / 2014-08-24
+==================
+
+ * Add support for file stat objects
+
+1.1.0 / 2014-08-24
+==================
+
+ * Add fast-path for empty entity
+ * Add weak ETag generation
+ * Shrink size of generated ETags
+
+1.0.1 / 2014-08-24
+==================
+
+ * Fix behavior of string containing Unicode
+
+1.0.0 / 2014-05-18
+==================
+
+ * Initial release
diff --git a/服务器端/node_modules/etag/LICENSE b/服务器端/node_modules/etag/LICENSE
new file mode 100644
index 0000000..cab251c
--- /dev/null
+++ b/服务器端/node_modules/etag/LICENSE
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2014-2016 Douglas Christopher Wilson
+
+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.
diff --git a/服务器端/node_modules/etag/README.md b/服务器端/node_modules/etag/README.md
new file mode 100644
index 0000000..09c2169
--- /dev/null
+++ b/服务器端/node_modules/etag/README.md
@@ -0,0 +1,159 @@
+# etag
+
+[![NPM Version][npm-image]][npm-url]
+[![NPM Downloads][downloads-image]][downloads-url]
+[![Node.js Version][node-version-image]][node-version-url]
+[![Build Status][travis-image]][travis-url]
+[![Test Coverage][coveralls-image]][coveralls-url]
+
+Create simple HTTP ETags
+
+This module generates HTTP ETags (as defined in RFC 7232) for use in
+HTTP responses.
+
+## Installation
+
+This is a [Node.js](https://nodejs.org/en/) module available through the
+[npm registry](https://www.npmjs.com/). Installation is done using the
+[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
+
+```sh
+$ npm install etag
+```
+
+## API
+
+
+
+```js
+var etag = require('etag')
+```
+
+### etag(entity, [options])
+
+Generate a strong ETag for the given entity. This should be the complete
+body of the entity. Strings, `Buffer`s, and `fs.Stats` are accepted. By
+default, a strong ETag is generated except for `fs.Stats`, which will
+generate a weak ETag (this can be overwritten by `options.weak`).
+
+
+
+```js
+res.setHeader('ETag', etag(body))
+```
+
+#### Options
+
+`etag` accepts these properties in the options object.
+
+##### weak
+
+Specifies if the generated ETag will include the weak validator mark (that
+is, the leading `W/`). The actual entity tag is the same. The default value
+is `false`, unless the `entity` is `fs.Stats`, in which case it is `true`.
+
+## Testing
+
+```sh
+$ npm test
+```
+
+## Benchmark
+
+```bash
+$ npm run-script bench
+
+> etag@1.8.1 bench nodejs-etag
+> node benchmark/index.js
+
+ http_parser@2.7.0
+ node@6.11.1
+ v8@5.1.281.103
+ uv@1.11.0
+ zlib@1.2.11
+ ares@1.10.1-DEV
+ icu@58.2
+ modules@48
+ openssl@1.0.2k
+
+> node benchmark/body0-100b.js
+
+ 100B body
+
+ 4 tests completed.
+
+ buffer - strong x 258,647 ops/sec ±1.07% (180 runs sampled)
+ buffer - weak x 263,812 ops/sec ±0.61% (184 runs sampled)
+ string - strong x 259,955 ops/sec ±1.19% (185 runs sampled)
+ string - weak x 264,356 ops/sec ±1.09% (184 runs sampled)
+
+> node benchmark/body1-1kb.js
+
+ 1KB body
+
+ 4 tests completed.
+
+ buffer - strong x 189,018 ops/sec ±1.12% (182 runs sampled)
+ buffer - weak x 190,586 ops/sec ±0.81% (186 runs sampled)
+ string - strong x 144,272 ops/sec ±0.96% (188 runs sampled)
+ string - weak x 145,380 ops/sec ±1.43% (187 runs sampled)
+
+> node benchmark/body2-5kb.js
+
+ 5KB body
+
+ 4 tests completed.
+
+ buffer - strong x 92,435 ops/sec ±0.42% (188 runs sampled)
+ buffer - weak x 92,373 ops/sec ±0.58% (189 runs sampled)
+ string - strong x 48,850 ops/sec ±0.56% (186 runs sampled)
+ string - weak x 49,380 ops/sec ±0.56% (190 runs sampled)
+
+> node benchmark/body3-10kb.js
+
+ 10KB body
+
+ 4 tests completed.
+
+ buffer - strong x 55,989 ops/sec ±0.93% (188 runs sampled)
+ buffer - weak x 56,148 ops/sec ±0.55% (190 runs sampled)
+ string - strong x 27,345 ops/sec ±0.43% (188 runs sampled)
+ string - weak x 27,496 ops/sec ±0.45% (190 runs sampled)
+
+> node benchmark/body4-100kb.js
+
+ 100KB body
+
+ 4 tests completed.
+
+ buffer - strong x 7,083 ops/sec ±0.22% (190 runs sampled)
+ buffer - weak x 7,115 ops/sec ±0.26% (191 runs sampled)
+ string - strong x 3,068 ops/sec ±0.34% (190 runs sampled)
+ string - weak x 3,096 ops/sec ±0.35% (190 runs sampled)
+
+> node benchmark/stats.js
+
+ stat
+
+ 4 tests completed.
+
+ real - strong x 871,642 ops/sec ±0.34% (189 runs sampled)
+ real - weak x 867,613 ops/sec ±0.39% (190 runs sampled)
+ fake - strong x 401,051 ops/sec ±0.40% (189 runs sampled)
+ fake - weak x 400,100 ops/sec ±0.47% (188 runs sampled)
+```
+
+## License
+
+[MIT](LICENSE)
+
+[npm-image]: https://img.shields.io/npm/v/etag.svg
+[npm-url]: https://npmjs.org/package/etag
+[node-version-image]: https://img.shields.io/node/v/etag.svg
+[node-version-url]: https://nodejs.org/en/download/
+[travis-image]: https://img.shields.io/travis/jshttp/etag/master.svg
+[travis-url]: https://travis-ci.org/jshttp/etag
+[coveralls-image]: https://img.shields.io/coveralls/jshttp/etag/master.svg
+[coveralls-url]: https://coveralls.io/r/jshttp/etag?branch=master
+[downloads-image]: https://img.shields.io/npm/dm/etag.svg
+[downloads-url]: https://npmjs.org/package/etag
diff --git a/服务器端/node_modules/etag/index.js b/服务器端/node_modules/etag/index.js
new file mode 100644
index 0000000..2a585c9
--- /dev/null
+++ b/服务器端/node_modules/etag/index.js
@@ -0,0 +1,131 @@
+/*!
+ * etag
+ * Copyright(c) 2014-2016 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+'use strict'
+
+/**
+ * Module exports.
+ * @public
+ */
+
+module.exports = etag
+
+/**
+ * Module dependencies.
+ * @private
+ */
+
+var crypto = require('crypto')
+var Stats = require('fs').Stats
+
+/**
+ * Module variables.
+ * @private
+ */
+
+var toString = Object.prototype.toString
+
+/**
+ * Generate an entity tag.
+ *
+ * @param {Buffer|string} entity
+ * @return {string}
+ * @private
+ */
+
+function entitytag (entity) {
+ if (entity.length === 0) {
+ // fast-path empty
+ return '"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"'
+ }
+
+ // compute hash of entity
+ var hash = crypto
+ .createHash('sha1')
+ .update(entity, 'utf8')
+ .digest('base64')
+ .substring(0, 27)
+
+ // compute length of entity
+ var len = typeof entity === 'string'
+ ? Buffer.byteLength(entity, 'utf8')
+ : entity.length
+
+ return '"' + len.toString(16) + '-' + hash + '"'
+}
+
+/**
+ * Create a simple ETag.
+ *
+ * @param {string|Buffer|Stats} entity
+ * @param {object} [options]
+ * @param {boolean} [options.weak]
+ * @return {String}
+ * @public
+ */
+
+function etag (entity, options) {
+ if (entity == null) {
+ throw new TypeError('argument entity is required')
+ }
+
+ // support fs.Stats object
+ var isStats = isstats(entity)
+ var weak = options && typeof options.weak === 'boolean'
+ ? options.weak
+ : isStats
+
+ // validate argument
+ if (!isStats && typeof entity !== 'string' && !Buffer.isBuffer(entity)) {
+ throw new TypeError('argument entity must be string, Buffer, or fs.Stats')
+ }
+
+ // generate entity tag
+ var tag = isStats
+ ? stattag(entity)
+ : entitytag(entity)
+
+ return weak
+ ? 'W/' + tag
+ : tag
+}
+
+/**
+ * Determine if object is a Stats object.
+ *
+ * @param {object} obj
+ * @return {boolean}
+ * @api private
+ */
+
+function isstats (obj) {
+ // genuine fs.Stats
+ if (typeof Stats === 'function' && obj instanceof Stats) {
+ return true
+ }
+
+ // quack quack
+ return obj && typeof obj === 'object' &&
+ 'ctime' in obj && toString.call(obj.ctime) === '[object Date]' &&
+ 'mtime' in obj && toString.call(obj.mtime) === '[object Date]' &&
+ 'ino' in obj && typeof obj.ino === 'number' &&
+ 'size' in obj && typeof obj.size === 'number'
+}
+
+/**
+ * Generate a tag for a stat.
+ *
+ * @param {object} stat
+ * @return {string}
+ * @private
+ */
+
+function stattag (stat) {
+ var mtime = stat.mtime.getTime().toString(16)
+ var size = stat.size.toString(16)
+
+ return '"' + size + '-' + mtime + '"'
+}
diff --git a/服务器端/node_modules/etag/package.json b/服务器端/node_modules/etag/package.json
new file mode 100644
index 0000000..b06ab80
--- /dev/null
+++ b/服务器端/node_modules/etag/package.json
@@ -0,0 +1,47 @@
+{
+ "name": "etag",
+ "description": "Create simple HTTP ETags",
+ "version": "1.8.1",
+ "contributors": [
+ "Douglas Christopher Wilson ",
+ "David Björklund "
+ ],
+ "license": "MIT",
+ "keywords": [
+ "etag",
+ "http",
+ "res"
+ ],
+ "repository": "jshttp/etag",
+ "devDependencies": {
+ "beautify-benchmark": "0.2.4",
+ "benchmark": "2.1.4",
+ "eslint": "3.19.0",
+ "eslint-config-standard": "10.2.1",
+ "eslint-plugin-import": "2.7.0",
+ "eslint-plugin-markdown": "1.0.0-beta.6",
+ "eslint-plugin-node": "5.1.1",
+ "eslint-plugin-promise": "3.5.0",
+ "eslint-plugin-standard": "3.0.1",
+ "istanbul": "0.4.5",
+ "mocha": "1.21.5",
+ "safe-buffer": "5.1.1",
+ "seedrandom": "2.4.3"
+ },
+ "files": [
+ "LICENSE",
+ "HISTORY.md",
+ "README.md",
+ "index.js"
+ ],
+ "engines": {
+ "node": ">= 0.6"
+ },
+ "scripts": {
+ "bench": "node benchmark/index.js",
+ "lint": "eslint --plugin markdown --ext js,md .",
+ "test": "mocha --reporter spec --bail --check-leaks test/",
+ "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/",
+ "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/"
+ }
+}
diff --git a/服务器端/node_modules/express/History.md b/服务器端/node_modules/express/History.md
new file mode 100644
index 0000000..4c12ec9
--- /dev/null
+++ b/服务器端/node_modules/express/History.md
@@ -0,0 +1,3579 @@
+4.18.1 / 2022-04-29
+===================
+
+ * Fix hanging on large stack of sync routes
+
+4.18.0 / 2022-04-25
+===================
+
+ * Add "root" option to `res.download`
+ * Allow `options` without `filename` in `res.download`
+ * Deprecate string and non-integer arguments to `res.status`
+ * Fix behavior of `null`/`undefined` as `maxAge` in `res.cookie`
+ * Fix handling very large stacks of sync middleware
+ * Ignore `Object.prototype` values in settings through `app.set`/`app.get`
+ * Invoke `default` with same arguments as types in `res.format`
+ * Support proper 205 responses using `res.send`
+ * Use `http-errors` for `res.format` error
+ * deps: body-parser@1.20.0
+ - Fix error message for json parse whitespace in `strict`
+ - Fix internal error when inflated body exceeds limit
+ - Prevent loss of async hooks context
+ - Prevent hanging when request already read
+ - deps: depd@2.0.0
+ - deps: http-errors@2.0.0
+ - deps: on-finished@2.4.1
+ - deps: qs@6.10.3
+ - deps: raw-body@2.5.1
+ * deps: cookie@0.5.0
+ - Add `priority` option
+ - Fix `expires` option to reject invalid dates
+ * deps: depd@2.0.0
+ - Replace internal `eval` usage with `Function` constructor
+ - Use instance methods on `process` to check for listeners
+ * deps: finalhandler@1.2.0
+ - Remove set content headers that break response
+ - deps: on-finished@2.4.1
+ - deps: statuses@2.0.1
+ * deps: on-finished@2.4.1
+ - Prevent loss of async hooks context
+ * deps: qs@6.10.3
+ * deps: send@0.18.0
+ - Fix emitted 416 error missing headers property
+ - Limit the headers removed for 304 response
+ - deps: depd@2.0.0
+ - deps: destroy@1.2.0
+ - deps: http-errors@2.0.0
+ - deps: on-finished@2.4.1
+ - deps: statuses@2.0.1
+ * deps: serve-static@1.15.0
+ - deps: send@0.18.0
+ * deps: statuses@2.0.1
+ - Remove code 306
+ - Rename `425 Unordered Collection` to standard `425 Too Early`
+
+4.17.3 / 2022-02-16
+===================
+
+ * deps: accepts@~1.3.8
+ - deps: mime-types@~2.1.34
+ - deps: negotiator@0.6.3
+ * deps: body-parser@1.19.2
+ - deps: bytes@3.1.2
+ - deps: qs@6.9.7
+ - deps: raw-body@2.4.3
+ * deps: cookie@0.4.2
+ * deps: qs@6.9.7
+ * Fix handling of `__proto__` keys
+ * pref: remove unnecessary regexp for trust proxy
+
+4.17.2 / 2021-12-16
+===================
+
+ * Fix handling of `undefined` in `res.jsonp`
+ * Fix handling of `undefined` when `"json escape"` is enabled
+ * Fix incorrect middleware execution with unanchored `RegExp`s
+ * Fix `res.jsonp(obj, status)` deprecation message
+ * Fix typo in `res.is` JSDoc
+ * deps: body-parser@1.19.1
+ - deps: bytes@3.1.1
+ - deps: http-errors@1.8.1
+ - deps: qs@6.9.6
+ - deps: raw-body@2.4.2
+ - deps: safe-buffer@5.2.1
+ - deps: type-is@~1.6.18
+ * deps: content-disposition@0.5.4
+ - deps: safe-buffer@5.2.1
+ * deps: cookie@0.4.1
+ - Fix `maxAge` option to reject invalid values
+ * deps: proxy-addr@~2.0.7
+ - Use `req.socket` over deprecated `req.connection`
+ - deps: forwarded@0.2.0
+ - deps: ipaddr.js@1.9.1
+ * deps: qs@6.9.6
+ * deps: safe-buffer@5.2.1
+ * deps: send@0.17.2
+ - deps: http-errors@1.8.1
+ - deps: ms@2.1.3
+ - pref: ignore empty http tokens
+ * deps: serve-static@1.14.2
+ - deps: send@0.17.2
+ * deps: setprototypeof@1.2.0
+
+4.17.1 / 2019-05-25
+===================
+
+ * Revert "Improve error message for `null`/`undefined` to `res.status`"
+
+4.17.0 / 2019-05-16
+===================
+
+ * Add `express.raw` to parse bodies into `Buffer`
+ * Add `express.text` to parse bodies into string
+ * Improve error message for non-strings to `res.sendFile`
+ * Improve error message for `null`/`undefined` to `res.status`
+ * Support multiple hosts in `X-Forwarded-Host`
+ * deps: accepts@~1.3.7
+ * deps: body-parser@1.19.0
+ - Add encoding MIK
+ - Add petabyte (`pb`) support
+ - Fix parsing array brackets after index
+ - deps: bytes@3.1.0
+ - deps: http-errors@1.7.2
+ - deps: iconv-lite@0.4.24
+ - deps: qs@6.7.0
+ - deps: raw-body@2.4.0
+ - deps: type-is@~1.6.17
+ * deps: content-disposition@0.5.3
+ * deps: cookie@0.4.0
+ - Add `SameSite=None` support
+ * deps: finalhandler@~1.1.2
+ - Set stricter `Content-Security-Policy` header
+ - deps: parseurl@~1.3.3
+ - deps: statuses@~1.5.0
+ * deps: parseurl@~1.3.3
+ * deps: proxy-addr@~2.0.5
+ - deps: ipaddr.js@1.9.0
+ * deps: qs@6.7.0
+ - Fix parsing array brackets after index
+ * deps: range-parser@~1.2.1
+ * deps: send@0.17.1
+ - Set stricter CSP header in redirect & error responses
+ - deps: http-errors@~1.7.2
+ - deps: mime@1.6.0
+ - deps: ms@2.1.1
+ - deps: range-parser@~1.2.1
+ - deps: statuses@~1.5.0
+ - perf: remove redundant `path.normalize` call
+ * deps: serve-static@1.14.1
+ - Set stricter CSP header in redirect response
+ - deps: parseurl@~1.3.3
+ - deps: send@0.17.1
+ * deps: setprototypeof@1.1.1
+ * deps: statuses@~1.5.0
+ - Add `103 Early Hints`
+ * deps: type-is@~1.6.18
+ - deps: mime-types@~2.1.24
+ - perf: prevent internal `throw` on invalid type
+
+4.16.4 / 2018-10-10
+===================
+
+ * Fix issue where `"Request aborted"` may be logged in `res.sendfile`
+ * Fix JSDoc for `Router` constructor
+ * deps: body-parser@1.18.3
+ - Fix deprecation warnings on Node.js 10+
+ - Fix stack trace for strict json parse error
+ - deps: depd@~1.1.2
+ - deps: http-errors@~1.6.3
+ - deps: iconv-lite@0.4.23
+ - deps: qs@6.5.2
+ - deps: raw-body@2.3.3
+ - deps: type-is@~1.6.16
+ * deps: proxy-addr@~2.0.4
+ - deps: ipaddr.js@1.8.0
+ * deps: qs@6.5.2
+ * deps: safe-buffer@5.1.2
+
+4.16.3 / 2018-03-12
+===================
+
+ * deps: accepts@~1.3.5
+ - deps: mime-types@~2.1.18
+ * deps: depd@~1.1.2
+ - perf: remove argument reassignment
+ * deps: encodeurl@~1.0.2
+ - Fix encoding `%` as last character
+ * deps: finalhandler@1.1.1
+ - Fix 404 output for bad / missing pathnames
+ - deps: encodeurl@~1.0.2
+ - deps: statuses@~1.4.0
+ * deps: proxy-addr@~2.0.3
+ - deps: ipaddr.js@1.6.0
+ * deps: send@0.16.2
+ - Fix incorrect end tag in default error & redirects
+ - deps: depd@~1.1.2
+ - deps: encodeurl@~1.0.2
+ - deps: statuses@~1.4.0
+ * deps: serve-static@1.13.2
+ - Fix incorrect end tag in redirects
+ - deps: encodeurl@~1.0.2
+ - deps: send@0.16.2
+ * deps: statuses@~1.4.0
+ * deps: type-is@~1.6.16
+ - deps: mime-types@~2.1.18
+
+4.16.2 / 2017-10-09
+===================
+
+ * Fix `TypeError` in `res.send` when given `Buffer` and `ETag` header set
+ * perf: skip parsing of entire `X-Forwarded-Proto` header
+
+4.16.1 / 2017-09-29
+===================
+
+ * deps: send@0.16.1
+ * deps: serve-static@1.13.1
+ - Fix regression when `root` is incorrectly set to a file
+ - deps: send@0.16.1
+
+4.16.0 / 2017-09-28
+===================
+
+ * Add `"json escape"` setting for `res.json` and `res.jsonp`
+ * Add `express.json` and `express.urlencoded` to parse bodies
+ * Add `options` argument to `res.download`
+ * Improve error message when autoloading invalid view engine
+ * Improve error messages when non-function provided as middleware
+ * Skip `Buffer` encoding when not generating ETag for small response
+ * Use `safe-buffer` for improved Buffer API
+ * deps: accepts@~1.3.4
+ - deps: mime-types@~2.1.16
+ * deps: content-type@~1.0.4
+ - perf: remove argument reassignment
+ - perf: skip parameter parsing when no parameters
+ * deps: etag@~1.8.1
+ - perf: replace regular expression with substring
+ * deps: finalhandler@1.1.0
+ - Use `res.headersSent` when available
+ * deps: parseurl@~1.3.2
+ - perf: reduce overhead for full URLs
+ - perf: unroll the "fast-path" `RegExp`
+ * deps: proxy-addr@~2.0.2
+ - Fix trimming leading / trailing OWS in `X-Forwarded-For`
+ - deps: forwarded@~0.1.2
+ - deps: ipaddr.js@1.5.2
+ - perf: reduce overhead when no `X-Forwarded-For` header
+ * deps: qs@6.5.1
+ - Fix parsing & compacting very deep objects
+ * deps: send@0.16.0
+ - Add 70 new types for file extensions
+ - Add `immutable` option
+ - Fix missing `