Example #1
0
        public void ParseRequestStream_AllHeaderTypes_AllHeadersParsed()
        {
            var streamedRequest = new[] {
                "GET /api/data HTTP/1.1",
                "Content-Length: 4",
                "Accept: application/json,text/xml",
                "Accept-Charset: utf-7;q=0.2, utf-8;q=0.1,*;q=0",
                "Content-Type: text/xml;charset=utf-8",
                "UnknownHeader: some:value",
                "",
                "data"
            };

            var byteStreamParts = new List <byte[]>();

            byteStreamParts.Add(Encoding.UTF8.GetBytes(string.Join("\r\n", streamedRequest)));

            var request = MutableHttpServerRequest.Parse(new TestStream(byteStreamParts)).Result;

            Assert.AreEqual(true, request.IsComplete);
            Assert.IsTrue(request.Headers.Any(h => h.Name == "UnknownHeader" && h.Value == "some:value"));
            Assert.AreEqual(4, request.ContentLength);
            Assert.AreEqual("utf-8", request.ContentTypeCharset);
            Assert.AreEqual("text/xml", request.ContentType);
            Assert.AreEqual("utf-7", request.AcceptCharsets.First());
            Assert.AreEqual("application/json", request.AcceptMediaTypes.First());
            Assert.AreEqual("text/xml", request.AcceptMediaTypes.Skip(1).First());
        }
