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