{"id":1407,"date":"2016-01-07T17:20:01","date_gmt":"2016-01-07T22:20:01","guid":{"rendered":"https:\/\/www.redline13.com\/blog\/?p=1407"},"modified":"2016-01-07T17:20:01","modified_gmt":"2016-01-07T22:20:01","slug":"writing-firefox-plugin-to-listen-to-http-traffic","status":"publish","type":"post","link":"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/","title":{"rendered":"Writing Firefox Plugin to listen to HTTP Traffic"},"content":{"rendered":"<div>The recorder was built by using Firefox docs, examples, and some open projects that demonstrate how to listen to HTTP traffic within a Firefox extension.<\/div>\n<h3><strong>Overview of source files<\/strong><\/h3>\n<div>We built this separating the work into 3 prototype objects.<\/div>\n<ul>\n<li>HttpRecorder.js &#8211; setup listening for requests\/response<\/li>\n<li>HttpVisitor.js &#8211; when a request or response is made we need to inspect the headers and data<\/li>\n<li>HttpPostParser.js &#8211; take a deeper look into the POST data stream<\/li>\n<\/ul>\n<div>Source\u00a0<a href=\"https:\/\/github.com\/redline13\/selenium-jmeter\/tree\/master\/content\/library\/recorder\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/redline13\/selenium-jmeter\/tree\/master\/content\/library\/recorder<\/a><\/div>\n<h3><strong>Getting access to the Observer Service<\/strong><\/h3>\n<ul>\n<li>This is how we access the service.<\/li>\n<\/ul>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">HttpRecorder.prototype.observerService = Components.classes[\"@mozilla.org\/observer-service;1\"].getService(Components.interfaces.nsIObserverService);\n<\/pre>\n<\/div>\n<h3><b>Observing the HTTP Traffic<\/b><\/h3>\n<ul>\n<li>Using the Observer service we sign up for certain topics (events)<\/li>\n<li>this &#8211; means our object provides the methods for callback<\/li>\n<\/ul>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">HttpRecorder.prototype.start = function() {\n\u00a0 \u00a0 this.observerService.addObserver(this, \"http-on-modify-request\", false);\n\u00a0 \u00a0 this.observerService.addObserver(this, \"http-on-examine-response\", false);\n};<\/pre>\n<\/div>\n<div>This is a pattern provided for Firefox extensions which allows actual modifications of the requests, though our plugin only needs to watch.<\/div>\n<div><\/div>\n<div>Using \u2018this\u2019 as the first parameter means our javascript object implement a function called \u2018observe\u2019 which will invoked for each web request.<\/div>\n<div><\/div>\n<div>This will capture all web requests not just for the tab you are on. \u00a0There are other mechanism to watch firefox behavior, like monitoring the DOM\u00a0that can be page specific, read more about <a href=\"https:\/\/developer.mozilla.org\/en-US\/Add-ons\/Overlay_Extensions\/XUL_School\/Intercepting_Page_Loads\">intercepting Web\u00a0Requests<\/a>. \u00a0Don\u2019t be surprised when you start seeing requests that you were not expecting.<\/div>\n<div><\/div>\n<h3><b>The Observer callback function<\/b><\/h3>\n<div>The <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Tech\/XPCOM\/Reference\/Interface\/nsIObserverService#notifyObservers()\">observe function<\/a> is the callback for all events you are going to capture.<\/div>\n<ul>\n<li>Subject:\u00a0A notification specific interface pointer, so you must know the type based on the event<\/li>\n<li>Topic: \u00a0the string representing the event<\/li>\n<li>Data: optional data object depending on event<\/li>\n<\/ul>\n<div><\/div>\n<div>The biggest learning curve was understanding the \u2018<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Tech\/XPCOM\/Reference\/Interface\/nsISupports#QueryInterface()\">QueryInterface<\/a>\u2019 function. \u00a0This looks into the current event (Subject) and sets its\u00a0interface,\u00a0to the Interface you pass in. \u00a0 I grokked it as casting to a type.<\/div>\n<ul>\n<li>Process the observe callback looking for the topics we care about<\/li>\n<li>http-on-modify-request\u00a0is HTTP requests,<\/li>\n<li>http-on-examine-response \u00a0is the HTTP Response<\/li>\n<\/ul>\n<div><\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">HttpRecorder.prototype.observe = function(subject, topic, data) {\n\u00a0 \u00a0 var chan = subject.QueryInterface(Components.interfaces.nsIHttpChannel);\n\n\u00a0 \u00a0 switch (topic) {\n\u00a0 \u00a0 \u00a0 \u00a0 case 'http-on-modify-request':\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 this.onRequest(subject);\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break;\n\u00a0 \u00a0 \u00a0 \u00a0 case 'http-on-examine-response':\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 this.onResponse(subject);\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break;\n\u00a0 \u00a0 \u00a0 \u00a0 default:\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break;\n\u00a0 \u00a0 }\n};<\/pre>\n<\/div>\n<h3><b>Stop Observing the HTTP Traffic<\/b><\/h3>\n<ul>\n<li>Simply remove the observers<\/li>\n<\/ul>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">HttpRecorder.prototype.stop = function() {\n\u00a0 \u00a0 try {\n\u00a0 \u00a0 \u00a0 \u00a0 this.observerService.removeObserver(this, \"http-on-examine-response\");\n\u00a0 \u00a0 \u00a0 \u00a0 this.observerService.removeObserver(this, \"http-on-modify-request\");\n\u00a0 \u00a0 } catch (e) {\n\u00a0 \u00a0 \u00a0 \u00a0 console.log(\"Failed to remove observer\", e);\n\u00a0 \u00a0 }\n};<\/pre>\n<\/div>\n<h3><b>Parsing the HTTP Request<\/b><\/h3>\n<ul>\n<li>Validate we want to parse this request<\/li>\n<li>Parse the basics<\/li>\n<li>Parse the headers<\/li>\n<li>if POST parse the POST<\/li>\n<\/ul>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">HttpRecorder.prototype.onRequest = function(http) {\n\n\u00a0\u00a0 var uri = http.URI.asciiSpec;\n\n\u00a0 \u00a0\/\/ Our own function to limit what we capture.\n\u00a0\u00a0 if (this.shouldInclude(uri) &amp;&amp; !this.shouldExclude(uri)) {\n\n\u00a0 \u00a0 \u00a0 \u00a0 var request = {};\n\u00a0 \u00a0 \u00a0 \u00a0 request.timestamp = Date.now();\n\u00a0 \u00a0 \u00a0 \u00a0 request.uri = uri;\n\u00a0 \u00a0 \u00a0 \u00a0 request.method = http.requestMethod;\n\u00a0 \u00a0 \u00a0 \u00a0 \/\/ ... Missing - but here we pick apart the request\u00a0\n\n\u00a0 \u00a0 \u00a0 \u00a0 \/\/ The headers of the request are not directly available this wraps the work\u00a0\n\u00a0 \u00a0 \u00a0 \u00a0 var visitor = new HttpVisitor(http);\n\u00a0 \u00a0 \u00a0 \u00a0 request.headers = visitor.walkRequest();\n\u00a0 \u00a0 \u00a0 \u00a0\n\u00a0 \u00a0 \u00a0 \u00a0 \/\/ Parsing an HTTP Post\u00a0requires a different interface so the work is separated out.\n\u00a0 \u00a0 \u00a0 \u00a0 if (http.requestMethod == 'POST') {\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 var post = visitor.parsePost();\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if ( post ) {\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 request.postBody = post.body;\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 request.postHeaders = post.headers;\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 request.postLines = post.lines;\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 request.postBinary = post.binary;\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }\n\u00a0 \u00a0 \u00a0 \u00a0 }\n\u00a0 \u00a0 \u00a0 \u00a0 this.requests.push(request);\n\u00a0 \u00a0 } else {\n\u00a0 \u00a0 \u00a0 \u00a0 this.ignoredRequests++;\n\u00a0 \u00a0 }\n};\n<\/pre>\n<\/div>\n<div><\/div>\n<h3><strong>Parsing the Response and matching to the request<\/strong><\/h3>\n<ul>\n<li>On response based on URI match to request<\/li>\n<li>Get request meta<\/li>\n<li>Get request headers<\/li>\n<\/ul>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">HttpRecorder.prototype.onResponse = function(http) {\n  var uri = http.URI.asciiSpec;\n  try {\n    if (this.shouldInclude(uri) &amp;&amp; !this.shouldExclude(uri)) {\n\n      \/\/ Match to request. \n      var theRequest = null;\n      for (var i in this.requests) {\n        if (this.requests[i].uri == uri) {\n          theRequest = this.requests[i];\n          break;\n        }\n      }\n      if (theRequest != null) {\n        var response = {};\n        response.uri = uri;\n        response.timestamp = Date.now();\n        response.method = http.requestMethod;\n        \/\/ .... missing but parses more of the response \n\n        \/\/ Parse the response headers\n        var visitor = new HttpVisitor(http);\n        response.headers = visitor.walkResponse();\n        theRequest.response = response;\n      } else {\n        this.missedResponses++;\n      }\n\n    } else {\n      this.ignoredResponses++;\n    }\n  } catch (e) {\n    console.log(\"Exception\", e);\n  }\n\n};\n<\/pre>\n<\/div>\n<h3><strong>Parsing the Request or Response Headers<\/strong><\/h3>\n<div>From above we can see we pass the request to HttpVisitor then call .walkResponse() or .walkRequest()<\/div>\n<ul>\n<li>Earlier we had cast the subject to\u00a0<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Tech\/XPCOM\/Reference\/Interface\/nsIHttpChannel\">Components.interfaces.nsIHttpChannel<\/a>\u00a0which has two functions\n<ul>\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Tech\/XPCOM\/Reference\/Interface\/nsIHttpChannel#visitRequestHeaders()\">visitRequestHeaders(&#8230;)<\/a><\/li>\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Tech\/XPCOM\/Reference\/Interface\/nsIHttpChannel#visitResponseHeaders()\">visitResponseHeaders(&#8230;)<\/a><\/li>\n<\/ul>\n<\/li>\n<li>These calls need a class which has a the corresponding callback function &#8211; visitHeader(name, value) which is below<\/li>\n<\/ul>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">HttpVisitor.prototype.walkRequest = function() {\n  this.headers = {};\n  \/\/ Tell the request to\n  this.http.visitRequestHeaders(this);\n  return this.headers;\n};\n\nHttpVisitor.prototype.walkResponse = function() {\n  this.headers = {};\n        \/\/ Tell the response to\n  this.http.visitResponseHeaders(this);\n  return this.headers;\n};\n\n\/\/ The callback \nHttpVisitor.prototype.visitHeader = function(name, value) {\n  this.headers[name] = value;\n};\n\n<\/pre>\n<\/div>\n<div><\/div>\n<div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>The recorder was built by using Firefox docs, examples, and some open projects that demonstrate how to listen to HTTP traffic within a Firefox extension. Overview of source files We built this separating the work into 3 prototype objects. HttpRecorder.js &#8211; setup listening for requests\/response HttpVisitor.js &#8211; when a request or response is made we need to inspect the headers and data HttpPostParser.js &#8211; take a deeper look into the POST data stream Source\u00a0https:\/\/github.com\/redline13\/selenium-jmeter\/tree\/master\/content\/library\/recorder Getting access<a class=\"more-link\" href=\"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/\">Read More &rarr;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[201,215,254],"class_list":{"0":"entry","1":"post","2":"publish","3":"author-user","4":"post-1407","6":"format-standard","7":"category-blog","8":"post_tag-extension","9":"post_tag-firefox","10":"post_tag-http-traffic"},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.12 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Writing Firefox Plugin to listen to HTTP Traffic - RedLine13<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Writing Firefox Plugin to listen to HTTP Traffic - RedLine13\" \/>\n<meta property=\"og:description\" content=\"The recorder was built by using Firefox docs, examples, and some open projects that demonstrate how to listen to HTTP traffic within a Firefox extension. Overview of source files We built this separating the work into 3 prototype objects. HttpRecorder.js &#8211; setup listening for requests\/response HttpVisitor.js &#8211; when a request or response is made we need to inspect the headers and data HttpPostParser.js &#8211; take a deeper look into the POST data stream Source\u00a0https:\/\/github.com\/redline13\/selenium-jmeter\/tree\/master\/content\/library\/recorder Getting accessRead More &rarr;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/\" \/>\n<meta property=\"og:site_name\" content=\"RedLine13\" \/>\n<meta property=\"article:published_time\" content=\"2016-01-07T22:20:01+00:00\" \/>\n<meta name=\"author\" content=\"RedLine13\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"RedLine13\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/\"},\"author\":{\"name\":\"RedLine13\",\"@id\":\"https:\/\/www.redline13.com\/blog\/#\/schema\/person\/4acbcdcb8a9c72ec5a274e69c0ebea28\"},\"headline\":\"Writing Firefox Plugin to listen to HTTP Traffic\",\"datePublished\":\"2016-01-07T22:20:01+00:00\",\"dateModified\":\"2016-01-07T22:20:01+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/\"},\"wordCount\":439,\"publisher\":{\"@id\":\"https:\/\/www.redline13.com\/blog\/#organization\"},\"keywords\":[\"extension\",\"firefox\",\"http traffic\"],\"articleSection\":[\"Blog\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/\",\"url\":\"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/\",\"name\":\"Writing Firefox Plugin to listen to HTTP Traffic - RedLine13\",\"isPartOf\":{\"@id\":\"https:\/\/www.redline13.com\/blog\/#website\"},\"datePublished\":\"2016-01-07T22:20:01+00:00\",\"dateModified\":\"2016-01-07T22:20:01+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.redline13.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Writing Firefox Plugin to listen to HTTP Traffic\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.redline13.com\/blog\/#website\",\"url\":\"https:\/\/www.redline13.com\/blog\/\",\"name\":\"RedLine13\",\"description\":\"(Almost) Free Load Testing in the Cloud\",\"publisher\":{\"@id\":\"https:\/\/www.redline13.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.redline13.com\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.redline13.com\/blog\/#organization\",\"name\":\"RedLine13\",\"url\":\"https:\/\/www.redline13.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.redline13.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.redline13.com\/blog\/wp-content\/uploads\/2013\/06\/cropped-rl13-header-logo.jpg\",\"contentUrl\":\"https:\/\/www.redline13.com\/blog\/wp-content\/uploads\/2013\/06\/cropped-rl13-header-logo.jpg\",\"width\":300,\"height\":68,\"caption\":\"RedLine13\"},\"image\":{\"@id\":\"https:\/\/www.redline13.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.redline13.com\/blog\/#\/schema\/person\/4acbcdcb8a9c72ec5a274e69c0ebea28\",\"name\":\"RedLine13\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.redline13.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514?s=96&d=mm&r=g\",\"caption\":\"RedLine13\"},\"sameAs\":[\"http:\/\/127.0.0.1\"],\"url\":\"https:\/\/www.redline13.com\/blog\/author\/user\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Writing Firefox Plugin to listen to HTTP Traffic - RedLine13","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/","og_locale":"en_US","og_type":"article","og_title":"Writing Firefox Plugin to listen to HTTP Traffic - RedLine13","og_description":"The recorder was built by using Firefox docs, examples, and some open projects that demonstrate how to listen to HTTP traffic within a Firefox extension. Overview of source files We built this separating the work into 3 prototype objects. HttpRecorder.js &#8211; setup listening for requests\/response HttpVisitor.js &#8211; when a request or response is made we need to inspect the headers and data HttpPostParser.js &#8211; take a deeper look into the POST data stream Source\u00a0https:\/\/github.com\/redline13\/selenium-jmeter\/tree\/master\/content\/library\/recorder Getting accessRead More &rarr;","og_url":"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/","og_site_name":"RedLine13","article_published_time":"2016-01-07T22:20:01+00:00","author":"RedLine13","twitter_card":"summary_large_image","twitter_misc":{"Written by":"RedLine13","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/#article","isPartOf":{"@id":"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/"},"author":{"name":"RedLine13","@id":"https:\/\/www.redline13.com\/blog\/#\/schema\/person\/4acbcdcb8a9c72ec5a274e69c0ebea28"},"headline":"Writing Firefox Plugin to listen to HTTP Traffic","datePublished":"2016-01-07T22:20:01+00:00","dateModified":"2016-01-07T22:20:01+00:00","mainEntityOfPage":{"@id":"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/"},"wordCount":439,"publisher":{"@id":"https:\/\/www.redline13.com\/blog\/#organization"},"keywords":["extension","firefox","http traffic"],"articleSection":["Blog"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/","url":"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/","name":"Writing Firefox Plugin to listen to HTTP Traffic - RedLine13","isPartOf":{"@id":"https:\/\/www.redline13.com\/blog\/#website"},"datePublished":"2016-01-07T22:20:01+00:00","dateModified":"2016-01-07T22:20:01+00:00","breadcrumb":{"@id":"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.redline13.com\/blog\/2016\/01\/writing-firefox-plugin-to-listen-to-http-traffic\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.redline13.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Writing Firefox Plugin to listen to HTTP Traffic"}]},{"@type":"WebSite","@id":"https:\/\/www.redline13.com\/blog\/#website","url":"https:\/\/www.redline13.com\/blog\/","name":"RedLine13","description":"(Almost) Free Load Testing in the Cloud","publisher":{"@id":"https:\/\/www.redline13.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.redline13.com\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.redline13.com\/blog\/#organization","name":"RedLine13","url":"https:\/\/www.redline13.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.redline13.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.redline13.com\/blog\/wp-content\/uploads\/2013\/06\/cropped-rl13-header-logo.jpg","contentUrl":"https:\/\/www.redline13.com\/blog\/wp-content\/uploads\/2013\/06\/cropped-rl13-header-logo.jpg","width":300,"height":68,"caption":"RedLine13"},"image":{"@id":"https:\/\/www.redline13.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.redline13.com\/blog\/#\/schema\/person\/4acbcdcb8a9c72ec5a274e69c0ebea28","name":"RedLine13","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.redline13.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514?s=96&d=mm&r=g","caption":"RedLine13"},"sameAs":["http:\/\/127.0.0.1"],"url":"https:\/\/www.redline13.com\/blog\/author\/user\/"}]}},"_links":{"self":[{"href":"https:\/\/www.redline13.com\/blog\/wp-json\/wp\/v2\/posts\/1407","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.redline13.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.redline13.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.redline13.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.redline13.com\/blog\/wp-json\/wp\/v2\/comments?post=1407"}],"version-history":[{"count":0,"href":"https:\/\/www.redline13.com\/blog\/wp-json\/wp\/v2\/posts\/1407\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.redline13.com\/blog\/wp-json\/wp\/v2\/media?parent=1407"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.redline13.com\/blog\/wp-json\/wp\/v2\/categories?post=1407"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.redline13.com\/blog\/wp-json\/wp\/v2\/tags?post=1407"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}