示例#1
0
        static void Main(string[] args)
        {
            new Program().New();

            if (false)
            {
                ParseHttpSSE2_Try2(s_buffer, true, r =>
                {
                    string s = Encoding.ASCII.GetString(s_buffer.AsSpan(r));
                    Console.WriteLine($"{r} -> {s}");
                });
            }

            if (false)
            {
                var reader = new HttpHeaderReader(s_buffer, true);

                while (reader.TryParse())
                {
                    Range r = reader.Range;

                    string s = Encoding.ASCII.GetString(s_buffer.AsSpan(r));
                    Console.WriteLine($"{r} -> {s}");
                }
            }

            if (false)
            {
                BenchmarkRunner.Run <Program>();
            }
        }
示例#2
0
        public void New()
        {
            var reader = new HttpHeaderReader(s_buffer, true);

            while (reader.TryParse())
            {
                // do nothing.
            }
        }
示例#3
0
        public void ShouldReadFirstNotEmptyLine()
        {
            var reader = new HttpHeaderReader(new StringReader(
                                                  new StringBuilder(String.Empty)
                                                  .AppendLine()
                                                  .AppendLine()
                                                  .AppendLine()
                                                  .AppendLine("HTTP/1.1 200 OK")
                                                  .ToString()
                                                  ));

            Assert.That(reader.ReadFirstLine(), Is.EqualTo("HTTP/1.1 200 OK"));
        }
        /// <summary>
        /// Handles the OnResponseReceived for the proxy, which occurs after the response is
        /// received from the web server, but before it is forwarded on to the browser.
        /// </summary>
        /// <param name="context">A <see cref="BenderProxy.ProcessingContext"/> object.</param>
        public override void OnResponseReceived(ProcessingContext context)
        {
            // These are valid credentials for the Basic case.
            string userName = "******";
            string password = "******";

            // Only do any processing on the response if the response is 401,
            // or "Unauthorized".
            if (context.ResponseHeader != null && context.ResponseHeader.StatusCode == 401)
            {
                // Read the headers from the response and finish reading the response
                // body, if any.
                Console.WriteLine("Received 401 - Unauthorized response");
                context.ServerStream.ReadTimeout  = 5000;
                context.ServerStream.WriteTimeout = 5000;
                StreamReader     reader       = new StreamReader(context.ServerStream);
                HttpHeaderReader headerReader = new HttpHeaderReader(reader);
                if (context.ResponseHeader.EntityHeaders.ContentLength != 0)
                {
                    string drainBody = ReadFromStream(reader);
                }

                // We do not want the proxy to do any further processing after
                // handling this message.
                context.StopProcessing();

                // Read the WWW-Authenticate header. Because of the way the test
                // web app is configured, it returns multiple headers, with
                // different schemes. We need to select the correct one.
                string authHeader = GetAuthenticationHeader(context.ResponseHeader.WWWAuthenticate, BasicGenerator.AuthorizationHeaderMarker);
                Console.WriteLine("Processing WWW-Authenticate header: {0}", authHeader);

                // Calculate the value for the Authorization header, and resend
                // the request (with the Authorization header) to the server
                // using BenderProxy's HttpMessageWriter.
                Console.WriteLine("Generating authorization header value for user name '{0}' and password '{1}'", userName, password);
                BasicGenerator generator = new BasicGenerator(userName, password, authHeader);
                string         authorizationHeaderValue = generator.GenerateAuthorizationHeader();
                Console.WriteLine("Resending request with Authorization header: {0}", authorizationHeaderValue);
                context.RequestHeader.Authorization = authorizationHeaderValue;
                HttpMessageWriter writer = new HttpMessageWriter(context.ServerStream);
                writer.Write(context.RequestHeader);

                // Get the authorized response, and forward it on to the browser, using
                // BenderProxy's HttpHeaderReader and support classes.
                HttpResponseHeader header     = new HttpResponseHeader(headerReader.ReadHttpMessageHeader());
                string             body       = ReadFromStream(reader);
                Stream             bodyStream = new MemoryStream(Encoding.UTF8.GetBytes(body));
                new HttpResponseWriter(context.ClientStream).Write(header, bodyStream, bodyStream.Length);
            }
        }
