diff --git a/lib/modules/datasource/metadata.ts b/lib/modules/datasource/metadata.ts index cbe96e040eb5ad46267ab499e90b9d71a73e630b..c0b1cd6a5de6f3f58c27acf402a99d847f9240c7 100644 --- a/lib/modules/datasource/metadata.ts +++ b/lib/modules/datasource/metadata.ts @@ -5,7 +5,7 @@ import { detectPlatform } from '../../util/common'; import { parseGitUrl } from '../../util/git/url'; import * as hostRules from '../../util/host-rules'; import { regEx } from '../../util/regex'; -import { parseUrl, trimTrailingSlash, validateUrl } from '../../util/url'; +import { isHttpUrl, parseUrl, trimTrailingSlash } from '../../util/url'; import { manualChangelogUrls, manualSourceUrls } from './metadata-manual'; import type { ReleaseResult } from './types'; @@ -195,7 +195,7 @@ export function addMetaData( ]; for (const urlKey of urlKeys) { const urlVal = dep[urlKey]; - if (is.string(urlVal) && validateUrl(urlVal.trim())) { + if (is.string(urlVal) && isHttpUrl(urlVal.trim())) { dep[urlKey] = urlVal.trim() as never; } else { delete dep[urlKey]; diff --git a/lib/modules/datasource/npm/npmrc.ts b/lib/modules/datasource/npm/npmrc.ts index ad605fe4ff2bc727c8cdd5e5bf27dcfb40b20ca7..73b2e1eef52896096410b2855b5e55fb953d2e93 100644 --- a/lib/modules/datasource/npm/npmrc.ts +++ b/lib/modules/datasource/npm/npmrc.ts @@ -8,7 +8,7 @@ import type { HostRule } from '../../../types'; import * as hostRules from '../../../util/host-rules'; import { regEx } from '../../../util/regex'; import { fromBase64 } from '../../../util/string'; -import { ensureTrailingSlash, validateUrl } from '../../../util/url'; +import { ensureTrailingSlash, isHttpUrl } from '../../../util/url'; import { defaultRegistryUrls } from './common'; import type { NpmrcRules } from './types'; @@ -89,7 +89,7 @@ export function convertNpmrcToRules(npmrc: Record<string, any>): NpmrcRules { const { registry } = npmrc; // packageRules order matters, so look for a default registry first if (is.nonEmptyString(registry)) { - if (validateUrl(registry)) { + if (isHttpUrl(registry)) { // Default registry rules.packageRules?.push({ matchDatasources, @@ -108,7 +108,7 @@ export function convertNpmrcToRules(npmrc: Record<string, any>): NpmrcRules { const keyType = keyParts.pop(); if (keyType === 'registry' && keyParts.length && is.nonEmptyString(value)) { const scope = keyParts.join(':'); - if (validateUrl(value)) { + if (isHttpUrl(value)) { rules.packageRules?.push({ matchDatasources, matchPackagePrefixes: [scope + '/'], diff --git a/lib/modules/datasource/terraform-module/index.ts b/lib/modules/datasource/terraform-module/index.ts index 9476cef7e5c3c35caf59f9ef670e2754b9c63fcf..fe89239f194926db268859e95d9ce46ab472fdc5 100644 --- a/lib/modules/datasource/terraform-module/index.ts +++ b/lib/modules/datasource/terraform-module/index.ts @@ -2,7 +2,7 @@ import { logger } from '../../../logger'; import { cache } from '../../../util/cache/package/decorator'; import { regEx } from '../../../util/regex'; import { coerceString } from '../../../util/string'; -import { validateUrl } from '../../../util/url'; +import { isHttpUrl } from '../../../util/url'; import * as hashicorpVersioning from '../../versioning/hashicorp'; import type { GetReleasesConfig, ReleaseResult } from '../types'; import { TerraformDatasource } from './base'; @@ -162,7 +162,7 @@ export class TerraformModuleDatasource extends TerraformDatasource { }; // Add the source URL if given - if (validateUrl(res.modules[0].source)) { + if (isHttpUrl(res.modules[0].source)) { dep.sourceUrl = res.modules[0].source; } diff --git a/lib/modules/datasource/terraform-module/utils.ts b/lib/modules/datasource/terraform-module/utils.ts index e3449faa23f039a11bdc6e2507568be54bffe418..b6f981f1dc6d88c2d8f0df1c991cbcd31febc5cb 100644 --- a/lib/modules/datasource/terraform-module/utils.ts +++ b/lib/modules/datasource/terraform-module/utils.ts @@ -1,4 +1,4 @@ -import { joinUrlParts, validateUrl } from '../../../util/url'; +import { isHttpUrl, joinUrlParts } from '../../../util/url'; import type { ServiceDiscoveryEndpointType, ServiceDiscoveryResult, @@ -12,7 +12,7 @@ export function createSDBackendURL( ): string { const sdEndpoint = sdResult[sdType] ?? ''; const fullPath = joinUrlParts(sdEndpoint, subPath); - if (validateUrl(fullPath)) { + if (isHttpUrl(fullPath)) { return fullPath; } return joinUrlParts(registryURL, fullPath); diff --git a/lib/modules/manager/npm/post-update/rules.ts b/lib/modules/manager/npm/post-update/rules.ts index 116704478acffd5231d5678209bfe50150914bd3..59380f7a616a968bd9164ff26ea1a979a07b5adb 100644 --- a/lib/modules/manager/npm/post-update/rules.ts +++ b/lib/modules/manager/npm/post-update/rules.ts @@ -2,7 +2,7 @@ import is from '@sindresorhus/is'; import * as hostRules from '../../../../util/host-rules'; import { regEx } from '../../../../util/regex'; import { toBase64 } from '../../../../util/string'; -import { validateUrl } from '../../../../util/url'; +import { isHttpUrl } from '../../../../util/url'; export interface HostRulesResult { additionalNpmrcContent: string[]; @@ -21,7 +21,7 @@ export function processHostRules(): HostRulesResult { if (hostRule.resolvedHost) { let uri = hostRule.matchHost; uri = - is.string(uri) && validateUrl(uri) + is.string(uri) && isHttpUrl(uri) ? uri.replace(regEx(/^https?:/), '') : // TODO: types (#22198) `//${uri}/`; diff --git a/lib/util/git/auth.ts b/lib/util/git/auth.ts index d22abd171634120440d1695a6774c02bc7d21c77..c776b3c4831031e3273e1dc63ba2b969c8a5a54b 100644 --- a/lib/util/git/auth.ts +++ b/lib/util/git/auth.ts @@ -4,7 +4,7 @@ import type { HostRule } from '../../types'; import { detectPlatform } from '../common'; import { find, getAll } from '../host-rules'; import { regEx } from '../regex'; -import { createURLFromHostOrURL, validateUrl } from '../url'; +import { createURLFromHostOrURL, isHttpUrl } from '../url'; import type { AuthenticationRule } from './types'; import { parseGitUrl } from './url'; @@ -203,7 +203,7 @@ function addAuthFromHostRule( ): NodeJS.ProcessEnv { let environmentVariables = env; const httpUrl = createURLFromHostOrURL(hostRule.matchHost!)?.toString(); - if (validateUrl(httpUrl)) { + if (isHttpUrl(httpUrl)) { logger.trace(`Adding Git authentication for ${httpUrl} using token auth.`); environmentVariables = getGitAuthenticatedEnvironmentVariables( httpUrl!, diff --git a/lib/util/host-rules.ts b/lib/util/host-rules.ts index 39ff6b65e006d06de02a5f25e95c92b82a725044..bae2c3f5c160b7908a946641343e076f177f2a75 100644 --- a/lib/util/host-rules.ts +++ b/lib/util/host-rules.ts @@ -6,7 +6,7 @@ import type { CombinedHostRule, HostRule } from '../types'; import { clone } from './clone'; import * as sanitize from './sanitize'; import { toBase64 } from './string'; -import { parseUrl, validateUrl } from './url'; +import { isHttpUrl, parseUrl } from './url'; let hostRules: HostRule[] = []; @@ -108,7 +108,7 @@ function isOnlyMatchHost( } function matchesHost(url: string, matchHost: string): boolean { - if (validateUrl(url) && validateUrl(matchHost)) { + if (isHttpUrl(url) && isHttpUrl(matchHost)) { return url.startsWith(matchHost); } diff --git a/lib/util/http/gerrit.ts b/lib/util/http/gerrit.ts index a163da021fc5ee33fa17e2117e56e14694e1d4b8..a690ba951b3147e660566b4670228e475dcaa58d 100644 --- a/lib/util/http/gerrit.ts +++ b/lib/util/http/gerrit.ts @@ -1,6 +1,6 @@ import { parseJson } from '../common'; import { regEx } from '../regex'; -import { validateUrl } from '../url'; +import { isHttpUrl } from '../url'; import type { HttpOptions, HttpResponse, InternalHttpOptions } from './types'; import { Http } from './index'; @@ -24,7 +24,7 @@ export class GerritHttp extends Http { path: string, options?: InternalHttpOptions, ): Promise<HttpResponse<T>> { - const url = validateUrl(path) ? path : baseUrl + path; + const url = isHttpUrl(path) ? path : baseUrl + path; const opts: InternalHttpOptions = { parseJson: (text: string) => parseJson(text.replace(GerritHttp.magicPrefix, ''), path), diff --git a/lib/util/url.spec.ts b/lib/util/url.spec.ts index cbc946437275548e7856400b9abb334450c8955b..a0c65cb7ae27b1bc57873dee1f361bec28e3e4fb 100644 --- a/lib/util/url.spec.ts +++ b/lib/util/url.spec.ts @@ -3,6 +3,7 @@ import { ensurePathPrefix, ensureTrailingSlash, getQueryString, + isHttpUrl, joinUrlParts, parseLinkHeader, parseUrl, @@ -10,7 +11,6 @@ import { resolveBaseUrl, trimSlashes, trimTrailingSlash, - validateUrl, } from './url'; describe('util/url', () => { @@ -97,15 +97,14 @@ describe('util/url', () => { expect(getQueryString({ a: 1, b: [1, 2] })).toBe('a=1&b=1&b=2'); }); - it('validates URLs', () => { - expect(validateUrl(undefined)).toBeFalse(); - expect(validateUrl('')).toBeFalse(); - expect(validateUrl(null)).toBeFalse(); - expect(validateUrl('foo')).toBeFalse(); - expect(validateUrl('ssh://github.com')).toBeFalse(); - expect(validateUrl('http://github.com')).toBeTrue(); - expect(validateUrl('https://github.com')).toBeTrue(); - expect(validateUrl('https://github.com', false)).toBeTrue(); + it('validates http-based URLs', () => { + expect(isHttpUrl(undefined)).toBeFalse(); + expect(isHttpUrl('')).toBeFalse(); + expect(isHttpUrl(null)).toBeFalse(); + expect(isHttpUrl('foo')).toBeFalse(); + expect(isHttpUrl('ssh://github.com')).toBeFalse(); + expect(isHttpUrl('http://github.com')).toBeTrue(); + expect(isHttpUrl('https://github.com')).toBeTrue(); }); it('parses URL', () => { diff --git a/lib/util/url.ts b/lib/util/url.ts index c28d421e41c389b3a876802e4f2c8682579db0ec..9ac957233127ff2305cb3fd08fe627c6d2ec73c5 100644 --- a/lib/util/url.ts +++ b/lib/util/url.ts @@ -85,16 +85,13 @@ export function getQueryString(params: Record<string, any>): string { return usp.toString(); } -export function validateUrl( - url: string | null | undefined, - httpOnly = true, -): boolean { +export function isHttpUrl(url: unknown): boolean { if (!is.nonEmptyString(url)) { return false; } try { const { protocol } = new URL(url); - return httpOnly ? !!protocol.startsWith('http') : !!protocol; + return protocol === 'https:' || protocol === 'http:'; } catch (err) { return false; } diff --git a/lib/workers/repository/update/pr/changelog/release-notes.ts b/lib/workers/repository/update/pr/changelog/release-notes.ts index 79d62f5d0ade941ca637356fafae836cb51a5c75..bdf4a34bd637ffe7fce5c043d0da6b245885ca14 100644 --- a/lib/workers/repository/update/pr/changelog/release-notes.ts +++ b/lib/workers/repository/update/pr/changelog/release-notes.ts @@ -9,7 +9,7 @@ import { detectPlatform } from '../../../../../util/common'; import { linkify } from '../../../../../util/markdown'; import { newlineRegex, regEx } from '../../../../../util/regex'; import { coerceString } from '../../../../../util/string'; -import { validateUrl } from '../../../../../util/url'; +import { isHttpUrl } from '../../../../../util/url'; import type { BranchUpgradeConfig } from '../../../../types'; import * as bitbucket from './bitbucket'; import * as gitea from './gitea'; @@ -346,12 +346,12 @@ export async function getReleaseNotesMd( .filter(Boolean); let body = section.replace(regEx(/.*?\n(-{3,}\n)?/), '').trim(); for (const word of title) { - if (word.includes(version) && !validateUrl(word)) { + if (word.includes(version) && !isHttpUrl(word)) { logger.trace({ body }, 'Found release notes for v' + version); // TODO: fix url const notesSourceUrl = `${baseUrl}${repository}/blob/HEAD/${changelogFile}`; const mdHeadingLink = title - .filter((word) => !validateUrl(word)) + .filter((word) => !isHttpUrl(word)) .join('-') .replace(regEx(/[^A-Za-z0-9-]/g), ''); const url = `${notesSourceUrl}#${mdHeadingLink}`;