Ejemplo n.º 1
0
        public void TestLiteralWithIncrementalIndexingCompleteEviction()
        {
            // Verify indexed host header
            this.Decode("4004" + Hex("name") + "05" + Hex("value"));
            mockHeaders.Verify(x => x.Add(AsciiString.Of("name"), AsciiString.Of("value")));
            mockHeaders.VerifyNoOtherCalls();
            mockHeaders.Reset();
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < 4096; i++)
            {
                sb.Append('a');
            }
            var value = sb.ToString();

            sb = new StringBuilder();
            sb.Append("417F811F");
            for (int i = 0; i < 4096; i++)
            {
                sb.Append("61"); // 'a'
            }
            this.Decode(sb.ToString());
            mockHeaders.Verify(x => x.Add(AsciiString.Of(":authority"), AsciiString.Of(value)));
            mockHeaders.VerifyNoOtherCalls();
            mockHeaders.Reset();

            // Verify next header is inserted at index 62
            this.Decode("4004" + Hex("name") + "05" + Hex("value") + "BE");
            mockHeaders.Verify(x => x.Add(AsciiString.Of("name"), AsciiString.Of("value")), Times.AtLeast(2));
            mockHeaders.VerifyNoOtherCalls();
        }
Ejemplo n.º 2
0
        public void TrailerWithEmptyLineInSeparateBuffer()
        {
            HttpResponseDecoder decoder = new HttpResponseDecoder();
            EmbeddedChannel     channel = new EmbeddedChannel(decoder);

            String headers = "HTTP/1.1 200 OK\r\n"
                             + "Transfer-Encoding: chunked\r\n"
                             + "Trailer: My-Trailer\r\n";

            Assert.False(channel.WriteInbound(Unpooled.CopiedBuffer(Encoding.ASCII.GetBytes(headers))));
            Assert.True(channel.WriteInbound(Unpooled.CopiedBuffer(Encoding.ASCII.GetBytes("\r\n"))));

            Assert.True(channel.WriteInbound(Unpooled.CopiedBuffer("0\r\n", Encoding.ASCII)));
            Assert.True(channel.WriteInbound(Unpooled.CopiedBuffer("My-Trailer: 42\r\n", Encoding.ASCII)));
            Assert.True(channel.WriteInbound(Unpooled.CopiedBuffer("\r\n", Encoding.ASCII)));

            var response = channel.ReadInbound <IHttpResponse>();

            Assert.Equal(2, response.Headers.Size);
            Assert.Equal("chunked", response.Headers.Get(HttpHeaderNames.TransferEncoding, null));
            Assert.Equal("My-Trailer", response.Headers.Get(HttpHeaderNames.Trailer, null));

            var lastContent = channel.ReadInbound <ILastHttpContent>();

            Assert.Equal(1, lastContent.TrailingHeaders.Size);
            Assert.Equal("42", lastContent.TrailingHeaders.Get(AsciiString.Of("My-Trailer"), null));
            Assert.Equal(0, lastContent.Content.ReadableBytes);
            lastContent.Release();

            Assert.False(channel.Finish());
        }
Ejemplo n.º 3
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);
                    }
                }
            }
        }
Ejemplo n.º 4
0
        private static void SetHttp2Scheme(HttpHeaders input, Uri uri, IHttp2Headers output)
        {
            var value = uri.Scheme;

            if (value is object)
            {
                output.Scheme = new AsciiString(value);
                return;
            }

            // Consume the Scheme extension header if present
            if (input.TryGet(ExtensionHeaderNames.Scheme, out var cValue))
            {
                output.Scheme = AsciiString.Of(cValue);
                return;
            }

            if (uri.Port == HttpScheme.Https.Port)
            {
                output.Scheme = HttpScheme.Https.Name;
            }
            else if (uri.Port == HttpScheme.Http.Port)
            {
                output.Scheme = HttpScheme.Http.Name;
            }

            ThrowHelper.ThrowArgumentException_SchemeMustBeSpecified();
        }
Ejemplo n.º 5
0
        public void CharSequenceComparerIgnoreCaseTest()
        {
            var dict = new Dictionary <ICharSequence, int>(AsciiString.CaseInsensitiveHasher);

            dict.Add(AsciiString.Of("Town"), 0);
            dict.Add(AsciiString.Of("fOo"), 1);
            dict.Add(AsciiString.Of("baR"), 2);
            Assert.True(dict.ContainsKey((AsciiString)"town"));
            Assert.Equal(0, dict[(AsciiString)"town"]);
            Assert.True(dict.ContainsKey((AsciiString)"foo"));
            Assert.Equal(1, dict[(AsciiString)"foo"]);
            Assert.True(dict.ContainsKey((AsciiString)"bar"));
            Assert.Equal(2, dict[(AsciiString)"bar"]);

            Assert.True(AsciiString.Of("town").ContentEqualsIgnoreCase(new StringCharSequence("town")));

            Assert.True(dict.ContainsKey(new StringCharSequence("town")));
            Assert.Equal(0, dict[new StringCharSequence("town")]);
            Assert.True(dict.ContainsKey(new StringCharSequence("foo")));
            Assert.Equal(1, dict[new StringCharSequence("foo")]);
            Assert.True(dict.ContainsKey(new StringCharSequence("bar")));
            Assert.Equal(2, dict[new StringCharSequence("bar")]);

            dict.Clear();
        }
