Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

jshttp

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jshttp - npm Package Compare versions

Comparing version
0.3.0
to
0.4.0
+5
-0
CHANGELOG.md
# 版本更新说明
## v0.4.0 - 2021.05.07
1. 新增配置项 `retry`,引入重试机制
2. 重构了调试日志功能
## v0.3.0 - 2021.05.06

@@ -4,0 +9,0 @@

+24
-1

@@ -91,2 +91,10 @@ 'use strict'

/**
* 重试次数
*
* 说明:
* 1. `0` 表示不重试
*/
retry: 0,
/**
* 是否开启调试模式

@@ -101,4 +109,19 @@ *

* 用于打印日志的函数
* @param {object} content 日志内容对象
* @param {number} content.status 响应状态码
* @param {string} content.url 请求地址
* @param {object} content.config 配置项
* @param {number} content.startTime 发起请求任务时间(时间戳)
* @param {number} content.endTime 结束请求任务时间(时间戳)
* @param {number} content.requestTime 本次发起请求时间(时间戳)
* @param {number} content.responseTime 本次结束响应时间(时间戳)
* @param {string} content.startTimeText 发起请求任务时间(文本格式)
* @param {string} content.endTimeText 结束请求任务时间(文本格式)
* @param {string} content.requestTimeText 本次发起请求时间(文本格式)
* @param {string} content.responseTimeText 本次结束响应时间(文本格式)
*/
logging: console.log,
logging: function logging(content) {
const message = `${content.startTimeText} ${content.responseTime - content.requestTime}ms ${content.config.method} ${content.url} ${content.status}`
console.log(message)
},

@@ -105,0 +128,0 @@ /*********************************** 对象类配置 **********************************/

@@ -29,2 +29,3 @@ 'use strict'

'timeout',
'retry',
'mock',

@@ -35,2 +36,3 @@ 'adapter',

'responseItems',
'validateStatus',
'sign',

@@ -37,0 +39,0 @@ 'debug',

@@ -159,2 +159,14 @@ 'use strict'

/**
* 配置项 `retry`
*
* 规则:
* 1. 非负整数
*/
if (config.retry !== undefined) {
if (!(Number.isInteger(config.retry) && config.retry >= 0)) {
throw new Error('配置项 `retry` 要求是一个非负整数(0,1,2,...)')
}
}
/**
* 配置项 `headers`

@@ -161,0 +173,0 @@ *

@@ -101,10 +101,10 @@ 'use strict'

/**
* 发起请求
* @param {object} config 配置项
* 发起请求(包含重试逻辑)
*/
async request(...args) {
// 整理参数,生成标准格式的 `config`
const customConfig = buildConfig(...args)
const config = mergeConfig(baseConfig, this.defaults, normalizeConfig(customConfig))
const context = new Context(config)
// 加入 `签名中间件`
const signFn = this.getSignMiddleware(config)

@@ -115,2 +115,49 @@ if (signFn) {

/** 最大重试次数 */
let retry = config.retry
/** 已重试次数 */
let retries = -1
/** 检验成功请求函数 */
const validateStatus = config.validateStatus
/** 响应结果列表 */
const responses = []
while (retry >= 0) {
retry--
retries++
const result = await this.execSingleRequest(config, retries)
responses.push(result)
if (validateStatus(result.status)) {
// 返回响应结果
const { responseItems } = config
const output = {}
responseItems.forEach((key) => {
if (typeof key === 'string') {
output[key] = result[key]
} else if (typeof key === 'object') {
const { item, alias } = key
output[alias] = result[item]
} else {
throw new Error('配置项 `responseItems` 格式错误')
}
})
if (responseItems.includes('responses')) {
output.responses = responses
}
return output
}
}
throw new Error(responses[responses.length - 1])
}
/**
* 执行单次请求
*/
async execSingleRequest(config, retries) {
const context = new Context(config)
context.retries = retries
const fn = this.createPipeline(config.middleware)

@@ -117,0 +164,0 @@ return await fn(context)

@@ -5,2 +5,3 @@ 'use strict'

const mockAdapter = require('../adapters/mock.js')
const STATE = Symbol('context#state')

@@ -14,5 +15,49 @@ module.exports = class Context {

this.adapter = config.mock && typeof config.mock === 'object' ? mockAdapter : config.adapter
/** 公共存储空间 */
this[STATE] = {}
}
/**
* 以指定名称存储当前时间
* @param {string} name 名称
*/
setTime(name) {
/**
* 辅助函数:对数字补零到指定位数
* @param {number} number 被格式化的数字
* @param {number} digit 格式化的位数
* @returns {string}
*/
function zerofill(number, digit = 2) {
const zero = '0'
for (let i = 0; i < digit; i++) {
if (number < Math.pow(10, i + 1)) {
const str = zero.repeat(digit - i - 1) + number.toString()
return str
}
}
return number
}
const time = new Date()
const year = time.getFullYear()
const month = zerofill(time.getMonth())
const day = zerofill(time.getDate())
const hour = zerofill(time.getHours())
const minute = zerofill(time.getMinutes())
const second = zerofill(time.getSeconds())
const millisecond = zerofill(time.getMilliseconds(), 3)
const str = `${year}-${month}-${day} ${hour}:${minute}:${second}.${millisecond}`
this[STATE][name] = time.getTime()
this[STATE][name + 'Text'] = str
}
get state() {
return this[STATE]
}
/**
* 用于在中间件中快速获取 `url`

@@ -75,2 +120,34 @@ */

}
/**
* 合成打印日志所需的内容
* @returns {object} content 日志内容对象
* @returns {number} content.status 响应状态码
* @returns {string} content.url 请求地址
* @returns {object} content.config 配置项
* @returns {number} content.startTime 发起请求任务时间(时间戳)
* @returns {number} content.endTime 结束请求任务时间(时间戳)
* @returns {number} content.requestTime 本次发起请求时间(时间戳)
* @returns {number} content.responseTime 本次结束响应时间(时间戳)
* @returns {string} content.startTimeText 发起请求任务时间(文本格式)
* @returns {string} content.endTimeText 结束请求任务时间(文本格式)
* @returns {string} content.requestTimeText 本次发起请求时间(文本格式)
* @returns {string} content.responseTimeText 本次结束响应时间(文本格式)
*/
getLoggingContent() {
const ctx = this
return {
status: ctx.response.status,
url: ctx.url,
config: ctx.config,
startTime: ctx.state.startTime,
endTime: ctx.state.endTime,
requestTime: ctx.state.requestTime,
responseTime: ctx.state.responseTime,
startTimeText: ctx.state.startTimeText,
endTimeText: ctx.state.endTimeText,
requestTimeText: ctx.state.requestTimeText,
responseTimeText: ctx.state.responseTimeText,
}
}
}

