internal void HandleRequest(HttpRequest request) { if (!request.IsResponseSent) { HttpRequest.SetCurrentRequest(request); Logger.LogMessage(DiagnosticsLevels.TRACE, "Attempting to process connection request."); if (request.URL.AbsolutePath == "/jquery.js") { request.ResponseStatus = HttpStatusCodes.OK; request.ResponseHeaders.ContentType = "text/javascript"; request.ResponseWriter.Write(Utility.ReadEmbeddedResource("Org.Reddragonit.EmbeddedWebServer.resources.jquery.min.js")); request.SendResponse(); } else if (request.URL.AbsolutePath == "/json.js") { request.ResponseStatus = HttpStatusCodes.OK; request.ResponseHeaders.ContentType = "text/javascript"; request.ResponseWriter.Write(Utility.ReadEmbeddedResource("Org.Reddragonit.EmbeddedWebServer.resources.json2.min.js")); request.SendResponse(); } else { DateTime start = DateTime.Now; Site site = null; if (_sites.Count > 1) { foreach (Site s in _sites) { if ((s.ServerName != null) && (s.ServerName == request.URL.Host)) { site = s; break; } } if (site==null) { foreach (Site s in _sites) { if (s.Aliases != null) { foreach (string str in s.Aliases) { if (str == request.URL.Host) { site = s; break; } } } } } if (site==null) { foreach (Site s in _sites) { foreach (sIPPortPair ipp in s.ListenOn) { if ((ipp.Address != IPAddress.Any) && (request.Connection.LocalEndPoint == new IPEndPoint(ipp.Address, ipp.Port))) { site = s; break; } } } } } if (site == null) site = _defaultSite; Logger.LogMessage(DiagnosticsLevels.DEBUG, "Total time to find site: " + DateTime.Now.Subtract(start).TotalMilliseconds.ToString() + "ms"); if ((!site.AllowGET && request.Method.ToUpper() == "GET") || (!site.AllowPOST && request.Method.ToUpper() == "POST")) { request.ResponseStatus = HttpStatusCodes.Method_Not_Allowed; request.SendResponse(); } else { request.SetTimeout(site); try { if (request.URL.AbsolutePath == "/") request.UseDefaultPath(site); site.ProcessRequest(request); } catch (ThreadAbortException tae) { if (!request.IsResponseSent) { request.ResponseStatus = HttpStatusCodes.Request_Timeout; request.ClearResponse(); request.ResponseWriter.WriteLine("The server timed out processing the request."); request.SendResponse(); } } catch (Exception e) { Logger.LogError(e); if (!request.IsResponseSent) { request.ResponseStatus = HttpStatusCodes.Internal_Server_Error; request.ClearResponse(); request.ResponseWriter.Write(e.Message); request.SendResponse(); } } Logger.LogMessage(DiagnosticsLevels.DEBUG, "Total time to process request to URL " + request.URL.AbsolutePath + " = " + DateTime.Now.Subtract(start).TotalMilliseconds.ToString() + "ms"); } } } else Logger.LogMessage(DiagnosticsLevels.TRACE, "Response sent prior to processing, error in request."); }
/* * This function is called by the port listener once the appropriate site has * been located to process the given request. It scans through all * available handlers and attempts to find the appropriate one. Once * it has found the appropriate handler, it flags this fact, then * checks if the handler is reusable. If so, run the request through, checking for * the requirement of a session first. If not, create a new instance, init the instance, and use the new instance * to perform the same tasks, once completed deinit the handler. */ public void ProcessRequest(HttpRequest request) { PreRequest(request); if (!request.IsResponseSent) { HttpRequest.SetCurrentRequest(request); DateTime start = DateTime.Now; _currentSite = this; string realm = null; bool authed = false; bool loadSession = false; this.PreAuthentication(request, out loadSession); if (loadSession) SessionManager.LoadStateForConnection(request, this); HttpAuthTypes authType = this.GetAuthenticationTypeForUrl(request.URL, out realm); switch (authType) { case HttpAuthTypes.Digest: if (!(request.Headers["Authorization"] == null ? "" : request.Headers["Authorization"]).Trim().StartsWith("Digest")) { request.ResponseHeaders["WWW-Authenticate"] = "Digest realm=\"" + realm + "\", nonce=\"" + Convert.ToBase64String(_rand.NextBytes(4)) + "\""; request.ResponseStatus = HttpStatusCodes.Unauthorized; } else { Dictionary<string, string> pars = _ExtractAuthData(request.Headers["Authorization"].Trim().Substring(request.Headers["Authorization"].Trim().IndexOf(' ') + 1)); string dpass = pars["response"]; foreach (sHttpAuthUsernamePassword usr in GetAuthenticationInformationForUrl(request.URL, pars["username"])) { if (usr.GetDigestString(realm, request.Method, pars["uri"], pars["nonce"]) == dpass) { authed = true; this.PostAuthentication(request, usr); break; } } if (!authed) { PostAuthenticationFailure(request, pars["username"]); request.ResponseStatus = HttpStatusCodes.Unauthorized; request.ResponseHeaders["WWW-Authenticate"] = "Digest realm=\"" + realm + "\", nonce=\"" + Convert.ToBase64String(_rand.NextBytes(4)) + "\""; } } break; case HttpAuthTypes.Basic: if (!(request.Headers["Authorization"] == null ? "" : request.Headers["Authorization"]).Trim().StartsWith("Basic")) { request.ResponseHeaders["WWW-Authenticate"] = "Basic realm=\"" + realm + "\""; request.ResponseStatus = HttpStatusCodes.Unauthorized; } else { string bpass = request.Headers["Authorization"].Trim().Split(' ')[1]; foreach (sHttpAuthUsernamePassword usr in GetAuthenticationInformationForUrl(request.URL, ASCIIEncoding.ASCII.GetString(Convert.FromBase64String(bpass)).Split(':')[0])) { if (usr.BasicAuthorizationString == bpass) { authed = true; this.PostAuthentication(request, usr); break; } } if (!authed) { PostAuthenticationFailure(request, ASCIIEncoding.ASCII.GetString(Convert.FromBase64String(bpass)).Split(':')[0]); request.ResponseStatus = HttpStatusCodes.Unauthorized; request.ResponseHeaders["WWW-Authenticate"] = "Basic realm=\"" + realm + "\""; } } break; case HttpAuthTypes.None: authed = true; break; } if (authed) { IRequestHandler handler = null; Monitor.Enter(_handlerCache); if (_handlerCache.ContainsKey(request.URL.AbsolutePath)) handler = (IRequestHandler)_handlerCache[request.URL.AbsolutePath].Value; Monitor.Exit(_handlerCache); if (handler == null) { foreach (IRequestHandler ih in Handlers) { if (ih.CanProcessRequest(request, this)) { handler = ih; Monitor.Enter(_handlerCache); if (!_handlerCache.ContainsKey(request.URL.AbsolutePath)) _handlerCache.Add(request.URL.AbsolutePath, new CachedItemContainer(handler)); Monitor.Exit(_handlerCache); break; } } } if (handler == null) { request.ClearResponse(); request.ResponseStatus = HttpStatusCodes.Not_Found; } else { Logger.LogMessage(DiagnosticsLevels.TRACE, "Time to determine handler for URL " + request.URL.AbsolutePath + " = " + DateTime.Now.Subtract(start).TotalMilliseconds + " ms"); if (handler.IsReusable) { if (handler.RequiresSessionForRequest(request, this) || (DefaultPage(request.IsMobile) == request.URL.AbsolutePath && SessionStateType != SiteSessionTypes.None)) SessionManager.LoadStateForConnection(request, this); try { handler.ProcessRequest(request, this); } catch (ThreadAbortException tae) { if (!request.IsResponseSent) { request.ResponseStatus = HttpStatusCodes.Request_Timeout; request.ResponseWriter.WriteLine("The request has taken to long to process."); request.SendResponse(); } } catch (Exception e) { Logger.LogError(e); if (!RequestError(request, e)) { request.ResponseStatus = HttpStatusCodes.Internal_Server_Error; request.ClearResponse(); request.ResponseWriter.Write(e.Message); } } if (handler.RequiresSessionForRequest(request, this) || (DefaultPage(request.IsMobile) == request.URL.AbsolutePath && SessionStateType != SiteSessionTypes.None)) SessionManager.StoreSessionForConnection(request, this); } else { IRequestHandler hndl = (IRequestHandler)handler.GetType().GetConstructor(Type.EmptyTypes).Invoke(new object[0]); hndl.Init(); if (hndl.RequiresSessionForRequest(request, this)) SessionManager.LoadStateForConnection(request, this); try { hndl.ProcessRequest(request, this); } catch (ThreadAbortException tae) { if (!request.IsResponseSent) { request.ResponseStatus = HttpStatusCodes.Request_Timeout; request.ResponseWriter.WriteLine("The request has taken to long to process."); request.SendResponse(); } } catch (Exception e) { Logger.LogError(e); if (!RequestError(request, e)) { request.ResponseStatus = HttpStatusCodes.Internal_Server_Error; request.ClearResponse(); request.ResponseWriter.Write(e.Message); } } if (hndl.RequiresSessionForRequest(request, this)) SessionManager.StoreSessionForConnection(request, this); hndl.DeInit(); } } } } PostRequest(request); if (request.IsResponseSent) Logger.LogMessage(DiagnosticsLevels.DEBUG, "WARNING: Response has already been sent before site called to send it."); else request.SendResponse(); try { request.Connection.DisposeRequest(request); } catch (Exception e) { } }