Skip to content

Commit

Permalink
feat: add methods for server
Browse files Browse the repository at this point in the history
  • Loading branch information
qiqiboy committed Apr 28, 2020
1 parent 651c7d9 commit 88003ce
Show file tree
Hide file tree
Showing 16 changed files with 386 additions and 105 deletions.
72 changes: 60 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ A simple utilities for browser cookies APIs
- [`setCookie`](#setcookie)
- [`delCookie`](#delcookie)
- [`getAllCookies`](#getallcookies)
- [`serialize`](#serialize)
- [`setDefault`](#setdefault)
- [`updateCookieSource`](#updatecookiesource)
* [参考文档](#参考文档)
- [document.cookie MDN 规范说明](#documentcookie-mdn-规范说明)
- [`maxAge` `sameSite`等新属性的兼容性](#maxage-samesite等新属性的兼容性)
Expand All @@ -37,16 +39,6 @@ A simple utilities for browser cookies APIs

而直到我发现了 [jshttp/cookie](https://github.com/jshttp/cookie) 这个标准库,虽然其是针对 `HTTP cookies` 规范定制,但是可以几乎完整适用于浏览器端。所以我基于该库做了稍微的修改定制,也就有了现在这个 `cookick`(名字由 `cookie``kick` 组合而来)

**补充与[`universal-cookie`](https://github.com/reactivestack/cookies/tree/master/packages/universal-cookie)的对比:**

> `universal-cookie`是我阅读`react-cookie`时发现的这个库(当然,我认为任何 react/vue-cookie 这种库都不应该存在,作者都是被驴踢了脑袋),非常意外的发现其实现思路与`cookick`惊人一致。如果我早两个小时前发现这个库,cookick 就不会产生了。但是我也在阅读了 `universal-cookie`的源码后,基于以下的几点不同,我还是倾向于 `cookick` 是一个更好的实现
- `universal-cookie``cookick`都是基于`jsHTTP/cookie`实现,所以两者对于 cookie 的操作都是一致的,并且操作 cookie 的方式、对标准的支持也都是一致的
- `cookick``path`做了更多支持优化,默认为根路径: `/`,也支持相对路径;`universal-cookie` 则是默认行为,即当前页面路径。经验来看,默认`/`还是更符合通用场景的
- `cookick` 更加适合 `ES Module` 规范下的子导出使用,因为其方法名都是明确的 cookie 相关命名,例如`getCookie` `setCookie`等;而`universal-cookie`这是简洁的`get` `set`等名称,只适合与对象访问式调用
- `universal-cookie`考虑了服务端调用,所以其使用需要先初始化后调用、还支持绑定 cookie 变动监听;`cookick`没有这些考虑,并且认为服务端使用应当直接使用`jsHTTP/cookie`,而 cookie 变动监听属于过度设计,在 cookie 在 web 开发中日渐式微的状况下,这种设计“纯属想多了”
- `universal-cookie` 名字很长,`cookick`名字较短

## 安装

[![cookick](https://nodei.co/npm/cookick.png?compact=true)](https://npm.im/cookick)
Expand Down Expand Up @@ -82,12 +74,16 @@ $ yarn add cookick

> 注:在`create-react-app`或者`vue-cli`构建的项目中,都是可以安全运行`cookick`的。
> `cookick`也可以在服务端中运行,但是不推荐。建议优先选择其它与服务端框架结合更紧密的其它 cookie 方法,例如 Express.js 推荐的 `cookie-parser`
## 如何使用

`cookick`提供了一组方法用于获取或者设置 cookie。

### `getCookie`

> 服务端在调用该方法前,需要先调用 [`updateCookieSource`](#updatecookiesource) 设置 cookie 解析来源。
```typescript
declare function getCookie(name: string): string | undefined;
```
Expand All @@ -102,6 +98,8 @@ getCookie('foo'); // 获取名称为 foo 的cookie

### `setCookie`

> 仅在浏览器端生效,服务端应当利用其返回值自行设置响应头来处理 cookie。
```typescript
interface CookieOptions {
path?: string;
Expand All @@ -113,7 +111,7 @@ interface CookieOptions {
sameSite?: boolean | 'lax' | 'strict' | 'none';
}

declare function setCookie(name: string, val: string | number, options?: CookieOptions): void;
declare function setCookie(name: string, val: string | number, options?: CookieOptions): string;
```

使用示例:
Expand Down Expand Up @@ -148,12 +146,23 @@ setCookie('foo', 'bar', {
httpOnly: true,
sameSite: 'strict'
});

/*=================服务端==================*/
req.setHeader('set-cookie', setCookie('foo', 'bar'));
```

### `delCookie`

> 仅在浏览器端生效,服务端应当利用其返回值自行设置响应头来处理 cookie。
```typescript
declare function delCookie(name: string, options?: CookieOptions): void;
declare function delCookie(
name: string,
options?: {
path?: string;
domain?: string;
}
): string;
```

使用示例:
Expand All @@ -167,10 +176,15 @@ delCookie('foo'); // 删除名称为 foo 的cookie
delCookie('foo', {
path: '/sub'
});

/*=================服务端==================*/
req.setHeader('set-cookie', delCookie('foo'));
```

### `getAllCookies`

> 服务端在调用该方法前,需要先调用 [`updateCookieSource`](#updatecookiesource) 设置 cookie 解析来源。
```typescript
declare function getAllCookies(): {
[P: string]: string | undefined;
Expand All @@ -185,6 +199,26 @@ import { getAllCookies } from 'cookick';
getAllCookies(); // 解析所有的cookie为一个object对象
```

### `serialize`

```typescript
declare function serialize(name: string, val: string | number, options?: CookieOptions): string;
```

序列化一个新的 cookie 为字符串,你可以将其用于在服务端或者浏览器端设置 cookie:

```typescript
const newCookieStr = serialize('foo', 'bar', {
path: '/'
});

// 浏览器端
document.cookie = newCookieStr;

// 服务端
response.setHeader('set-cookie', newCookieStr);
```

### `setDefault`

设置默认参数
Expand All @@ -205,6 +239,20 @@ setDefault({
});
```

### `updateCookieSource`

该方法建议仅在服务端调用,在调用`getCookie` `getAllCookies`等方法前,通过该方法将服务端请求的 cookie 字符串更新到`cookick`

```typescript
const { updateCookieSource, getCookie } = require('cookick');

app.get('/', (req, res) => {
udpateCookieSource(req.headers.cookie);

console.log(getCookie('foo'));
});
```

## 参考文档

### document.cookie MDN 规范说明
Expand Down
36 changes: 31 additions & 5 deletions dist/cookick.cjs.development.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,39 +221,65 @@ function getAbsolute(path) {
}

var defaultOptions = {};
var isBrowser = typeof document === 'object';
var cookieSource = '';
var hasSetSource = false;
function getCookie(name) {
var cookies = getAllCookies();
return cookies[name];
}
function setCookie(name, val, options) {
if (typeof document === 'object') {
document.cookie = serialize(name, val, _objectSpread({}, defaultOptions, {}, options));
var cookie = serialize$1(name, val, options);

if (isBrowser) {
document.cookie = cookie;
}

return cookie;
}
function delCookie(name, options) {
setCookie(name, '', _objectSpread({}, options, {
return setCookie(name, '', _objectSpread({}, options, {
expires: new Date(1970)
}));
}
function getAllCookies() {
return parse(typeof document === 'object' ? document.cookie || '' : '');
if (isBrowser) {
return parse(cookieSource || document.cookie || '');
}

if ( !hasSetSource) {
console.error("Warning: You should call 'updateCookieSource(request.cookie)' first.");
}

return parse(cookieSource || '');
}
function serialize$1(name, val, options) {
return serialize(name, val, _objectSpread({}, defaultOptions, {}, options));
}
function setDefault(options) {
return Object.assign(defaultOptions, options);
}
function updateCookieSource(cookie) {
cookieSource = cookie;
hasSetSource = true;
}

var COOKIE = /*#__PURE__*/Object.freeze({
__proto__: null,
getCookie: getCookie,
setCookie: setCookie,
delCookie: delCookie,
getAllCookies: getAllCookies,
setDefault: setDefault
serialize: serialize$1,
setDefault: setDefault,
updateCookieSource: updateCookieSource
});

exports.default = COOKIE;
exports.delCookie = delCookie;
exports.getAllCookies = getAllCookies;
exports.getCookie = getCookie;
exports.serialize = serialize$1;
exports.setCookie = setCookie;
exports.setDefault = setDefault;
exports.updateCookieSource = updateCookieSource;
2 changes: 1 addition & 1 deletion dist/cookick.cjs.production.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 30 additions & 6 deletions dist/cookick.esm.development.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,35 +215,59 @@ function getAbsolute(path) {
}

var defaultOptions = {};
var isBrowser = typeof document === 'object';
var cookieSource = '';
var hasSetSource = false;
function getCookie(name) {
var cookies = getAllCookies();
return cookies[name];
}
function setCookie(name, val, options) {
if (typeof document === 'object') {
document.cookie = serialize(name, val, _objectSpread({}, defaultOptions, {}, options));
var cookie = serialize$1(name, val, options);

if (isBrowser) {
document.cookie = cookie;
}

return cookie;
}
function delCookie(name, options) {
setCookie(name, '', _objectSpread({}, options, {
return setCookie(name, '', _objectSpread({}, options, {
expires: new Date(1970)
}));
}
function getAllCookies() {
return parse(typeof document === 'object' ? document.cookie || '' : '');
if (isBrowser) {
return parse(cookieSource || document.cookie || '');
}

if ( !hasSetSource) {
console.error("Warning: You should call 'updateCookieSource(request.cookie)' first.");
}

return parse(cookieSource || '');
}
function serialize$1(name, val, options) {
return serialize(name, val, _objectSpread({}, defaultOptions, {}, options));
}
function setDefault(options) {
return Object.assign(defaultOptions, options);
}
function updateCookieSource(cookie) {
cookieSource = cookie;
hasSetSource = true;
}

var COOKIE = /*#__PURE__*/Object.freeze({
__proto__: null,
getCookie: getCookie,
setCookie: setCookie,
delCookie: delCookie,
getAllCookies: getAllCookies,
setDefault: setDefault
serialize: serialize$1,
setDefault: setDefault,
updateCookieSource: updateCookieSource
});

export default COOKIE;
export { delCookie, getAllCookies, getCookie, setCookie, setDefault };
export { delCookie, getAllCookies, getCookie, serialize$1 as serialize, setCookie, setDefault, updateCookieSource };
Loading

0 comments on commit 88003ce

Please sign in to comment.