Consolidate axios request logic into its own service

CORL-1277
This commit is contained in:
nick-funk
2020-08-13 12:44:57 -06:00
parent 6e896a189d
commit e2fc4c0038
3 changed files with 103 additions and 10 deletions
@@ -0,0 +1,79 @@
import axios, { Method } from "axios";
import http from "http";
import https from "https";
import { capitalize } from "lodash";
import { version } from "coral-common/version";
export type Axios = (
url: string,
options?: AxiosOptions,
timeout?: number
) => Promise<AxiosResponse>;
export interface AxiosResponse {
ok: boolean;
status: number;
data: any;
}
export interface CreateAxiosOptions {
/**
* name is the string that is attached to the `User-Agent` header as:
*
* `Coral ${name}/${version}`
*/
name: string;
}
export interface AxiosOptions {
method: Method;
headers: any;
body: any;
}
export const createAxios = ({ name }: CreateAxiosOptions): Axios => {
// defaultHeaders are the headers attached to each request (unless they are
// overridden).
const defaultHeaders = {
"User-Agent": `Coral ${capitalize(name)}/${version}`,
};
// Create HTTP agents to improve connection performance.
const agents = {
https: new https.Agent({
keepAlive: true,
}),
http: new http.Agent({
keepAlive: true,
}),
};
return async (
url: string,
{ method = "GET", headers = {}, body = {} }: AxiosOptions,
timeout?: number
) => {
const response = await axios.request({
method,
url,
headers: {
...defaultHeaders,
...headers,
},
data: body,
timeout,
timeoutErrorMessage: "axios request timed out",
httpAgent: agents.http,
httpsAgent: agents.https,
});
const ok = response.status >= 200 || response.status <= 299;
return {
ok,
status: response.status,
data: response.data,
};
};
};
@@ -0,0 +1 @@
export * from "./axios";
@@ -1,11 +1,15 @@
import axios from "axios";
import path from "path";
import { URL } from "url";
import { TOXICITY_ENDPOINT_DEFAULT } from "coral-common/constants";
import { LanguageCode } from "coral-common/helpers";
import logger from "coral-server/logger";
import { getURLWithCommentID } from "coral-server/models/story";
import { createAxios } from "../axios.ts";
const axios = createAxios({ name: "perspective" });
/**
* Language is the language key that is supported by the Perspective API in the
* ISO 631-1 format.
@@ -135,28 +139,33 @@ export async function sendToPerspective(
try {
// Create the request and send it.
const res = await axios.post(url.toString(), body, {
headers: {
"Content-Type": "application/json",
const res = await axios(
url.toString(),
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body,
},
timeout,
});
timeout
);
// Non-successful response
if (res.status < 200 || res.status > 299) {
if (!res.ok) {
return {
ok: false,
ok: res.ok,
status: res.status,
data: null,
};
}
// Parse the JSON body and send back the result!
const data = res.data;
return {
ok: true,
status: res.status,
data,
data: res.data,
};
} catch (err) {
// Ensure that the API key doesn't get leaked to the logs by accident.
@@ -167,6 +176,10 @@ export async function sendToPerspective(
);
}
if (err.message && err.message.startsWith("axios request timed out")) {
logger.error("perspective request timed out");
}
// Rethrow the error.
throw err;
}