Example #1
0
        public void Nginx_SingleRequest()
        {
            AssertNginxInPath();

            var nginx          = StartNginx("ServerConfigs/NginxBasicConfig.conf");
            var expectedResult = "Hello World!";

            var app = new FCGIApplication();

            app.OnRequestReceived += (sender, request) =>
            {
                request.WriteResponseASCII("HTTP/1.1 200 OK\nContent-Type:text/html\n\n" + expectedResult);
                request.Close();
            };

            var appThread = new Thread(() => {
                app.Run(19000);
            });

            appThread.Start();

            var result = GetHttp("http://localhost:8182");

            app.Stop();
            StopNginx(nginx);

            Assert.AreEqual(expectedResult, result);
        }
Example #2
0
        public void FCGIApp_GetValues()
        {
            var app = new FCGIApplication();

            // Connect to the app, impoersonating a webserver
            var inputStream = new MemoryStream();

            inputStream.Capacity = 4096;
            var outputStream = new MemoryStream();

            outputStream.Capacity = 4096;

            // Send a GetValues record
            var getValues = new Record
            {
                Type          = Record.RecordType.GetValues,
                RequestId     = 0,
                ContentLength = 0,
            };

            getValues.WriteToStream(inputStream);
            inputStream.Seek(0, SeekOrigin.Begin);
            app.ProcessStream(inputStream, outputStream);
            outputStream.Seek(0, SeekOrigin.Begin);

            // Now the app should respond with a GetValuesResult
            var response = Record.ReadRecord(outputStream);

            Assert.AreEqual(Record.RecordType.GetValuesResult, response.Type);
            Assert.AreEqual(0, response.RequestId);

            var responseValues = response.GetNameValuePairs();

            // Response should include these three values
            Assert.Contains("FCGI_MAX_CONNS", responseValues.Keys);
            Assert.Contains("FCGI_MAX_REQS", responseValues.Keys);
            Assert.Contains("FCGI_MPXS_CONNS", responseValues.Keys);

            // No other values should be included
            Assert.AreEqual(3, responseValues.Count);

            int responseMaxConns, responseMaxReqs, responseMultiplexing;

            // Make sure the returned values look plausible
            var sMaxConns     = Encoding.ASCII.GetString(responseValues["FCGI_MAX_CONNS"]);
            var sMaxReqs      = Encoding.ASCII.GetString(responseValues["FCGI_MAX_REQS"]);
            var sMultiplexing = Encoding.ASCII.GetString(responseValues["FCGI_MPXS_CONNS"]);

            Assert.IsTrue(int.TryParse(sMaxConns, out responseMaxConns));
            Assert.IsTrue(int.TryParse(sMaxReqs, out responseMaxReqs));
            Assert.IsTrue(int.TryParse(sMultiplexing, out responseMultiplexing));

            Assert.GreaterOrEqual(responseMaxConns, 0);
            Assert.GreaterOrEqual(responseMaxReqs, 0);
            Assert.GreaterOrEqual(responseMultiplexing, 0);
            Assert.LessOrEqual(responseMultiplexing, 1);
        }
Example #3
0
        public void FCGIApp_DisconnectedOperations()
        {
            // Create a new FCGIApplication without opening a connection
            // and make sure everything can be called without any problems
            var app = new FCGIApplication();

            Assert.IsFalse(app.Process());
            Assert.IsFalse(app.ProcessStream(new MemoryStream(), new MemoryStream()));
            Assert.IsFalse(app.ProcessSingleRecord(new MemoryStream(), new MemoryStream()));
            Assert.IsFalse(app.Connected);

            app.StopListening();
        }
Example #4
0
        public void Nginx_ManyRequests_Keepalive()
        {
            AssertNginxInPath();

            var nginx          = StartNginx("ServerConfigs/NginxKeepalive.conf");
            var expectedResult = "Hello World!";

            var app = new FCGIApplication();

            app.OnRequestReceived += (sender, request) =>
            {
                request.WriteResponseASCII("HTTP/1.1 200 OK\nContent-Type:text/html\n\n" + expectedResult);
                request.Close();
            };

            var appThread = new Thread(() => {
                app.Run(19000);
            });

            appThread.Start();

            Task <string>[] results = new Task <string> [500];

            for (int i = 0; i < results.Length; i++)
            {
                results[i] = GetHttpAsync("http://localhost:8182");
                Thread.Sleep(20);
            }

            // Count the number of correct results
            int successCount = 0;
            // We will allow 2% of errors
            int minimumSuccessCount = (int)(results.Length * 0.95);

            for (int i = 0; i < results.Length; i++)
            {
                results[i].Wait(20000);

                var result = results[i].Result;
                if (result == expectedResult)
                {
                    successCount++;
                }
            }

            Assert.GreaterOrEqual(successCount, minimumSuccessCount, "At least 95% of requests should be successful");

            StopNginx(nginx);
            app.Stop();
            appThread.Join(500);
        }
