private Task SendHttp(IRequestContext context) { var incoming = context.Incoming; incoming.SendHeaders(context); var head = new StringBuilder(); head.Append(incoming.Method); head.Append(' '); //head.Append(incoming.Scheme == Scheme.Https ? "https" : " http"); //head.Append("://"); //head.Append(incoming.DomainName); //head.Append(':'); //head.Append(incoming.DestinationPort); head.Append(incoming.Path.HasValue ? incoming.Path.Value : "/"); if (incoming.Query.HasValue) { head.Append(incoming.Query); } head.Append(' '); head.Append("HTTP/1.1"); head.Append("\r\n"); head.Append("Host: "); head.Append(incoming.DomainName); head.Append(":"); head.Append(incoming.DestinationPort); head.Append("\r\n"); if (incoming.Headers != null) { foreach (var header in incoming.Headers) { if (string.IsNullOrEmpty(header.Key)) { continue; } if (string.Equals("Connection", header.Key, StringComparison.OrdinalIgnoreCase) || string.Equals("Keep-Alive", header.Key, StringComparison.OrdinalIgnoreCase) || string.Equals("Host", header.Key, StringComparison.OrdinalIgnoreCase)) { continue; } if (header.Value == null || header.Value.Length == 0) { continue; } foreach (var headValue in header.Value) { head.Append(header.Key); head.Append(": "); head.Append(headValue); head.Append("\r\n"); } } } head.Append("Connection: Keep-Alive\r\n"); head.Append("Keep-Alive: timeout="); head.Append((int)(_maximumIdleTime.TotalSeconds + 5)); head.Append("\r\n\r\n"); var headBytes = Encoding.ASCII.GetBytes(head.ToString()); context.Log?.Log(LogType.TcpIp, LogLevel.Detailed, () => $"Writing {headBytes.Length} bytes of header to the connection stream"); if (context.Log != null && context.Log.WillLog(LogType.TcpIp, LogLevel.VeryDetailed)) { var headLines = head.ToString().Replace("\r", "").Split('\n'); foreach (var headLine in headLines.Where(h => !string.IsNullOrEmpty(h))) { context.Log.Log(LogType.TcpIp, LogLevel.VeryDetailed, () => $"> {headLine}"); } } _stream.Write(headBytes, 0, headBytes.Length); return(Task.Run(() => { if (incoming.Content != null && incoming.Content.CanRead) { var buffer = incoming.ContentLength.HasValue ? _bufferPool.Get(incoming.ContentLength.Value) : _bufferPool.Get(); try { int Read() { var readTask = incoming.Content.ReadAsync(buffer, 0, buffer.Length); readTask.Wait(); if (readTask.IsFaulted) { context.Log?.Log(LogType.Exception, LogLevel.Important, () => $"Connection failed to read from the incoming stream. {readTask.Exception.Message}"); throw new ConnectionException(this, "incoming read task faulted", readTask.Exception); } if (readTask.IsCanceled) { context.Log?.Log(LogType.TcpIp, LogLevel.Important, () => $"Timeout reading from the incoming stream"); throw new ConnectionException(this, "read task timed out"); } var bytesRead = readTask.Result; context.Log?.Log(LogType.TcpIp, LogLevel.Detailed, () => $"Read {bytesRead} bytes from the incoming stream"); return bytesRead; } void Write(int count) { var writeTask = _stream.WriteAsync(buffer, 0, count); writeTask.Wait(); if (writeTask.IsFaulted) { context.Log?.Log(LogType.Exception, LogLevel.Important, () => $"Connection failed to write to Tcp stream. {writeTask.Exception.Message}"); throw new ConnectionException(this, "Tcp write task faulted", writeTask.Exception); } if (writeTask.IsCanceled) { context.Log?.Log(LogType.TcpIp, LogLevel.Important, () => $"Timeout writing to Tcp stream"); throw new ConnectionException(this, "Tcp write task timed out"); } } while (true) { var bytesRead = Read(); if (bytesRead == 0) { break; } context.Log?.Log(LogType.TcpIp, LogLevel.VeryDetailed, () => $"Read {bytesRead} bytes of content from the incomming stream"); Write(bytesRead); context.Log?.Log(LogType.TcpIp, LogLevel.VeryDetailed, () => $"Wrote {bytesRead} bytes to the Tcp connection"); } } finally { _bufferPool.Reuse(buffer); } } })); }