450 lines
15 KiB
C#
450 lines
15 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using UnityEngine;
|
||
|
||
namespace Zion.ERP.Inventory
|
||
{
|
||
/// <summary>
|
||
/// API配置验证器
|
||
/// </summary>
|
||
public static class ApiConfigValidator
|
||
{
|
||
/// <summary>
|
||
/// 验证结果
|
||
/// </summary>
|
||
public class ValidationResult
|
||
{
|
||
/// <summary>
|
||
/// 是否验证通过
|
||
/// </summary>
|
||
public bool IsValid { get; set; }
|
||
|
||
/// <summary>
|
||
/// 错误信息列表
|
||
/// </summary>
|
||
public List<string> Errors { get; set; } = new List<string>();
|
||
|
||
/// <summary>
|
||
/// 警告信息列表
|
||
/// </summary>
|
||
public List<string> Warnings { get; set; } = new List<string>();
|
||
|
||
/// <summary>
|
||
/// 验证通过的信息
|
||
/// </summary>
|
||
public List<string> Info { get; set; } = new List<string>();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证API配置
|
||
/// </summary>
|
||
/// <param name="config">配置数据</param>
|
||
/// <returns>验证结果</returns>
|
||
public static ValidationResult Validate(ApiConfigData config)
|
||
{
|
||
var result = new ValidationResult();
|
||
|
||
if (config == null)
|
||
{
|
||
result.IsValid = false;
|
||
result.Errors.Add("配置数据为空");
|
||
return result;
|
||
}
|
||
|
||
// 验证基本信息
|
||
ValidateBasicInfo(config, result);
|
||
|
||
// 验证环境配置
|
||
ValidateEnvironments(config, result);
|
||
|
||
// 验证API接口配置
|
||
ValidateEndpoints(config, result);
|
||
|
||
// 验证全局参数
|
||
ValidateGlobalParameters(config, result);
|
||
|
||
// 验证配置完整性
|
||
ValidateCompleteness(config, result);
|
||
|
||
// 设置验证结果
|
||
result.IsValid = result.Errors.Count == 0;
|
||
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证基本信息
|
||
/// </summary>
|
||
private static void ValidateBasicInfo(ApiConfigData config, ValidationResult result)
|
||
{
|
||
if (string.IsNullOrEmpty(config.Version))
|
||
{
|
||
result.Errors.Add("版本号不能为空");
|
||
}
|
||
else if (!IsValidVersion(config.Version))
|
||
{
|
||
result.Errors.Add($"版本号格式不正确:{config.Version}");
|
||
}
|
||
|
||
if (string.IsNullOrEmpty(config.Description))
|
||
{
|
||
result.Warnings.Add("建议添加配置描述");
|
||
}
|
||
|
||
result.Info.Add($"配置版本:{config.Version}");
|
||
result.Info.Add($"当前环境:{config.CurrentEnvironment}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证环境配置
|
||
/// </summary>
|
||
private static void ValidateEnvironments(ApiConfigData config, ValidationResult result)
|
||
{
|
||
if (config.Environments == null || config.Environments.Count == 0)
|
||
{
|
||
result.Errors.Add("未配置任何环境");
|
||
return;
|
||
}
|
||
|
||
// 检查环境名称重复
|
||
var environmentNames = config.Environments.Select(e => e.Environment).ToList();
|
||
var duplicateEnvironments = environmentNames.GroupBy(x => x).Where(g => g.Count() > 1).Select(g => g.Key);
|
||
foreach (var env in duplicateEnvironments)
|
||
{
|
||
result.Errors.Add($"环境名称重复:{env}");
|
||
}
|
||
|
||
// 验证每个环境配置
|
||
foreach (var env in config.Environments)
|
||
{
|
||
ValidateEnvironment(env, result);
|
||
}
|
||
|
||
// 检查当前环境是否存在
|
||
var currentEnv = config.Environments.FirstOrDefault(e => e.Environment == config.CurrentEnvironment);
|
||
if (currentEnv == null)
|
||
{
|
||
result.Errors.Add($"当前环境 {config.CurrentEnvironment} 不存在");
|
||
}
|
||
else if (!currentEnv.IsEnabled)
|
||
{
|
||
result.Warnings.Add($"当前环境 {config.CurrentEnvironment} 未启用");
|
||
}
|
||
|
||
result.Info.Add($"配置了 {config.Environments.Count} 个环境");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证单个环境配置
|
||
/// </summary>
|
||
private static void ValidateEnvironment(ApiEnvironmentConfig env, ValidationResult result)
|
||
{
|
||
if (string.IsNullOrEmpty(env.BaseUrl))
|
||
{
|
||
result.Errors.Add($"环境 {env.Environment} 的基础URL不能为空");
|
||
}
|
||
else if (!IsValidUrl(env.BaseUrl))
|
||
{
|
||
result.Errors.Add($"环境 {env.Environment} 的基础URL格式不正确:{env.BaseUrl}");
|
||
}
|
||
|
||
if (env.DefaultTimeout <= 0)
|
||
{
|
||
result.Errors.Add($"环境 {env.Environment} 的默认超时时间必须大于0");
|
||
}
|
||
|
||
if (env.DefaultRetryCount < 0)
|
||
{
|
||
result.Errors.Add($"环境 {env.Environment} 的默认重试次数不能为负数");
|
||
}
|
||
|
||
if (string.IsNullOrEmpty(env.Description))
|
||
{
|
||
result.Warnings.Add($"建议为环境 {env.Environment} 添加描述");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证API接口配置
|
||
/// </summary>
|
||
private static void ValidateEndpoints(ApiConfigData config, ValidationResult result)
|
||
{
|
||
if (config.Endpoints == null || config.Endpoints.Count == 0)
|
||
{
|
||
result.Warnings.Add("未配置任何API接口");
|
||
return;
|
||
}
|
||
|
||
// 检查接口名称重复
|
||
var endpointNames = config.Endpoints.Select(e => e.Name).ToList();
|
||
var duplicateEndpoints = endpointNames.GroupBy(x => x).Where(g => g.Count() > 1).Select(g => g.Key);
|
||
foreach (var endpoint in duplicateEndpoints)
|
||
{
|
||
result.Errors.Add($"API接口名称重复:{endpoint}");
|
||
}
|
||
|
||
// 验证每个接口配置
|
||
foreach (var endpoint in config.Endpoints)
|
||
{
|
||
ValidateEndpoint(endpoint, result);
|
||
}
|
||
|
||
result.Info.Add($"配置了 {config.Endpoints.Count} 个API接口");
|
||
result.Info.Add($"启用了 {config.Endpoints.Count(e => e.IsEnabled)} 个API接口");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证单个API接口配置
|
||
/// </summary>
|
||
private static void ValidateEndpoint(ApiEndpoint endpoint, ValidationResult result)
|
||
{
|
||
if (string.IsNullOrEmpty(endpoint.Name))
|
||
{
|
||
result.Errors.Add("API接口名称不能为空");
|
||
}
|
||
else if (!IsValidEndpointName(endpoint.Name))
|
||
{
|
||
result.Errors.Add($"API接口名称格式不正确:{endpoint.Name}");
|
||
}
|
||
|
||
if (string.IsNullOrEmpty(endpoint.Description))
|
||
{
|
||
result.Warnings.Add($"建议为API接口 {endpoint.Name} 添加描述");
|
||
}
|
||
|
||
if (string.IsNullOrEmpty(endpoint.UrlTemplate))
|
||
{
|
||
result.Errors.Add($"API接口 {endpoint.Name} 的URL模板不能为空");
|
||
}
|
||
else
|
||
{
|
||
ValidateUrlTemplate(endpoint.UrlTemplate, endpoint.Name, result);
|
||
}
|
||
|
||
if (string.IsNullOrEmpty(endpoint.Method))
|
||
{
|
||
result.Errors.Add($"API接口 {endpoint.Name} 的HTTP方法不能为空");
|
||
}
|
||
else if (!IsValidHttpMethod(endpoint.Method))
|
||
{
|
||
result.Errors.Add($"API接口 {endpoint.Name} 的HTTP方法不正确:{endpoint.Method}");
|
||
}
|
||
|
||
if (endpoint.Timeout <= 0)
|
||
{
|
||
result.Errors.Add($"API接口 {endpoint.Name} 的超时时间必须大于0");
|
||
}
|
||
|
||
if (endpoint.RetryCount < 0)
|
||
{
|
||
result.Errors.Add($"API接口 {endpoint.Name} 的重试次数不能为负数");
|
||
}
|
||
|
||
// 验证参数配置
|
||
if (endpoint.Parameters != null)
|
||
{
|
||
foreach (var param in endpoint.Parameters)
|
||
{
|
||
ValidateParameter(param, $"API接口 {endpoint.Name}", result);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证URL模板
|
||
/// </summary>
|
||
private static void ValidateUrlTemplate(string urlTemplate, string endpointName, ValidationResult result)
|
||
{
|
||
// 检查是否包含必需的基础URL占位符
|
||
if (!urlTemplate.Contains("{BaseUrl}") && !urlTemplate.StartsWith("http"))
|
||
{
|
||
result.Errors.Add($"API接口 {endpointName} 的URL模板缺少基础URL占位符或完整的URL");
|
||
}
|
||
|
||
// 检查占位符格式
|
||
var placeholders = ExtractPlaceholders(urlTemplate);
|
||
foreach (var placeholder in placeholders)
|
||
{
|
||
if (!IsValidPlaceholder(placeholder))
|
||
{
|
||
result.Warnings.Add($"API接口 {endpointName} 的URL模板包含未知占位符:{placeholder}");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证全局参数
|
||
/// </summary>
|
||
private static void ValidateGlobalParameters(ApiConfigData config, ValidationResult result)
|
||
{
|
||
if (config.GlobalParameters == null || config.GlobalParameters.Count == 0)
|
||
{
|
||
result.Info.Add("未配置全局参数");
|
||
return;
|
||
}
|
||
|
||
// 检查参数名称重复
|
||
var paramNames = config.GlobalParameters.Select(p => p.Name).ToList();
|
||
var duplicateParams = paramNames.GroupBy(x => x).Where(g => g.Count() > 1).Select(g => g.Key);
|
||
foreach (var param in duplicateParams)
|
||
{
|
||
result.Errors.Add($"全局参数名称重复:{param}");
|
||
}
|
||
|
||
// 验证每个参数
|
||
foreach (var param in config.GlobalParameters)
|
||
{
|
||
ValidateParameter(param, "全局参数", result);
|
||
}
|
||
|
||
result.Info.Add($"配置了 {config.GlobalParameters.Count} 个全局参数");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证单个参数
|
||
/// </summary>
|
||
private static void ValidateParameter(ApiParameter param, string context, ValidationResult result)
|
||
{
|
||
if (string.IsNullOrEmpty(param.Name))
|
||
{
|
||
result.Errors.Add($"{context} 参数名称不能为空");
|
||
}
|
||
|
||
if (param.IsRequired && string.IsNullOrEmpty(param.Value))
|
||
{
|
||
result.Errors.Add($"{context} {param.Name} 是必需参数,但值为空");
|
||
}
|
||
|
||
if (string.IsNullOrEmpty(param.Description))
|
||
{
|
||
result.Warnings.Add($"建议为{context} {param.Name} 添加描述");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证配置完整性
|
||
/// </summary>
|
||
private static void ValidateCompleteness(ApiConfigData config, ValidationResult result)
|
||
{
|
||
// 检查是否有启用的环境
|
||
var enabledEnvironments = config.Environments?.Where(e => e.IsEnabled).ToList();
|
||
if (enabledEnvironments == null || enabledEnvironments.Count == 0)
|
||
{
|
||
result.Errors.Add("没有启用的环境配置");
|
||
}
|
||
|
||
// 检查是否有启用的API接口
|
||
var enabledEndpoints = config.Endpoints?.Where(e => e.IsEnabled).ToList();
|
||
if (enabledEndpoints == null || enabledEndpoints.Count == 0)
|
||
{
|
||
result.Warnings.Add("没有启用的API接口");
|
||
}
|
||
|
||
// 检查配置的完整性
|
||
if (config.Environments != null && config.Environments.Count > 0 &&
|
||
config.Endpoints != null && config.Endpoints.Count > 0)
|
||
{
|
||
result.Info.Add("配置结构完整");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证版本号格式
|
||
/// </summary>
|
||
private static bool IsValidVersion(string version)
|
||
{
|
||
return System.Text.RegularExpressions.Regex.IsMatch(version, @"^\d+\.\d+\.\d+$");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证URL格式
|
||
/// </summary>
|
||
private static bool IsValidUrl(string url)
|
||
{
|
||
return Uri.TryCreate(url, UriKind.Absolute, out _);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证API接口名称格式
|
||
/// </summary>
|
||
private static bool IsValidEndpointName(string name)
|
||
{
|
||
return System.Text.RegularExpressions.Regex.IsMatch(name, @"^[A-Za-z][A-Za-z0-9_]*$");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证HTTP方法
|
||
/// </summary>
|
||
private static bool IsValidHttpMethod(string method)
|
||
{
|
||
var validMethods = new[] { "GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS" };
|
||
return validMethods.Contains(method.ToUpper());
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证占位符
|
||
/// </summary>
|
||
private static bool IsValidPlaceholder(string placeholder)
|
||
{
|
||
var validPlaceholders = new[] { "BaseUrl", "PaperId", "ExamRoomId" };
|
||
return validPlaceholders.Contains(placeholder);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 提取URL模板中的占位符
|
||
/// </summary>
|
||
private static List<string> ExtractPlaceholders(string urlTemplate)
|
||
{
|
||
var placeholders = new List<string>();
|
||
var matches = System.Text.RegularExpressions.Regex.Matches(urlTemplate, @"\{([^}]+)\}");
|
||
foreach (System.Text.RegularExpressions.Match match in matches)
|
||
{
|
||
placeholders.Add(match.Groups[1].Value);
|
||
}
|
||
return placeholders;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 打印验证结果
|
||
/// </summary>
|
||
public static void PrintValidationResult(ValidationResult result)
|
||
{
|
||
if (result.IsValid)
|
||
{
|
||
Debug.Log("✅ API配置验证通过");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("❌ API配置验证失败");
|
||
}
|
||
|
||
if (result.Errors.Count > 0)
|
||
{
|
||
Debug.LogError("错误信息:");
|
||
foreach (var error in result.Errors)
|
||
{
|
||
Debug.LogError($" - {error}");
|
||
}
|
||
}
|
||
|
||
if (result.Warnings.Count > 0)
|
||
{
|
||
Debug.LogWarning("警告信息:");
|
||
foreach (var warning in result.Warnings)
|
||
{
|
||
Debug.LogWarning($" - {warning}");
|
||
}
|
||
}
|
||
|
||
if (result.Info.Count > 0)
|
||
{
|
||
Debug.Log("信息:");
|
||
foreach (var info in result.Info)
|
||
{
|
||
Debug.Log($" - {info}");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} |