| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- // Create axios instance
- import { APP_GAME_APK, APP_LOGIN, APP_LOG, BASE_API } from "./config";
- import axios from "axios";
- import { getHttpMsg, getUrlParam, isDebugEnv, localStorageGet, localStorageSet } from "@utils/helpers";
- import { LOCAL_ACTIVITY_C, LOCAL_IS_LOGIN, LOCAL_SIGN, LOCAL_WHEEL_INVITE_CODE } from "@constants/localkey";
- import { toast } from "react-toastify";
- import LZString from "lz-string";
- import { isStandalone, isTWA } from "@utils/UAUtils";
- import { normalizeClientError, reportClientLog, sanitizeUrlForLog } from "@utils/clientLog";
- const SENSITIVE_LOG_KEY = /(pass(word)?|sign|token|secret|authorization|cookie|phone|email|cpf|cashapp|paypal)/i;
- const stringifyForDebug = (value) => {
- try {
- return JSON.stringify(value, (key, item) => SENSITIVE_LOG_KEY.test(key) ? "[REDACTED]" : item);
- } catch (e) {
- return "[unserializable]";
- }
- };
- const getSign = () => {
- const sign = localStorageGet(LOCAL_SIGN, "");
- return sign;
- }
- const getC = () => {
- let c = localStorageGet(LOCAL_ACTIVITY_C, "");
- //容错为空时候再检测下url
- if (!c){
- let ccode = getUrlParam("c");
- if (ccode != null) {
- localStorageSet(LOCAL_ACTIVITY_C, ccode);
- c=ccode;
- }
- }
- return c;
- }
- const getComParams = () => {
- let params = {};
- if (global.BFP != null) params.bfp = global.BFP;
- if (global.FF != null) params.ff = global.FF;
- if(window.themeConfig)params.regionid=window.themeConfig.product;
- else params.regionid = window.location.hostname.split('.')[window.location.hostname.startsWith("www")?1:0];
- let sign = getSign();
- if (!!sign) params.sign = sign;
- let c = getC();
- if (!!c) params.c = c;
- params._d = global.device;
- params._t = Date.now() + "_" + global.width + "_" + global.height;
- if (isStandalone() || isTWA()) {
- params.pwa = 1;
- }
- let act = localStorageGet(LOCAL_WHEEL_INVITE_CODE);
- if (act != null && act !== "") {
- params.act = act;
- }
- return params;
- }
- const checkResponse = (data) => {
- if (data) {
- //登录失效
- if (data.code === 404) {
- let msg = getHttpMsg(data);
- toast.error(msg, {
- onClose: () => {
- window.location.replace(window.location.origin)
- }, toastId: "checkResponse"
- });
- }
- else if (data.code === 777) {
- let action = {
- type: "main/updateOpenPay",
- payload: 1,
- }
- setTimeout(() => {
- if (global.dispatch) global.dispatch(action);
- }, 1000)
- }
- }
- }
- const isLogRequest = (url = "") => {
- return String(url).includes(APP_LOG);
- }
- const service = axios.create({
- baseURL: BASE_API,
- withCredentials: true,
- timeout: 10000, // Request timeout
- retry: 2,//重复5次
- retryDelay: 1000,
- compress: !isDebugEnv()
- });
- //出错重试 retry
- const checkRetryRequest = (error) => {
- let config = error.config;
- if (!config || !config.retry) return Promise.reject(error);
- config.__retryCount = config.__retryCount || 0;
- if (config.__retryCount >= config.retry) {
- // Reject with the error
- return Promise.reject(error);
- }
- config.__retryCount += 1;
- // Create new promise to handle exponential backoff
- let backoff = new Promise(function (resolve) {
- setTimeout(function () {
- resolve();
- }, config.retryDelay || 1);
- });
- // Return the promise in which recalls axios to retry the request
- return backoff.then(function () {
- return service(config);
- });
- }
- // Request intercepter
- service.interceptors.request.use(
- config => {
- if (config.compress) {
- let data = config.ori_data;
- if (data == null) data = config.data;
- if (data) {
- let compressData = LZString.compressToBase64(JSON.stringify(data));
- config.data = {
- lz: compressData
- }
- config.ori_data = data;
- }
- let params = config.ori_params;
- if (params == null) params = config.params;
- if (params) {
- let compressParams = LZString.compressToBase64(JSON.stringify(params));
- config.params = {
- lz: compressParams
- }
- config.ori_params = params;
- }
- }
- return config;
- },
- error => {
- // Do something with request error
- return Promise.reject(error);
- }
- );
- // response pre-processing
- service.interceptors.response.use(
- response => {
- let data = response.data;
- if (typeof data === "string") {
- const decompressed = LZString.decompressFromBase64(data);
- const candidates = [decompressed, data];
- for (const candidate of candidates) {
- if (typeof candidate !== "string" || candidate === "") continue;
- try {
- response.data = JSON.parse(candidate);
- data = response.data;
- break;
- } catch (error) {
- // Try the next representation; preserve the original string if neither parses.
- }
- }
- }
- if (data && typeof data === "object" && typeof data.code === "string") {
- const code = data.code.trim();
- if (/^-?\d+$/.test(code)) data.code = Number(code);
- }
- if (isDebugEnv()) {
- const responseUrl = response.request?.responseURL || response.config?.url || "";
- console.debug(sanitizeUrlForLog(responseUrl), stringifyForDebug(response.data));
- }
- const requestUrl = response.config && response.config.url;
- if (!isLogRequest(requestUrl) && data && data.code != null && data.code !== 200) {
- reportClientLog("api_response_error", {
- url: requestUrl,
- method_type: response.config && response.config.method,
- code: data.code,
- msg: data.msg || data.message,
- response: data
- }, {
- throttleKey: `api_response_error:${requestUrl}:${data.code}:${data.msg || data.message || ""}`,
- throttleMs: 5000
- });
- }
- checkResponse(response.data);
- return response.data;
- },
- error => {
- const config = error.config || {};
- const retry = config.retry || 0;
- const retryCount = config.__retryCount || 0;
- const willRetry = retry && retryCount < retry;
- if (!willRetry && !isLogRequest(config.url)) {
- reportClientLog("api_request_error", {
- url: config.url,
- method_type: config.method,
- status: error.response && error.response.status,
- message: error.message,
- error: normalizeClientError(error),
- response: error.response && error.response.data
- }, {
- throttleKey: `api_request_error:${config.url}:${error.message || ""}`,
- throttleMs: 5000
- });
- }
- return checkRetryRequest(error);
- }
- );
- let _guestLoginPromise = null;
- const ensureSign = async (requestUrl) => {
- if (getSign()) return;
- const isLogin = localStorageGet(LOCAL_IS_LOGIN, "") === "1" || !!global.user;
- if (!isLogin) return;
- const isLoginUrl = requestUrl && (requestUrl.includes("/login") || requestUrl.includes("/register") || requestUrl.includes("/routes"));
- if (isLoginUrl) return;
- if (!_guestLoginPromise) {
- _guestLoginPromise = (async () => {
- try {
- const comParams = getComParams();
- const loginData = { type: "guest", ...comParams };
- const resp = await service({ method: "post", url: APP_LOGIN, data: loginData });
- if (resp && resp.code === 200 && resp.data) {
- const sign = resp.data.sign;
- if (sign) {
- localStorageSet(LOCAL_SIGN, sign);
- global.user = resp.data;
- }
- }
- } catch (e) {
- console.error("ensureSign guest login error", e);
- } finally {
- _guestLoginPromise = null;
- }
- })();
- }
- await _guestLoginPromise;
- };
- const get = async (params = {}) => {
- await ensureSign(params.url);
- const requestParams = {
- ...params,
- params: { ...(params.params || {}), ...getComParams() }
- };
- return service({
- method: 'get',
- ...requestParams
- });
- }
- const post = async (params = {}) => {
- await ensureSign(params.url);
- const requestParams = {
- ...params,
- data: { ...(params.data || {}), ...getComParams() }
- };
- if (isDebugEnv()) console.debug(`post params: ${stringifyForDebug(requestParams.data)} url:${params.url}`);
- return service({
- method: 'post',
- ...requestParams
- });
- }
- const put = async (params = {}) => {
- await ensureSign(params.url);
- const requestParams = {
- ...params,
- data: { ...(params.data || {}), ...getComParams() }
- };
- return service({
- method: 'put',
- ...requestParams
- });
- }
- const adelete = async (params = {}) => {
- await ensureSign(params.url);
- const requestParams = {
- ...params,
- data: { ...(params.data || {}), ...getComParams() }
- };
- return service({
- method: 'delete',
- ...requestParams
- });
- }
- const buildQuery = (param) => {
- if (param == null || typeof param === "string") return param;
- const query = new URLSearchParams();
- for (const key in param) {
- let value = param[key];
- if (value != null && typeof value === "object") value = JSON.stringify(value);
- query.append(key, value == null ? "" : String(value));
- }
- return query.toString();
- }
- const getAPKUrl = (apkUrl = null) => {
- let params = getComParams();
- let url = apkUrl == null ? BASE_API + APP_GAME_APK : apkUrl;
- const separator = url.includes("?") ? "&" : "?";
- if (!isDebugEnv()) {
- url += separator + "lz=" + encodeURIComponent(LZString.compressToBase64(JSON.stringify(params)));
- }
- else {
- url += separator + buildQuery(params);
- }
- return url;
- }
- /** 解析 quickSave 生成的 path:/s_k_c 或 /s_k_c/xxx => { s_k, c },用于 routes 恢复环境与 basename */
- export const parseQuickSavePath = () => {
- const pathname = window.location.pathname || "";
- const m = pathname.match(/^\/([a-zA-Z0-9]+)_(\d+)(?:\/.*)?$/);
- return m ? { s_k: m[1], c: m[2] } : null;
- };
- /** 当前 pathname(去掉 s_k_c 前缀),用于与 "/"、ROUTE_PATH 等比较时与首页一视同仁 */
- export const getLogicalPathname = () => {
- const pathname = window.location.pathname || "";
- const q = parseQuickSavePath();
- if (!q) return pathname;
- const prefix = `/${q.s_k}_${q.c}`;
- if (pathname === prefix || pathname === prefix + "/") return "/";
- if (pathname.startsWith(prefix + "/")) return pathname.slice(prefix.length) || "/";
- return pathname;
- };
- const Http = {
- get,
- post,
- put,
- delete: adelete,
- getAPKUrl
- }
- export default Http;
|