Example #5
0
        static void Main(string[] args)
        {
            // Create a new FCGIApplication, will accept FastCGI requests
            var app = new FCGIApplication();

            // Handle requests by responding with a 'Hello World' message
            app.OnRequestReceived += (sender, request) =>
            {
                request.WriteResponseASCII("HTTP/1.1 200 OK\nContent-Type:text/html\n\nHello World!");
                request.Close();
            };

            // Start listening on port 19000
            app.Run(19000);
        }
Example #6
0
        public void Nginx_ManyRequests_Keepalive()
        {
            AssertNginxInPath();

            var nginx          = StartNginx("ServerConfigs/NginxKeepalive.conf");
            var expectedResult = "Hello World!";

            var app = new FCGIApplication();

            app.OnRequestReceived += (sender, request) =>
            {
                request.WriteResponseASCII("HTTP/1.1 200 OK\nContent-Type:text/html\n\n" + expectedResult);
                request.Close();
            };

            var appThread = new Thread(() => {
                app.Run(19000);
            });

            appThread.Start();

            Task <string>[] results = new Task <string> [1000];

            for (int i = 0; i < results.Length; i++)
            {
                results[i] = GetHttpAsync("http://localhost:8182");
                Thread.Sleep(1);
            }

            for (int i = 0; i < results.Length; i++)
            {
                results[i].Wait(20000);
                var result = results[i].Result;
                Assert.AreEqual(expectedResult, result);
            }

            StopNginx(nginx);
            app.Stop();
            appThread.Join(500);
        }
Example #7
0
        static void Main(string[] args)
        {
            // Create a new FCGIApplication, will accept FastCGI requests
            var app = new FCGIApplication();

            // Handle requests by responding with a 'Hello World' message
            app.OnRequestReceived += (sender, request) =>
            {
                StringBuilder responseString = new StringBuilder();
                //responseString.AppendLine ( "HTTP/1.1" );
                responseString.AppendLine("Status: 200 OK");
                responseString.AppendLine("Content-Type: text/html");
                //responseString.AppendLine("charset=utf-8");
                //responseString.AppendLine();
                responseString.AppendLine();
                responseString.AppendLine("Hello World!");

                request.WriteResponseASCII(responseString.ToString());
                request.Close();
            };

            // Start listening on port 19000
            app.Run(19000);
        }
Example #8
0
        public void FCGIApp_Connections()
        {
            // Create an app that actually listens on the loopback interface
            var app = new FCGIApplication();

            app.Timeout = 100;

            try
            {
                app.Listen(new IPEndPoint(IPAddress.Loopback, 21511));
                Request receivedRequest = null;
                app.OnRequestReceived += (sender, request) => {
                    receivedRequest = request;
                    request.WriteResponseASCII("Hello Server!");
                    request.Close();
                };

                app.Process();

                var serverSocket = new Socket(SocketType.Stream, ProtocolType.Tcp);
                var asyncResult  = serverSocket.BeginConnect(new IPEndPoint(IPAddress.Loopback, 21511), (r) => { }, null);

                while (!asyncResult.IsCompleted)
                {
                    app.Process();
                }

                serverSocket.EndConnect(asyncResult);

                var serverStream = new NetworkStream(serverSocket);

                // Now send a request to the app and make sure it is received correctly.

                var requestId = 5172;

                var beginRequestContent = new byte[]
                {
                    0x00,                           // role byte 1
                    (byte)Constants.FCGI_RESPONDER, // role byte 2
                    0x00,                           // flags
                    0x00, 0x00, 0x00, 0x00, 0x00    // reserved bytes
                };

                var beginRequest = new Record
                {
                    Type          = Record.RecordType.BeginRequest,
                    RequestId     = requestId,
                    ContentLength = beginRequestContent.Length,
                    ContentData   = beginRequestContent
                };

                beginRequest.WriteToStream(serverStream);

                var stdinRequest = new Record
                {
                    Type          = Record.RecordType.Stdin,
                    RequestId     = requestId,
                    ContentLength = 0,
                    ContentData   = new byte[0]
                };

                stdinRequest.WriteToStream(serverStream);

                serverStream.Flush();

                // Make the app digest everything
                while (receivedRequest == null)
                {
                    app.Process();
                }


                // Do we have the correct request?
                Assert.AreEqual(requestId, receivedRequest.RequestId);

                // And did the response work?
                var responseRecord = Record.ReadRecord(serverStream);
                Assert.AreEqual(Record.RecordType.Stdout, responseRecord.Type);
                Assert.AreEqual("Hello Server!", Encoding.ASCII.GetString(responseRecord.ContentData));

                // Change the timeout while still connected
                app.Timeout = 100;

                app.StopListening();
                Assert.IsFalse(app.Connected);
            }
            // If the port is already in use, an execution can be thrown.
            // Report the test as inconclusive then.
            catch (SocketException e)
            {
                Assert.Inconclusive("SocketException: " + e.Message);
            }
        }
