Esempio n. 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);
                    }
                }
            }
        }
Esempio n. 2
0
        public void ContentEqualsIgnoreCase()
        {
            byte[]      bytes       = { 32, (byte)'a' };
            AsciiString asciiString = new AsciiString(bytes, 1, 1, false);

            // https://github.com/netty/netty/issues/9475
            Assert.False(asciiString.ContentEqualsIgnoreCase(new StringCharSequence("b")));
            Assert.False(asciiString.ContentEqualsIgnoreCase(AsciiString.Of("b")));
        }
        protected override void Verify(IFullHttpResponse response)
        {
            if (!response.Status.Equals(HttpResponseStatus.SwitchingProtocols))
            {
                throw new WebSocketHandshakeException($"Invalid handshake response getStatus: {response.Status}");
            }

            HttpHeaders headers = response.Headers;

            if (!headers.TryGet(HttpHeaderNames.Upgrade, out ICharSequence upgrade) ||
                !Websocket.ContentEqualsIgnoreCase(upgrade))
            {
                throw new WebSocketHandshakeException($"Invalid handshake response upgrade: {upgrade}");
            }

            if (!headers.ContainsValue(HttpHeaderNames.Connection, HttpHeaderValues.Upgrade, true))
            {
                headers.TryGet(HttpHeaderNames.Connection, out upgrade);
                throw new WebSocketHandshakeException($"Invalid handshake response connection: {upgrade}");
            }

            IByteBuffer challenge = response.Content;

            if (!challenge.Equals(this.expectedChallengeResponseBytes))
            {
                throw new WebSocketHandshakeException("Invalid challenge");
            }
        }
Esempio n. 4
0
 public void EqualsIgnoreCase()
 {
     Assert.True(AsciiString.ContentEqualsIgnoreCase(null, null));
     Assert.False(AsciiString.ContentEqualsIgnoreCase(null, (StringCharSequence)"foo"));
     Assert.False(AsciiString.ContentEqualsIgnoreCase((StringCharSequence)"bar", null));
     Assert.True(AsciiString.ContentEqualsIgnoreCase((StringCharSequence)"FoO", (StringCharSequence)"fOo"));
 }
Esempio n. 5
0
        private AsciiString Get0(ICharSequence name)
        {
            var nameHash = AsciiString.GetHashCode(name);

            var pseudoHeadersEnd = _pseudoHeaders.Length - 1;

            for (int i = 0; i < pseudoHeadersEnd; i += 2)
            {
                AsciiString roName = _pseudoHeaders[i];
                if (roName.GetHashCode() == nameHash && roName.ContentEqualsIgnoreCase(name))
                {
                    return(_pseudoHeaders[i + 1]);
                }
            }

            var otherHeadersEnd = _otherHeaders.Length - 1;

            for (int i = 0; i < otherHeadersEnd; i += 2)
            {
                AsciiString roName = _otherHeaders[i];
                if (roName.GetHashCode() == nameHash && roName.ContentEqualsIgnoreCase(name))
                {
                    return(_otherHeaders[i + 1]);
                }
            }
            return(null);
        }
Esempio n. 6
0
        protected override void Verify(IFullHttpResponse response)
        {
            if (!response.Status.Equals(HttpResponseStatus.SwitchingProtocols))
            {
                ThrowHelper.ThrowWebSocketHandshakeException_InvalidHandshakeResponseGS(response);
            }

            HttpHeaders headers = response.Headers;

            if (!headers.TryGet(HttpHeaderNames.Upgrade, out ICharSequence upgrade) ||
                !Websocket.ContentEqualsIgnoreCase(upgrade))
            {
                ThrowHelper.ThrowWebSocketHandshakeException_InvalidHandshakeResponseU(upgrade);
            }

            if (!headers.ContainsValue(HttpHeaderNames.Connection, HttpHeaderValues.Upgrade, true))
            {
                _ = headers.TryGet(HttpHeaderNames.Connection, out upgrade);
                ThrowHelper.ThrowWebSocketHandshakeException_InvalidHandshakeResponseConn(upgrade);
            }

            IByteBuffer challenge = response.Content;

            if (!challenge.Equals(_expectedChallengeResponseBytes))
            {
                ThrowHelper.ThrowWebSocketHandshakeException_InvalidChallenge();
            }
        }
