Esempio n. 1
0
        ILastHttpContent ReadTrailingHeaders(IByteBuffer buffer)
        {
            AppendableCharSequence line = this.headerParser.Parse(buffer);

            if (line == null)
            {
                return(null);
            }
            AsciiString lastHeader = null;

            if (line.Count > 0)
            {
                ILastHttpContent trailingHeaders = this.trailer;
                if (trailingHeaders == null)
                {
                    trailingHeaders = new DefaultLastHttpContent(Unpooled.Empty, this.ValidateHeaders);
                    this.trailer    = trailingHeaders;
                }
                do
                {
                    byte firstChar = line.Bytes[0];
                    if (lastHeader != null && (firstChar == ' ' || firstChar == '\t'))
                    {
                        IList <ICharSequence> current = trailingHeaders.TrailingHeaders.GetAll(lastHeader);
                        if (current.Count > 0)
                        {
                            int           lastPos     = current.Count - 1;
                            ICharSequence lineTrimmed = CharUtil.Trim(line);
                            current[lastPos] = new AsciiString($"{current[lastPos]} {lineTrimmed}");
                        }
                    }
                    else
                    {
                        this.SplitHeader(line);
                        AsciiString headerName = this.name;
                        if (!HttpHeaderNames.ContentLength.ContentEqualsIgnoreCase(headerName) &&
                            !HttpHeaderNames.TransferEncoding.ContentEqualsIgnoreCase(headerName) &&
                            !HttpHeaderNames.Trailer.ContentEqualsIgnoreCase(headerName))
                        {
                            trailingHeaders.TrailingHeaders.Add(headerName, this.value);
                        }
                        lastHeader = this.name;
                        // reset name and value fields
                        this.name  = null;
                        this.value = null;
                    }

                    line = this.headerParser.Parse(buffer);
                    if (line == null)
                    {
                        return(null);
                    }
                } while (line.Count > 0);

                this.trailer = null;
                return(trailingHeaders);
            }

            return(EmptyLastHttpContent.Default);
        }
Esempio n. 2
0
        private ILastHttpContent ReadTrailingHeaders(IByteBuffer buffer)
        {
            AppendableCharSequence line = _headerParser.Parse(buffer);

            if (line is null)
            {
                return(null);
            }
            ILastHttpContent trailingHeaders = _trailer;

            if (0u >= (uint)line.Count && trailingHeaders is null)
            {
                // We have received the empty line which signals the trailer is complete and did not parse any trailers
                // before. Just return an empty last content to reduce allocations.
                return(EmptyLastHttpContent.Default);
            }

            AsciiString lastHeader = null;

            if (trailingHeaders is null)
            {
                trailingHeaders = new DefaultLastHttpContent(Unpooled.Empty, ValidateHeaders);
                _trailer        = trailingHeaders;
            }
            while ((uint)line.Count > 0u)
            {
                byte firstChar = line.Bytes[0];
                if (lastHeader is object && (firstChar == c_space || firstChar == c_tab))
                {
                    IList <ICharSequence> current = trailingHeaders.TrailingHeaders.GetAll(lastHeader);
                    if ((uint)current.Count > 0u)
                    {
                        int lastPos = current.Count - 1;
                        //please do not make one line from below code
                        //as it breaks +XX:OptimizeStringConcat optimization
                        ICharSequence lineTrimmed = CharUtil.Trim(line);
                        current[lastPos] = new AsciiString($"{current[lastPos]}{lineTrimmed}");
                    }
                }
                else
                {
                    SplitHeader(line);
                    AsciiString headerName = _name;
                    if (!HttpHeaderNames.ContentLength.ContentEqualsIgnoreCase(headerName) &&
                        !HttpHeaderNames.TransferEncoding.ContentEqualsIgnoreCase(headerName) &&
                        !HttpHeaderNames.Trailer.ContentEqualsIgnoreCase(headerName))
                    {
                        _ = trailingHeaders.TrailingHeaders.Add(headerName, _value);
                    }
                    lastHeader = _name;
                    // reset name and value fields
                    _name  = null;
                    _value = null;
                }

                line = _headerParser.Parse(buffer);
                if (line is null)
                {
                    return(null);
                }
            }

            _trailer = null;
            return(trailingHeaders);
        }
