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.