示例#5
0
        /// <summary>
        ///     Read <see cref="ProcessingContext.RequestHeader" /> from <see cref="ProcessingContext.ClientStream" />.
        ///     <see cref="ProcessingContext.ClientStream" /> should be defined at this point.
        /// </summary>
        /// <param name="context">current request context</param>
        protected virtual void ReceiveRequest(ProcessingContext context)
        {
            ContractUtils.Requires <ArgumentNullException>(context != null, "context");
            ContractUtils.Requires <InvalidContextException>(context.ClientStream != null, "ClientStream");

            var headerReader = new HttpHeaderReader(new PlainStreamReader(context.ClientStream));

            headerReader.Log += this.OnComponentLog;

            try
            {
                context.RequestHeader = new HttpRequestHeader(headerReader.ReadHttpMessageHeader());

                OnLog(LogLevel.Debug, "Request Received. {0}", TraceUtils.GetHttpTrace(context.RequestHeader));

                if (context.RequestHeader.Headers.Contains(GeneralHeaders.ProxyConnectionHeader))
                {
                    context.RequestHeader.Headers.Remove(GeneralHeaders.ProxyConnectionHeader);
                }

                if (!EnableKeepAlive)
                {
                    context.RequestHeader.GeneralHeaders.Connection = "close";
                }
            }
            catch (IOException ex)
            {
                if (ex.IsSocketException(SocketError.OperationAborted, SocketError.ConnectionReset))
                {
                    OnLog(LogLevel.Warn, "Request was terminated by client. {0}", TraceUtils.GetHttpTrace(context.RequestHeader));
                }
                else if (ex is EndOfStreamException)
                {
                    OnLog(LogLevel.Error, "Failed to read request. {0}", TraceUtils.GetHttpTrace(context.RequestHeader));
                }
                else if (ex.IsSocketException(SocketError.TimedOut))
                {
                    OnLog(LogLevel.Warn, "Client request time out. {0}", TraceUtils.GetHttpTrace(context.RequestHeader));
                }
                else
                {
                    throw;
                }

                context.StopProcessing();
            }
        }
示例#6
0
        public void ShouldReadHttpHeaders()
        {
            var reader = new HttpHeaderReader(new StringReader(
                                                  new StringBuilder(String.Empty)
                                                  .AppendLine("Cache-Control:private")
                                                  .AppendLine("Content-Encoding:gzip")
                                                  .AppendLine("Content-Length:27046")
                                                  .AppendLine()
                                                  .ToString()
                                                  ));

            Assert.That(reader.ReadHeaders(), Is.EqualTo(new List <String>
            {
                "Cache-Control:private",
                "Content-Encoding:gzip",
                "Content-Length:27046"
            }));
        }
示例#7
0
        public void ShouldReadHttpMessageHeader()
        {
            var reader = new HttpHeaderReader(new StringReader(
                                                  new StringBuilder("HTTP/1.1 200 OK")
                                                  .AppendLine()
                                                  .AppendLine("Cache-Control:private")
                                                  .AppendLine("Content-Encoding:gzip")
                                                  .AppendLine("Content-Length:27046")
                                                  .AppendLine()
                                                  .ToString()
                                                  ));

            var header = reader.ReadHttpMessageHeader();

            Assert.That(header.StartLine, Is.EqualTo("HTTP/1.1 200 OK"));
            Assert.That(header.GeneralHeaders.CacheControl, Is.EqualTo("private"));
            Assert.That(header.EntityHeaders.ContentEncoding, Is.EqualTo("gzip"));
            Assert.That(header.EntityHeaders.ContentLength, Is.EqualTo(27046));
        }
