1 //
2 // HttpRequestHeaders.cs
3 //
4 // Authors:
5 //	Marek Safar  <marek.safar@gmail.com>
6 //
7 // Copyright (C) 2011 Xamarin Inc (http://www.xamarin.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 
29 using System.Collections.Generic;
30 
31 namespace System.Net.Http.Headers
32 {
33 	public sealed class HttpRequestHeaders : HttpHeaders
34 	{
35 		bool? expectContinue;
36 
HttpRequestHeaders()37 		internal HttpRequestHeaders ()
38 			: base (HttpHeaderKind.Request)
39 		{
40 		}
41 
42 		public HttpHeaderValueCollection<MediaTypeWithQualityHeaderValue> Accept {
43 			get {
44 				return GetValues<MediaTypeWithQualityHeaderValue> ("Accept");
45 			}
46 		}
47 
48 		public HttpHeaderValueCollection<StringWithQualityHeaderValue> AcceptCharset {
49 			get {
50 				return GetValues<StringWithQualityHeaderValue> ("Accept-Charset");
51 			}
52 		}
53 
54 		public HttpHeaderValueCollection<StringWithQualityHeaderValue> AcceptEncoding {
55 			get {
56 				return GetValues<StringWithQualityHeaderValue> ("Accept-Encoding");
57 			}
58 		}
59 
60 		public HttpHeaderValueCollection<StringWithQualityHeaderValue> AcceptLanguage {
61 			get {
62 				return GetValues<StringWithQualityHeaderValue> ("Accept-Language");
63 			}
64 		}
65 
66 		public AuthenticationHeaderValue Authorization {
67 			get {
68 				return GetValue<AuthenticationHeaderValue> ("Authorization");
69 			}
70 			set {
71 				AddOrRemove ("Authorization", value);
72 			}
73 		}
74 
75 		public CacheControlHeaderValue CacheControl {
76 			get {
77 				return GetValue<CacheControlHeaderValue> ("Cache-Control");
78 			}
79 			set {
80 				AddOrRemove ("Cache-Control", value);
81 			}
82 		}
83 
84 		public HttpHeaderValueCollection<string> Connection {
85 			get {
86 				return GetValues<string> ("Connection");
87 			}
88 		}
89 
90 		public bool? ConnectionClose {
91 			get {
92 				if (connectionclose == true || Connection.Find (l => string.Equals (l, "close", StringComparison.OrdinalIgnoreCase)) != null)
93 					return true;
94 
95 				return connectionclose;
96 			}
97 			set {
98 				if (connectionclose == value)
99 					return;
100 
101 				Connection.Remove ("close");
102 				if (value == true)
103 					Connection.Add ("close");
104 
105 				connectionclose = value;
106 			}
107 		}
108 
109 		internal bool ConnectionKeepAlive {
110 			get {
111 				return Connection.Find (l => string.Equals (l, "Keep-Alive", StringComparison.OrdinalIgnoreCase)) != null;
112 			}
113 		}
114 
115 		public DateTimeOffset? Date {
116 			get {
117 				return GetValue<DateTimeOffset?> ("Date");
118 			}
119 			set {
120 				AddOrRemove ("Date", value, Parser.DateTime.ToString);
121 			}
122 		}
123 
124 		public HttpHeaderValueCollection<NameValueWithParametersHeaderValue> Expect {
125 			get {
126 				return GetValues<NameValueWithParametersHeaderValue> ("Expect");
127 			}
128 		}
129 
130 		public bool? ExpectContinue {
131 			get {
132 				if (expectContinue.HasValue)
133 					return expectContinue;
134 
135 				var found = TransferEncoding.Find (l => string.Equals (l.Value, "100-continue", StringComparison.OrdinalIgnoreCase));
136 				return found != null ? true : (bool?) null;
137 			}
138 			set {
139 				if (expectContinue == value)
140 					return;
141 
142 				Expect.Remove (l => l.Name == "100-continue");
143 
144 				if (value == true)
145 					Expect.Add (new NameValueWithParametersHeaderValue ("100-continue"));
146 
147 				expectContinue = value;
148 			}
149 		}
150 
151 		public string From {
152 			get {
153 				return GetValue<string> ("From");
154 			}
155 			set {
156 				if (!string.IsNullOrEmpty (value) && !Parser.EmailAddress.TryParse (value, out value))
157 					throw new FormatException ();
158 
159 				AddOrRemove ("From", value);
160 			}
161 		}
162 
163 		public string Host {
164 			get {
165 				return GetValue<string> ("Host");
166 			}
167 			set {
168 				AddOrRemove ("Host", value);
169 			}
170 		}
171 
172 		public HttpHeaderValueCollection<EntityTagHeaderValue> IfMatch {
173 			get {
174 				return GetValues<EntityTagHeaderValue> ("If-Match");
175 			}
176 		}
177 
178 		public DateTimeOffset? IfModifiedSince {
179 			get {
180 				return GetValue<DateTimeOffset?> ("If-Modified-Since");
181 			}
182 			set {
183 				AddOrRemove ("If-Modified-Since", value, Parser.DateTime.ToString);
184 			}
185 		}
186 
187 		public HttpHeaderValueCollection<EntityTagHeaderValue> IfNoneMatch {
188 			get {
189 				return GetValues<EntityTagHeaderValue> ("If-None-Match");
190 			}
191 		}
192 
193 		public RangeConditionHeaderValue IfRange {
194 			get {
195 				return GetValue<RangeConditionHeaderValue> ("If-Range");
196 			}
197 			set {
198 				AddOrRemove ("If-Range", value);
199 			}
200 		}
201 
202 		public DateTimeOffset? IfUnmodifiedSince {
203 			get {
204 				return GetValue<DateTimeOffset?> ("If-Unmodified-Since");
205 			}
206 			set {
207 				AddOrRemove ("If-Unmodified-Since", value, Parser.DateTime.ToString);
208 			}
209 		}
210 
211 		public int? MaxForwards {
212 			get {
213 				return GetValue<int?> ("Max-Forwards");
214 			}
215 			set {
216 				AddOrRemove ("Max-Forwards", value);
217 			}
218 		}
219 
220 		public HttpHeaderValueCollection<NameValueHeaderValue> Pragma {
221 			get {
222 				return GetValues<NameValueHeaderValue> ("Pragma");
223 			}
224 		}
225 
226 		public AuthenticationHeaderValue ProxyAuthorization {
227 			get {
228 				return GetValue<AuthenticationHeaderValue> ("Proxy-Authorization");
229 			}
230 			set {
231 				AddOrRemove ("Proxy-Authorization", value);
232 			}
233 		}
234 
235 		public RangeHeaderValue Range {
236 			get {
237 				return GetValue<RangeHeaderValue> ("Range");
238 			}
239 			set {
240 				AddOrRemove ("Range", value);
241 			}
242 		}
243 
244 		public Uri Referrer {
245 			get {
246 				return GetValue<Uri> ("Referer");
247 			}
248 			set {
249 				AddOrRemove ("Referer", value);
250 			}
251 		}
252 
253 		public HttpHeaderValueCollection<TransferCodingWithQualityHeaderValue> TE {
254 		    get {
255 		        return GetValues<TransferCodingWithQualityHeaderValue> ("TE");
256 		    }
257 		}
258 
259 		public HttpHeaderValueCollection<string> Trailer {
260 			get {
261 				return GetValues<string> ("Trailer");
262 			}
263 		}
264 
265 		public HttpHeaderValueCollection<TransferCodingHeaderValue> TransferEncoding {
266 			get {
267 				return GetValues<TransferCodingHeaderValue> ("Transfer-Encoding");
268 			}
269 		}
270 
271 		public bool? TransferEncodingChunked {
272 			get {
273 				if (transferEncodingChunked.HasValue)
274 					return transferEncodingChunked;
275 
276 				var found = TransferEncoding.Find (l => string.Equals (l.Value, "chunked", StringComparison.OrdinalIgnoreCase));
277 				return found != null ? true : (bool?) null;
278 			}
279 			set {
280 				if (value == transferEncodingChunked)
281 					return;
282 
283 				TransferEncoding.Remove (l => l.Value == "chunked");
284 				if (value == true)
285 					TransferEncoding.Add (new TransferCodingHeaderValue ("chunked"));
286 
287 				transferEncodingChunked = value;
288 			}
289 		}
290 
291 		public HttpHeaderValueCollection<ProductHeaderValue> Upgrade {
292 			get {
293 				return GetValues<ProductHeaderValue> ("Upgrade");
294 			}
295 		}
296 
297 		public HttpHeaderValueCollection<ProductInfoHeaderValue> UserAgent {
298 			get {
299 				return GetValues<ProductInfoHeaderValue> ("User-Agent");
300 			}
301 		}
302 
303 		public HttpHeaderValueCollection<ViaHeaderValue> Via {
304 			get {
305 				return GetValues<ViaHeaderValue> ("Via");
306 			}
307 		}
308 
309 		public HttpHeaderValueCollection<WarningHeaderValue> Warning {
310 			get {
311 				return GetValues<WarningHeaderValue> ("Warning");
312 			}
313 		}
314 
AddHeaders(HttpRequestHeaders headers)315 		internal void AddHeaders (HttpRequestHeaders headers)
316 		{
317 			foreach (var header in headers) {
318 				TryAddWithoutValidation (header.Key, header.Value);
319 			}
320 		}
321 	}
322 }
323