186 lines
6.3 KiB
C#
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();
|
|
}
|
|
} |