Esempio n. 3
0
        State?ReadHeaders(IByteBuffer buffer)
        {
            IHttpMessage httpMessage = _message;
            HttpHeaders  headers     = httpMessage.Headers;

            AppendableCharSequence line = _headerParser.Parse(buffer);

            if (line is null)
            {
                return(null);
            }
            // ReSharper disable once ConvertIfDoToWhile
            if ((uint)line.Count > 0u)
            {
                do
                {
                    byte firstChar = line.Bytes[0];
                    if (_name is object && (firstChar == c_space || firstChar == c_tab))
                    {
                        //please do not make one line from below code
                        //as it breaks +XX:OptimizeStringConcat optimization
                        ICharSequence trimmedLine = CharUtil.Trim(line);
                        _value = new AsciiString($"{_value} {trimmedLine}");
                    }
                    else
                    {
                        if (_name is object)
                        {
                            _ = headers.Add(_name, _value);
                        }
                        SplitHeader(line);
                    }

                    line = _headerParser.Parse(buffer);
                    if (line is null)
                    {
                        return(null);
                    }
                } while ((uint)line.Count > 0u);
            }

            // Add the last header.
            if (_name is object)
            {
                _ = headers.Add(_name, _value);
            }

            // reset name and value fields
            _name  = null;
            _value = null;

            var  values = headers.GetAll(HttpHeaderNames.ContentLength);
            uint contentLengthValuesCount = (uint)values.Count;

            if (contentLengthValuesCount > 0u)
            {
                // Guard against multiple Content-Length headers as stated in
                // https://tools.ietf.org/html/rfc7230#section-3.3.2:
                //
                // If a message is received that has multiple Content-Length header
                //   fields with field-values consisting of the same decimal value, or a
                //   single Content-Length header field with a field value containing a
                //   list of identical decimal values (e.g., "Content-Length: 42, 42"),
                //   indicating that duplicate Content-Length header fields have been
                //   generated or combined by an upstream message processor, then the
                //   recipient MUST either reject the message as invalid or replace the
                //   duplicated field-values with a single valid Content-Length field
                //   containing that decimal value prior to determining the message body
                //   length or forwarding the message.
                if (contentLengthValuesCount > 1u && httpMessage.ProtocolVersion == HttpVersion.Http11)
                {
                    ThrowHelper.ThrowArgumentException_Multiple_Content_Length_Headers_Found();
                }
                if (!long.TryParse(values[0].ToString(), out _contentLength))
                {
                    ThrowHelper.ThrowArgumentException_Invalid_Content_Length();
                }
            }

            if (IsContentAlwaysEmpty(httpMessage))
            {
                HttpUtil.SetTransferEncodingChunked(httpMessage, false);
                return(State.SkipControlChars);
            }
            else if (HttpUtil.IsTransferEncodingChunked(httpMessage))
            {
                if (contentLengthValuesCount > 0u && httpMessage.ProtocolVersion == HttpVersion.Http11)
                {
                    HandleTransferEncodingChunkedWithContentLength(httpMessage);
                }

                return(State.ReadChunkSize);
            }
            else if (ContentLength() >= 0L)
            {
                return(State.ReadFixedLengthContent);
            }
            else
            {
                return(State.ReadVariableLengthContent);
            }
        }
