private void SendResponse() { var statusCode = response.Status; var responseBody = ProcessRanges(response, ref statusCode); var responseStream = new ConcatenatedStream(); try { var headerBlock = new StringBuilder(); headerBlock.AppendFormat( "HTTP/1.1 {0} {1}\r\n", (uint)statusCode, HttpPhrases.Phrases[statusCode] ); headerBlock.Append(response.Headers.HeaderBlock); headerBlock.Append(CRLF); var headerStream = new MemoryStream( Encoding.ASCII.GetBytes(headerBlock.ToString())); responseStream.AddStream(headerStream); if (Method != "HEAD" && responseBody != null) { responseStream.AddStream(responseBody); responseBody = null; } owner.Logger.LogTrace($"{this} - {(uint)statusCode} response for {Path}"); state = HttpStates.Writing; var sp = new StreamPump(responseStream, stream, BUFFER_SIZE); sp.Pump((pump, result) => { pump.Input.Close(); pump.Input.Dispose(); if (result == StreamPumpResult.Delivered) { owner.Logger.LogTrace($"{this} - Done writing response"); string conn; if (Headers.TryGetValue("connection", out conn) && conn.ToUpperInvariant() == "KEEP-ALIVE") { ReadNext(); return; } } else { owner.Logger.LogTrace($"{this} - Client aborted connection"); } Close(); }); } catch (Exception) { responseStream.Dispose(); throw; } finally { responseBody?.Dispose(); } }
internal Redirect(HttpCode code, string uri) : base(code, "text/plain", "Redirecting...") { Headers.Add("Location", uri); }
private void ReadCallback(IAsyncResult result) { if (state == HttpStates.Closed) { return; } State = HttpStates.Reading; try { var read = stream.EndRead(result); if (read < 0) { throw new HttpException("Client did not send anything"); } owner.Logger.LogTrace($"{this} - Read {read} bytes"); readStream.Write(buffer, 0, read); lastActivity = DateTime.Now; } catch (Exception) { if (!IsATimeout) { owner.Logger.LogTrace($"{this} - Failed to read data"); Close(); } return; } try { if (!hasHeaders) { readStream.Seek(0, SeekOrigin.Begin); var reader = new StreamReader(readStream); for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) { line = line.Trim(); if (string.IsNullOrEmpty(line)) { hasHeaders = true; readStream = StreamManager.GetStream(); if (Headers.ContainsKey("content-length") && uint.TryParse(Headers["content-length"], out bodyBytes)) { if (bodyBytes > 1 << 20) { throw new IOException("Body too long"); } var ascii = Encoding.ASCII.GetBytes(reader.ReadToEnd()); readStream.Write(ascii, 0, ascii.Length); owner.Logger.LogTrace($"Must read body bytes {bodyBytes}"); } break; } if (Method == null) { var parts = line.Split(new[] { ' ' }, 3); Method = parts[0].Trim().ToUpperInvariant(); Path = parts[1].Trim(); owner.Logger.LogTrace($"{this} - {Method} request for {Path}"); } else { var parts = line.Split(new[] { ':' }, 2); Headers[parts[0]] = Uri.UnescapeDataString(parts[1]).Trim(); } } } if (bodyBytes != 0 && bodyBytes > readStream.Length) { owner.Logger.LogTrace($"{this} - Bytes to go { (bodyBytes - readStream.Length) }"); Read(); return; } using (readStream) { Body = Encoding.UTF8.GetString(readStream.ToArray()); } SetupResponse(); } catch (Exception ex) { owner.Logger.LogTrace($"{this} - Failed to process request Ex [{ ex }]"); response = error500.HandleRequest(this); SendResponse(); } }