import CONSTANT from './CONSTANT'
import {
Toast } from 'antd-mobile'
import {
getAppLogin, isNetworkConnected, showNoNetPage} from '../utils/getAppApi'
import {
history } from '../utils/history'
import * as Sentry from '@sentry/browser'
import {
redirectSSO} from "../utils/Utility"
window.requestDict = window.requestDict || {
}
let status200 = false
const Loading = (flag, loadingClass) => {
if (loadingClass && document.getElementsByClassName(loadingClass)[0]) {
const elm = document.getElementsByClassName(loadingClass)[0]
if (flag && !elm.className.includes('loading_md')) {
elm.className += ' loading_md '
} else {
elm.className = elm.className.replace('loading_md', '')
}
}
}
const clear401Data = () => {
const clearData = ['userInfo', 'wechatFree', 'token']
clearData.forEach(data => localStorage.removeItem(data))
}
const handleRequest = (config) => {
Loading(true, config.loadingClass)
return config
}
const handleResponseHeader = (headers, rep, statusCode) => {
if (window.isApp) {
return rep
}
if (!headers) {
clear401Data()
}
if (rep.status == 200) {
status200 = true
return rep
} else if (rep.status >= 500) {
Sentry.setExtra('fetch_data', rep)
Sentry.captureMessage('fetch_500_error')
if(!statusCode) history.push('/serverError')
} else if (rep.status == 401) {
clear401Data()
redirectSSO('replace','/')
} else {
Sentry.setExtra('fetch_data', rep)
Sentry.captureMessage('fetch_400_error')
if(!statusCode) history.push('/errorPage')
}
}
const handleResponse = (res, config) => {
const reponseCode = config.reponseCode
if (res.code !== '00' && process.env.SENTRY) {
Sentry.setExtra('fetch_data', {
url: config.newUrl, ...res})
Sentry.captureMessage('fetch_200_error')
}
if (reponseCode) {
return res
} else if (res.code === '00' || res.status == 200) {
if (window.isApp) {
res.data && res.data.oneid && res.data.oneid.accessToken && window.localStorage.setItem('token', res.data.oneid.accessToken)
} else {
res.data && res.data.accessToken && window.localStorage.setItem('token', res.data.accessToken)
}
return res.data
} else {
Toast.info(res.message, 2)
}
}
let defaultHeaders = {
'Accept': 'application/json',
'Content-Type': 'application/json;charset=utf-8'
}
function request(config, hasResend = 0) {
let {
url, body, method, header, dnsType, loadingClass, reponseCode, type = "", cache, browsercachelevel, statusCode } = config
if (cache && method === "GET" && window.requestDict[url]) {
return window.requestDict[url]
}
let newUrl = CONSTANT.BaseURL + (url[0] == "/" ? url.substr(1) : url)
let headers
if (dnsType === "carConfig") {
headers = Promise.resolve({
channelId: "cop_mobile", "Content-Type": "application/json" })
} else if (dnsType === "codeToken") {
newUrl = CONSTANT.BasecodeTokenURL + (url[0] == "/" ? url.substr(1) : url)
headers = Promise.resolve({
"Content-Type": "application/json" })
} else {
headers = Promise.resolve({
...defaultHeaders, 'X-Channel': window.isApp ? '1002' : '1000', 'X-Access-Token': localStorage.getItem('token') || '', ...header })
}
const ret = headers.then(headers => {
handleRequest({
url: newUrl, loadingClass, reponseCode })
status200 = false
if (window.fetch) {
const requestConfig = {
credentials: "same-origin",
method: method || "GET",
headers,
mode: "cors",
cache: browsercachelevel || 'default'
}
if (method === "POST" || method === "PUT") {
Object.defineProperty(requestConfig, "body", {
value: type === 'file' ? body : JSON.stringify(body)
})
if (type === 'file') {
delete requestConfig.headers["Content-Type"]
}
}
return new Promise((resolve, reject) => {
fetch(newUrl, requestConfig)
.then(response => {
Loading(false, loadingClass)
const rep = handleResponseHeader(response.headers.get('x-token-expired'), response, statusCode)
return rep.json()
}, error => {
console.error('fetch_error: ', error)
if(window.isApp) {
isNetworkConnected().then(res => {
showNoNetPage(!res.isConnected)
})
} else {
if(!navigator.onLine) history.push('/notNetwork?fetch')
}
})
.then(res => {
if (window.isApp && res.code === '40101' && hasResend < 1) {
reject('resend')
} else {
resolve(handleResponse(res, {
url, newUrl, _cache: cache, method, loadingClass, reponseCode }))
}
}, error => {
if (error.response) {
reject(error.response.data)
} else {
reject(error)
}
console.error(error)
})
})
} else {
return new Promise((resolve, reject) => {
let requestObj
if (window.XMLHttpRequest) {
requestObj = new XMLHttpRequest()
} else {
requestObj = new ActiveXObject()
}
const sendData = JSON.stringify(body)
requestObj.open(method, newUrl, true)
Object.keys(headers).forEach(key => {
requestObj.setRequestHeader(key, headers[key])
})
requestObj.send(sendData)
requestObj.onreadystatechange = () => {
Loading(false, loadingClass)
if (requestObj.readyState === 4) {
const rep = handleResponseHeader(requestObj.getResponseHeader('x-token-expired'), requestObj, statusCode)
if (rep && requestObj.status === 200) {
let obj = requestObj.response
if (typeof obj !== "object") {
obj = JSON.parse(obj)
}
resolve(handleResponse(obj, {
url, _cache: cache, method, loadingClass, reponseCode }))
} else {
console.log(requestObj)
reject(requestObj)
}
}
}
})
}
})
if (cache && method === "GET" && status200) {
window.requestDict[url] = ret
}
return ret
}
export default function sendRequest(config) {
return new Promise(function(resolve, rejected){
request(config).then(r => {
resolve(r)
}).catch(err => {
if(window.isApp && err === 'resend') {
getAppLogin().then(t => {
if(t) {
config.cache = false
config.browsercachelevel = 'reload'
request(config, 1).then(res => {
resolve(res)
}).catch(e => {
console.log('resend request error: ', e)
})
} else {
rejected('error in getAppLogin')
}
})
} else {
rejected(err)
}
})
})
}