Ejemplo n.º 6
0
        public void HeadersOnlyRequest()
        {
            this.BootstrapEnv(2, 1, 0);
            IFullHttpRequest request = new DefaultFullHttpRequest(DotNetty.Codecs.Http.HttpVersion.Http11, HttpMethod.Get,
                                                                  "http://[email protected]:5555/example");
            HttpHeaders httpHeaders = request.Headers;

            httpHeaders.SetInt(HttpConversionUtil.ExtensionHeaderNames.StreamId, 5);
            httpHeaders.Set(HttpHeaderNames.Host, "[email protected]:5555");
            httpHeaders.Set(HttpConversionUtil.ExtensionHeaderNames.Scheme, "http");
            httpHeaders.Add(AsciiString.Of("foo"), AsciiString.Of("goo"));
            httpHeaders.Add(AsciiString.Of("foo"), AsciiString.Of("goo2"));
            httpHeaders.Add(AsciiString.Of("foo2"), AsciiString.Of("goo2"));
            var http2Headers = new DefaultHttp2Headers()
            {
                Method    = new AsciiString("GET"),
                Path      = new AsciiString("/example"),
                Authority = new AsciiString("www.example.org:5555"),
                Scheme    = new AsciiString("http")
            };

            http2Headers.Add(new AsciiString("foo"), new AsciiString("goo"));
            http2Headers.Add(new AsciiString("foo"), new AsciiString("goo2"));
            http2Headers.Add(new AsciiString("foo2"), new AsciiString("goo2"));

            var writePromise = this.NewPromise();

            this.VerifyHeadersOnly(http2Headers, writePromise, this.clientChannel.WriteAndFlushAsync(request, writePromise));
        }
Ejemplo n.º 7
0
        public void TestPseudoHeadersWithRemovePreservesPseudoIterationOrder()
        {
            var headers = NewHeaders();

            var nonPseudoHeaders = new DefaultHttp2Headers();

            foreach (var entry in headers)
            {
                if (entry.Key.Count == 0 || entry.Key[0] != ':' &&
                    !nonPseudoHeaders.Contains(entry.Key))
                {
                    nonPseudoHeaders.Add(entry.Key, entry.Value);
                }
            }

            Assert.False(nonPseudoHeaders.IsEmpty);

            // Remove all the non-pseudo headers and verify
            foreach (var nonPseudoHeaderEntry in nonPseudoHeaders)
            {
                Assert.True(headers.Remove(nonPseudoHeaderEntry.Key));
                VerifyPseudoHeadersFirst(headers);
                VerifyAllPseudoHeadersPresent(headers);
            }

            // Add back all non-pseudo headers
            foreach (var nonPseudoHeaderEntry in nonPseudoHeaders)
            {
                headers.Add(nonPseudoHeaderEntry.Key, AsciiString.Of("goo"));
                VerifyPseudoHeadersFirst(headers);
                VerifyAllPseudoHeadersPresent(headers);
            }
        }
Ejemplo n.º 8
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")));
        }
        public void TestExceptionDuringConnect()
        {
            IEventLoopGroup group         = null;
            IChannel        serverChannel = null;
            IChannel        clientChannel = null;

            try
            {
                group = new DefaultEventLoopGroup(1);
                var addr      = new LocalAddress("a");
                var exception = new AtomicReference <Exception>();
                var sf        =
                    new ServerBootstrap().Channel <LocalServerChannel>().Group(group).ChildHandler(
                        new ActionChannelInitializer <IChannel>(ch =>
                {
                    ch.Pipeline.AddFirst(new HttpResponseEncoder());
                    var response = new DefaultFullHttpResponse(
                        HttpVersion.Http11,
                        HttpResponseStatus.BadGateway);
                    response.Headers.Add(AsciiString.Of("name"), "value");
                    response.Headers.Add(HttpHeaderNames.ContentLength, "0");
                    ch.WriteAndFlushAsync(response);
                }
                                                                )).BindAsync(addr);
                serverChannel = sf.Result;

                var cf = new Bootstrap().Channel <LocalChannel>().Group(group).Handler(
                    new ActionChannelInitializer <IChannel>(ch =>
                {
                    ch.Pipeline.AddFirst(new HttpProxyHandler(addr));
                    ch.Pipeline.AddLast(new ErrorCaptureHandler(exception));
                })).ConnectAsync(new DnsEndPoint("localhost", 1234));

                clientChannel = cf.Result;
                clientChannel.CloseAsync().Wait();

                Assert.True(exception.Value is HttpProxyConnectException);
                var actual = (HttpProxyConnectException)exception.Value;
                Assert.NotNull(actual.Headers);
                Assert.Equal("value", actual.Headers.GetAsString(AsciiString.Of("name")));
            }
            finally
            {
                if (clientChannel != null)
                {
                    clientChannel.CloseAsync();
                }
                if (serverChannel != null)
                {
                    serverChannel.CloseAsync();
                }
                if (group != null)
                {
                    @group.ShutdownGracefullyAsync().Wait();
                }
            }
        }
