PolicyConditions.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*
  2. * Copyright (C) Alibaba Cloud Computing
  3. * All rights reserved.
  4. *
  5. * 版权所有 (C)阿里云计算有限公司
  6. */
  7. using System;
  8. using System.Collections.Generic;
  9. using System.ComponentModel;
  10. using System.Text;
  11. namespace Aliyun.OSS
  12. {
  13. /// <summary>
  14. /// Conditions匹配方式。
  15. /// </summary>
  16. public enum MatchMode
  17. {
  18. /// <summary>
  19. /// 未知的
  20. /// </summary>
  21. Unknown,
  22. /// <summary>
  23. /// 精确匹配
  24. /// </summary>
  25. Exact,
  26. /// <summary>
  27. /// 前缀匹配
  28. /// </summary>
  29. StartWith,
  30. /// <summary>
  31. /// 范围匹配
  32. /// </summary>
  33. Range
  34. };
  35. /// <summary>
  36. /// Conditions元组类型,目前支持二元组({ ... })、三元组([ ... ])。
  37. /// </summary>
  38. internal enum TupleType
  39. {
  40. Unknown,
  41. Two,
  42. Three
  43. };
  44. /// <summary>
  45. /// 抽象Condition项。
  46. /// </summary>
  47. internal abstract class AbstractConditionItem
  48. {
  49. public string Name { get; set; }
  50. public MatchMode MatchMode { get; set; }
  51. public TupleType TupleType { get; set; }
  52. protected AbstractConditionItem(string name, MatchMode matchMode, TupleType tupleType)
  53. {
  54. Name = name;
  55. MatchMode = matchMode;
  56. TupleType = tupleType;
  57. }
  58. public abstract string Jsonize();
  59. }
  60. /// <summary>
  61. /// Equal类型条件项。
  62. /// </summary>
  63. internal class EqualConditionItem : AbstractConditionItem
  64. {
  65. public string Value { get; set; }
  66. public EqualConditionItem(string name, string value)
  67. : this(name, value, TupleType.Two)
  68. { }
  69. public EqualConditionItem(string name, string value, TupleType tupleType)
  70. : base(name, MatchMode.Exact, tupleType)
  71. {
  72. Value = value;
  73. }
  74. public override string Jsonize()
  75. {
  76. string jsonizedCond = null;
  77. switch (TupleType)
  78. {
  79. case TupleType.Two:
  80. jsonizedCond = String.Format("{{\"{0}\":\"{1}\"}},", Name, Value);
  81. break;
  82. case TupleType.Three:
  83. jsonizedCond = String.Format("[\"eq\",\"${0}\",\"{1}\"],", Name, Value);
  84. break;
  85. default:
  86. throw new InvalidEnumArgumentException("Invalid tuple type " + TupleType.ToString());
  87. }
  88. return jsonizedCond;
  89. }
  90. }
  91. /// <summary>
  92. /// StartWith类型条件项。
  93. /// </summary>
  94. internal class StartWithConditionItem : AbstractConditionItem
  95. {
  96. public string Value { get; set; }
  97. public StartWithConditionItem(string name, string value)
  98. : base(name, MatchMode.StartWith, TupleType.Three)
  99. {
  100. Value = value;
  101. }
  102. public override string Jsonize()
  103. {
  104. return String.Format("[\"starts-with\",\"${0}\",\"{1}\"],", Name, Value);
  105. }
  106. }
  107. /// <summary>
  108. /// ContentLengthRange类型条件项。
  109. /// </summary>
  110. internal class RangeConditionItem : AbstractConditionItem
  111. {
  112. public long Minimum { get; set; }
  113. public long Maximum { get; set; }
  114. public RangeConditionItem(string name, long min, long max)
  115. : base(name, MatchMode.Range, TupleType.Three)
  116. {
  117. Minimum = min;
  118. Maximum = max;
  119. }
  120. public override string Jsonize()
  121. {
  122. return String.Format("[\"content-length-range\",{0},{1}],", Minimum, Maximum);
  123. }
  124. }
  125. /// <summary>
  126. /// Conditions列表,用于指定 Post 请求表单域的合法值。
  127. /// </summary>
  128. public class PolicyConditions
  129. {
  130. /// <summary>
  131. /// 文件长度范围
  132. /// </summary>
  133. public const string CondContentLengthRange = "content-length-range";
  134. /// <summary>
  135. /// 文件被下载时的网页的缓存行为
  136. /// </summary>
  137. public const string CondCacheControl = "Cache-Control";
  138. /// <summary>
  139. /// RFC2616中定义的HTTP请求内容类型
  140. /// </summary>
  141. public const string CondContentType = "Content-Type";
  142. /// <summary>
  143. /// 文件被下载时的名称
  144. /// </summary>
  145. public const string CondContentDisposition = "Content-Disposition";
  146. /// <summary>
  147. /// 文件被下载时的内容编码格式
  148. /// </summary>
  149. public const string CondContentEncoding = "Content-Encoding";
  150. /// <summary>
  151. /// 过期时间
  152. /// </summary>
  153. public const string CondExpires = "Expires";
  154. /// <summary>
  155. /// 名称
  156. /// </summary>
  157. public const string CondKey = "key";
  158. /// <summary>
  159. /// 成功时的重定向
  160. /// </summary>
  161. public const string CondSuccessActionRedirect = "success_action_redirect";
  162. /// <summary>
  163. /// 成功时的状态
  164. /// </summary>
  165. public const string CondSuccessActionStatus = "success_action_status";
  166. /// <summary>
  167. /// 用户自定义meta元素的前缀x-oss-meta-
  168. /// </summary>
  169. public const string CondXOssMetaPrefix = "x-oss-meta-";
  170. private IList<AbstractConditionItem> _conds = new List<AbstractConditionItem>();
  171. /// <summary>
  172. /// 采用默认匹配方式(精确匹配)添加Conditions项。
  173. /// </summary>
  174. /// <param name="name">Condition名称。</param>
  175. /// <param name="value">Condition数值。</param>
  176. public void AddConditionItem(string name, string value)
  177. {
  178. MatchRuleChecker.Check(MatchMode.Exact, name);
  179. _conds.Add(new EqualConditionItem(name, value));
  180. }
  181. /// <summary>
  182. /// 采用指定匹配模式添加Conditions项。
  183. /// </summary>
  184. /// <param name="matchMode">Conditions匹配方式。</param>
  185. /// <param name="name">Condition名称。</param>
  186. /// <param name="value">Condition数值。</param>
  187. public void AddConditionItem(MatchMode matchMode, string name, string value)
  188. {
  189. MatchRuleChecker.Check(matchMode, name);
  190. switch (matchMode)
  191. {
  192. case MatchMode.Exact:
  193. _conds.Add(new EqualConditionItem(name, value, TupleType.Three));
  194. break;
  195. case MatchMode.StartWith:
  196. _conds.Add(new StartWithConditionItem(name, value));
  197. break;
  198. default:
  199. throw new InvalidEnumArgumentException("Unsupported match mode " +
  200. matchMode);
  201. }
  202. }
  203. /// <summary>
  204. /// 采用范围匹配模式添加Conditions项。
  205. /// </summary>
  206. /// <param name="name">Condition名称。</param>
  207. /// <param name="min">范围最小值。</param>
  208. /// <param name="max">范围最大值。</param>
  209. public void AddConditionItem(string name, long min, long max)
  210. {
  211. if (min > max)
  212. throw new ArgumentException(String.Format("Invalid range [{0}, {1}].", min, max));
  213. _conds.Add(new RangeConditionItem(name, min, max));
  214. }
  215. internal string Jsonize()
  216. {
  217. var jsonizedConds = new StringBuilder();
  218. jsonizedConds.Append("\"conditions\":[");
  219. foreach (var cond in _conds)
  220. jsonizedConds.Append(cond.Jsonize());
  221. if (_conds.Count > 0)
  222. jsonizedConds.Remove(jsonizedConds.Length - 1, 1);
  223. jsonizedConds.Append("]");
  224. return jsonizedConds.ToString();
  225. }
  226. }
  227. internal static class MatchRuleChecker
  228. {
  229. private static IDictionary<string, IList<MatchMode>> _supportedMatchRules
  230. = new Dictionary<string, IList<MatchMode>>();
  231. static MatchRuleChecker()
  232. {
  233. var ordinaryMatchModes = new List<MatchMode> {MatchMode.Exact, MatchMode.StartWith};
  234. var specialMatchModes = new List<MatchMode> {MatchMode.Range};
  235. _supportedMatchRules.Add(PolicyConditions.CondContentLengthRange, specialMatchModes);
  236. _supportedMatchRules.Add(PolicyConditions.CondCacheControl, ordinaryMatchModes);
  237. _supportedMatchRules.Add(PolicyConditions.CondContentType, ordinaryMatchModes);
  238. _supportedMatchRules.Add(PolicyConditions.CondContentDisposition, ordinaryMatchModes);
  239. _supportedMatchRules.Add(PolicyConditions.CondContentEncoding, ordinaryMatchModes);
  240. _supportedMatchRules.Add(PolicyConditions.CondExpires, ordinaryMatchModes);
  241. _supportedMatchRules.Add(PolicyConditions.CondKey, ordinaryMatchModes);
  242. _supportedMatchRules.Add(PolicyConditions.CondSuccessActionRedirect, ordinaryMatchModes);
  243. _supportedMatchRules.Add(PolicyConditions.CondSuccessActionStatus, ordinaryMatchModes);
  244. _supportedMatchRules.Add(PolicyConditions.CondXOssMetaPrefix, ordinaryMatchModes);
  245. }
  246. public static void Check(MatchMode matchMode, string condName)
  247. {
  248. if (_supportedMatchRules.ContainsKey(condName))
  249. {
  250. var mms = _supportedMatchRules[condName];
  251. if (!mms.Contains(matchMode))
  252. {
  253. throw new ArgumentException(
  254. String.Format("Unsupported match mode for condition item {0}", condName));
  255. }
  256. }
  257. }
  258. }
  259. }