ln.http/ln.http/HttpRequest.cs

186 lines
6.3 KiB
C#

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<String, String> 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("(?<host>(\\w[^:]*|\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|\\[\\]]+))(:(?<port>\\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<string, string>();
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<T>() => JsonConvert.DeserializeObject<T>(Text);
public object Json(Type nativeType) => JsonConvert.DeserializeObject(Text, nativeType);
public void Dispose() => ContentStream?.Dispose();
}
}