Ejemplo n.º 10
0
        private static IHttp2Headers Headers()
        {
            var headers = new DefaultHttp2Headers(false);

            headers.Method    = AsciiString.Of("GET");
            headers.Scheme    = AsciiString.Of("https");
            headers.Authority = AsciiString.Of("example.org");
            headers.Path      = AsciiString.Of("/some/path/resource2");
            headers.Add(Http2TestUtil.RandomString(), Http2TestUtil.RandomString());
            return(headers);
        }
Ejemplo n.º 11
0
        private static IHttp2Headers LargeHeaders()
        {
            DefaultHttp2Headers headers = new DefaultHttp2Headers(false);

            for (int i = 0; i < 100; ++i)
            {
                string key   = "this-is-a-test-header-key-" + i;
                string value = "this-is-a-test-header-value-" + i;
                headers.Add(AsciiString.Of(key), AsciiString.Of(value));
            }
            return(headers);
        }
        public void TestDuplicateHandshakeResponseHeaders()
        {
            WebSocketServerHandshaker serverHandshaker = NewHandshaker("ws://example.com/chat",
                                                                       "chat", WebSocketDecoderConfig.Default);
            IFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.Http11, HttpMethod.Get, "/chat");

            request.Headers
            .Set(HttpHeaderNames.Host, "example.com")
            .Set(HttpHeaderNames.Origin, "example.com")
            .Set(HttpHeaderNames.Upgrade, HttpHeaderValues.Websocket)
            .Set(HttpHeaderNames.Connection, HttpHeaderValues.Upgrade)
            .Set(HttpHeaderNames.SecWebsocketKey, "dGhlIHNhbXBsZSBub25jZQ==")
            .Set(HttpHeaderNames.SecWebsocketOrigin, "http://example.com")
            .Set(HttpHeaderNames.SecWebsocketProtocol, "chat, superchat")
            .Set(HttpHeaderNames.SecWebsocketVersion, WebSocketVersion().ToHttpHeaderValue());
            HttpHeaders customResponseHeaders = new DefaultHttpHeaders();

            // set duplicate required headers and one custom
            customResponseHeaders
            .Set(HttpHeaderNames.Connection, HttpHeaderValues.Upgrade)
            .Set(HttpHeaderNames.Upgrade, HttpHeaderValues.Websocket)
            .Set(AsciiString.Of("custom"), AsciiString.Of("header"));

            if (WebSocketVersion() != Http.WebSockets.WebSocketVersion.V00)
            {
                customResponseHeaders.Set(HttpHeaderNames.SecWebsocketAccept, "12345");
            }

            IFullHttpResponse response = null;

            try
            {
                response = serverHandshaker.NewHandshakeResponse(request, customResponseHeaders);
                HttpHeaders responseHeaders = response.Headers;

                Assert.Equal(1, responseHeaders.GetAll(HttpHeaderNames.Connection).Count);
                Assert.Equal(1, responseHeaders.GetAll(HttpHeaderNames.Upgrade).Count);
                Assert.True(responseHeaders.ContainsValue(AsciiString.Of("custom"), AsciiString.Of("header"), true));
                if (WebSocketVersion() != Http.WebSockets.WebSocketVersion.V00)
                {
                    Assert.False(responseHeaders.ContainsValue(HttpHeaderNames.SecWebsocketAccept, AsciiString.Of("12345"), false));
                }
            }
            finally
            {
                request.Release();
                if (response != null)
                {
                    response.Release();
                }
            }
        }
        public void TestCustomHeaders()
        {
            EndPoint socketAddress = new DnsEndPoint("10.0.0.1", 8080);

            TestInitialMessage(
                socketAddress,
                "10.0.0.1:8080",
                "10.0.0.1:8080",
                new DefaultHttpHeaders()
                .Add(AsciiString.Of("CUSTOM_HEADER"), "CUSTOM_VALUE1")
                .Add(AsciiString.Of("CUSTOM_HEADER"), "CUSTOM_VALUE2"),
                true);
        }
Ejemplo n.º 14
0
        public void DontCombineSetCookieHeadersRegardlessOfCase()
        {
            CombinedHttpHeaders headers = NewCombinedHttpHeaders();

            headers.Add(AsciiString.Of("Set-Cookie"), "a");
            CombinedHttpHeaders otherHeaders = NewCombinedHttpHeaders();

            otherHeaders.Add(AsciiString.Of("set-cookie"), "b");
            otherHeaders.Add(AsciiString.Of("SET-COOKIE"), "c");
            headers.Add(otherHeaders);
            var list = headers.GetAll(HttpHeaderNames.SetCookie);

            Assert.Equal(3, headers.GetAll(HttpHeaderNames.SetCookie).Count);
        }
Ejemplo n.º 15
0
        private static IHttp2Headers NewHeaders()
        {
            var headers = new DefaultHttp2Headers();

            headers.Add(AsciiString.Of("name1"), new[] { AsciiString.Of("value1"), AsciiString.Of("value2") });
            headers.Method = AsciiString.Of("POST");
            headers.Add(AsciiString.Of("2name"), AsciiString.Of("value3"));
            headers.Path      = AsciiString.Of("/index.html");
            headers.Status    = AsciiString.Of("200");
            headers.Authority = AsciiString.Of("netty.io");
            headers.Add(AsciiString.Of("name3"), AsciiString.Of("value4"));
            headers.Scheme = AsciiString.Of("https");
            return(headers);
        }
