/// <summary> /// Called asynchronously when a request was successfull and we received the response. /// </summary> /// <param name="args">The session event arguments.</param> /// <returns> The task.</returns> private async Task handleHttpSessionResponse(SessionEventArgs args) { var cancellationToken = args.CancellationTokenSource.Token; // read response & headers from server await args.WebSession.ReceiveResponse(cancellationToken); var response = args.WebSession.Response; args.ReRequest = false; // check for windows authentication if (isWindowsAuthenticationEnabledAndSupported) { if (response.StatusCode == (int)HttpStatusCode.Unauthorized) { await handle401UnAuthorized(args); } else { WinAuthEndPoint.AuthenticatedResponse(args.WebSession.Data); } } //save original values so that if user changes them //we can still use original values when syphoning out data from attached tcp connection. response.SetOriginalHeaders(); // if user requested call back then do it if (!response.Locked) { await invokeBeforeResponse(args); } // it may changed in the user event response = args.WebSession.Response; var clientStreamWriter = args.ProxyClient.ClientStreamWriter; //user set custom response by ignoring original response from server. if (response.Locked) { //write custom user response with body and return. await clientStreamWriter.WriteResponseAsync(response, cancellationToken : cancellationToken); if (args.WebSession.ServerConnection != null && !args.WebSession.CloseServerConnection) { // syphon out the original response body from server connection // so that connection will be good to be reused. await args.SyphonOutBodyAsync(false, cancellationToken); } return; } // if user requested to send request again // likely after making modifications from User Response Handler if (args.ReRequest) { // clear current response await args.ClearResponse(cancellationToken); await handleHttpSessionRequestInternal(args.WebSession.ServerConnection, args); return; } response.Locked = true; // Write back to client 100-conitinue response if that's what server returned if (response.Is100Continue) { await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion, (int)HttpStatusCode.Continue, "Continue", cancellationToken); await clientStreamWriter.WriteLineAsync(cancellationToken); } else if (response.ExpectationFailed) { await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion, (int)HttpStatusCode.ExpectationFailed, "Expectation Failed", cancellationToken); await clientStreamWriter.WriteLineAsync(cancellationToken); } if (!args.IsTransparent) { response.Headers.FixProxyHeaders(); } if (response.IsBodyRead) { await clientStreamWriter.WriteResponseAsync(response, cancellationToken : cancellationToken); } else { // Write back response status to client await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion, response.StatusCode, response.StatusDescription, cancellationToken); await clientStreamWriter.WriteHeadersAsync(response.Headers, cancellationToken : cancellationToken); // Write body if exists if (response.HasBody) { await args.CopyResponseBodyAsync(clientStreamWriter, TransformationMode.None, cancellationToken); } } }
/// <summary> /// Called asynchronously when a request was successfully and we received the response /// </summary> /// <param name="args"></param> /// <returns>true if client/server connection was terminated (and disposed) </returns> private async Task HandleHttpSessionResponse(SessionEventArgs args) { try { //read response & headers from server await args.WebSession.ReceiveResponse(); var response = args.WebSession.Response; //check for windows authentication if (isWindowsAuthenticationEnabledAndSupported && response.StatusCode == (int)HttpStatusCode.Unauthorized) { await Handle401UnAuthorized(args); } args.ReRequest = false; //If user requested call back then do it if (BeforeResponse != null && !response.ResponseLocked) { await BeforeResponse.InvokeAsync(this, args, ExceptionFunc); } //if user requested to send request again //likely after making modifications from User Response Handler if (args.ReRequest) { //clear current response await args.ClearResponse(); await HandleHttpSessionRequestInternal(args.WebSession.ServerConnection, args); return; } response.ResponseLocked = true; var clientStreamWriter = args.ProxyClient.ClientStreamWriter; //Write back to client 100-conitinue response if that's what server returned if (response.Is100Continue) { await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion, (int)HttpStatusCode.Continue, "Continue"); await clientStreamWriter.WriteLineAsync(); } else if (response.ExpectationFailed) { await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion, (int)HttpStatusCode.ExpectationFailed, "Expectation Failed"); await clientStreamWriter.WriteLineAsync(); } //Write back response status to client await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion, response.StatusCode, response.StatusDescription); if (!args.IsTransparent) { response.Headers.FixProxyHeaders(); } if (response.IsBodyRead) { bool isChunked = response.IsChunked; string contentEncoding = response.ContentEncoding; if (contentEncoding != null) { response.Body = await GetCompressedResponseBody(contentEncoding, response.Body); if (isChunked == false) { response.ContentLength = response.Body.Length; } else { response.ContentLength = -1; } } await clientStreamWriter.WriteHeadersAsync(response.Headers); await clientStreamWriter.WriteBodyAsync(response.Body, isChunked); } else { await clientStreamWriter.WriteHeadersAsync(response.Headers); //Write body if exists if (response.HasBody) { await args.CopyResponseBodyAsync(clientStreamWriter, false); } } } catch (Exception e) when(!(e is ProxyHttpException)) { throw new ProxyHttpException("Error occured whilst handling session response", e, args); } }
/// <summary> /// Called asynchronously when a request was successful and we received the response. /// </summary> /// <param name="args">The session event arguments.</param> /// <returns> The task.</returns> private async Task handleHttpSessionResponse(SessionEventArgs args) { var cancellationToken = args.CancellationTokenSource.Token; // read response & headers from server await args.HttpClient.ReceiveResponse(cancellationToken); // Server may send expect-continue even if not asked for it in request. // According to spec "the client can simply discard this interim response." if (args.HttpClient.Response.StatusCode == (int)HttpStatusCode.Continue) { await args.ClearResponse(cancellationToken); await args.HttpClient.ReceiveResponse(cancellationToken); } args.TimeLine["Response Received"] = DateTime.Now; var response = args.HttpClient.Response; args.ReRequest = false; // check for windows authentication if (isWindowsAuthenticationEnabledAndSupported) { if (response.StatusCode == (int)HttpStatusCode.Unauthorized) { await handle401UnAuthorized(args); } else { WinAuthEndPoint.AuthenticatedResponse(args.HttpClient.Data); } } //save original values so that if user changes them //we can still use original values when syphoning out data from attached tcp connection. response.SetOriginalHeaders(); // if user requested call back then do it if (!response.Locked) { await invokeBeforeResponse(args); } // it may changed in the user event response = args.HttpClient.Response; var clientStreamWriter = args.ProxyClient.ClientStreamWriter; //user set custom response by ignoring original response from server. if (response.Locked) { //write custom user response with body and return. await clientStreamWriter.WriteResponseAsync(response, cancellationToken : cancellationToken); if (args.HttpClient.Connection != null && !args.HttpClient.CloseServerConnection) { // syphon out the original response body from server connection // so that connection will be good to be reused. await args.SyphonOutBodyAsync(false, cancellationToken); } return; } // if user requested to send request again // likely after making modifications from User Response Handler if (args.ReRequest) { await tcpConnectionFactory.Release(args.HttpClient.Connection); // clear current response await args.ClearResponse(cancellationToken); var httpCmd = Request.CreateRequestLine(args.HttpClient.Request.Method, args.HttpClient.Request.RequestUriString, args.HttpClient.Request.HttpVersion); await handleHttpSessionRequest(httpCmd, args, null, args.ClientConnection.NegotiatedApplicationProtocol, cancellationToken, args.CancellationTokenSource); return; } response.Locked = true; if (!args.IsTransparent) { response.Headers.FixProxyHeaders(); } if (response.IsBodyRead) { await clientStreamWriter.WriteResponseAsync(response, cancellationToken : cancellationToken); } else { // Write back response status to client await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion, response.StatusCode, response.StatusDescription, cancellationToken); await clientStreamWriter.WriteHeadersAsync(response.Headers, cancellationToken : cancellationToken); // Write body if exists if (response.HasBody) { await args.CopyResponseBodyAsync(clientStreamWriter, TransformationMode.None, cancellationToken); } } args.TimeLine["Response Sent"] = DateTime.Now; }
/// <summary> /// Called asynchronously when a request was successfully and we received the response. /// </summary> /// <param name="args">The session event arguments.</param> /// <returns> The task.</returns> private async Task HandleHttpSessionResponse(SessionEventArgs args) { try { var cancellationToken = args.CancellationTokenSource.Token; // read response & headers from server await args.WebSession.ReceiveResponse(cancellationToken); var response = args.WebSession.Response; args.ReRequest = false; // check for windows authentication if (isWindowsAuthenticationEnabledAndSupported) { if (response.StatusCode == (int)HttpStatusCode.Unauthorized) { await Handle401UnAuthorized(args); } else { WinAuthEndPoint.AuthenticatedResponse(args.WebSession.Data); } } response.OriginalHasBody = response.HasBody; // if user requested call back then do it if (!response.Locked) { await InvokeBeforeResponse(args); } // it may changed in the user event response = args.WebSession.Response; var clientStreamWriter = args.ProxyClient.ClientStreamWriter; if (response.TerminateResponse || response.Locked) { await clientStreamWriter.WriteResponseAsync(response, cancellationToken : cancellationToken); if (!response.TerminateResponse) { // syphon out the response body from server before setting the new body await args.SyphonOutBodyAsync(false, cancellationToken); } else { args.WebSession.ServerConnection.Dispose(); args.WebSession.ServerConnection = null; } return; } // if user requested to send request again // likely after making modifications from User Response Handler if (args.ReRequest) { // clear current response await args.ClearResponse(cancellationToken); await HandleHttpSessionRequestInternal(args.WebSession.ServerConnection, args); return; } response.Locked = true; // Write back to client 100-conitinue response if that's what server returned if (response.Is100Continue) { await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion, (int)HttpStatusCode.Continue, "Continue", cancellationToken); await clientStreamWriter.WriteLineAsync(cancellationToken); } else if (response.ExpectationFailed) { await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion, (int)HttpStatusCode.ExpectationFailed, "Expectation Failed", cancellationToken); await clientStreamWriter.WriteLineAsync(cancellationToken); } if (!args.IsTransparent) { response.Headers.FixProxyHeaders(); } if (response.IsBodyRead) { await clientStreamWriter.WriteResponseAsync(response, cancellationToken : cancellationToken); } else { // Write back response status to client await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion, response.StatusCode, response.StatusDescription, cancellationToken); await clientStreamWriter.WriteHeadersAsync(response.Headers, cancellationToken : cancellationToken); // Write body if exists if (response.HasBody) { await args.CopyResponseBodyAsync(clientStreamWriter, TransformationMode.None, cancellationToken); } } } catch (Exception e) when(!(e is ProxyHttpException)) { throw new ProxyHttpException("Error occured whilst handling session response", e, args); } }