Example #2
0
        private async void ProcessRequestAsync(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
        {
            await Task.Run(async() =>
            {
                try
                {
                    using (var inputStream = args.Socket.InputStream)
                        using (var outputStream = args.Socket.OutputStream)
                        {
                            var request           = await MutableHttpServerRequest.Parse(inputStream);
                            var result            = await HandleRequestExAsync(request);
                            var httpResponse      = result.Item1;
                            var routeRegistration = result.Item2;
                            await WriteResponseAsync(httpResponse, outputStream);

                            if (routeRegistration != null)
                            {
                                await routeRegistration.Stream(args.Socket);
                            }
                        }
                }
                catch (Exception ex)
                {
                    _log.Error($"Exception while handling process: {ex.Message}");
                }
                finally
                {
                    try
                    {
                        args.Socket.Dispose();
                    }
                    catch { }
                }
            });
        }
Example #3
0
        private async void ProcessRequestAsync(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
        {
            await Task.Run(async() =>
            {
                try
                {
                    using (var inputStream = args.Socket.InputStream)
                    {
                        var request = await MutableHttpServerRequest.Parse(inputStream);

                        var httpResponse = await HandleRequestAsync(request);

                        await WriteResponseAsync(httpResponse, args.Socket);
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"Exception while handling process: {ex.Message}");
                }
                finally
                {
                    try
                    {
                        args.Socket.Dispose();
                    }
                    catch { }
                }
            });
        }
Example #4
0
        public void ParseRequestStream_AcceptEncodingWithQuality_DefaultQuality1AsAccept()
        {
            var streamedRequest = "GET /api/data HTTP/1.1\r\nAccept-Encoding: gzip,deflate;q=0.7\r\n\r\n";

            var byteStreamParts = Encoding.UTF8.GetBytes(streamedRequest);

            var request = MutableHttpServerRequest.Parse(new TestStream(new[] { byteStreamParts })).Result;

            Assert.AreEqual(true, request.IsComplete);
            Assert.AreEqual("gzip", request.AcceptEncodings.First());
        }
Example #5
0
        public void ParseRequestStream_AcceptWithQuality_DefaultQuality1AsAccept()
        {
            var streamedRequest = "GET /api/data HTTP/1.1\r\nAccept: application/json,text/xml;q=0.7\r\n\r\n";

            var byteStreamParts = Encoding.UTF8.GetBytes(streamedRequest);

            var request = MutableHttpServerRequest.Parse(new TestStream(new[] { byteStreamParts })).Result;

            Assert.AreEqual(true, request.IsComplete);
            Assert.AreEqual("application/json", request.AcceptMediaTypes.First());
        }
Example #6
0
        public void ParseRequestStream_AcceptCharsetWithQuality_QualityHighestAsAccept()
        {
            var streamedRequest = "GET /api/data HTTP/1.1\r\nAccept-Charset: iso-8859-1;q=0.5,utf-8;q=0.7\r\n\r\n";

            var byteStreamParts = Encoding.UTF8.GetBytes(streamedRequest);

            var request = MutableHttpServerRequest.Parse(new TestStream(new[] { byteStreamParts })).Result;

            Assert.AreEqual(true, request.IsComplete);
            Assert.AreEqual("utf-8", request.AcceptCharsets.First());
        }
Example #7
0
        internal async Task <MutableHttpServerRequest> ParseRequestStream(IInputStream requestStream)
        {
            var httpStream = new HttpRequestStream(requestStream);
            var request    = new MutableHttpServerRequest();

            try
            {
                var stream = await httpStream.ReadAsync(BUFFER_SIZE, InputStreamOptions.Partial);

                byte[] streamData = stream.Data;

                var requestPipeline = GetPipeline();
                using (var pipeLineEnumerator = requestPipeline.GetEnumerator())
                {
                    pipeLineEnumerator.MoveNext();
                    bool requestComplete = false;

                    while (!requestComplete)
                    {
                        pipeLineEnumerator.Current.HandleRequestPart(streamData, request);
                        streamData = pipeLineEnumerator.Current.UnparsedData;

                        if (pipeLineEnumerator.Current.IsFinished)
                        {
                            if (!pipeLineEnumerator.Current.IsSucceeded ||
                                !pipeLineEnumerator.MoveNext())
                            {
                                break;
                            }
                        }
                        else
                        {
                            var newStreamdata = await httpStream.ReadAsync(BUFFER_SIZE, InputStreamOptions.Partial);

                            if (!newStreamdata.ReadSuccessful)
                            {
                                break;
                            }

                            streamData = streamData.ConcatArray(newStreamdata.Data);
                        }
                    }
                }

                request.IsComplete = requestPipeline.All(p => p.IsSucceeded);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }

            return(request);
        }
        public override void HandleRequestPart(byte[] stream, MutableHttpServerRequest resultThisFar)
        {
            var word = stream.ReadNextWord();

            if (word.WordFound)
            {
                resultThisFar.Uri = new Uri(word.Word, UriKind.RelativeOrAbsolute);
                UnparsedData = word.RemainingBytes;
                IsFinished = true;
                IsSucceeded = true;
            }
        }
        public override void HandleRequestPart(byte[] stream, MutableHttpServerRequest resultThisFar)
        {
            var word = stream.ReadNextWord();

            if (word.WordFound)
            {
                resultThisFar.Uri = new Uri(word.Word, UriKind.RelativeOrAbsolute);
                UnparsedData      = word.RemainingBytes;
                IsFinished        = true;
                IsSucceeded       = true;
            }
        }
Example #10
0
        public override void HandleRequestPart(byte[] stream, MutableHttpServerRequest resultThisFar)
        {
            var word = stream.ReadNextWord();

            if (word.WordFound)
            {
                resultThisFar.HttpVersion = word.Word;
                UnparsedData = word.RemainingBytes;
                IsFinished   = true;
                IsSucceeded  = true;
            }
        }
        public override void HandleRequestPart(byte[] stream, MutableHttpServerRequest resultThisFar)
        {
            var word = stream.ReadNextWord();

            if (word.WordFound)
            {
                resultThisFar.HttpVersion = word.Word;
                UnparsedData = word.RemainingBytes;
                IsFinished = true;
                IsSucceeded = true;
            }
        }
Example #12
0
        internal async Task<MutableHttpServerRequest> ParseRequestStream(IInputStream requestStream)
        {
            var httpStream = new HttpRequestStream(requestStream);
            var request = new MutableHttpServerRequest();

            try
            {
                var stream = await httpStream.ReadAsync(BUFFER_SIZE, InputStreamOptions.Partial);
                byte[] streamData = stream.Data;

                var requestPipeline = GetPipeline();
                using (var pipeLineEnumerator = requestPipeline.GetEnumerator())
                {
                    pipeLineEnumerator.MoveNext();
                    bool requestComplete = false;

                    while (!requestComplete)
                    {
                        pipeLineEnumerator.Current.HandleRequestPart(streamData, request);
                        streamData = pipeLineEnumerator.Current.UnparsedData;

                        if (pipeLineEnumerator.Current.IsFinished)
                        {
                            if (!pipeLineEnumerator.Current.IsSucceeded ||
                                !pipeLineEnumerator.MoveNext())
                            {
                                break;
                            }
                        }
                        else
                        {
                            var newStreamdata = await httpStream.ReadAsync(BUFFER_SIZE, InputStreamOptions.Partial);

                            if (!newStreamdata.ReadSuccessful)
                            {
                                break;
                            }

                            streamData = streamData.ConcatArray(newStreamdata.Data);
                        }
                    }
                }

                request.IsComplete = requestPipeline.All(p => p.IsSucceeded);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }

            return request;
        }
Example #13
0
        public void ParseRequestStream_AllAcceptEncodingsAreReturned()
        {
            var streamedRequest = "GET /api/data HTTP/1.1\r\nAccept-Encoding: gzip,deflate;q=0.7\r\n\r\n";

            var byteStreamParts = Encoding.UTF8.GetBytes(streamedRequest);

            var request = MutableHttpServerRequest.Parse(new TestStream(new[] { byteStreamParts })).Result;

            Assert.AreEqual(true, request.IsComplete);
            Assert.AreEqual(2, request.AcceptEncodings.Count());
            Assert.AreEqual("gzip", request.AcceptEncodings.ElementAt(0));
            Assert.AreEqual("deflate", request.AcceptEncodings.ElementAt(1));
        }
Example #14
0
        public void ParseRequestStream_WithoutDataAndHeaders_CompleteRequest()
        {
            var streamedRequest = new[] {
                "GET /api/data HTTP/1.1\r\n", //to force double /r/n on string.Join
                ""
            };

            var byteStreamParts = new List <byte[]>();

            byteStreamParts.Add(Encoding.UTF8.GetBytes(string.Join("\r\n", streamedRequest)));

            var request = MutableHttpServerRequest.Parse(new TestStream(byteStreamParts)).Result;

            Assert.AreEqual(true, request.IsComplete);
        }
Example #15
0
        public void ParseRequestStream_AllDataAtOnce_CompleteRequest()
        {
            var streamedRequest = "GET /api/data HTTP/1.1\r\nContent-Length: 4\r\n\r\ndata";
            var byteStreamParts = new List <byte[]>();

            byteStreamParts.Add(Encoding.UTF8.GetBytes(streamedRequest));

            var request = MutableHttpServerRequest.Parse(new TestStream(byteStreamParts)).Result;

            Assert.AreEqual(HttpMethod.GET, request.Method);
            Assert.AreEqual(new Uri("/api/data", UriKind.Relative), request.Uri);
            CollectionAssert.AreEqual(Encoding.UTF8.GetBytes("data"), request.Content);
            Assert.AreEqual(4, request.ContentLength);
            Assert.AreEqual("HTTP/1.1", request.HttpVersion);
            Assert.AreEqual(true, request.IsComplete);
        }
Example #16
0
        public void ParseRequestStream_FragmentedData_ValidRequest()
        {
            var byteStreamParts = new List <byte[]>();

            byteStreamParts.Add(Encoding.UTF8.GetBytes("GET /api/data HTTP/1.1\r\n"));
            byteStreamParts.Add(Encoding.UTF8.GetBytes("Content-Leng"));
            byteStreamParts.Add(Encoding.UTF8.GetBytes("th: 4\r\n"));
            byteStreamParts.Add(Encoding.UTF8.GetBytes("\r\nd"));
            byteStreamParts.Add(Encoding.UTF8.GetBytes("a"));
            byteStreamParts.Add(Encoding.UTF8.GetBytes("t"));
            byteStreamParts.Add(Encoding.UTF8.GetBytes("a"));

            var request = MutableHttpServerRequest.Parse(new TestStream(byteStreamParts)).Result;

            Assert.AreEqual(true, request.IsComplete);
            CollectionAssert.AreEqual(Encoding.UTF8.GetBytes("data"), request.Content);
        }
Example #17
0
        public void ParseRequestStream_DataLengthInSecondPart_ValidRequest()
        {
            var httpHeadersPart1 = "GET /api/data HTTP/1.1\r\n";
            var httpHeadersPart2 = "Content-Length: 4\r\n\r\n";
            var content          = Encoding.UTF8.GetBytes("data");
            var byteStreamParts  = new List <byte[]>();

            byteStreamParts.Add(Encoding.UTF8.GetBytes(httpHeadersPart1));
            byteStreamParts.Add(Encoding.UTF8.GetBytes(httpHeadersPart2));
            byteStreamParts.Add(new byte[] { });
            byteStreamParts.Add(content);

            var request = MutableHttpServerRequest.Parse(new TestStream(byteStreamParts)).Result;

            Assert.AreEqual(true, request.IsComplete);
            CollectionAssert.AreEqual(content, request.Content);
        }
Example #18
0
        public void ParseRequestStream_ContentLengthNumberMissing_RequestIncomplete()
        {
            var streamedRequest = new[] {
                "GET /api/data HTTP/1.1",
                "Content-Length: four",
                "",
                "data"
            };

            var byteStreamParts = new List <byte[]>();

            byteStreamParts.Add(Encoding.UTF8.GetBytes(string.Join("\r\n", streamedRequest)));

            var request = MutableHttpServerRequest.Parse(new TestStream(byteStreamParts)).Result;

            Assert.AreEqual(false, request.IsComplete);
        }
Example #19
0
        public void ParseRequestStream_TooMuchData_RequestIncomplete()
        {
            var streamedRequest = new[] {
                "GET /api/data HTTP/1.1",
                "Content-Length: 4",
                "",
                "data"
            };

            var extraData       = "plusanotherextrafewbytes";
            var byteStreamParts = new List <byte[]>();

            byteStreamParts.Add(Encoding.UTF8.GetBytes(string.Join("\r\n", streamedRequest) + extraData));

            var request = MutableHttpServerRequest.Parse(new TestStream(byteStreamParts)).Result;

            Assert.AreEqual(false, request.IsComplete);
        }
Example #20
0
 public override void HandleRequestPart(byte[] stream, MutableHttpServerRequest resultThisFar)
 {
     if (resultThisFar.ContentLength == 0)
     {
         IsFinished  = true;
         IsSucceeded = stream.Length == 0;
     }
     else
     {
         _content.AddRange(stream);
         if (_content.Count == resultThisFar.ContentLength)
         {
             resultThisFar.Content = _content.ToArray();
             IsFinished            = true;
             IsSucceeded           = true;
         }
         // else if content is bigger, finished will never be set, badrequest will happen
     }
 }
Example #21
0
        public void ParseRequestStream_PartedData_ValidRequest()
        {
            var streamedRequest = new[] {
                "GET /api/data HTTP/1.1",
                "Content-Length: 4\r\n", //to force double /r/n on string.Join
                ""
            };

            var content         = Encoding.UTF8.GetBytes("data");
            var byteStreamParts = new List <byte[]>();

            byteStreamParts.Add(Encoding.UTF8.GetBytes(string.Join("\r\n", streamedRequest)));
            byteStreamParts.Add(content);

            var request = MutableHttpServerRequest.Parse(new TestStream(byteStreamParts)).Result;

            Assert.AreEqual(true, request.IsComplete);
            CollectionAssert.AreEqual(content, request.Content);
        }
Example #22
0
 public override void HandleRequestPart(byte[] stream, MutableHttpServerRequest resultThisFar)
 {
     if (resultThisFar.ContentLength == 0)
     {
         IsFinished = true;
         IsSucceeded = stream.Length == 0;
     }
     else
     {
         _content.AddRange(stream);
         if (_content.Count == resultThisFar.ContentLength)
         {
             resultThisFar.Content = _content.ToArray();
             IsFinished = true;
             IsSucceeded = true;
         }
         // else if content is bigger, finished will never be set, badrequest will happen
     }
 }
Example #23
0
        public void ParseRequestStream_ThreeEmptyResponses_EmptyRequestString()
        {
            var streamedRequest = new[] {
                "GET /api/data HTTP/1.1",
                "Content-Length: 4\r\n", //to force double /r/n on string.Join
                ""
            };

            var content         = "data";
            var byteStreamParts = new List <byte[]>();

            byteStreamParts.Add(Encoding.UTF8.GetBytes(string.Join("\r\n", streamedRequest)));
            byteStreamParts.Add(new byte[] { });
            byteStreamParts.Add(new byte[] { });
            byteStreamParts.Add(new byte[] { });
            byteStreamParts.Add(new byte[] { });
            byteStreamParts.Add(Encoding.UTF8.GetBytes(content));

            var request = MutableHttpServerRequest.Parse(new TestStream(byteStreamParts)).Result;

            Assert.AreEqual(false, request.IsComplete);
        }
 public abstract void HandleRequestPart(byte[] stream, MutableHttpServerRequest resultThisFar);
Example #25
0
        /// <summary>
        /// A regex would be nice :)
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="resultThisFar"></param>
        public override void HandleRequestPart(byte[] stream, MutableHttpServerRequest resultThisFar)
        {
            UnparsedData = stream;

            string headerName = null;
            var bytesLeft = stream.Length;
            int headerValueStartIndex = 0;
            int headerValueEndIndex = 0;
            for (var i = 0; i < stream.Length; i++, bytesLeft--)
            {
                byte currentByte = stream[i];
                if (headerName == null && currentByte == Constants.ColonByte)
                {
                    headerName = GetHeaderString(stream, headerValueEndIndex, i);
                    headerValueStartIndex = i + 1;
                }
                else if (stream[i] == Constants.CRByte)
                {
                    // Special case when /r/n is received or /r/ncontentdata
                    if (i == 0 && bytesLeft >= 2 && stream[1] == Constants.LFByte)
                    {
                        IsFinished = true;
                        IsSucceeded = true;
                        headerValueEndIndex = 2;
                        break;
                    }

                    if (headerName != null &&
                        bytesLeft >= 2 &&
                        stream[i + 1] == Constants.LFByte)
                    {
                        // Handle end of one header scenario
                        var headerValue = GetHeaderString(stream, headerValueStartIndex, i);
                        headerValue = headerValue.TrimWhitespaces();
                        try
                        {
                            resultThisFar.AddHeader(_headerFactory.Create(headerName, headerValue));
                        }
                        catch (Exception)
                        {
                            IsFinished = true;
                            IsSucceeded = false;
                            break;
                        }
                        finally
                        {
                            headerName = null;
                            headerValueStartIndex = 0;
                            headerValueEndIndex = i + 2;
                        }
                    }

                    if (bytesLeft >= 4 &&
                        stream[i + 1] == Constants.LFByte &&
                        stream[i + 2] == Constants.CRByte &&
                        stream[i + 3] == Constants.LFByte)
                    {
                        // Handle end of headers scenario
                        headerValueEndIndex = i + 4;
                        IsFinished = true;
                        IsSucceeded = true;
                        break;
                    }
                }
            }

            UnparsedData = stream.Skip(headerValueEndIndex).ToArray();
        }
Example #26
0
        /// <summary>
        /// A regex would be nice :)
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="resultThisFar"></param>
        public override void HandleRequestPart(byte[] stream, MutableHttpServerRequest resultThisFar)
        {
            UnparsedData = stream;

            string headerName            = null;
            var    bytesLeft             = stream.Length;
            int    headerValueStartIndex = 0;
            int    headerValueEndIndex   = 0;

            for (var i = 0; i < stream.Length; i++, bytesLeft--)
            {
                byte currentByte = stream[i];
                if (headerName == null && currentByte == Constants.ColonByte)
                {
                    headerName            = GetHeaderString(stream, headerValueEndIndex, i);
                    headerValueStartIndex = i + 1;
                }
                else if (stream[i] == Constants.CRByte)
                {
                    // Special case when /r/n is received or /r/ncontentdata
                    if (i == 0 && bytesLeft >= 2 && stream[1] == Constants.LFByte)
                    {
                        IsFinished          = true;
                        IsSucceeded         = true;
                        headerValueEndIndex = 2;
                        break;
                    }

                    if (headerName != null &&
                        bytesLeft >= 2 &&
                        stream[i + 1] == Constants.LFByte)
                    {
                        // Handle end of one header scenario
                        var headerValue = GetHeaderString(stream, headerValueStartIndex, i);
                        headerValue = headerValue.TrimWhitespaces();
                        try
                        {
                            resultThisFar.AddHeader(_headerFactory.Create(headerName, headerValue));
                        }
                        catch (Exception)
                        {
                            IsFinished  = true;
                            IsSucceeded = false;
                            break;
                        }
                        finally
                        {
                            headerName            = null;
                            headerValueStartIndex = 0;
                            headerValueEndIndex   = i + 2;
                        }
                    }

                    if (bytesLeft >= 4 &&
                        stream[i + 1] == Constants.LFByte &&
                        stream[i + 2] == Constants.CRByte &&
                        stream[i + 3] == Constants.LFByte)
                    {
                        // Handle end of headers scenario
                        headerValueEndIndex = i + 4;
                        IsFinished          = true;
                        IsSucceeded         = true;
                        break;
                    }
                }
            }

            UnparsedData = stream.Skip(headerValueEndIndex).ToArray();
        }
Example #27
0
 public abstract void HandleRequestPart(byte[] stream, MutableHttpServerRequest resultThisFar);