I’ve written a node app that fetches data from an API, using multiple endpoints. I am also using proxies to do this.
I’m currently using socks-proxy-agent
to create a https agent for my axios
instances to use the proxy.
Here is the class that does all of this:
export class Checker { private region: Region private proxy: AxiosProxyConfig | false private client: AxiosInstance constructor(region: Region, proxy?: AxiosProxyConfig | false) { this.region = region; this.proxy = proxy; if (proxy) { const proxyOptions = `socks://${proxy.host}:${proxy.port}`; const httpsAgent = new SocksProxyAgent(proxyOptions); this.client = axios.create({ timeout: 5000, httpsAgent: httpsAgent }); } else { this.client = axios.create({ timeout: 5000 }); } } public check(account: Account): Promise<CheckResponse> { return new Promise((resolve, reject) => { this.client.post("xxx", { acr_values: "urn:riot:bronze", claims: "", client_id: "riot-client", nonce: 1, redirect_uri: "http://localhost/redirect", response_type: "token id_token", scope: "openid link ban lol_region", }).then((response) => { const cookies = response.headers["set-cookie"]; this.client.put( "xxx", { type: "auth", username: account.username, password: account.password, remember: false, language: "en_GB", region: this.region.login, }, { headers: { Cookie: cookies, }, } ).then(async (response) => { //200 OK const { data } = response; if (data.error) { //Error is present. switch (data.error) { case "auth_failure": resolve({ type: CheckResponseType.INVALID }); break; case "rate_limited": reject({ type: CheckResponseType.RATE_LIMITED, proxy: this.proxy }); break; default: console.log("Unknown auth response error type: ", data.error) reject({ type: CheckResponseType.RETRY }); } } else { //Login was successful - we can now get auth token and check champs etc. const { uri } = data.response.parameters; const access_token = /#access_token=(.*?)&/.exec(uri)[1] || null; this.client.defaults.headers = { Authorization: `Bearer ${access_token}` } this.client.post("xxx").then(async (response) => { const userInfo = response.data; const summoner: Summoner = { account: account, region: this.region, id: userInfo.lol.cuid, profileIcon: userInfo.lol_account.profile_icon, name: userInfo.lol_account.summoner_name, level: userInfo.lol_account.summoner_level, emailVerified: userInfo.email_verified, phoneVerified: userInfo.phone_number_verified } if (userInfo.ban.code) { resolve({ type: CheckResponseType.BANNED }); } else { try { const accountId = userInfo.lol.cuid; const inventory = await this.client.get(`xxx`); const champions = inventory.data.data.items.CHAMPION; const skins = inventory.data.data.items.CHAMPION_SKIN; const store = await this.client.get(`xxx`); const matchHistory = await this.client.get(`xxx`); const lastPlayed = matchHistory.data.games.games[0].gameCreation; summoner.data = { blueEssence: store.data.player.ip, riotPoints: store.data.player.rp, refunds: store.data.refundCreditsRemaining, champions: [], skins: [], lastPlayed: lastPlayed } champions.map((champion) => { summoner.data.champions.push({ id: champion.itemId, purchaseDate: champion.purchaseDate }); }); skins.map((skin) => { summoner.data.skins.push({ id: skin.itemId, purchaseDate: skin.purchaseDate, vintage: skin.payload.isVintage }); }); resolve({ type: CheckResponseType.SUCCESS, summoner: summoner }); } catch { reject({ type: CheckResponseType.RETRY }); } } }); } }).catch(() => { reject({ type: CheckResponseType.RETRY }); }); }).catch(() => { reject({ type: CheckResponseType.RETRY }); }); }); } }
However, if there’s an issue with a proxy, I get unhandled promise rejections like this that seem to be coming from the socket:
(node:2200) UnhandledPromiseRejectionWarning: Error: connect ETIMEDOUT 46.101.212.177:9050 at SocksClient.closeSocket (C:NodeAppslol-crackernode_modulessocksbuildclientsocksclient.js:364:32) at SocksClient.onErrorHandler (C:NodeAppslol-crackernode_modulessocksbuildclientsocksclient.js:337:14) at Socket.onError (C:NodeAppslol-crackernode_modulessocksbuildclientsocksclient.js:199:38) at Object.onceWrapper (events.js:422:26) at Socket.emit (events.js:315:20) at emitErrorNT (internal/streams/destroy.js:92:8) at emitErrorAndCloseNT (internal/streams/destroy.js:60:3) at processTicksAndRejections (internal/process/task_queues.js:84:21) (node:2200) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2266) (node:2200) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
However, I’m pretty sure I’ve handled everything. I even have a try/catch
block around my await calls.
Advertisement
Answer
As I’m looking at your code this api call this.client.post("https://auth.riotgames.com/userinfo")
doesn’t have catch
function.
By separating each one of your api calls in different functions and returning them, your code becomes much cleaner and finding these errors becomes easier.