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>(); } }
public void New() { var reader = new HttpHeaderReader(s_buffer, true); while (reader.TryParse()) { // do nothing. } }
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); } }
/// <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(); } }
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" })); }
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)); }
/// <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(); }
/// <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); }
/// <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(); } } } }