FastGithubConfig.cs 3.5 KB

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