public static async Task <HttpRequest> GetIncomingRequest(Stream inputStream, List <byte> cache, Delegate_verifyHeaders proc_verify, CancellationToken token) { // Read Request Line string request = await ReadLineAsync(inputStream, cache, token); if (string.IsNullOrEmpty(request)) { return(null); // 表示前端已经切断通讯 } #if NO string[] tokens = request.Split(' '); if (tokens.Length != 3) { throw new Exception("invalid http request line"); } #endif List <string> tokens = MessageUtility.SplitFirstLine(request); if (tokens == null) { throw new Exception("1 invalid http request line '" + request + "'"); } string method = tokens[0].ToUpper(); string url = tokens[1]; string protocolVersion = tokens[2]; //Read Headers Dictionary <string, string> headers = new Dictionary <string, string>(); string line; while ((line = await ReadLineAsync(inputStream, cache, token)) != null) { if (line.Equals("")) { break; } int separator = line.IndexOf(':'); if (separator == -1) { throw new Exception("1 invalid http header line: " + line); } string name = line.Substring(0, separator); int pos = separator + 1; while ((pos < line.Length) && (line[pos] == ' ')) { pos++; } string value = line.Substring(pos, line.Length - pos); headers.Add(name, value); if (headers.Count > MAX_HEADER_LINES) { throw new Exception("headers 行数超过配额"); } } if (proc_verify != null) { if (proc_verify(headers) == false) { return(null); } } byte[] raw_content = null; if (headers.ContainsKey("Content-Length")) { int totalBytes = Convert.ToInt32(headers["Content-Length"]); if (totalBytes >= MAX_ENTITY_BYTES) { throw new Exception("Content-Length " + totalBytes + " 超过配额"); } int bytesLeft = totalBytes; byte[] bytes = new byte[totalBytes]; while (bytesLeft > 0) { byte[] buffer = new byte[bytesLeft > 1024 ? 1024 : bytesLeft]; int nRet = 0; if (cache.Count > 0) { nRet = Math.Min(buffer.Length, cache.Count); Array.Copy(cache.ToArray(), buffer, nRet); cache.RemoveRange(0, nRet); } int n = 0; if (nRet < buffer.Length) { // int n = inputStream.Read(buffer, 0, buffer.Length); n = await inputStream.ReadAsync(buffer, nRet, buffer.Length - nRet, token); } buffer.CopyTo(bytes, totalBytes - bytesLeft); bytesLeft -= nRet + n; } raw_content = bytes; } return(new HttpRequest() { Method = method, Url = url, Version = protocolVersion, Headers = headers, Content = raw_content }); }
// 从 dp2library 获得响应 private static async Task <HttpResponse> GetResponseAsync(Stream inputStream, CancellationToken token) { // Read Response Line string first_line = await ReadLineAsync0(inputStream, token); #if NO // HTTP/1.1 404 Not Found string[] tokens = request.Split(' '); if (tokens.Length != 3) { throw new Exception("1 invalid http response line '" + request + "'"); } #endif List <string> tokens = MessageUtility.SplitFirstLine(first_line); if (tokens == null) { throw new Exception("1 invalid http response line '" + first_line + "'"); } string version = tokens[0].ToUpper(); string status_code = tokens[1]; string reason_phrase = tokens[2]; //Read Headers Dictionary <string, string> headers = new Dictionary <string, string>(); string line; while ((line = await ReadLineAsync0(inputStream, token)) != null) { if (line.Equals("")) { break; } int separator = line.IndexOf(':'); if (separator == -1) { throw new Exception("2 invalid http header line: " + line); } string name = line.Substring(0, separator); int pos = separator + 1; while ((pos < line.Length) && (line[pos] == ' ')) { pos++; } string value = line.Substring(pos, line.Length - pos); headers.Add(name, value); } byte[] raw_content = null; if (headers.ContainsKey("Content-Length")) { int totalBytes = Convert.ToInt32(headers["Content-Length"]); // TODO 观察配额 int bytesLeft = totalBytes; byte[] bytes = new byte[totalBytes]; while (bytesLeft > 0) { byte[] buffer = new byte[bytesLeft > 1024 ? 1024 : bytesLeft]; int n = await inputStream.ReadAsync(buffer, 0, buffer.Length, token); buffer.CopyTo(bytes, totalBytes - bytesLeft); bytesLeft -= n; } raw_content = bytes; } return(new HttpResponse() { StatusCode = status_code, ReasonPhrase = reason_phrase, Headers = headers, Content = raw_content }); }