/// <summary> /// Initializes a new instance of the <see cref="WebData"/> class. /// </summary> /// <param name="request">The request.</param> /// <param name="stopWatch">The stopwatch.</param> internal WebData(WebRequest request, Stopwatch stopWatch) { StopWatch = stopWatch; Request = request; Result = new WebResultBuilder(request); // check for method call { string url = request.DecodedUrl.TrimEnd('/'); if (url.Length == 0) { url = "/"; } Method = request.Server.FindMethod(url); if (Method != null) { Trace.TraceInformation("Method Call: {0} Url: {1} {2}", Method, Request, Session); } } }
/// <summary>Handles a client stage1 (preparations).</summary> /// <remarks>Performs the firewall checks and enters stage2.</remarks> internal void HandleClient(WebServerClient client) { System.Globalization.CultureInfo threadCulture = Thread.CurrentThread.CurrentCulture; int threadId = Thread.CurrentThread.ManagedThreadId; WebResultBuilder result = null; try { // callback for connected client ClientConnected?.Invoke(this, new WebClientEventArgs(client)); // do request handling int requestNumber = 0; if (PerformanceChecks) { Trace.TraceInformation( $"HandleClient [{threadId}] <cyan>{client.RemoteEndPoint}<default> ready to receive request. " + $"Elapsed <cyan>{client.StopWatch.Elapsed.FormatTime()}<default>."); } while (client.IsConnected) { result = null; if (PerformanceChecks && requestNumber > 0) { Trace.TraceInformation( $"HandleClient [{threadId}] <cyan>{client.RemoteEndPoint}<default> request <green>{requestNumber}<default> handling completed. " + $"Elapsed <cyan>{client.StopWatch.Elapsed.FormatTime()}<default>."); } // read first request line string firstLine = client.Reader.ReadLine(); client.StopWatch.Reset(); if (PerformanceChecks) { Trace.TraceInformation( $"HandleClient [{threadId}] <cyan>{client.RemoteEndPoint}<default> start handling request <cyan>{++requestNumber}<default>. " + $"Elapsed <cyan>{client.StopWatch.Elapsed.FormatTime()}<default>."); } // load request var request = WebRequest.Load(this, firstLine, client); // prepare web data object var data = new WebData(request, client.StopWatch); result = data.Result; // update thread culture Thread.CurrentThread.CurrentCulture = data.Request.Culture; // handle request but change some default exceptions to web exceptions try { HandleRequest(client, data); } catch (ObjectDisposedException) { Trace.TraceInformation($"HandleClient [{threadId}] <red>{client.RemoteEndPoint}<default> Connection closed"); } catch (InvalidOperationException ex) { throw new WebServerException(ex, WebError.InvalidOperation, 0, ex.Message); } catch (ArgumentException ex) { throw new WebServerException(ex, WebError.InvalidParameters, 0, ex.Message); } } } catch (WebServerException ex) { Trace.TraceInformation(ex.ToString()); if (result == null) { result = new WebResultBuilder(this); } result.AddMessage(WebMessage.Create(ex)); if (ex.Error == WebError.AuthenticationRequired || ex.Error == WebError.InvalidTransactionKey) { result.Headers["WWW-Authenticate"] = $"Basic realm=\"{AssemblyVersionInfo.Program.Company} - {AssemblyVersionInfo.Program.Product}\""; } result.CloseAfterAnswer = true; client.SendAnswer(result.ToAnswer()); } catch (SocketException) { Trace.TraceInformation($"HandleClient [{threadId}] <red>{client.RemoteEndPoint}<default> Connection closed"); /*client closed connection*/ } catch (EndOfStreamException) { /*client closed connection*/ Trace.TraceInformation($"HandleClient [{threadId}] <red>{client.RemoteEndPoint}<default> Connection closed"); } catch (Exception ex) { if (ex.InnerException is SocketException) { Trace.TraceInformation($"HandleClient [{threadId}] <red>{client.RemoteEndPoint}<default> Connection closed"); return; } string supportCode = Base32.Safe.Encode(Environment.TickCount); Trace.TraceError("<red>Unhandled Internal Server Error<default> Code {1}\n{0}", ex.ToString(), supportCode); if (result == null) { result = new WebResultBuilder(this); } result.AddMessage(ex.Source, WebError.InternalServerError, $"Internal Server Error\nUnexpected result on request.\nPlease contact support!\nSupport Code = {supportCode}"); result.CloseAfterAnswer = true; client.SendAnswer(result.ToAnswer()); } finally { while (client.IsConnected && client.Reader.Available == 0) { Thread.Sleep(1); } client.Close(); if (client != null) { ClientDisconnected?.Invoke(this, new WebClientEventArgs(client)); } // reset thread culture if (Thread.CurrentThread.CurrentCulture != threadCulture) { Thread.CurrentThread.CurrentCulture = threadCulture; } } }
/// <summary> /// Initializes a new instance of the <see cref="WebData"/> class. /// </summary> /// <param name="server">The server.</param> /// <param name="stopWatch">The stop watch.</param> internal WebData(WebServer server, Stopwatch stopWatch) { StopWatch = stopWatch; Result = new WebResultBuilder(server); }