如何在Fiddler script中捕获请求结果并针对返回内容发起一个新请求

2024-11-28 01:21:13
推荐回答(1个)
回答1:

通过FiddlerScript实现根据条件重发请求

Fiddler是个强大的Web调试工具,具体的功能不在此多述,可以参考后面的链接以及Fiddler官网的手册。本文主要介绍Fiddler的重发请求功能,并通过自定义脚本实现根据条件来重发请求。 在进行Web调试时,经常会遇到浏览器请求正常但是程序请求异常的情况,这时我们常常需要使用Fiddler对比这两个请求的异同,然后将一个请求改变参数或HTTP头进行重发来查看返回结果的差异,这样可以确定哪个参数或哪个HTTP头导致的问题。如下图重发可以有多种不同的选择,常用的有三个:

  • Reissue Requests: 直接重发选定请求

  • Reissue and Edit: 重发选定请求,并在请求之前断点,可以对请求进行修改

  • Reissue from Composer: 将选定请求送到Composer窗口,和将请求拖拽到Composer效果是一样的,在Composer窗口中可以对请求有更精确的控制

  • 请点击输入图片描述

    只简单的重发指定请求,或在指定请求上进行编辑往往是不够的,在项目中我们偶尔会遇到这样的情形:先发送请求A,然后根据请求A结果中的某个值来发送请求B,譬如有这样的两个接口:get_random_server.php接口通过接收的数据随机返回一个服务器ID,get_data.php接口则根据刚刚的服务器ID来获取数据。下面是一个示例:

  • localhost/get_random_server.php?data=Hello -> 返回JSON结果:{ success: true, sid: 2 }

  • localhost/get_data.php?sid=2

  • 这个时候Fiddler的可扩展性就能大显神威了,可以通过两种方式实现Fiddler的扩展:FiddlerScript和插件机制,这里使用FiddlerScript就足够应付了。在Fiddler的菜单项Rules中选择Customize Rules...就可以打开Fiddler的自定义脚本文件CustomRules.js,该脚本一般保存在\Documents\Fiddler2\Scripts目录下。我推荐使用Fidder ScriptEditor进行脚本的编辑,Fidder ScriptEditor具有语法高亮和语法检查的功能,并在右侧面板提供了Fiddler内置的函数列表。 通过展开浏览右侧的函数列表,就基本上可以大概的了解到几个可能会用到的函数了:

  • FiddlerApplication.oProxy.SendRequest

  • FiddlerApplication.oProxy.SendRequestAndWait

  • FiddlerObject.utilIssueRequest

  • 我们先通过下面的代码来练练手,将下面的代码拷贝到CustomRules.js中并保存,Fidder ScriptEditor会自动检查语法错误,并重新加载脚本,无需重启Fiddler脚本即可生效。CustomRules.js使用的是JScript.Net语法,对于Javascipt或.C#程序员应该可以很快上手。这时在Fiddler中随便选择一条请求,点击右键,会发现最上面多了一个选择项Test Send Request,选择该项可以达到和Reissue Requests同样的功能,重发指定请求。

    12345678910111213
  •    
  • public static ContextAction("Test Send Request")function SendRequest(oSessions: Session[]) {         if (oSessions.Length == 0) return;    FiddlerApplication.Log.LogString("Sending...");         var selected: Session = oSessions[0];         var oSD = new System.Collections.Specialized.StringDictionary();    var res = FiddlerApplication.oProxy.SendRequestAndWait(selected.oRequest.headers, selected.RequestBody, oSD, null);    FiddlerApplication.Log.LogString("Request has been Send.");    FiddlerApplication.Log.LogString(res.GetResponseBodyAsString());}
  •    
  • SendRequest/SendRequestAndWait函数有一个不方便之处,他的两个参数oHeaders和arrRequestBodyBytes分别是HTTPRequestHeaders和Byte[]类型,为了调用这个方法必须将HTTP的header和body转换为这两个类型,不如字符串来的简便。这个时候utilIssueRequest函数正好满足我们的定制需要,可以精确的控制一个请求的细节,类似于Composer中的Raw。下面的代码是一个使用utilIssueRequest函数的实例,具体的HTTP请求以字符串的形式拼接起来。

    1234567891011121314151617181920212223242526272829303132
  •    
  • public static ContextAction("Probe this!")function ProbeSession(oSessions: Session[]) {         if (oSessions.Length == 0) return;    FiddlerApplication.Log.LogString("Probing...");         var selected: Session = oSessions[0];    var raw = "";         // methods    var method:String = selected.RequestMethod;    var url:String = selected.fullUrl;    var protocol = "HTTP/1.1";    FiddlerApplication.Log.LogString(method + " " + url + " " + protocol);    raw += method + " " + url + " " + protocol + "\r\n";         // headers    for (var i:int = 0; i < selected.oRequest.headers.Count(); i++) {        var header = selected.oRequest.headers[i];        FiddlerApplication.Log.LogString(header);        raw += header + "\r\n";    }         // body    FiddlerApplication.Log.LogString("---");    var body = selected.GetRequestBodyAsString();    FiddlerApplication.Log.LogString(body);    raw += "\r\n" + body;         FiddlerObject.utilIssueRequest(raw);    FiddlerApplication.Log.LogString("Request has been Send.");}
  •    
  • HTTP请求的格式如下:

    1234567891011
  •    
  • POST http://localhost/get_random_server.php HTTP/1.1Host: localhostConnection: keep-aliveAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36Accept-Encoding: gzip,deflate,sdchAccept-Language: zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4Content-Type: application/x-www-form-urlencodedContent-Length: 23 data=%E4%BD%A0%E5%A5%BD
  •    
  • 后面的工作就水到渠成了,通过SendRequestAndWait获取请求A的结果,解析请求A结果获取sid参数,然后拼接HTTP请求调用utilIssueRequest函数,此处从略。