## [v2.1.0] - TBD
- cookies are now parsed and populated into ctx.cookie as a default behavior
+- new addCookie common helper
- added HTTP status and message enums
- updated devDependencies
return lines;
};
+/**
+ * Adds a new cookie.
+ * @param {http.ServerResponse} res
+ * @param {String} name
+ * @param {String} value
+ * @param {Object=} opt
+ * @param {String=} opt.domain
+ * @param {Date=} opt.expires
+ * @param {Boolean=} opt.httpOnly
+ * @param {Number=} opt.maxAge
+ * @param {String=} opt.path
+ * @param {String=} opt.sameSite
+ * @param {Boolean=} opt.secure
+ */
+function addCookie(res, name, value, opt = {}) {
+ const options = {
+ domain: undefined,
+ expires: undefined,
+ httpOnly: false,
+ maxAge: undefined,
+ path: undefined,
+ sameSite: undefined,
+ secure: false,
+ ...opt,
+ };
+ // TODO: validate name, value
+ const cookieParts = [
+ `${name}=${value}`,
+ ];
+ if (options.domain) {
+ cookieParts.push(`Domain=${options.domain}`);
+ }
+ if (options.expires) {
+ if (!(options.expires instanceof Date)) {
+ throw new TypeError('cookie expires must be Date');
+ }
+ cookieParts.push(`Expires=${options.expires.toUTCString()}`);
+ }
+ if (options.httpOnly) {
+ cookieParts.push('HttpOnly');
+ }
+ if (options.maxAge) {
+ cookieParts.push(`Max-Age=${options.maxAge}`);
+ }
+ if (options.path) {
+ cookieParts.push(`Path=${options.path}`);
+ }
+ if (options.sameSite) {
+ if (!(['Strict', 'Lax', 'None'].includes(options.sameSite))) {
+ throw new RangeError('cookie sameSite value not valid');
+ }
+ cookieParts.push(`SameSite=${options.sameSite}`);
+ }
+ if (options.secure) {
+ cookieParts.push('Secure');
+ }
+ res.appendHeader(Enum.Header.SetCookie, cookieParts.join('; '));
+}
+
+
module.exports = {
+ addCookie,
fileScope,
generateETag,
get,
});
}); // unfoldHeaderLines
+ describe('addCookie', function () {
+ let res, name, value;
+ beforeEach(function () {
+ res = {
+ appendHeader: sinon.stub(),
+ };
+ name = 'someCookieName';
+ value = 'someCookieValue';
+ });
+ it('covers no options', function () {
+ common.addCookie(res, name, value, {});
+ assert(res.appendHeader.called);
+ });
+ it('covers all options', function () {
+ common.addCookie(res, name, value, {
+ domain: 'example.com',
+ expires: new Date(),
+ httpOnly: true,
+ maxAge: 9999999,
+ path: '/foo',
+ sameSite: 'Lax',
+ secure: true,
+ });
+ assert(res.appendHeader.called);
+ });
+ it('covers invalid expires', function () {
+ assert.throws(() => common.addCookie(res, name, value, { expires: 'never' }), TypeError);
+ });
+ it('covers invalid sameSite', function () {
+ assert.throws(() => common.addCookie(res, name, value, { sameSite: 'Whatever' }));
+ });
+ it('covers no options', function () {
+ common.addCookie(res, name, value);
+ assert(res.appendHeader.called);
+ });
+ }); // addCookie
+
});