diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 513de297c9dab6806a5e33c1c2f5f1e424280be4..ec9023d4682464d3ac3dfe8da349724e95e1b91b 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -922,6 +922,12 @@ Example for configuring `docker` auth: } ``` +If multiple `hostRules` match a request, then they will be applied in the following order/priority: + +1. rules with only `hostType` specified +1. rules with only `matchHost` specified (sorted by `matchHost` length if multiple match) +1. rules with both `matchHost` and `hostType` specified (sorted by `matchHost` length if multiple match) + To disable requests to a particular host, you can configure a rule like: ```json diff --git a/lib/util/host-rules.spec.ts b/lib/util/host-rules.spec.ts index 449b7337705495459bdfdc97c1ae8b1075b23824..122d260ae250cd4a82c5285f98fe385130cee294 100644 --- a/lib/util/host-rules.spec.ts +++ b/lib/util/host-rules.spec.ts @@ -114,18 +114,18 @@ describe('util/host-rules', () => { matchHost: 'https://api.github.com', token: 'abc', }); - // Initialized generic host rule for github platform - add({ - hostType: PlatformId.Github, - matchHost: 'https://api.github.com', - token: 'abc', - }); // specific host rule for using other token in different org add({ hostType: PlatformId.Github, matchHost: 'https://api.github.com/repos/org-b/', token: 'def', }); + // Initialized generic host rule for github platform + add({ + hostType: PlatformId.Github, + matchHost: 'https://api.github.com', + token: 'abc', + }); expect( find({ hostType: PlatformId.Github, @@ -237,6 +237,21 @@ describe('util/host-rules', () => { }) ).toEqual({ token: 'abc' }); }); + it('matches shortest matchHost first', () => { + add({ + matchHost: 'https://nuget.local/api', + token: 'longest', + } as any); + add({ + matchHost: 'https://nuget.local/', + token: 'shortest', + } as any); + expect( + find({ + url: 'https://nuget.local/api/sub-resource', + }) + ).toEqual({ token: 'longest' }); + }); it('returns hosts', () => { add({ hostType: NugetDatasource.id, diff --git a/lib/util/host-rules.ts b/lib/util/host-rules.ts index 2e80cdfa883d549b35df688ed36d5d14959e6fbe..2a7adac71ba6f6e885072dfe812144cf19195679 100644 --- a/lib/util/host-rules.ts +++ b/lib/util/host-rules.ts @@ -110,6 +110,14 @@ function matchesHost(rule: HostRule, search: HostRuleSearch): boolean { return hostname === rule.matchHost || hostname.endsWith(dotPrefixedMatchHost); } +function prioritizeLongestMatchHost(rule1: HostRule, rule2: HostRule): number { + // istanbul ignore if: won't happen in practice + if (!rule1.matchHost || !rule2.matchHost) { + return 0; + } + return rule1.matchHost.length - rule2.matchHost.length; +} + export function find(search: HostRuleSearch): HostRule { if (!(search.hostType || search.url)) { logger.warn({ search }, 'Invalid hostRules search'); @@ -130,6 +138,7 @@ export function find(search: HostRuleSearch): HostRule { }); hostRules .filter((rule) => isHostOnlyRule(rule) && matchesHost(rule, search)) + .sort(prioritizeLongestMatchHost) .forEach((rule) => { res = merge(res, rule); }); @@ -141,6 +150,7 @@ export function find(search: HostRuleSearch): HostRule { matchesHostType(rule, search) && matchesHost(rule, search) ) + .sort(prioritizeLongestMatchHost) .forEach((rule) => { res = merge(res, rule); });