CORSRule.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. using System;
  2. using System.Collections.Generic;
  3. namespace Aliyun.OSS
  4. {
  5. /// <summary>
  6. /// 表示一条CORS规则。
  7. /// </summary>
  8. public class CORSRule
  9. {
  10. private IList<String> _allowedOrigins = new List<String>();
  11. private IList<String> _allowedMethods = new List<String>();
  12. private IList<String> _allowedHeaders = new List<String>();
  13. private IList<String> _exposeHeaders = new List<String>();
  14. private Int32 _maxAgeSeconds;
  15. /// <summary>
  16. /// 指定允许的跨域请求的来源,允许使用多个元素来指定多个允许的来源。
  17. /// 允许使用最多一个*通配符。如果指定为“ *”则表示允许所有的来源的跨域请求。
  18. /// </summary>
  19. public IList<String> AllowedOrigins
  20. {
  21. get { return ((List<string>) _allowedOrigins).AsReadOnly(); }
  22. set
  23. {
  24. if (CountOfAsterisk(value) > 1)
  25. throw new ArgumentException("At most one asterisk wildcard allowed.");
  26. _allowedOrigins = value;
  27. }
  28. }
  29. /// <summary>
  30. /// 指定允许的跨域请求方法(GET,PUT,DELETE,POST,HEAD)。
  31. /// </summary>
  32. public IList<String> AllowedMethods
  33. {
  34. get { return ((List<string>)_allowedMethods).AsReadOnly(); }
  35. set { _allowedMethods = value; }
  36. }
  37. /// <summary>
  38. /// 控制在 OPTIONS 预取指令中 Access-Control-Request-Headers 头中指定的 header
  39. /// 是否允许。在 Access-Control-Request-Headers 中指定的每个 header 都必须在
  40. /// AllowedHeader 中有一条对应的项。允许使用最多一个*通配符。
  41. /// </summary>
  42. public IList<String> AllowedHeaders
  43. {
  44. get { return ((List<string>)_allowedHeaders).AsReadOnly(); }
  45. set
  46. {
  47. if (CountOfAsterisk(value) > 1)
  48. throw new ArgumentException("At most one asterisk wildcard allowed.");
  49. _allowedHeaders = value;
  50. }
  51. }
  52. /// <summary>
  53. /// 指定允许用户从应用程序中访问的响应头(例如一个 Javascript 的
  54. /// XMLHttpRequest 对象。不允许使用 *通配符。
  55. /// </summary>
  56. public IList<String> ExposeHeaders
  57. {
  58. get { return ((List<string>)_exposeHeaders).AsReadOnly(); }
  59. set
  60. {
  61. if (CountOfAsterisk(value) > 0)
  62. throw new ArgumentException("Asterisk wildcard not allowed.");
  63. _exposeHeaders = value;
  64. }
  65. }
  66. /// <summary>
  67. /// 指定浏览器对特定资源的预取( OPTIONS)请求返回结果的缓存时间,单位为秒,
  68. /// 最大值不超过999999999,且一个 CORSRule 里面最多允许出现一个。
  69. /// </summary>
  70. public Int32 MaxAgeSeconds
  71. {
  72. get { return _maxAgeSeconds; }
  73. set
  74. {
  75. if (value < 0 || value > 999999999)
  76. throw new ArgumentException("MaxAge should not less than 0 or greater than 999999999");
  77. _maxAgeSeconds = value;
  78. }
  79. }
  80. /// <summary>
  81. /// 添加一条AllowedOrigin。
  82. /// </summary>
  83. /// <param name="allowedOrigin">指定允许的跨域请求的来源,允许使用最多一个“*”通配符。 </param>
  84. public void AddAllowedOrigin(String allowedOrigin)
  85. {
  86. if (allowedOrigin == null)
  87. throw new ArgumentNullException("allowedOrigin");
  88. var hasAsterisk = allowedOrigin.Contains("*");
  89. if (hasAsterisk && CountOfAsterisk(_allowedOrigins) > 0)
  90. throw new ArgumentException("At most one asterisk wildcard allowed.");
  91. _allowedOrigins.Add(allowedOrigin);
  92. }
  93. /// <summary>
  94. /// 添加一条AllowedMethod。
  95. /// </summary>
  96. /// <param name="allowedMethod">指定允许的跨域请求方法。 类型:GET,PUT,DELETE,POST,HEAD</param>
  97. public void AddAllowedMethod(String allowedMethod)
  98. {
  99. if (!InAllowedMethods(allowedMethod))
  100. throw new ArgumentException("allowedMethod not in allowed methods(GET/PUT/DELETED/POST/HEAD)");
  101. _allowedMethods.Add(allowedMethod);
  102. }
  103. /// <summary>
  104. /// 添加一条AllowedHeader。
  105. /// </summary>
  106. /// <param name="allowedHeader">控制在OPTIONS预取指令中Access-Control-Request-Headers头中指定的header是否允许 </param>
  107. public void AddAllowedHeader(String allowedHeader)
  108. {
  109. if (allowedHeader == null)
  110. throw new ArgumentNullException("allowedHeader");
  111. var hasAsterisk = allowedHeader.Contains("*");
  112. if (hasAsterisk && CountOfAsterisk(AllowedHeaders) > 0)
  113. throw new ArgumentException("At most one asterisk wildcard allowed.");
  114. _allowedHeaders.Add(allowedHeader);
  115. }
  116. /// <summary>
  117. /// 添加一条ExposeHeader。
  118. /// </summary>
  119. /// <param name="exposedHeader">指定允许用户从应用程序中访问的响应头(例如一个Javascript的XMLHttpRequest对象)</param>
  120. public void AddExposeHeader(String exposedHeader)
  121. {
  122. if (exposedHeader == null)
  123. throw new ArgumentNullException("exposedHeader");
  124. var hasAsterisk = exposedHeader.Contains("*");
  125. if (hasAsterisk)
  126. throw new ArgumentException("Asterisk wildcard not allowed.");
  127. _exposeHeaders.Add(exposedHeader);
  128. }
  129. /// <summary>
  130. /// 获取*通配符的个数。
  131. /// </summary>
  132. /// <param name="items">获取这些数据里的通配符个数</param>
  133. /// <returns>通配符的个数</returns>
  134. private static int CountOfAsterisk(IEnumerable<string> items)
  135. {
  136. int count = 0;
  137. foreach (var item in items)
  138. {
  139. if (!string.IsNullOrEmpty(item) && item.Trim() == "*")
  140. {
  141. count++;
  142. }
  143. }
  144. return count;
  145. }
  146. /// <summary>
  147. /// 判断某个method是否被允许
  148. /// </summary>
  149. /// <param name="allowedMethod">需要判断的method</param>
  150. /// <returns>是否被允许</returns>
  151. private static bool InAllowedMethods(string allowedMethod)
  152. {
  153. if (string.IsNullOrEmpty(allowedMethod))
  154. throw new ArgumentException("allowedMethod should not be null or empty");
  155. var tmp = allowedMethod.Trim();
  156. if (tmp == "GET" || tmp == "PUT" || tmp == "DELETED" ||
  157. tmp == "POST" || tmp == "HEAD")
  158. {
  159. return true;
  160. }
  161. return false;
  162. }
  163. }
  164. }