196 lines
5.5 KiB
JavaScript

// import needle from 'needle'
// import progress from 'request-progress'
import BackgroundTimer from 'react-native-background-timer'
import { debugRequest } from './env'
import { requestMsg } from './message'
import { bHh } from './music/options'
import { deflateRaw } from 'pako'
const defaultHeaders = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
}
// var proxyUrl = "http://" + user + ":" + password + "@" + host + ":" + port;
// var proxiedRequest = request.defaults({'proxy': proxyUrl});
/**
* 请求超时自动重试
* @param {*} url
* @param {*} options
*/
export const httpFetch = (url, options = { method: 'get' }) => {
const requestObj = fetchData(url, options)
return {
promise: requestObj.request.catch(err => {
console.log('出错', err.message)
switch (err.message) {
case 'socket hang up':
return Promise.reject(new Error(requestMsg.unachievable))
case 'Aborted':
return Promise.reject(new Error(requestMsg.timeout))
case 'Network request failed':
return Promise.reject(new Error(requestMsg.notConnectNetwork))
default:
return Promise.reject(err)
}
}),
cancelHttp() {
requestObj.abort()
},
}
}
/**
* http get 请求
* @param {*} url 地址
* @param {*} options 选项
* @param {*} callback 回调
* @return {Number} index 用于取消请求
*/
export const httpGet = (url, options, callback) => {
if (typeof options === 'function') {
callback = options
options = {}
}
const requestObj = fetchData(url, { ...options, method: 'get' })
requestObj.request.then(resp => {
callback(null, resp, resp.body)
}).catch(err => {
debugRequest && console.log(JSON.stringify(err))
callback(err, null, null)
})
return () => {
requestObj.abort()
}
}
/*
const fetchWithTimeout = (resource, options) => {
const { timeout = 8000 } = options
const controller = new global.AbortController()
const id = BackgroundTimer.setTimeout(() => controller.abort(), timeout)
return {
request: global.fetch(resource, {
...options,
signal: controller.signal,
}).then(response => {
BackgroundTimer.clearTimeout(id)
return response
}),
abort() {
controller.abort()
},
}
} */
const handleDeflateRaw = data => new Promise((resolve, reject) => {
resolve(Buffer.from(deflateRaw(data)))
// deflateRaw(data, (err, buf) => {
// if (err) return reject(err)
// resolve(buf)
// })
})
const regx = /(?:\d\w)+/g
const handleRequestData = async(url, {
method = 'get',
headers = {},
format = 'json',
cache = 'no-store',
...options
}) => {
// console.log(url, options)
headers = Object.assign({
Accept: 'application/json',
}, headers)
options.cache = cache
if (method.toLocaleLowerCase() === 'post' && !headers['Content-Type']) {
if (options.form) {
headers['Content-Type'] = 'application/x-www-form-urlencoded'
const formBody = []
for (let [key, value] of Object.entries(options.form)) {
let encodedKey = encodeURIComponent(key)
let encodedValue = encodeURIComponent(value)
formBody.push(`${encodedKey}=${encodedValue}`)
}
options.body = formBody.join('&')
delete options.form
} else if (options.formData) {
headers['Content-Type'] = 'multipart/form-data'
const formBody = []
for (let [key, value] of Object.entries(options.form)) {
let encodedKey = encodeURIComponent(key)
let encodedValue = encodeURIComponent(value)
formBody.push(`${encodedKey}=${encodedValue}`)
}
options.body = options.formData
delete options.formData
} else {
headers['Content-Type'] = 'application/json'
}
}
if (headers['Content-Type'] === 'application/json' && options.body) {
options.body = JSON.stringify(options.body)
}
if (headers[bHh]) {
let s = Buffer.from(bHh, 'hex').toString()
s = s.replace(s.substr(-1), '')
s = Buffer.from(s, 'base64').toString()
const v = process.versions.app.split('-')[0].split('.').map(n => n.length < 3 ? n.padStart(3, '0') : n).join('')
const v2 = process.versions.app.split('-')[1] || ''
headers[s] = !s || `${(await handleDeflateRaw(Buffer.from(JSON.stringify(`${url}${v}`.match(regx), null, 1).concat(v)).toString('base64'))).toString('hex')}&${parseInt(v)}${v2}`
delete headers[bHh]
}
return {
...options,
method,
headers: Object.assign({}, defaultHeaders, headers),
}
}
const fetchData = (url, { timeout = 15000, ...options }) => {
console.log('---start---', url)
const controller = new global.AbortController()
const id = BackgroundTimer.setTimeout(() => controller.abort(), timeout)
return {
request: handleRequestData(url, options).then(options => {
return global.fetch(url, {
...options,
signal: controller.signal,
}).then(response => {
BackgroundTimer.clearTimeout(id)
return response
}).then(resp => resp.text().then(text => {
// console.log(options, headers, text)
return {
headers: resp.headers.map,
body: text,
statusCode: resp.status,
url: resp.url,
ok: resp.ok,
}
})).then(resp => {
try {
resp.body = JSON.parse(resp.body)
} catch (_) {
}
return resp
}).catch(err => {
// console.log(err, err.code, err.message)
return Promise.reject(err)
})
}),
abort() {
controller.abort()
},
}
}