private async Task handleHttpSessionRequest(TcpServerConnection connection, SessionEventArgs args)
        {
            var cancellationToken = args.CancellationTokenSource.Token;
            var request           = args.HttpClient.Request;

            request.Locked = true;

            var body = request.CompressBodyAndUpdateContentLength();

            // set the connection and send request headers
            args.HttpClient.SetConnection(connection);
            await args.HttpClient.SendRequest(Enable100ContinueBehaviour, args.IsTransparent,
                                              cancellationToken);

            // If a successful 100 continue request was made, inform that to the client and reset response
            if (request.ExpectationSucceeded)
            {
                var clientStreamWriter = args.ProxyClient.ClientStreamWriter;
                var response           = args.HttpClient.Response;

                var headerBuilder = new HeaderBuilder();
                headerBuilder.WriteResponseLine(response.HttpVersion, response.StatusCode, response.StatusDescription);
                headerBuilder.WriteHeaders(response.Headers);
                await clientStreamWriter.WriteHeadersAsync(headerBuilder, cancellationToken);

                await args.ClearResponse(cancellationToken);
            }

            // send body to server if available
            if (request.HasBody)
            {
                if (request.IsBodyRead)
                {
                    var writer = args.HttpClient.Connection.StreamWriter;
                    await writer.WriteBodyAsync(body !, request.IsChunked, cancellationToken);
                }
                else if (!request.ExpectationFailed)
                {
                    // get the request body unless an unsuccessful 100 continue request was made
                    HttpWriter writer = args.HttpClient.Connection.StreamWriter !;
                    await args.CopyRequestBodyAsync(writer, TransformationMode.None, cancellationToken);
                }
            }

            args.TimeLine["Request Sent"] = DateTime.Now;

            // parse and send response
            await handleHttpSessionResponse(args);
        }
        /// <summary>
        ///     Handle a specific session (request/response sequence)
        /// </summary>
        /// <param name="serverConnection">The tcp connection.</param>
        /// <param name="args">The session event arguments.</param>
        /// <returns></returns>
        private async Task HandleHttpSessionRequestInternal(TcpServerConnection serverConnection, SessionEventArgs args)
        {
            try
            {
                var cancellationToken = args.CancellationTokenSource.Token;
                var request           = args.WebSession.Request;
                request.Locked = true;

                var body = request.CompressBodyAndUpdateContentLength();

                // if expect continue is enabled then send the headers first
                // and see if server would return 100 conitinue
                if (request.ExpectContinue)
                {
                    args.WebSession.SetConnection(serverConnection);
                    await args.WebSession.SendRequest(Enable100ContinueBehaviour, args.IsTransparent,
                                                      cancellationToken);
                }

                // If 100 continue was the response inform that to the client
                if (Enable100ContinueBehaviour)
                {
                    var clientStreamWriter = args.ProxyClient.ClientStreamWriter;

                    if (request.Is100Continue)
                    {
                        await clientStreamWriter.WriteResponseStatusAsync(args.WebSession.Response.HttpVersion,
                                                                          (int)HttpStatusCode.Continue, "Continue", cancellationToken);

                        await clientStreamWriter.WriteLineAsync(cancellationToken);
                    }
                    else if (request.ExpectationFailed)
                    {
                        await clientStreamWriter.WriteResponseStatusAsync(args.WebSession.Response.HttpVersion,
                                                                          (int)HttpStatusCode.ExpectationFailed, "Expectation Failed", cancellationToken);

                        await clientStreamWriter.WriteLineAsync(cancellationToken);
                    }
                }

                // If expect continue is not enabled then set the connectio and send request headers
                if (!request.ExpectContinue)
                {
                    args.WebSession.SetConnection(serverConnection);
                    await args.WebSession.SendRequest(Enable100ContinueBehaviour, args.IsTransparent,
                                                      cancellationToken);
                }

                // check if content-length is > 0
                if (request.ContentLength > 0)
                {
                    if (request.IsBodyRead)
                    {
                        var writer = args.WebSession.ServerConnection.StreamWriter;
                        await writer.WriteBodyAsync(body, request.IsChunked, cancellationToken);
                    }
                    else
                    {
                        if (!request.ExpectationFailed)
                        {
                            if (request.HasBody)
                            {
                                HttpWriter writer = args.WebSession.ServerConnection.StreamWriter;
                                await args.CopyRequestBodyAsync(writer, TransformationMode.None, cancellationToken);
                            }
                        }
                    }
                }

                // If not expectation failed response was returned by server then parse response
                if (!request.ExpectationFailed)
                {
                    await HandleHttpSessionResponse(args);
                }
            }
            catch (Exception e) when(!(e is ProxyHttpException))
            {
                throw new ProxyHttpException("Error occured whilst handling session request (internal)", e, args);
            }
        }
        /// <summary>
        /// Handle a specific session (request/response sequence)
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="args"></param>
        /// <returns>True if close the connection</returns>
        private async Task HandleHttpSessionRequestInternal(TcpConnection connection, SessionEventArgs args)
        {
            try
            {
                var request = args.WebSession.Request;
                request.RequestLocked = true;

                //if expect continue is enabled then send the headers first
                //and see if server would return 100 conitinue
                if (request.ExpectContinue)
                {
                    args.WebSession.SetConnection(connection);
                    await args.WebSession.SendRequest(Enable100ContinueBehaviour, args.IsTransparent);
                }

                //If 100 continue was the response inform that to the client
                if (Enable100ContinueBehaviour)
                {
                    var clientStreamWriter = args.ProxyClient.ClientStreamWriter;

                    if (request.Is100Continue)
                    {
                        await clientStreamWriter.WriteResponseStatusAsync(args.WebSession.Response.HttpVersion, (int)HttpStatusCode.Continue, "Continue");

                        await clientStreamWriter.WriteLineAsync();
                    }
                    else if (request.ExpectationFailed)
                    {
                        await clientStreamWriter.WriteResponseStatusAsync(args.WebSession.Response.HttpVersion, (int)HttpStatusCode.ExpectationFailed, "Expectation Failed");

                        await clientStreamWriter.WriteLineAsync();
                    }
                }

                //If expect continue is not enabled then set the connectio and send request headers
                if (!request.ExpectContinue)
                {
                    args.WebSession.SetConnection(connection);
                    await args.WebSession.SendRequest(Enable100ContinueBehaviour, args.IsTransparent);
                }

                //check if content-length is > 0
                if (request.ContentLength > 0)
                {
                    //If request was modified by user
                    if (request.IsBodyRead)
                    {
                        if (request.ContentEncoding != null)
                        {
                            request.Body = await GetCompressedResponseBody(request.ContentEncoding, request.Body);
                        }

                        var body = request.Body;

                        //chunked send is not supported as of now
                        request.ContentLength = body.Length;

                        await args.WebSession.ServerConnection.StreamWriter.WriteAsync(body);
                    }
                    else
                    {
                        if (!request.ExpectationFailed)
                        {
                            //If its a post/put/patch request, then read the client html body and send it to server
                            if (request.HasBody)
                            {
                                HttpWriter writer = args.WebSession.ServerConnection.StreamWriter;
                                await args.CopyRequestBodyAsync(writer, false);
                            }
                        }
                    }
                }

                //If not expectation failed response was returned by server then parse response
                if (!request.ExpectationFailed)
                {
                    await HandleHttpSessionResponse(args);
                }
            }
            catch (Exception e) when(!(e is ProxyHttpException))
            {
                throw new ProxyHttpException("Error occured whilst handling session request (internal)", e, args);
            }
        }