using System; using System.IO; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using ln.http.content; using ln.json; using ln.type; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace ln.http { public class HttpRequest : IDisposable { public string RequestMethodName { get; } public Uri RequestUri { get; private set; } public HttpVersion HttpVersion { get; } public HeaderContainer Headers { get; } public HttpMethod Method { get; private set; } public String Host { get; private set; } public int Port { get; private set; } public bool ViaTLS { get; private set; } public QueryStringParameters Query { get; private set; } public Uri BaseUri { get; private set; } Dictionary requestCookies; public HttpContentStream ContentStream { get; } public HttpRequest(string requestMethodName, Uri requestUri, HttpVersion httpVersion, bool viaTLS, HeaderContainer headerContainer, HttpContentStream contentStream) { RequestMethodName = requestMethodName; RequestUri = requestUri; HttpVersion = httpVersion; Headers = headerContainer; ViaTLS = viaTLS; ContentStream = contentStream; Initialize(); } //private static Regex reHostPort = new Regex("(?(\\w[^:]*|\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|\\[\\]]+))(:(?\\d+))?"); void Initialize() { if (Enum.TryParse(RequestMethodName, out HttpMethod httpMethod)) Method = httpMethod; else Method = HttpMethod.NONE; if (Headers.TryGetValue("Host", out string host)) { int colon = host.LastIndexOf(':'); if (colon != -1) { Host = host.Substring(0, colon).Trim(); Port = int.Parse(host.Substring(colon + 1).Trim()); } else { Host = host.Trim(); } } else { Host = RequestUri.Host; Port = RequestUri.Port; } /* if (Headers.TryGetValue("X-Forwarded-Host", out string forwardedHost)) host = forwardedHost; if (Headers.TryGetValue("X-Forwarded-For", out string forwardedFor)) ClientAddress = IPAddress.Parse(forwardedFor.ReadToken(',')); if (Headers.TryGetValue("X-Forwarded-Proto", out string forwardedProto)) TLS = forwardedProto.Equals("https"); if (Headers.TryGetValue("Forwarded", out string forwarded)) { // ToDo: Implement parser } */ BaseUri = new UriBuilder(ViaTLS ? "https:" : "http:", Host, Port).Uri; RequestUri = new Uri(BaseUri, RequestUri); Query = new QueryStringParameters(RequestUri.Query); requestCookies = new Dictionary(); if (Headers.TryGetValue("Cookie", out string cookies)) SetupCookies(cookies); } private void SetupCookies(string cookies) { foreach (String cookie in cookies.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { string[] c = cookie.Split(new char[] { '=' }, 2); string cn, cv; cn = c[0].Trim(); if (c.Length > 1) cv = c[1].Trim(); else cv = ""; if (!this.requestCookies.ContainsKey(cn)) this.requestCookies.Add(cn, cv); } } public override string ToString() => $"[HttpRequest: Host={Host} Port={Port} HttpVersion={HttpVersion} Method={Method} URI={RequestUri} Query={Query}]"; public String GetRequestHeader(String name) { return GetRequestHeader(name, ""); } public String GetRequestHeader(String name, String def) { if (Headers.TryGetValue(name, out string value)) return value; return def; } public String[] CookieNames => requestCookies.Keys.ToArray(); public bool ContainsCookie(String name) => this.requestCookies.ContainsKey(name); public String GetCookie(String name) => requestCookies[name]; public bool TryGetCookie(string cookieName, out string cookieValue) => requestCookies.TryGetValue(cookieName, out cookieValue); public HttpResponse Redirect(string location, params object[] p) => Redirect(HttpStatusCode.SeeOther, location, p); public HttpResponse Redirect(HttpStatusCode statusCode, string location, params object[] p) { if (p?.Length > 0) location = string.Format(location, p); HttpResponse response = new HttpResponse(statusCode); response.SetHeader("Location", location); return response; } public JSONValue ToJsonValue() { long p = ContentStream.Position; try { using (TextReader reader = new StreamReader(ContentStream)) return JSONParser.Parse(reader); } finally { ContentStream.Position = p; } } private string? _bodyText; public string Text { get { if (_bodyText is null) _bodyText = Encoding.UTF8.GetString(ContentStream.ReadToEnd()); return _bodyText; } } private JObject? _jobject; public JObject Json() { if (_jobject is null) _jobject = JObject.Load(new JsonTextReader(new StringReader(Text))); return _jobject; } public T Json() => JsonConvert.DeserializeObject(Text); public object Json(Type nativeType) => JsonConvert.DeserializeObject(Text, nativeType); public void Dispose() => ContentStream?.Dispose(); } }