public async Task TestReadLines_ShouldReturnResponse() { string expected = "GET /modules/testModule/sign?api-version=2018-06-28 HTTP/1.1\r\nHost: localhost:8081\r\nConnection: close\r\nContent-Type: application/json\r\nContent-Length: 100\r\n\r\n"; byte[] expectedBytes = Encoding.UTF8.GetBytes(expected); var memory = new MemoryStream(expectedBytes, true); IList <string> lines = new List <string>(); var buffered = new HttpBufferedStream(memory); System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken); string line = await buffered.ReadLineAsync(cancellationToken); while (!string.IsNullOrEmpty(line)) { lines.Add(line); line = await buffered.ReadLineAsync(cancellationToken); } Assert.AreEqual(5, lines.Count); Assert.AreEqual("GET /modules/testModule/sign?api-version=2018-06-28 HTTP/1.1", lines[0]); Assert.AreEqual("Host: localhost:8081", lines[1]); Assert.AreEqual("Connection: close", lines[2]); Assert.AreEqual("Content-Type: application/json", lines[3]); Assert.AreEqual("Content-Length: 100", lines[4]); }
async Task SetResponseStatusLine(HttpResponseMessage httpResponse, HttpBufferedStream bufferedStream, CancellationToken cancellationToken) { string statusLine = await bufferedStream.ReadLineAsync(cancellationToken).ConfigureAwait(false); if (string.IsNullOrWhiteSpace(statusLine)) { throw new HttpRequestException("Response is empty."); } string[] statusLineParts = statusLine.Split(new[] { SP }, 3); if (statusLineParts.Length < 3) { throw new HttpRequestException("Status line is not valid."); } string[] httpVersion = statusLineParts[0].Split(new[] { ProtocolVersionSeparator }, 2); if (httpVersion.Length < 2 || !Version.TryParse(httpVersion[1], out Version versionNumber)) { throw new HttpRequestException($"Version is not valid {statusLineParts[0]}."); } httpResponse.Version = versionNumber; if (!Enum.TryParse(statusLineParts[1], out HttpStatusCode statusCode)) { throw new HttpRequestException($"StatusCode is not valid {statusLineParts[1]}."); } httpResponse.StatusCode = statusCode; httpResponse.ReasonPhrase = statusLineParts[2]; }
async Task SetHeadersAndContent(HttpResponseMessage httpResponse, HttpBufferedStream bufferedStream, CancellationToken cancellationToken) { IList <string> headers = new List <string>(); string line = await bufferedStream.ReadLineAsync(cancellationToken).ConfigureAwait(false); while (!string.IsNullOrWhiteSpace(line)) { headers.Add(line); line = await bufferedStream.ReadLineAsync(cancellationToken).ConfigureAwait(false); } httpResponse.Content = new StreamContent(bufferedStream); foreach (string header in headers) { if (string.IsNullOrWhiteSpace(header)) { // headers end break; } int headerSeparatorPosition = header.IndexOf(HeaderSeparator); if (headerSeparatorPosition <= 0) { throw new HttpRequestException($"Header is invalid {header}."); } string headerName = header.Substring(0, headerSeparatorPosition).Trim(); string headerValue = header.Substring(headerSeparatorPosition + 1).Trim(); bool headerAdded = httpResponse.Headers.TryAddWithoutValidation(headerName, headerValue); if (!headerAdded) { if (string.Equals(headerName, ContentLengthHeaderName, StringComparison.InvariantCultureIgnoreCase)) { if (!long.TryParse(headerValue, out long contentLength)) { throw new HttpRequestException($"Header value is invalid for {headerName}."); } await httpResponse.Content.LoadIntoBufferAsync(contentLength).ConfigureAwait(false); } httpResponse.Content.Headers.TryAddWithoutValidation(headerName, headerValue); } } }