Beispiel #1
0
        public static void ToHttp2Headers(HttpHeaders inHeaders, IHttp2Headers output)
        {
            // Choose 8 as a default size because it is unlikely we will see more than 4 Connection headers values, but
            // still allowing for "enough" space in the map to reduce the chance of hash code collision.
            var connectionBlacklist = ToLowercaseMap(inHeaders.GetAll(HttpHeaderNames.Connection), 8);

            foreach (var entry in inHeaders)
            {
                AsciiString aName = entry.Key.ToLowerCase();
                if (!HttpToHttp2HeaderBlacklist.Contains(aName) && !connectionBlacklist.Contains(aName))
                {
                    // https://tools.ietf.org/html/rfc7540#section-8.1.2.2 makes a special exception for TE
                    if (aName.ContentEqualsIgnoreCase(HttpHeaderNames.Te))
                    {
                        ToHttp2HeadersFilterTE(entry, output);
                    }
                    else if (aName.ContentEqualsIgnoreCase(HttpHeaderNames.Cookie))
                    {
                        AsciiString value       = AsciiString.Of(entry.Value);
                        uint        uValueCount = (uint)value.Count;
                        // split up cookies to allow for better compression
                        // https://tools.ietf.org/html/rfc7540#section-8.1.2.5
                        try
                        {
                            int index = value.ForEachByte(ByteProcessor.FindSemicolon);
                            if (uValueCount > (uint)index) // != -1
                            {
                                int start = 0;
                                do
                                {
                                    _ = output.Add(HttpHeaderNames.Cookie, value.SubSequence(start, index, false));
                                    // skip 2 characters "; " (see https://tools.ietf.org/html/rfc6265#section-4.2.1)
                                    start = index + 2;
                                } while ((uint)start < uValueCount &&
                                         uValueCount > (uint)(index = value.ForEachByte(start, value.Count - start, ByteProcessor.FindSemicolon))); // != -1
                                if ((uint)start >= uValueCount)
                                {
                                    ThrowHelper.ThrowArgumentException_CookieValueIsOfUnexpectedFormat(value);
                                }
                                _ = output.Add(HttpHeaderNames.Cookie, value.SubSequence(start, value.Count, false));
                            }
                            else
                            {
                                _ = output.Add(HttpHeaderNames.Cookie, value);
                            }
                        }
                        catch (Exception)
                        {
                            // This is not expect to happen because FIND_SEMI_COLON never throws but must be caught
                            // because of the ByteProcessor interface.
                            ThrowHelper.ThrowInvalidOperationException();
                        }
                    }
                    else
                    {
                        _ = output.Add(aName, entry.Value);
                    }
                }
            }
        }
Beispiel #2
0
        public void AppendToHeaderList(ICharSequence name, ICharSequence value)
        {
            _headersLength     += HpackHeaderField.SizeOf(name, value);
            _exceededMaxLength |= _headersLength > _maxHeaderListSize;

            if (_exceededMaxLength || _validationException is object)
            {
                // We don't store the header since we've already failed validation requirements.
                return;
            }

            if (_validate)
            {
                try
                {
                    _previousType = HpackDecoder.Validate(_streamId, name, _previousType);
                }
                catch (Http2Exception ex)
                {
                    _validationException = ex;
                    return;
                }
            }

            _ = _headers.Add(name, value);
        }
        private static IHttp2Headers DummyHeaders(IHttp2Headers headers, int times)
        {
            string largeValue = Repeat("dummy-value", 100);

            for (int i = 0; i < times; i++)
            {
                headers.Add((AsciiString)string.Format("dummy-{0}", i), (AsciiString)largeValue);
            }
            return(headers);
        }
Beispiel #4
0
 /// <summary>
 /// Filter the <see cref="HttpHeaderNames.Te"/> header according to the
 /// <a href="https://tools.ietf.org/html/rfc7540#section-8.1.2.2">special rules in the HTTP/2 RFC</a>.
 /// </summary>
 /// <param name="entry">An entry whose name is <see cref="HttpHeaderNames.Te"/>.</param>
 /// <param name="output">the resulting HTTP/2 headers.</param>
 private static void ToHttp2HeadersFilterTE(HeaderEntry <AsciiString, ICharSequence> entry, IHttp2Headers output)
 {
     if (AsciiString.IndexOf(entry.Value, ',', 0) == -1)
     {
         if (AsciiString.ContentEqualsIgnoreCase(AsciiString.Trim(entry.Value), HttpHeaderValues.Trailers))
         {
             _ = output.Add(HttpHeaderNames.Te, HttpHeaderValues.Trailers);
         }
     }
     else
     {
         var teValues = StringUtil.UnescapeCsvFields(entry.Value);
         foreach (var teValue in teValues)
         {
             if (AsciiString.ContentEqualsIgnoreCase(AsciiString.Trim(teValue), HttpHeaderValues.Trailers))
             {
                 _ = output.Add(HttpHeaderNames.Te, HttpHeaderValues.Trailers);
                 break;
             }
         }
     }
 }