ostrio:cookies

v2.7.2Published 4 months ago

support support

Isomorphic Cookies

Isomorphic and bulletproof 🍪 cookies for meteor.js applications with support of Client, Server, Browser, Cordova, and other Meteor-supported environments.

  • 👨‍💻 Stable codebase, 80.000+ downloads;
  • 👨‍🔬 ~96% Tests coverage;
  • 📦 No external dependencies, no underscore, no jQuery, no Blaze;
  • 🖥 Full support with same API on both Server and Client environments;
  • 📱 Compatible with Cordova, Browser and other Meteor's Client environments;
  • ㊗️ Unicode support as cookies' value;
  • 👨‍💻 String, Array, Object, and Boolean are supported cookies' value types;
  • ♿ IE support, thanks to @derwok;
  • 📦 Looking for Client's (Browser) persistent storage? Try ClientStorage package.

Install:

meteor add ostrio:cookies

ES6 Import:

1import { Cookies } from 'meteor/ostrio:cookies';

FAQ:

  • Cordova compatible? Cordova usageThis recommendation is only for outgoing Client -to-> Server Cookies; Server -to-> Client cookies work out-of-the-box. Enable withCredentials. Enable {allowQueryStringCookies: true} and {allowedCordovaOrigins: true} on both Client and Server. When those two options are set to true Cookies going to be transfered to server via get-query. As security measure only when Origin header matches ^http://localhost:12[0-9]{3}$ expression. Meteor/Cordova connect through localhost:12XXX, local server, for outgoing requests, this also instructs the server to respond with the requested cookies (sent as GET-Parameters) in the response as Set-Cookie header. The reason for this workaround is the general lack of cookie support in Meteor/Cordova when setting in the client — but cookies set by the server are always sent along with every request;
  • Cookies are missing on Server — In 99% cases it's caused by Meteor's webapp http server callback-chain disorder. Make sure new Cookies() is called before Routes are registered. Routing packages usually take care of * (e.g. catch-all or 404) route, not passing request further to callback-chain. And as freshly installed package it would be placed at the end of .meteor/packages file, where list-order matters. We recommend to place ostrio:cookies package above all community packages in .meteor/packages list.

API:

  • Note — On a server, cookies will be set only after headers are sent (on next route or page reload). To send cookies from Client to Server without a page reload use send() method.
  • Server Usage Note — On a server Cookies implemented as a middleware. To get access to current user's cookies use req.Cookies instance. For more - see examples section below.

Fetch cookies new Cookies(opts) [Isomorphic]

Create new instance of Cookies

  • opts.auto {Boolean} - [Server] Auto-bind in middleware as req.Cookies, by default true
  • opts.handler {Function} - [Server] Middleware function (e.g. hook/callback called within middleware pipeline) with single argument cookies as Cookies instance. See "Alternative Usage" section
  • opts.onCookies {Function} - [Server] Callback/hook triggered after .send() method called on Client and received by Server, called with single argument cookies as Cookies instance. Note: this hook available only if auto option is true
  • opts.TTL {Number|Boolean} - Default cookies expiration time (max-age) in milliseconds, by default - false (session, no TTL)
  • opts.runOnServer {Boolean} - Set to false to avoid server usage (by default - true)
  • opts.allowQueryStringCookies {Boolean} - Allow passing Cookies in a query string (in URL). Primary should be used only in Cordova environment. Note: this option will be used only on Cordova
  • opts.allowedCordovaOrigins {Regex|Boolean} - [Server] Allow setting Cookies from that specific origin which in Meteor/Cordova is localhost:12XXX. Set to default ^http:\/\/localhost:12[0-9]{3}$ if set to true. Default: false
1import { Cookies } from 'meteor/ostrio:cookies';
2const cookies = new Cookies();

cookies.get(key) [Isomorphic]

Read a cookie. If the cookie doesn't exist a null will be returned.

  • key {String} - The name of the cookie to read

cookies.set(key, value, [opts]) [Isomorphic]

