using System; using System.Collections.Generic; namespace Aliyun.OSS { /// /// 表示一条CORS规则。 /// public class CORSRule { private IList _allowedOrigins = new List(); private IList _allowedMethods = new List(); private IList _allowedHeaders = new List(); private IList _exposeHeaders = new List(); private Int32 _maxAgeSeconds; /// /// 指定允许的跨域请求的来源,允许使用多个元素来指定多个允许的来源。 /// 允许使用最多一个*通配符。如果指定为“ *”则表示允许所有的来源的跨域请求。 /// public IList AllowedOrigins { get { return ((List) _allowedOrigins).AsReadOnly(); } set { if (CountOfAsterisk(value) > 1) throw new ArgumentException("At most one asterisk wildcard allowed."); _allowedOrigins = value; } } /// /// 指定允许的跨域请求方法(GET,PUT,DELETE,POST,HEAD)。 /// public IList AllowedMethods { get { return ((List)_allowedMethods).AsReadOnly(); } set { _allowedMethods = value; } } /// /// 控制在 OPTIONS 预取指令中 Access-Control-Request-Headers 头中指定的 header /// 是否允许。在 Access-Control-Request-Headers 中指定的每个 header 都必须在 /// AllowedHeader 中有一条对应的项。允许使用最多一个*通配符。 /// public IList AllowedHeaders { get { return ((List)_allowedHeaders).AsReadOnly(); } set { if (CountOfAsterisk(value) > 1) throw new ArgumentException("At most one asterisk wildcard allowed."); _allowedHeaders = value; } } /// /// 指定允许用户从应用程序中访问的响应头(例如一个 Javascript 的 /// XMLHttpRequest 对象。不允许使用 *通配符。 /// public IList ExposeHeaders { get { return ((List)_exposeHeaders).AsReadOnly(); } set { if (CountOfAsterisk(value) > 0) throw new ArgumentException("Asterisk wildcard not allowed."); _exposeHeaders = value; } } /// /// 指定浏览器对特定资源的预取( OPTIONS)请求返回结果的缓存时间,单位为秒, /// 最大值不超过999999999,且一个 CORSRule 里面最多允许出现一个。 /// public Int32 MaxAgeSeconds { get { return _maxAgeSeconds; } set { if (value < 0 || value > 999999999) throw new ArgumentException("MaxAge should not less than 0 or greater than 999999999"); _maxAgeSeconds = value; } } /// /// 添加一条AllowedOrigin。 /// /// 指定允许的跨域请求的来源,允许使用最多一个“*”通配符。 public void AddAllowedOrigin(String allowedOrigin) { if (allowedOrigin == null) throw new ArgumentNullException("allowedOrigin"); var hasAsterisk = allowedOrigin.Contains("*"); if (hasAsterisk && CountOfAsterisk(_allowedOrigins) > 0) throw new ArgumentException("At most one asterisk wildcard allowed."); _allowedOrigins.Add(allowedOrigin); } /// /// 添加一条AllowedMethod。 /// /// 指定允许的跨域请求方法。 类型:GET,PUT,DELETE,POST,HEAD public void AddAllowedMethod(String allowedMethod) { if (!InAllowedMethods(allowedMethod)) throw new ArgumentException("allowedMethod not in allowed methods(GET/PUT/DELETED/POST/HEAD)"); _allowedMethods.Add(allowedMethod); } /// /// 添加一条AllowedHeader。 /// /// 控制在OPTIONS预取指令中Access-Control-Request-Headers头中指定的header是否允许 public void AddAllowedHeader(String allowedHeader) { if (allowedHeader == null) throw new ArgumentNullException("allowedHeader"); var hasAsterisk = allowedHeader.Contains("*"); if (hasAsterisk && CountOfAsterisk(AllowedHeaders) > 0) throw new ArgumentException("At most one asterisk wildcard allowed."); _allowedHeaders.Add(allowedHeader); } /// /// 添加一条ExposeHeader。 /// /// 指定允许用户从应用程序中访问的响应头(例如一个Javascript的XMLHttpRequest对象) public void AddExposeHeader(String exposedHeader) { if (exposedHeader == null) throw new ArgumentNullException("exposedHeader"); var hasAsterisk = exposedHeader.Contains("*"); if (hasAsterisk) throw new ArgumentException("Asterisk wildcard not allowed."); _exposeHeaders.Add(exposedHeader); } /// /// 获取*通配符的个数。 /// /// 获取这些数据里的通配符个数 /// 通配符的个数 private static int CountOfAsterisk(IEnumerable items) { int count = 0; foreach (var item in items) { if (!string.IsNullOrEmpty(item) && item.Trim() == "*") { count++; } } return count; } /// /// 判断某个method是否被允许 /// /// 需要判断的method /// 是否被允许 private static bool InAllowedMethods(string allowedMethod) { if (string.IsNullOrEmpty(allowedMethod)) throw new ArgumentException("allowedMethod should not be null or empty"); var tmp = allowedMethod.Trim(); if (tmp == "GET" || tmp == "PUT" || tmp == "DELETED" || tmp == "POST" || tmp == "HEAD") { return true; } return false; } } }