public static void WriteResponse(this HttpMessageWriter writer, StatusCodes statusCodes, ContentType contentType, byte[] content) { writer.WriteStatusLine(statusCodes); writer.WriteAuxiliaryHeaders(); writer.WriteContentType(contentType); writer.WriteContentLength(content.Length); writer.WriteCRLF(); writer.Write(content); }
public String ShouldWriteHttpMessage(HttpMessageHeader header, Stream body, long?bodyLength) { var outputStream = new MemoryStream(); var httpWriter = new HttpMessageWriter(outputStream); httpWriter.Write(header, body, bodyLength); return(Encoding.ASCII.GetString(outputStream.ToArray())); }
/// <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); } }
private void SendJsonMessage(Session session) { using (var writer = new HttpMessageWriter()) { //byte[] json = Encoding.UTF8.GetBytes(string.Format(@"{{id:{0}}}", session.Id)); byte[] json = Encoding.UTF8.GetBytes(string.Format(@"{0}", session.Id)); writer.WriteStatusLine(StatusCodes.OK); //writer.Write(Encoding.UTF8.GetBytes("Content-Type: application/json\r\n")); writer.WriteContentLength(json.Length); writer.WriteAccessControlHeaders(); writer.WriteCRLF(); writer.Write(json); SendWriter(session, writer); } }
/// <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 String ShouldWriteHttpMessage(HttpMessageHeader header, Stream body, long? bodyLength) { var outputStream = new MemoryStream(); var httpWriter = new HttpMessageWriter(outputStream); httpWriter.Write(header, body, bodyLength); return Encoding.ASCII.GetString(outputStream.ToArray()); }
/// <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(); } } } }
/// <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) { Contract.Requires<ArgumentNullException>(context != null, "context"); Contract.Requires<InvalidContextException>(context.ServerStream != null, "ServerStream"); Contract.Requires<InvalidContextException>(context.RequestHeader != null, "RequestHeader"); Contract.Requires<InvalidContextException>(context.ClientStream != null, "ClientStream"); Contract.Requires<InvalidContextException>(context.ClientSocket != null, "ClientSocket"); var requestWriter = new HttpMessageWriter(context.ServerStream); var responseReader = new HttpHeaderReader(new PlainStreamReader(context.ServerStream)); try { requestWriter.Write(context.RequestHeader, context.ClientStream, context.ClientSocket.Available); context.ResponseHeader = new HttpResponseHeader(responseReader.ReadHttpMessageHeader()); if (Logger.IsDebugEnabled) { Logger.DebugFormat("Response Received: {0}", TraceUtils.GetHttpTrace(context.ResponseHeader)); } } catch (IOException ex) { var responseWriter = new HttpResponseWriter(context.ClientStream); if (ex.IsSocketException(SocketError.TimedOut)) { Logger.WarnFormat("Request to remote server has timed out. {0}", TraceUtils.GetHttpTrace(context.RequestHeader)); responseWriter.WriteGatewayTimeout(); } else { throw; } context.StopProcessing(); } }