Ejemplo n.º 16
0
        public void AsciiStringComparerIgnoreCaseTest()
        {
            var dict = new Dictionary <AsciiString, int>(AsciiStringComparer.IgnoreCase);

            dict.Add(AsciiString.Of("Town"), 0);
            dict.Add(AsciiString.Of("fOo"), 1);
            dict.Add(AsciiString.Of("baR"), 2);
            Assert.True(dict.ContainsKey((AsciiString)"town"));
            Assert.Equal(0, dict[(AsciiString)"town"]);
            Assert.True(dict.ContainsKey((AsciiString)"foo"));
            Assert.Equal(1, dict[(AsciiString)"foo"]);
            Assert.True(dict.ContainsKey((AsciiString)"bar"));
            Assert.Equal(2, dict[(AsciiString)"bar"]);
        }
Ejemplo n.º 17
0
            public void TranslateHeaders(IEnumerable <HeaderEntry <ICharSequence, ICharSequence> > inputHeaders)
            {
                // lazily created as needed
                StringBuilder cookies = null;

                foreach (var entry in inputHeaders)
                {
                    var name  = entry.Key;
                    var value = entry.Value;

                    if (_translations.TryGet(name, out var translatedName))
                    {
                        _ = _output.Add(translatedName, AsciiString.Of(value));
                    }
                    else if (!PseudoHeaderName.IsPseudoHeader(name))
                    {
                        // https://tools.ietf.org/html/rfc7540#section-8.1.2.3
                        // All headers that start with ':' are only valid in HTTP/2 context
                        if (0u >= (uint)name.Count || name[0] == ':')
                        {
                            StringBuilderManager.Free(cookies);
                            ThrowHelper.ThrowStreamError_InvalidHttp2HeaderEncounteredInTranslationToHttp1(_streamId, name);
                        }
                        var cookie = HttpHeaderNames.Cookie;
                        if (cookie.Equals(name))
                        {
                            // combine the cookie values into 1 header entry.
                            // https://tools.ietf.org/html/rfc7540#section-8.1.2.5
                            if (cookies is null)
                            {
                                cookies = StringBuilderManager.Allocate();
                            }
                            else if ((uint)cookies.Length > 0u)
                            {
                                _ = cookies.Append("; ");
                            }
                            _ = cookies.Append(value.ToString());
                        }
                        else
                        {
                            _ = _output.Add(AsciiString.Of(name), value);
                        }
                    }
                }
                if (cookies is object)
                {
                    _ = _output.Add(HttpHeaderNames.Cookie, StringBuilderManager.ReturnAndFree(cookies));
                }
            }
Ejemplo n.º 18
0
        static IHttp2Headers Http1HeadersToHttp2Headers(IFullHttpRequest request)
        {
            IHttp2Headers http2Headers = new DefaultHttp2Headers()
            {
                Method = HttpMethod.Get.AsciiName,
                Path   = AsciiString.Of(request.Uri),
                Scheme = HttpScheme.Http.Name
            };

            if (request.Headers.TryGet(HttpHeaderNames.Host, out var host))
            {
                http2Headers.Authority = host;
            }
            return(http2Headers);
        }
Ejemplo n.º 19
0
        public void IndexOf()
        {
            AsciiString foo = AsciiString.Of("This is a test");
            int         i1  = foo.IndexOf(' ', 0);

            Assert.Equal(4, i1);
            int i2 = foo.IndexOf(' ', i1 + 1);

            Assert.Equal(7, i2);
            int i3 = foo.IndexOf(' ', i2 + 1);

            Assert.Equal(9, i3);
            Assert.True(i3 + 1 < foo.Count);
            int i4 = foo.IndexOf(' ', i3 + 1);

            Assert.Equal(-1, i4);
        }
        public void ClientRequestTrailingHeaders()
        {
            this.BootstrapEnv(1, 1, 1);
            string           text    = "some data";
            IByteBuffer      content = Unpooled.CopiedBuffer(Encoding.UTF8.GetBytes(text));
            IFullHttpRequest request = new DefaultFullHttpRequest(DotNetty.Codecs.Http.HttpVersion.Http11, HttpMethod.Get,
                                                                  "/some/path/resource2", content, true);

            try
            {
                HttpHeaders httpHeaders = request.Headers;
                httpHeaders.SetInt(HttpConversionUtil.ExtensionHeaderNames.StreamId, 3);
                httpHeaders.SetInt(HttpHeaderNames.ContentLength, text.Length);
                httpHeaders.SetShort(HttpConversionUtil.ExtensionHeaderNames.StreamWeight, 16);
                HttpHeaders trailingHeaders = request.TrailingHeaders;
                trailingHeaders.Set(AsciiString.Of("Foo"), AsciiString.Of("goo"));
                trailingHeaders.Set(AsciiString.Of("fOo2"), AsciiString.Of("goo2"));
                trailingHeaders.Add(AsciiString.Of("foO2"), AsciiString.Of("goo3"));
                var http2Headers = new DefaultHttp2Headers()
                {
                    Method = new AsciiString("GET"),
                    Path   = new AsciiString("/some/path/resource2"),
                };
                IHttp2Headers http2Headers2 = new DefaultHttp2Headers();
                http2Headers2.Set(new AsciiString("foo"), new AsciiString("goo"));
                http2Headers2.Set(new AsciiString("foo2"), new AsciiString("goo2"));
                http2Headers2.Add(new AsciiString("foo2"), new AsciiString("goo3"));
                Http2TestUtil.RunInChannel(this.clientChannel, () =>
                {
                    this.clientHandler.Encoder.WriteHeadersAsync(this.CtxClient(), 3, http2Headers, 0, false, this.NewPromiseClient());
                    this.clientHandler.Encoder.WriteDataAsync(this.CtxClient(), 3, content.RetainedDuplicate(), 0, false, this.NewPromiseClient());
                    this.clientHandler.Encoder.WriteHeadersAsync(this.CtxClient(), 3, http2Headers2, 0, true, this.NewPromiseClient());
                    this.clientChannel.Flush();
                });
                this.AwaitRequests();
                var requestCaptor = new ArgumentCaptor <IFullHttpMessage>();
                this.serverListener.Verify(x => x.MessageReceived(It.Is <IHttpObject>(v => requestCaptor.Capture((IFullHttpMessage)v))));
                this.capturedRequests = requestCaptor.GetAllValues();
                Assert.Equal(request, (IFullHttpRequest)this.capturedRequests[0]);
            }
            finally
            {
                request.Release();
            }
        }
