/// <summary> /// Establish secured connection with client and receive HTTP request using it. /// </summary> /// <param name="context">current request context</param> protected override void ReceiveRequest(ProcessingContext context) { base.ReceiveRequest(context); if (context.Processed) { return; } if (context.RequestHeader == null) { throw new InvalidContextException("RequestHeader"); } if (context.RequestHeader.MethodType != RequestMethodTypes.CONNECT) { throw new InvalidOperationException("Not SSL request"); } if (context.ClientStream == null) { throw new InvalidContextException("ClientStream"); } var responseWriter = new HttpResponseWriter(context.ClientStream); var sslStream = new SslStream(context.ClientStream, false, _certificateValidationCallback); try { responseWriter.WriteConnectionEstablished(); sslStream.AuthenticateAsServer(_certificate, false, SslProtocols.Tls, false); context.ClientStream = sslStream; base.ReceiveRequest(context); } catch (IOException ex) { if (ex.IsSocketException(SocketError.ConnectionReset, SocketError.ConnectionAborted)) { Logger.WarnFormat("Request Aborted. {0}", TraceUtils.GetHttpTrace(context.RequestHeader)); } else if (ex.IsSocketException(SocketError.TimedOut)) { Logger.WarnFormat("Client request time out. {0}", TraceUtils.GetHttpTrace(context.RequestHeader)); } else { throw; } context.StopProcessing(); } }
/// <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(); } }
/// <summary> /// Send respose to <see cref="ProcessingContext.ClientStream" /> containing /// <see cref="ProcessingContext.ResponseHeader" /> /// and rest of<see cref="ProcessingContext.ServerStream" />. /// Expect <see cref="ProcessingContext.ServerStream" />, <see cref="ProcessingContext.ClientStream" /> and /// <see cref="ProcessingContext.ResponseHeader" /> to be defined. /// </summary> /// <param name="context">current request context</param> protected virtual void SendResponse(ProcessingContext context) { Contract.Requires <ArgumentNullException>(context != null, "context"); Contract.Requires <InvalidContextException>(context.ServerStream != null, "ServerStream"); Contract.Requires <InvalidContextException>(context.ResponseHeader != null, "ResponseHeader"); Contract.Requires <InvalidContextException>(context.ClientStream != null, "ClientStream"); Contract.Requires <InvalidContextException>(context.ServerSocket != null, "ServerSocket"); var responseWriter = new HttpResponseWriter(context.ClientStream); try { responseWriter.Write(context.ResponseHeader, context.ServerStream, context.ServerSocket.Available); if (Logger.IsDebugEnabled) { Logger.DebugFormat("Response Sent. {0}", TraceUtils.GetHttpTrace(context.ResponseHeader)); } } catch (IOException ex) { if (ex.IsSocketException(SocketError.TimedOut)) { Logger.WarnFormat("Request to remote server has timed out. {0}", TraceUtils.GetHttpTrace(context.RequestHeader)); responseWriter.WriteGatewayTimeout(); } else if (ex.IsSocketException(SocketError.ConnectionReset, SocketError.ConnectionAborted)) { if (Logger.IsDebugEnabled) { Logger.DebugFormat("Request Aborted. {0}", TraceUtils.GetHttpTrace(context.RequestHeader)); } } else { throw; } context.StopProcessing(); } }
/// <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(); } }