using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text; namespace ln.http { public class HeaderContainer : IEnumerable
{ private Dictionary _headers = new Dictionary(); public HeaderContainer() { } public HeaderContainer(IEnumerable
headers) { foreach (var header in headers) Add(new Header(header)); } public HeaderContainer(Stream stream) { Read(stream); } public string this[string headerName] { get => Get(headerName); set => Set(headerName, value); } public bool TryGetHeader(string headerName, out Header header) => _headers.TryGetValue(headerName.ToLower(), out header); public bool TryGetValue(string headerName, out string headerValue) { if (_headers.TryGetValue(headerName.ToLower(), out Header header)) { headerValue = header.Value; return true; } headerValue = null; return false; } public bool Contains(string headerName) => _headers.ContainsKey(headerName.ToLower()); public void Add(string headerName, string headerValue) { string lowerHeaderName = headerName.ToLower(); if (_headers.TryGetValue(lowerHeaderName, out Header header)) header.Value += " " + headerValue; else _headers.Add(lowerHeaderName, new Header(headerName, headerValue)); } public void Add(Header header) => Add(header.Name, header.Value); public void Remove(string headerName) => _headers.Remove(headerName.ToLower()); public void Clear() => _headers.Clear(); public void Set(string headerName, String headerValue) { string lowerHeaderName = headerName.ToLower(); if (!_headers.TryGetValue(lowerHeaderName, out Header header)) { header = new Header(headerName, ""); _headers.Add(lowerHeaderName, header); } header.Value = headerValue; } public string Get(string headerName) => Get(headerName, null); public string Get(string headerName, string defaultValue) { if (TryGetHeader(headerName, out Header header)) return header.Value; return defaultValue; } public int GetInteger(string headerName) { return int.Parse(Get(headerName)); } public int GetInteger(string headerName, int defaultValue) { if (TryGetValue(headerName, out string headerValue)) return int.Parse(headerValue); return defaultValue; } public bool TryGetInteger(string headerName, out int value) { value = 0; return TryGetValue(headerName, out string headerValue) && int.TryParse(headerValue, out value); } public float GetFloat(string headerName) { return float.Parse(Get(headerName)); } public float GetFloat(string headerName, float defaultValue) { if (TryGetValue(headerName, out string headerValue)) return float.Parse(headerValue); return defaultValue; } public bool TryGetFloat(string headerName, out float value) { value = 0; return TryGetValue(headerName, out string headerValue) && float.TryParse(headerValue, out value); } public double GetDouble(string headerName) { return double.Parse(Get(headerName)); } public double GetDouble(string headerName, double defaultValue) { if (TryGetValue(headerName, out string headerValue)) return double.Parse(headerValue); return defaultValue; } public bool TryGetDouble(string headerName, out double value) { value = 0; return TryGetValue(headerName, out string headerValue) && double.TryParse(headerValue, out value); } public IEnumerator
GetEnumerator() => _headers.Values.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public override string ToString() { StringBuilder sb = new StringBuilder(); foreach (var header in _headers) sb.AppendFormat("{0}: {1}\r\n", header.Value.Name, header.Value.Value); return sb.ToString(); } public void Read(Stream stream) { string headerName = null; string headerLine; while (!String.Empty.Equals(headerLine = HttpConnection.ReadLine(stream))) { int colon = headerLine.IndexOf(':', StringComparison.InvariantCulture); if (char.IsWhiteSpace(headerLine[0])) { if (headerName is string) Add(headerName, " " + headerLine.Substring(1).Trim()); else throw new FormatException("expected header name"); } else if (colon > 0) { headerName = headerLine.Substring(0, colon).Trim(); Add(headerName, headerLine.Substring(colon + 1).Trim()); } } } public void CopyTo(Stream stream) { foreach (var header in _headers.Values) { byte[] bytes = Encoding.ASCII.GetBytes($"{header.Name}: {header.Value}\r\n"); stream.Write(bytes, 0, bytes.Length); } stream.Write(new byte[] { 0x0d, 0x0a }, 0, 2); } } public class Header { private string _name; private Dictionary _parameters; public string Name { get => _name; set { _name = value; UpperName = value.ToUpper(); } } public string UpperName { get; private set; } public string Value { get; set; } public Header(string headerName) { Name = headerName; Value = String.Empty; } public Header(string headerName, string headerValue) { Name = headerName; Value = headerValue; } public Header(Header src) { Name = src.Name; Value = src.Value; } public bool TryGetParameter(string parameterName, out string parameterValue) { if (_parameters is null) ParseParameters(); return _parameters.TryGetValue(parameterName, out parameterValue); } public bool ContainsParameter(string parameterName) { if (_parameters is null) ParseParameters(); return _parameters.ContainsKey(parameterName); } public Header ParseParameters() { _parameters = new Dictionary(); int idxSemicolon = Value.IndexOf(';'); if (idxSemicolon != -1) { string[] ptoks = Value.Split(';'); foreach (string ptok in ptoks) { int idxEqual = ptok.IndexOf('='); string pn, pv; if (idxEqual != -1) { pn = ptok.Substring(0, idxEqual).Trim(); pv = ptok.Substring(idxEqual + 1); } else { pn = ptok.Trim(); pv = ""; } _parameters.Add(pn, pv); } } return this; } public override string ToString() => String.Format("{0}: {1}", Name, Value); } }