Esempio n. 7
0
        private static void TestValueIteratorSingleValue(IHttp2Headers headers, ICharSequence name, ICharSequence value)
        {
            var itr = headers.GetAll(name).GetEnumerator();

            Assert.True(itr.MoveNext());
            Assert.True(AsciiString.ContentEqualsIgnoreCase(value, itr.Current));
            Assert.False(itr.MoveNext());
        }
Esempio n. 8
0
        public void TestGet()
        {
            var headers = NewClientHeaders();

            Assert.True(AsciiString.ContentEqualsIgnoreCase((AsciiString)"value1", headers.Get((AsciiString)"Name1", null)));
            Assert.True(AsciiString.ContentEqualsIgnoreCase((AsciiString)"/foo",
                                                            headers.Get(PseudoHeaderName.Path.Value, null)));
            Assert.Null(headers.Get(PseudoHeaderName.Status.Value, null));
            Assert.Null(headers.Get((AsciiString)"a missing header", null));
        }
Esempio n. 9
0
            protected override bool IsStartMessage(IHttpObject msg)
            {
                if (msg is IHttpResponse response)
                {
                    HttpHeaders headers = response.Headers;

                    var contentType = headers.Get(HttpHeaderNames.ContentType, null);
                    if (AsciiString.ContentEqualsIgnoreCase(contentType, HttpHeaderValues.TextPlain))
                    {
                        return(true);
                    }
                }

                return(false);
            }
Esempio n. 10
0
        public void TestIteratorMultipleValues()
        {
            var headers = ReadOnlyHttp2Headers.ServerHeaders(false, new AsciiString("200"), new AsciiString[] {
                new AsciiString("name2"), new AsciiString("value1"),
                new AsciiString("name1"), new AsciiString("value2"),
                new AsciiString("name2"), new AsciiString("value3")
            });
            var itr = headers.GetAll((AsciiString)"name2").GetEnumerator();

            Assert.True(itr.MoveNext());
            Assert.True(AsciiString.ContentEqualsIgnoreCase((AsciiString)"value1", itr.Current));
            Assert.True(itr.MoveNext());
            Assert.True(AsciiString.ContentEqualsIgnoreCase((AsciiString)"value3", itr.Current));
            Assert.False(itr.MoveNext());
        }
Esempio n. 11
0
        public void EqualsIgnoreCase()
        {
            Assert.True(AsciiString.ContentEqualsIgnoreCase(null, null));
            Assert.False(AsciiString.ContentEqualsIgnoreCase(null, (StringCharSequence)"foo"));
            Assert.False(AsciiString.ContentEqualsIgnoreCase((StringCharSequence)"bar", null));
            Assert.True(AsciiString.ContentEqualsIgnoreCase((StringCharSequence)"FoO", (StringCharSequence)"fOo"));

            // Test variations (Ascii + String, Ascii + Ascii, String + Ascii)
            Assert.True(AsciiString.ContentEqualsIgnoreCase((AsciiString)"FoO", (StringCharSequence)"fOo"));
            Assert.True(AsciiString.ContentEqualsIgnoreCase((AsciiString)"FoO", (AsciiString)"fOo"));
            Assert.True(AsciiString.ContentEqualsIgnoreCase((StringCharSequence)"FoO", (AsciiString)"fOo"));

            // Test variations (Ascii + String, Ascii + Ascii, String + Ascii)
            Assert.False(AsciiString.ContentEqualsIgnoreCase((AsciiString)"FoO", (StringCharSequence)"bAr"));
            Assert.False(AsciiString.ContentEqualsIgnoreCase((AsciiString)"FoO", (AsciiString)"bAr"));
            Assert.False(AsciiString.ContentEqualsIgnoreCase((StringCharSequence)"FoO", (AsciiString)"bAr"));
        }
Esempio n. 12
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;
             }
         }
     }
 }
