ln.http/ln.http/HeaderContainer.cs

269 lines
8.2 KiB
C#

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<Header>
{
private Dictionary<string, Header> _headers = new Dictionary<string, Header>();
public HeaderContainer()
{
}
public HeaderContainer(IEnumerable<Header> 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<Header> 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<string, string> _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<string, string>();
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);
}
}