@centralping/sugar-cookie
v0.1.0
Published
A slightly opinionated browser cookie parser.
Downloads
1
Readme
@CentralPing/sugar-cookie
A slightly opinionated browser cookie parser.
Backgound
JavaScript can access and modify HTTP cookies through the document.cookie
interface. Unfortunately the API is a bit limited and cumbersome for managing cookies and storing values of types other than strings. sugar-cookie
is effectively a wrapper around the native interface to aid with this and adds a little sugar on as well.
Motivation & Opinion
Why make yet another cookie parser when there are plenty of existing modules (including the original module this one is based on)? To be honest the main reason is simply an exercise in refactoring the aforementioned original module into a current version (at least as of mid 2018).
The other main reason is to continue to provide an alternative approach for dealing with a an odditiy of the document.cookie
interface that most of the existing cookie parsers gloss over: that cookie names are not unique across host/path matching (see the note on RFC2109).
Since cookie names can match multiple cookies depending on domain/path matching most browsers will return cookies in the order of specifity of the matches but with no way to determine what the host/path is for the returned cookies (document.cookie
only returns the name:value
pairs concatened together). Most parsers that are aware of this assume the browser is doing the right thing and only return the first cookie value per name. A problem with this approach is that a developer would never know there were mulitple matching cookies (which could be a pretty nasty thing to debug) or if it was desired they would never be able to access the other values without using document.cookie
directly.
Which brings us to the slightly opinionated aspect of this module. Due to the possibility of a cookie name having mutliple values this module will return all cookie values as an array of values. While this will generally result in single element arrays, it will always provide a developer a way of quickly checking if there are multiple values and if so a way of having access to them. Unfortunately there is no way to include any information about the respective host/path values as this is not provided from the interface.
Another opinionated aspect of this module is the use of JSON stringification and parsing by default. Why? Well, since all cookie values are a concatenated string of name=value[;attributes]
then any non-string values would need to be converted to a string. This happens automatically via the object value's toString
method. Most objects will use the Object.prototype.toString
method which simply returns [object OBJECT_TYPE]
where OBJECT_TYPE
is the type of the object. Arrays are a notable exception as their toString
method will effectively act as a join
using commas. Reading these values later will either be useless, as in the case of most object types, or they will remain a string value rather than be reconstitued to the original object type.
What about pre-existing cookie values? The JSON parser would simply return them as strings (unless of course they were already encoded JSON). The only issue with using this approach is any strings set by sugarCookie
would then be encoded JSON which includes quotation marks. Any other cookie parser might need to be aware of this. I have not seen this as an issue yet. If this is not desired or if a different conversion is desired then the conversion can be disabled (null
, false
or any falsy value) or modified by providing a function that accepts a string value.
A Note on Retreiving And Storing Cookies
RFC2109 states cookies are unique based on their name, domain and path. The document.cookie
interface returns all accessible cookies (name, value pairs) by the domain and path matching rules. This creates a situation where a cookie name could be shared between multiple cookies. Therefore when setting a value, proper care should be taken to assign the cookie to the correct domain and path to avoid either creating a new cookie or updating an incorrect one.
Installation
npm i --save https://github.com/CentralPing/sugar-cookie
API Reference
sugarCookie~getAll(pattern, [conv]) ⇒ Object.<String, Array>
Gets all cookies matching the domain/path of the current page with optinal name pattern matching. Values will be automatically parsed by JSON by default. Cookie values are returned as arrays due to names being non-unique for different hosts/paths.
Kind: inner method of sugarCookie
Returns: Object.<String, Array> - An object where each key is a cookie name.
| Param | Type | Default | Description | | --- | --- | --- | --- | | pattern | RegExp | String | | A regexp (or string) to match cookie names. Strings can be substring matches (e.g. "bar" would match cookie "foobar"). | | [conv] | function | JSON.parse | Function to convert value. |
Example
const cookies = getAll();
sugarCookie~get([name], [conv]) ⇒ Array
Get the value(s) for a cookie matching the provided name and the domain/path of the current page. Values will be automatically parsed by JSON by default. Cookie values are returned as arrays due to names being non-unique for different hosts/paths.
Kind: inner method of sugarCookie
Returns: Array - An array of parsed (if applicable) values.
| Param | Type | Default | Description | | --- | --- | --- | --- | | [name] | String | | The name of the cookie. | | [conv] | function | JSON.parse | Function to convert value. |
Example
const fooCookie = get('foo');
sugarCookie~put([name], [value], [attributes], [conv])
Sets (or updates) a cookie with the provided name domain/path.
Kind: inner method of sugarCookie
| Param | Type | Default | Description | | --- | --- | --- | --- | | [name] | String | | The name of the cookie. | | [value] | * | '' | The value of the cookie. By default, all values are stringified to allow easy conversion back to original types (as allowed by JSON parsing). | | [attributes] | Object | | See Cookies for more information about attributes. | | [attributes.domain] | String | | The domain of the cookie. Defaults to the host portion of the current document location. If a domain is specified, subdomains are always included. | | [attributes.path] | String | | The absolute path of the cookie. Defaults to the current path of the current document location. | | [attributes.secure] | Boolean | | Indicates whether the cookie is transmitted over secure protocols such as HTTPS. | | [attributes.samesite] | String | | Indicates if a cookie shouldn't be sent with cross-site requests. See SameSite for more information. | | [attributes.maxAge] | Number | | The maximum age of a cookie in seconds. | | [attributes.expires] | Date | String | | The GMT timestamp of the cookie expiration. | | [conv] | function | JSON.stringify | Function to convert value. |
Example
put('foo', {someObject: 'value'});
put('bar', 'someStringValue', {path: '/somePath'});
sugarCookie~remove([name], [attributes])
Removes an existing cookie (sets the expiration and max-age attributes to expired values).
Kind: inner method of sugarCookie
| Param | Type | Description | | --- | --- | --- | | [name] | String | The name of the cookie. | | [attributes] | Object | See Cookies for more information about attributes. | | [attributes.domain] | String | The domain of the cookie. Defaults to the host portion of the current document location. If a domain is specified, subdomains are always included. | | [attributes.path] | String | The absolute path of the cookie. Defaults to the current path of the current document location. |
Example
remove('foo');
remove('bar', {path: '/somePath'});
Examples
For Basic Cookie Parsing
// Path: '/'
// Assuming no existing cookies
sugarCookie.put('foo', 'hello');
sugarCookie.put('bar', 'ciao');
sugarCookie.get('foo'); // ['hello']
sugarCookie.getAll(); // {foo: ['hello'], bar: ['ciao']}
sugarCookie.getAll('ar'); // {bar: ['ciao']}
sugarCookie.remove('foo');
sugarCookie.get('foo'); // undefined
sugarCookie.getAll(); // {bar: ['ciao']}
// Path: '/bar'
// Assuming foo and bar cookies exist at path '/'
sugarCookie.put('foo', 'bye');
sugarCookie.get('foo'); // ['bye', 'hello']
sugarCookie.getAll(); // {foo: ['bye', 'hello'], bar: ['ciao']}
sugarCookie.getAll('ar'); // {bar: ['ciao']}
sugarCookie.remove('foo');
sugarCookie.get('foo'); // ['bye']
sugarCookie.getAll(); // {bar: ['ciao'], 'foo': ['bye']}
For Storing Any Type of Value
sugarCookie.put('foo', {say: 'hello'});
sugarCookie.put('bar', ['ciao']);
sugarCookie.get('foo'); // [{say: 'hello'}]
sugarCookie.getAll(); // {foo: [{say: 'hello'}], bar: [['ciao']]}
sugarCookie.getAll('ar'); // {bar: [['ciao']]}
sugarCookie.remove('foo');
sugarCookie.get('foo'); // undefined
sugarCookie.getAll(); // {bar: [['ciao']]}
License
MIT