示例#8
0
        /// <summary>
        ///     Copy chunked message body to <see cref="OutputStream" /> from given stream
        /// </summary>
        /// <param name="body">chunked HTTP message body</param>
        protected virtual void CopyChunkedMessageBody(Stream body)
        {
            var reader = new HttpHeaderReader(new PlainStreamReader(body));

            var writer = new StreamWriter(OutputStream, Encoding.ASCII);

            for (var size = reader.ReadNextChunkSize(); size != 0; size = reader.ReadNextChunkSize())
            {
                writer.WriteLine(size.ToString("X"));
                writer.Flush();

                CopyPlainMessageBody(body, size);

                writer.WriteLine();
                writer.Flush();
            }

            writer.WriteLine("0");
            writer.Flush();
        }
示例#9
0
        /// <summary>
        ///     Send <see cref="ProcessingContext.RequestHeader" /> to server,
        ///     copy rest of the <see cref="ProcessingContext.ClientStream" /> to <see cref="ProcessingContext.ServerStream" />
        ///     and read <see cref="ProcessingContext.ResponseHeader" /> from <see cref="ProcessingContext.ServerStream" />.
        ///     Expects <see cref="ProcessingContext.ServerStream" />, <see cref="ProcessingContext.RequestHeader" /> and
        ///     <see cref="ProcessingContext.ClientStream" /> to be defined.
        /// </summary>
        /// <param name="context">current request context</param>
        protected virtual void ReceiveResponse(ProcessingContext context)
        {
            ContractUtils.Requires <ArgumentNullException>(context != null, "context");
            ContractUtils.Requires <InvalidContextException>(context.ServerStream != null, "ServerStream");
            ContractUtils.Requires <InvalidContextException>(context.RequestHeader != null, "RequestHeader");
            ContractUtils.Requires <InvalidContextException>(context.ClientStream != null, "ClientStream");
            ContractUtils.Requires <InvalidContextException>(context.ClientSocket != null, "ClientSocket");

            var requestWriter = new HttpMessageWriter(context.ServerStream);

            requestWriter.Log += this.OnComponentLog;

            var responseReader = new HttpHeaderReader(new PlainStreamReader(context.ServerStream));

            responseReader.Log += this.OnComponentLog;

            try
            {
                requestWriter.Write(context.RequestHeader, context.ClientStream, context.ClientSocket.Available);
                context.ResponseHeader = new HttpResponseHeader(responseReader.ReadHttpMessageHeader());

                OnLog(LogLevel.Debug, "Response Received: {0}", TraceUtils.GetHttpTrace(context.ResponseHeader));
            }
            catch (IOException ex)
            {
                var responseWriter = new HttpResponseWriter(context.ClientStream);

                if (ex.IsSocketException(SocketError.TimedOut))
                {
                    OnLog(LogLevel.Warn, "Request to remote server has timed out. {0}", TraceUtils.GetHttpTrace(context.RequestHeader));

                    responseWriter.WriteGatewayTimeout();
                }
                else
                {
                    throw;
                }

                context.StopProcessing();
            }
        }
        private void ProcessResponse(ProcessingContext context)
        {
            // Only do any processing on the response if the response is 401,
            // or "Unauthorized".
            if (context.ResponseHeader != null && context.ResponseHeader.StatusCode == 401)
            {
                //context.ServerStream.ReadTimeout = 5000;
                //context.ServerStream.WriteTimeout = 5000;
                var reader = new StreamReader(context.ServerStream);
                if (context.ResponseHeader.EntityHeaders.ContentLength != 0)
                {
                    ReadFromStream(reader);
                }
                // We do not want the proxy to do any further processing after
                // handling this message.
                context.StopProcessing();


                if (context.ResponseHeader.WWWAuthenticate.Contains(BasicGenerator.AuthorizationHeaderMarker))
                {
                    // This is the generation of the HTTP Basic authorization header value.
                    var basicAuthHeaderValue = $"user:pass";
                    var encodedHeaderValue   = Convert.ToBase64String(Encoding.ASCII.GetBytes(basicAuthHeaderValue));
                    context.RequestHeader.Authorization = "Basic " + encodedHeaderValue;

                    // Resend the request (with the Authorization header) to the server
                    // using BenderProxy's HttpMessageWriter.
                    var writer = new HttpMessageWriter(context.ServerStream);
                    writer.Write(context.RequestHeader);

                    // Get the authorized response, and forward it on to the browser, using
                    // BenderProxy's HttpHeaderReader and support classes.
                    var    headerReader = new HttpHeaderReader(reader);
                    var    header       = new HttpResponseHeader(headerReader.ReadHttpMessageHeader());
                    var    body         = ReadFromStream(reader);
                    Stream bodyStream   = new MemoryStream(Encoding.UTF8.GetBytes(body));
                    new HttpResponseWriter(context.ClientStream).Write(header, bodyStream, bodyStream.Length);
                }
                else if (context.ResponseHeader.WWWAuthenticate.Contains(NtlmGenerator.AuthorizationHeaderMarker))
                {
                    // Read the WWW-Authenticate header. Because of the way the test
                    // web app is configured, it returns multiple headers, with
                    // different schemes. We need to select the correct one.
                    var authHeader = GetAuthenticationHeader(context.ResponseHeader.WWWAuthenticate,
                                                             NtlmGenerator.AuthorizationHeaderMarker);

                    var type1            = new NtlmNegotiateMessageGenerator();
                    var type1HeaderValue = type1.GenerateAuthorizationHeader();
                    context.RequestHeader.Authorization = type1HeaderValue;
                    var writer = new HttpMessageWriter(context.ServerStream);
                    writer.Write(context.RequestHeader);

                    var headerReader        = new HttpHeaderReader(reader);
                    var challengeHeader     = new HttpResponseHeader(headerReader.ReadHttpMessageHeader());
                    var challengeAuthHeader = challengeHeader.WWWAuthenticate;
                    var challengeBody       = ReadFromStream(reader);

                    if (!string.IsNullOrEmpty(challengeAuthHeader) &&
                        challengeAuthHeader.StartsWith(NtlmGenerator.AuthorizationHeaderMarker))
                    {
                        // If a proper message was received (the "type 2" or "Challenge" message),
                        // parse it, and generate the proper authentication header (the "type 3"
                        // or "Authorization" message).
                        var type2            = new NtlmChallengeMessageGenerator(challengeAuthHeader);
                        var type3            = new NtlmAuthenticateMessageGenerator(null, null, "user", "pass", type2);
                        var type3HeaderValue = type3.GenerateAuthorizationHeader();
                        context.RequestHeader.Authorization = type3HeaderValue;
                        writer.Write(context.RequestHeader);

                        // Get the authorized response from the server, and forward it on to
                        // the browser.
                        var    header     = new HttpResponseHeader(headerReader.ReadHttpMessageHeader());
                        var    body       = ReadFromStream(reader);
                        Stream bodyStream = new MemoryStream(Encoding.UTF8.GetBytes(body));
                        new HttpResponseWriter(context.ClientStream).Write(header, bodyStream, bodyStream.Length);
                        context.ClientStream.Flush();
                    }
                }
            }
        }
 public Peticion(TcpClient cliente)
 {
     this.cliente = cliente;
     r            = new HttpHeaderReader(cliente);
     w            = new HttpFileWriter(cliente);
 }
