title: Fiddler (FiddlerCore) response work slow when inserting script
body: <p>I try to create proxy server with fiddlercore and when i use event BeforeResponse code work very slow. What i'm attempt to do is to insert script at the top of the current browsed page. </p>
  
  <p>Why is below code so slow is it need to be inserted some kind of filter or what?</p>
  
  <pre><code>Fiddler.FiddlerApplication.BeforeResponse += delegate(Fiddler.Session oS)
          {
              Console.WriteLine("{0}:HTTP {1} for {2}", oS.id, oS.responseCode, oS.fullUrl);
  
              oS.utilDecodeResponse(); 
              string HTML = oS.GetResponseBodyAsString();
  
              HtmlDocument htmlDoc = new HtmlDocument();
              try
              {
                  htmlDoc.LoadHtml(HTML);
                  HtmlNode node = htmlDoc.CreateElement("script");
                  node.SetAttributeValue("src", "https://somesite.com");
                  HtmlNode Head = htmlDoc.DocumentNode.SelectSingleNode("//Head");
  
                  if (Head != null)
                  {
                      Head.AppendChild(node);
                      oS.utilSetResponseBody(htmlDoc.DocumentNode.OuterHtml);
                  }
              }
              catch (Exception ex)
              {
                  Console.WriteLine(ex.Message.ToString());
              }
  
              Console.WriteLine("URL: {0}", oS.url);
          };
  </code></pre>
  
  <p>Here is full code:</p>
  
  <pre><code>    /*
      * This demo program shows how to use the FiddlerCore library.
      *
      * Before compiling, ensure that the project's REFERENCES list points to the 
      * copy of FiddlerCore.dll included in this package.
      *
      * By default, the project is compiled without support for the SAZ File format.
      * If you want to add SAZ support, define the token SAZ_SUPPORT in the list of
      * Conditional Compilation symbols on the project's BUILD tab. You will also
      * need to add Ionic.Zip.Reduced.dll to your project's references.
      */
  
      using System;
      using System.Collections.Generic;
      using System.IO;
      using System.Reflection;
      using System.Threading;
      using Fiddler;
      using System.Diagnostics;
      using HtmlAgilityPack;
      using System.Security.Cryptography.X509Certificates;
      using System.Text.RegularExpressions;
  
      namespace Demo
      {
          class Program
          {
              static Proxy oSecureEndpoint;
              static string sSecureEndpointHostname = "localhost";
              static int iSecureEndpointPort = 7777;
  
              public static void WriteCommandResponse(string s)
              {
                  ConsoleColor oldColor = Console.ForegroundColor;
                  Console.ForegroundColor = ConsoleColor.Yellow;
                  Console.WriteLine(s);
                  Console.ForegroundColor = oldColor;
              }
  
              public static void DoQuit()
              {
                  WriteCommandResponse("Shutting down...");
                  //  UninstallCertificate();
                  //  Console.Write("\ncert: {0}", CertMaker.rootCertExists()); Console.ReadLine();
                  //  if (null != oSecureEndpoint) oSecureEndpoint.Dispose();
                  Fiddler.FiddlerApplication.Shutdown();
  
                  Thread.Sleep(500);
              }
              private static string Ellipsize(string s, int iLen)
              {
                  if (s.Length &lt;= iLen) return s;
                  return s.Substring(0, iLen - 3) + "...";
              }
  
      #if SAZ_SUPPORT
              private static void ReadSessions(List&lt;Fiddler.Session&gt; oAllSessions)
              {
                  Session[] oLoaded = Utilities.ReadSessionArchive(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) 
                                                                 + Path.DirectorySeparatorChar + "ToLoad.saz", false);
  
                  if ((oLoaded != null) &amp;&amp; (oLoaded.Length &gt; 0))
                  {
                      oAllSessions.AddRange(oLoaded);
                      WriteCommandResponse("Loaded: " + oLoaded.Length + " sessions.");
                  }
              }
  
              private static void SaveSessionsToDesktop(List&lt;Fiddler.Session&gt; oAllSessions)
              {
                  bool bSuccess = false;
                  string sFilename = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
                                   + Path.DirectorySeparatorChar + DateTime.Now.ToString("hh-mm-ss") + ".saz";
                  try
                  {
                      try
                      {
                          Monitor.Enter(oAllSessions);
  
                          string sPassword = null;
                          Console.WriteLine("Password Protect this Archive (Y/N)?");
                          ConsoleKeyInfo oCKI = Console.ReadKey();
                          if ((oCKI.KeyChar == 'y') || (oCKI.KeyChar == 'Y'))
                          {
                              Console.WriteLine("\nEnter the password:");
                              sPassword = Console.ReadLine();
                              Console.WriteLine(String.Format("\nEncrypting with Password: '{0}'", sPassword));
                          }
                          Console.WriteLine();
  
                          bSuccess = Utilities.WriteSessionArchive(sFilename, oAllSessions.ToArray(), sPassword, false);
                      }
                      finally
                      {
                          Monitor.Exit(oAllSessions);
                      }
  
                      WriteCommandResponse( bSuccess ? ("Wrote: " + sFilename) : ("Failed to save: " + sFilename) );
                  }
                  catch (Exception eX)
                  {
                      Console.WriteLine("Save failed: " + eX.Message);
                  }
              }
      #endif
              public static bool InstallCertificate()
              {
                  if (!CertMaker.rootCertExists())
                  {
                      if (!CertMaker.createRootCert())
                          return false;
  
                      if (!CertMaker.trustRootCert())
                          return false;
                  }
  
                  return true;
              }
  
              public static bool UninstallCertificate()
              {
                  if (CertMaker.rootCertExists())
                  {
                      if (!CertMaker.removeFiddlerGeneratedCerts(true))
                          return false;
                  }
                  return true;
              }
  
              private static void WriteSessionList(List&lt;Fiddler.Session&gt; oAllSessions)
              {
                  ConsoleColor oldColor = Console.ForegroundColor;
                  Console.ForegroundColor = ConsoleColor.White;
                  Console.WriteLine("Session list contains...");
                  try
                  {
                      Monitor.Enter(oAllSessions);
                      foreach (Session oS in oAllSessions)
                      {
                          Console.Write(String.Format("{0} {1} {2}\n{3} {4}\n\n", oS.id, oS.oRequest.headers.HTTPMethod, Ellipsize(oS.fullUrl, 60), oS.responseCode, oS.oResponse.MIMEType));
                      }
                  }
                  finally
                  {
                      Monitor.Exit(oAllSessions);
                  }
                  Console.WriteLine();
                  Console.ForegroundColor = oldColor;
              }
  
              private static bool setMachineTrust(X509Certificate2 oRootCert)
              {
                  try
                  {
                      // X509Certificate2 cert = X509Certificate2("C:\Path\my.pfx", "password");
  
                      X509Store certStore = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
                      certStore.Open(OpenFlags.ReadWrite);
  
                      try
                      {
                          certStore.Add(oRootCert);
                      }
                      finally
                      {
                          certStore.Close();
                      }
                      return true;
                  }
                  catch (Exception eX)
                  {
                      return false;
                  }
              }
  
              static void Main(string[] args)
              {
                  List&lt;Fiddler.Session&gt; oAllSessions = new List&lt;Fiddler.Session&gt;();
  
                  // &lt;-- Personalize for your Application, 64 chars or fewer
                  Fiddler.FiddlerApplication.SetAppDisplayName("FiddlerCoreDemoApp");
                  #region AttachEventListeners
  
                  // Simply echo notifications to the console.  Because Fiddler.CONFIG.QuietMode=true 
                  // by default, we must handle notifying the user ourselves.
                  Fiddler.FiddlerApplication.OnNotification += delegate(object sender, NotificationEventArgs oNEA) { Console.WriteLine("** NotifyUser: " + oNEA.NotifyString); };
                  Fiddler.FiddlerApplication.Log.OnLogString += delegate(object sender, LogEventArgs oLEA) { Console.WriteLine("** LogString: " + oLEA.LogString); };
  
                  Fiddler.FiddlerApplication.BeforeRequest += delegate(Fiddler.Session oS)
                  {
                      oS.bBufferResponse = true;
  
                      //Monitor.Enter(oAllSessions);
                      //oAllSessions.Add(oS);
                      //Monitor.Exit(oAllSessions);
                      //oS["X-AutoAuth"] = "(default)";
  
                      //if ((oS.oRequest.pipeClient.LocalPort == iSecureEndpointPort) &amp;&amp; (oS.hostname == sSecureEndpointHostname))
                      {
                          // oSession.oRequest["NewHeaderName"] = "New header value";
                          // oS.oResponse.headers.Add("headerName", "\nThis is new header!!!\n").ToString()
  
                          //oS.utilCreateResponseAndBypassServer();
                          //oS.oResponse.headers.Add("headerName", "This is new header!!!\n");
  
                          //oS.oResponse.headers.SetStatus(200, "Ok");
                          //oS.oResponse["Content-Type"] = "text/html; charset=UTF-8";
                          //oS.oResponse["Cache-Control"] = "private, max-age=0";
  
                          // oS.utilSetResponseBody("fazlija ");
  
                          //oS.utilSetResponseBody("&lt;html&gt;&lt;body&gt;Response for https://" + sSecureEndpointHostname + ":" + iSecureEndpointPort.ToString() + " received. Your response was:&lt;br /&gt;&lt;plaintext&gt;" + oS.oRequest.headers.ToString());
                          // oS.oResponse["NewHeaderName"] = "\nNew header value";
                          // oSession.oResponse.headers.Remove("Set-Cookie");
                      //}
                  };
  
                  // Fiddler.FiddlerApplication.OnReadResponseBuffer += new EventHandler&lt;RawReadEventArgs&gt;(FiddlerApplication_OnReadResponseBuffer);
                  Fiddler.FiddlerApplication.BeforeResponse += delegate(Fiddler.Session oS)
                  {
                      Console.WriteLine("{0}:HTTP {1} for {2}", oS.id, oS.responseCode, oS.fullUrl);
                       oS.utilDecodeResponse(); oS.utilReplaceInResponse("Amazon", "Something");
                  };
  
                  Fiddler.FiddlerApplication.AfterSessionComplete += delegate(Fiddler.Session oS)
                  {
                      //Console.WriteLine("Finished session:\t" + oS.fullUrl); 
                      Console.Title = ("Session list contains: " + oAllSessions.Count.ToString() + " sessions");
                  };
  
                  Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress);
                  #endregion AttachEventListeners
  
                  string sSAZInfo = "NoSAZ";
  
                  Console.WriteLine(String.Format("Starting {0} ({1})...", Fiddler.FiddlerApplication.GetVersionString(), sSAZInfo));
  
                  Fiddler.CONFIG.IgnoreServerCertErrors = false;
  
                  FiddlerApplication.Prefs.SetBoolPref("fiddler.network.streaming.abortifclientaborts", true);
  
                  // For forward-compatibility with updated FiddlerCore libraries, it is strongly recommended that you 
                  // start with the DEFAULT options and manually disable specific unwanted options.
                  FiddlerCoreStartupFlags oFCSF = FiddlerCoreStartupFlags.Default;
  
                  // NOTE: In the next line, you can pass 0 for the port (instead of 8877) to have FiddlerCore auto-select an available port
                  int iPort = 8879;
                  Fiddler.FiddlerApplication.Startup(iPort, oFCSF);
  
                  FiddlerApplication.Log.LogFormat("Created endpoint listening on port {0}", iPort);
  
                  FiddlerApplication.Log.LogFormat("Starting with settings: [{0}]", oFCSF);
                  FiddlerApplication.Log.LogFormat("Gateway: {0}", CONFIG.UpstreamGateway.ToString());
  
                  Console.WriteLine("Hit CTRL+C to end session.");
  
                  // We'll also create a HTTPS listener, useful for when FiddlerCore is masquerading as a HTTPS server
                  // instead of acting as a normal CERN-style proxy server.
                  oSecureEndpoint = FiddlerApplication.CreateProxyEndpoint(iSecureEndpointPort, true, sSecureEndpointHostname);
                  if (null != oSecureEndpoint)
                  {
                      FiddlerApplication.Log.LogFormat("Created secure endpoint listening on port {0}, using a HTTPS certificate for '{1}'", iSecureEndpointPort, sSecureEndpointHostname);
                  }
  
                  bool bDone = false;
                  do
                  {
  
                  } while (!bDone);
              }
  
  
              /// &lt;summary&gt;
              /// This callback allows your code to evaluate the certificate for a site and optionally override default validation behavior for that certificate.
              /// You should not implement this method unless you understand why it is a security risk.
              /// &lt;/summary&gt;
              static void CheckCert(object sender, ValidateServerCertificateEventArgs e)
              {
                  if (null != e.ServerCertificate)
                  {
                      Console.WriteLine("Certificate for " + e.ExpectedCN + " was for site " + e.ServerCertificate.Subject + " and errors were " + e.CertificatePolicyErrors.ToString());
  
                      if (e.ServerCertificate.Subject.Contains("fiddler2.com"))
                      {
                          Console.WriteLine("Got a certificate for fiddler2.com. We'll say this is also good for any other site, like https://fiddlertool.com.");
                          e.ValidityState = CertificateValidity.ForceValid;
                      }
                  }
              }
  
  
              /*
              // This event handler is called on every socket read for the HTTP Response. You almost certainly don't want
              // to add a handler for this event, but the code below shows how you can use it to mess up your HTTP traffic.
              static void FiddlerApplication_OnReadResponseBuffer(object sender, RawReadEventArgs e)
              {
                  // NOTE: arrDataBuffer is a fixed-size array. Only bytes 0 to iCountOfBytes should be read/manipulated.
                  //
                  // Just for kicks, lowercase every byte. Note that this will obviously break any binary content.
                  for (int i = 0; i &lt; e.iCountOfBytes; i++)
                  {
                      if ((e.arrDataBuffer[i] &gt; 0x40) &amp;&amp; (e.arrDataBuffer[i] &lt; 0x5b))
                      {
                          e.arrDataBuffer[i] = (byte)(e.arrDataBuffer[i] + (byte)0x20);
                      }
                  }
                  Console.WriteLine(String.Format("Read {0} response bytes for session {1}", e.iCountOfBytes, e.sessionOwner.id));
              }
              */
  
              /// &lt;summary&gt;
              /// When the user hits CTRL+C, this event fires.  We use this to shut down and unregister our FiddlerCore.
              /// &lt;/summary&gt;
              /// &lt;param name="sender"&gt;&lt;/param&gt;
              /// &lt;param name="e"&gt;&lt;/param&gt;
              static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
              {
                  DoQuit();
              }
  
              /*
              public static bool InstallCertificate()
              {
                  if (!CertMaker.rootCertExists())
                  {
                      if (!CertMaker.createRootCert())
                          return false;
  
                      if (!CertMaker.trustRootCert())
                          return false;
  
  
  
                      App.Configuration.UrlCapture.Cert =
                          FiddlerApplication.Prefs.GetStringPref("fiddler.certmaker.bc.cert", null);
                      App.Configuration.UrlCapture.Key =
                          FiddlerApplication.Prefs.GetStringPref("fiddler.certmaker.bc.key", null);
                  }
  
                  return true;
              }
              public static bool UninstallCertificate()
              {
                  if (CertMaker.rootCertExists())
                  {
                      if (!CertMaker.removeFiddlerGeneratedCerts(true))
                          return false;
                  }
                  App.Configuration.UrlCapture.Cert = null;
                  App.Configuration.UrlCapture.Key = null;
                  return true;
              }
  
               */
          }
      }
  </code></pre>