@@ -9,3 +9,10 @@ 'use strict'

module.exports = async function dispatch(ctx) {
// 记录发起请求时间
ctx.setTime('requestTime')
const result = await ctx.adapter(ctx.config)
// 记录完成请求时间
ctx.setTime('responseTime')
ctx.response = new Response(result)

@@ -12,0 +19,0 @@ ctx.request = result.request

+18
-21

@@ -7,29 +7,26 @@ 'use strict'

module.exports = async function initialize(ctx, next) {
/** 请求开始时间 */
const startTime = Date.now()
// 记录本次请求任务开始时间
ctx.setTime('startTime')
await next()
/** 请求结束时间 */
const endTime = Date.now()
const cost = endTime - startTime
// 记录本次请求任务结束时间
ctx.setTime('endTime')
// 打印日志
if (ctx.config.debug && typeof ctx.config.logging === 'function') {
const message = `[${ctx.response.status}] ${ctx.config.method} ${ctx.url} ${cost}ms `
ctx.config.logging(message)
const content = ctx.getLoggingContent()
ctx.config.logging(content)
}
// 返回响应结果
const { responseItems } = ctx.config
const output = {}
responseItems.forEach((key) => {
if (typeof key === 'string') {
output[key] = ctx.response[key]
} else if (typeof key === 'object') {
const { item, alias } = key
output[alias] = ctx.response[item]
} else {
throw new Error('配置项 `responseItems` 格式错误')
}
})
return output
return {
status: ctx.response.status,
statusText: ctx.response.statusText,
headers: ctx.response.headers,
data: ctx.response.data,
request: ctx.response.request,
url: ctx.url,
config: ctx.config,
}
}
{
"name": "jshttp",
"version": "0.3.0",
"version": "0.4.0",
"description": "能在任何 Javascript 环境使用的 HTTP 请求库,支持 Node.js,浏览器,微信小程序,支付宝小程序,百度小程序 ...",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -205,2 +205,9 @@ # jshttp

/**
* 重试次数
*
* 使用 `validateStatus` 方法对响应结果进行校验,校验不通过则重试。建议配置中间件的 `ctx.retries` (当前重试次数)属性操作,当其大于 0 时,进行若干操作。
*/
retry: 0,
/****************** 以下配置项一般情况下不需要额外设置,使用默认值即可 *********************/

@@ -207,0 +214,0 @@