Exemplo n.º 1
0
        static public async Task HttpHandleAsync(Stream input, Stream output,
                                                 Func <HttpRequest, Task <HttpResponse> > handler, CancellationToken cancel = default(CancellationToken))
        {
            //await Task.Delay(TimeSpan.FromMilliseconds(5000));
            //Console.WriteLine(RuntimeHelpers.GetHashCode(client));
            using (var reader = new BufferedStreamReader(input))
            {
                var httpRequest = await reader.ReadLineAsync(8192);

                //Console.WriteLine($"httpRequest: {httpRequest}");
                var headers      = new HttpHeaders();
                var headersChars = 0;
                while (true)
                {
                    var rawLine = await reader.ReadLineAsync(8192);

                    headersChars += rawLine.Length;
                    if (headersChars > 8192)
                    {
                        throw new IndexOutOfRangeException("Request headers content is too big");
                    }

                    var line = rawLine.Trim();
                    if (string.IsNullOrEmpty(line))
                    {
                        break;
                    }
                    var parts = line.Split(':', 2);
                    headers.Add(parts[0].Trim(), (parts.Length >= 2) ? parts[1].Trim() : "");
                }

                long contentLength;
                long.TryParse(headers.GetFirst("Content-Length") ?? "0", out contentLength);

                var          limited = reader.Limit(contentLength);
                var          request = new HttpRequest(httpRequest, headers, limited);
                HttpResponse response;
                try
                {
                    response = await handler(request);
                }
                catch (Exception e)
                {
                    response = new HttpResponse(e.Message, HttpStatus.InternalServerError);
                }

                await limited.SkipRemaining();

                //Console.WriteLine(headers);
                //Console.WriteLine("Host:" + headers.GetFirst("host"));

                var sb = new StringBuilder();
                sb.Append($"HTTP/1.1 {response.Status.Code} {response.Status.Message}\r\n");
                response.Headers.Replace("Content-Length", response.Body.Length.ToString());
                response.Headers.Replace("Connection", "Closed");
                foreach (var pair in response.Headers.Items)
                {
                    sb.Append($"{pair.Key}: {pair.Value}\r\n");
                }

                sb.Append("\r\n");
                await output.WriteAsync(new ReadOnlyMemory <byte>(Encoding.UTF8.GetBytes(sb.ToString())),
                                        cancel);

                await response.Body.WriteAsync(output);
            }
        }