From 1d0fb7d260d2ab98ea652e8baed4804d5039bacd Mon Sep 17 00:00:00 2001 From: sunnylqm Date: Sat, 18 Jan 2020 23:55:10 +0800 Subject: [PATCH] Backup domains --- .prettierrc.js | 1 - lib/getHost.js | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/index.d.ts | 1 - lib/index.js | 40 +++++++++++++++++++++-------------- 4 files changed, 81 insertions(+), 18 deletions(-) create mode 100644 lib/getHost.js diff --git a/.prettierrc.js b/.prettierrc.js index e23377f..9166a04 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -1,5 +1,4 @@ module.exports = { - printWidth: 120, trailingComma: 'all', singleQuote: true, }; diff --git a/lib/getHost.js b/lib/getHost.js new file mode 100644 index 0000000..022e071 --- /dev/null +++ b/lib/getHost.js @@ -0,0 +1,57 @@ +let availableDomain = 'update.reactnative.cn'; + +function ping(domain) { + return new Promise((resolve, reject) => { + const xhr = new XMLHttpRequest(); + xhr.onreadystatechange = e => { + if (xhr.readyState !== 4) { + return; + } + if (xhr.status === 200) { + resolve(domain); + } else { + setTimeout(reject, 5000); + } + }; + xhr.open('HEAD', `https://${domain}`); + xhr.send(); + xhr.timeout = 5000; + xhr.ontimeout = reject; + }); +} + +function logger(...args) { + // console.warn('pushy', ...args); +} + +export async function tryBackupDomains() { + try { + await ping(availableDomain); + logger('main domain ok'); + return; + } catch (e) { + logger('main domain failed'); + } + let backupDomains = []; + try { + const resp = await fetch( + 'https://cdn.jsdelivr.net/gh/reactnativecn/react-native-pushy@master/domains.json', + ); + backupDomains = await resp.json(); + logger('get remote domains:', backupDomains); + } catch (e) { + logger('get remote domains failed'); + return; + } + const fastestDomain = await Promise.race(backupDomains.map(ping)); + if (typeof fastestDomain === 'string') { + logger(`pick domain: ${fastestDomain}`); + availableDomain = fastestDomain; + } else { + logger('all remote domains failed'); + } +} + +export default function getHost() { + return `https://${availableDomain}/api`; +} diff --git a/lib/index.d.ts b/lib/index.d.ts index 9859f16..0f7ff6c 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -19,7 +19,6 @@ export interface UpdateAvailableResult { hash: string; description: string; metaInfo: string; - updateUrl: string; pdiffUrl: string; diffUrl: string; } diff --git a/lib/index.js b/lib/index.js index d15513c..ac1ef08 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,7 +1,7 @@ +import getHost, { tryBackupDomains } from './getHost'; import { NativeAppEventEmitter, NativeModules } from 'react-native'; -const Pushy = NativeModules.Pushy || {}; -const host = 'https://update.reactnative.cn/api'; +const Pushy = NativeModules.Pushy || {}; export const downloadRootDir = Pushy.downloadRootDir; export const packageVersion = Pushy.packageVersion; @@ -28,7 +28,6 @@ There is available update: hash: 'hash', description: '添加聊天功能\n修复商城页面BUG', metaInfo: '{"silent":true}', - updateUrl: 'http://update-packages.reactnative.cn/hash', pdiffUrl: 'http://update-packages.reactnative.cn/hash', diffUrl: 'http://update-packages.reactnative.cn/hash', } @@ -40,20 +39,29 @@ function assertRelease() { } } -export async function checkUpdate(APPKEY) { +export async function checkUpdate(APPKEY, isRetry) { assertRelease(); - const resp = await fetch(`${host}/checkUpdate/${APPKEY}`, { - method: 'POST', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - packageVersion, - hash: currentVersion, - buildTime, - }), - }); + let resp; + try { + resp = await fetch(`${getHost()}/checkUpdate/${APPKEY}`, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + packageVersion, + hash: currentVersion, + buildTime, + }), + }); + } catch (e) { + if (isRetry) { + throw new Error('Could not connect to pushy server'); + } + await tryBackupDomains(); + return checkUpdate(APPKEY, true); + } if (resp.status !== 200) { throw new Error((await resp.json()).message);