diff --git a/pkg/harvester/validators/vm-image.js b/pkg/harvester/validators/vm-image.js index 214b0fe5958..9ee35a7d489 100644 --- a/pkg/harvester/validators/vm-image.js +++ b/pkg/harvester/validators/vm-image.js @@ -2,6 +2,35 @@ import { HCI } from '@pkg/harvester/config/labels-annotations'; export const VM_IMAGE_FILE_FORMAT = ['qcow', 'qcow2', 'raw', 'img', 'iso']; +/** + * Extracts the filename from a URL, handling query parameters and fragments + * @param {string} url - The URL to parse + * @returns {string} - The filename without query params or fragments + */ +function getFilenameFromUrl(url) { + try { + // Try to parse as a full URL + const urlObj = new URL(url); + // Get pathname and extract the last segment + const pathname = urlObj.pathname; + return pathname.split('/').pop() || ''; + } catch (e) { + // If URL parsing fails, treat as a relative path + // Remove query params and fragments manually + const cleanUrl = url.split('?')[0].split('#')[0]; + return cleanUrl.split('/').pop() || ''; + } +} + +/** + * Validates image URL format + * @param {string} url - The image URL to validate + * @param {object} getters - Vuex getters + * @param {array} errors - Array to collect validation errors + * @param {any} validatorArgs - Additional validator arguments + * @param {string} type - Type of validation ('file' or other) + * @returns {array} - Array of validation errors + */ export function imageUrl(url, getters, errors, validatorArgs, type) { const t = getters['i18n/t']; @@ -9,12 +38,20 @@ export function imageUrl(url, getters, errors, validatorArgs, type) { return errors; } - const suffixName = url.split('/').pop(); - const fileSuffix = suffixName.split('.').pop().toLowerCase(); + // Extract filename, handling query parameters and fragments + const filename = getFilenameFromUrl(url); + + if (!filename) { + const tipString = type === 'file' ? 'harvester.validation.image.ruleFileTip' : 'harvester.validation.image.ruleTip'; + errors.push(t(tipString)); + return errors; + } + + // Get file extension + const fileSuffix = filename.split('.').pop().toLowerCase(); if (!VM_IMAGE_FILE_FORMAT.includes(fileSuffix)) { const tipString = type === 'file' ? 'harvester.validation.image.ruleFileTip' : 'harvester.validation.image.ruleTip'; - errors.push(t(tipString)); } @@ -29,4 +66,4 @@ export function fileRequired(annotations = {}, getters, errors, validatorArgs, t } return errors; -} +} \ No newline at end of file