Used ejs to conditionally render login/logout text. Main index file is now index.ejs
This commit is contained in:
442
node_modules/express-session/HISTORY.md
generated
vendored
Normal file
442
node_modules/express-session/HISTORY.md
generated
vendored
Normal file
@@ -0,0 +1,442 @@
|
||||
1.17.3 / 2022-05-11
|
||||
===================
|
||||
|
||||
* Fix resaving already-saved new session at end of request
|
||||
* deps: cookie@0.4.2
|
||||
|
||||
1.17.2 / 2021-05-19
|
||||
===================
|
||||
|
||||
* Fix `res.end` patch to always commit headers
|
||||
* deps: cookie@0.4.1
|
||||
* deps: safe-buffer@5.2.1
|
||||
|
||||
1.17.1 / 2020-04-16
|
||||
===================
|
||||
|
||||
* Fix internal method wrapping error on failed reloads
|
||||
|
||||
1.17.0 / 2019-10-10
|
||||
===================
|
||||
|
||||
* deps: cookie@0.4.0
|
||||
- Add `SameSite=None` support
|
||||
* deps: safe-buffer@5.2.0
|
||||
|
||||
1.16.2 / 2019-06-12
|
||||
===================
|
||||
|
||||
* Fix restoring `cookie.originalMaxAge` when store returns `Date`
|
||||
* deps: parseurl@~1.3.3
|
||||
|
||||
1.16.1 / 2019-04-11
|
||||
===================
|
||||
|
||||
* Fix error passing `data` option to `Cookie` constructor
|
||||
* Fix uncaught error from bad session data
|
||||
|
||||
1.16.0 / 2019-04-10
|
||||
===================
|
||||
|
||||
* Catch invalid `cookie.maxAge` value earlier
|
||||
* Deprecate setting `cookie.maxAge` to a `Date` object
|
||||
* Fix issue where `resave: false` may not save altered sessions
|
||||
* Remove `utils-merge` dependency
|
||||
* Use `safe-buffer` for improved Buffer API
|
||||
* Use `Set-Cookie` as cookie header name for compatibility
|
||||
* deps: depd@~2.0.0
|
||||
- Replace internal `eval` usage with `Function` constructor
|
||||
- Use instance methods on `process` to check for listeners
|
||||
- perf: remove argument reassignment
|
||||
* deps: on-headers@~1.0.2
|
||||
- Fix `res.writeHead` patch missing return value
|
||||
|
||||
1.15.6 / 2017-09-26
|
||||
===================
|
||||
|
||||
* deps: debug@2.6.9
|
||||
* deps: parseurl@~1.3.2
|
||||
- perf: reduce overhead for full URLs
|
||||
- perf: unroll the "fast-path" `RegExp`
|
||||
* deps: uid-safe@~2.1.5
|
||||
- perf: remove only trailing `=`
|
||||
* deps: utils-merge@1.0.1
|
||||
|
||||
1.15.5 / 2017-08-02
|
||||
===================
|
||||
|
||||
* Fix `TypeError` when `req.url` is an empty string
|
||||
* deps: depd@~1.1.1
|
||||
- Remove unnecessary `Buffer` loading
|
||||
|
||||
1.15.4 / 2017-07-18
|
||||
===================
|
||||
|
||||
* deps: debug@2.6.8
|
||||
|
||||
1.15.3 / 2017-05-17
|
||||
===================
|
||||
|
||||
* deps: debug@2.6.7
|
||||
- deps: ms@2.0.0
|
||||
|
||||
1.15.2 / 2017-03-26
|
||||
===================
|
||||
|
||||
* deps: debug@2.6.3
|
||||
- Fix `DEBUG_MAX_ARRAY_LENGTH`
|
||||
* deps: uid-safe@~2.1.4
|
||||
- Remove `base64-url` dependency
|
||||
|
||||
1.15.1 / 2017-02-10
|
||||
===================
|
||||
|
||||
* deps: debug@2.6.1
|
||||
- Fix deprecation messages in WebStorm and other editors
|
||||
- Undeprecate `DEBUG_FD` set to `1` or `2`
|
||||
|
||||
1.15.0 / 2017-01-22
|
||||
===================
|
||||
|
||||
* Fix detecting modified session when session contains "cookie" property
|
||||
* Fix resaving already-saved reloaded session at end of request
|
||||
* deps: crc@3.4.4
|
||||
- perf: use `Buffer.from` when available
|
||||
* deps: debug@2.6.0
|
||||
- Allow colors in workers
|
||||
- Deprecated `DEBUG_FD` environment variable
|
||||
- Use same color for same namespace
|
||||
- Fix error when running under React Native
|
||||
- deps: ms@0.7.2
|
||||
* perf: remove unreachable branch in set-cookie method
|
||||
|
||||
1.14.2 / 2016-10-30
|
||||
===================
|
||||
|
||||
* deps: crc@3.4.1
|
||||
- Fix deprecation warning in Node.js 7.x
|
||||
* deps: uid-safe@~2.1.3
|
||||
- deps: base64-url@1.3.3
|
||||
|
||||
1.14.1 / 2016-08-24
|
||||
===================
|
||||
|
||||
* Fix not always resetting session max age before session save
|
||||
* Fix the cookie `sameSite` option to actually alter the `Set-Cookie`
|
||||
* deps: uid-safe@~2.1.2
|
||||
- deps: base64-url@1.3.2
|
||||
|
||||
1.14.0 / 2016-07-01
|
||||
===================
|
||||
|
||||
* Correctly inherit from `EventEmitter` class in `Store` base class
|
||||
* Fix issue where `Set-Cookie` `Expires` was not always updated
|
||||
* Methods are no longer enumerable on `req.session` object
|
||||
* deps: cookie@0.3.1
|
||||
- Add `sameSite` option
|
||||
- Improve error message when `encode` is not a function
|
||||
- Improve error message when `expires` is not a `Date`
|
||||
- perf: enable strict mode
|
||||
- perf: use for loop in parse
|
||||
- perf: use string concatination for serialization
|
||||
* deps: parseurl@~1.3.1
|
||||
- perf: enable strict mode
|
||||
* deps: uid-safe@~2.1.1
|
||||
- Use `random-bytes` for byte source
|
||||
- deps: base64-url@1.2.2
|
||||
* perf: enable strict mode
|
||||
* perf: remove argument reassignment
|
||||
|
||||
1.13.0 / 2016-01-10
|
||||
===================
|
||||
|
||||
* Fix `rolling: true` to not set cookie when no session exists
|
||||
- Better `saveUninitialized: false` + `rolling: true` behavior
|
||||
* deps: crc@3.4.0
|
||||
|
||||
1.12.1 / 2015-10-29
|
||||
===================
|
||||
|
||||
* deps: cookie@0.2.3
|
||||
- Fix cookie `Max-Age` to never be a floating point number
|
||||
|
||||
1.12.0 / 2015-10-25
|
||||
===================
|
||||
|
||||
* Support the value `'auto'` in the `cookie.secure` option
|
||||
* deps: cookie@0.2.2
|
||||
- Throw on invalid values provided to `serialize`
|
||||
* deps: depd@~1.1.0
|
||||
- Enable strict mode in more places
|
||||
- Support web browser loading
|
||||
* deps: on-headers@~1.0.1
|
||||
- perf: enable strict mode
|
||||
|
||||
1.11.3 / 2015-05-22
|
||||
===================
|
||||
|
||||
* deps: cookie@0.1.3
|
||||
- Slight optimizations
|
||||
* deps: crc@3.3.0
|
||||
|
||||
1.11.2 / 2015-05-10
|
||||
===================
|
||||
|
||||
* deps: debug@~2.2.0
|
||||
- deps: ms@0.7.1
|
||||
* deps: uid-safe@~2.0.0
|
||||
|
||||
1.11.1 / 2015-04-08
|
||||
===================
|
||||
|
||||
* Fix mutating `options.secret` value
|
||||
|
||||
1.11.0 / 2015-04-07
|
||||
===================
|
||||
|
||||
* Support an array in `secret` option for key rotation
|
||||
* deps: depd@~1.0.1
|
||||
|
||||
1.10.4 / 2015-03-15
|
||||
===================
|
||||
|
||||
* deps: debug@~2.1.3
|
||||
- Fix high intensity foreground color for bold
|
||||
- deps: ms@0.7.0
|
||||
|
||||
1.10.3 / 2015-02-16
|
||||
===================
|
||||
|
||||
* deps: cookie-signature@1.0.6
|
||||
* deps: uid-safe@1.1.0
|
||||
- Use `crypto.randomBytes`, if available
|
||||
- deps: base64-url@1.2.1
|
||||
|
||||
1.10.2 / 2015-01-31
|
||||
===================
|
||||
|
||||
* deps: uid-safe@1.0.3
|
||||
- Fix error branch that would throw
|
||||
- deps: base64-url@1.2.0
|
||||
|
||||
1.10.1 / 2015-01-08
|
||||
===================
|
||||
|
||||
* deps: uid-safe@1.0.2
|
||||
- Remove dependency on `mz`
|
||||
|
||||
1.10.0 / 2015-01-05
|
||||
===================
|
||||
|
||||
* Add `store.touch` interface for session stores
|
||||
* Fix `MemoryStore` expiration with `resave: false`
|
||||
* deps: debug@~2.1.1
|
||||
|
||||
1.9.3 / 2014-12-02
|
||||
==================
|
||||
|
||||
* Fix error when `req.sessionID` contains a non-string value
|
||||
|
||||
1.9.2 / 2014-11-22
|
||||
==================
|
||||
|
||||
* deps: crc@3.2.1
|
||||
- Minor fixes
|
||||
|
||||
1.9.1 / 2014-10-22
|
||||
==================
|
||||
|
||||
* Remove unnecessary empty write call
|
||||
- Fixes Node.js 0.11.14 behavior change
|
||||
- Helps work-around Node.js 0.10.1 zlib bug
|
||||
|
||||
1.9.0 / 2014-09-16
|
||||
==================
|
||||
|
||||
* deps: debug@~2.1.0
|
||||
- Implement `DEBUG_FD` env variable support
|
||||
* deps: depd@~1.0.0
|
||||
|
||||
1.8.2 / 2014-09-15
|
||||
==================
|
||||
|
||||
* Use `crc` instead of `buffer-crc32` for speed
|
||||
* deps: depd@0.4.5
|
||||
|
||||
1.8.1 / 2014-09-08
|
||||
==================
|
||||
|
||||
* Keep `req.session.save` non-enumerable
|
||||
* Prevent session prototype methods from being overwritten
|
||||
|
||||
1.8.0 / 2014-09-07
|
||||
==================
|
||||
|
||||
* Do not resave already-saved session at end of request
|
||||
* deps: cookie-signature@1.0.5
|
||||
* deps: debug@~2.0.0
|
||||
|
||||
1.7.6 / 2014-08-18
|
||||
==================
|
||||
|
||||
* Fix exception on `res.end(null)` calls
|
||||
|
||||
1.7.5 / 2014-08-10
|
||||
==================
|
||||
|
||||
* Fix parsing original URL
|
||||
* deps: on-headers@~1.0.0
|
||||
* deps: parseurl@~1.3.0
|
||||
|
||||
1.7.4 / 2014-08-05
|
||||
==================
|
||||
|
||||
* Fix response end delay for non-chunked responses
|
||||
|
||||
1.7.3 / 2014-08-05
|
||||
==================
|
||||
|
||||
* Fix `res.end` patch to call correct upstream `res.write`
|
||||
|
||||
1.7.2 / 2014-07-27
|
||||
==================
|
||||
|
||||
* deps: depd@0.4.4
|
||||
- Work-around v8 generating empty stack traces
|
||||
|
||||
1.7.1 / 2014-07-26
|
||||
==================
|
||||
|
||||
* deps: depd@0.4.3
|
||||
- Fix exception when global `Error.stackTraceLimit` is too low
|
||||
|
||||
1.7.0 / 2014-07-22
|
||||
==================
|
||||
|
||||
* Improve session-ending error handling
|
||||
- Errors are passed to `next(err)` instead of `console.error`
|
||||
* deps: debug@1.0.4
|
||||
* deps: depd@0.4.2
|
||||
- Add `TRACE_DEPRECATION` environment variable
|
||||
- Remove non-standard grey color from color output
|
||||
- Support `--no-deprecation` argument
|
||||
- Support `--trace-deprecation` argument
|
||||
|
||||
1.6.5 / 2014-07-11
|
||||
==================
|
||||
|
||||
* Do not require `req.originalUrl`
|
||||
* deps: debug@1.0.3
|
||||
- Add support for multiple wildcards in namespaces
|
||||
|
||||
1.6.4 / 2014-07-07
|
||||
==================
|
||||
|
||||
* Fix blank responses for stores with synchronous operations
|
||||
|
||||
1.6.3 / 2014-07-04
|
||||
==================
|
||||
|
||||
* Fix resave deprecation message
|
||||
|
||||
1.6.2 / 2014-07-04
|
||||
==================
|
||||
|
||||
* Fix confusing option deprecation messages
|
||||
|
||||
1.6.1 / 2014-06-28
|
||||
==================
|
||||
|
||||
* Fix saveUninitialized deprecation message
|
||||
|
||||
1.6.0 / 2014-06-28
|
||||
==================
|
||||
|
||||
* Add deprecation message to undefined `resave` option
|
||||
* Add deprecation message to undefined `saveUninitialized` option
|
||||
* Fix `res.end` patch to return correct value
|
||||
* Fix `res.end` patch to handle multiple `res.end` calls
|
||||
* Reject cookies with missing signatures
|
||||
|
||||
1.5.2 / 2014-06-26
|
||||
==================
|
||||
|
||||
* deps: cookie-signature@1.0.4
|
||||
- fix for timing attacks
|
||||
|
||||
1.5.1 / 2014-06-21
|
||||
==================
|
||||
|
||||
* Move hard-to-track-down `req.secret` deprecation message
|
||||
|
||||
1.5.0 / 2014-06-19
|
||||
==================
|
||||
|
||||
* Debug name is now "express-session"
|
||||
* Deprecate integration with `cookie-parser` middleware
|
||||
* Deprecate looking for secret in `req.secret`
|
||||
* Directly read cookies; `cookie-parser` no longer required
|
||||
* Directly set cookies; `res.cookie` no longer required
|
||||
* Generate session IDs with `uid-safe`, faster and even less collisions
|
||||
|
||||
1.4.0 / 2014-06-17
|
||||
==================
|
||||
|
||||
* Add `genid` option to generate custom session IDs
|
||||
* Add `saveUninitialized` option to control saving uninitialized sessions
|
||||
* Add `unset` option to control unsetting `req.session`
|
||||
* Generate session IDs with `rand-token` by default; reduce collisions
|
||||
* deps: buffer-crc32@0.2.3
|
||||
|
||||
1.3.1 / 2014-06-14
|
||||
==================
|
||||
|
||||
* Add description in package for npmjs.org listing
|
||||
|
||||
1.3.0 / 2014-06-14
|
||||
==================
|
||||
|
||||
* Integrate with express "trust proxy" by default
|
||||
* deps: debug@1.0.2
|
||||
|
||||
1.2.1 / 2014-05-27
|
||||
==================
|
||||
|
||||
* Fix `resave` such that `resave: true` works
|
||||
|
||||
1.2.0 / 2014-05-19
|
||||
==================
|
||||
|
||||
* Add `resave` option to control saving unmodified sessions
|
||||
|
||||
1.1.0 / 2014-05-12
|
||||
==================
|
||||
|
||||
* Add `name` option; replacement for `key` option
|
||||
* Use `setImmediate` in MemoryStore for node.js >= 0.10
|
||||
|
||||
1.0.4 / 2014-04-27
|
||||
==================
|
||||
|
||||
* deps: debug@0.8.1
|
||||
|
||||
1.0.3 / 2014-04-19
|
||||
==================
|
||||
|
||||
* Use `res.cookie()` instead of `res.setHeader()`
|
||||
* deps: cookie@0.1.2
|
||||
|
||||
1.0.2 / 2014-02-23
|
||||
==================
|
||||
|
||||
* Add missing dependency to `package.json`
|
||||
|
||||
1.0.1 / 2014-02-15
|
||||
==================
|
||||
|
||||
* Add missing dependencies to `package.json`
|
||||
|
||||
1.0.0 / 2014-02-15
|
||||
==================
|
||||
|
||||
* Genesis from `connect`
|
24
node_modules/express-session/LICENSE
generated
vendored
Normal file
24
node_modules/express-session/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2010 Sencha Inc.
|
||||
Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
|
||||
Copyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.com>
|
||||
|
||||
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.
|
985
node_modules/express-session/README.md
generated
vendored
Normal file
985
node_modules/express-session/README.md
generated
vendored
Normal file
@@ -0,0 +1,985 @@
|
||||
# express-session
|
||||
|
||||
[![NPM Version][npm-version-image]][npm-url]
|
||||
[![NPM Downloads][npm-downloads-image]][node-url]
|
||||
[![Build Status][ci-image]][ci-url]
|
||||
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||
|
||||
## 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 express-session
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
```js
|
||||
var session = require('express-session')
|
||||
```
|
||||
|
||||
### session(options)
|
||||
|
||||
Create a session middleware with the given `options`.
|
||||
|
||||
**Note** Session data is _not_ saved in the cookie itself, just the session ID.
|
||||
Session data is stored server-side.
|
||||
|
||||
**Note** Since version 1.5.0, the [`cookie-parser` middleware](https://www.npmjs.com/package/cookie-parser)
|
||||
no longer needs to be used for this module to work. This module now directly reads
|
||||
and writes cookies on `req`/`res`. Using `cookie-parser` may result in issues
|
||||
if the `secret` is not the same between this module and `cookie-parser`.
|
||||
|
||||
**Warning** The default server-side session storage, `MemoryStore`, is _purposely_
|
||||
not designed for a production environment. It will leak memory under most
|
||||
conditions, does not scale past a single process, and is meant for debugging and
|
||||
developing.
|
||||
|
||||
For a list of stores, see [compatible session stores](#compatible-session-stores).
|
||||
|
||||
#### Options
|
||||
|
||||
`express-session` accepts these properties in the options object.
|
||||
|
||||
##### cookie
|
||||
|
||||
Settings object for the session ID cookie. The default value is
|
||||
`{ path: '/', httpOnly: true, secure: false, maxAge: null }`.
|
||||
|
||||
The following are options that can be set in this object.
|
||||
|
||||
##### cookie.domain
|
||||
|
||||
Specifies the value for the `Domain` `Set-Cookie` attribute. By default, no domain
|
||||
is set, and most clients will consider the cookie to apply to only the current
|
||||
domain.
|
||||
|
||||
##### cookie.expires
|
||||
|
||||
Specifies the `Date` object to be the value for the `Expires` `Set-Cookie` attribute.
|
||||
By default, no expiration is set, and most clients will consider this a
|
||||
"non-persistent cookie" and will delete it on a condition like exiting a web browser
|
||||
application.
|
||||
|
||||
**Note** If both `expires` and `maxAge` are set in the options, then the last one
|
||||
defined in the object is what is used.
|
||||
|
||||
**Note** The `expires` option should not be set directly; instead only use the `maxAge`
|
||||
option.
|
||||
|
||||
##### cookie.httpOnly
|
||||
|
||||
Specifies the `boolean` value for the `HttpOnly` `Set-Cookie` attribute. When truthy,
|
||||
the `HttpOnly` attribute is set, otherwise it is not. By default, the `HttpOnly`
|
||||
attribute is set.
|
||||
|
||||
**Note** be careful when setting this to `true`, as compliant clients will not allow
|
||||
client-side JavaScript to see the cookie in `document.cookie`.
|
||||
|
||||
##### cookie.maxAge
|
||||
|
||||
Specifies the `number` (in milliseconds) to use when calculating the `Expires`
|
||||
`Set-Cookie` attribute. This is done by taking the current server time and adding
|
||||
`maxAge` milliseconds to the value to calculate an `Expires` datetime. By default,
|
||||
no maximum age is set.
|
||||
|
||||
**Note** If both `expires` and `maxAge` are set in the options, then the last one
|
||||
defined in the object is what is used.
|
||||
|
||||
##### cookie.path
|
||||
|
||||
Specifies the value for the `Path` `Set-Cookie`. By default, this is set to `'/'`, which
|
||||
is the root path of the domain.
|
||||
|
||||
##### cookie.sameSite
|
||||
|
||||
Specifies the `boolean` or `string` to be the value for the `SameSite` `Set-Cookie` attribute.
|
||||
By default, this is `false`.
|
||||
|
||||
- `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
|
||||
- `false` will not set the `SameSite` attribute.
|
||||
- `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement.
|
||||
- `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.
|
||||
- `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
|
||||
|
||||
More information about the different enforcement levels can be found in
|
||||
[the specification][rfc-6265bis-03-4.1.2.7].
|
||||
|
||||
**Note** This is an attribute that has not yet been fully standardized, and may change in
|
||||
the future. This also means many clients may ignore this attribute until they understand it.
|
||||
|
||||
**Note** There is a [draft spec](https://tools.ietf.org/html/draft-west-cookie-incrementalism-01)
|
||||
that requires that the `Secure` attribute be set to `true` when the `SameSite` attribute has been
|
||||
set to `'none'`. Some web browsers or other clients may be adopting this specification.
|
||||
|
||||
##### cookie.secure
|
||||
|
||||
Specifies the `boolean` value for the `Secure` `Set-Cookie` attribute. When truthy,
|
||||
the `Secure` attribute is set, otherwise it is not. By default, the `Secure`
|
||||
attribute is not set.
|
||||
|
||||
**Note** be careful when setting this to `true`, as compliant clients will not send
|
||||
the cookie back to the server in the future if the browser does not have an HTTPS
|
||||
connection.
|
||||
|
||||
Please note that `secure: true` is a **recommended** option. However, it requires
|
||||
an https-enabled website, i.e., HTTPS is necessary for secure cookies. If `secure`
|
||||
is set, and you access your site over HTTP, the cookie will not be set. If you
|
||||
have your node.js behind a proxy and are using `secure: true`, you need to set
|
||||
"trust proxy" in express:
|
||||
|
||||
```js
|
||||
var app = express()
|
||||
app.set('trust proxy', 1) // trust first proxy
|
||||
app.use(session({
|
||||
secret: 'keyboard cat',
|
||||
resave: false,
|
||||
saveUninitialized: true,
|
||||
cookie: { secure: true }
|
||||
}))
|
||||
```
|
||||
|
||||
For using secure cookies in production, but allowing for testing in development,
|
||||
the following is an example of enabling this setup based on `NODE_ENV` in express:
|
||||
|
||||
```js
|
||||
var app = express()
|
||||
var sess = {
|
||||
secret: 'keyboard cat',
|
||||
cookie: {}
|
||||
}
|
||||
|
||||
if (app.get('env') === 'production') {
|
||||
app.set('trust proxy', 1) // trust first proxy
|
||||
sess.cookie.secure = true // serve secure cookies
|
||||
}
|
||||
|
||||
app.use(session(sess))
|
||||
```
|
||||
|
||||
The `cookie.secure` option can also be set to the special value `'auto'` to have
|
||||
this setting automatically match the determined security of the connection. Be
|
||||
careful when using this setting if the site is available both as HTTP and HTTPS,
|
||||
as once the cookie is set on HTTPS, it will no longer be visible over HTTP. This
|
||||
is useful when the Express `"trust proxy"` setting is properly setup to simplify
|
||||
development vs production configuration.
|
||||
|
||||
##### genid
|
||||
|
||||
Function to call to generate a new session ID. Provide a function that returns
|
||||
a string that will be used as a session ID. The function is given `req` as the
|
||||
first argument if you want to use some value attached to `req` when generating
|
||||
the ID.
|
||||
|
||||
The default value is a function which uses the `uid-safe` library to generate IDs.
|
||||
|
||||
**NOTE** be careful to generate unique IDs so your sessions do not conflict.
|
||||
|
||||
```js
|
||||
app.use(session({
|
||||
genid: function(req) {
|
||||
return genuuid() // use UUIDs for session IDs
|
||||
},
|
||||
secret: 'keyboard cat'
|
||||
}))
|
||||
```
|
||||
|
||||
##### name
|
||||
|
||||
The name of the session ID cookie to set in the response (and read from in the
|
||||
request).
|
||||
|
||||
The default value is `'connect.sid'`.
|
||||
|
||||
**Note** if you have multiple apps running on the same hostname (this is just
|
||||
the name, i.e. `localhost` or `127.0.0.1`; different schemes and ports do not
|
||||
name a different hostname), then you need to separate the session cookies from
|
||||
each other. The simplest method is to simply set different `name`s per app.
|
||||
|
||||
##### proxy
|
||||
|
||||
Trust the reverse proxy when setting secure cookies (via the "X-Forwarded-Proto"
|
||||
header).
|
||||
|
||||
The default value is `undefined`.
|
||||
|
||||
- `true` The "X-Forwarded-Proto" header will be used.
|
||||
- `false` All headers are ignored and the connection is considered secure only
|
||||
if there is a direct TLS/SSL connection.
|
||||
- `undefined` Uses the "trust proxy" setting from express
|
||||
|
||||
##### resave
|
||||
|
||||
Forces the session to be saved back to the session store, even if the session
|
||||
was never modified during the request. Depending on your store this may be
|
||||
necessary, but it can also create race conditions where a client makes two
|
||||
parallel requests to your server and changes made to the session in one
|
||||
request may get overwritten when the other request ends, even if it made no
|
||||
changes (this behavior also depends on what store you're using).
|
||||
|
||||
The default value is `true`, but using the default has been deprecated,
|
||||
as the default will change in the future. Please research into this setting
|
||||
and choose what is appropriate to your use-case. Typically, you'll want
|
||||
`false`.
|
||||
|
||||
How do I know if this is necessary for my store? The best way to know is to
|
||||
check with your store if it implements the `touch` method. If it does, then
|
||||
you can safely set `resave: false`. If it does not implement the `touch`
|
||||
method and your store sets an expiration date on stored sessions, then you
|
||||
likely need `resave: true`.
|
||||
|
||||
##### rolling
|
||||
|
||||
Force the session identifier cookie to be set on every response. The expiration
|
||||
is reset to the original [`maxAge`](#cookiemaxage), resetting the expiration
|
||||
countdown.
|
||||
|
||||
The default value is `false`.
|
||||
|
||||
With this enabled, the session identifier cookie will expire in
|
||||
[`maxAge`](#cookiemaxage) since the last response was sent instead of in
|
||||
[`maxAge`](#cookiemaxage) since the session was last modified by the server.
|
||||
|
||||
This is typically used in conjuction with short, non-session-length
|
||||
[`maxAge`](#cookiemaxage) values to provide a quick timeout of the session data
|
||||
with reduced potential of it occurring during on going server interactions.
|
||||
|
||||
**Note** When this option is set to `true` but the `saveUninitialized` option is
|
||||
set to `false`, the cookie will not be set on a response with an uninitialized
|
||||
session. This option only modifies the behavior when an existing session was
|
||||
loaded for the request.
|
||||
|
||||
##### saveUninitialized
|
||||
|
||||
Forces a session that is "uninitialized" to be saved to the store. A session is
|
||||
uninitialized when it is new but not modified. Choosing `false` is useful for
|
||||
implementing login sessions, reducing server storage usage, or complying with
|
||||
laws that require permission before setting a cookie. Choosing `false` will also
|
||||
help with race conditions where a client makes multiple parallel requests
|
||||
without a session.
|
||||
|
||||
The default value is `true`, but using the default has been deprecated, as the
|
||||
default will change in the future. Please research into this setting and
|
||||
choose what is appropriate to your use-case.
|
||||
|
||||
**Note** if you are using Session in conjunction with PassportJS, Passport
|
||||
will add an empty Passport object to the session for use after a user is
|
||||
authenticated, which will be treated as a modification to the session, causing
|
||||
it to be saved. *This has been fixed in PassportJS 0.3.0*
|
||||
|
||||
##### secret
|
||||
|
||||
**Required option**
|
||||
|
||||
This is the secret used to sign the session ID cookie. This can be either a string
|
||||
for a single secret, or an array of multiple secrets. If an array of secrets is
|
||||
provided, only the first element will be used to sign the session ID cookie, while
|
||||
all the elements will be considered when verifying the signature in requests. The
|
||||
secret itself should be not easily parsed by a human and would best be a random set
|
||||
of characters. A best practice may include:
|
||||
|
||||
- The use of environment variables to store the secret, ensuring the secret itself
|
||||
does not exist in your repository.
|
||||
- Periodic updates of the secret, while ensuring the previous secret is in the
|
||||
array.
|
||||
|
||||
Using a secret that cannot be guessed will reduce the ability to hijack a session to
|
||||
only guessing the session ID (as determined by the `genid` option).
|
||||
|
||||
Changing the secret value will invalidate all existing sessions. In order to rotate
|
||||
the secret without invalidating sessions, provide an array of secrets, with the new
|
||||
secret as first element of the array, and including previous secrets as the later
|
||||
elements.
|
||||
|
||||
##### store
|
||||
|
||||
The session store instance, defaults to a new `MemoryStore` instance.
|
||||
|
||||
##### unset
|
||||
|
||||
Control the result of unsetting `req.session` (through `delete`, setting to `null`,
|
||||
etc.).
|
||||
|
||||
The default value is `'keep'`.
|
||||
|
||||
- `'destroy'` The session will be destroyed (deleted) when the response ends.
|
||||
- `'keep'` The session in the store will be kept, but modifications made during
|
||||
the request are ignored and not saved.
|
||||
|
||||
### 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:
|
||||
|
||||
```js
|
||||
// Use the session middleware
|
||||
app.use(session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }}))
|
||||
|
||||
// Access the session as req.session
|
||||
app.get('/', function(req, res, next) {
|
||||
if (req.session.views) {
|
||||
req.session.views++
|
||||
res.setHeader('Content-Type', 'text/html')
|
||||
res.write('<p>views: ' + req.session.views + '</p>')
|
||||
res.write('<p>expires in: ' + (req.session.cookie.maxAge / 1000) + 's</p>')
|
||||
res.end()
|
||||
} else {
|
||||
req.session.views = 1
|
||||
res.end('welcome to the session demo. refresh!')
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
#### Session.regenerate(callback)
|
||||
|
||||
To regenerate the session simply invoke the method. Once complete,
|
||||
a new SID and `Session` instance will be initialized at `req.session`
|
||||
and the `callback` will be invoked.
|
||||
|
||||
```js
|
||||
req.session.regenerate(function(err) {
|
||||
// will have a new session here
|
||||
})
|
||||
```
|
||||
|
||||
#### Session.destroy(callback)
|
||||
|
||||
Destroys the session and will unset the `req.session` property.
|
||||
Once complete, the `callback` will be invoked.
|
||||
|
||||
```js
|
||||
req.session.destroy(function(err) {
|
||||
// cannot access session here
|
||||
})
|
||||
```
|
||||
|
||||
#### Session.reload(callback)
|
||||
|
||||
Reloads the session data from the store and re-populates the
|
||||
`req.session` object. Once complete, the `callback` will be invoked.
|
||||
|
||||
```js
|
||||
req.session.reload(function(err) {
|
||||
// session updated
|
||||
})
|
||||
```
|
||||
|
||||
#### Session.save(callback)
|
||||
|
||||
Save the session back to the store, replacing the contents on the store with the
|
||||
contents in memory (though a store may do something else--consult the store's
|
||||
documentation for exact behavior).
|
||||
|
||||
This method is automatically called at the end of the HTTP response if the
|
||||
session data has been altered (though this behavior can be altered with various
|
||||
options in the middleware constructor). Because of this, typically this method
|
||||
does not need to be called.
|
||||
|
||||
There are some cases where it is useful to call this method, for example,
|
||||
redirects, long-lived requests or in WebSockets.
|
||||
|
||||
```js
|
||||
req.session.save(function(err) {
|
||||
// session saved
|
||||
})
|
||||
```
|
||||
|
||||
#### Session.touch()
|
||||
|
||||
Updates the `.maxAge` property. Typically this is
|
||||
not necessary to call, as the session middleware does this for you.
|
||||
|
||||
### req.session.id
|
||||
|
||||
Each session has a unique ID associated with it. This property is an
|
||||
alias of [`req.sessionID`](#reqsessionid-1) and cannot be modified.
|
||||
It has been added to make the session ID accessible from the `session`
|
||||
object.
|
||||
|
||||
### req.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.
|
||||
|
||||
#### Cookie.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
|
||||
|
||||
```js
|
||||
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 reset
|
||||
`req.session.cookie.maxAge` to its original value.
|
||||
|
||||
```js
|
||||
req.session.cookie.maxAge // => 30000
|
||||
```
|
||||
|
||||
#### Cookie.originalMaxAge
|
||||
|
||||
The `req.session.cookie.originalMaxAge` property returns the original
|
||||
`maxAge` (time-to-live), in milliseconds, of the session cookie.
|
||||
|
||||
### req.sessionID
|
||||
|
||||
To get the ID of the loaded session, access the request property
|
||||
`req.sessionID`. This is simply a read-only value set when a session
|
||||
is loaded/created.
|
||||
|
||||
## Session Store Implementation
|
||||
|
||||
Every session store _must_ be an `EventEmitter` and implement specific
|
||||
methods. The following methods are the list of **required**, **recommended**,
|
||||
and **optional**.
|
||||
|
||||
* Required methods are ones that this module will always call on the store.
|
||||
* Recommended methods are ones that this module will call on the store if
|
||||
available.
|
||||
* Optional methods are ones this module does not call at all, but helps
|
||||
present uniform stores to users.
|
||||
|
||||
For an example implementation view the [connect-redis](http://github.com/visionmedia/connect-redis) repo.
|
||||
|
||||
### store.all(callback)
|
||||
|
||||
**Optional**
|
||||
|
||||
This optional method is used to get all sessions in the store as an array. The
|
||||
`callback` should be called as `callback(error, sessions)`.
|
||||
|
||||
### store.destroy(sid, callback)
|
||||
|
||||
**Required**
|
||||
|
||||
This required method is used to destroy/delete a session from the store given
|
||||
a session ID (`sid`). The `callback` should be called as `callback(error)` once
|
||||
the session is destroyed.
|
||||
|
||||
### store.clear(callback)
|
||||
|
||||
**Optional**
|
||||
|
||||
This optional method is used to delete all sessions from the store. The
|
||||
`callback` should be called as `callback(error)` once the store is cleared.
|
||||
|
||||
### store.length(callback)
|
||||
|
||||
**Optional**
|
||||
|
||||
This optional method is used to get the count of all sessions in the store.
|
||||
The `callback` should be called as `callback(error, len)`.
|
||||
|
||||
### store.get(sid, callback)
|
||||
|
||||
**Required**
|
||||
|
||||
This required method is used to get a session from the store given a session
|
||||
ID (`sid`). The `callback` should be called as `callback(error, session)`.
|
||||
|
||||
The `session` argument should be a session if found, otherwise `null` or
|
||||
`undefined` if the session was not found (and there was no error). A special
|
||||
case is made when `error.code === 'ENOENT'` to act like `callback(null, null)`.
|
||||
|
||||
### store.set(sid, session, callback)
|
||||
|
||||
**Required**
|
||||
|
||||
This required method is used to upsert a session into the store given a
|
||||
session ID (`sid`) and session (`session`) object. The callback should be
|
||||
called as `callback(error)` once the session has been set in the store.
|
||||
|
||||
### store.touch(sid, session, callback)
|
||||
|
||||
**Recommended**
|
||||
|
||||
This recommended method is used to "touch" a given session given a
|
||||
session ID (`sid`) and session (`session`) object. The `callback` should be
|
||||
called as `callback(error)` once the session has been touched.
|
||||
|
||||
This is primarily used when the store will automatically delete idle sessions
|
||||
and this method is used to signal to the store the given session is active,
|
||||
potentially resetting the idle timer.
|
||||
|
||||
## Compatible Session Stores
|
||||
|
||||
The following modules implement a session store that is compatible with this
|
||||
module. Please make a PR to add additional modules :)
|
||||
|
||||
[![★][aerospike-session-store-image] aerospike-session-store][aerospike-session-store-url] A session store using [Aerospike](http://www.aerospike.com/).
|
||||
|
||||
[aerospike-session-store-url]: https://www.npmjs.com/package/aerospike-session-store
|
||||
[aerospike-session-store-image]: https://badgen.net/github/stars/aerospike/aerospike-session-store-expressjs?label=%E2%98%85
|
||||
|
||||
[![★][better-sqlite3-session-store-image] better-sqlite3-session-store][better-sqlite3-session-store-url] A session store based on [better-sqlite3](https://github.com/JoshuaWise/better-sqlite3).
|
||||
|
||||
[better-sqlite3-session-store-url]: https://www.npmjs.com/package/better-sqlite3-session-store
|
||||
[better-sqlite3-session-store-image]: https://badgen.net/github/stars/timdaub/better-sqlite3-session-store?label=%E2%98%85
|
||||
|
||||
[![★][cassandra-store-image] cassandra-store][cassandra-store-url] An Apache Cassandra-based session store.
|
||||
|
||||
[cassandra-store-url]: https://www.npmjs.com/package/cassandra-store
|
||||
[cassandra-store-image]: https://badgen.net/github/stars/webcc/cassandra-store?label=%E2%98%85
|
||||
|
||||
[![★][cluster-store-image] cluster-store][cluster-store-url] A wrapper for using in-process / embedded
|
||||
stores - such as SQLite (via knex), leveldb, files, or memory - with node cluster (desirable for Raspberry Pi 2
|
||||
and other multi-core embedded devices).
|
||||
|
||||
[cluster-store-url]: https://www.npmjs.com/package/cluster-store
|
||||
[cluster-store-image]: https://badgen.net/github/stars/coolaj86/cluster-store?label=%E2%98%85
|
||||
|
||||
[![★][connect-arango-image] connect-arango][connect-arango-url] An ArangoDB-based session store.
|
||||
|
||||
[connect-arango-url]: https://www.npmjs.com/package/connect-arango
|
||||
[connect-arango-image]: https://badgen.net/github/stars/AlexanderArvidsson/connect-arango?label=%E2%98%85
|
||||
|
||||
[![★][connect-azuretables-image] connect-azuretables][connect-azuretables-url] An [Azure Table Storage](https://azure.microsoft.com/en-gb/services/storage/tables/)-based session store.
|
||||
|
||||
[connect-azuretables-url]: https://www.npmjs.com/package/connect-azuretables
|
||||
[connect-azuretables-image]: https://badgen.net/github/stars/mike-goodwin/connect-azuretables?label=%E2%98%85
|
||||
|
||||
[![★][connect-cloudant-store-image] connect-cloudant-store][connect-cloudant-store-url] An [IBM Cloudant](https://cloudant.com/)-based session store.
|
||||
|
||||
[connect-cloudant-store-url]: https://www.npmjs.com/package/connect-cloudant-store
|
||||
[connect-cloudant-store-image]: https://badgen.net/github/stars/adriantanasa/connect-cloudant-store?label=%E2%98%85
|
||||
|
||||
[![★][connect-couchbase-image] connect-couchbase][connect-couchbase-url] A [couchbase](http://www.couchbase.com/)-based session store.
|
||||
|
||||
[connect-couchbase-url]: https://www.npmjs.com/package/connect-couchbase
|
||||
[connect-couchbase-image]: https://badgen.net/github/stars/christophermina/connect-couchbase?label=%E2%98%85
|
||||
|
||||
[![★][connect-datacache-image] connect-datacache][connect-datacache-url] An [IBM Bluemix Data Cache](http://www.ibm.com/cloud-computing/bluemix/)-based session store.
|
||||
|
||||
[connect-datacache-url]: https://www.npmjs.com/package/connect-datacache
|
||||
[connect-datacache-image]: https://badgen.net/github/stars/adriantanasa/connect-datacache?label=%E2%98%85
|
||||
|
||||
[![★][@google-cloud/connect-datastore-image] @google-cloud/connect-datastore][@google-cloud/connect-datastore-url] A [Google Cloud Datastore](https://cloud.google.com/datastore/docs/concepts/overview)-based session store.
|
||||
|
||||
[@google-cloud/connect-datastore-url]: https://www.npmjs.com/package/@google-cloud/connect-datastore
|
||||
[@google-cloud/connect-datastore-image]: https://badgen.net/github/stars/GoogleCloudPlatform/cloud-datastore-session-node?label=%E2%98%85
|
||||
|
||||
[![★][connect-db2-image] connect-db2][connect-db2-url] An IBM DB2-based session store built using [ibm_db](https://www.npmjs.com/package/ibm_db) module.
|
||||
|
||||
[connect-db2-url]: https://www.npmjs.com/package/connect-db2
|
||||
[connect-db2-image]: https://badgen.net/github/stars/wallali/connect-db2?label=%E2%98%85
|
||||
|
||||
[![★][connect-dynamodb-image] connect-dynamodb][connect-dynamodb-url] A DynamoDB-based session store.
|
||||
|
||||
[connect-dynamodb-url]: https://www.npmjs.com/package/connect-dynamodb
|
||||
[connect-dynamodb-image]: https://badgen.net/github/stars/ca98am79/connect-dynamodb?label=%E2%98%85
|
||||
|
||||
[![★][@google-cloud/connect-firestore-image] @google-cloud/connect-firestore][@google-cloud/connect-firestore-url] A [Google Cloud Firestore](https://cloud.google.com/firestore/docs/overview)-based session store.
|
||||
|
||||
[@google-cloud/connect-firestore-url]: https://www.npmjs.com/package/@google-cloud/connect-firestore
|
||||
[@google-cloud/connect-firestore-image]: https://badgen.net/github/stars/googleapis/nodejs-firestore-session?label=%E2%98%85
|
||||
|
||||
[![★][connect-hazelcast-image] connect-hazelcast][connect-hazelcast-url] Hazelcast session store for Connect and Express.
|
||||
|
||||
[connect-hazelcast-url]: https://www.npmjs.com/package/connect-hazelcast
|
||||
[connect-hazelcast-image]: https://badgen.net/github/stars/huseyinbabal/connect-hazelcast?label=%E2%98%85
|
||||
|
||||
[![★][connect-loki-image] connect-loki][connect-loki-url] A Loki.js-based session store.
|
||||
|
||||
[connect-loki-url]: https://www.npmjs.com/package/connect-loki
|
||||
[connect-loki-image]: https://badgen.net/github/stars/Requarks/connect-loki?label=%E2%98%85
|
||||
|
||||
[![★][connect-lowdb-image] connect-lowdb][connect-lowdb-url] A lowdb-based session store.
|
||||
|
||||
[connect-lowdb-url]: https://www.npmjs.com/package/connect-lowdb
|
||||
[connect-lowdb-image]: https://badgen.net/github/stars/travishorn/connect-lowdb?label=%E2%98%85
|
||||
|
||||
[![★][connect-memcached-image] connect-memcached][connect-memcached-url] A memcached-based session store.
|
||||
|
||||
[connect-memcached-url]: https://www.npmjs.com/package/connect-memcached
|
||||
[connect-memcached-image]: https://badgen.net/github/stars/balor/connect-memcached?label=%E2%98%85
|
||||
|
||||
[![★][connect-memjs-image] connect-memjs][connect-memjs-url] A memcached-based session store using
|
||||
[memjs](https://www.npmjs.com/package/memjs) as the memcached client.
|
||||
|
||||
[connect-memjs-url]: https://www.npmjs.com/package/connect-memjs
|
||||
[connect-memjs-image]: https://badgen.net/github/stars/liamdon/connect-memjs?label=%E2%98%85
|
||||
|
||||
[![★][connect-ml-image] connect-ml][connect-ml-url] A MarkLogic Server-based session store.
|
||||
|
||||
[connect-ml-url]: https://www.npmjs.com/package/connect-ml
|
||||
[connect-ml-image]: https://badgen.net/github/stars/bluetorch/connect-ml?label=%E2%98%85
|
||||
|
||||
[![★][connect-monetdb-image] connect-monetdb][connect-monetdb-url] A MonetDB-based session store.
|
||||
|
||||
[connect-monetdb-url]: https://www.npmjs.com/package/connect-monetdb
|
||||
[connect-monetdb-image]: https://badgen.net/github/stars/MonetDB/npm-connect-monetdb?label=%E2%98%85
|
||||
|
||||
[![★][connect-mongo-image] connect-mongo][connect-mongo-url] A MongoDB-based session store.
|
||||
|
||||
[connect-mongo-url]: https://www.npmjs.com/package/connect-mongo
|
||||
[connect-mongo-image]: https://badgen.net/github/stars/kcbanner/connect-mongo?label=%E2%98%85
|
||||
|
||||
[![★][connect-mongodb-session-image] connect-mongodb-session][connect-mongodb-session-url] Lightweight MongoDB-based session store built and maintained by MongoDB.
|
||||
|
||||
[connect-mongodb-session-url]: https://www.npmjs.com/package/connect-mongodb-session
|
||||
[connect-mongodb-session-image]: https://badgen.net/github/stars/mongodb-js/connect-mongodb-session?label=%E2%98%85
|
||||
|
||||
[![★][connect-mssql-v2-image] connect-mssql-v2][connect-mssql-v2-url] A Microsoft SQL Server-based session store based on [connect-mssql](https://www.npmjs.com/package/connect-mssql).
|
||||
|
||||
[connect-mssql-v2-url]: https://www.npmjs.com/package/connect-mssql-v2
|
||||
[connect-mssql-v2-image]: https://badgen.net/github/stars/jluboff/connect-mssql-v2?label=%E2%98%85
|
||||
|
||||
[![★][connect-neo4j-image] connect-neo4j][connect-neo4j-url] A [Neo4j](https://neo4j.com)-based session store.
|
||||
|
||||
[connect-neo4j-url]: https://www.npmjs.com/package/connect-neo4j
|
||||
[connect-neo4j-image]: https://badgen.net/github/stars/MaxAndersson/connect-neo4j?label=%E2%98%85
|
||||
|
||||
[![★][connect-pg-simple-image] connect-pg-simple][connect-pg-simple-url] A PostgreSQL-based session store.
|
||||
|
||||
[connect-pg-simple-url]: https://www.npmjs.com/package/connect-pg-simple
|
||||
[connect-pg-simple-image]: https://badgen.net/github/stars/voxpelli/node-connect-pg-simple?label=%E2%98%85
|
||||
|
||||
[![★][connect-redis-image] connect-redis][connect-redis-url] A Redis-based session store.
|
||||
|
||||
[connect-redis-url]: https://www.npmjs.com/package/connect-redis
|
||||
[connect-redis-image]: https://badgen.net/github/stars/tj/connect-redis?label=%E2%98%85
|
||||
|
||||
[![★][connect-session-firebase-image] connect-session-firebase][connect-session-firebase-url] A session store based on the [Firebase Realtime Database](https://firebase.google.com/docs/database/)
|
||||
|
||||
[connect-session-firebase-url]: https://www.npmjs.com/package/connect-session-firebase
|
||||
[connect-session-firebase-image]: https://badgen.net/github/stars/benweier/connect-session-firebase?label=%E2%98%85
|
||||
|
||||
[![★][connect-session-knex-image] connect-session-knex][connect-session-knex-url] A session store using
|
||||
[Knex.js](http://knexjs.org/), which is a SQL query builder for PostgreSQL, MySQL, MariaDB, SQLite3, and Oracle.
|
||||
|
||||
[connect-session-knex-url]: https://www.npmjs.com/package/connect-session-knex
|
||||
[connect-session-knex-image]: https://badgen.net/github/stars/llambda/connect-session-knex?label=%E2%98%85
|
||||
|
||||
[![★][connect-session-sequelize-image] connect-session-sequelize][connect-session-sequelize-url] A session store using
|
||||
[Sequelize.js](http://sequelizejs.com/), which is a Node.js / io.js ORM for PostgreSQL, MySQL, SQLite and MSSQL.
|
||||
|
||||
[connect-session-sequelize-url]: https://www.npmjs.com/package/connect-session-sequelize
|
||||
[connect-session-sequelize-image]: https://badgen.net/github/stars/mweibel/connect-session-sequelize?label=%E2%98%85
|
||||
|
||||
[![★][connect-sqlite3-image] connect-sqlite3][connect-sqlite3-url] A [SQLite3](https://github.com/mapbox/node-sqlite3) session store modeled after the TJ's `connect-redis` store.
|
||||
|
||||
[connect-sqlite3-url]: https://www.npmjs.com/package/connect-sqlite3
|
||||
[connect-sqlite3-image]: https://badgen.net/github/stars/rawberg/connect-sqlite3?label=%E2%98%85
|
||||
|
||||
[![★][connect-typeorm-image] connect-typeorm][connect-typeorm-url] A [TypeORM](https://github.com/typeorm/typeorm)-based session store.
|
||||
|
||||
[connect-typeorm-url]: https://www.npmjs.com/package/connect-typeorm
|
||||
[connect-typeorm-image]: https://badgen.net/github/stars/makepost/connect-typeorm?label=%E2%98%85
|
||||
|
||||
[![★][couchdb-expression-image] couchdb-expression][couchdb-expression-url] A [CouchDB](https://couchdb.apache.org/)-based session store.
|
||||
|
||||
[couchdb-expression-url]: https://www.npmjs.com/package/couchdb-expression
|
||||
[couchdb-expression-image]: https://badgen.net/github/stars/tkshnwesper/couchdb-expression?label=%E2%98%85
|
||||
|
||||
[![★][dynamodb-store-image] dynamodb-store][dynamodb-store-url] A DynamoDB-based session store.
|
||||
|
||||
[dynamodb-store-url]: https://www.npmjs.com/package/dynamodb-store
|
||||
[dynamodb-store-image]: https://badgen.net/github/stars/rafaelrpinto/dynamodb-store?label=%E2%98%85
|
||||
|
||||
[![★][express-etcd-image] express-etcd][express-etcd-url] An [etcd](https://github.com/stianeikeland/node-etcd) based session store.
|
||||
|
||||
[express-etcd-url]: https://www.npmjs.com/package/express-etcd
|
||||
[express-etcd-image]: https://badgen.net/github/stars/gildean/express-etcd?label=%E2%98%85
|
||||
|
||||
[![★][express-mysql-session-image] express-mysql-session][express-mysql-session-url] A session store using native
|
||||
[MySQL](https://www.mysql.com/) via the [node-mysql](https://github.com/felixge/node-mysql) module.
|
||||
|
||||
[express-mysql-session-url]: https://www.npmjs.com/package/express-mysql-session
|
||||
[express-mysql-session-image]: https://badgen.net/github/stars/chill117/express-mysql-session?label=%E2%98%85
|
||||
|
||||
[![★][express-nedb-session-image] express-nedb-session][express-nedb-session-url] A NeDB-based session store.
|
||||
|
||||
[express-nedb-session-url]: https://www.npmjs.com/package/express-nedb-session
|
||||
[express-nedb-session-image]: https://badgen.net/github/stars/louischatriot/express-nedb-session?label=%E2%98%85
|
||||
|
||||
[![★][express-oracle-session-image] express-oracle-session][express-oracle-session-url] A session store using native
|
||||
[oracle](https://www.oracle.com/) via the [node-oracledb](https://www.npmjs.com/package/oracledb) module.
|
||||
|
||||
[express-oracle-session-url]: https://www.npmjs.com/package/express-oracle-session
|
||||
[express-oracle-session-image]: https://badgen.net/github/stars/slumber86/express-oracle-session?label=%E2%98%85
|
||||
|
||||
[![★][express-session-cache-manager-image] express-session-cache-manager][express-session-cache-manager-url]
|
||||
A store that implements [cache-manager](https://www.npmjs.com/package/cache-manager), which supports
|
||||
a [variety of storage types](https://www.npmjs.com/package/cache-manager#store-engines).
|
||||
|
||||
[express-session-cache-manager-url]: https://www.npmjs.com/package/express-session-cache-manager
|
||||
[express-session-cache-manager-image]: https://badgen.net/github/stars/theogravity/express-session-cache-manager?label=%E2%98%85
|
||||
|
||||
[![★][express-session-etcd3-image] express-session-etcd3][express-session-etcd3-url] An [etcd3](https://github.com/mixer/etcd3) based session store.
|
||||
|
||||
[express-session-etcd3-url]: https://www.npmjs.com/package/express-session-etcd3
|
||||
[express-session-etcd3-image]: https://badgen.net/github/stars/willgm/express-session-etcd3?label=%E2%98%85
|
||||
|
||||
[![★][express-session-level-image] express-session-level][express-session-level-url] A [LevelDB](https://github.com/Level/levelup) based session store.
|
||||
|
||||
[express-session-level-url]: https://www.npmjs.com/package/express-session-level
|
||||
[express-session-level-image]: https://badgen.net/github/stars/tgohn/express-session-level?label=%E2%98%85
|
||||
|
||||
[![★][express-session-rsdb-image] express-session-rsdb][express-session-rsdb-url] Session store based on Rocket-Store: A very simple, super fast and yet powerfull, flat file database.
|
||||
|
||||
[express-session-rsdb-url]: https://www.npmjs.com/package/express-session-rsdb
|
||||
[express-session-rsdb-image]: https://badgen.net/github/stars/paragi/express-session-rsdb?label=%E2%98%85
|
||||
|
||||
[![★][express-sessions-image] express-sessions][express-sessions-url] A session store supporting both MongoDB and Redis.
|
||||
|
||||
[express-sessions-url]: https://www.npmjs.com/package/express-sessions
|
||||
[express-sessions-image]: https://badgen.net/github/stars/konteck/express-sessions?label=%E2%98%85
|
||||
|
||||
[![★][firestore-store-image] firestore-store][firestore-store-url] A [Firestore](https://github.com/hendrysadrak/firestore-store)-based session store.
|
||||
|
||||
[firestore-store-url]: https://www.npmjs.com/package/firestore-store
|
||||
[firestore-store-image]: https://badgen.net/github/stars/hendrysadrak/firestore-store?label=%E2%98%85
|
||||
|
||||
[![★][fortune-session-image] fortune-session][fortune-session-url] A [Fortune.js](https://github.com/fortunejs/fortune)
|
||||
based session store. Supports all backends supported by Fortune (MongoDB, Redis, Postgres, NeDB).
|
||||
|
||||
[fortune-session-url]: https://www.npmjs.com/package/fortune-session
|
||||
[fortune-session-image]: https://badgen.net/github/stars/aliceklipper/fortune-session?label=%E2%98%85
|
||||
|
||||
[![★][hazelcast-store-image] hazelcast-store][hazelcast-store-url] A Hazelcast-based session store built on the [Hazelcast Node Client](https://www.npmjs.com/package/hazelcast-client).
|
||||
|
||||
[hazelcast-store-url]: https://www.npmjs.com/package/hazelcast-store
|
||||
[hazelcast-store-image]: https://badgen.net/github/stars/jackspaniel/hazelcast-store?label=%E2%98%85
|
||||
|
||||
[![★][level-session-store-image] level-session-store][level-session-store-url] A LevelDB-based session store.
|
||||
|
||||
[level-session-store-url]: https://www.npmjs.com/package/level-session-store
|
||||
[level-session-store-image]: https://badgen.net/github/stars/toddself/level-session-store?label=%E2%98%85
|
||||
|
||||
[![★][lowdb-session-store-image] lowdb-session-store][lowdb-session-store-url] A [lowdb](https://www.npmjs.com/package/lowdb)-based session store.
|
||||
|
||||
[lowdb-session-store-url]: https://www.npmjs.com/package/lowdb-session-store
|
||||
[lowdb-session-store-image]: https://badgen.net/github/stars/fhellwig/lowdb-session-store?label=%E2%98%85
|
||||
|
||||
[![★][medea-session-store-image] medea-session-store][medea-session-store-url] A Medea-based session store.
|
||||
|
||||
[medea-session-store-url]: https://www.npmjs.com/package/medea-session-store
|
||||
[medea-session-store-image]: https://badgen.net/github/stars/BenjaminVadant/medea-session-store?label=%E2%98%85
|
||||
|
||||
[![★][memorystore-image] memorystore][memorystore-url] A memory session store made for production.
|
||||
|
||||
[memorystore-url]: https://www.npmjs.com/package/memorystore
|
||||
[memorystore-image]: https://badgen.net/github/stars/roccomuso/memorystore?label=%E2%98%85
|
||||
|
||||
[![★][mssql-session-store-image] mssql-session-store][mssql-session-store-url] A SQL Server-based session store.
|
||||
|
||||
[mssql-session-store-url]: https://www.npmjs.com/package/mssql-session-store
|
||||
[mssql-session-store-image]: https://badgen.net/github/stars/jwathen/mssql-session-store?label=%E2%98%85
|
||||
|
||||
[![★][nedb-session-store-image] nedb-session-store][nedb-session-store-url] An alternate NeDB-based (either in-memory or file-persisted) session store.
|
||||
|
||||
[nedb-session-store-url]: https://www.npmjs.com/package/nedb-session-store
|
||||
[nedb-session-store-image]: https://badgen.net/github/stars/JamesMGreene/nedb-session-store?label=%E2%98%85
|
||||
|
||||
[![★][@quixo3/prisma-session-store-image] @quixo3/prisma-session-store][@quixo3/prisma-session-store-url] A session store for the [Prisma Framework](https://www.prisma.io).
|
||||
|
||||
[@quixo3/prisma-session-store-url]: https://www.npmjs.com/package/@quixo3/prisma-session-store
|
||||
[@quixo3/prisma-session-store-image]: https://badgen.net/github/stars/kleydon/prisma-session-store?label=%E2%98%85
|
||||
|
||||
[![★][restsession-image] restsession][restsession-url] Store sessions utilizing a RESTful API
|
||||
|
||||
[restsession-url]: https://www.npmjs.com/package/restsession
|
||||
[restsession-image]: https://badgen.net/github/stars/jankal/restsession?label=%E2%98%85
|
||||
|
||||
[![★][sequelstore-connect-image] sequelstore-connect][sequelstore-connect-url] A session store using [Sequelize.js](http://sequelizejs.com/).
|
||||
|
||||
[sequelstore-connect-url]: https://www.npmjs.com/package/sequelstore-connect
|
||||
[sequelstore-connect-image]: https://badgen.net/github/stars/MattMcFarland/sequelstore-connect?label=%E2%98%85
|
||||
|
||||
[![★][session-file-store-image] session-file-store][session-file-store-url] A file system-based session store.
|
||||
|
||||
[session-file-store-url]: https://www.npmjs.com/package/session-file-store
|
||||
[session-file-store-image]: https://badgen.net/github/stars/valery-barysok/session-file-store?label=%E2%98%85
|
||||
|
||||
[![★][session-pouchdb-store-image] session-pouchdb-store][session-pouchdb-store-url] Session store for PouchDB / CouchDB. Accepts embedded, custom, or remote PouchDB instance and realtime synchronization.
|
||||
|
||||
[session-pouchdb-store-url]: https://www.npmjs.com/package/session-pouchdb-store
|
||||
[session-pouchdb-store-image]: https://badgen.net/github/stars/solzimer/session-pouchdb-store?label=%E2%98%85
|
||||
|
||||
[![★][session-rethinkdb-image] session-rethinkdb][session-rethinkdb-url] A [RethinkDB](http://rethinkdb.com/)-based session store.
|
||||
|
||||
[session-rethinkdb-url]: https://www.npmjs.com/package/session-rethinkdb
|
||||
[session-rethinkdb-image]: https://badgen.net/github/stars/llambda/session-rethinkdb?label=%E2%98%85
|
||||
|
||||
[![★][@databunker/session-store-image] @databunker/session-store][@databunker/session-store-url] A [Databunker](https://databunker.org/)-based encrypted session store.
|
||||
|
||||
[@databunker/session-store-url]: https://www.npmjs.com/package/@databunker/session-store
|
||||
[@databunker/session-store-image]: https://badgen.net/github/stars/securitybunker/databunker-session-store?label=%E2%98%85
|
||||
|
||||
[![★][sessionstore-image] sessionstore][sessionstore-url] A session store that works with various databases.
|
||||
|
||||
[sessionstore-url]: https://www.npmjs.com/package/sessionstore
|
||||
[sessionstore-image]: https://badgen.net/github/stars/adrai/sessionstore?label=%E2%98%85
|
||||
|
||||
[![★][tch-nedb-session-image] tch-nedb-session][tch-nedb-session-url] A file system session store based on NeDB.
|
||||
|
||||
[tch-nedb-session-url]: https://www.npmjs.com/package/tch-nedb-session
|
||||
[tch-nedb-session-image]: https://badgen.net/github/stars/tomaschyly/NeDBSession?label=%E2%98%85
|
||||
|
||||
## Examples
|
||||
|
||||
### View counter
|
||||
|
||||
A simple example using `express-session` to store page views for a user.
|
||||
|
||||
```js
|
||||
var express = require('express')
|
||||
var parseurl = require('parseurl')
|
||||
var session = require('express-session')
|
||||
|
||||
var app = express()
|
||||
|
||||
app.use(session({
|
||||
secret: 'keyboard cat',
|
||||
resave: false,
|
||||
saveUninitialized: true
|
||||
}))
|
||||
|
||||
app.use(function (req, res, next) {
|
||||
if (!req.session.views) {
|
||||
req.session.views = {}
|
||||
}
|
||||
|
||||
// get the url pathname
|
||||
var pathname = parseurl(req).pathname
|
||||
|
||||
// count the views
|
||||
req.session.views[pathname] = (req.session.views[pathname] || 0) + 1
|
||||
|
||||
next()
|
||||
})
|
||||
|
||||
app.get('/foo', function (req, res, next) {
|
||||
res.send('you viewed this page ' + req.session.views['/foo'] + ' times')
|
||||
})
|
||||
|
||||
app.get('/bar', function (req, res, next) {
|
||||
res.send('you viewed this page ' + req.session.views['/bar'] + ' times')
|
||||
})
|
||||
|
||||
app.listen(3000)
|
||||
```
|
||||
|
||||
### User login
|
||||
|
||||
A simple example using `express-session` to keep a user log in session.
|
||||
|
||||
```js
|
||||
var escapeHtml = require('escape-html')
|
||||
var express = require('express')
|
||||
var session = require('express-session')
|
||||
|
||||
var app = express()
|
||||
|
||||
app.use(session({
|
||||
secret: 'keyboard cat',
|
||||
resave: false,
|
||||
saveUninitialized: true
|
||||
}))
|
||||
|
||||
// middleware to test if authenticated
|
||||
function isAuthenticated (req, res, next) {
|
||||
if (req.session.user) next()
|
||||
else next('route')
|
||||
}
|
||||
|
||||
app.get('/', isAuthenticated, function (req, res) {
|
||||
// this is only called when there is an authentication user due to isAuthenticated
|
||||
res.send('hello, ' + escapeHtml(req.session.user) + '!' +
|
||||
' <a href="/logout">Logout</a>')
|
||||
})
|
||||
|
||||
app.get('/', function (req, res) {
|
||||
res.send('<form action="/login" method="post">' +
|
||||
'Username: <input name="user"><br>' +
|
||||
'Password: <input name="pass" type="password"><br>' +
|
||||
'<input type="submit" text="Login"></form>')
|
||||
})
|
||||
|
||||
app.post('/login', express.urlencoded({ extended: false }), function (req, res) {
|
||||
// login logic to validate req.body.user and req.body.pass
|
||||
// would be implemented here. for this example any combo works
|
||||
|
||||
// regenerate the session, which is good practice to help
|
||||
// guard against forms of session fixation
|
||||
req.session.regenerate(function (err) {
|
||||
if (err) next(err)
|
||||
|
||||
// store user information in session, typically a user id
|
||||
req.session.user = req.body.user
|
||||
|
||||
// save the session before redirection to ensure page
|
||||
// load does not happen before session is saved
|
||||
req.session.save(function (err) {
|
||||
if (err) return next(err)
|
||||
res.redirect('/')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
app.get('/logout', function (req, res, next) {
|
||||
// logout logic
|
||||
|
||||
// clear the user from the session object and save.
|
||||
// this will ensure that re-using the old session id
|
||||
// does not have a logged in user
|
||||
req.session.user = null
|
||||
req.session.save(function (err) {
|
||||
if (err) next(err)
|
||||
|
||||
// regenerate the session, which is good practice to help
|
||||
// guard against forms of session fixation
|
||||
req.session.regenerate(function (err) {
|
||||
if (err) next(err)
|
||||
res.redirect('/')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
app.listen(3000)
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
This module uses the [debug](https://www.npmjs.com/package/debug) module
|
||||
internally to log information about session operations.
|
||||
|
||||
To see all the internal logs, set the `DEBUG` environment variable to
|
||||
`express-session` when launching your app (`npm start`, in this example):
|
||||
|
||||
```sh
|
||||
$ DEBUG=express-session npm start
|
||||
```
|
||||
|
||||
On Windows, use the corresponding command;
|
||||
|
||||
```sh
|
||||
> set DEBUG=express-session & npm start
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
[rfc-6265bis-03-4.1.2.7]: https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7
|
||||
[ci-image]: https://badgen.net/github/checks/expressjs/session/master?label=ci
|
||||
[ci-url]: https://github.com/expressjs/session/actions?query=workflow%3Aci
|
||||
[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/session/master
|
||||
[coveralls-url]: https://coveralls.io/r/expressjs/session?branch=master
|
||||
[node-url]: https://nodejs.org/en/download
|
||||
[npm-downloads-image]: https://badgen.net/npm/dm/express-session
|
||||
[npm-url]: https://npmjs.org/package/express-session
|
||||
[npm-version-image]: https://badgen.net/npm/v/express-session
|
685
node_modules/express-session/index.js
generated
vendored
Normal file
685
node_modules/express-session/index.js
generated
vendored
Normal file
@@ -0,0 +1,685 @@
|
||||
/*!
|
||||
* express-session
|
||||
* Copyright(c) 2010 Sencha Inc.
|
||||
* Copyright(c) 2011 TJ Holowaychuk
|
||||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var Buffer = require('safe-buffer').Buffer
|
||||
var cookie = require('cookie');
|
||||
var crypto = require('crypto')
|
||||
var debug = require('debug')('express-session');
|
||||
var deprecate = require('depd')('express-session');
|
||||
var onHeaders = require('on-headers')
|
||||
var parseUrl = require('parseurl');
|
||||
var signature = require('cookie-signature')
|
||||
var uid = require('uid-safe').sync
|
||||
|
||||
var Cookie = require('./session/cookie')
|
||||
var MemoryStore = require('./session/memory')
|
||||
var Session = require('./session/session')
|
||||
var Store = require('./session/store')
|
||||
|
||||
// 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.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var warning = 'Warning: connect.session() MemoryStore is not\n'
|
||||
+ 'designed for a production environment, as it will leak\n'
|
||||
+ 'memory, and will not scale past a single process.';
|
||||
|
||||
/**
|
||||
* Node.js 0.8+ async implementation.
|
||||
* @private
|
||||
*/
|
||||
|
||||
/* istanbul ignore next */
|
||||
var defer = typeof setImmediate === 'function'
|
||||
? setImmediate
|
||||
: function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) }
|
||||
|
||||
/**
|
||||
* Setup session store with the given `options`.
|
||||
*
|
||||
* @param {Object} [options]
|
||||
* @param {Object} [options.cookie] Options for cookie
|
||||
* @param {Function} [options.genid]
|
||||
* @param {String} [options.name=connect.sid] Session ID cookie name
|
||||
* @param {Boolean} [options.proxy]
|
||||
* @param {Boolean} [options.resave] Resave unmodified sessions back to the store
|
||||
* @param {Boolean} [options.rolling] Enable/disable rolling session expiration
|
||||
* @param {Boolean} [options.saveUninitialized] Save uninitialized sessions to the store
|
||||
* @param {String|Array} [options.secret] Secret for signing session ID
|
||||
* @param {Object} [options.store=MemoryStore] Session store
|
||||
* @param {String} [options.unset]
|
||||
* @return {Function} middleware
|
||||
* @public
|
||||
*/
|
||||
|
||||
function session(options) {
|
||||
var opts = options || {}
|
||||
|
||||
// get the cookie options
|
||||
var cookieOptions = opts.cookie || {}
|
||||
|
||||
// get the session id generate function
|
||||
var generateId = opts.genid || generateSessionId
|
||||
|
||||
// get the session cookie name
|
||||
var name = opts.name || opts.key || 'connect.sid'
|
||||
|
||||
// get the session store
|
||||
var store = opts.store || new MemoryStore()
|
||||
|
||||
// get the trust proxy setting
|
||||
var trustProxy = opts.proxy
|
||||
|
||||
// get the resave session option
|
||||
var resaveSession = opts.resave;
|
||||
|
||||
// get the rolling session option
|
||||
var rollingSessions = Boolean(opts.rolling)
|
||||
|
||||
// get the save uninitialized session option
|
||||
var saveUninitializedSession = opts.saveUninitialized
|
||||
|
||||
// get the cookie signing secret
|
||||
var secret = opts.secret
|
||||
|
||||
if (typeof generateId !== 'function') {
|
||||
throw new TypeError('genid option must be a function');
|
||||
}
|
||||
|
||||
if (resaveSession === undefined) {
|
||||
deprecate('undefined resave option; provide resave option');
|
||||
resaveSession = true;
|
||||
}
|
||||
|
||||
if (saveUninitializedSession === undefined) {
|
||||
deprecate('undefined saveUninitialized option; provide saveUninitialized option');
|
||||
saveUninitializedSession = true;
|
||||
}
|
||||
|
||||
if (opts.unset && opts.unset !== 'destroy' && opts.unset !== 'keep') {
|
||||
throw new TypeError('unset option must be "destroy" or "keep"');
|
||||
}
|
||||
|
||||
// TODO: switch to "destroy" on next major
|
||||
var unsetDestroy = opts.unset === 'destroy'
|
||||
|
||||
if (Array.isArray(secret) && secret.length === 0) {
|
||||
throw new TypeError('secret option array must contain one or more strings');
|
||||
}
|
||||
|
||||
if (secret && !Array.isArray(secret)) {
|
||||
secret = [secret];
|
||||
}
|
||||
|
||||
if (!secret) {
|
||||
deprecate('req.secret; provide secret option');
|
||||
}
|
||||
|
||||
// notify user that this store is not
|
||||
// meant for a production environment
|
||||
/* istanbul ignore next: not tested */
|
||||
if (env === 'production' && store instanceof MemoryStore) {
|
||||
console.warn(warning);
|
||||
}
|
||||
|
||||
// generates the new session
|
||||
store.generate = function(req){
|
||||
req.sessionID = generateId(req);
|
||||
req.session = new Session(req);
|
||||
req.session.cookie = new Cookie(cookieOptions);
|
||||
|
||||
if (cookieOptions.secure === 'auto') {
|
||||
req.session.cookie.secure = issecure(req, trustProxy);
|
||||
}
|
||||
};
|
||||
|
||||
var storeImplementsTouch = typeof store.touch === 'function';
|
||||
|
||||
// register event listeners for the store to track readiness
|
||||
var storeReady = true
|
||||
store.on('disconnect', function ondisconnect() {
|
||||
storeReady = false
|
||||
})
|
||||
store.on('connect', function onconnect() {
|
||||
storeReady = true
|
||||
})
|
||||
|
||||
return function session(req, res, next) {
|
||||
// self-awareness
|
||||
if (req.session) {
|
||||
next()
|
||||
return
|
||||
}
|
||||
|
||||
// Handle connection as if there is no session if
|
||||
// the store has temporarily disconnected etc
|
||||
if (!storeReady) {
|
||||
debug('store is disconnected')
|
||||
next()
|
||||
return
|
||||
}
|
||||
|
||||
// pathname mismatch
|
||||
var originalPath = parseUrl.original(req).pathname || '/'
|
||||
if (originalPath.indexOf(cookieOptions.path || '/') !== 0) return next();
|
||||
|
||||
// ensure a secret is available or bail
|
||||
if (!secret && !req.secret) {
|
||||
next(new Error('secret option required for sessions'));
|
||||
return;
|
||||
}
|
||||
|
||||
// backwards compatibility for signed cookies
|
||||
// req.secret is passed from the cookie parser middleware
|
||||
var secrets = secret || [req.secret];
|
||||
|
||||
var originalHash;
|
||||
var originalId;
|
||||
var savedHash;
|
||||
var touched = false
|
||||
|
||||
// expose store
|
||||
req.sessionStore = store;
|
||||
|
||||
// get the session ID from the cookie
|
||||
var cookieId = req.sessionID = getcookie(req, name, secrets);
|
||||
|
||||
// set-cookie
|
||||
onHeaders(res, function(){
|
||||
if (!req.session) {
|
||||
debug('no session');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!shouldSetCookie(req)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// only send secure cookies via https
|
||||
if (req.session.cookie.secure && !issecure(req, trustProxy)) {
|
||||
debug('not secured');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!touched) {
|
||||
// touch session
|
||||
req.session.touch()
|
||||
touched = true
|
||||
}
|
||||
|
||||
// set cookie
|
||||
setcookie(res, name, req.sessionID, secrets[0], req.session.cookie.data);
|
||||
});
|
||||
|
||||
// proxy end() to commit the session
|
||||
var _end = res.end;
|
||||
var _write = res.write;
|
||||
var ended = false;
|
||||
res.end = function end(chunk, encoding) {
|
||||
if (ended) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ended = true;
|
||||
|
||||
var ret;
|
||||
var sync = true;
|
||||
|
||||
function writeend() {
|
||||
if (sync) {
|
||||
ret = _end.call(res, chunk, encoding);
|
||||
sync = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_end.call(res);
|
||||
}
|
||||
|
||||
function writetop() {
|
||||
if (!sync) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!res._header) {
|
||||
res._implicitHeader()
|
||||
}
|
||||
|
||||
if (chunk == null) {
|
||||
ret = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
var contentLength = Number(res.getHeader('Content-Length'));
|
||||
|
||||
if (!isNaN(contentLength) && contentLength > 0) {
|
||||
// measure chunk
|
||||
chunk = !Buffer.isBuffer(chunk)
|
||||
? Buffer.from(chunk, encoding)
|
||||
: chunk;
|
||||
encoding = undefined;
|
||||
|
||||
if (chunk.length !== 0) {
|
||||
debug('split response');
|
||||
ret = _write.call(res, chunk.slice(0, chunk.length - 1));
|
||||
chunk = chunk.slice(chunk.length - 1, chunk.length);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = _write.call(res, chunk, encoding);
|
||||
sync = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (shouldDestroy(req)) {
|
||||
// destroy session
|
||||
debug('destroying');
|
||||
store.destroy(req.sessionID, function ondestroy(err) {
|
||||
if (err) {
|
||||
defer(next, err);
|
||||
}
|
||||
|
||||
debug('destroyed');
|
||||
writeend();
|
||||
});
|
||||
|
||||
return writetop();
|
||||
}
|
||||
|
||||
// no session to save
|
||||
if (!req.session) {
|
||||
debug('no session');
|
||||
return _end.call(res, chunk, encoding);
|
||||
}
|
||||
|
||||
if (!touched) {
|
||||
// touch session
|
||||
req.session.touch()
|
||||
touched = true
|
||||
}
|
||||
|
||||
if (shouldSave(req)) {
|
||||
req.session.save(function onsave(err) {
|
||||
if (err) {
|
||||
defer(next, err);
|
||||
}
|
||||
|
||||
writeend();
|
||||
});
|
||||
|
||||
return writetop();
|
||||
} else if (storeImplementsTouch && shouldTouch(req)) {
|
||||
// store implements touch method
|
||||
debug('touching');
|
||||
store.touch(req.sessionID, req.session, function ontouch(err) {
|
||||
if (err) {
|
||||
defer(next, err);
|
||||
}
|
||||
|
||||
debug('touched');
|
||||
writeend();
|
||||
});
|
||||
|
||||
return writetop();
|
||||
}
|
||||
|
||||
return _end.call(res, chunk, encoding);
|
||||
};
|
||||
|
||||
// generate the session
|
||||
function generate() {
|
||||
store.generate(req);
|
||||
originalId = req.sessionID;
|
||||
originalHash = hash(req.session);
|
||||
wrapmethods(req.session);
|
||||
}
|
||||
|
||||
// inflate the session
|
||||
function inflate (req, sess) {
|
||||
store.createSession(req, sess)
|
||||
originalId = req.sessionID
|
||||
originalHash = hash(sess)
|
||||
|
||||
if (!resaveSession) {
|
||||
savedHash = originalHash
|
||||
}
|
||||
|
||||
wrapmethods(req.session)
|
||||
}
|
||||
|
||||
function rewrapmethods (sess, callback) {
|
||||
return function () {
|
||||
if (req.session !== sess) {
|
||||
wrapmethods(req.session)
|
||||
}
|
||||
|
||||
callback.apply(this, arguments)
|
||||
}
|
||||
}
|
||||
|
||||
// wrap session methods
|
||||
function wrapmethods(sess) {
|
||||
var _reload = sess.reload
|
||||
var _save = sess.save;
|
||||
|
||||
function reload(callback) {
|
||||
debug('reloading %s', this.id)
|
||||
_reload.call(this, rewrapmethods(this, callback))
|
||||
}
|
||||
|
||||
function save() {
|
||||
debug('saving %s', this.id);
|
||||
savedHash = hash(this);
|
||||
_save.apply(this, arguments);
|
||||
}
|
||||
|
||||
Object.defineProperty(sess, 'reload', {
|
||||
configurable: true,
|
||||
enumerable: false,
|
||||
value: reload,
|
||||
writable: true
|
||||
})
|
||||
|
||||
Object.defineProperty(sess, 'save', {
|
||||
configurable: true,
|
||||
enumerable: false,
|
||||
value: save,
|
||||
writable: true
|
||||
});
|
||||
}
|
||||
|
||||
// check if session has been modified
|
||||
function isModified(sess) {
|
||||
return originalId !== sess.id || originalHash !== hash(sess);
|
||||
}
|
||||
|
||||
// check if session has been saved
|
||||
function isSaved(sess) {
|
||||
return originalId === sess.id && savedHash === hash(sess);
|
||||
}
|
||||
|
||||
// determine if session should be destroyed
|
||||
function shouldDestroy(req) {
|
||||
return req.sessionID && unsetDestroy && req.session == null;
|
||||
}
|
||||
|
||||
// determine if session should be saved to store
|
||||
function shouldSave(req) {
|
||||
// cannot set cookie without a session ID
|
||||
if (typeof req.sessionID !== 'string') {
|
||||
debug('session ignored because of bogus req.sessionID %o', req.sessionID);
|
||||
return false;
|
||||
}
|
||||
|
||||
return !saveUninitializedSession && !savedHash && cookieId !== req.sessionID
|
||||
? isModified(req.session)
|
||||
: !isSaved(req.session)
|
||||
}
|
||||
|
||||
// determine if session should be touched
|
||||
function shouldTouch(req) {
|
||||
// cannot set cookie without a session ID
|
||||
if (typeof req.sessionID !== 'string') {
|
||||
debug('session ignored because of bogus req.sessionID %o', req.sessionID);
|
||||
return false;
|
||||
}
|
||||
|
||||
return cookieId === req.sessionID && !shouldSave(req);
|
||||
}
|
||||
|
||||
// determine if cookie should be set on response
|
||||
function shouldSetCookie(req) {
|
||||
// cannot set cookie without a session ID
|
||||
if (typeof req.sessionID !== 'string') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return cookieId !== req.sessionID
|
||||
? saveUninitializedSession || isModified(req.session)
|
||||
: rollingSessions || req.session.cookie.expires != null && isModified(req.session);
|
||||
}
|
||||
|
||||
// generate a session if the browser doesn't send a sessionID
|
||||
if (!req.sessionID) {
|
||||
debug('no SID sent, generating session');
|
||||
generate();
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
// generate the session object
|
||||
debug('fetching %s', req.sessionID);
|
||||
store.get(req.sessionID, function(err, sess){
|
||||
// error handling
|
||||
if (err && err.code !== 'ENOENT') {
|
||||
debug('error %j', err);
|
||||
next(err)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
if (err || !sess) {
|
||||
debug('no session found')
|
||||
generate()
|
||||
} else {
|
||||
debug('session found')
|
||||
inflate(req, sess)
|
||||
}
|
||||
} catch (e) {
|
||||
next(e)
|
||||
return
|
||||
}
|
||||
|
||||
next()
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a session ID for a new session.
|
||||
*
|
||||
* @return {String}
|
||||
* @private
|
||||
*/
|
||||
|
||||
function generateSessionId(sess) {
|
||||
return uid(24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the session ID cookie from request.
|
||||
*
|
||||
* @return {string}
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getcookie(req, name, secrets) {
|
||||
var header = req.headers.cookie;
|
||||
var raw;
|
||||
var val;
|
||||
|
||||
// read from cookie header
|
||||
if (header) {
|
||||
var cookies = cookie.parse(header);
|
||||
|
||||
raw = cookies[name];
|
||||
|
||||
if (raw) {
|
||||
if (raw.substr(0, 2) === 's:') {
|
||||
val = unsigncookie(raw.slice(2), secrets);
|
||||
|
||||
if (val === false) {
|
||||
debug('cookie signature invalid');
|
||||
val = undefined;
|
||||
}
|
||||
} else {
|
||||
debug('cookie unsigned')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// back-compat read from cookieParser() signedCookies data
|
||||
if (!val && req.signedCookies) {
|
||||
val = req.signedCookies[name];
|
||||
|
||||
if (val) {
|
||||
deprecate('cookie should be available in req.headers.cookie');
|
||||
}
|
||||
}
|
||||
|
||||
// back-compat read from cookieParser() cookies data
|
||||
if (!val && req.cookies) {
|
||||
raw = req.cookies[name];
|
||||
|
||||
if (raw) {
|
||||
if (raw.substr(0, 2) === 's:') {
|
||||
val = unsigncookie(raw.slice(2), secrets);
|
||||
|
||||
if (val) {
|
||||
deprecate('cookie should be available in req.headers.cookie');
|
||||
}
|
||||
|
||||
if (val === false) {
|
||||
debug('cookie signature invalid');
|
||||
val = undefined;
|
||||
}
|
||||
} else {
|
||||
debug('cookie unsigned')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash the given `sess` object omitting changes to `.cookie`.
|
||||
*
|
||||
* @param {Object} sess
|
||||
* @return {String}
|
||||
* @private
|
||||
*/
|
||||
|
||||
function hash(sess) {
|
||||
// serialize
|
||||
var str = JSON.stringify(sess, function (key, val) {
|
||||
// ignore sess.cookie property
|
||||
if (this === sess && key === 'cookie') {
|
||||
return
|
||||
}
|
||||
|
||||
return val
|
||||
})
|
||||
|
||||
// hash
|
||||
return crypto
|
||||
.createHash('sha1')
|
||||
.update(str, 'utf8')
|
||||
.digest('hex')
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if request is secure.
|
||||
*
|
||||
* @param {Object} req
|
||||
* @param {Boolean} [trustProxy]
|
||||
* @return {Boolean}
|
||||
* @private
|
||||
*/
|
||||
|
||||
function issecure(req, trustProxy) {
|
||||
// socket is https server
|
||||
if (req.connection && req.connection.encrypted) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// do not trust proxy
|
||||
if (trustProxy === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// no explicit trust; try req.secure from express
|
||||
if (trustProxy !== true) {
|
||||
return req.secure === true
|
||||
}
|
||||
|
||||
// read the proto from x-forwarded-proto header
|
||||
var header = req.headers['x-forwarded-proto'] || '';
|
||||
var index = header.indexOf(',');
|
||||
var proto = index !== -1
|
||||
? header.substr(0, index).toLowerCase().trim()
|
||||
: header.toLowerCase().trim()
|
||||
|
||||
return proto === 'https';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cookie on response.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
function setcookie(res, name, val, secret, options) {
|
||||
var signed = 's:' + signature.sign(val, secret);
|
||||
var data = cookie.serialize(name, signed, options);
|
||||
|
||||
debug('set-cookie %s', data);
|
||||
|
||||
var prev = res.getHeader('Set-Cookie') || []
|
||||
var header = Array.isArray(prev) ? prev.concat(data) : [prev, data];
|
||||
|
||||
res.setHeader('Set-Cookie', header)
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify and decode the given `val` with `secrets`.
|
||||
*
|
||||
* @param {String} val
|
||||
* @param {Array} secrets
|
||||
* @returns {String|Boolean}
|
||||
* @private
|
||||
*/
|
||||
function unsigncookie(val, secrets) {
|
||||
for (var i = 0; i < secrets.length; i++) {
|
||||
var result = signature.unsign(val, secrets[i]);
|
||||
|
||||
if (result !== false) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
134
node_modules/express-session/node_modules/cookie/HISTORY.md
generated
vendored
Normal file
134
node_modules/express-session/node_modules/cookie/HISTORY.md
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
0.4.2 / 2022-02-02
|
||||
==================
|
||||
|
||||
* pref: read value only when assigning in parse
|
||||
* pref: remove unnecessary regexp in parse
|
||||
|
||||
0.4.1 / 2020-04-21
|
||||
==================
|
||||
|
||||
* Fix `maxAge` option to reject invalid values
|
||||
|
||||
0.4.0 / 2019-05-15
|
||||
==================
|
||||
|
||||
* Add `SameSite=None` support
|
||||
|
||||
0.3.1 / 2016-05-26
|
||||
==================
|
||||
|
||||
* Fix `sameSite: true` to work with draft-7 clients
|
||||
- `true` now sends `SameSite=Strict` instead of `SameSite`
|
||||
|
||||
0.3.0 / 2016-05-26
|
||||
==================
|
||||
|
||||
* Add `sameSite` option
|
||||
- Replaces `firstPartyOnly` option, never implemented by browsers
|
||||
* Improve error message when `encode` is not a function
|
||||
* Improve error message when `expires` is not a `Date`
|
||||
|
||||
0.2.4 / 2016-05-20
|
||||
==================
|
||||
|
||||
* perf: enable strict mode
|
||||
* perf: use for loop in parse
|
||||
* perf: use string concatination for serialization
|
||||
|
||||
0.2.3 / 2015-10-25
|
||||
==================
|
||||
|
||||
* Fix cookie `Max-Age` to never be a floating point number
|
||||
|
||||
0.2.2 / 2015-09-17
|
||||
==================
|
||||
|
||||
* Fix regression when setting empty cookie value
|
||||
- Ease the new restriction, which is just basic header-level validation
|
||||
* Fix typo in invalid value errors
|
||||
|
||||
0.2.1 / 2015-09-17
|
||||
==================
|
||||
|
||||
* Throw on invalid values provided to `serialize`
|
||||
- Ensures the resulting string is a valid HTTP header value
|
||||
|
||||
0.2.0 / 2015-08-13
|
||||
==================
|
||||
|
||||
* Add `firstPartyOnly` option
|
||||
* Throw better error for invalid argument to parse
|
||||
* perf: hoist regular expression
|
||||
|
||||
0.1.5 / 2015-09-17
|
||||
==================
|
||||
|
||||
* Fix regression when setting empty cookie value
|
||||
- Ease the new restriction, which is just basic header-level validation
|
||||
* Fix typo in invalid value errors
|
||||
|
||||
0.1.4 / 2015-09-17
|
||||
==================
|
||||
|
||||
* Throw better error for invalid argument to parse
|
||||
* Throw on invalid values provided to `serialize`
|
||||
- Ensures the resulting string is a valid HTTP header value
|
||||
|
||||
0.1.3 / 2015-05-19
|
||||
==================
|
||||
|
||||
* Reduce the scope of try-catch deopt
|
||||
* Remove argument reassignments
|
||||
|
||||
0.1.2 / 2014-04-16
|
||||
==================
|
||||
|
||||
* Remove unnecessary files from npm package
|
||||
|
||||
0.1.1 / 2014-02-23
|
||||
==================
|
||||
|
||||
* Fix bad parse when cookie value contained a comma
|
||||
* Fix support for `maxAge` of `0`
|
||||
|
||||
0.1.0 / 2013-05-01
|
||||
==================
|
||||
|
||||
* Add `decode` option
|
||||
* Add `encode` option
|
||||
|
||||
0.0.6 / 2013-04-08
|
||||
==================
|
||||
|
||||
* Ignore cookie parts missing `=`
|
||||
|
||||
0.0.5 / 2012-10-29
|
||||
==================
|
||||
|
||||
* Return raw cookie value if value unescape errors
|
||||
|
||||
0.0.4 / 2012-06-21
|
||||
==================
|
||||
|
||||
* Use encode/decodeURIComponent for cookie encoding/decoding
|
||||
- Improve server/client interoperability
|
||||
|
||||
0.0.3 / 2012-06-06
|
||||
==================
|
||||
|
||||
* Only escape special characters per the cookie RFC
|
||||
|
||||
0.0.2 / 2012-06-01
|
||||
==================
|
||||
|
||||
* Fix `maxAge` option to not throw error
|
||||
|
||||
0.0.1 / 2012-05-28
|
||||
==================
|
||||
|
||||
* Add more tests
|
||||
|
||||
0.0.0 / 2012-05-28
|
||||
==================
|
||||
|
||||
* Initial release
|
24
node_modules/express-session/node_modules/cookie/LICENSE
generated
vendored
Normal file
24
node_modules/express-session/node_modules/cookie/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2012-2014 Roman Shtylman <shtylman@gmail.com>
|
||||
Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>
|
||||
|
||||
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.
|
||||
|
286
node_modules/express-session/node_modules/cookie/README.md
generated
vendored
Normal file
286
node_modules/express-session/node_modules/cookie/README.md
generated
vendored
Normal file
@@ -0,0 +1,286 @@
|
||||
# cookie
|
||||
|
||||
[![NPM Version][npm-version-image]][npm-url]
|
||||
[![NPM Downloads][npm-downloads-image]][npm-url]
|
||||
[![Node.js Version][node-version-image]][node-version-url]
|
||||
[![Build Status][github-actions-ci-image]][github-actions-ci-url]
|
||||
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||
|
||||
Basic HTTP cookie parser and serializer for HTTP servers.
|
||||
|
||||
## 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 cookie
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
```js
|
||||
var cookie = require('cookie');
|
||||
```
|
||||
|
||||
### cookie.parse(str, options)
|
||||
|
||||
Parse an HTTP `Cookie` header string and returning an object of all cookie name-value pairs.
|
||||
The `str` argument is the string representing a `Cookie` header value and `options` is an
|
||||
optional object containing additional parsing options.
|
||||
|
||||
```js
|
||||
var cookies = cookie.parse('foo=bar; equation=E%3Dmc%5E2');
|
||||
// { foo: 'bar', equation: 'E=mc^2' }
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
`cookie.parse` accepts these properties in the options object.
|
||||
|
||||
##### decode
|
||||
|
||||
Specifies a function that will be used to decode a cookie's value. Since the value of a cookie
|
||||
has a limited character set (and must be a simple string), this function can be used to decode
|
||||
a previously-encoded cookie value into a JavaScript string or other object.
|
||||
|
||||
The default function is the global `decodeURIComponent`, which will decode any URL-encoded
|
||||
sequences into their byte representations.
|
||||
|
||||
**note** if an error is thrown from this function, the original, non-decoded cookie value will
|
||||
be returned as the cookie's value.
|
||||
|
||||
### cookie.serialize(name, value, options)
|
||||
|
||||
Serialize a cookie name-value pair into a `Set-Cookie` header string. The `name` argument is the
|
||||
name for the cookie, the `value` argument is the value to set the cookie to, and the `options`
|
||||
argument is an optional object containing additional serialization options.
|
||||
|
||||
```js
|
||||
var setCookie = cookie.serialize('foo', 'bar');
|
||||
// foo=bar
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
`cookie.serialize` accepts these properties in the options object.
|
||||
|
||||
##### domain
|
||||
|
||||
Specifies the value for the [`Domain` `Set-Cookie` attribute][rfc-6265-5.2.3]. By default, no
|
||||
domain is set, and most clients will consider the cookie to apply to only the current domain.
|
||||
|
||||
##### encode
|
||||
|
||||
Specifies a function that will be used to encode a cookie's value. Since value of a cookie
|
||||
has a limited character set (and must be a simple string), this function can be used to encode
|
||||
a value into a string suited for a cookie's value.
|
||||
|
||||
The default function is the global `encodeURIComponent`, which will encode a JavaScript string
|
||||
into UTF-8 byte sequences and then URL-encode any that fall outside of the cookie range.
|
||||
|
||||
##### expires
|
||||
|
||||
Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute][rfc-6265-5.2.1].
|
||||
By default, no expiration is set, and most clients will consider this a "non-persistent cookie" and
|
||||
will delete it on a condition like exiting a web browser application.
|
||||
|
||||
**note** the [cookie storage model specification][rfc-6265-5.3] states that if both `expires` and
|
||||
`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
|
||||
so if both are set, they should point to the same date and time.
|
||||
|
||||
##### httpOnly
|
||||
|
||||
Specifies the `boolean` value for the [`HttpOnly` `Set-Cookie` attribute][rfc-6265-5.2.6]. When truthy,
|
||||
the `HttpOnly` attribute is set, otherwise it is not. By default, the `HttpOnly` attribute is not set.
|
||||
|
||||
**note** be careful when setting this to `true`, as compliant clients will not allow client-side
|
||||
JavaScript to see the cookie in `document.cookie`.
|
||||
|
||||
##### maxAge
|
||||
|
||||
Specifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute][rfc-6265-5.2.2].
|
||||
The given number will be converted to an integer by rounding down. By default, no maximum age is set.
|
||||
|
||||
**note** the [cookie storage model specification][rfc-6265-5.3] states that if both `expires` and
|
||||
`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
|
||||
so if both are set, they should point to the same date and time.
|
||||
|
||||
##### path
|
||||
|
||||
Specifies the value for the [`Path` `Set-Cookie` attribute][rfc-6265-5.2.4]. By default, the path
|
||||
is considered the ["default path"][rfc-6265-5.1.4].
|
||||
|
||||
##### sameSite
|
||||
|
||||
Specifies the `boolean` or `string` to be the value for the [`SameSite` `Set-Cookie` attribute][rfc-6265bis-03-4.1.2.7].
|
||||
|
||||
- `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
|
||||
- `false` will not set the `SameSite` attribute.
|
||||
- `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement.
|
||||
- `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.
|
||||
- `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
|
||||
|
||||
More information about the different enforcement levels can be found in
|
||||
[the specification][rfc-6265bis-03-4.1.2.7].
|
||||
|
||||
**note** This is an attribute that has not yet been fully standardized, and may change in the future.
|
||||
This also means many clients may ignore this attribute until they understand it.
|
||||
|
||||
##### secure
|
||||
|
||||
Specifies the `boolean` value for the [`Secure` `Set-Cookie` attribute][rfc-6265-5.2.5]. When truthy,
|
||||
the `Secure` attribute is set, otherwise it is not. By default, the `Secure` attribute is not set.
|
||||
|
||||
**note** be careful when setting this to `true`, as compliant clients will not send the cookie back to
|
||||
the server in the future if the browser does not have an HTTPS connection.
|
||||
|
||||
## Example
|
||||
|
||||
The following example uses this module in conjunction with the Node.js core HTTP server
|
||||
to prompt a user for their name and display it back on future visits.
|
||||
|
||||
```js
|
||||
var cookie = require('cookie');
|
||||
var escapeHtml = require('escape-html');
|
||||
var http = require('http');
|
||||
var url = require('url');
|
||||
|
||||
function onRequest(req, res) {
|
||||
// Parse the query string
|
||||
var query = url.parse(req.url, true, true).query;
|
||||
|
||||
if (query && query.name) {
|
||||
// Set a new cookie with the name
|
||||
res.setHeader('Set-Cookie', cookie.serialize('name', String(query.name), {
|
||||
httpOnly: true,
|
||||
maxAge: 60 * 60 * 24 * 7 // 1 week
|
||||
}));
|
||||
|
||||
// Redirect back after setting cookie
|
||||
res.statusCode = 302;
|
||||
res.setHeader('Location', req.headers.referer || '/');
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the cookies on the request
|
||||
var cookies = cookie.parse(req.headers.cookie || '');
|
||||
|
||||
// Get the visitor name set in the cookie
|
||||
var name = cookies.name;
|
||||
|
||||
res.setHeader('Content-Type', 'text/html; charset=UTF-8');
|
||||
|
||||
if (name) {
|
||||
res.write('<p>Welcome back, <b>' + escapeHtml(name) + '</b>!</p>');
|
||||
} else {
|
||||
res.write('<p>Hello, new visitor!</p>');
|
||||
}
|
||||
|
||||
res.write('<form method="GET">');
|
||||
res.write('<input placeholder="enter your name" name="name"> <input type="submit" value="Set Name">');
|
||||
res.end('</form>');
|
||||
}
|
||||
|
||||
http.createServer(onRequest).listen(3000);
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
```sh
|
||||
$ npm test
|
||||
```
|
||||
|
||||
## Benchmark
|
||||
|
||||
```
|
||||
$ npm run bench
|
||||
|
||||
> cookie@0.4.1 bench
|
||||
> node benchmark/index.js
|
||||
|
||||
node@16.13.1
|
||||
v8@9.4.146.24-node.14
|
||||
uv@1.42.0
|
||||
zlib@1.2.11
|
||||
brotli@1.0.9
|
||||
ares@1.18.1
|
||||
modules@93
|
||||
nghttp2@1.45.1
|
||||
napi@8
|
||||
llhttp@6.0.4
|
||||
openssl@1.1.1l+quic
|
||||
cldr@39.0
|
||||
icu@69.1
|
||||
tz@2021a
|
||||
unicode@13.0
|
||||
ngtcp2@0.1.0-DEV
|
||||
nghttp3@0.1.0-DEV
|
||||
|
||||
> node benchmark/parse-top.js
|
||||
|
||||
cookie.parse - top sites
|
||||
|
||||
15 tests completed.
|
||||
|
||||
parse accounts.google.com x 504,358 ops/sec ±6.55% (171 runs sampled)
|
||||
parse apple.com x 1,369,991 ops/sec ±0.84% (189 runs sampled)
|
||||
parse cloudflare.com x 360,669 ops/sec ±3.75% (182 runs sampled)
|
||||
parse docs.google.com x 521,496 ops/sec ±4.90% (180 runs sampled)
|
||||
parse drive.google.com x 553,514 ops/sec ±0.59% (189 runs sampled)
|
||||
parse en.wikipedia.org x 286,052 ops/sec ±0.62% (188 runs sampled)
|
||||
parse linkedin.com x 178,817 ops/sec ±0.61% (192 runs sampled)
|
||||
parse maps.google.com x 284,585 ops/sec ±0.68% (188 runs sampled)
|
||||
parse microsoft.com x 161,230 ops/sec ±0.56% (192 runs sampled)
|
||||
parse play.google.com x 352,144 ops/sec ±1.01% (181 runs sampled)
|
||||
parse plus.google.com x 275,204 ops/sec ±7.78% (156 runs sampled)
|
||||
parse support.google.com x 339,493 ops/sec ±1.02% (191 runs sampled)
|
||||
parse www.google.com x 286,110 ops/sec ±0.90% (191 runs sampled)
|
||||
parse youtu.be x 548,557 ops/sec ±0.60% (184 runs sampled)
|
||||
parse youtube.com x 545,293 ops/sec ±0.65% (191 runs sampled)
|
||||
|
||||
> node benchmark/parse.js
|
||||
|
||||
cookie.parse - generic
|
||||
|
||||
6 tests completed.
|
||||
|
||||
simple x 1,266,646 ops/sec ±0.65% (191 runs sampled)
|
||||
decode x 838,413 ops/sec ±0.60% (191 runs sampled)
|
||||
unquote x 877,820 ops/sec ±0.72% (189 runs sampled)
|
||||
duplicates x 516,680 ops/sec ±0.61% (191 runs sampled)
|
||||
10 cookies x 156,874 ops/sec ±0.52% (189 runs sampled)
|
||||
100 cookies x 14,663 ops/sec ±0.53% (191 runs sampled)
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [RFC 6265: HTTP State Management Mechanism][rfc-6265]
|
||||
- [Same-site Cookies][rfc-6265bis-03-4.1.2.7]
|
||||
|
||||
[rfc-6265bis-03-4.1.2.7]: https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7
|
||||
[rfc-6265]: https://tools.ietf.org/html/rfc6265
|
||||
[rfc-6265-5.1.4]: https://tools.ietf.org/html/rfc6265#section-5.1.4
|
||||
[rfc-6265-5.2.1]: https://tools.ietf.org/html/rfc6265#section-5.2.1
|
||||
[rfc-6265-5.2.2]: https://tools.ietf.org/html/rfc6265#section-5.2.2
|
||||
[rfc-6265-5.2.3]: https://tools.ietf.org/html/rfc6265#section-5.2.3
|
||||
[rfc-6265-5.2.4]: https://tools.ietf.org/html/rfc6265#section-5.2.4
|
||||
[rfc-6265-5.2.5]: https://tools.ietf.org/html/rfc6265#section-5.2.5
|
||||
[rfc-6265-5.2.6]: https://tools.ietf.org/html/rfc6265#section-5.2.6
|
||||
[rfc-6265-5.3]: https://tools.ietf.org/html/rfc6265#section-5.3
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/cookie/master
|
||||
[coveralls-url]: https://coveralls.io/r/jshttp/cookie?branch=master
|
||||
[github-actions-ci-image]: https://img.shields.io/github/workflow/status/jshttp/cookie/ci/master?label=ci
|
||||
[github-actions-ci-url]: https://github.com/jshttp/cookie/actions/workflows/ci.yml
|
||||
[node-version-image]: https://badgen.net/npm/node/cookie
|
||||
[node-version-url]: https://nodejs.org/en/download
|
||||
[npm-downloads-image]: https://badgen.net/npm/dm/cookie
|
||||
[npm-url]: https://npmjs.org/package/cookie
|
||||
[npm-version-image]: https://badgen.net/npm/v/cookie
|
202
node_modules/express-session/node_modules/cookie/index.js
generated
vendored
Normal file
202
node_modules/express-session/node_modules/cookie/index.js
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
/*!
|
||||
* cookie
|
||||
* Copyright(c) 2012-2014 Roman Shtylman
|
||||
* Copyright(c) 2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
exports.parse = parse;
|
||||
exports.serialize = serialize;
|
||||
|
||||
/**
|
||||
* Module variables.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var decode = decodeURIComponent;
|
||||
var encode = encodeURIComponent;
|
||||
|
||||
/**
|
||||
* RegExp to match field-content in RFC 7230 sec 3.2
|
||||
*
|
||||
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
|
||||
* field-vchar = VCHAR / obs-text
|
||||
* obs-text = %x80-FF
|
||||
*/
|
||||
|
||||
var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
|
||||
|
||||
/**
|
||||
* Parse a cookie header.
|
||||
*
|
||||
* Parse the given cookie header string into an object
|
||||
* The object has the various cookies as keys(names) => values
|
||||
*
|
||||
* @param {string} str
|
||||
* @param {object} [options]
|
||||
* @return {object}
|
||||
* @public
|
||||
*/
|
||||
|
||||
function parse(str, options) {
|
||||
if (typeof str !== 'string') {
|
||||
throw new TypeError('argument str must be a string');
|
||||
}
|
||||
|
||||
var obj = {}
|
||||
var opt = options || {};
|
||||
var pairs = str.split(';')
|
||||
var dec = opt.decode || decode;
|
||||
|
||||
for (var i = 0; i < pairs.length; i++) {
|
||||
var pair = pairs[i];
|
||||
var index = pair.indexOf('=')
|
||||
|
||||
// skip things that don't look like key=value
|
||||
if (index < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var key = pair.substring(0, index).trim()
|
||||
|
||||
// only assign once
|
||||
if (undefined == obj[key]) {
|
||||
var val = pair.substring(index + 1, pair.length).trim()
|
||||
|
||||
// quoted values
|
||||
if (val[0] === '"') {
|
||||
val = val.slice(1, -1)
|
||||
}
|
||||
|
||||
obj[key] = tryDecode(val, dec);
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize data into a cookie header.
|
||||
*
|
||||
* Serialize the a name value pair into a cookie string suitable for
|
||||
* http headers. An optional options object specified cookie parameters.
|
||||
*
|
||||
* serialize('foo', 'bar', { httpOnly: true })
|
||||
* => "foo=bar; httpOnly"
|
||||
*
|
||||
* @param {string} name
|
||||
* @param {string} val
|
||||
* @param {object} [options]
|
||||
* @return {string}
|
||||
* @public
|
||||
*/
|
||||
|
||||
function serialize(name, val, options) {
|
||||
var opt = options || {};
|
||||
var enc = opt.encode || encode;
|
||||
|
||||
if (typeof enc !== 'function') {
|
||||
throw new TypeError('option encode is invalid');
|
||||
}
|
||||
|
||||
if (!fieldContentRegExp.test(name)) {
|
||||
throw new TypeError('argument name is invalid');
|
||||
}
|
||||
|
||||
var value = enc(val);
|
||||
|
||||
if (value && !fieldContentRegExp.test(value)) {
|
||||
throw new TypeError('argument val is invalid');
|
||||
}
|
||||
|
||||
var str = name + '=' + value;
|
||||
|
||||
if (null != opt.maxAge) {
|
||||
var maxAge = opt.maxAge - 0;
|
||||
|
||||
if (isNaN(maxAge) || !isFinite(maxAge)) {
|
||||
throw new TypeError('option maxAge is invalid')
|
||||
}
|
||||
|
||||
str += '; Max-Age=' + Math.floor(maxAge);
|
||||
}
|
||||
|
||||
if (opt.domain) {
|
||||
if (!fieldContentRegExp.test(opt.domain)) {
|
||||
throw new TypeError('option domain is invalid');
|
||||
}
|
||||
|
||||
str += '; Domain=' + opt.domain;
|
||||
}
|
||||
|
||||
if (opt.path) {
|
||||
if (!fieldContentRegExp.test(opt.path)) {
|
||||
throw new TypeError('option path is invalid');
|
||||
}
|
||||
|
||||
str += '; Path=' + opt.path;
|
||||
}
|
||||
|
||||
if (opt.expires) {
|
||||
if (typeof opt.expires.toUTCString !== 'function') {
|
||||
throw new TypeError('option expires is invalid');
|
||||
}
|
||||
|
||||
str += '; Expires=' + opt.expires.toUTCString();
|
||||
}
|
||||
|
||||
if (opt.httpOnly) {
|
||||
str += '; HttpOnly';
|
||||
}
|
||||
|
||||
if (opt.secure) {
|
||||
str += '; Secure';
|
||||
}
|
||||
|
||||
if (opt.sameSite) {
|
||||
var sameSite = typeof opt.sameSite === 'string'
|
||||
? opt.sameSite.toLowerCase() : opt.sameSite;
|
||||
|
||||
switch (sameSite) {
|
||||
case true:
|
||||
str += '; SameSite=Strict';
|
||||
break;
|
||||
case 'lax':
|
||||
str += '; SameSite=Lax';
|
||||
break;
|
||||
case 'strict':
|
||||
str += '; SameSite=Strict';
|
||||
break;
|
||||
case 'none':
|
||||
str += '; SameSite=None';
|
||||
break;
|
||||
default:
|
||||
throw new TypeError('option sameSite is invalid');
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try decoding a string using a decoding function.
|
||||
*
|
||||
* @param {string} str
|
||||
* @param {function} decode
|
||||
* @private
|
||||
*/
|
||||
|
||||
function tryDecode(str, decode) {
|
||||
try {
|
||||
return decode(str);
|
||||
} catch (e) {
|
||||
return str;
|
||||
}
|
||||
}
|
42
node_modules/express-session/node_modules/cookie/package.json
generated
vendored
Normal file
42
node_modules/express-session/node_modules/cookie/package.json
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "cookie",
|
||||
"description": "HTTP server cookie parsing and serialization",
|
||||
"version": "0.4.2",
|
||||
"author": "Roman Shtylman <shtylman@gmail.com>",
|
||||
"contributors": [
|
||||
"Douglas Christopher Wilson <doug@somethingdoug.com>"
|
||||
],
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"cookie",
|
||||
"cookies"
|
||||
],
|
||||
"repository": "jshttp/cookie",
|
||||
"devDependencies": {
|
||||
"beautify-benchmark": "0.2.4",
|
||||
"benchmark": "2.1.4",
|
||||
"eslint": "7.32.0",
|
||||
"eslint-plugin-markdown": "2.2.1",
|
||||
"mocha": "9.2.0",
|
||||
"nyc": "15.1.0",
|
||||
"top-sites": "1.1.85"
|
||||
},
|
||||
"files": [
|
||||
"HISTORY.md",
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
"index.js"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
},
|
||||
"scripts": {
|
||||
"bench": "node benchmark/index.js",
|
||||
"lint": "eslint .",
|
||||
"test": "mocha --reporter spec --bail --check-leaks --ui qunit test/",
|
||||
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
|
||||
"test-cov": "nyc --reporter=html --reporter=text npm test",
|
||||
"update-bench": "node scripts/update-benchmark.js",
|
||||
"version": "node scripts/version-history.js && git add HISTORY.md"
|
||||
}
|
||||
}
|
47
node_modules/express-session/package.json
generated
vendored
Normal file
47
node_modules/express-session/package.json
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "express-session",
|
||||
"version": "1.17.3",
|
||||
"description": "Simple session middleware for Express",
|
||||
"author": "TJ Holowaychuk <tj@vision-media.ca> (http://tjholowaychuk.com)",
|
||||
"contributors": [
|
||||
"Douglas Christopher Wilson <doug@somethingdoug.com>",
|
||||
"Joe Wagner <njwjs722@gmail.com>"
|
||||
],
|
||||
"repository": "expressjs/session",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cookie": "0.4.2",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "~2.0.0",
|
||||
"on-headers": "~1.0.2",
|
||||
"parseurl": "~1.3.3",
|
||||
"safe-buffer": "5.2.1",
|
||||
"uid-safe": "~2.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"after": "0.8.2",
|
||||
"cookie-parser": "1.4.6",
|
||||
"eslint": "7.32.0",
|
||||
"eslint-plugin-markdown": "2.2.1",
|
||||
"express": "4.17.3",
|
||||
"mocha": "10.0.0",
|
||||
"nyc": "15.1.0",
|
||||
"supertest": "6.2.3"
|
||||
},
|
||||
"files": [
|
||||
"session/",
|
||||
"HISTORY.md",
|
||||
"index.js"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint . && node ./scripts/lint-readme.js",
|
||||
"test": "mocha --require test/support/env --check-leaks --bail --no-exit --reporter spec test/",
|
||||
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
|
||||
"test-cov": "nyc npm test",
|
||||
"version": "node scripts/version-history.js && git add HISTORY.md"
|
||||
}
|
||||
}
|
150
node_modules/express-session/session/cookie.js
generated
vendored
Normal file
150
node_modules/express-session/session/cookie.js
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
/*!
|
||||
* Connect - session - Cookie
|
||||
* Copyright(c) 2010 Sencha Inc.
|
||||
* Copyright(c) 2011 TJ Holowaychuk
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var cookie = require('cookie')
|
||||
var deprecate = require('depd')('express-session')
|
||||
|
||||
/**
|
||||
* Initialize a new `Cookie` with the given `options`.
|
||||
*
|
||||
* @param {IncomingMessage} req
|
||||
* @param {Object} options
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var Cookie = module.exports = function Cookie(options) {
|
||||
this.path = '/';
|
||||
this.maxAge = null;
|
||||
this.httpOnly = true;
|
||||
|
||||
if (options) {
|
||||
if (typeof options !== 'object') {
|
||||
throw new TypeError('argument options must be a object')
|
||||
}
|
||||
|
||||
for (var key in options) {
|
||||
if (key !== 'data') {
|
||||
this[key] = options[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.originalMaxAge === undefined || this.originalMaxAge === null) {
|
||||
this.originalMaxAge = this.maxAge
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* 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) {
|
||||
if (ms && typeof ms !== 'number' && !(ms instanceof Date)) {
|
||||
throw new TypeError('maxAge must be a number or Date')
|
||||
}
|
||||
|
||||
if (ms instanceof Date) {
|
||||
deprecate('maxAge as Date; pass number of milliseconds instead')
|
||||
}
|
||||
|
||||
this.expires = typeof ms === 'number'
|
||||
? 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
|
||||
, sameSite: this.sameSite
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Return a serialized cookie string.
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
serialize: function(name, val){
|
||||
return cookie.serialize(name, val, this.data);
|
||||
},
|
||||
|
||||
/**
|
||||
* Return JSON representation of this cookie.
|
||||
*
|
||||
* @return {Object}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
toJSON: function(){
|
||||
return this.data;
|
||||
}
|
||||
};
|
187
node_modules/express-session/session/memory.js
generated
vendored
Normal file
187
node_modules/express-session/session/memory.js
generated
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
/*!
|
||||
* express-session
|
||||
* Copyright(c) 2010 Sencha Inc.
|
||||
* Copyright(c) 2011 TJ Holowaychuk
|
||||
* Copyright(c) 2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var Store = require('./store')
|
||||
var util = require('util')
|
||||
|
||||
/**
|
||||
* Shim setImmediate for node.js < 0.10
|
||||
* @private
|
||||
*/
|
||||
|
||||
/* istanbul ignore next */
|
||||
var defer = typeof setImmediate === 'function'
|
||||
? setImmediate
|
||||
: function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) }
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
*/
|
||||
|
||||
module.exports = MemoryStore
|
||||
|
||||
/**
|
||||
* A session store in memory.
|
||||
* @public
|
||||
*/
|
||||
|
||||
function MemoryStore() {
|
||||
Store.call(this)
|
||||
this.sessions = Object.create(null)
|
||||
}
|
||||
|
||||
/**
|
||||
* Inherit from Store.
|
||||
*/
|
||||
|
||||
util.inherits(MemoryStore, Store)
|
||||
|
||||
/**
|
||||
* Get all active sessions.
|
||||
*
|
||||
* @param {function} callback
|
||||
* @public
|
||||
*/
|
||||
|
||||
MemoryStore.prototype.all = function all(callback) {
|
||||
var sessionIds = Object.keys(this.sessions)
|
||||
var sessions = Object.create(null)
|
||||
|
||||
for (var i = 0; i < sessionIds.length; i++) {
|
||||
var sessionId = sessionIds[i]
|
||||
var session = getSession.call(this, sessionId)
|
||||
|
||||
if (session) {
|
||||
sessions[sessionId] = session;
|
||||
}
|
||||
}
|
||||
|
||||
callback && defer(callback, null, sessions)
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all sessions.
|
||||
*
|
||||
* @param {function} callback
|
||||
* @public
|
||||
*/
|
||||
|
||||
MemoryStore.prototype.clear = function clear(callback) {
|
||||
this.sessions = Object.create(null)
|
||||
callback && defer(callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the session associated with the given session ID.
|
||||
*
|
||||
* @param {string} sessionId
|
||||
* @public
|
||||
*/
|
||||
|
||||
MemoryStore.prototype.destroy = function destroy(sessionId, callback) {
|
||||
delete this.sessions[sessionId]
|
||||
callback && defer(callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch session by the given session ID.
|
||||
*
|
||||
* @param {string} sessionId
|
||||
* @param {function} callback
|
||||
* @public
|
||||
*/
|
||||
|
||||
MemoryStore.prototype.get = function get(sessionId, callback) {
|
||||
defer(callback, null, getSession.call(this, sessionId))
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit the given session associated with the given sessionId to the store.
|
||||
*
|
||||
* @param {string} sessionId
|
||||
* @param {object} session
|
||||
* @param {function} callback
|
||||
* @public
|
||||
*/
|
||||
|
||||
MemoryStore.prototype.set = function set(sessionId, session, callback) {
|
||||
this.sessions[sessionId] = JSON.stringify(session)
|
||||
callback && defer(callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of active sessions.
|
||||
*
|
||||
* @param {function} callback
|
||||
* @public
|
||||
*/
|
||||
|
||||
MemoryStore.prototype.length = function length(callback) {
|
||||
this.all(function (err, sessions) {
|
||||
if (err) return callback(err)
|
||||
callback(null, Object.keys(sessions).length)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Touch the given session object associated with the given session ID.
|
||||
*
|
||||
* @param {string} sessionId
|
||||
* @param {object} session
|
||||
* @param {function} callback
|
||||
* @public
|
||||
*/
|
||||
|
||||
MemoryStore.prototype.touch = function touch(sessionId, session, callback) {
|
||||
var currentSession = getSession.call(this, sessionId)
|
||||
|
||||
if (currentSession) {
|
||||
// update expiration
|
||||
currentSession.cookie = session.cookie
|
||||
this.sessions[sessionId] = JSON.stringify(currentSession)
|
||||
}
|
||||
|
||||
callback && defer(callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get session from the store.
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getSession(sessionId) {
|
||||
var sess = this.sessions[sessionId]
|
||||
|
||||
if (!sess) {
|
||||
return
|
||||
}
|
||||
|
||||
// parse
|
||||
sess = JSON.parse(sess)
|
||||
|
||||
if (sess.cookie) {
|
||||
var expires = typeof sess.cookie.expires === 'string'
|
||||
? new Date(sess.cookie.expires)
|
||||
: sess.cookie.expires
|
||||
|
||||
// destroy expired session
|
||||
if (expires && expires <= Date.now()) {
|
||||
delete this.sessions[sessionId]
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return sess
|
||||
}
|
143
node_modules/express-session/session/session.js
generated
vendored
Normal file
143
node_modules/express-session/session/session.js
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
/*!
|
||||
* Connect - session - Session
|
||||
* Copyright(c) 2010 Sencha Inc.
|
||||
* Copyright(c) 2011 TJ Holowaychuk
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Expose Session.
|
||||
*/
|
||||
|
||||
module.exports = Session;
|
||||
|
||||
/**
|
||||
* Create a new `Session` with the given request and `data`.
|
||||
*
|
||||
* @param {IncomingRequest} req
|
||||
* @param {Object} data
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function Session(req, data) {
|
||||
Object.defineProperty(this, 'req', { value: req });
|
||||
Object.defineProperty(this, 'id', { value: req.sessionID });
|
||||
|
||||
if (typeof data === 'object' && data !== null) {
|
||||
// merge data into this, ignoring prototype properties
|
||||
for (var prop in data) {
|
||||
if (!(prop in this)) {
|
||||
this[prop] = data[prop]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update reset `.cookie.maxAge` to prevent
|
||||
* the cookie from expiring when the
|
||||
* session is still active.
|
||||
*
|
||||
* @return {Session} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
defineMethod(Session.prototype, 'touch', function touch() {
|
||||
return this.resetMaxAge();
|
||||
});
|
||||
|
||||
/**
|
||||
* Reset `.maxAge` to `.originalMaxAge`.
|
||||
*
|
||||
* @return {Session} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
defineMethod(Session.prototype, 'resetMaxAge', function resetMaxAge() {
|
||||
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
|
||||
*/
|
||||
|
||||
defineMethod(Session.prototype, 'save', function save(fn) {
|
||||
this.req.sessionStore.set(this.id, this, fn || function(){});
|
||||
return this;
|
||||
});
|
||||
|
||||
/**
|
||||
* Re-loads the session data _without_ altering
|
||||
* the maxAge 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
|
||||
*/
|
||||
|
||||
defineMethod(Session.prototype, 'reload', function reload(fn) {
|
||||
var req = this.req
|
||||
var 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
|
||||
*/
|
||||
|
||||
defineMethod(Session.prototype, 'destroy', function destroy(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
|
||||
*/
|
||||
|
||||
defineMethod(Session.prototype, 'regenerate', function regenerate(fn) {
|
||||
this.req.sessionStore.regenerate(this.req, fn);
|
||||
return this;
|
||||
});
|
||||
|
||||
/**
|
||||
* Helper function for creating a method on a prototype.
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @param {String} name
|
||||
* @param {Function} fn
|
||||
* @private
|
||||
*/
|
||||
function defineMethod(obj, name, fn) {
|
||||
Object.defineProperty(obj, name, {
|
||||
configurable: true,
|
||||
enumerable: false,
|
||||
value: fn,
|
||||
writable: true
|
||||
});
|
||||
};
|
102
node_modules/express-session/session/store.js
generated
vendored
Normal file
102
node_modules/express-session/session/store.js
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
/*!
|
||||
* Connect - session - Store
|
||||
* Copyright(c) 2010 Sencha Inc.
|
||||
* Copyright(c) 2011 TJ Holowaychuk
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var Cookie = require('./cookie')
|
||||
var EventEmitter = require('events').EventEmitter
|
||||
var Session = require('./session')
|
||||
var util = require('util')
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
module.exports = Store
|
||||
|
||||
/**
|
||||
* Abstract base class for session stores.
|
||||
* @public
|
||||
*/
|
||||
|
||||
function Store () {
|
||||
EventEmitter.call(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Inherit from EventEmitter.
|
||||
*/
|
||||
|
||||
util.inherits(Store, EventEmitter)
|
||||
|
||||
/**
|
||||
* 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 };
|
||||
fn(null, self.createSession(req, sess))
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Create session from JSON `sess` data.
|
||||
*
|
||||
* @param {IncomingRequest} req
|
||||
* @param {Object} sess
|
||||
* @return {Session}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Store.prototype.createSession = function(req, sess){
|
||||
var expires = sess.cookie.expires
|
||||
var originalMaxAge = sess.cookie.originalMaxAge
|
||||
|
||||
sess.cookie = new Cookie(sess.cookie);
|
||||
|
||||
if (typeof expires === 'string') {
|
||||
// convert expires to a Date object
|
||||
sess.cookie.expires = new Date(expires)
|
||||
}
|
||||
|
||||
// keep originalMaxAge intact
|
||||
sess.cookie.originalMaxAge = originalMaxAge
|
||||
|
||||
req.session = new Session(req, sess);
|
||||
return req.session;
|
||||
};
|
Reference in New Issue
Block a user