public static QueryStringValuesCollection FromNameValueCollection(NameValueCollection d) { var col = new QueryStringValuesCollection(); foreach (string key in d.Keys) { var values = d.GetValues(key); if (values == null) { continue; } var valuesCollection = new ValuesCollection(); if (key == null) { var value = values[0]; string _key = value; valuesCollection.AddValue(new Value(null)); col._valuesCollections[_key] = valuesCollection; } else { foreach (var value in values) { valuesCollection.AddValue(new Value(value)); } col._valuesCollections[key] = valuesCollection; } } return(col); }
public WebServerRequestContext(HttpListenerContext httpContext, IPAddress remoteEndpoint) { this.httpContext = httpContext; QueryString = QueryStringValuesCollection.FromNameValueCollection(httpContext.Request.QueryString); Headers = QueryStringValuesCollection.FromNameValueCollection(httpContext.Request.Headers); RemoteEndpoint = remoteEndpoint; ForwardedUri = Headers.GetStringOrDefault("X-Forwarded-Uri", null); HttpMethod = new HttpMethod(httpContext.Request.HttpMethod); }
private static async Task <object> ParseKnownTypes(HttpListenerContext httpContext, WebServerRequestContext ctx) { ContentType ct; try { ct = new ContentType(httpContext.Request.ContentType); } catch (FormatException) { return(null); } string payload; switch (ct.MediaType) { case "application/x-www-form-urlencoded": payload = await ctx.ReadAsString(); if (payload == null) { return("(empty)"); } ctx.FormData = QueryStringValuesCollection.Parse(payload); return(ctx.FormData); case "application/json": payload = await ctx.ReadAsString(); if (payload == null) { return("(empty)"); } ctx.JsonData = JToken.Parse(payload); return(ctx.JsonData); case "text/xml": payload = await ctx.ReadAsString(); if (payload == null) { return("(empty)"); } ctx.XmlData = XDocument.Parse(payload); return(ctx.XmlData); default: return(null); } }
public async void Handle() { WebServerRequestContext ctx = new WebServerRequestContext(_httpContext, RemoteEndpoint); var httpContext = _httpContext; httpContext.Response.AppendHeader("Access-Control-Allow-Origin", "*"); var props = new Dictionary <string, object>() { ["method"] = _httpContext.Request.HttpMethod, ["path"] = _httpContext.Request.Url.AbsolutePath, }; using (MappedDiagnosticsLogicalContext.SetScoped("client_id", ClientId)) using (MappedDiagnosticsLogicalContext.SetScoped("remote_ip", RemoteEndpoint)) { try { // Parse request props.Add("query", QueryStringValuesCollection.FromNameValueCollection(_httpContext.Request.QueryString).GetAsDictionary()); props.Add("content_type", httpContext.Request.ContentType); props.Add("content_length", httpContext.Request.ContentLength64); if (httpContext.Request.ContentType != null) { props.Add("content", await ParseKnownTypes(httpContext, ctx)); } var match = MatchRoutes(ctx.Path, ctx.HttpMethod); if (match.RouteMatch == null) { Logger.Trace() .Message($"[{ClientId}] Not found HTTP request - {_httpContext.Request.HttpMethod} {_httpContext.Request.Url.AbsolutePath}") .Properties(props) .Property("status_code", 404) .Write(); httpContext.Response.StatusCode = 404; httpContext.Response.OutputStream.Close(); return; } var ep = match.Endpoint; ctx.Params = match.RouteMatch.Params; Logger.Trace() .Message($"[{ClientId}] New HTTP request - {_httpContext.Request.HttpMethod} {_httpContext.Request.Url.AbsolutePath}") .Properties(props) .Write(); Stopwatch timer = new Stopwatch(); timer.Start(); var response = await ep.Callback(ctx); ProcessingTime = timer.ElapsedMilliseconds; if (response == null) { httpContext.Response.StatusCode = 200; httpContext.Response.ContentLength64 = 0; } else { foreach (string responseHeader in response._headers) { httpContext.Response.Headers.Add(responseHeader, response._headers[responseHeader]); } await response.WriteToResponse(this, httpContext.Response); } } catch (UnauthorizedException) { Logger.Info() .Message($"[{ClientId}] Unauthorized HTTP request - {_httpContext.Request.HttpMethod} {_httpContext.Request.Url.PathAndQuery}") .Properties(props) .Property("status_code", 401) .Write(); httpContext.Response.StatusCode = 401; } catch (Exception e) { Logger.Error() .Message($"[{ClientId}] Error during handling HTTP request - {_httpContext.Request.HttpMethod} {_httpContext.Request.Url.PathAndQuery}") .Properties(props) .Property("status_code", 500) .Exception(e) .Write(); httpContext.Response.StatusCode = 500; } try { httpContext.Response.OutputStream.Close(); } catch { // ignored } } }