Ejemplo n.º 21
0
        public void TestTransferCodingGZIPAndChunked()
        {
            string requestStr = "POST / HTTP/1.1\r\n" +
                                "Host: example.com\r\n" +
                                "Content-Type: application/x-www-form-urlencoded\r\n" +
                                "Trailer: My-Trailer\r\n" +
                                "Transfer-Encoding: gzip, chunked\r\n" +
                                "\r\n";
            HttpRequestDecoder decoder      = new HttpRequestDecoder();
            HttpContentDecoder decompressor = new HttpContentDecompressor();
            EmbeddedChannel    channel      = new EmbeddedChannel(decoder, decompressor);

            Assert.True(channel.WriteInbound(Unpooled.CopiedBuffer(requestStr, Encoding.ASCII)));

            string chunkLength = GzHelloWorld.Length.ToString("x2");

            Assert.True(channel.WriteInbound(Unpooled.CopiedBuffer(chunkLength + "\r\n", Encoding.ASCII)));
            Assert.True(channel.WriteInbound(Unpooled.CopiedBuffer(GzHelloWorld)));
            Assert.True(channel.WriteInbound(Unpooled.CopiedBuffer(Encoding.ASCII.GetBytes("\r\n"))));
            Assert.True(channel.WriteInbound(Unpooled.CopiedBuffer("0\r\n", Encoding.ASCII)));
            Assert.True(channel.WriteInbound(Unpooled.CopiedBuffer("My-Trailer: 42\r\n\r\n", Encoding.ASCII)));

            IHttpRequest request = channel.ReadInbound <IHttpRequest>();

            Assert.True(request.Result.IsSuccess);
            Assert.True(request.Headers.ContainsValue(HttpHeaderNames.TransferEncoding, HttpHeaderValues.Chunked, true));
            Assert.False(request.Headers.Contains(HttpHeaderNames.ContentLength));

            IHttpContent chunk1 = channel.ReadInbound <IHttpContent>();

            Assert.True(chunk1.Result.IsSuccess);
            Assert.Equal(HelloWorld, chunk1.Content.ToString(Encoding.ASCII));
            chunk1.Release();

            ILastHttpContent chunk2 = channel.ReadInbound <ILastHttpContent>();

            Assert.True(chunk2.Result.IsSuccess);
            Assert.Equal("42", chunk2.TrailingHeaders.Get(AsciiString.Of("My-Trailer"), null));
            chunk2.Release();

            Assert.False(channel.Finish());
            channel.ReleaseInbound();
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Converts the given HTTP/1.x headers into HTTP/2 headers.
        /// The following headers are only used if they can not be found in from the <c>HOST</c> header or the
        /// <c>Request-Line</c> as defined by <a href="https://tools.ietf.org/html/rfc7230">rfc7230</a>
        /// <para><see cref="ExtensionHeaderNames.Scheme"/></para>
        /// <see cref="ExtensionHeaderNames.Path"/> is ignored and instead extracted from the <c>Request-Line</c>.
        /// </summary>
        /// <param name="input"></param>
        /// <param name="validateHeaders"></param>
        /// <returns></returns>
        public static IHttp2Headers ToHttp2Headers(IHttpMessage input, bool validateHeaders)
        {
            HttpHeaders   inHeaders = input.Headers;
            IHttp2Headers output    = new DefaultHttp2Headers(validateHeaders, inHeaders.Size);

            if (input is IHttpRequest request)
            {
                output.Method = request.Method.AsciiName;
                // TODO java.net.URI isOriginForm  isAsteriskForm
                if (Uri.TryCreate(request.Uri, UriKind.Absolute, out var requestTargetUri) && !requestTargetUri.IsFile) // .NETCore 非Windows系统,会把 '/' 打头的相对 url 默认为 UnixFileUri
                {
                    output.Path = ToHttp2Path(requestTargetUri);
                    SetHttp2Scheme(inHeaders, requestTargetUri, output);
                    _ = requestTargetUri.Authority;
                    // Attempt to take from HOST header before taking from the request-line
                    var host = inHeaders.GetAsString(HttpHeaderNames.Host);
                    SetHttp2Authority(string.IsNullOrEmpty(host) ? requestTargetUri.Authority : host, output);
                }
                else
                {
                    output.Path = new AsciiString(request.Uri);
                    // Consume the Scheme extension header if present
                    if (inHeaders.TryGet(ExtensionHeaderNames.Scheme, out var cValue))
                    {
                        output.Scheme = AsciiString.Of(cValue);
                    }
                    if (output.Scheme is null)
                    {
                        ThrowHelper.ThrowArgumentException_SchemeMustBeSpecified();
                    }
                    var host = inHeaders.GetAsString(HttpHeaderNames.Host);
                    SetHttp2Authority(host, output);
                }
            }
            else if (input is IHttpResponse response)
            {
                output.Status = response.Status.CodeAsText;
            }

            // Add the HTTP headers which have not been consumed above
            ToHttp2Headers(inHeaders, output);
            return(output);
        }
Ejemplo n.º 23
0
        private static CharSequenceMap <AsciiString> ToLowercaseMap(IEnumerable <ICharSequence> values, int arraySizeHint)
        {
            var valueConverter = UnsupportedValueConverter <AsciiString> .Instance;
            var result         = new CharSequenceMap <AsciiString>(true, valueConverter, arraySizeHint);

            foreach (var item in values)
            {
                AsciiString lowerCased = AsciiString.Of(item).ToLowerCase();
                try
                {
                    int index = lowerCased.ForEachByte(ByteProcessor.FindComma);
                    if (index != -1)
                    {
                        int start = 0;
                        do
                        {
                            _     = result.Add(lowerCased.SubSequence(start, index, false).Trim(), AsciiString.Empty);
                            start = index + 1;
                        } while (start < lowerCased.Count &&
                                 (index = lowerCased.ForEachByte(start, lowerCased.Count - start, ByteProcessor.FindComma)) != -1);
                        _ = result.Add(lowerCased.SubSequence(start, lowerCased.Count, false).Trim(), AsciiString.Empty);
                    }
                    else
                    {
                        _ = result.Add(lowerCased.Trim(), AsciiString.Empty);
                    }
                }
                catch (Exception)
                {
                    // This is not expect to happen because FIND_COMMA never throws but must be caught
                    // because of the ByteProcessor interface.
                    ThrowHelper.ThrowInvalidOperationException();
                }
            }

            return(result);
        }
Ejemplo n.º 24
0
 public void TestLiteralNeverIndexedWithEmptyName()
 {
     this.Decode("100005" + Hex("value"));
     mockHeaders.Verify(x => x.Add(AsciiString.Empty, AsciiString.Of("value")), Times.Once);
 }
Ejemplo n.º 25
0
        public void ChunkedRequestWithBodyAndTrailingHeaders()
        {
            string        text            = "foooooo";
            string        text2           = "goooo";
            List <string> receivedBuffers = new List <string>();

            this.serverListener
            .Setup(x => x.OnDataRead(
                       It.IsAny <IChannelHandlerContext>(),
                       It.Is <int>(v => v == 3),
                       It.IsAny <IByteBuffer>(),
                       It.Is <int>(v => v == 0),
                       It.Is <bool>(v => v == false)))
            .Returns <IChannelHandlerContext, int, IByteBuffer, int, bool>((ctx, id, buf, p, e) =>
            {
                lock (receivedBuffers)
                {
                    receivedBuffers.Add(buf.ToString(Encoding.UTF8));
                }
                return(0);
            });
            this.BootstrapEnv(4, 1, 1);
            IHttpRequest request = new DefaultHttpRequest(DotNetty.Codecs.Http.HttpVersion.Http11, HttpMethod.Post,
                                                          "http://[email protected]:5555/example");
            HttpHeaders httpHeaders = request.Headers;

            httpHeaders.Set(HttpHeaderNames.Host, "www.example.org:5555");
            httpHeaders.Add(HttpHeaderNames.TransferEncoding, "chunked");
            httpHeaders.Add(AsciiString.Of("foo"), AsciiString.Of("goo"));
            httpHeaders.Add(AsciiString.Of("foo"), AsciiString.Of("goo2"));
            httpHeaders.Add(AsciiString.Of("foo2"), AsciiString.Of("goo2"));
            var http2Headers = new DefaultHttp2Headers()
            {
                Method    = new AsciiString("POST"),
                Path      = new AsciiString("/example"),
                Authority = new AsciiString("www.example.org:5555"),
                Scheme    = new AsciiString("http")
            };

            http2Headers.Add(new AsciiString("foo"), new AsciiString("goo"));
            http2Headers.Add(new AsciiString("foo"), new AsciiString("goo2"));
            http2Headers.Add(new AsciiString("foo2"), new AsciiString("goo2"));

            DefaultHttpContent httpContent     = new DefaultHttpContent(Unpooled.CopiedBuffer(text, Encoding.UTF8));
            ILastHttpContent   lastHttpContent = new DefaultLastHttpContent(Unpooled.CopiedBuffer(text2, Encoding.UTF8));

            lastHttpContent.TrailingHeaders.Add(AsciiString.Of("trailing"), AsciiString.Of("bar"));

            IHttp2Headers http2TrailingHeaders = new DefaultHttp2Headers
            {
                { new AsciiString("trailing"), new AsciiString("bar") }
            };

            var writePromise       = this.NewPromise();
            var writeFuture        = this.clientChannel.WriteAsync(request, writePromise);
            var contentPromise     = this.NewPromise();
            var contentFuture      = this.clientChannel.WriteAsync(httpContent, contentPromise);
            var lastContentPromise = this.NewPromise();
            var lastContentFuture  = this.clientChannel.WriteAsync(lastHttpContent, lastContentPromise);

            this.clientChannel.Flush();

            Assert.True(writePromise.Task.Wait(TimeSpan.FromSeconds(WAIT_TIME_SECONDS)));
            Assert.True(writePromise.IsSuccess);
            Assert.True(writeFuture.Wait(TimeSpan.FromSeconds(WAIT_TIME_SECONDS)));
            Assert.True(writeFuture.IsSuccess());

            Assert.True(contentPromise.Task.Wait(TimeSpan.FromSeconds(WAIT_TIME_SECONDS)));
            Assert.True(contentPromise.IsSuccess);
            Assert.True(contentFuture.Wait(TimeSpan.FromSeconds(WAIT_TIME_SECONDS)));
            Assert.True(contentFuture.IsSuccess());

            Assert.True(lastContentPromise.Task.Wait(TimeSpan.FromSeconds(WAIT_TIME_SECONDS)));
            Assert.True(lastContentPromise.IsSuccess);
            Assert.True(lastContentFuture.Wait(TimeSpan.FromSeconds(WAIT_TIME_SECONDS)));
            Assert.True(lastContentFuture.IsSuccess());

            this.AwaitRequests();
            this.serverListener.Verify(
                x => x.OnHeadersRead(
                    It.IsAny <IChannelHandlerContext>(),
                    It.Is <int>(v => v == 3),
                    It.Is <IHttp2Headers>(v => v.Equals(http2Headers)),
                    It.Is <int>(v => v == 0),
                    It.IsAny <short>(),
                    It.IsAny <bool>(),
                    It.Is <int>(v => v == 0),
                    It.Is <bool>(v => v == false)));
            this.serverListener.Verify(
                x => x.OnDataRead(
                    It.IsAny <IChannelHandlerContext>(),
                    It.Is <int>(v => v == 3),
                    It.IsAny <IByteBuffer>(),
                    It.Is <int>(v => v == 0),
                    It.Is <bool>(v => v == false)));
            this.serverListener.Verify(
                x => x.OnHeadersRead(
                    It.IsAny <IChannelHandlerContext>(),
                    It.Is <int>(v => v == 3),
                    It.Is <IHttp2Headers>(v => v.Equals(http2TrailingHeaders)),
                    It.Is <int>(v => v == 0),
                    It.IsAny <short>(),
                    It.IsAny <bool>(),
                    It.Is <int>(v => v == 0),
                    It.Is <bool>(v => v == true)));
            lock (receivedBuffers)
            {
                Assert.Single(receivedBuffers);
                Assert.Equal(text + text2, receivedBuffers[0]);
            }
        }
Ejemplo n.º 26
0
        public void SupportIanaStatusCodes()
        {
            var forbiddenIanaCodes = new HashSet <int>();

            forbiddenIanaCodes.Add(1004);
            forbiddenIanaCodes.Add(1005);
            forbiddenIanaCodes.Add(1006);
            var validIanaCodes = new HashSet <int>();

            for (int i = 1000; i < 1015; i++)
            {
                validIanaCodes.Add(i);
            }
            validIanaCodes.ExceptWith(forbiddenIanaCodes);

            foreach (int statusCode in validIanaCodes)
            {
                var encoderChannel = new EmbeddedChannel(new WebSocket08FrameEncoder(true));
                var decoderChannel = new EmbeddedChannel(new WebSocket08FrameDecoder(true, true, 65535, false));

                Assert.True(encoderChannel.WriteOutbound(new CloseWebSocketFrame(statusCode, AsciiString.Of("Bye"))));
                Assert.True(encoderChannel.Finish());
                var serializedCloseFrame = encoderChannel.ReadOutbound <IByteBuffer>();
                Assert.Null(encoderChannel.ReadOutbound <object>());

                Assert.True(decoderChannel.WriteInbound(serializedCloseFrame));
                Assert.True(decoderChannel.Finish());

                var outputFrame = decoderChannel.ReadInbound <CloseWebSocketFrame>();
                Assert.Null(decoderChannel.ReadOutbound <object>());
                try
                {
                    Assert.Equal(statusCode, outputFrame.StatusCode());
                }
                finally
                {
                    outputFrame.Release();
                }
            }
        }
Ejemplo n.º 27
0
        static async Task Main(string[] args)
        {
            ExampleHelper.SetConsoleLogger();

            bool useLibuv = ClientSettings.UseLibuv;

            Console.WriteLine("Transport type : " + (useLibuv ? "Libuv" : "Socket"));

            IEventLoopGroup group;

            if (useLibuv)
            {
                group = new EventLoopGroup();
            }
            else
            {
                group = new MultithreadEventLoopGroup();
            }

            X509Certificate2 cert       = null;
            string           targetHost = null;

            if (ClientSettings.IsSsl)
            {
                cert       = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password");
                targetHost = cert.GetNameInfo(X509NameType.DnsName, false);
            }
            try
            {
                var bootstrap = new Bootstrap();
                bootstrap
                .Group(group)
                .Option(ChannelOption.TcpNodelay, true)
                .Option(ChannelOption.SoKeepalive, true);
                if (useLibuv)
                {
                    bootstrap.Channel <TcpChannel>();
                }
                else
                {
                    bootstrap.Channel <TcpSocketChannel>();
                }

                bootstrap.Handler(new Http2ClientFrameInitializer(cert, targetHost));

                IChannel channel = await bootstrap.ConnectAsync(new IPEndPoint(ClientSettings.Host, ClientSettings.Port));

                try
                {
                    Console.WriteLine("Connected to [" + ClientSettings.Host + ':' + ClientSettings.Port + ']');

                    Http2ClientStreamFrameResponseHandler streamFrameResponseHandler =
                        new Http2ClientStreamFrameResponseHandler();

                    Http2StreamChannelBootstrap streamChannelBootstrap = new Http2StreamChannelBootstrap(channel);
                    IHttp2StreamChannel         streamChannel          = await streamChannelBootstrap.OpenAsync();

                    streamChannel.Pipeline.AddLast(streamFrameResponseHandler);

                    // Send request (a HTTP/2 HEADERS frame - with ':method = GET' in this case)
                    var                 path    = ExampleHelper.Configuration["path"];
                    HttpScheme          scheme  = ClientSettings.IsSsl ? HttpScheme.Https : HttpScheme.Http;
                    DefaultHttp2Headers headers = new DefaultHttp2Headers
                    {
                        Method = HttpMethod.Get.AsciiName,
                        Path   = AsciiString.Of(path),
                        Scheme = scheme.Name
                    };
                    IHttp2HeadersFrame headersFrame = new DefaultHttp2HeadersFrame(headers);
                    await streamChannel.WriteAndFlushAsync(headersFrame);

                    Console.WriteLine("Sent HTTP/2 GET request to " + path);

                    // Wait for the responses (or for the latch to expire), then clean up the connections
                    if (!streamFrameResponseHandler.ResponseSuccessfullyCompleted())
                    {
                        Console.WriteLine("Did not get HTTP/2 response in expected time.");
                    }

                    Console.WriteLine("Finished HTTP/2 request, will close the connection.");
                    Console.ReadKey();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                    Console.WriteLine("按任意键退出");
                    Console.ReadKey();
                }
                finally
                {
                    // Wait until the connection is closed.
                    await channel.CloseAsync();
                }
            }
            finally
            {
                await group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1));
            }
        }
