增加cookie支持

v1 1.3.0
宇天 2020-09-21 17:53:21 +08:00
parent a0ca0620ef
commit d3ad579b4d
4 changed files with 156 additions and 32 deletions

View File

@ -138,7 +138,7 @@ response.location('/foo')
let html = fs.readFileSync('./index.html') let html = fs.readFileSync('./index.html')
response.render(html) // send from a html file. response.render(html) // send from a html file.
let txt = '<h1>hello doJS</h1>' let txt = '<h1>hello world</h1>'
response.render(txt) response.render(txt)
response.render("You're not able to here", 401) response.render("You're not able to here", 401)
@ -189,3 +189,12 @@ response.send(200, 'success', { name: 'foo', age: 16 }, 'blabla')
* data `<String>` | `<Buffer>` optional * data `<String>` | `<Buffer>` optional
> 向客户端输出内容。 > 向客户端输出内容。
### cookie(key, value, options)
* key `<String>`
* value `<String>`
* options `<Object>` 额外配置[可选]
> 向客户端写入cookies。

View File

@ -5,6 +5,7 @@
import fs from 'iofs' import fs from 'iofs'
import STATUS_TEXT from './lib/http-code.js' import STATUS_TEXT from './lib/http-code.js'
import { serialize } from './lib/cookie.js'
export default class Response { export default class Response {
constructor(req, res) { constructor(req, res) {
@ -34,34 +35,6 @@ export default class Response {
this.statusCode = code this.statusCode = code
} }
/**
* [append 往header插入信息]
* @param {String} key [description]
* @param {String} val [description]
*/
append(key, val) {
if (this.rendered) {
return
}
var prev = this.get(key)
var value
if (Array.isArray(val)) {
value = val
} else {
value = [val]
}
if (prev) {
if (Array.isArray(prev)) {
value = prev.concat(val)
} else {
value = [prev].concat(val)
}
}
return this.set(key, value)
}
/** /**
* [redirect 页面跳转] * [redirect 页面跳转]
* @param {String} url [要跳转的URL] * @param {String} url [要跳转的URL]
@ -148,8 +121,14 @@ export default class Response {
return return
} }
if (typeof code !== 'number') { if (typeof code !== 'number') {
if (typeof code === 'object') {
data = code
code = 200
msg = STATUS_TEXT[code]
} else {
msg = code + '' msg = code + ''
code = 400 code = 400
}
} else if (typeof msg === 'object') { } else if (typeof msg === 'object') {
data = msg data = msg
code = code || 200 code = code || 200
@ -222,4 +201,62 @@ export default class Response {
} }
return this return this
} }
/**
* [append 往header插入信息]
* @param {String} key [description]
* @param {String} val [description]
*/
append(key, val) {
if (this.rendered) {
return
}
var prev = this.get(key)
var value
if (Array.isArray(val)) {
value = val
} else {
value = [val]
}
if (prev) {
if (Array.isArray(prev)) {
value = prev.concat(val)
} else {
value = [prev].concat(val)
}
}
return this.set(key, value)
}
/**
* [set 设置cookie]
* @param {[string]} key
* @param {[string/number]} val
* @param {[object]} opts [设置cookie的额外信息,如域,有效期等]
*/
cookie(key, val, opts = {}) {
//读取之前已经写过的cookie缓存
var cache = this.get('set-cookie')
if (cache) {
if (!Array.isArray(cache)) {
cache = [cache]
}
} else {
cache = []
}
if (cache.length > 0) {
// 如果之前已经写了一个相同的cookie, 则删除之前的
cache = cache.filter(it => {
let _key = it.split('=')[0].trim()
return key !== _key
})
}
cache.push(serialize(key, val, opts))
this.set('set-cookie', cache)
}
} }

78
lib/cookie.js Normal file
View File

@ -0,0 +1,78 @@
/**
* @author yutent<yutent.io@gmail.com>
* @date 2020/09/20 15:08:50
*/
var KEY_REGEXP = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/
// var SPLIT_REGEXP = /; */
var encode = encodeURIComponent
// var decode = decodeURIComponent
/**
* [serialize 序列化对象]
*/
export function serialize(key, val, opts) {
var pairs = []
if (!KEY_REGEXP.test(key)) {
return ''
}
val = encode(val)
opts = opts || {}
if (val && !KEY_REGEXP.test(val)) {
return ''
}
pairs.push(key + '=' + val)
if (opts.hasOwnProperty('expires') && opts.expires) {
// pairs.push('Expires=' + opts.expires.toUTCString())
// 有效期, 已不建议使用,改用 max-age
if (Date.isDate(opts.expires)) {
opts.maxAge = ~~(opts.expires.getTime() / 1000)
} else {
opts.maxAge = +opts.expires
}
delete opts.expires
}
if (opts.hasOwnProperty('maxAge') && opts.maxAge) {
//有效期
opts.maxAge = opts.maxAge
pairs.push('Max-Age=' + opts.maxAge)
}
if (opts.hasOwnProperty('domain')) {
//域
if (!KEY_REGEXP.test(opts.domain)) {
return ''
}
pairs.push('Domain=' + opts.domain)
}
if (opts.hasOwnProperty('path')) {
//目录
if (!KEY_REGEXP.test(opts.path)) {
return ''
}
pairs.push('Path=' + opts.path)
} else {
pairs.push('Path=/')
}
if (opts.httpOnly) {
pairs.push('HttpOnly')
}
if (opts.secure) {
pairs.push('Secure')
}
if (opts.firstPartyOnly) {
pairs.push('First-Party-Only')
}
return pairs.join('; ')
}

View File

@ -1,6 +1,6 @@
{ {
"name": "@gm5/response", "name": "@gm5/response",
"version": "1.2.0", "version": "1.3.0",
"type": "module", "type": "module",
"description": "对Http的response进一步封装, 提供常用的API", "description": "对Http的response进一步封装, 提供常用的API",
"main": "index.js", "main": "index.js",