/// <summary> /// Triggered before the response is sent back to the client /// </summary> /// <param name="responseInfo"></param> /// <returns></returns> protected override HttpResponseInfo OnBeforeResponseToClient(HttpResponseInfo responseInfo) { if (_responseReplacements != null && _responseReplacements.Count > 0) { string response = responseInfo.ToString(); bool wasReplaced = false; foreach (string key in _responseReplacements.Keys) { if (Utils.IsMatch(response, key)) { response = Utils.ReplaceGroups(response, key, _responseReplacements[key]); HttpServerConsole.Instance.WriteLine(LogMessageType.Information, "Response replacement applied for pattern: '{0}'", key); wasReplaced = true; } } if (wasReplaced) { //remove chunked encoding response = Regex.Replace(response, "Transfer-Encoding:\\s?chunked\\r\\n", "", RegexOptions.IgnoreCase); responseInfo = new HttpResponseInfo(response); } } if (!_isNonEssential) { //update tracked paterns from the response PatternTracker.Instance.UpdatePatternValues(responseInfo); } if (CurrDataStoreRequestInfo != null) { //trap the response (this will only occur if the trap is enabled) if (HttpTrap.Instance.TrapResponses) { TrafficDataStore.SaveResponse(CurrDataStoreRequestInfo.Id, responseInfo.ToArray()); if (HttpTrap.Instance.TrapResponse(CurrDataStoreRequestInfo, responseInfo)) { responseInfo = new HttpResponseInfo(TrafficDataStore.LoadResponseData(CurrDataStoreRequestInfo.Id)); if (responseInfo.ResponseBody != null && responseInfo.ResponseBody.IsChunked == false) { responseInfo.Headers["Content-Length"] = responseInfo.ResponseBody.Length.ToString(); } } } if (_trackRequestContext) { //replace the request with its request id //store information about where the request was found in previous traffic responses stored in the //current traffic file TrackRequestContext(_requestInfo); } } return(responseInfo); }
/// <summary> /// Writes a CRWAE message to the client when response is not available from server /// </summary> /// <param name="statusCode">HTTP status code for the response</param> /// <param name="reason">Brief explanation of error</param> /// <param name="serviceCode">ID of the CRAWE message</param> /// <param name="args">Message args</param> protected virtual void ReturnHttpErrorResponse(HttpStatusCode statusCode, string reason, ServiceCode serviceCode, params object [] args) { byte[] messageBytes = HttpErrorResponse.GenerateHttpErrorResponse(statusCode, reason, serviceCode, args); if (!TryWriteToStream(messageBytes)) { return; } //add the response if we are adding requests to the data source if (_currDataStoreRequestInfo != null) { _currDataStoreRequestInfo.ResponseStatus = statusCode.ToString(); _currDataStoreRequestInfo.ResponseTime = DateTime.Now; TrafficDataStore.SaveResponse(_currDataStoreRequestInfo.Id, messageBytes); _currDataStoreRequestInfo = null; } ClientStreamWrapper.Close(); }
/// <summary> /// Writes a response to the client stream /// </summary> /// <param name="responseInfo"></param> protected virtual void ReturnResponse(HttpResponseInfo responseInfo) { HttpServerConsole.Instance.WriteLine(LogMessageType.Information, "Sending response: {0} for request: {1}", responseInfo.StatusLine, _requestInfo.RequestLine); if (_currDataStoreRequestInfo != null) { _currDataStoreRequestInfo.ResponseStatus = responseInfo.Status.ToString(); _currDataStoreRequestInfo.ResponseTime = DateTime.Now; } //process response headers if (responseInfo.Status == 401) { //we need to send the proxy support header/ or overwrite the existing proxy support header responseInfo.Headers["Proxy-Support"] = "Session-Based-Authentication"; } //if connection is close disconnect, or if the client sent us a connection close message if (String.Compare(responseInfo.Headers[CONNECTION_HEADER], "close", true) == 0 || String.Compare(_requestInfo.Headers[CONNECTION_HEADER], "close", true) == 0) { _isClose = true; } byte[] responseHead = HandleResponseByteChunk(responseInfo.ResponseHead); if (!TryWriteToStream(responseHead)) { return; } ; // Return the substitute response body if (responseInfo.ResponseBody.IsChunked) { byte[] chunk; byte[] chunkBuf; while ((chunk = responseInfo.ResponseBody.ReadChunk()) != null) { //write the chunk size line chunkBuf = Constants.DefaultEncoding.GetBytes(String.Format("{0:x}\r\n", chunk.Length)); chunkBuf = HandleResponseByteChunk(chunkBuf); if (!TryWriteToStream(chunkBuf)) { return; } //write the chunk chunk = HandleResponseByteChunk(chunk); if (!TryWriteToStream(chunk)) { return; } chunkBuf = Constants.DefaultEncoding.GetBytes("\r\n"); chunkBuf = HandleResponseByteChunk(chunkBuf); if (!TryWriteToStream(chunkBuf)) { return; } } //write a last chunk with the value 0 // write the last chunk size chunkBuf = Constants.DefaultEncoding.GetBytes("0\r\n\r\n"); chunkBuf = HandleResponseByteChunk(chunkBuf); if (!TryWriteToStream(chunkBuf)) { return; } } else { byte[] buffer = responseInfo.ResponseBody.ToArray(); if (buffer != null) { buffer = HandleResponseByteChunk(buffer); if (!TryWriteToStream(buffer)) { return; } } } //cleanup the request info _requestBuilder = new ByteArrayBuilder(); if (_currDataStoreRequestInfo != null) { TrafficDataStore.SaveResponse(_currDataStoreRequestInfo.Id, _currentRequestResponseBytes); } _currDataStoreRequestInfo = null; _currentRequestResponseBytes = null; //close the connection if the request had a connection close header if (_isClose) { ClientStreamWrapper.Close(); } else { _isBusy = false; ClientStreamWrapper.BeginRead(Buffer, 0, Buffer.Length, new AsyncCallback(OnRead), ClientStreamWrapper); } }