Skip to content

Commit

Permalink
feat: support priority (#52)
Browse files Browse the repository at this point in the history
pick from pillarjs/cookies@fb39c0a

closes #41
  • Loading branch information
fengmk2 committed Feb 19, 2024
1 parent f8ce911 commit f9f1214
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 53 deletions.
24 changes: 0 additions & 24 deletions .github/PULL_REQUEST_TEMPLATE.md

This file was deleted.

8 changes: 4 additions & 4 deletions README.md
Expand Up @@ -52,11 +52,11 @@ cookies.set('foo', longText);

## Contributors

|[<img src="https://avatars.githubusercontent.com/u/156269?v=4" width="100px;"/><br/><sub><b>fengmk2</b></sub>](https://github.com/fengmk2)<br/>|[<img src="https://avatars.githubusercontent.com/u/985607?v=4" width="100px;"/><br/><sub><b>dead-horse</b></sub>](https://github.com/dead-horse)<br/>|[<img src="https://avatars.githubusercontent.com/u/227713?v=4" width="100px;"/><br/><sub><b>atian25</b></sub>](https://github.com/atian25)<br/>|[<img src="https://avatars.githubusercontent.com/u/5856440?v=4" width="100px;"/><br/><sub><b>whxaxes</b></sub>](https://github.com/whxaxes)<br/>|[<img src="https://avatars.githubusercontent.com/u/5102113?v=4" width="100px;"/><br/><sub><b>xyeric</b></sub>](https://github.com/xyeric)<br/>|[<img src="https://avatars.githubusercontent.com/u/3939959?v=4" width="100px;"/><br/><sub><b>jedmeng</b></sub>](https://github.com/jedmeng)<br/>|
|[<img src="https://avatars.githubusercontent.com/u/156269?v=4" width="100px;"/><br/><sub><b>fengmk2</b></sub>](https://github.com/fengmk2)<br/>|[<img src="https://avatars.githubusercontent.com/u/985607?v=4" width="100px;"/><br/><sub><b>dead-horse</b></sub>](https://github.com/dead-horse)<br/>|[<img src="https://avatars.githubusercontent.com/u/32174276?v=4" width="100px;"/><br/><sub><b>semantic-release-bot</b></sub>](https://github.com/semantic-release-bot)<br/>|[<img src="https://avatars.githubusercontent.com/u/227713?v=4" width="100px;"/><br/><sub><b>atian25</b></sub>](https://github.com/atian25)<br/>|[<img src="https://avatars.githubusercontent.com/u/5856440?v=4" width="100px;"/><br/><sub><b>whxaxes</b></sub>](https://github.com/whxaxes)<br/>|[<img src="https://avatars.githubusercontent.com/u/5102113?v=4" width="100px;"/><br/><sub><b>xyeric</b></sub>](https://github.com/xyeric)<br/>|
| :---: | :---: | :---: | :---: | :---: | :---: |
|[<img src="https://avatars.githubusercontent.com/u/17005098?v=4" width="100px;"/><br/><sub><b>Junyan</b></sub>](https://github.com/Junyan)<br/>|[<img src="https://avatars.githubusercontent.com/u/12657964?v=4" width="100px;"/><br/><sub><b>beliefgp</b></sub>](https://github.com/beliefgp)<br/>|[<img src="https://avatars.githubusercontent.com/u/52845048?v=4" width="100px;"/><br/><sub><b>snapre</b></sub>](https://github.com/snapre)<br/>|[<img src="https://avatars.githubusercontent.com/u/360661?v=4" width="100px;"/><br/><sub><b>popomore</b></sub>](https://github.com/popomore)<br/>|[<img src="https://avatars.githubusercontent.com/u/32174276?v=4" width="100px;"/><br/><sub><b>semantic-release-bot</b></sub>](https://github.com/semantic-release-bot)<br/>|[<img src="https://avatars.githubusercontent.com/u/1276859?v=4" width="100px;"/><br/><sub><b>ziyunfei</b></sub>](https://github.com/ziyunfei)<br/>|
[<img src="https://avatars.githubusercontent.com/u/12656301?v=4" width="100px;"/><br/><sub><b>brizer</b></sub>](https://github.com/brizer)<br/>|[<img src="https://avatars.githubusercontent.com/u/7692708?v=4" width="100px;"/><br/><sub><b>xuezier</b></sub>](https://github.com/xuezier)<br/>|[<img src="https://avatars.githubusercontent.com/u/16103358?v=4" width="100px;"/><br/><sub><b>onlylovermb</b></sub>](https://github.com/onlylovermb)<br/>
|[<img src="https://avatars.githubusercontent.com/u/3939959?v=4" width="100px;"/><br/><sub><b>jedmeng</b></sub>](https://github.com/jedmeng)<br/>|[<img src="https://avatars.githubusercontent.com/u/17005098?v=4" width="100px;"/><br/><sub><b>Junyan</b></sub>](https://github.com/Junyan)<br/>|[<img src="https://avatars.githubusercontent.com/u/12657964?v=4" width="100px;"/><br/><sub><b>beliefgp</b></sub>](https://github.com/beliefgp)<br/>|[<img src="https://avatars.githubusercontent.com/u/52845048?v=4" width="100px;"/><br/><sub><b>snapre</b></sub>](https://github.com/snapre)<br/>|[<img src="https://avatars.githubusercontent.com/u/360661?v=4" width="100px;"/><br/><sub><b>popomore</b></sub>](https://github.com/popomore)<br/>|[<img src="https://avatars.githubusercontent.com/u/22520131?v=4" width="100px;"/><br/><sub><b>tang-xy</b></sub>](https://github.com/tang-xy)<br/>|
[<img src="https://avatars.githubusercontent.com/u/1276859?v=4" width="100px;"/><br/><sub><b>ziyunfei</b></sub>](https://github.com/ziyunfei)<br/>|[<img src="https://avatars.githubusercontent.com/u/12656301?v=4" width="100px;"/><br/><sub><b>brizer</b></sub>](https://github.com/brizer)<br/>|[<img src="https://avatars.githubusercontent.com/u/7692708?v=4" width="100px;"/><br/><sub><b>xuezier</b></sub>](https://github.com/xuezier)<br/>|[<img src="https://avatars.githubusercontent.com/u/16103358?v=4" width="100px;"/><br/><sub><b>onlylovermb</b></sub>](https://github.com/onlylovermb)<br/>

This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Sat Aug 05 2023 01:46:53 GMT+0800`.
This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Mon Feb 19 2024 17:41:40 GMT+0800`.

<!-- GITCONTRIBUTOR_END -->
26 changes: 14 additions & 12 deletions README.zh-CN.md
Expand Up @@ -44,13 +44,14 @@ ctx.cookies.set('key', 'value', options);
- domain - `String` cookie 的有效域名范围,默认为 `undefined`
- expires - `Date` cookie 的失效时间。
- maxAge - `Number` cookie 的最大有效时间,如果设置了 maxAge,将会覆盖 expires 的值。
- secure - `Boolean` 是否只在加密信道中传输,注意,如果请求为 http 时,不允许设置为 true https 时自动设置为 true。
- partitioned - `Boolean` 是否设置独立分区状态([CHIPS](https://developers.google.com/privacy-sandbox/3pcd/chips))的 Cookie。注意,只有 `secure` 为 true 的时候此配置才会生效。
- removeUnpartitioned - `Boolean` 是否删除非独立分区状态的同名 cookie。注意,只有 `partitioned` 为 true 的时候此配置才会生效。
- httpOnly - `Boolean` 如果设置为 ture,则浏览器中不允许读取这个 cookie 的值。
- overwrite - `Boolean` 如果设置为 true,在一个请求上重复写入同一个 key 将覆盖前一次写入的值,默认为 false。
- signed - `Boolean` 是否需要对 cookie 进行签名,需要配合 get 时传递 signed 参数,此时前端无法篡改这个 cookie,默认为 true。
- encrypt - `Boolean` 是否需要对 cookie 进行加密,需要配合 get 时传递 encrypt 参数,此时前端无法读到真实的 cookie 值,默认为 false。
- secure - `Boolean` 是否只在加密信道中传输,注意,如果请求为 http 时,不允许设置为 `true`,https 时自动设置为 `true`
- partitioned - `Boolean` 是否设置独立分区状态([CHIPS](https://developers.google.com/privacy-sandbox/3pcd/chips))的 Cookie。注意,只有 `secure``true` 的时候此配置才会生效。
- removeUnpartitioned - `Boolean` 是否删除非独立分区状态的同名 cookie。注意,只有 `partitioned``true` 的时候此配置才会生效。
- httpOnly - `Boolean` 如果设置为 `true`,则浏览器中不允许读取这个 cookie 的值。
- overwrite - `Boolean` 如果设置为 `true`,在一个请求上重复写入同一个 key 将覆盖前一次写入的值,默认为 `false`
- signed - `Boolean` 是否需要对 cookie 进行签名,需要配合 get 时传递 signed 参数,此时前端无法篡改这个 cookie,默认为 `true`
- encrypt - `Boolean` 是否需要对 cookie 进行加密,需要配合 get 时传递 encrypt 参数,此时前端无法读到真实的 cookie 值,默认为 `false`
- priority - `String` 表示 cookie 优先级的字符串,可以设置为 `'low'`, `'medium'`, `'high'`,默认为 `undefined`[A Retention Priority Attribute for HTTP Cookies](https://datatracker.ietf.org/doc/html/draft-west-cookie-priority)

## 读取 cookie

Expand All @@ -66,15 +67,16 @@ ctx.cookies.set('key', 'value', options);
## License

[MIT](LICENSE)

<!-- GITCONTRIBUTOR_START -->

## Contributors
## 贡献者

|[<img src="https://avatars.githubusercontent.com/u/156269?v=4" width="100px;"/><br/><sub><b>fengmk2</b></sub>](https://github.com/fengmk2)<br/>|[<img src="https://avatars.githubusercontent.com/u/985607?v=4" width="100px;"/><br/><sub><b>dead-horse</b></sub>](https://github.com/dead-horse)<br/>|[<img src="https://avatars.githubusercontent.com/u/227713?v=4" width="100px;"/><br/><sub><b>atian25</b></sub>](https://github.com/atian25)<br/>|[<img src="https://avatars.githubusercontent.com/u/5856440?v=4" width="100px;"/><br/><sub><b>whxaxes</b></sub>](https://github.com/whxaxes)<br/>|[<img src="https://avatars.githubusercontent.com/u/5102113?v=4" width="100px;"/><br/><sub><b>xyeric</b></sub>](https://github.com/xyeric)<br/>|[<img src="https://avatars.githubusercontent.com/u/3939959?v=4" width="100px;"/><br/><sub><b>jedmeng</b></sub>](https://github.com/jedmeng)<br/>|
|[<img src="https://avatars.githubusercontent.com/u/156269?v=4" width="100px;"/><br/><sub><b>fengmk2</b></sub>](https://github.com/fengmk2)<br/>|[<img src="https://avatars.githubusercontent.com/u/985607?v=4" width="100px;"/><br/><sub><b>dead-horse</b></sub>](https://github.com/dead-horse)<br/>|[<img src="https://avatars.githubusercontent.com/u/32174276?v=4" width="100px;"/><br/><sub><b>semantic-release-bot</b></sub>](https://github.com/semantic-release-bot)<br/>|[<img src="https://avatars.githubusercontent.com/u/227713?v=4" width="100px;"/><br/><sub><b>atian25</b></sub>](https://github.com/atian25)<br/>|[<img src="https://avatars.githubusercontent.com/u/5856440?v=4" width="100px;"/><br/><sub><b>whxaxes</b></sub>](https://github.com/whxaxes)<br/>|[<img src="https://avatars.githubusercontent.com/u/5102113?v=4" width="100px;"/><br/><sub><b>xyeric</b></sub>](https://github.com/xyeric)<br/>|
| :---: | :---: | :---: | :---: | :---: | :---: |
|[<img src="https://avatars.githubusercontent.com/u/17005098?v=4" width="100px;"/><br/><sub><b>Junyan</b></sub>](https://github.com/Junyan)<br/>|[<img src="https://avatars.githubusercontent.com/u/12657964?v=4" width="100px;"/><br/><sub><b>beliefgp</b></sub>](https://github.com/beliefgp)<br/>|[<img src="https://avatars.githubusercontent.com/u/52845048?v=4" width="100px;"/><br/><sub><b>snapre</b></sub>](https://github.com/snapre)<br/>|[<img src="https://avatars.githubusercontent.com/u/360661?v=4" width="100px;"/><br/><sub><b>popomore</b></sub>](https://github.com/popomore)<br/>|[<img src="https://avatars.githubusercontent.com/u/32174276?v=4" width="100px;"/><br/><sub><b>semantic-release-bot</b></sub>](https://github.com/semantic-release-bot)<br/>|[<img src="https://avatars.githubusercontent.com/u/1276859?v=4" width="100px;"/><br/><sub><b>ziyunfei</b></sub>](https://github.com/ziyunfei)<br/>|
[<img src="https://avatars.githubusercontent.com/u/12656301?v=4" width="100px;"/><br/><sub><b>brizer</b></sub>](https://github.com/brizer)<br/>|[<img src="https://avatars.githubusercontent.com/u/7692708?v=4" width="100px;"/><br/><sub><b>xuezier</b></sub>](https://github.com/xuezier)<br/>|[<img src="https://avatars.githubusercontent.com/u/16103358?v=4" width="100px;"/><br/><sub><b>onlylovermb</b></sub>](https://github.com/onlylovermb)<br/>
|[<img src="https://avatars.githubusercontent.com/u/3939959?v=4" width="100px;"/><br/><sub><b>jedmeng</b></sub>](https://github.com/jedmeng)<br/>|[<img src="https://avatars.githubusercontent.com/u/17005098?v=4" width="100px;"/><br/><sub><b>Junyan</b></sub>](https://github.com/Junyan)<br/>|[<img src="https://avatars.githubusercontent.com/u/12657964?v=4" width="100px;"/><br/><sub><b>beliefgp</b></sub>](https://github.com/beliefgp)<br/>|[<img src="https://avatars.githubusercontent.com/u/52845048?v=4" width="100px;"/><br/><sub><b>snapre</b></sub>](https://github.com/snapre)<br/>|[<img src="https://avatars.githubusercontent.com/u/360661?v=4" width="100px;"/><br/><sub><b>popomore</b></sub>](https://github.com/popomore)<br/>|[<img src="https://avatars.githubusercontent.com/u/22520131?v=4" width="100px;"/><br/><sub><b>tang-xy</b></sub>](https://github.com/tang-xy)<br/>|
[<img src="https://avatars.githubusercontent.com/u/1276859?v=4" width="100px;"/><br/><sub><b>ziyunfei</b></sub>](https://github.com/ziyunfei)<br/>|[<img src="https://avatars.githubusercontent.com/u/12656301?v=4" width="100px;"/><br/><sub><b>brizer</b></sub>](https://github.com/brizer)<br/>|[<img src="https://avatars.githubusercontent.com/u/7692708?v=4" width="100px;"/><br/><sub><b>xuezier</b></sub>](https://github.com/xuezier)<br/>|[<img src="https://avatars.githubusercontent.com/u/16103358?v=4" width="100px;"/><br/><sub><b>onlylovermb</b></sub>](https://github.com/onlylovermb)<br/>

This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Sat Aug 05 2023 01:46:53 GMT+0800`.
[git-contributor 说明](https://github.com/xudafeng/git-contributor),自动生成时间:`Mon Feb 19 2024 17:41:40 GMT+0800`

<!-- GITCONTRIBUTOR_END -->
3 changes: 2 additions & 1 deletion benchmark/index.js
Expand Up @@ -2,9 +2,10 @@

const Benchmark = require('benchmark');
const benchmarks = require('beautify-benchmark');
const EggCookies = require('..');
const Cookies = require('cookies');
const Keygrip = require('keygrip');
const EggCookies = require('..');

const suite = new Benchmark.Suite();

const keys = [ 'this is a very very loooooooooooooooooooooooooooooooooooooong key' ];
Expand Down
4 changes: 4 additions & 0 deletions index.d.ts
Expand Up @@ -72,6 +72,10 @@ declare namespace EggCookies {
* Remove unpartitioned same name cookie or not.
*/
removeUnpartitioned?: boolean;
/**
* The cookie priority.
*/
priority?: 'low' | 'medium' | 'high';
}

class CookieError extends Error { }
Expand Down
24 changes: 18 additions & 6 deletions lib/cookie.js
Expand Up @@ -9,16 +9,19 @@ const assert = require('assert');
* field-vchar = VCHAR / obs-text
* obs-text = %x80-FF
*/

const fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/; // eslint-disable-line no-control-regex

/**
* RegExp to match Same-Site cookie attribute value.
* https://en.wikipedia.org/wiki/HTTP_cookie#SameSite_cookie
*/

const sameSiteRegExp = /^(?:none|lax|strict)$/i;

/**
* RegExp to match Priority cookie attribute value.
*/
const PRIORITY_REGEXP = /^(?:low|medium|high)$/i;

class Cookie {
constructor(name, value, attrs) {
assert(fieldContentRegExp.test(name), 'argument name is invalid');
Expand All @@ -27,12 +30,16 @@ class Cookie {
this.name = name;
this.value = value || '';
this.attrs = mergeDefaultAttrs(attrs);
assert(!this.attrs.path || fieldContentRegExp.test(this.attrs.path), 'argument option path is invalid');
assert(!this.attrs.path || fieldContentRegExp.test(this.attrs.path),
'argument option path is invalid');
if (typeof this.attrs.domain === 'function') {
this.attrs.domain = this.attrs.domain();
}
assert(!this.attrs.domain || fieldContentRegExp.test(this.attrs.domain), 'argument option domain is invalid');
assert(!this.attrs.sameSite || this.attrs.sameSite === true || sameSiteRegExp.test(this.attrs.sameSite), 'argument option sameSite is invalid');
assert(!this.attrs.domain || fieldContentRegExp.test(this.attrs.domain),
'argument option domain is invalid');
assert(!this.attrs.sameSite || this.attrs.sameSite === true || sameSiteRegExp.test(this.attrs.sameSite),
'argument option sameSite is invalid');
assert(!this.attrs.priority || PRIORITY_REGEXP.test(this.attrs.priority), 'argument option priority is invalid');
if (!value) {
this.attrs.expires = new Date(0);
// make sure maxAge is empty
Expand All @@ -56,6 +63,7 @@ class Cookie {
}
if (attrs.expires) header += '; expires=' + attrs.expires.toUTCString();
if (attrs.domain) header += '; domain=' + attrs.domain;
if (attrs.priority) header += '; priority=' + attrs.priority.toLowerCase();
if (attrs.sameSite) header += '; samesite=' + (attrs.sameSite === true ? 'strict' : attrs.sameSite.toLowerCase());
if (attrs.secure) header += '; secure';
if (attrs.httpOnly) header += '; httponly';
Expand All @@ -65,7 +73,10 @@ class Cookie {
}
}

const ATTRS = [ 'path', 'expires', 'domain', 'httpOnly', 'secure', 'partitioned', 'maxAge', 'overwrite', 'sameSite' ];
const ATTRS = [
'path', 'expires', 'domain', 'httpOnly', 'secure', 'partitioned', 'maxAge', 'overwrite', 'sameSite',
'priority',
];
function mergeDefaultAttrs(attrs) {
const merged = {
path: '/',
Expand All @@ -74,6 +85,7 @@ function mergeDefaultAttrs(attrs) {
overwrite: false,
sameSite: false,
partitioned: false,
priority: undefined,
};
if (!attrs) return merged;

Expand Down
6 changes: 3 additions & 3 deletions lib/cookies.js
Expand Up @@ -238,16 +238,16 @@ function parseChromiumAndMajorVersion(userAgent) {
return { chromium: true, majorVersion: parseInt(m[1]) };
}

const partternCache = new Map();
const _patternCache = new Map();
function getPattern(name) {
const cache = partternCache.get(name);
const cache = _patternCache.get(name);
if (cache) return cache;
const reg = new RegExp(
'(?:^|;) *' +
name.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') +
'=([^;]*)'
);
partternCache.set(name, reg);
_patternCache.set(name, reg);
return reg;
}

Expand Down
2 changes: 1 addition & 1 deletion test/cookies.js
@@ -1,7 +1,7 @@
'use strict';

const Cookies = require('..');
const EventEmitter = require('events');
const Cookies = require('..');

module.exports = (req, options, defaultCookieOptions) => {
options = options || {};
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/ts/cookiesTest.ts
Expand Up @@ -60,7 +60,7 @@ saveActualAnswer.test1.actualIndex = cookie.indexOf('bar');

// Test 2: should signed work fine
cookies = CreateCookie();
cookies.set('foo', 'bar', { signed: true });
cookies.set('foo', 'bar', { signed: true, priority: 'high' });
cookie = (<any>cookies).ctx.response.headers['set-cookie'].join(';');
(<any>cookies).ctx.request.headers.cookie = cookie;
value = cookies.get('foo', { signed: true });
Expand Down

0 comments on commit f9f1214

Please sign in to comment.