Esempio n. 1
0
        public HttpResponse Filter(ref SequenceReader <byte> reader)
        {
            if (_currentResponse == null)
            {
                if (!reader.TryReadTo(out ReadOnlySequence <byte> pack, _CRLF.Span, advancePastDelimiter: false))
                {
                    return(null);
                }
                total = total.ConcactSequence(pack);
                total = total.ConcactSequence(new ReadOnlySequence <byte>(_CRLF));

                reader.Advance(_CRLF.Length);
                var statusLine = pack.GetString(Encoding.UTF8);
                if (string.IsNullOrEmpty(statusLine))
                {
                    return(null);
                }
                var metaInfos = statusLine.Split(' ', 3, StringSplitOptions.RemoveEmptyEntries);
                if (metaInfos.Length != 3)
                {
                    return(null);
                }
                if (!reader.TryReadTo(out pack, _headerTerminator.Span, advancePastDelimiter: false))
                {
                    return(null);
                }
                total = total.ConcactSequence(pack);
                total = total.ConcactSequence(new ReadOnlySequence <byte>(_headerTerminator));
                reader.Advance(_headerTerminator.Length);
                var header = new HttpHeader(pack);
                if (!int.TryParse(metaInfos[1], out var statusCode))
                {
                    return(null);
                }
                var response = new HttpResponse(metaInfos[0], statusCode, metaInfos[2], header);

                var transferEncoding = response.Header["transfer-encoding"];
                if (transferEncoding == "chunked")
                {
                    _currentResponse = response;
                    chunked          = true;
                    return(Filter(ref reader));
                }

                var contentLength = response.Header?["content-length"];

                if (string.IsNullOrEmpty(contentLength)) // no content
                {
                    return(response);
                }

                var bodyLength = long.Parse(contentLength);

                if (bodyLength == 0)
                {
                    return(response);
                }

                _bodyLength      = bodyLength;
                _currentResponse = response;

                return(Filter(ref reader));
            }

            if (chunked)
            {
                if (chunkedCurrentLength == 0)
                {
                    if (!reader.TryReadTo(out ReadOnlySequence <byte> pack, _CRLF.Span, advancePastDelimiter: false))
                    {
                        return(null);
                    }
                    reader.Advance(_CRLF.Length);
                    chunkedCurrentLength = Convert.ToInt32($"0x{pack.GetString(Encoding.UTF8)}", 16);
                    body = body.ConcactSequence(pack);
                    body = body.ConcactSequence(new ReadOnlySequence <byte>(_CRLF));
                    if (chunkedCurrentLength == 0)
                    {
                        body  = body.ConcactSequence(new ReadOnlySequence <byte>(_CRLF));
                        total = total.ConcactSequence(body, false);
                        _currentResponse.Data = total;
                        return(_currentResponse);
                    }
                }
                if (reader.Remaining < chunkedCurrentLength)
                {
                    return(null);
                }

                var chunkedPack = reader.Sequence.Slice(reader.Consumed, this.chunkedCurrentLength);
                body = body.ConcactSequence(chunkedPack);
                body = body.ConcactSequence(new ReadOnlySequence <byte>(_CRLF));
                reader.Advance(chunkedCurrentLength);
                reader.Advance(_CRLF.Length);
                chunkedCurrentLength = 0;
                return(Filter(ref reader));
            }


            body = body.ConcactSequence(reader.Sequence.Slice(reader.Consumed, reader.Remaining));

            reader.Advance(reader.Remaining);

            if (body.Length < _bodyLength)
            {
                return(null);
            }


            total = total.ConcactSequence(body, false);
            _currentResponse.Data = total;
            return(_currentResponse);
        }
        public HttpRequest Filter(ref SequenceReader <byte> reader)
        {
            if (_bodyLength == 0)
            {
                var terminatorSpan = _headerTerminator.Span;

                if (!reader.TryReadTo(out ReadOnlySequence <byte> pack, _CRLF, advancePastDelimiter: false))
                {
                    return(null);
                }

                reader.Advance(_CRLF.Length);
                var requestLine = pack.GetString(Encoding.UTF8);
                if (string.IsNullOrEmpty(requestLine))
                {
                    return(null);
                }
                var metaInfos = requestLine.Split(' ', 3, StringSplitOptions.RemoveEmptyEntries);
                if (metaInfos.Length != 3)
                {
                    return(null);
                }
                if (!reader.TryReadTo(out pack, terminatorSpan, advancePastDelimiter: false))
                {
                    return(null);
                }
                reader.Advance(terminatorSpan.Length);
                var header = new HttpHeader(pack);

                var request = new HttpRequest(metaInfos[0], metaInfos[1], metaInfos[2], header);

                var contentLength = request.Header["content-length"];

                if (string.IsNullOrEmpty(contentLength)) // no content
                {
                    return(request);
                }

                var bodyLength = long.Parse(contentLength);

                if (bodyLength == 0)
                {
                    return(request);
                }

                _bodyLength     = bodyLength;
                _currentRequest = request;

                return(Filter(ref reader));
            }

            if (reader.Remaining < _bodyLength)
            {
                return(null);
            }

            var seq = reader.Sequence;

            _currentRequest.Body = seq.Slice(reader.Consumed, _bodyLength).GetString(Encoding.UTF8);
            reader.Advance(_bodyLength);

            return(_currentRequest);
        }