Create/overwrite a cookie.

  • key {String} - The name of the cookie to create/overwrite
  • value {String|Number|Boolean|Object|Array} - The value of the cookie
  • opts {Object} - [Optional]
  • opts.expires {Number|Date|Infinity} - [Optional] Date, Number as milliseconds or Infinity for a never-expires cookie. If not specified the cookie will expire at the end of session (number as milliseconds or Date object)
  • opts.maxAge {Number} - [Optional] The max-age in seconds (e.g. 31536e3 for a year)
  • opts.path {String} - [Optional] The path from where the cookie will be readable. E.g., "/", "/mydir"; if not specified, defaults to the current path of the current document location (string or null). The path must be absolute (see RFC 2965). For more information on how to use relative paths in this argument, see: docs
  • opts.domain {String} - [Optional] The domain from where the cookie will be readable. E.g., "example.com", ".example.com" (includes all subdomains) or "subdomain.example.com"; if not specified, defaults to the host portion of the current document location (string or null)
  • opts.secure {Boolean} - [Optional] The cookie will be transmitted only over secure protocol as https
  • opts.httpOnly {Boolean} - [Optional] An HttpOnly cookie cannot be accessed by client-side APIs, such as JavaScript. This restriction eliminates the threat of cookie theft via cross-site scripting (XSS)
  • opts.sameSite {Boolean} {String: None, Strict, or Lax} - [Optional] Cross-site cookies usage policy. Read more on wikipedia, web.dev, and ietf. Default: false
  • opts.firstPartyOnly {Boolean} - [Optional] Deprecated use sameSite instead

cookies.remove([key], [path], [domain]) [Isomorphic]

  • remove() - Remove all cookies on current domain
  • remove(key) - Remove a cookie on current domain
  • remove(key, path, domain):
    • key {String} - The name of the cookie to create/overwrite
    • path {String} - [Optional] The path from where the cookie was readable. E.g., "/", "/mydir"; if not specified, defaults to the current path of the current document location (string or null). The path must be absolute (see RFC 2965). For more information on how to use relative paths in this argument, read more
    • domain {String} - [Optional] The domain from where the cookie was readable. E.g., "example.com", ".example.com" (includes all subdomains) or "subdomain.example.com"; if not specified, defaults to the host portion of the current document location (string or null)

cookies.has(key) [Isomorphic]

Check whether a cookie exists in the current position, returns boolean value

  • key {String} - The name of the cookie to check

cookies.keys() [Isomorphic]

Returns an array of all readable cookies from this location

cookies.send([callback]) [Client]

Send all current cookies to server.

Examples:

1/* Both Client & Server */
2import { Meteor } from 'meteor/meteor';
3import { Cookies } from 'meteor/ostrio:cookies';
4const cookies = new Cookies();
5
6/* Client */
7if (Meteor.isClient) {
8  cookies.set('locale', 'en'); //true
9  cookies.set('country', 'usa'); //true
10  cookies.set('gender', 'male'); //true
11
12  cookies.get('gender'); //male
13
14  cookies.has('locale'); //true
15  cookies.has('city'); //false
16
17  cookies.keys(); //['locale', 'country', 'gender']
18
19  cookies.remove('locale'); //true
20  cookies.get('locale'); //undefined
21
22  cookies.keys(); //['country', 'gender']
23
24  cookies.remove(); //true
25  cookies.keys(); //[""]
26
27  cookies.remove(); //false
28}
29
30/* Server */
31if (Meteor.isServer) {
32  const { WebApp } = require('meteor/webapp');
33
34  WebApp.connectHandlers.use((req, res, next) => {
35    cookies = req.Cookies;
36
37    cookies.set('locale', 'en'); //true
38    cookies.set('country', 'usa'); //true
39    cookies.set('gender', 'male'); //true
40
41    cookies.get('gender'); //male
42
43    cookies.has('locale'); //true
44    cookies.has('city'); //false
45
46    cookies.keys(); //['locale', 'country', 'gender']
47
48    cookies.remove('locale'); //true
49    cookies.get('locale'); //undefined
50
51    cookies.keys(); //['country', 'gender']
52
53    cookies.remove(); //true
54    cookies.keys(); //[""]
55
56    cookies.remove(); //false
57
58    next(); // Pass request to the next handler
59  });
60}

Alternative Usage

1/* Both Client & Server */
2import { Meteor } from 'meteor/meteor';
3import { Cookies } from 'meteor/ostrio:cookies';
4
5/* Client */
6if (Meteor.isClient) {
7  const cookies = new Cookies();
8  cookies.set('gender', 'male'); //true
9  cookies.get('gender'); //male
10  cookies.has('city'); //false
11  cookies.keys(); //['gender']
12}
13
14/* Server */
15if (Meteor.isServer) {
16  const { WebApp } = require('meteor/webapp');
17
18  const cookie = new Cookies({
19    auto: false, // Do not bind as a middleware by default (recommended, but not required)
20    handler(cookies) {
21      cookies.set('gender', 'male'); //true
22      cookies.get('gender'); //male
23      cookies.has('city'); //false
24      cookies.keys(); //['gender']
25    }
26  });
27
28  WebApp.connectHandlers.use(cookie.middleware());
29}

Running Tests

  1. Clone this package
  2. In Terminal (Console) go to directory where package is cloned
  3. Then run:

Meteor/Tinytest

# Default
meteor test-packages ./

# With custom port
meteor test-packages ./ --port 8888

Support our open source contributions