Esempio n. 4
0
        State?ReadHeaders(IByteBuffer buffer)
        {
            IHttpMessage httpMessage = this.message;
            HttpHeaders  headers     = httpMessage.Headers;

            AppendableCharSequence line = this.headerParser.Parse(buffer);

            if (line == null)
            {
                return(null);
            }
            // ReSharper disable once ConvertIfDoToWhile
            if (line.Count > 0)
            {
                do
                {
                    byte firstChar = line.Bytes[0];
                    if (this.name != null && (firstChar == ' ' || firstChar == '\t'))
                    {
                        ICharSequence trimmedLine = CharUtil.Trim(line);
                        this.value = new AsciiString($"{this.value} {trimmedLine}");
                    }
                    else
                    {
                        if (this.name != null)
                        {
                            headers.Add(this.name, this.value);
                        }
                        this.SplitHeader(line);
                    }

                    line = this.headerParser.Parse(buffer);
                    if (line == null)
                    {
                        return(null);
                    }
                } while (line.Count > 0);
            }

            // Add the last header.
            if (this.name != null)
            {
                headers.Add(this.name, this.value);
            }
            // reset name and value fields
            this.name  = null;
            this.value = null;

            State nextState;

            if (this.IsContentAlwaysEmpty(httpMessage))
            {
                HttpUtil.SetTransferEncodingChunked(httpMessage, false);
                nextState = State.SkipControlChars;
            }
            else if (HttpUtil.IsTransferEncodingChunked(httpMessage))
            {
                nextState = State.ReadChunkSize;
            }
            else if (this.ContentLength() >= 0)
            {
                nextState = State.ReadFixedLengthContent;
            }
            else
            {
                nextState = State.ReadVariableLengthContent;
            }
            return(nextState);
        }
Esempio n. 5
0
        //
        // Check from the request ContentType if this request is a Multipart request.
        // return an array of String if multipartDataBoundary exists with the multipartDataBoundary
        // as first element, charset if any as second (missing if not set), else null
        //
        protected internal static ICharSequence[] GetMultipartDataBoundary(ICharSequence contentType)
        {
            // Check if Post using "multipart/form-data; boundary=--89421926422648 [; charset=xxx]"
            ICharSequence[] headerContentType = SplitHeaderContentType(contentType);
            AsciiString     multiPartHeader   = HttpHeaderValues.MultipartFormData;

            if (headerContentType[0].RegionMatchesIgnoreCase(0, multiPartHeader, 0, multiPartHeader.Count))
            {
                int         mrank;
                int         crank;
                AsciiString boundaryHeader = HttpHeaderValues.Boundary;
                if (headerContentType[1].RegionMatchesIgnoreCase(0, boundaryHeader, 0, boundaryHeader.Count))
                {
                    mrank = 1;
                    crank = 2;
                }
                else if (headerContentType[2].RegionMatchesIgnoreCase(0, boundaryHeader, 0, boundaryHeader.Count))
                {
                    mrank = 2;
                    crank = 1;
                }
                else
                {
                    return(null);
                }
                ICharSequence boundary = headerContentType[mrank].SubstringAfter(HttpConstants.EqualsSignChar);
                if (boundary is null)
                {
                    ThrowHelper.ThrowErrorDataDecoderException_NeedBoundaryValue();
                }
                if (boundary[0] == HttpConstants.DoubleQuoteChar)
                {
                    ICharSequence bound = CharUtil.Trim(boundary);
                    int           index = bound.Count - 1;
                    if (bound[index] == HttpConstants.DoubleQuoteChar)
                    {
                        boundary = bound.SubSequence(1, index);
                    }
                }
                AsciiString charsetHeader = HttpHeaderValues.Charset;
                if (headerContentType[crank].RegionMatchesIgnoreCase(0, charsetHeader, 0, charsetHeader.Count))
                {
                    ICharSequence charset = headerContentType[crank].SubstringAfter(HttpConstants.EqualsSignChar);
                    if (charset is object)
                    {
                        return(new[]
                        {
                            new StringCharSequence("--" + boundary.ToString()),
                            charset
                        });
                    }
                }

                return(new ICharSequence[]
                {
                    new StringCharSequence("--" + boundary.ToString())
                });
            }

            return(null);
        }