Ejemplo n.º 28
0
        /// <summary>
        /// Create a new object to contain the request data.
        /// </summary>
        /// <param name="streamId">The stream associated with the request</param>
        /// <param name="http2Headers">The initial set of HTTP/2 headers to create the request with</param>
        /// <param name="validateHttpHeaders"><c>true</c> to validate HTTP headers in the http-codec
        /// <para><c>false</c> not to validate HTTP headers in the http-codec</para></param>
        /// <returns>A new request object which represents headers for a chunked request</returns>
        /// <exception cref="Http2Exception">See <see cref="AddHttp2ToHttpHeaders(int, IHttp2Headers, HttpHeaders, DotNettyHttpVersion, bool, bool)"/></exception>
        public static IHttpRequest ToHttpRequest(int streamId, IHttp2Headers http2Headers, bool validateHttpHeaders)
        {
            // HTTP/2 does not define a way to carry the version identifier that is included in the HTTP/1.1 request line.
            var method = http2Headers.Method;

            if (method is null)
            {
                ThrowHelper.ThrowArgumentNullException_MethodHeader();
            }
            var path = http2Headers.Path;

            if (path is null)
            {
                ThrowHelper.ThrowArgumentNullException_PathHeader();
            }

            var msg = new DefaultHttpRequest(DotNettyHttpVersion.Http11, HttpMethod.ValueOf(AsciiString.Of(method)),
                                             path.ToString(), validateHttpHeaders);

            try
            {
                AddHttp2ToHttpHeaders(streamId, http2Headers, msg.Headers, msg.ProtocolVersion, false, true);
            }
            catch (Http2Exception)
            {
                throw;
            }
            catch (Exception t)
            {
                ThrowHelper.ThrowStreamError_Http2ToHttp1HeadersConversionError(streamId, t);
            }
            return(msg);
        }
Ejemplo n.º 29
0
 public void TestLiteralWithIncrementalIndexingWithEmptyName()
 {
     this.Decode("400005" + Hex("value"));
     mockHeaders.Verify(x => x.Add(AsciiString.Empty, AsciiString.Of("value")), Times.Once);
 }
Ejemplo n.º 30
0
        public void TestHeaderNameValidation()
        {
            var headers = NewHeaders();

            Assert.Throws <Http2Exception>(() => headers.Add(AsciiString.Of("Foo"), AsciiString.Of("foo")));
        }