Telerik blogs

FiddlerScript is one of the most powerful features in Fiddler; it allows you to enhance Fiddler's UI, add new features, and modify requests and responses “on the fly” to introduce any behavior you'd like.

FiddlerScript is based on JScript.NET, a .NET version of JavaScript, so it's easy for web developers to use, and the syntax is close enough to C# that most .NET developers can write simple rules with little effort.

Editing FiddlerScript

To get started, simply click Rules > Customize Rules to open your FiddlerScript file. If the file opens in Notepad that means you haven't yet installed the FiddlerScript Editor, which offers syntax-highlighting, Intellisense-style code completion, and a Class Explorer:

image

If you're doing any non-trivial updates to your FiddlerScript, you should definitely install the FiddlerScript editor, which is part of Fiddler Classic. You'll find it bundled with the SyntaxView Inspectors that offer syntax-highlighting and formatting of common web types (HTML, CSS, JavaScript, etc).

No matter what editor you use, when you update the script and save it, Fiddler will automatically notice the new file version and attempt to load it. If the script loads successfully, a sound will play and the Fiddler status bar will say “CustomRules.js was loaded at <datetime>” (this text is actually set by the Main function inside the FiddlerScript file itself. You can change it to anything you'd like.) If compilation of the script fails, an error message will be shown and you can use it to help fix whatever problem you've found in your script.

If you ever corrupt your FiddlerScript so badly that you can't fix it, simply delete the CustomRules.js file from \Documents\Fiddler2\Scripts and restart Fiddler. Fiddler will automatically regenerate the file using the latest SampleRules.js file included in the Fiddler installation package.

FiddlerScript Methods

Your FiddlerScript file includes a single static class (named Handlers) which Fiddler uses to locate the methods that are called as it runs. Generally speaking, all of your code should be placed inside static methods on this class.

Fiddler automatically executes a number of “Application event methods” as it runs:

static function OnBoot Executes when Fiddler finishes launching.
static function OnShutdown Executes as Fiddler is closing down.
static function OnAttach Executes as Fiddler registers itself as the system proxy.
static function OnDetach Executes as Fiddler unregisters itself as the system proxy.
static function Main Executes every time Fiddler successfully loads and compiles the FiddlerScript

As Fiddler processes Web Sessions, each Session is passed (as a parameter) to an method based on the current state of the Session. The “Session event methods” are invoked in the following order:

static function OnPeekAtRequestHeaders

Called immediately after a set of request headers has been read from the client. This is typically too early to do much useful work, since the body hasn't yet been read, but sometimes it may be useful.

Tip: The request body is not available yet when this method runs, so don't try to use it; your code will throw an exception.

static function OnBeforeRequest Called after Fiddler has read a complete HTTP(S) request from the client. You should use this method to update the request headers or the request body if desired.

Tip: The Response is not available yet when this method runs, so don't try to use it; your code will throw an exception.
static function OnPeekAtResponseHeaders Called after Fiddler has sent the request to the server and the server's response headers have been read. You might use this method to set the bBufferResponse property on the Session to control streaming of the response body based on the headers.

Tip: The response body is not available yet when this method runs, so don't try to use it; your code will throw an exception.
static function OnBeforeResponse Fires after the complete response has been read from the server. This event fires before the response is returned to the client (unless Streaming was enabled). You should use this method to update the response headers or the response body if desired.

Tip: The Request was already sent to the server before this method runs, so don't expect that changing it here will do anything useful.

In some cases, two other methods may run:

static function OnReturningError Called if Fiddler is returning an error message to the client (e.g. DNS lookup failed, Cannot Connect, etc). You may use this method to customize the response sent to the client.
static function OnWebSocketMessage Called when a request or response message is received on a WebSocket connection. You can use this method to alter the contents of the message or prevent it from being transmitted.

FiddlerScript also exposes a method to allow scripts to participate in the handling of input to Fiddler's QuickExec box.

static function OnExecAction(sParams: String[]) Called when the user enters a command in the QuickExec box. Return true if your script has handled the specified command, otherwise return false.

 

Targeting Sessions

When using the Session event methods, your code typically consists of two major parts:

  1. Recognizing of Web Sessions of interest (Targeting)
  2. Making changes to those Sessions (Updating)

In most cases, you only want to update certain Web Sessions, so your code should examine the properties of the Web Session to decide if the current Session is one needing modification. There are several useful helper methods for this task:

if (oSession.uriContains("caseInsensitiveStringFromURI")) {
  /* do something */
}

if (oSession.HostnameIs("SiteICareAbout.com")) {
  /* do something */
}

if (oSession.HTTPMethodIs("POST") && 
    oSession.oRequest.headers.ExistsAndContains("SoapAction", "SendBody") {
  /* do something for SOAP POSTS */
}

In many cases, you don't want to target requests which represent CONNECT tunnels through which secure traffic flows, because you instead only want to modify the HTTPS requests inside the tunnel rather than the tunnel itself. To do that, simply check to see whether the request's HTTP Method is “Connect” and if so, skip the Session:

if (!oSession.HTTPMethodIs("CONNECT")) {
  /* ignore CONNECT tunnels */
}

Often, complaints that “My rules didn't update the Session properly” turn out to be related to the fact that the Sessions were not targeted properly. To help identify such problems, each rule should always update the Session's UI so that it's plain to see whether the rule is being applied:

// case-sensitively replace oldString with newString
if (oSession.fullUrl.indexOf("oldString") > -1) { 
  oSession["ui-backcolor"] = "lime";
  oSession["ui-bold"] = "changing URL for this session";
  oSession.fullUrl = oSession.fullUrl.Replace("oldString", "newString");
}

This rule block changes the Web Session's background color to lime green and bolds its text before replacing all instances of “oldString” in the URL with “newString”.

image

That way, if the rule is running on Sessions you don't expect (or if it isn't running on Sessions you do) you can more easily identify the problem with your targeting.

FiddlerScript and Attributes

The Handlers class also allows you to expose fields (simple variables) or methods that can be annotated using attributes which cause the fields to appear within the Fiddler UI.

For instance, you can add a Clean command to the Web Sessions List's context menu using the ContextAction attribute:

public static ContextAction("Clean")
function doClean(arrSess: Session[]) {        
  for (var i: int=0; i < arrSess.Length; i++) {
    arrSess[i].utilDecodeResponse();
    var oRH = arrSess[i].oRequest.headers;
    oRH.RemoveRange(["Cookie",
                     "DNT",
                     "User-Agent",
                     "Accept",
                     "UA-CPU",
                     "Accept-Language",
                     "Accept-Encoding",
                     "Pragma",
                     "Connection",
                     "X-Download-Initiator"]);
    oRH = arrSess[i].oResponse.headers;
    oRH.RemoveRange(["Vary",
                     "X-Powered-By",
                     "X-ASPNET-Version",
                     "x-amz-id-2",
                     "x-amz-request-id",
                     "Last-Modified",
                     "x-amz-version-id",
                     "Accept-Ranges",
                     "ETag",
                     "Pragma",
                     "Connection",
                     "Server",
                     "Cache-Control",
                     "Date",
                     "X-Cache",
                     "Expires",
                     "Age",
                     "Via",
                     "X-Varnish",
                     "Access-Control-Allow-Origin",
                     "X-Content-Type-Options",
                     "X-Frame-Options",
                     "X-XSS-Protection",
                     "Keep-Alive"]);
  }
  MessageBox.Show("Done");
}

You can add a new column to the Web Sessions list that runs on every session using the BindUIColumn attribute:

public static BindUIColumn("Method", 60)
function FillMethodColumn(oS: Session): String {
  return oS.RequestMethod;
}

You can add a new top-level menu using the QuickLinks attribute:

QuickLinkMenu("&Links") 
QuickLinkItem("IE GeoLoc TestDrive", "http://ie.microsoft.com/testdrive/HTML5/Geolocation/Default.html")
QuickLinkItem("FiddlerCore", "http://fiddler.wikidot.com/fiddlercore")
public static function DoLinksMenu(sText: String, sAction: String)
{
  Utilities.LaunchHyperlink(sAction);
}

Because recompiling your FiddlerScript reinitializes all of its variables, you may want to use the BindPref attribute to preserve the value of a variable. Fiddler will automatically reload the variable's value from a preference when FiddlerScript loads, and will automatically update the preference value when FiddlerScript unloads:

BindPref("fiddlerscript.ephemeral.bpResponseURI")
public static var bpResponseURI:String = null;

When the preference's name contains the word “Ephemeral”, Fiddler will discard the preference value each time Fiddler exits, preserving it only across recompiles of the script within a single Fiddler instance.

I hope you find FiddlerScript a powerful way to enhance Fiddler to suit your specific needs.


About the Author

Eric Lawrence

(@ericlaw) has built websites and web client software since the mid-1990s. After over a decade of working on the web for Microsoft, Eric joined Telerik in October 2012 to enhance the Fiddler Web Debugger on a full-time basis. With his recent move to Austin, Texas, Eric has now lived in the American South, North, West, and East.

Comments

Comments are disabled in preview mode.