2
0

FastGithubConfig.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. using Microsoft.Extensions.Logging;
  2. using Microsoft.Extensions.Options;
  3. using System;
  4. using System.Collections.Concurrent;
  5. using System.Collections.Generic;
  6. using System.Diagnostics.CodeAnalysis;
  7. using System.Linq;
  8. using System.Net;
  9. namespace FastGithub.Configuration
  10. {
  11. /// <summary>
  12. /// FastGithub配置
  13. /// </summary>
  14. public class FastGithubConfig
  15. {
  16. private readonly ILogger<FastGithubConfig> logger;
  17. private SortedDictionary<DomainPattern, DomainConfig> domainConfigs;
  18. private ConcurrentDictionary<string, DomainConfig?> domainConfigCache;
  19. /// <summary>
  20. /// 回退的dns
  21. /// </summary>
  22. public IPEndPoint[] FallbackDns { get; set; }
  23. /// <summary>
  24. /// FastGithub配置
  25. /// </summary>
  26. /// <param name="options"></param>
  27. /// <param name="logger"></param>
  28. public FastGithubConfig(
  29. IOptionsMonitor<FastGithubOptions> options,
  30. ILogger<FastGithubConfig> logger)
  31. {
  32. this.logger = logger;
  33. var opt = options.CurrentValue;
  34. this.FallbackDns = opt.FallbackDns.Select(item => item.ToIPEndPoint()).ToArray();
  35. this.domainConfigs = ConvertDomainConfigs(opt.DomainConfigs);
  36. this.domainConfigCache = new ConcurrentDictionary<string, DomainConfig?>();
  37. options.OnChange(opt => this.Update(opt));
  38. }
  39. /// <summary>
  40. /// 更新配置
  41. /// </summary>
  42. /// <param name="options"></param>
  43. private void Update(FastGithubOptions options)
  44. {
  45. try
  46. {
  47. this.FallbackDns = options.FallbackDns.Select(item => item.ToIPEndPoint()).ToArray();
  48. this.domainConfigs = ConvertDomainConfigs(options.DomainConfigs);
  49. this.domainConfigCache = new ConcurrentDictionary<string, DomainConfig?>();
  50. }
  51. catch (Exception ex)
  52. {
  53. this.logger.LogError(ex.Message);
  54. }
  55. }
  56. /// <summary>
  57. /// 配置转换
  58. /// </summary>
  59. /// <param name="domainConfigs"></param>
  60. /// <returns></returns>
  61. private static SortedDictionary<DomainPattern, DomainConfig> ConvertDomainConfigs(Dictionary<string, DomainConfig> domainConfigs)
  62. {
  63. var result = new SortedDictionary<DomainPattern, DomainConfig>();
  64. foreach (var kv in domainConfigs)
  65. {
  66. result.Add(new DomainPattern(kv.Key), kv.Value);
  67. }
  68. return result;
  69. }
  70. /// <summary>
  71. /// 是否匹配指定的域名
  72. /// </summary>
  73. /// <param name="domain"></param>
  74. /// <returns></returns>
  75. public bool IsMatch(string domain)
  76. {
  77. return this.domainConfigs.Keys.Any(item => item.IsMatch(domain));
  78. }
  79. /// <summary>
  80. /// 尝试获取域名配置
  81. /// </summary>
  82. /// <param name="domain"></param>
  83. /// <param name="value"></param>
  84. /// <returns></returns>
  85. public bool TryGetDomainConfig(string domain, [MaybeNullWhen(false)] out DomainConfig value)
  86. {
  87. value = this.domainConfigCache.GetOrAdd(domain, GetDomainConfig);
  88. return value != null;
  89. DomainConfig? GetDomainConfig(string domain)
  90. {
  91. var key = this.domainConfigs.Keys.FirstOrDefault(item => item.IsMatch(domain));
  92. return key == null ? null : this.domainConfigs[key];
  93. }
  94. }
  95. }
  96. }