Example #9
0
        public void FCGIApp_Params()
        {
            var app = new FCGIApplication();

            Request receivedRequest = null;

            app.OnRequestReceived += (sender, request) =>
            {
                receivedRequest = request;
            };

            // Connect to the app, impoersonating a webserver
            var streamServerToApp = new MemoryStream();

            streamServerToApp.Capacity = 4096;
            var streamAppToServer = new MemoryStream();

            streamAppToServer.Capacity = 4096;

            // Send a request to it and make sure it responds to requests.

            var requestId = 5172;

            var beginRequestContent = new byte[]
            {
                0x00,                           // role byte 1
                (byte)Constants.FCGI_RESPONDER, // role byte 2
                Constants.FCGI_KEEP_CONN,       // flags
                0x00, 0x00, 0x00, 0x00, 0x00    // reserved bytes
            };

            var beginRequest = new Record
            {
                Type          = Record.RecordType.BeginRequest,
                RequestId     = requestId,
                ContentLength = beginRequestContent.Length,
                ContentData   = beginRequestContent
            };

            beginRequest.WriteToStream(streamServerToApp);

            var paramDict = new Dictionary <string, byte[]>
            {
                { "SOME_NAME", Encoding.UTF8.GetBytes("SOME_KEY") },
                { "SOME_OTHER_NAME", Encoding.UTF8.GetBytes("SOME_KEY") },
                //{"ONE_MEGABYTE_OF_ZEROS", new byte[1024 * 1024] },
                { "EMPTY_VALUE", new byte[0] },
                { "1", Encoding.UTF8.GetBytes("☕☳üß - \n \r\n .,;(){}%$!") },
                { "2", Encoding.UTF8.GetBytes("") },
                { "3", Encoding.UTF8.GetBytes(" ") },
                { "4", Encoding.UTF8.GetBytes("\n") },
                { "5", Encoding.UTF8.GetBytes(";") },
            };

            var paramsRequest = new Record
            {
                Type      = Record.RecordType.Params,
                RequestId = requestId
            };

            paramsRequest.SetNameValuePairs(paramDict);
            paramsRequest.WriteToStream(streamServerToApp);

            // Empty params record indicates that the parameters are fully transmitted
            var paramsCloseRequest = new Record
            {
                Type          = Record.RecordType.Params,
                RequestId     = requestId,
                ContentLength = 0,
                ContentData   = new byte[0]
            };

            paramsCloseRequest.WriteToStream(streamServerToApp);


            // Empty stdin indicates that the request is fully transmitted
            var stdinRequest = new Record
            {
                Type          = Record.RecordType.Stdin,
                RequestId     = requestId,
                ContentLength = 0,
                ContentData   = new byte[0]
            };

            stdinRequest.WriteToStream(streamServerToApp);

            streamServerToApp.Seek(0, SeekOrigin.Begin);

            app.ProcessStream(streamServerToApp, streamAppToServer);

            // Now the app should have received the request. Make sure the Parameters correctly decoded
            Assert.IsNotNull(receivedRequest);
            Assert.AreEqual(paramDict.Count, receivedRequest.Parameters.Count);

            foreach (var entry in paramDict)
            {
                Assert.Contains(entry.Key, receivedRequest.Parameters.Keys);
                Assert.AreEqual(entry.Value, receivedRequest.Parameters[entry.Key]);
            }
        }
