X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem.Net.Http%2FSystem.Net.Http.Headers%2FHttpHeaders.cs;h=ffef647b5ee5a76029019d606acdb8e3e8c250e4;hb=c39718bbb394fe97281e6e64945b4572bef29121;hp=9dcb1b44d8fa180aca172bda55d4293c2746b111;hpb=880bea0e62f7b4d97eab34fde65c5121e706ea72;p=mono.git diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs index 9dcb1b44d8f..ffef647b5ee 100644 --- a/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs +++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs @@ -29,6 +29,7 @@ using System.Collections; using System.Collections.Generic; using System.Linq; +using System.Text; namespace System.Net.Http.Headers { @@ -45,9 +46,12 @@ namespace System.Net.Http.Headers public object Parsed; List values; - public HeaderBucket (object parsed) + public readonly Func CustomToString; + + public HeaderBucket (object parsed, Func converter = null) { this.Parsed = parsed; + this.CustomToString = converter; } public bool HasStringValues { @@ -60,6 +64,20 @@ namespace System.Net.Http.Headers get { return values ?? (values = new List ()); } + set { + values = value; + } + } + + public string ParsedToString () + { + if (Parsed == null) + return null; + + if (CustomToString != null) + return CustomToString (Parsed); + + return Parsed.ToString (); } } @@ -72,12 +90,23 @@ namespace System.Net.Http.Headers HeaderInfo.CreateMulti ("Accept-Charset", StringWithQualityHeaderValue.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateMulti ("Accept-Encoding", StringWithQualityHeaderValue.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateMulti ("Accept-Language", StringWithQualityHeaderValue.TryParse, HttpHeaderKind.Request), + HeaderInfo.CreateMulti ("Accept-Ranges", CollectionParser.TryParse, HttpHeaderKind.Response), HeaderInfo.CreateSingle ("Age", Parser.TimeSpanSeconds.TryParse, HttpHeaderKind.Response), + HeaderInfo.CreateMulti ("Allow", CollectionParser.TryParse, HttpHeaderKind.Content, 0), HeaderInfo.CreateSingle ("Authorization", AuthenticationHeaderValue.TryParse, HttpHeaderKind.Request), - HeaderInfo.CreateSingle ("Cache-Control", CacheControlHeaderValue.TryParse, HttpHeaderKind.Request), - HeaderInfo.CreateSingle ("Connection", Parser.Token.TryParse, HttpHeaderKind.Request), - HeaderInfo.CreateSingle ("Date", Parser.DateTime.TryParse, HttpHeaderKind.Request), + HeaderInfo.CreateSingle ("Cache-Control", CacheControlHeaderValue.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response), + HeaderInfo.CreateMulti ("Connection", CollectionParser.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response), + HeaderInfo.CreateMulti ("Content-Encoding", CollectionParser.TryParse, HttpHeaderKind.Content), + HeaderInfo.CreateMulti ("Content-Language", CollectionParser.TryParse, HttpHeaderKind.Content), + HeaderInfo.CreateSingle ("Content-Length", Parser.Long.TryParse, HttpHeaderKind.Content), + HeaderInfo.CreateSingle ("Content-Location", Parser.Uri.TryParse, HttpHeaderKind.Content), + HeaderInfo.CreateSingle ("Content-MD5", Parser.MD5.TryParse, HttpHeaderKind.Content), + HeaderInfo.CreateSingle ("Content-Range", ContentRangeHeaderValue.TryParse, HttpHeaderKind.Content), + HeaderInfo.CreateSingle ("Content-Type", MediaTypeHeaderValue.TryParse, HttpHeaderKind.Content), + HeaderInfo.CreateSingle ("Date", Parser.DateTime.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response), + HeaderInfo.CreateSingle ("ETag", EntityTagHeaderValue.TryParse, HttpHeaderKind.Response), HeaderInfo.CreateMulti ("Expect", NameValueWithParametersHeaderValue.TryParse, HttpHeaderKind.Request), + HeaderInfo.CreateSingle ("Expires", Parser.DateTime.TryParse, HttpHeaderKind.Content), HeaderInfo.CreateSingle ("From", Parser.EmailAddress.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateSingle ("Host", Parser.Uri.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateMulti ("If-Match", EntityTagHeaderValue.TryParse, HttpHeaderKind.Request), @@ -85,18 +114,25 @@ namespace System.Net.Http.Headers HeaderInfo.CreateMulti ("If-None-Match", EntityTagHeaderValue.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateSingle ("If-Range", RangeConditionHeaderValue.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateSingle ("If-Unmodified-Since", Parser.DateTime.TryParse, HttpHeaderKind.Request), + HeaderInfo.CreateSingle ("Last-Modified", Parser.DateTime.TryParse, HttpHeaderKind.Content), + HeaderInfo.CreateSingle ("Location", Parser.Uri.TryParse, HttpHeaderKind.Response), HeaderInfo.CreateSingle ("Max-Forwards", Parser.Int.TryParse, HttpHeaderKind.Request), - HeaderInfo.CreateMulti ("Pragma", NameValueHeaderValue.TryParse, HttpHeaderKind.Request), + HeaderInfo.CreateMulti ("Pragma", NameValueHeaderValue.TryParsePragma, HttpHeaderKind.Request | HttpHeaderKind.Response), + HeaderInfo.CreateMulti ("Proxy-Authenticate", AuthenticationHeaderValue.TryParse, HttpHeaderKind.Response), HeaderInfo.CreateSingle ("Proxy-Authorization", AuthenticationHeaderValue.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateSingle ("Range", RangeHeaderValue.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateSingle ("Referer", Parser.Uri.TryParse, HttpHeaderKind.Request), - HeaderInfo.CreateMulti ("TE", TransferCodingWithQualityHeaderValue.TryParse, HttpHeaderKind.Request), - HeaderInfo.CreateMulti ("Trailer", Parser.Token.TryParse, HttpHeaderKind.Request), - HeaderInfo.CreateMulti ("Transfer-Encoding", TransferCodingHeaderValue.TryParse, HttpHeaderKind.Request), - HeaderInfo.CreateMulti ("Upgrade", ProductHeaderValue.TryParse, HttpHeaderKind.Request), + HeaderInfo.CreateSingle ("Retry-After", RetryConditionHeaderValue.TryParse, HttpHeaderKind.Response), + HeaderInfo.CreateMulti ("Server", ProductInfoHeaderValue.TryParse, HttpHeaderKind.Response), + HeaderInfo.CreateMulti ("TE", TransferCodingWithQualityHeaderValue.TryParse, HttpHeaderKind.Request, 0), + HeaderInfo.CreateMulti ("Trailer", CollectionParser.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response), + HeaderInfo.CreateMulti ("Transfer-Encoding", TransferCodingHeaderValue.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response), + HeaderInfo.CreateMulti ("Upgrade", ProductHeaderValue.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response), HeaderInfo.CreateMulti ("User-Agent", ProductInfoHeaderValue.TryParse, HttpHeaderKind.Request), - HeaderInfo.CreateMulti ("Via", ViaHeaderValue.TryParse, HttpHeaderKind.Request), - HeaderInfo.CreateMulti ("Warning", WarningHeaderValue.TryParse, HttpHeaderKind.Request) + HeaderInfo.CreateMulti ("Vary", CollectionParser.TryParse, HttpHeaderKind.Response), + HeaderInfo.CreateMulti ("Via", ViaHeaderValue.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response), + HeaderInfo.CreateMulti ("Warning", WarningHeaderValue.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response), + HeaderInfo.CreateMulti ("WWW-Authenticate", AuthenticationHeaderValue.TryParse, HttpHeaderKind.Response) }; known_headers = new Dictionary (StringComparer.OrdinalIgnoreCase); @@ -108,6 +144,8 @@ namespace System.Net.Http.Headers readonly Dictionary headers; readonly HttpHeaderKind HeaderKind; + internal bool? connectionclose, transferEncodingChunked; + protected HttpHeaders () { headers = new Dictionary (StringComparer.OrdinalIgnoreCase); @@ -183,18 +221,22 @@ namespace System.Net.Http.Headers return ok; } - public void AddWithoutValidation (string name, string value) + public bool TryAddWithoutValidation (string name, string value) { - AddWithoutValidation (name, new[] { value }); + return TryAddWithoutValidation (name, new[] { value }); } - public void AddWithoutValidation (string name, IEnumerable values) + public bool TryAddWithoutValidation (string name, IEnumerable values) { if (values == null) throw new ArgumentNullException ("values"); - CheckName (name); + HeaderInfo headerInfo; + if (!TryCheckName (name, out headerInfo)) + return false; + AddInternal (name, values, null, true); + return true; } HeaderInfo CheckName (string name) @@ -202,18 +244,38 @@ namespace System.Net.Http.Headers if (string.IsNullOrEmpty (name)) throw new ArgumentException ("name"); - if (!Parser.Token.IsValid (name)) - throw new FormatException (); + Parser.Token.Check (name); HeaderInfo headerInfo; - if (known_headers.TryGetValue (name, out headerInfo) && (headerInfo.HeaderKind & HeaderKind) == 0) - throw new InvalidOperationException (name); + if (known_headers.TryGetValue (name, out headerInfo) && (headerInfo.HeaderKind & HeaderKind) == 0) { + if (HeaderKind != HttpHeaderKind.None && ((HeaderKind | headerInfo.HeaderKind) & HttpHeaderKind.Content) != 0) + throw new InvalidOperationException (name); + + return null; + } return headerInfo; } + bool TryCheckName (string name, out HeaderInfo headerInfo) + { + if (!Parser.Token.TryCheck (name)) { + headerInfo = null; + return false; + } + + if (known_headers.TryGetValue (name, out headerInfo) && (headerInfo.HeaderKind & HeaderKind) == 0) { + if (HeaderKind != HttpHeaderKind.None && ((HeaderKind | headerInfo.HeaderKind) & HttpHeaderKind.Content) != 0) + return false; + } + + return true; + } + public void Clear () { + connectionclose = null; + transferEncodingChunked = null; headers.Clear (); } @@ -227,8 +289,16 @@ namespace System.Net.Http.Headers public IEnumerator>> GetEnumerator () { foreach (var entry in headers) { - IEnumerable values = null; // TODO: - yield return new KeyValuePair> (entry.Key, values); + var bucket = headers[entry.Key]; + + HeaderInfo headerInfo; + known_headers.TryGetValue (entry.Key, out headerInfo); + + var svalues = GetAllHeaderValues (bucket, headerInfo); + if (svalues == null) + continue; + + yield return new KeyValuePair> (entry.Key, svalues); } } @@ -239,6 +309,8 @@ namespace System.Net.Http.Headers public IEnumerable GetValues (string name) { + CheckName (name); + IEnumerable values; if (!TryGetValues (name, out values)) throw new InvalidOperationException (); @@ -254,7 +326,11 @@ namespace System.Net.Http.Headers public bool TryGetValues (string name, out IEnumerable values) { - var header_info = CheckName (name); + HeaderInfo headerInfo; + if (!TryCheckName (name, out headerInfo)) { + values = null; + return false; + } HeaderBucket bucket; if (!headers.TryGetValue (name, out bucket)) { @@ -262,19 +338,30 @@ namespace System.Net.Http.Headers return false; } - List string_values = new List (); - if (header_info != null && header_info.AllowsMany) { - header_info.AddToStringCollection (string_values, bucket.Parsed); - } else { - if (bucket.Parsed != null) - string_values.Add (bucket.Parsed.ToString ()); - } + values = GetAllHeaderValues (bucket, headerInfo); + return true; + } - if (bucket.HasStringValues) - string_values.AddRange (bucket.Values); + public override string ToString () + { + var sb = new StringBuilder (); + foreach (var entry in this) { + sb.Append (entry.Key); + sb.Append (": "); + + bool first = true; + foreach (var v in entry.Value) { + if (!first) + sb.Append (", "); + + sb.Append (v); + first = false; + } - values = string_values; - return true; + sb.Append ("\r\n"); + } + + return sb.ToString (); } internal void AddOrRemove (string name, string value) @@ -294,11 +381,53 @@ namespace System.Net.Http.Headers } internal void AddOrRemove (string name, T? value) where T : struct + { + AddOrRemove (name, value, null); + } + + internal void AddOrRemove (string name, T? value, Func converter) where T : struct { if (!value.HasValue) Remove (name); else - SetValue (name, value); + SetValue (name, value, converter); + } + + List GetAllHeaderValues (HeaderBucket bucket, HeaderInfo headerInfo) + { + List string_values = null; + if (headerInfo != null && headerInfo.AllowsMany) { + string_values = headerInfo.ToStringCollection (bucket.Parsed); + } else { + if (bucket.Parsed != null) { + string s = bucket.ParsedToString (); + if (!string.IsNullOrEmpty (s)) { + string_values = new List (); + string_values.Add (s); + } + } + } + + if (bucket.HasStringValues) { + if (string_values == null) + string_values = new List (); + + string_values.AddRange (bucket.Values); + } + + return string_values; + } + + internal static HttpHeaderKind GetKnownHeaderKind (string name) + { + if (string.IsNullOrEmpty (name)) + throw new ArgumentException ("name"); + + HeaderInfo headerInfo; + if (known_headers.TryGetValue (name, out headerInfo)) + return headerInfo.HeaderKind; + + return HttpHeaderKind.None; } internal T GetValue (string name) @@ -308,11 +437,19 @@ namespace System.Net.Http.Headers if (!headers.TryGetValue (name, out value)) return default (T); - var res = (T) value.Parsed; - if (value.HasStringValues && typeof (T) == typeof (string) && (object) res == null) - res = (T) (object) value.Values[0]; + if (value.HasStringValues) { + var hinfo = known_headers[name]; - return res; + object pvalue; + if (!hinfo.TryParse (value.Values [0], out pvalue)) { + return typeof (T) == typeof (string) ? (T) (object) value.Values[0] : default (T); + } + + value.Parsed = pvalue; + value.Values = null; + } + + return (T) value.Parsed; } internal HttpHeaderValueCollection GetValues (string name) where T : class @@ -324,12 +461,28 @@ namespace System.Net.Http.Headers headers.Add (name, value); } + if (value.HasStringValues) { + var hinfo = known_headers[name]; + if (value.Parsed == null) + value.Parsed = hinfo.CreateCollection (this); + + object pvalue; + for (int i = 0; i < value.Values.Count; ++i) { + if (!hinfo.TryParse (value.Values[i], out pvalue)) + continue; + + hinfo.AddToCollection (value.Parsed, pvalue); + value.Values.RemoveAt (i); + --i; + } + } + return (HttpHeaderValueCollection) value.Parsed; } - void SetValue (string name, T value) + void SetValue (string name, T value, Func toStringConverter = null) { - headers[name] = new HeaderBucket (value); + headers[name] = new HeaderBucket (value, toStringConverter); } } }