예제 #1
0
        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();
            }
        }
예제 #2
0
 internal Redirect(HttpCode code, string uri)
     : base(code, "text/plain", "Redirecting...")
 {
     Headers.Add("Location", uri);
 }
예제 #3
0
        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();
            }
        }