Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Ops] Upgrade to axios 1.4 #163732

Merged
merged 11 commits into from
Aug 22, 2023
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,7 @@
"antlr4ts": "^0.5.0-alpha.3",
"archiver": "^5.3.1",
"async": "^3.2.3",
"axios": "^0.27.2",
"axios": "^1.4.0",
"base64-js": "^1.3.1",
"bitmap-sdf": "^1.0.3",
"blurhash": "^2.0.1",
Expand Down
5 changes: 1 addition & 4 deletions packages/kbn-ci-stats-reporter/src/ci_stats_reporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ import { REPO_ROOT, kibanaPackageJson } from '@kbn/repo-info';
import { parseConfig, Config, CiStatsMetadata } from '@kbn/ci-stats-core';
import type { SomeDevLog } from '@kbn/some-dev-log';

// @ts-expect-error not "public", but necessary to prevent Jest shimming from breaking things
import httpAdapter from 'axios/lib/adapters/http';

import type { CiStatsTestGroupInfo, CiStatsTestRun } from './ci_stats_test_group_types';

const BASE_URL = 'https://ci-stats.kibana.dev';
Expand Down Expand Up @@ -375,7 +372,7 @@ export class CiStatsReporter {
headers,
data: body,
params: query,
adapter: httpAdapter,
adapter: 'http',

// if it can be serialized into a string, send it
maxBodyLength: Infinity,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import Url from 'url';

import Axios, { AxiosRequestConfig, AxiosInstance } from 'axios';
import Axios, { AxiosRequestConfig, AxiosInstance, AxiosHeaders, AxiosHeaderValue } from 'axios';
import { isAxiosResponseError, isAxiosRequestError } from '@kbn/dev-utils';
import { ToolingLog } from '@kbn/tooling-log';

Expand Down Expand Up @@ -130,7 +130,7 @@ export class GithubApi {
): Promise<{
status: number;
statusText: string;
headers: Record<string, string | string[] | undefined>;
headers: Record<string, AxiosHeaderValue | undefined>;
data: T;
}> {
const executeRequest = !this.dryRun || options.safeForDryRun;
Expand All @@ -145,7 +145,7 @@ export class GithubApi {
return {
status: 200,
statusText: 'OK',
headers: {},
headers: new AxiosHeaders(),
data: dryRunResponse,
};
}
Expand All @@ -158,7 +158,7 @@ export class GithubApi {
const githubApiFailed = isAxiosResponseError(error) && error.response.status >= 500;
const errorResponseLog =
isAxiosResponseError(error) &&
`[${error.config.method} ${error.config.url}] ${error.response.status} ${error.response.statusText} Error`;
`[${error.config?.method} ${error.config?.url}] ${error.response.status} ${error.response.statusText} Error`;

if ((unableToReachGithub || githubApiFailed) && attempt < maxAttempts) {
const waitMs = 1000 * attempt;
Expand Down
7 changes: 7 additions & 0 deletions packages/kbn-test/src/jest/resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ module.exports = (request, options) => {
return module.exports(request.replace('@elastic/eui/lib/', '@elastic/eui/test-env/'), options);
}

if (request === 'axios') {
return resolve.sync('axios/dist/node/axios.cjs', {
basedir: options.basedir,
extensions: options.extensions,
});
}

if (request === `elastic-apm-node`) {
return APM_AGENT_MOCK;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/kbn-test/src/kbn_client/kbn_client_requester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { KbnClientRequesterError } from './kbn_client_requester_error';

const isConcliftOnGetError = (error: any) => {
return (
isAxiosResponseError(error) && error.config.method === 'GET' && error.response.status === 409
isAxiosResponseError(error) && error.config?.method === 'GET' && error.response.status === 409
);
};

Expand Down
8 changes: 2 additions & 6 deletions src/dev/build/lib/download.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ import Axios from 'axios';
import { isAxiosResponseError } from '@kbn/dev-utils';
import { ToolingLog } from '@kbn/tooling-log';

// https://github.com/axios/axios/tree/ffea03453f77a8176c51554d5f6c3c6829294649/lib/adapters
// @ts-expect-error untyped internal module used to prevent axios from using xhr adapter in tests
import AxiosHttpAdapter from 'axios/lib/adapters/http';

import { mkdirp } from './fs';

function tryUnlink(path: string) {
Expand Down Expand Up @@ -78,7 +74,7 @@ export async function downloadToDisk({
const response = await Axios.request({
url,
responseType: 'stream',
adapter: AxiosHttpAdapter,
adapter: 'http',
});

if (response.status !== 200) {
Expand Down Expand Up @@ -171,7 +167,7 @@ export async function downloadToString({
const resp = await Axios.request<string>({
url,
method: 'GET',
adapter: AxiosHttpAdapter,
adapter: 'http',
responseType: 'text',
validateStatus: !expectStatus ? undefined : (status) => status === expectStatus,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,6 @@ const UNAUTHORIZED_CA = fsReadFileSync(UNAUTHORIZED_CA_FILE);
const Auth = 'elastic:changeme';
const AuthB64 = Buffer.from(Auth).toString('base64');

// eslint-disable-next-line @typescript-eslint/no-var-requires
const AxiosDefaultsAadapter = require('axios/lib/adapters/http');

describe('axios connections', () => {
let testServer: http.Server | https.Server | null;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand All @@ -65,7 +62,7 @@ describe('axios connections', () => {
// needed to prevent the dreaded Error: Cross origin http://localhost forbidden
// see: https://github.com/axios/axios/issues/1754#issuecomment-572778305
savedAxiosDefaultsAdapter = axios.defaults.adapter;
axios.defaults.adapter = AxiosDefaultsAadapter;
axios.defaults.adapter = 'http';
});

afterEach(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ const CA = fsReadFileSync(CA_FILE, 'utf8');
const Auth = 'elastic:changeme';
const AuthB64 = Buffer.from(Auth).toString('base64');

// eslint-disable-next-line @typescript-eslint/no-var-requires
const AxiosDefaultsAadapter = require('axios/lib/adapters/http');

const ServerResponse = 'A unique response returned by the server!';

describe('axios connections', () => {
Expand All @@ -53,7 +50,7 @@ describe('axios connections', () => {
// needed to prevent the dreaded Error: Cross origin http://localhost forbidden
// see: https://github.com/axios/axios/issues/1754#issuecomment-572778305
savedAxiosDefaultsAdapter = axios.defaults.adapter;
axios.defaults.adapter = AxiosDefaultsAadapter;
axios.defaults.adapter = 'http';
});

afterEach(() => {
Expand Down
20 changes: 15 additions & 5 deletions x-pack/plugins/actions/server/lib/axios_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@
*/

import { isObjectLike, isEmpty } from 'lodash';
import { AxiosInstance, Method, AxiosResponse, AxiosRequestConfig } from 'axios';
import {
AxiosInstance,
Method,
AxiosResponse,
AxiosRequestConfig,
AxiosHeaders,
AxiosHeaderValue,
} from 'axios';
import { Logger } from '@kbn/core/server';
import { getCustomAgents } from './get_custom_agents';
import { ActionsConfigurationUtilities } from '../actions_config';
Expand All @@ -29,7 +36,7 @@ export const request = async <T = unknown>({
method?: Method;
data?: T;
configurationUtilities: ActionsConfigurationUtilities;
headers?: Record<string, string> | null;
headers?: Record<string, AxiosHeaderValue>;
sslOverrides?: SSLSettings;
} & AxiosRequestConfig): Promise<AxiosResponse> => {
const { httpAgent, httpsAgent } = getCustomAgents(
Expand All @@ -43,8 +50,7 @@ export const request = async <T = unknown>({
return await axios(url, {
...config,
method,
// Axios doesn't support `null` value for `headers` property.
headers: headers ?? undefined,
headers,
data: data ?? {},
// use httpAgent and httpsAgent and set axios proxy: false, to be able to handle fail on invalid certs
httpAgent,
Expand Down Expand Up @@ -149,6 +155,10 @@ export const createAxiosResponse = (res: Partial<AxiosResponse>): AxiosResponse
status: 200,
statusText: 'OK',
headers: { ['content-type']: 'application/json' },
config: { method: 'GET', url: 'https://example.com' },
config: {
method: 'GET',
url: 'https://example.com',
headers: new AxiosHeaders(),
},
...res,
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import axios, { AxiosError, AxiosInstance, AxiosResponse } from 'axios';
import axios, { AxiosError, AxiosHeaders, AxiosInstance, AxiosResponse } from 'axios';
import { loggingSystemMock } from '@kbn/core/server/mocks';
import { MockedLogger } from '@kbn/logging-mocks';
import { actionsConfigMock } from '../actions_config.mock';
Expand All @@ -29,7 +29,7 @@ const requestMock = utils.request as jest.Mock;
const createAxiosError = (): AxiosError => {
const error = new Error() as AxiosError;
error.isAxiosError = true;
error.config = { method: 'get', url: 'https://example.com' };
error.config = { method: 'get', url: 'https://example.com', headers: new AxiosHeaders() };
error.response = {
data: { errorMessage: 'An error occurred', errorCode: 500 },
} as AxiosResponse;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@
import { isPlainObject, isEmpty } from 'lodash';
import { Type } from '@kbn/config-schema';
import { Logger } from '@kbn/logging';
import axios, { AxiosInstance, AxiosResponse, AxiosError, AxiosRequestHeaders } from 'axios';
import axios, {
AxiosInstance,
AxiosResponse,
AxiosError,
AxiosRequestHeaders,
AxiosHeaders,
AxiosHeaderValue,
} from 'axios';
import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server';
import { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import { finished } from 'stream/promises';
Expand Down Expand Up @@ -75,7 +82,7 @@ export abstract class SubActionConnector<Config, Secrets> {
}
}

private getHeaders(headers?: AxiosRequestHeaders) {
private getHeaders(headers?: AxiosRequestHeaders): Record<string, AxiosHeaderValue> {
return { ...headers, 'Content-Type': 'application/json' };
}

Expand Down Expand Up @@ -130,7 +137,7 @@ export abstract class SubActionConnector<Config, Secrets> {
method,
data: this.normalizeData(data),
configurationUtilities: this.configurationUtilities,
headers: this.getHeaders(headers),
headers: this.getHeaders(headers as AxiosHeaders),
});

this.validateResponse(responseSchema, res.data);
Expand All @@ -139,7 +146,7 @@ export abstract class SubActionConnector<Config, Secrets> {
} catch (error) {
if (isAxiosError(error)) {
this.logger.debug(
`Request to external service failed. Connector Id: ${this.connector.id}. Connector type: ${this.connector.type}. Method: ${error.config.method}. URL: ${error.config.url}`
`Request to external service failed. Connector Id: ${this.connector.id}. Connector type: ${this.connector.type}. Method: ${error.config?.method}. URL: ${error.config?.url}`
);

let responseBody = '';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ init().catch((e) => {
console.error(e.message);
} else if (isAxiosError(e)) {
console.error(
`${e.config.method?.toUpperCase() || 'GET'} ${e.config.url} (Code: ${
`${e.config?.method?.toUpperCase() || 'GET'} ${e.config?.url} (Code: ${
e.response?.status
})`
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,17 @@ export async function getKibanaVersion({
switch (e.response?.status) {
case 401:
throw new AbortError(
`Could not access Kibana with the provided credentials. Username: "${e.config.auth?.username}". Password: "${e.config.auth?.password}"`
`Could not access Kibana with the provided credentials. Username: "${e.config?.auth?.username}". Password: "${e.config?.auth?.password}"`
);

case 404:
throw new AbortError(
`Could not get version on ${e.config.url} (Code: 404)`
`Could not get version on ${e.config?.url} (Code: 404)`
);

default:
throw new AbortError(
`Cannot access Kibana on ${e.config.baseURL}. Please specify Kibana with: "--kibana-url <url>"`
`Cannot access Kibana on ${e.config?.baseURL}. Please specify Kibana with: "--kibana-url <url>"`
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe.each(packageInfos)('Chromium archive: %s/%s', (architecture, platform)

const originalAxios = axios.defaults.adapter;
beforeAll(async () => {
axios.defaults.adapter = require('axios/lib/adapters/http'); // allow Axios to send actual requests
axios.defaults.adapter = 'http';
});

afterAll(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ export class FormattedAxiosError extends Error {
super(axiosError.message);

this.request = {
method: axiosError.config.method ?? '?',
url: axiosError.config.url ?? '?',
data: axiosError.config.data ?? '',
method: axiosError.config?.method ?? '?',
url: axiosError.config?.url ?? '?',
data: axiosError.config?.data ?? '',
};

this.response = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import type { AxiosInstance, AxiosResponse } from 'axios';
import axios from 'axios';
import axios, { AxiosHeaders } from 'axios';
import type { Logger } from '@kbn/core/server';
import type { TelemetryPluginStart, TelemetryPluginSetup } from '@kbn/telemetry-plugin/server';
import type { UsageCounter } from '@kbn/usage-collection-plugin/server';
Expand Down Expand Up @@ -71,7 +71,9 @@ export class PreviewTelemetryEventsSender implements ITelemetryEventsSender {
status: 200,
statusText: 'ok',
headers: {},
config: {},
config: {
headers: new AxiosHeaders(),
},
};
return Promise.resolve(okResponse);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import { AxiosHeaders } from 'axios';
import {
getObjectValueByKeyAsString,
stringifyObjValues,
Expand Down Expand Up @@ -60,6 +61,7 @@ describe('cases_webhook/utils', () => {
config: {
method: 'post',
url: 'https://poster.com',
headers: new AxiosHeaders({}),
},
};
it('Throws error when missing content-type', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
jest.mock('axios', () => ({
create: jest.fn(),
AxiosHeaders: jest.requireActual('axios').AxiosHeaders,
}));

import axios from 'axios';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import { AxiosRequestHeaders, AxiosResponse, ResponseType } from 'axios';
import { AxiosResponse, ResponseType } from 'axios';
import { IncomingMessage } from 'http';
import { OpenAiProviderType } from '../../../../common/gen_ai/constants';
import {
Expand Down Expand Up @@ -77,7 +77,7 @@ export const getAxiosOptions = (
provider: string,
apiKey: string,
stream: boolean
): { headers: AxiosRequestHeaders; responseType?: ResponseType } => {
): { headers: Record<string, string>; responseType?: ResponseType } => {
const responseType = stream ? { responseType: 'stream' as ResponseType } : {};
switch (provider) {
case OpenAiProviderType.OpenAi:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
import { fromNullable, Option, map, filter } from 'fp-ts/lib/Option';
import { pipe } from 'fp-ts/lib/pipeable';

export function getRetryAfterIntervalFromHeaders(headers: Record<string, string>): Option<number> {
export function getRetryAfterIntervalFromHeaders(headers: Record<string, unknown>): Option<number> {
return pipe(
fromNullable(headers['retry-after']),
map((retryAfter) => parseInt(retryAfter, 10)),
map((retryAfter) => parseInt(retryAfter as string, 10)),
filter((retryAfter) => !isNaN(retryAfter))
);
}