PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/WCFWebApi/src/System.Net.Http/System/Net/Http/Headers/HttpRequestHeaders.cs

#
C# | 427 lines | 366 code | 52 blank | 9 comment | 39 complexity | a39c5747ed2b49a6eebdd7cbfe01f8bf MD5 | raw file
Possible License(s): CC-BY-SA-3.0, Apache-2.0
  1. using System.Collections.Generic;
  2. using System.Diagnostics.CodeAnalysis;
  3. using System.Diagnostics.Contracts;
  4. namespace System.Net.Http.Headers
  5. {
  6. [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix",
  7. Justification = "This is not a collection")]
  8. public sealed class HttpRequestHeaders : HttpHeaders
  9. {
  10. private static readonly Dictionary<string, HttpHeaderParser> parserStore;
  11. private static readonly HashSet<string> invalidHeaders;
  12. private HttpGeneralHeaders generalHeaders;
  13. private HttpHeaderValueCollection<MediaTypeWithQualityHeaderValue> accept;
  14. private HttpHeaderValueCollection<NameValueWithParametersHeaderValue> expect;
  15. private bool expectContinueSet;
  16. private HttpHeaderValueCollection<EntityTagHeaderValue> ifMatch;
  17. private HttpHeaderValueCollection<EntityTagHeaderValue> ifNoneMatch;
  18. private HttpHeaderValueCollection<TransferCodingWithQualityHeaderValue> te;
  19. private HttpHeaderValueCollection<ProductInfoHeaderValue> userAgent;
  20. private HttpHeaderValueCollection<StringWithQualityHeaderValue> acceptCharset;
  21. private HttpHeaderValueCollection<StringWithQualityHeaderValue> acceptEncoding;
  22. private HttpHeaderValueCollection<StringWithQualityHeaderValue> acceptLanguage;
  23. #region Request Headers
  24. public HttpHeaderValueCollection<MediaTypeWithQualityHeaderValue> Accept
  25. {
  26. get
  27. {
  28. if (accept == null)
  29. {
  30. accept = new HttpHeaderValueCollection<MediaTypeWithQualityHeaderValue>(
  31. HttpKnownHeaderNames.Accept, this);
  32. }
  33. return accept;
  34. }
  35. }
  36. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Charset",
  37. Justification = "The HTTP header name is 'Accept-Charset'.")]
  38. public HttpHeaderValueCollection<StringWithQualityHeaderValue> AcceptCharset
  39. {
  40. get
  41. {
  42. if (acceptCharset == null)
  43. {
  44. acceptCharset = new HttpHeaderValueCollection<StringWithQualityHeaderValue>(
  45. HttpKnownHeaderNames.AcceptCharset, this);
  46. }
  47. return acceptCharset;
  48. }
  49. }
  50. public HttpHeaderValueCollection<StringWithQualityHeaderValue> AcceptEncoding
  51. {
  52. get
  53. {
  54. if (acceptEncoding == null)
  55. {
  56. acceptEncoding = new HttpHeaderValueCollection<StringWithQualityHeaderValue>(
  57. HttpKnownHeaderNames.AcceptEncoding, this);
  58. }
  59. return acceptEncoding;
  60. }
  61. }
  62. public HttpHeaderValueCollection<StringWithQualityHeaderValue> AcceptLanguage
  63. {
  64. get
  65. {
  66. if (acceptLanguage == null)
  67. {
  68. acceptLanguage = new HttpHeaderValueCollection<StringWithQualityHeaderValue>(
  69. HttpKnownHeaderNames.AcceptLanguage, this);
  70. }
  71. return acceptLanguage;
  72. }
  73. }
  74. public AuthenticationHeaderValue Authorization
  75. {
  76. get { return (AuthenticationHeaderValue)GetParsedValues(HttpKnownHeaderNames.Authorization); }
  77. set { SetOrRemoveParsedValue(HttpKnownHeaderNames.Authorization, value); }
  78. }
  79. public HttpHeaderValueCollection<NameValueWithParametersHeaderValue> Expect
  80. {
  81. get { return ExpectCore; }
  82. }
  83. // Note that ServicePoint.Expect100Continue is on by default. However, by default we don't set any header
  84. // value. I.e. ExpectContinue returns 'null' by default. The fact that HWR will add "Expect: 100-continue"
  85. // anyways is a transport channel feature and can be turned off by setting ExpectContinue to 'false'.
  86. // Remember: these headers are also used on the server side, where ExpectContinue should only be true
  87. // if the received request message actually has this header value set.
  88. public bool? ExpectContinue
  89. {
  90. get
  91. {
  92. if (ExpectCore.IsSpecialValueSet)
  93. {
  94. return true;
  95. }
  96. if (expectContinueSet)
  97. {
  98. return false;
  99. }
  100. return null;
  101. }
  102. set
  103. {
  104. if (value == true)
  105. {
  106. expectContinueSet = true;
  107. ExpectCore.SetSpecialValue();
  108. }
  109. else
  110. {
  111. expectContinueSet = value != null;
  112. ExpectCore.RemoveSpecialValue();
  113. }
  114. }
  115. }
  116. public string From
  117. {
  118. get { return (string)GetParsedValues(HttpKnownHeaderNames.From); }
  119. set
  120. {
  121. // null and empty string are equivalent. In this case it means, remove the From header value (if any).
  122. if (value == string.Empty)
  123. {
  124. value = null;
  125. }
  126. if ((value != null) && !HeaderUtilities.IsValidEmailAddress(value))
  127. {
  128. throw new FormatException(SR.net_http_headers_invalid_from_header);
  129. }
  130. SetOrRemoveParsedValue(HttpKnownHeaderNames.From, value);
  131. }
  132. }
  133. public string Host
  134. {
  135. get { return (string)GetParsedValues(HttpKnownHeaderNames.Host); }
  136. set
  137. {
  138. // null and empty string are equivalent. In this case it means, remove the Host header value (if any).
  139. if (value == string.Empty)
  140. {
  141. value = null;
  142. }
  143. string host = null;
  144. if ((value != null) && (HttpRuleParser.GetHostLength(value, 0, false, out host) != value.Length))
  145. {
  146. throw new FormatException(SR.net_http_headers_invalid_host_header);
  147. }
  148. SetOrRemoveParsedValue(HttpKnownHeaderNames.Host, value);
  149. }
  150. }
  151. public HttpHeaderValueCollection<EntityTagHeaderValue> IfMatch
  152. {
  153. get
  154. {
  155. if (ifMatch == null)
  156. {
  157. ifMatch = new HttpHeaderValueCollection<EntityTagHeaderValue>(
  158. HttpKnownHeaderNames.IfMatch, this);
  159. }
  160. return ifMatch;
  161. }
  162. }
  163. public DateTimeOffset? IfModifiedSince
  164. {
  165. get { return HeaderUtilities.GetDateTimeOffsetValue(HttpKnownHeaderNames.IfModifiedSince, this); }
  166. set { SetOrRemoveParsedValue(HttpKnownHeaderNames.IfModifiedSince, value); }
  167. }
  168. public HttpHeaderValueCollection<EntityTagHeaderValue> IfNoneMatch
  169. {
  170. get
  171. {
  172. if (ifNoneMatch == null)
  173. {
  174. ifNoneMatch = new HttpHeaderValueCollection<EntityTagHeaderValue>(
  175. HttpKnownHeaderNames.IfNoneMatch, this);
  176. }
  177. return ifNoneMatch;
  178. }
  179. }
  180. public RangeConditionHeaderValue IfRange
  181. {
  182. get { return (RangeConditionHeaderValue)GetParsedValues(HttpKnownHeaderNames.IfRange); }
  183. set { SetOrRemoveParsedValue(HttpKnownHeaderNames.IfRange, value); }
  184. }
  185. public DateTimeOffset? IfUnmodifiedSince
  186. {
  187. get { return HeaderUtilities.GetDateTimeOffsetValue(HttpKnownHeaderNames.IfUnmodifiedSince, this); }
  188. set { SetOrRemoveParsedValue(HttpKnownHeaderNames.IfUnmodifiedSince, value); }
  189. }
  190. public int? MaxForwards
  191. {
  192. get
  193. {
  194. object storedValue = GetParsedValues(HttpKnownHeaderNames.MaxForwards);
  195. if (storedValue != null)
  196. {
  197. return (int)storedValue;
  198. }
  199. return null;
  200. }
  201. set { SetOrRemoveParsedValue(HttpKnownHeaderNames.MaxForwards, value); }
  202. }
  203. public AuthenticationHeaderValue ProxyAuthorization
  204. {
  205. get { return (AuthenticationHeaderValue)GetParsedValues(HttpKnownHeaderNames.ProxyAuthorization); }
  206. set { SetOrRemoveParsedValue(HttpKnownHeaderNames.ProxyAuthorization, value); }
  207. }
  208. public RangeHeaderValue Range
  209. {
  210. get { return (RangeHeaderValue)GetParsedValues(HttpKnownHeaderNames.Range); }
  211. set { SetOrRemoveParsedValue(HttpKnownHeaderNames.Range, value); }
  212. }
  213. public Uri Referrer
  214. {
  215. get { return (Uri)GetParsedValues(HttpKnownHeaderNames.Referer); }
  216. set { SetOrRemoveParsedValue(HttpKnownHeaderNames.Referer, value); }
  217. }
  218. public HttpHeaderValueCollection<TransferCodingWithQualityHeaderValue> TE
  219. {
  220. get
  221. {
  222. if (te == null)
  223. {
  224. te = new HttpHeaderValueCollection<TransferCodingWithQualityHeaderValue>(
  225. HttpKnownHeaderNames.TE, this);
  226. }
  227. return te;
  228. }
  229. }
  230. public HttpHeaderValueCollection<ProductInfoHeaderValue> UserAgent
  231. {
  232. get
  233. {
  234. if (userAgent == null)
  235. {
  236. userAgent = new HttpHeaderValueCollection<ProductInfoHeaderValue>(HttpKnownHeaderNames.UserAgent,
  237. this);
  238. }
  239. return userAgent;
  240. }
  241. }
  242. private HttpHeaderValueCollection<NameValueWithParametersHeaderValue> ExpectCore
  243. {
  244. get
  245. {
  246. if (expect == null)
  247. {
  248. expect = new HttpHeaderValueCollection<NameValueWithParametersHeaderValue>(
  249. HttpKnownHeaderNames.Expect, this, HeaderUtilities.ExpectContinue);
  250. }
  251. return expect;
  252. }
  253. }
  254. #endregion
  255. #region General Headers
  256. public CacheControlHeaderValue CacheControl
  257. {
  258. get { return generalHeaders.CacheControl; }
  259. set { generalHeaders.CacheControl = value; }
  260. }
  261. public HttpHeaderValueCollection<string> Connection
  262. {
  263. get { return generalHeaders.Connection; }
  264. }
  265. public bool? ConnectionClose
  266. {
  267. get { return generalHeaders.ConnectionClose; }
  268. set { generalHeaders.ConnectionClose = value; }
  269. }
  270. public DateTimeOffset? Date
  271. {
  272. get { return generalHeaders.Date; }
  273. set { generalHeaders.Date = value; }
  274. }
  275. public HttpHeaderValueCollection<NameValueHeaderValue> Pragma
  276. {
  277. get { return generalHeaders.Pragma; }
  278. }
  279. public HttpHeaderValueCollection<string> Trailer
  280. {
  281. get { return generalHeaders.Trailer; }
  282. }
  283. // Like ContentEncoding: Order matters!
  284. public HttpHeaderValueCollection<TransferCodingHeaderValue> TransferEncoding
  285. {
  286. get { return generalHeaders.TransferEncoding; }
  287. }
  288. public bool? TransferEncodingChunked
  289. {
  290. get { return generalHeaders.TransferEncodingChunked; }
  291. set { generalHeaders.TransferEncodingChunked = value; }
  292. }
  293. public HttpHeaderValueCollection<ProductHeaderValue> Upgrade
  294. {
  295. get { return generalHeaders.Upgrade; }
  296. }
  297. public HttpHeaderValueCollection<ViaHeaderValue> Via
  298. {
  299. get { return generalHeaders.Via; }
  300. }
  301. public HttpHeaderValueCollection<WarningHeaderValue> Warning
  302. {
  303. get { return generalHeaders.Warning; }
  304. }
  305. #endregion
  306. internal HttpRequestHeaders()
  307. {
  308. this.generalHeaders = new HttpGeneralHeaders(this);
  309. base.SetConfiguration(parserStore, invalidHeaders);
  310. }
  311. static HttpRequestHeaders()
  312. {
  313. parserStore = new Dictionary<string, HttpHeaderParser>(HeaderUtilities.CaseInsensitiveStringComparer);
  314. parserStore.Add(HttpKnownHeaderNames.Accept, MediaTypeHeaderParser.MultipleValuesParser);
  315. parserStore.Add(HttpKnownHeaderNames.AcceptCharset, GenericHeaderParser.MultipleValueStringWithQualityParser);
  316. parserStore.Add(HttpKnownHeaderNames.AcceptEncoding, GenericHeaderParser.MultipleValueStringWithQualityParser);
  317. parserStore.Add(HttpKnownHeaderNames.AcceptLanguage, GenericHeaderParser.MultipleValueStringWithQualityParser);
  318. parserStore.Add(HttpKnownHeaderNames.Authorization, GenericHeaderParser.SingleValueAuthenticationParser);
  319. parserStore.Add(HttpKnownHeaderNames.Expect, GenericHeaderParser.MultipleValueNameValueWithParametersParser);
  320. parserStore.Add(HttpKnownHeaderNames.From, GenericHeaderParser.MailAddressParser);
  321. parserStore.Add(HttpKnownHeaderNames.Host, GenericHeaderParser.HostParser);
  322. parserStore.Add(HttpKnownHeaderNames.IfMatch, GenericHeaderParser.MultipleValueEntityTagParser);
  323. parserStore.Add(HttpKnownHeaderNames.IfModifiedSince, DateHeaderParser.Parser);
  324. parserStore.Add(HttpKnownHeaderNames.IfNoneMatch, GenericHeaderParser.MultipleValueEntityTagParser);
  325. parserStore.Add(HttpKnownHeaderNames.IfRange, GenericHeaderParser.RangeConditionParser);
  326. parserStore.Add(HttpKnownHeaderNames.IfUnmodifiedSince, DateHeaderParser.Parser);
  327. parserStore.Add(HttpKnownHeaderNames.MaxForwards, Int32NumberHeaderParser.Parser);
  328. parserStore.Add(HttpKnownHeaderNames.ProxyAuthorization, GenericHeaderParser.SingleValueAuthenticationParser);
  329. parserStore.Add(HttpKnownHeaderNames.Range, GenericHeaderParser.RangeParser);
  330. parserStore.Add(HttpKnownHeaderNames.Referer, UriHeaderParser.RelativeOrAbsoluteUriParser);
  331. parserStore.Add(HttpKnownHeaderNames.TE, TransferCodingHeaderParser.MultipleValueWithQualityParser);
  332. parserStore.Add(HttpKnownHeaderNames.UserAgent, ProductInfoHeaderParser.MultipleValueParser);
  333. HttpGeneralHeaders.AddParsers(parserStore);
  334. invalidHeaders = new HashSet<string>(HeaderUtilities.CaseInsensitiveStringComparer);
  335. HttpResponseHeaders.AddKnownHeaders(invalidHeaders);
  336. HttpContentHeaders.AddKnownHeaders(invalidHeaders);
  337. }
  338. internal static void AddKnownHeaders(HashSet<string> headerSet)
  339. {
  340. Contract.Requires(headerSet != null);
  341. headerSet.Add(HttpKnownHeaderNames.Accept);
  342. headerSet.Add(HttpKnownHeaderNames.AcceptCharset);
  343. headerSet.Add(HttpKnownHeaderNames.AcceptEncoding);
  344. headerSet.Add(HttpKnownHeaderNames.AcceptLanguage);
  345. headerSet.Add(HttpKnownHeaderNames.Authorization);
  346. headerSet.Add(HttpKnownHeaderNames.Expect);
  347. headerSet.Add(HttpKnownHeaderNames.From);
  348. headerSet.Add(HttpKnownHeaderNames.Host);
  349. headerSet.Add(HttpKnownHeaderNames.IfMatch);
  350. headerSet.Add(HttpKnownHeaderNames.IfModifiedSince);
  351. headerSet.Add(HttpKnownHeaderNames.IfNoneMatch);
  352. headerSet.Add(HttpKnownHeaderNames.IfRange);
  353. headerSet.Add(HttpKnownHeaderNames.IfUnmodifiedSince);
  354. headerSet.Add(HttpKnownHeaderNames.MaxForwards);
  355. headerSet.Add(HttpKnownHeaderNames.ProxyAuthorization);
  356. headerSet.Add(HttpKnownHeaderNames.Range);
  357. headerSet.Add(HttpKnownHeaderNames.Referer);
  358. headerSet.Add(HttpKnownHeaderNames.TE);
  359. headerSet.Add(HttpKnownHeaderNames.UserAgent);
  360. }
  361. internal override void AddHeaders(HttpHeaders sourceHeaders)
  362. {
  363. base.AddHeaders(sourceHeaders);
  364. HttpRequestHeaders sourceRequestHeaders = sourceHeaders as HttpRequestHeaders;
  365. Contract.Assert(sourceRequestHeaders != null);
  366. // Copy special values, but do not overwrite
  367. generalHeaders.AddSpecialsFrom(sourceRequestHeaders.generalHeaders);
  368. bool? expectContinue = ExpectContinue;
  369. if (!expectContinue.HasValue)
  370. {
  371. ExpectContinue = sourceRequestHeaders.ExpectContinue;
  372. }
  373. }
  374. }
  375. }