Esempio n. 13
0
        public void MessagesSplitBetweenMultipleBuffers()
        {
            var          channel = new EmbeddedChannel(new HttpRequestDecoder());
            const string Crlf    = "\r\n";
            const string Str1    = "GET /some/path HTTP/1.1" + Crlf +
                                   "Host: localhost1" + Crlf + Crlf +
                                   "GET /some/other/path HTTP/1.0" + Crlf +
                                   "Hos";
            const string Str2 = "t: localhost2" + Crlf +
                                "content-length: 0" + Crlf + Crlf;

            byte[] data = Encoding.ASCII.GetBytes(Str1);
            channel.WriteInbound(Unpooled.CopiedBuffer(data));

            var req = channel.ReadInbound <IHttpRequest>();

            Assert.Equal(HttpVersion.Http11, req.ProtocolVersion);
            Assert.Equal("/some/path", req.Uri);
            Assert.Equal(1, req.Headers.Size);
            Assert.True(AsciiString.ContentEqualsIgnoreCase((StringCharSequence)"localhost1", req.Headers.Get(HttpHeaderNames.Host, null)));
            var cnt = channel.ReadInbound <ILastHttpContent>();

            cnt.Release();

            data = Encoding.ASCII.GetBytes(Str2);
            channel.WriteInbound(Unpooled.CopiedBuffer(data));
            req = channel.ReadInbound <IHttpRequest>();
            Assert.Equal(HttpVersion.Http10, req.ProtocolVersion);
            Assert.Equal("/some/other/path", req.Uri);
            Assert.Equal(2, req.Headers.Size);
            Assert.True(AsciiString.ContentEqualsIgnoreCase((StringCharSequence)"localhost2", req.Headers.Get(HttpHeaderNames.Host, null)));
            Assert.True(AsciiString.ContentEqualsIgnoreCase((StringCharSequence)"0", req.Headers.Get(HttpHeaderNames.ContentLength, null)));
            cnt = channel.ReadInbound <ILastHttpContent>();
            cnt.Release();

            Assert.False(channel.FinishAndReleaseAll());
        }
Esempio n. 14
0
 public bool ConvertToBoolean(ICharSequence value) => AsciiString.ContentEqualsIgnoreCase(value, TrueAscii);
Esempio n. 15
0
        protected internal override void Decode(IChannelHandlerContext context, IHttpObject message, List <object> output)
        {
            IFullHttpResponse response = null;

            try
            {
                if (!this.upgradeRequested)
                {
                    throw new InvalidOperationException("Read HTTP response without requesting protocol switch");
                }

                if (message is IHttpResponse rep)
                {
                    if (!HttpResponseStatus.SwitchingProtocols.Equals(rep.Status))
                    {
                        // The server does not support the requested protocol, just remove this handler
                        // and continue processing HTTP.
                        // NOTE: not releasing the response since we're letting it propagate to the
                        // next handler.
                        context.FireUserEventTriggered(UpgradeEvent.UpgradeRejected);
                        RemoveThisHandler(context);
                        context.FireChannelRead(rep);
                        return;
                    }
                }

                if (message is IFullHttpResponse fullRep)
                {
                    response = fullRep;
                    // Need to retain since the base class will release after returning from this method.
                    response.Retain();
                    output.Add(response);
                }
                else
                {
                    // Call the base class to handle the aggregation of the full request.
                    base.Decode(context, message, output);
                    if (output.Count == 0)
                    {
                        // The full request hasn't been created yet, still awaiting more data.
                        return;
                    }

                    Debug.Assert(output.Count == 1);
                    response = (IFullHttpResponse)output[0];
                }

                if (response.Headers.TryGet(HttpHeaderNames.Upgrade, out ICharSequence upgradeHeader) && !AsciiString.ContentEqualsIgnoreCase(this.upgradeCodec.Protocol, upgradeHeader))
                {
                    throw new  InvalidOperationException($"Switching Protocols response with unexpected UPGRADE protocol: {upgradeHeader}");
                }

                // Upgrade to the new protocol.
                this.sourceCodec.PrepareUpgradeFrom(context);
                this.upgradeCodec.UpgradeTo(context, response);

                // Notify that the upgrade to the new protocol completed successfully.
                context.FireUserEventTriggered(UpgradeEvent.UpgradeSuccessful);

                // We guarantee UPGRADE_SUCCESSFUL event will be arrived at the next handler
                // before http2 setting frame and http response.
                this.sourceCodec.UpgradeFrom(context);

                // We switched protocols, so we're done with the upgrade response.
                // Release it and clear it from the output.
                response.Release();
                output.Clear();
                RemoveThisHandler(context);
            }
            catch (Exception exception)
            {
                ReferenceCountUtil.Release(response);
                context.FireExceptionCaught(exception);
                RemoveThisHandler(context);
            }
        }