Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update yar to use request.yar instead of request.session #89

Merged
merged 3 commits into from Jan 5, 2016
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions API.md
Expand Up @@ -7,7 +7,7 @@
- `name` - determines the name of the cookie used to store session information. Defaults to _session_.
- `maxCookieSize` - maximum cookie size before using server-side storage. Defaults to 1K. Set to zero to always use server-side storage.
- `storeBlank` - determines whether to store empty session before they've been modified. Defaults to _true_.
- `errorOnCacheNotReady` - will cause yar to throw exception if trying to persist to cache when cache is unavailable. Setting to false will allow application using yar to run uninterrupted if cache is not ready (however sessions will not be saving). Defaults to _true_.
- `errorOnCacheNotReady` - will cause yar to throw an exception if trying to persist to cache when the cache is unavailable. Setting this to false will allow applications using yar to run uninterrupted if the cache is not ready (however sessions will not be saving). Defaults to _true_.
- `cache` - **hapi** [cache options](https://github.com/hapijs/hapi/blob/master/API.md#servercacheoptions) which includes
(among other options):
- `expiresIn` - server-side storage expiration (defaults to 1 day).
Expand All @@ -21,13 +21,13 @@

#### Methods

**yar** adds the `session` property to every request object and initializes the `session.id` on the first request from each browser. The `request.session` interface provides the following methods:
**yar** adds the `yar` property to every request object and initializes the `yar.id` on the first request from each browser. The `request.yar` interface provides the following methods:

- `reset()` - clears the session and assigns a new session id.
- `set(key, value)` - assigns a value (string, object, etc) to a given key which will persist across requests. Returns the value.
- `set(keysObject)` - assigns values to multiple keys using each 'keysObject' top-level property. Returns the keysObject.
- `get(key, clear)` - retreive value using a key. If 'clear' is 'true', key is cleared on return.
- `get(key, clear)` - retrieve value using a key. If 'clear' is 'true', key is cleared on return.
- `clear(key)` - clears key.
- `touch()` - Manually notify the session of changes (when using `get()` and changing the content of the returned reference directly without calling `set()`).
- `flash(type, message, isOverride)` - stores volatile data - data that should be deleted once read. When given no arguments, it will return all of the flash messages and delete the originals. When given only a type, it will return all of the flash messages of that type and delete the originals. When given a type and a message, it will set or append that message to the given type. 'isOverride' used to indicate that the message provided should replace any existing value instead of being appended to it (defaults to false).
- `lazy(enabled)` - if set to 'true', enables lazy mode. In lazy mode, `request.session` can be modified directly (e.g. setting `request.session.myKey` to an object value), and those keys will be stored and loaded back. Lazy mode isn't as fast as the normal get/set because it has to store the session state on every responses regardless of any changes being made.
- `lazy(enabled)` - if set to 'true', enables lazy mode. In lazy mode, `request.yar` can be modified directly (e.g. setting `request.yar.myKey` to an object value), and those keys will be stored and loaded back. Lazy mode isn't as fast as the normal get/set because it has to store the session state on every responses regardless of any changes being made.
2 changes: 1 addition & 1 deletion LICENSE
@@ -1,4 +1,4 @@
Copyright (c) 2013-2014, Mark Bradshaw
Copyright (c) 2015-2016, Mark Bradshaw
Copyright (c) 2013-2014, Walmart and other contributors.
All rights reserved.

Expand Down
11 changes: 6 additions & 5 deletions README.md
Expand Up @@ -6,18 +6,19 @@ A [**hapi**](https://github.com/hapijs/hapi) session plugin and cookie jar
[![Build Status](https://secure.travis-ci.org/hapijs/yar.png)](http://travis-ci.org/hapijs/yar)
[![Dependency Status](https://david-dm.org/hapijs/yar.svg)](https://david-dm.org/hapijs/yar)

[![Join the chat at https://gitter.im/hapijs/yar](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/hapijs/yar?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

Lead Maintainer: [Mark Bradshaw](https://github.com/mark-bradshaw)

## Install

$ npm install yar

## Upgrading to 4.x and greater
## Upgrading to 4.x.x and greater

Please note that version 4.x has a small breaking change. This probably doesn't affect most people, but it's worth noting. In version 3.x if a cookie was invalid, either due to corruption or change in encryption password, the server would respond with a HTTP 400 error. Starting in 4.x the default settings avoid this and instead silently drop the invalid cookie. This is probably the desired behavior, but since it's different you should be aware of it when upgrading.

## Upgrading to 6.x.x and greater

Starting with Hapi 12 the `request.session` placeholder was removed. The guidance from Hapi maintainer Eran Hammer was for this and similar modules to move data storage away from request.session and use a more unique location. So, starting in 6.x.x the yar storage has been moved to `request.yar`. All the functionality remains the same, but it just lives in a different location. I apologize in advance for the inconvenience this may cause but updating your code should be fairly straight forward.

## Usage

Expand All @@ -30,13 +31,13 @@ For example, the first handler sets a session key and the second gets it:
```javascript
var handler1 = function (request, reply) {

request.session.set('example', { key: 'value' });
request.yar.set('example', { key: 'value' });
return reply();
};

var handler2 = function (request, reply) {

var example = request.session.get('example');
var example = request.yar.get('example');
reply(example.key); // Will send back 'value'
};
```
Expand Down
8 changes: 4 additions & 4 deletions examples/index.js
Expand Up @@ -28,7 +28,7 @@ server.route({
method: 'GET',
path: '/',
config: {
handler: (request, reply) => reply(request.session._store)
handler: (request, reply) => reply(request.yar._store)
}
});

Expand All @@ -38,7 +38,7 @@ server.route({
config: {
handler: (request, reply) => {

request.session.set('test', 1);
request.yar.set('test', 1);
return reply.redirect('/');
}
}
Expand All @@ -50,7 +50,7 @@ server.route({
config: {
handler: (request, reply) => {

request.session.set(request.params.key, request.params.value);
request.yar.set(request.params.key, request.params.value);
return reply.redirect('/');
}
}
Expand All @@ -62,7 +62,7 @@ server.route({
config: {
handler: (request, reply) => {

request.session.reset();
request.yar.reset();
return reply.redirect('/');
}
}
Expand Down
110 changes: 55 additions & 55 deletions lib/index.js
Expand Up @@ -54,35 +54,35 @@ exports.register = (server, options, next) => {

const load = () => {

request.session = Hoek.clone(request.state[settings.name]);
if (request.session &&
request.session.id) {
request.yar = Hoek.clone(request.state[settings.name]);
if (request.yar &&
request.yar.id) {

request.session._isModified = false;
if (!settings.errorOnCacheNotReady && !cache.isReady() && !request.session._store) {
request.yar._isModified = false;
if (!settings.errorOnCacheNotReady && !cache.isReady() && !request.yar._store) {
request.log('Cache is not ready: not loading sessions from cache');
request.session._store = {};
request.yar._store = {};
}
if (request.session._store) {
if (request.yar._store) {
return decorate();
}

request.session._store = {};
return cache.get(request.session.id, (err, value, cached) => {
request.yar._store = {};
return cache.get(request.yar.id, (err, value, cached) => {

if (err) {
return decorate(err);
}

if (cached && cached.item) {
request.session._store = cached.item;
request.yar._store = cached.item;
}

return decorate();
});
}

request.session = {
request.yar = {
id: Uuid.v4(),
_store: {},
_isModified: settings.storeBlank
Expand All @@ -93,39 +93,39 @@ exports.register = (server, options, next) => {

const decorate = (err) => {

if (request.session._store._lazyKeys) {
request.session._isLazy = true; // Default to lazy mode if previously set
request.session._store._lazyKeys.forEach((key) => {
if (request.yar._store._lazyKeys) {
request.yar._isLazy = true; // Default to lazy mode if previously set
request.yar._store._lazyKeys.forEach((key) => {

request.session[key] = request.session._store[key];
delete request.session._store[key];
request.yar[key] = request.yar._store[key];
delete request.yar._store[key];
});
}

request.session.reset = () => {
request.yar.reset = () => {

cache.drop(request.session.id, () => {});
request.session.id = Uuid.v4();
request.session._store = {};
request.session._isModified = true;
cache.drop(request.yar.id, () => {});
request.yar.id = Uuid.v4();
request.yar._store = {};
request.yar._isModified = true;
};

request.session.get = (key, clear) => {
request.yar.get = (key, clear) => {

const value = request.session._store[key];
const value = request.yar._store[key];
if (clear) {
request.session.clear(key);
request.yar.clear(key);
}

return value;
};

request.session.set = (key, value) => {
request.yar.set = (key, value) => {

Hoek.assert(key, 'Missing key');
Hoek.assert(typeof key === 'string' || (typeof key === 'object' && value === undefined), 'Invalid session.set() arguments');
Hoek.assert(typeof key === 'string' || (typeof key === 'object' && value === undefined), 'Invalid yar.set() arguments');

request.session._isModified = true;
request.yar._isModified = true;

if (typeof key === 'string') {
// convert key of type string into an object, for consistency.
Expand All @@ -136,48 +136,48 @@ exports.register = (server, options, next) => {

Object.keys(key).forEach((name) => {

request.session._store[name] = key[name];
request.yar._store[name] = key[name];
});

return value !== undefined ? value : key;
};

request.session.clear = (key) => {
request.yar.clear = (key) => {

request.session._isModified = true;
delete request.session._store[key];
request.yar._isModified = true;
delete request.yar._store[key];
};

request.session.touch = () => {
request.yar.touch = () => {

request.session._isModified = true;
request.yar._isModified = true;
};

request.session.flash = (type, message, isOverride) => {
request.yar.flash = (type, message, isOverride) => {

let messages;
request.session._isModified = true;
request.session._store._flash = request.session._store._flash || {};
request.yar._isModified = true;
request.yar._store._flash = request.yar._store._flash || {};

if (!type && !message) {
messages = request.session._store._flash;
request.session._store._flash = {};
messages = request.yar._store._flash;
request.yar._store._flash = {};
return messages;
}

if (!message) {
messages = request.session._store._flash[type];
delete request.session._store._flash[type];
messages = request.yar._store._flash[type];
delete request.yar._store._flash[type];
return messages || [];
}

request.session._store._flash[type] = (isOverride ? message : (request.session._store._flash[type] || []).concat(message));
return request.session._store._flash[type];
request.yar._store._flash[type] = (isOverride ? message : (request.yar._store._flash[type] || []).concat(message));
return request.yar._store._flash[type];
};

request.session.lazy = (enabled) => {
request.yar.lazy = (enabled) => {

request.session._isLazy = enabled;
request.yar._isLazy = enabled;
};

if (err) {
Expand All @@ -194,30 +194,30 @@ exports.register = (server, options, next) => {

server.ext('onPreResponse', (request, reply) => {

if (!request.session ||
(!request.session._isModified && !request.session._isLazy)) {
if (!request.yar ||
(!request.yar._isModified && !request.yar._isLazy)) {

return reply.continue();
}

const prepare = () => {

if (request.session._isLazy) {
if (request.yar._isLazy) {
const lazyKeys = [];
const keys = Object.keys(request.session);
const keys = Object.keys(request.yar);
for (let i = 0; i < keys.length; ++i) {
const key = keys[i];
if (['id', '_store', '_isModified', '_isLazy', 'reset', 'get', 'set', 'clear', 'touch', 'flash', 'lazy'].indexOf(key) === -1 &&
key[0] !== '_' &&
typeof request.session.key !== 'function') {
typeof request.yar.key !== 'function') {

lazyKeys.push(key);
request.session._store[key] = request.session[key];
request.yar._store[key] = request.yar[key];
}
}

if (lazyKeys.length) {
request.session._store._lazyKeys = lazyKeys;
request.yar._store._lazyKeys = lazyKeys;
}
}

Expand All @@ -231,8 +231,8 @@ exports.register = (server, options, next) => {
const cookie = function () {

const content = {
id: request.session.id,
_store: request.session._store
id: request.yar.id,
_store: request.yar._store
};

Statehood.prepareValue(settings.name, content, settings.cookieOptions, (err, value) => {
Expand All @@ -257,8 +257,8 @@ exports.register = (server, options, next) => {
return reply.continue();
}

reply.state(settings.name, { id: request.session.id });
cache.set(request.session.id, request.session._store, 0, (err) => {
reply.state(settings.name, { id: request.yar.id });
cache.set(request.yar.id, request.yar._store, 0, (err) => {

if (err) {
return reply(err);
Expand Down