Example #10
0
        public void FCGIApp_Request()
        {
            var app = new FCGIApplication();

            app.OnRequestReceived += (sender, request) =>
            {
                request.WriteResponseASCII("Hello!");
                request.Close();
            };

            // Connect to the app, impoersonating a webserver
            var streamServerToApp = new MemoryStream();

            streamServerToApp.Capacity = 4096;
            var streamAppToServer = new MemoryStream();

            streamAppToServer.Capacity = 4096;

            // Send a request to it and make sure it responds to requests.

            var requestId = 5172;

            var beginRequestContent = new byte[]
            {
                0x00,                           // role byte 1
                (byte)Constants.FCGI_RESPONDER, // role byte 2
                Constants.FCGI_KEEP_CONN,       // flags
                0x00, 0x00, 0x00, 0x00, 0x00    // reserved bytes
            };

            var beginRequest = new Record
            {
                Type          = Record.RecordType.BeginRequest,
                RequestId     = requestId,
                ContentLength = beginRequestContent.Length,
                ContentData   = beginRequestContent
            };

            beginRequest.WriteToStream(streamServerToApp);

            // Empty stdin indicates that the request is fully transmitted
            var stdinRequest = new Record
            {
                Type          = Record.RecordType.Stdin,
                RequestId     = requestId,
                ContentLength = 0,
                ContentData   = new byte[0]
            };

            stdinRequest.WriteToStream(streamServerToApp);

            streamServerToApp.Seek(0, SeekOrigin.Begin);

            app.ProcessStream(streamServerToApp, streamAppToServer);;

            streamAppToServer.Seek(0, SeekOrigin.Begin);

            // Now the app should respond with 'Hello!'

            var response = Record.ReadRecord(streamAppToServer);

            var expectedBytes = Encoding.ASCII.GetBytes("Hello!");

            Assert.AreEqual(Record.RecordType.Stdout, response.Type);
            Assert.AreEqual(requestId, response.RequestId);
            Assert.AreEqual(expectedBytes.Length, response.ContentLength);
            Assert.AreEqual(expectedBytes, response.ContentData);

            // Then, an empty stdout record should indicate the end of the response body
            response = Record.ReadRecord(streamAppToServer);
            Assert.AreEqual(Record.RecordType.Stdout, response.Type);
            Assert.AreEqual(requestId, response.RequestId);
            Assert.AreEqual(0, response.ContentLength);

            // And finally, a EndRequest record should close the request.
            response = Record.ReadRecord(streamAppToServer);
            Assert.AreEqual(Record.RecordType.EndRequest, response.Type);
            Assert.AreEqual(requestId, response.RequestId);
        }
Example #11
0
        public void FCGIApp_LargeRequest()
        {
            var app = new FCGIApplication();

            var expectedLength = 128317;

            app.OnRequestReceived += (sender, request) =>
            {
                var responseBody = new byte[expectedLength];
                request.WriteResponse(responseBody);
                request.Close();
            };

            // Connect to the app, impoersonating a webserver
            var inputStream = new MemoryStream();

            inputStream.Capacity = 4096;
            var outputStream = new MemoryStream();

            outputStream.Capacity = 4096 + expectedLength;

            // Send a request to it and make sure it responds to requests.

            var requestId = 5172;

            var beginRequestContent = new byte[]
            {
                0x00,                           // role byte 1
                (byte)Constants.FCGI_RESPONDER, // role byte 2
                Constants.FCGI_KEEP_CONN,       // flags
                0x00, 0x00, 0x00, 0x00, 0x00    // reserved bytes
            };

            var beginRequest = new Record
            {
                Type          = Record.RecordType.BeginRequest,
                RequestId     = requestId,
                ContentLength = beginRequestContent.Length,
                ContentData   = beginRequestContent
            };

            beginRequest.WriteToStream(inputStream);

            // Empty stdin indicates that the request is fully transmitted
            var stdinRequest = new Record
            {
                Type          = Record.RecordType.Stdin,
                RequestId     = requestId,
                ContentLength = 0,
                ContentData   = new byte[0]
            };

            stdinRequest.WriteToStream(inputStream);

            inputStream.Seek(0, SeekOrigin.Begin);

            app.ProcessStream(inputStream, outputStream);

            outputStream.Seek(0, SeekOrigin.Begin);

            // Now the app should respond with a large response, splitted into 64KB stdout records

            var response = Record.ReadRecord(outputStream);

            Assert.AreEqual(65535, response.ContentLength);

            var totalLength = 0;

            while (response.ContentLength > 0)
            {
                Assert.AreEqual(Record.RecordType.Stdout, response.Type);
                Assert.AreEqual(requestId, response.RequestId);

                totalLength += response.ContentLength;

                response = Record.ReadRecord(outputStream);
            }

            Assert.AreEqual(expectedLength, totalLength);

            // Then, an empty stdout record should indicate the end of the response body
            Assert.AreEqual(Record.RecordType.Stdout, response.Type);
            Assert.AreEqual(requestId, response.RequestId);
            Assert.AreEqual(0, response.ContentLength);

            // And finally, a EndRequest record should close the request.
            response = Record.ReadRecord(outputStream);
            Assert.AreEqual(Record.RecordType.EndRequest, response.Type);
            Assert.AreEqual(requestId, response.RequestId);
        }