示例#12
0
        /// <summary>
        /// Handles the OnResponseReceived for the proxy, which occurs after the response is
        /// received from the web server, but before it is forwarded on to the browser.
        /// </summary>
        /// <param name="context">A <see cref="BenderProxy.ProcessingContext"/> object.</param>
        public override void OnResponseReceived(ProcessingContext context)
        {
            string userName = "******";
            string password = "******";

            if (context.ResponseHeader != null && context.ResponseHeader.StatusCode == 401)
            {
                // Only process requests for localhost or the redirected-
                // via-hosts-file-entry host, and where NTLM auth is requested.
                List <string> candidateUrls = new List <string>()
                {
                    string.Format("localhost:{0}", TestWebAppPort), string.Format("{0}:{1}", TestWebAppHostName, TestWebAppPort)
                };
                if (candidateUrls.Contains(context.RequestHeader.Host) && context.ResponseHeader.WWWAuthenticate != null && context.ResponseHeader.WWWAuthenticate.Contains(NtlmGenerator.AuthorizationHeaderMarker))
                {
                    // Read the headers from the response and finish reading the response
                    // body, if any.
                    Console.WriteLine("Received 401 - Unauthorized response");
                    context.ServerStream.ReadTimeout  = 5000;
                    context.ServerStream.WriteTimeout = 5000;
                    StreamReader reader = new StreamReader(context.ServerStream);
                    if (context.ResponseHeader.EntityHeaders.ContentLength != 0)
                    {
                        string drainBody = ReadFromStream(reader);
                    }

                    // We do not want the proxy to do any further processing after
                    // handling this message.
                    context.StopProcessing();

                    // Read the WWW-Authenticate header. Because of the way the test
                    // web app is configured, it returns multiple headers, with
                    // different schemes. We need to select the correct one.
                    string authHeader = GetAuthenticationHeader(context.ResponseHeader.WWWAuthenticate, NtlmGenerator.AuthorizationHeaderMarker);
                    Console.WriteLine("Processing WWW-Authenticate header: {0}", authHeader);

                    // Generate the initial message (the "type 1" or "Negotiation" message")
                    // and get the response, using BenderProxy's HttpMessageWriter and
                    // HttpHeaderReader and support classes.
                    Console.WriteLine("Generating authorization header value for Negotiate ('Type 1') message");
                    NtlmNegotiateMessageGenerator type1 = new NtlmNegotiateMessageGenerator();
                    string type1HeaderValue             = type1.GenerateAuthorizationHeader();
                    context.RequestHeader.Authorization = type1HeaderValue;
                    Console.WriteLine("Resending request with Authorization header: {0}", type1HeaderValue);
                    HttpMessageWriter writer = new HttpMessageWriter(context.ServerStream);
                    writer.Write(context.RequestHeader);

                    HttpHeaderReader   headerReader        = new HttpHeaderReader(reader);
                    HttpResponseHeader challengeHeader     = new HttpResponseHeader(headerReader.ReadHttpMessageHeader());
                    string             challengeAuthHeader = challengeHeader.WWWAuthenticate;
                    string             challengeBody       = ReadFromStream(reader);

                    if (!string.IsNullOrEmpty(challengeAuthHeader) && challengeAuthHeader.StartsWith(NtlmGenerator.AuthorizationHeaderMarker))
                    {
                        // If a proper message was received (the "type 2" or "Challenge" message),
                        // parse it, and generate the proper authentication header (the "type 3"
                        // or "Authorization" message).
                        Console.WriteLine("Received 401 response with Challenge ('Type 2') message: {0}", challengeAuthHeader);
                        NtlmChallengeMessageGenerator type2 = new NtlmChallengeMessageGenerator(challengeAuthHeader);
                        Console.WriteLine("Generating Authorization ('Type 3') message for user name '{0}' and password '{1}'", userName, password);
                        NtlmAuthenticateMessageGenerator type3 = new NtlmAuthenticateMessageGenerator(null, null, userName, password, type2);
                        string type3HeaderValue = type3.GenerateAuthorizationHeader();
                        Console.WriteLine("Resending request with Authorization header: {0}", type3HeaderValue);
                        context.RequestHeader.Authorization = type3HeaderValue;
                        writer.Write(context.RequestHeader);

                        // Get the authorized response from the server, and forward it on to
                        // the browser.
                        HttpResponseHeader header     = new HttpResponseHeader(headerReader.ReadHttpMessageHeader());
                        string             body       = ReadFromStream(reader);
                        Stream             bodyStream = new MemoryStream(Encoding.UTF8.GetBytes(body));
                        new HttpResponseWriter(context.ClientStream).Write(header, bodyStream, bodyStream.Length);
                        context.ClientStream.Flush();
                    }
                }
            }
        }