Skip to content
Snippets Groups Projects
Unverified Commit f39d73f9 authored by Rhys Arkins's avatar Rhys Arkins Committed by GitHub
Browse files

feat(internal): apply host-rules in http module (#6501)

parent cb573a03
Branches
No related tags found
No related merge requests found
...@@ -152,6 +152,7 @@ exports[`api/docker getReleases adds library/ prefix for Docker Hub (implicit) 1 ...@@ -152,6 +152,7 @@ exports[`api/docker getReleases adds library/ prefix for Docker Hub (implicit) 1
Array [ Array [
"https://index.docker.io/v2/", "https://index.docker.io/v2/",
Object { Object {
"auth": "some-username:some-password",
"headers": Object { "headers": Object {
"user-agent": "https://github.com/renovatebot/renovate", "user-agent": "https://github.com/renovatebot/renovate",
}, },
...@@ -416,6 +417,7 @@ exports[`api/docker getReleases uses custom registry in depName 1`] = ` ...@@ -416,6 +417,7 @@ exports[`api/docker getReleases uses custom registry in depName 1`] = `
Array [ Array [
"https://registry.company.com/v2/", "https://registry.company.com/v2/",
Object { Object {
"auth": "some-username:some-password",
"headers": Object { "headers": Object {
"user-agent": "https://github.com/renovatebot/renovate", "user-agent": "https://github.com/renovatebot/renovate",
}, },
...@@ -432,6 +434,7 @@ exports[`api/docker getReleases uses custom registry in depName 1`] = ` ...@@ -432,6 +434,7 @@ exports[`api/docker getReleases uses custom registry in depName 1`] = `
Array [ Array [
"https://registry.company.com/v2/node/tags/list?n=10000", "https://registry.company.com/v2/node/tags/list?n=10000",
Object { Object {
"auth": "some-username:some-password",
"headers": Object { "headers": Object {
"user-agent": "https://github.com/renovatebot/renovate", "user-agent": "https://github.com/renovatebot/renovate",
}, },
...@@ -448,6 +451,7 @@ exports[`api/docker getReleases uses custom registry in depName 1`] = ` ...@@ -448,6 +451,7 @@ exports[`api/docker getReleases uses custom registry in depName 1`] = `
Array [ Array [
"https://registry.company.com/v2/", "https://registry.company.com/v2/",
Object { Object {
"auth": "some-username:some-password",
"headers": Object { "headers": Object {
"user-agent": "https://github.com/renovatebot/renovate", "user-agent": "https://github.com/renovatebot/renovate",
}, },
...@@ -493,6 +497,7 @@ Array [ ...@@ -493,6 +497,7 @@ Array [
Array [ Array [
"https://registry.company.com/v2/", "https://registry.company.com/v2/",
Object { Object {
"auth": "some-username:some-password",
"headers": Object { "headers": Object {
"user-agent": "https://github.com/renovatebot/renovate", "user-agent": "https://github.com/renovatebot/renovate",
}, },
...@@ -509,6 +514,7 @@ Array [ ...@@ -509,6 +514,7 @@ Array [
Array [ Array [
"https://registry.company.com/v2/node/tags/list?n=10000", "https://registry.company.com/v2/node/tags/list?n=10000",
Object { Object {
"auth": "some-username:some-password",
"headers": Object { "headers": Object {
"user-agent": "https://github.com/renovatebot/renovate", "user-agent": "https://github.com/renovatebot/renovate",
}, },
...@@ -525,6 +531,7 @@ Array [ ...@@ -525,6 +531,7 @@ Array [
Array [ Array [
"https://api.github.com/user/9287/repos?page=3&per_page=100", "https://api.github.com/user/9287/repos?page=3&per_page=100",
Object { Object {
"auth": "some-username:some-password",
"headers": Object { "headers": Object {
"user-agent": "https://github.com/renovatebot/renovate", "user-agent": "https://github.com/renovatebot/renovate",
}, },
...@@ -541,6 +548,7 @@ Array [ ...@@ -541,6 +548,7 @@ Array [
Array [ Array [
"https://registry.company.com/v2/", "https://registry.company.com/v2/",
Object { Object {
"auth": "some-username:some-password",
"headers": Object { "headers": Object {
"user-agent": "https://github.com/renovatebot/renovate", "user-agent": "https://github.com/renovatebot/renovate",
}, },
...@@ -557,6 +565,7 @@ Array [ ...@@ -557,6 +565,7 @@ Array [
Array [ Array [
"https://registry.company.com/v2/node/manifests/latest", "https://registry.company.com/v2/node/manifests/latest",
Object { Object {
"auth": "some-username:some-password",
"headers": Object { "headers": Object {
"accept": "application/vnd.docker.distribution.manifest.v2+json", "accept": "application/vnd.docker.distribution.manifest.v2+json",
"user-agent": "https://github.com/renovatebot/renovate", "user-agent": "https://github.com/renovatebot/renovate",
...@@ -579,6 +588,7 @@ exports[`api/docker getReleases uses lower tag limit for ECR deps 1`] = ` ...@@ -579,6 +588,7 @@ exports[`api/docker getReleases uses lower tag limit for ECR deps 1`] = `
Array [ Array [
"https://123456789.dkr.ecr.us-east-1.amazonaws.com/v2/", "https://123456789.dkr.ecr.us-east-1.amazonaws.com/v2/",
Object { Object {
"auth": "some-username:some-password",
"headers": Object { "headers": Object {
"user-agent": "https://github.com/renovatebot/renovate", "user-agent": "https://github.com/renovatebot/renovate",
}, },
...@@ -595,6 +605,7 @@ exports[`api/docker getReleases uses lower tag limit for ECR deps 1`] = ` ...@@ -595,6 +605,7 @@ exports[`api/docker getReleases uses lower tag limit for ECR deps 1`] = `
Array [ Array [
"https://123456789.dkr.ecr.us-east-1.amazonaws.com/v2/node/tags/list?n=1000", "https://123456789.dkr.ecr.us-east-1.amazonaws.com/v2/node/tags/list?n=1000",
Object { Object {
"auth": "some-username:some-password",
"headers": Object { "headers": Object {
"user-agent": "https://github.com/renovatebot/renovate", "user-agent": "https://github.com/renovatebot/renovate",
}, },
...@@ -611,6 +622,7 @@ exports[`api/docker getReleases uses lower tag limit for ECR deps 1`] = ` ...@@ -611,6 +622,7 @@ exports[`api/docker getReleases uses lower tag limit for ECR deps 1`] = `
Array [ Array [
"https://123456789.dkr.ecr.us-east-1.amazonaws.com/v2/", "https://123456789.dkr.ecr.us-east-1.amazonaws.com/v2/",
Object { Object {
"auth": "some-username:some-password",
"headers": Object { "headers": Object {
"user-agent": "https://github.com/renovatebot/renovate", "user-agent": "https://github.com/renovatebot/renovate",
}, },
......
...@@ -37,6 +37,7 @@ describe('datasource/maven', () => { ...@@ -37,6 +37,7 @@ describe('datasource/maven', () => {
hostName: 'frontend_for_private_s3_repository', hostName: 'frontend_for_private_s3_repository',
username: 'username', username: 'username',
password: 'password', password: 'password',
timeout: 20000,
}); });
jest.resetAllMocks(); jest.resetAllMocks();
nock.cleanAll(); nock.cleanAll();
......
...@@ -12,6 +12,7 @@ import * as cargo from './artifacts'; ...@@ -12,6 +12,7 @@ import * as cargo from './artifacts';
jest.mock('fs-extra'); jest.mock('fs-extra');
jest.mock('child_process'); jest.mock('child_process');
jest.mock('../../util/exec/env'); jest.mock('../../util/exec/env');
jest.mock('../../util/http');
const fs: jest.Mocked<typeof _fs> = _fs as any; const fs: jest.Mocked<typeof _fs> = _fs as any;
const exec: jest.Mock<typeof _exec> = _exec as any; const exec: jest.Mock<typeof _exec> = _exec as any;
......
...@@ -15,6 +15,7 @@ jest.mock('fs-extra'); ...@@ -15,6 +15,7 @@ jest.mock('fs-extra');
jest.mock('child_process'); jest.mock('child_process');
jest.mock('../../util/exec/env'); jest.mock('../../util/exec/env');
jest.mock('../../util/host-rules'); jest.mock('../../util/host-rules');
jest.mock('../../util/http');
const fs: jest.Mocked<typeof _fs> = _fs as any; const fs: jest.Mocked<typeof _fs> = _fs as any;
const exec: jest.Mock<typeof _exec> = _exec as any; const exec: jest.Mock<typeof _exec> = _exec as any;
......
...@@ -14,6 +14,7 @@ jest.mock('fs-extra'); ...@@ -14,6 +14,7 @@ jest.mock('fs-extra');
jest.mock('child_process'); jest.mock('child_process');
jest.mock('../../util/exec/env'); jest.mock('../../util/exec/env');
jest.mock('../../util/host-rules'); jest.mock('../../util/host-rules');
jest.mock('../../util/http');
const fs: jest.Mocked<typeof _fs> = _fs as any; const fs: jest.Mocked<typeof _fs> = _fs as any;
const exec: jest.Mock<typeof _exec> = _exec as any; const exec: jest.Mock<typeof _exec> = _exec as any;
......
...@@ -90,281 +90,3 @@ Object { ...@@ -90,281 +90,3 @@ Object {
}, },
} }
`; `;
exports[`util/got/index uses basic auth 1`] = `
Object {
"body": Object {},
"options": Object {
"auth": ":test",
"baseUrl": "https://api.github.com/",
"cache": false,
"decompress": true,
"followRedirect": true,
"form": false,
"gotTimeout": Object {
"request": 60000,
},
"hash": "",
"headers": Object {
"accept": "application/json",
"accept-encoding": "gzip, deflate",
"user-agent": "got/9.6.0 (https://github.com/sindresorhus/got)",
},
"hooks": Object {
"afterResponse": Array [],
"beforeError": Array [],
"beforeRedirect": Array [],
"beforeRequest": Array [],
"beforeRetry": Array [],
"init": Array [],
},
"hostname": "api.github.com",
"href": "https://api.github.com/some",
"json": true,
"method": "GET",
"path": "/some",
"pathname": "/some",
"protocol": "https:",
"retry": Object {
"errorCodes": Set {},
"methods": Set {},
"retries": [Function],
"statusCodes": Set {},
},
"search": "",
"stream": false,
"throwHttpErrors": true,
"useElectronNet": false,
},
}
`;
exports[`util/got/index uses basic auth 2`] = `
Object {
"body": Object {},
"options": Object {
"auth": ":test",
"baseUrl": "https://api.github.com/",
"cache": false,
"decompress": true,
"followRedirect": true,
"form": false,
"gotTimeout": Object {
"request": 60000,
},
"hash": "",
"headers": Object {
"accept": "application/json",
"accept-encoding": "gzip, deflate",
"user-agent": "got/9.6.0 (https://github.com/sindresorhus/got)",
},
"hooks": Object {
"afterResponse": Array [],
"beforeError": Array [],
"beforeRedirect": Array [],
"beforeRequest": Array [],
"beforeRetry": Array [],
"init": Array [],
},
"hostname": "api.github.com",
"href": "https://api.github.com/some",
"json": true,
"method": "GET",
"path": "/some",
"pathname": "/some",
"protocol": "https:",
"retry": Object {
"errorCodes": Set {},
"methods": Set {},
"retries": [Function],
"statusCodes": Set {},
},
"search": "",
"stream": false,
"throwHttpErrors": true,
"useElectronNet": false,
},
}
`;
exports[`util/got/index uses bearer auth 1`] = `
Object {
"body": Object {},
"options": Object {
"baseUrl": "https://api.github.com/",
"cache": false,
"decompress": true,
"followRedirect": true,
"form": false,
"hash": "",
"headers": Object {
"accept": "application/json",
"accept-encoding": "gzip, deflate",
"authorization": "Bearer XXX",
"user-agent": "got/9.6.0 (https://github.com/sindresorhus/got)",
},
"hooks": Object {
"afterResponse": Array [],
"beforeError": Array [],
"beforeRedirect": Array [],
"beforeRequest": Array [],
"beforeRetry": Array [],
"init": Array [],
},
"hostname": "api.github.com",
"href": "https://api.github.com/some",
"json": true,
"method": "GET",
"path": "/some",
"pathname": "/some",
"protocol": "https:",
"retry": Object {
"errorCodes": Set {},
"methods": Set {},
"retries": [Function],
"statusCodes": Set {},
},
"search": "",
"stream": false,
"throwHttpErrors": true,
"useElectronNet": false,
},
}
`;
exports[`util/got/index uses bearer auth 2`] = `
Object {
"body": Object {},
"options": Object {
"baseUrl": "https://api.github.com/",
"cache": false,
"decompress": true,
"followRedirect": true,
"form": false,
"hash": "",
"headers": Object {
"accept": "application/json",
"accept-encoding": "gzip, deflate",
"authorization": "Bearer XXX",
"user-agent": "got/9.6.0 (https://github.com/sindresorhus/got)",
},
"hooks": Object {
"afterResponse": Array [],
"beforeError": Array [],
"beforeRedirect": Array [],
"beforeRequest": Array [],
"beforeRetry": Array [],
"init": Array [],
},
"hostname": "api.github.com",
"href": "https://api.github.com/some",
"json": true,
"method": "GET",
"path": "/some",
"pathname": "/some",
"protocol": "https:",
"retry": Object {
"errorCodes": Set {},
"methods": Set {},
"retries": [Function],
"statusCodes": Set {},
},
"search": "",
"stream": false,
"throwHttpErrors": true,
"useElectronNet": false,
},
}
`;
exports[`util/got/index uses private-token auth 1`] = `
Object {
"body": Object {},
"options": Object {
"baseUrl": "https://api.github.com/",
"cache": false,
"decompress": true,
"followRedirect": true,
"form": false,
"hash": "",
"headers": Object {
"Private-token": "XXX",
"accept": "application/json",
"accept-encoding": "gzip, deflate",
"user-agent": "got/9.6.0 (https://github.com/sindresorhus/got)",
},
"hooks": Object {
"afterResponse": Array [],
"beforeError": Array [],
"beforeRedirect": Array [],
"beforeRequest": Array [],
"beforeRetry": Array [],
"init": Array [],
},
"hostType": "gitlab",
"hostname": "api.github.com",
"href": "https://api.github.com/some",
"json": true,
"method": "GET",
"path": "/some",
"pathname": "/some",
"protocol": "https:",
"retry": Object {
"errorCodes": Set {},
"methods": Set {},
"retries": [Function],
"statusCodes": Set {},
},
"search": "",
"stream": false,
"throwHttpErrors": true,
"useElectronNet": false,
},
}
`;
exports[`util/got/index uses token auth 1`] = `
Object {
"body": Object {},
"options": Object {
"baseUrl": "https://api.github.com/",
"cache": false,
"decompress": true,
"followRedirect": true,
"form": false,
"hash": "",
"headers": Object {
"accept": "application/json",
"accept-encoding": "gzip, deflate",
"authorization": "token XXX",
"user-agent": "got/9.6.0 (https://github.com/sindresorhus/got)",
},
"hooks": Object {
"afterResponse": Array [],
"beforeError": Array [],
"beforeRedirect": Array [],
"beforeRequest": Array [],
"beforeRetry": Array [],
"init": Array [],
},
"hostType": "gitea",
"hostname": "api.github.com",
"href": "https://api.github.com/some",
"json": true,
"method": "GET",
"path": "/some",
"pathname": "/some",
"protocol": "https:",
"retry": Object {
"errorCodes": Set {},
"methods": Set {},
"retries": [Function],
"statusCodes": Set {},
},
"search": "",
"stream": false,
"throwHttpErrors": true,
"useElectronNet": false,
},
}
`;
/* eslint-disable no-param-reassign */
import { logger } from '../../logger';
import * as hostRules from '../host-rules';
import { create } from './util';
// Apply host rules to requests
export default create({
options: {},
handler: (options, next) => {
// istanbul ignore if: never happen?
if (!options.hostname) {
return next(options);
}
const { username, password, token, timeout } = hostRules.find({
hostType: options.hostType,
url: options.href,
});
if (options.headers.authorization || options.auth || options.token) {
logger.trace('Authorization already set for host: ' + options.hostname);
} else if (password) {
logger.trace(
'Applying Basic authentication for host ' + options.hostname
);
options.auth = `${username || ''}:${password}`;
} else if (token) {
logger.trace(
'Applying Bearer authentication for host ' + options.hostname
);
options.token = token;
}
if (timeout) {
options.gotTimeout = { request: timeout };
}
return next(options);
},
});
import nock from 'nock'; import nock from 'nock';
import { getName } from '../../../test/util'; import { getName } from '../../../test/util';
import { import { PLATFORM_TYPE_GITHUB } from '../../constants/platforms';
PLATFORM_TYPE_GITEA,
PLATFORM_TYPE_GITHUB,
PLATFORM_TYPE_GITLAB,
} from '../../constants/platforms';
import * as hostRules from '../host-rules'; import * as hostRules from '../host-rules';
import { GotJSONOptions } from './common'; import { GotJSONOptions } from './common';
import { api } from '.'; import { api } from '.';
...@@ -36,39 +32,6 @@ describe(getName(__filename), () => { ...@@ -36,39 +32,6 @@ describe(getName(__filename), () => {
return nock(baseUrl, opts).get('/some').times(times).reply(200, {}); return nock(baseUrl, opts).get('/some').times(times).reply(200, {});
} }
it('uses bearer auth', async () => {
const req = mock({ reqheaders: { authorization: 'Bearer XXX' } }, 2);
hostRules.add({ baseUrl, token: 'XXX' });
expect(await got()).toMatchSnapshot();
expect(await got({ token: 'XXX' })).toMatchSnapshot();
expect(req.isDone()).toBe(true);
});
it('uses basic auth', async () => {
const req = mock({ reqheaders: { authorization: 'Basic OnRlc3Q=' } }, 2);
hostRules.add({ password: 'test', timeout: 60000 });
expect(await got()).toMatchSnapshot();
expect(await got({ auth: ':test' })).toMatchSnapshot();
expect(req.isDone()).toBe(true);
});
it('uses token auth', async () => {
const req = mock({ reqheaders: { authorization: 'token XXX' } });
hostRules.add({ baseUrl, token: 'XXX' });
expect(await got({ hostType: PLATFORM_TYPE_GITEA })).toMatchSnapshot();
expect(req.isDone()).toBe(true);
});
it('uses private-token auth', async () => {
const req = mock({ reqheaders: { 'private-token': 'XXX' } });
hostRules.add({ baseUrl, token: 'XXX' });
expect(await got({ hostType: PLATFORM_TYPE_GITLAB })).toMatchSnapshot();
expect(req.isDone()).toBe(true);
});
it('gets', async () => { it('gets', async () => {
const req = mock({}) const req = mock({})
.head('/some') .head('/some')
......
import got from 'got'; import got from 'got';
import auth from './auth'; import auth from './auth';
import hostRules from './host-rules';
import { mergeInstances } from './util'; import { mergeInstances } from './util';
export * from './common'; export * from './common';
...@@ -10,6 +9,6 @@ export * from './common'; ...@@ -10,6 +9,6 @@ export * from './common';
* - Cache all GET requests for the lifetime of the repo * - Cache all GET requests for the lifetime of the repo
* *
*/ */
export const api = mergeInstances(got, hostRules, auth); export const api = mergeInstances(got, auth);
export default api; export default api;
import { logger } from '../../logger';
import * as hostRules from '../host-rules';
// Apply host rules to requests
export function applyHostRules(url: string, inOptions: any): any {
const options = { ...inOptions };
const foundRules =
hostRules.find({
hostType: options.hostType,
url,
}) || {};
const { username, password, token, timeout } = foundRules;
if (options.headers?.authorization || options.auth || options.token) {
logger.trace('Authorization already set for host: ' + options.hostname);
} else if (password) {
logger.trace('Applying Basic authentication for host ' + options.hostname);
options.auth = `${username || ''}:${password}`;
} else if (token) {
logger.trace('Applying Bearer authentication for host ' + options.hostname);
options.token = token;
}
if (timeout) {
options.timeout = timeout;
}
return options;
}
...@@ -4,6 +4,7 @@ import { GotPromise } from 'got'; ...@@ -4,6 +4,7 @@ import { GotPromise } from 'got';
import * as runCache from '../cache/run'; import * as runCache from '../cache/run';
import { clone } from '../clone'; import { clone } from '../clone';
import got from '../got'; import got from '../got';
import { applyHostRules } from './host-rules';
interface OutgoingHttpHeaders { interface OutgoingHttpHeaders {
[header: string]: number | string | string[] | undefined; [header: string]: number | string | string[] | undefined;
...@@ -55,7 +56,7 @@ export class Http<GetOptions = HttpOptions, PostOptions = HttpPostOptions> { ...@@ -55,7 +56,7 @@ export class Http<GetOptions = HttpOptions, PostOptions = HttpPostOptions> {
url = URL.resolve(httpOptions.baseUrl, url); url = URL.resolve(httpOptions.baseUrl, url);
} }
// TODO: deep merge in order to merge headers // TODO: deep merge in order to merge headers
const options: any = { let options: any = {
method: 'get', method: 'get',
...this.options, ...this.options,
hostType: this.hostType, hostType: this.hostType,
...@@ -88,6 +89,8 @@ export class Http<GetOptions = HttpOptions, PostOptions = HttpPostOptions> { ...@@ -88,6 +89,8 @@ export class Http<GetOptions = HttpOptions, PostOptions = HttpPostOptions> {
'https://github.com/renovatebot/renovate', 'https://github.com/renovatebot/renovate',
}; };
options = applyHostRules(url, options);
// Cache GET requests unless useCache=false // Cache GET requests unless useCache=false
let promisedRes: GotPromise<any>; let promisedRes: GotPromise<any>;
if (options.method === 'get') { if (options.method === 'get') {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment