Exemplo n.º 1
0
        public void HeadersParsing()
        {
            const string request = "GET / HTTP/1.1\r\n" +
                                   "Host: localhost:80\r\n" +
                                   "User-Agent: xunit\r\n" +
                                   "Connection: close\r\n" +
                                   "X-Multiple-Header: value1, value2\r\n" +
                                   "\r\n"; // five lines total

            byte[] requestBytes = Encoding.UTF8.GetBytes(request);
            int    position     = 0;

            using (var stream = new MemoryStream())
            {
                stream.Write(requestBytes, 0, requestBytes.Length);

                stream.Seek(0, SeekOrigin.Begin);
                var rawHeaders = Http11Helper.ReadHeaders(stream);

                Assert.Equal(rawHeaders.Length, 5);

                string[] splittedRequestString = rawHeaders[0].Split(' ');
                Assert.Equal(splittedRequestString[0], "GET");
                Assert.Equal(splittedRequestString[1], "/");
                Assert.Equal(splittedRequestString[2], "HTTP/1.1");

                var headers = Http11Helper.ParseHeaders(rawHeaders.Skip(1).ToArray());
                Assert.Equal(headers.Count, 4);
                Assert.Contains("Host", headers.Keys);
                Assert.Contains("User-Agent", headers.Keys);
                Assert.Contains("Connection", headers.Keys);
                Assert.Contains("X-Multiple-Header", headers.Keys);

                Assert.Equal(headers["Host"].Length, 1);
                Assert.Equal(headers["User-Agent"].Length, 1);
                Assert.Equal(headers["Connection"].Length, 1);
                Assert.Equal(headers["X-Multiple-Header"].Length, 2);

                Assert.Equal(headers["Host"][0], "localhost:80");
                Assert.Equal(headers["User-Agent"][0], "xunit");
                Assert.Equal(headers["Connection"][0], "close");
                Assert.Equal(headers["X-Multiple-Header"][0], "value1");
                Assert.Equal(headers["X-Multiple-Header"][1], "value2");
            }
        }
Exemplo n.º 2
0
        public void ResponseSentCorrect()
        {
            var headers = new Dictionary <string, string[]>
            {
                { "Connection", new[] { "close" } },
                { "Content-Type", new [] { "text/plain" } }
            };
            const string dataString = "test";

            byte[] data = Encoding.UTF8.GetBytes(dataString);

            using (var stream = new MemoryStream())
            {
                Http11Helper.SendResponse(stream, data, StatusCode.Code200Ok, headers);
                stream.Seek(0, SeekOrigin.Begin);
                string[] splittedResponse = Http11Helper.ReadHeaders(stream);

                byte[] response = new byte[data.Length];//test - 4 bytes
                int    read     = stream.Read(response, 0, response.Length);

                //Need to loop here... 4 bytes only - let's think that C# is in the good mood today. :-)
                Assert.Equal(read, response.Length);

                // let count number of items:
                // response string
                // Connection header
                // Content-Type header
                // Content-Length header
                // delimiter between headers and body - empty string
                // lines in response body
                Assert.Contains("HTTP/1.1", splittedResponse[0]);
                Assert.Contains(StatusCode.Code200Ok.ToString(CultureInfo.InvariantCulture), splittedResponse[0]);
                Assert.Contains(StatusCode.Reason200Ok, splittedResponse[0]);

                Assert.Contains("Connection: close", splittedResponse);
                Assert.Contains("Content-Type: " + "text/plain", splittedResponse);
                Assert.Contains("Content-Length: " + data.Length, splittedResponse);

                Assert.Equal(read, data.Length);
            }
        }
Exemplo n.º 3
0
        public void UpgradeByHttp11()
        {
            var requestStr = ConfigurationManager.AppSettings["smallTestFile"];
            Uri uri;

            Uri.TryCreate(ConfigurationManager.AppSettings["unsecureAddress"] + requestStr, UriKind.Absolute, out uri);

            bool finalFrameReceived            = false;
            var  responseBody                  = new StringBuilder();
            var  finalFrameReceivedRaisedEvent = new ManualResetEvent(false);

            var clientStream = TestHelpers.GetHandshakedStream(uri);

            var mockedAdapter = new Mock <Http2ClientMessageHandler>(clientStream, ConnectionEnd.Client,
                                                                     clientStream is SslStream,
                                                                     new CancellationToken())
            {
                CallBase = true
            };

            var adapter = mockedAdapter.Object;

            mockedAdapter.Protected().Setup("ProcessIncomingData", ItExpr.IsAny <Http2Stream>(), ItExpr.IsAny <Frame>())
            .Callback <Http2Stream, Frame>((stream, frame) =>
            {
                bool isFin;
                do
                {
                    var dataFrame = frame as DataFrame;
                    responseBody.Append(Encoding.UTF8.GetString(
                                            dataFrame.Payload.Array.Skip(dataFrame.Payload.Offset)
                                            .Take(dataFrame.Payload.Count)
                                            .ToArray()));
                    isFin = dataFrame.IsEndStream;
                } while (!isFin && stream.ReceivedDataAmount > 0);
                if (isFin)
                {
                    finalFrameReceived = true;
                    finalFrameReceivedRaisedEvent.Set();
                }
            });

            // process http/1.1 headers
            var http11Headers = "GET " + uri.AbsolutePath + " HTTP/1.1\r\n" +
                                "Host: " + uri.Host + "\r\n" +
                                "Connection: Upgrade, HTTP2-Settings\r\n" +
                                "Upgrade: " + Protocols.Http2NoTls + "\r\n" +
                                "HTTP2-Settings: \r\n" + // TODO send any valid settings
                                "\r\n";

            clientStream.Write(Encoding.UTF8.GetBytes(http11Headers));
            clientStream.Flush();

            try
            {
                var response = Http11Helper.ReadHeaders(clientStream);
                Assert.Equal(
                    "HTTP/1.1 " + StatusCode.Code101SwitchingProtocols + " " + StatusCode.Reason101SwitchingProtocols,
                    response[0]);
                var headers = Http11Helper.ParseHeaders(response.Skip(1));
                Assert.Contains("Connection", headers.Keys);
                Assert.Equal("Upgrade", headers["Connection"][0]);
                Assert.Contains("Upgrade", headers.Keys);
                Assert.Equal(Protocols.Http2NoTls, headers["Upgrade"][0]);

                adapter.StartSessionAsync();

                // there are http2 frames after upgrade headers - we don't need to send request explicitly
                finalFrameReceivedRaisedEvent.WaitOne(10000);

                Assert.True(finalFrameReceived);
                Assert.Equal(TestHelpers.FileContentSimpleTest, responseBody.ToString());
            }
            finally
            {
                adapter.Dispose();
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Processes incoming request.
        /// </summary>
        public async void ProcessRequest()
        {
            try
            {
                // invalid connection, skip
                if (!_client.CanRead)
                {
                    return;
                }

                var rawHeaders = Http11Helper.ReadHeaders(_client);

                Http2Logger.LogDebug("Http1.1 Protocol Handler. Process request " + string.Join(" ", rawHeaders));

                // invalid connection, skip
                if (rawHeaders == null || rawHeaders.Length == 0)
                {
                    return;
                }

                // headers[0] contains METHOD, URI and VERSION like "GET /api/values/1 HTTP/1.1"
                var headers = Http11Helper.ParseHeaders(rawHeaders.Skip(1).ToArray());

                // client MUST include Host header due to HTTP/1.1 spec
                if (!headers.ContainsKey("Host"))
                {
                    throw new ApplicationException("Host header is missing");
                }

                // parse request parameters: method, path, host, etc
                var splittedRequestString = rawHeaders[0].Split(' ');
                var method = splittedRequestString[0];

                if (!IsMethodSupported(method))
                {
                    throw new NotSupportedException(method + " method is not currently supported via HTTP/1.1");
                }

                var scheme = _protocol == SslProtocols.None ? Uri.UriSchemeHttp : Uri.UriSchemeHttps;

                var path = splittedRequestString[1];

                // main OWIN environment components
                // OWIN request and response below shares the same environment dictionary instance
                _environment = CreateOwinEnvironment(method, scheme, "", path, headers);
                _request     = new OwinRequest(_environment);
                _response    = new OwinResponse(_environment);

                // we may need to populate additional fields if request supports UPGRADE
                AddOpaqueUpgradeIfNeeded();

                await _next.Invoke(new OwinContext(_environment));

                if (_opaqueCallback == null)
                {
                    EndResponse();
                }
                else
                {
                    // do not close connection
                    EndResponse(false);

                    var opaqueEnvironment = CreateOpaqueEnvironment();
                    await _opaqueCallback(new OwinContext(opaqueEnvironment));
                }
            }
            catch (Exception ex)
            {
                Http2Logger.LogError(ex.Message);
                EndResponse(ex);
                Http2Logger.LogDebug("Closing connection");
                _client.Close();
            }
        }