// // GenericLoopbackServer implementation // public override async Task <HttpRequestData> ReadRequestDataAsync(bool readBody = true) { HttpRequestData requestData = new HttpRequestData(); List <byte[]> headerLines = await ReadRequestHeaderBytesAsync().ConfigureAwait(false); // Parse method and path string[] splits = Encoding.ASCII.GetString(headerLines[0]).Split(' '); requestData.Method = splits[0]; requestData.Path = splits[1]; requestData.Version = Version.Parse(splits[2].Substring(splits[2].IndexOf('/') + 1)); // Convert header lines to key/value pairs // Skip first line since it's the status line foreach (byte[] lineBytes in headerLines.Skip(1)) { string line = Encoding.ASCII.GetString(lineBytes); int offset = line.IndexOf(':'); string name = line.Substring(0, offset); string value = line.Substring(offset + 1).TrimStart(); requestData.Headers.Add(new HttpHeaderData(name, value, raw: lineBytes)); } if (requestData.Method != "GET") { if (requestData.GetHeaderValueCount("Content-Length") != 0) { _contentLength = int.Parse(requestData.GetSingleHeaderValue("Content-Length")); } else if (requestData.GetHeaderValueCount("Transfer-Encoding") != 0 && requestData.GetSingleHeaderValue("Transfer-Encoding") == "chunked") { _contentLength = -1; } } if (readBody) { requestData.Body = await ReadRequestBodyAsync().ConfigureAwait(false); _bodyRead = true; } return(requestData); }
// // GenericLoopbackServer implementation // public override async Task <HttpRequestData> ReadRequestDataAsync(bool readBody = true) { List <string> headerLines = null; HttpRequestData requestData = new HttpRequestData(); headerLines = await ReadRequestHeaderAsync().ConfigureAwait(false); // Parse method and path string[] splits = headerLines[0].Split(' '); requestData.Method = splits[0]; requestData.Path = splits[1]; // Convert header lines to key/value pairs // Skip first line since it's the status line foreach (var line in headerLines.Skip(1)) { int offset = line.IndexOf(':'); string name = line.Substring(0, offset); string value = line.Substring(offset + 1).TrimStart(); requestData.Headers.Add(new HttpHeaderData(name, value)); } if (requestData.Method != "GET") { if (requestData.GetHeaderValueCount("Content-Length") != 0) { _contentLength = Int32.Parse(requestData.GetSingleHeaderValue("Content-Length")); } else if (requestData.GetHeaderValueCount("Transfer-Encoding") != 0 && requestData.GetSingleHeaderValue("Transfer-Encoding") == "chunked") { _contentLength = -1; } } if (readBody) { requestData.Body = await ReadRequestBodyAsync().ConfigureAwait(false); _bodyRead = true; } return(requestData); }
// // GenericLoopbackServer implementation // public override async Task <HttpRequestData> HandleRequestAsync(HttpStatusCode statusCode = HttpStatusCode.OK, IList <HttpHeaderData> headers = null, string content = null) { string headerString = null; if (headers != null) { foreach (HttpHeaderData headerData in headers) { headerString = headerString + $"{headerData.Name}: {headerData.Value}\r\n"; } } List <string> headerLines = null; HttpRequestData requestData = new HttpRequestData(); await AcceptConnectionAsync(async connection => { headerLines = await connection.ReadRequestHeaderAsync().ConfigureAwait(false); // Parse method and path string[] splits = headerLines[0].Split(' '); requestData.Method = splits[0]; requestData.Path = splits[1]; // Convert header lines to key/value pairs // Skip first line since it's the status line foreach (var line in headerLines.Skip(1)) { int offset = line.IndexOf(':'); string name = line.Substring(0, offset); string value = line.Substring(offset + 1).TrimStart(); requestData.Headers.Add(new HttpHeaderData(name, value)); } if (requestData.Method != "GET") { if (requestData.GetHeaderValueCount("Content-Length") != 0) { int contentLength = Int32.Parse(requestData.GetSingleHeaderValue("Content-Length")); if (contentLength > 0) { byte[] buffer = new byte[contentLength]; int bytesRead = await connection.ReadBlockAsync(buffer, 0, contentLength).ConfigureAwait(false); Assert.Equal(contentLength, bytesRead); requestData.Body = buffer; } } else if (requestData.GetHeaderValueCount("Transfer-Encoding") != 0 && requestData.GetSingleHeaderValue("Transfer-Encoding") == "chunked") { while (true) { string chunkHeader = await connection.ReadLineAsync().ConfigureAwait(false); int chunkLength = int.Parse(chunkHeader, System.Globalization.NumberStyles.HexNumber); if (chunkLength == 0) { // Last chunk. Read CRLF and exit. await connection.ReadLineAsync().ConfigureAwait(false); break; } byte[] buffer = new byte[chunkLength]; await connection.ReadBlockAsync(buffer, 0, chunkLength).ConfigureAwait(false); await connection.ReadLineAsync().ConfigureAwait(false); if (requestData.Body == null) { requestData.Body = buffer; } else { byte[] newBuffer = new byte[requestData.Body.Length + chunkLength]; requestData.Body.CopyTo(newBuffer, 0); buffer.CopyTo(newBuffer, requestData.Body.Length); requestData.Body = newBuffer; } } } } await connection.SendResponseAsync(statusCode, headerString + "Connection: close\r\n", content).ConfigureAwait(false); }); return(requestData); }