예제 #1
0
        //
        // 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);
        }