[
  {
    "path": "Rakefile",
    "content": "require \"rubygems\"\nrequire \"rake/gempackagetask\"\nrequire \"rake/rdoctask\"\n\nbegin\n  require 'jeweler'\n  Jeweler::Tasks.new do |gemspec|\n    gemspec.name = \"net-http-spy\"\n    gemspec.summary = \"Ever wondered what HTTP requests the Ruby gem you are using to connect to a third party API is making? Use HTTP Spy to see what is going on behind the scenes.\"\n    gemspec.email = \"martin@beyondthetype.com\"\n    gemspec.homepage = \"http://github.com/martinbtt/net-http-spy\"\n    gemspec.description = \"Ever wondered what HTTP requests the Ruby gem you are using to connect to a third party API is making? Use HTTP Spy to see what is going on behind the scenes.\"\n    gemspec.authors = [\"Martin Sadler\"]\n    gemspec.files.include Dir[\"examples/*.rb\"] + [\"readme.markdown\"]\n  end\nrescue LoadError\n  puts \"Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com\"\nend\n\ntask :default => :spec\n\nrequire \"spec\"\nrequire \"spec/rake/spectask\"\nSpec::Rake::SpecTask.new do |t|\n  t.spec_opts = %w(--format specdoc --colour)\n  t.libs = [\"spec\"]\nend\n\n\n# Generate documentation\nRake::RDocTask.new do |rd|\n  rd.main = \"readme.markdown\"\n  rd.rdoc_files.include(\"readme.markdown\", \"lib/**/*.rb\")\n  rd.rdoc_dir = \"rdoc\"\nend\n\ndesc 'Clear out RDoc and generated packages'\ntask :clean => [:clobber_rdoc, :clobber_package] do\n  rm \"#{spec.name}.gemspec\"\nend\n"
  },
  {
    "path": "VERSION",
    "content": "0.2.1\n"
  },
  {
    "path": "examples/fogbugz.rb",
    "content": "# Just showing an example of something other than Twitter.\nrequire 'rubygems'\nrequire 'fogbugz-api' # sudo gem install austinmoody-fogbugz-api\nrequire File.expand_path(File.join(File.dirname(__FILE__),'..','lib','spy'))\n\nconfig = {:username    => \"yourusername\",\n          :password    => \"yourpass\", \n          :domain      => \"yourdomain.fogbugz.com\"\n          }\n\nNet::HTTP.http_logger_options = {:body => true, :trace => false}\n\n@fogbugz = FogBugz.new(config[:domain],true) # create instance\n@fogbugz.logon(config[:username],config[:password]) # logs into FogBugz and sets *token*\n"
  },
  {
    "path": "examples/google.rb",
    "content": "# Just showing an example of something other than Twitter. \n# Garb lets you access the Google Analytics API\nrequire 'rubygems'\nrequire 'garb'\nrequire File.expand_path(File.join(File.dirname(__FILE__),'..','lib','net-http-spy'))\n\nNet::HTTP.http_logger_options = {:body => false, :trace => false, :verbose => false}\nGarb::Session.login('yourgoogleusername', 'yourpassword')\n"
  },
  {
    "path": "examples/twitter-calltrace.rb",
    "content": "# See where the external API calls take place within the gem you are using with the :trace option \nrequire 'rubygems'\nrequire 'twitter'\nrequire File.expand_path(File.join(File.dirname(__FILE__),'..','lib','net-http-spy'))\n\nNet::HTTP.http_logger_options = {:trace => true}\nTwitter::Search.new('httparty').each { |r| r }\n"
  },
  {
    "path": "examples/twitter-customlog.rb",
    "content": "# By default the logger outputs to STDOUT, it's easy to change this to a file if you like\n# Great to capture and then use for testing with tools like FakeWeb when combined with :body => true \nrequire 'rubygems'\nrequire 'twitter'\nrequire File.expand_path(File.join(File.dirname(__FILE__),'..','lib','net-http-spy'))\n\nNet::HTTP.http_logger = Logger.new('twitter.log')\nTwitter::Search.new('httparty').each { |r| r }\n"
  },
  {
    "path": "examples/twitter-simple.rb",
    "content": "# Simplist example. All you need to do is include the spy lib for it to start doing the right thing\nrequire 'rubygems'\nrequire 'twitter'\nrequire File.expand_path(File.join(File.dirname(__FILE__),'..','lib','net-http-spy'))\n\nTwitter::Search.new('httparty').each { |r| r }\n"
  },
  {
    "path": "examples/twitter-verbose.rb",
    "content": "# Net::HTTP has it's own logging/debug functionality. Turn on :verbose to show the full raw HTTP communication\nrequire 'rubygems'\nrequire 'twitter'\nrequire File.expand_path(File.join(File.dirname(__FILE__),'..','lib','net-http-spy'))\n\nNet::HTTP.http_logger_options = {:verbose => true}\nTwitter::Search.new('httparty').each { |r| r }\n"
  },
  {
    "path": "examples/twitter-withbody.rb",
    "content": "# Display the full response/request body. Usually just the response code is shown.\nrequire 'rubygems'\nrequire 'twitter'\nrequire File.expand_path(File.join(File.dirname(__FILE__),'..','lib','net-http-spy'))\n\nNet::HTTP.http_logger_options = {:body => true}\nTwitter::Search.new('httparty').each { |r| r }\n"
  },
  {
    "path": "lib/net-http-spy.rb",
    "content": "require 'net/https'\nrequire 'logger'\nrequire 'cgi'\n\n# HTTP SPY\nmodule Net\n  class HTTP\n    alias :old_initialize :initialize\n    alias :old_request :request\n\n    class << self\n      attr_accessor :http_logger\n      attr_accessor :http_logger_options\n    end\n\n    def initialize(*args, &block)\n      self.class.http_logger_options ||= {}\n      defaults =  {:body => false, :trace => false, :verbose => false, :limit => -1}\n      self.class.http_logger_options = (self.class.http_logger_options == :default) ? defaults : self.class.http_logger_options\n      @logger_options = defaults.merge(self.class.http_logger_options)\n      @params_limit = @logger_options[:params_limit] || @logger_options[:limit]\n      @body_limit   = @logger_options[:body_limit]   || @logger_options[:limit]\n      \n      self.class.http_logger.info \"CONNECT: #{args.inspect}\" if !@logger_options[:verbose]\n\n      old_initialize(*args, &block)\n      @debug_output   = self.class.http_logger if @logger_options[:verbose]\n    end\n\n\n    def request(*args, &block)\n      unless started? || @logger_options[:verbose]\n        req = args[0].class::METHOD\n        self.class.http_logger.info \"#{req} #{args[0].path}\"\n      end\n\n      result = old_request(*args, &block)\n      unless started? || @logger_options[:verbose]\n\n        self.class.http_logger.info \"PARAMS #{CGI.parse(args[0].body).inspect[0..@params_limit]} \" if args[0].body && req != 'CONNECT'\n        self.class.http_logger.info \"TRACE: #{caller.reverse}\" if @logger_options[:trace]\n        self.class.http_logger.info \"BODY: #{(@logger_options[:body] ? result.body : result.class.name)[0..@body_limit]}\"\n      end\n      result\n    end\n\n\n  end\n\nend\n\nNet::HTTP.http_logger = Logger.new(STDOUT)\n"
  },
  {
    "path": "net-http-spy.gemspec",
    "content": "# Generated by jeweler\n# DO NOT EDIT THIS FILE DIRECTLY\n# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command\n# -*- encoding: utf-8 -*-\n\nGem::Specification.new do |s|\n  s.name = %q{net-http-spy}\n  s.version = \"0.2.1\"\n\n  s.required_rubygems_version = Gem::Requirement.new(\">= 0\") if s.respond_to? :required_rubygems_version=\n  s.authors = [\"Martin Sadler\"]\n  s.date = %q{2009-12-05}\n  s.description = %q{Ever wondered what HTTP requests the Ruby gem you are using to connect to a third party API is making? Use HTTP Spy to see what is going on behind the scenes.}\n  s.email = %q{martin@beyondthetype.com}\n  s.files = [\n    \"Rakefile\",\n     \"VERSION\",\n     \"examples/fogbugz.rb\",\n     \"examples/google.rb\",\n     \"examples/twitter-calltrace.rb\",\n     \"examples/twitter-customlog.rb\",\n     \"examples/twitter-simple.rb\",\n     \"examples/twitter-verbose.rb\",\n     \"examples/twitter-withbody.rb\",\n     \"lib/net-http-spy.rb\",\n     \"net-http-spy.gemspec\",\n     \"readme.markdown\",\n     \"spec/spec.opts\",\n     \"spec/spec_helper.rb\",\n     \"spec/spy_spec.rb\"\n  ]\n  s.homepage = %q{http://github.com/martinbtt/net-http-spy}\n  s.rdoc_options = [\"--charset=UTF-8\"]\n  s.require_paths = [\"lib\"]\n  s.rubygems_version = %q{1.3.5}\n  s.summary = %q{Ever wondered what HTTP requests the Ruby gem you are using to connect to a third party API is making? Use HTTP Spy to see what is going on behind the scenes.}\n  s.test_files = [\n    \"spec/spec_helper.rb\",\n     \"spec/spy_spec.rb\",\n     \"examples/fogbugz.rb\",\n     \"examples/google.rb\",\n     \"examples/twitter-calltrace.rb\",\n     \"examples/twitter-customlog.rb\",\n     \"examples/twitter-simple.rb\",\n     \"examples/twitter-verbose.rb\",\n     \"examples/twitter-withbody.rb\"\n  ]\n\n  if s.respond_to? :specification_version then\n    current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION\n    s.specification_version = 3\n\n    if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then\n    else\n    end\n  else\n  end\nend\n\n"
  },
  {
    "path": "readme.markdown",
    "content": "## About\n\nEver wondered what HTTP requests the Ruby gem you are using to connect to a third party\nAPI is making? Use HTTP Spy to see what is going on behind the scenes.\n\n## Installation\n\nsudo gem install martinbtt-net-http-spy\n\n## Example Usage\n\n    require 'rubygems'\n    require 'twitter'\n    gem 'net-http-spy'\n    require 'net-http-spy'\n    \n    Twitter::Search.new('httparty').each { |r| r }\n    # Outputs...\n    -- : CONNECT: [\"search.twitter.com\", 80]\n    -- : GET /search.json?q=httparty\n    -- : BODY: Net::HTTPOK\n\n\nSee the examples folder for more. \n\n## Further Options\n\nShow the call trace to the originating line of code in the third party gem\n    \n    Net::HTTP.http_logger_options = {:trace => true}\n\nOutput the body of the request \n\n    Net::HTTP.http_logger_options = {:body => true}\n\nShow the full raw HTTP output\n   \n    Net::HTTP.http_logger_options = {:verbose => true}\n\nChange the logger. By default HTTP spy logs to STDOUT \n\n    Net::HTTP.http_logger = Logger.new('twitter.log')\n\n## Bonus Points\n\nUse it to grab sample data for FakeWeb = testing goodness.\n\n## Notes\n\nThis is a pretty early release. I'm sure there is plenty that can be done to improve compatibility\nas several libraries call Net::HTTP in a slightly different way. \nFeel free to fork and send in pull requests/patches.\n\n## Find Me \n\nMartin Sadler (martin -- at -- beyondthetype.com)\n\n* Blog:      http://www.beyondthetype.com\n* Follow:    http://twitter.com/martinbtt\n* Code:      http://github.com/martinbtt\n* Recommend: http://www.workingwithrails.com/person/5152-martin-sadler"
  },
  {
    "path": "spec/spec.opts",
    "content": "--format\n  progress\n--colour\n"
  },
  {
    "path": "spec/spec_helper.rb",
    "content": "require 'rubygems'\ngem 'rspec'\nrequire 'spec'\nrequire 'net/http'\nrequire 'open-uri'\nrequire 'twitter'\nrequire 'mechanize'\n\nrequire 'webmock/rspec'\ninclude WebMock\n\nLIVE = ENV['LIVE']\nWebMock.allow_net_connect! if LIVE\n\n\nrequire File.join(File.dirname(__FILE__), '..', 'lib', 'net-http-spy')\n\n\nclass DummyLogger \n  \n  attr_accessor :lines\n  \n  def initialize\n    reset!\n  end\n  \n  def <<(msg)\n    @lines << msg\n  end\n  \n  def info(msg)\n     @lines << msg\n  end\n\n  def reset!\n    @lines = []\n  end\n  \nend\n"
  },
  {
    "path": "spec/spy_spec.rb",
    "content": "require File.join(File.dirname(__FILE__), 'spec_helper')\n\n# Bare bones spec to make sure the core functionality is working\ndescribe \"Net:HTTP Spying on\" do\n  before(:all) do\n    Net::HTTP.http_logger = DummyLogger.new()\n  end\n\n  describe \"a get request with default options\" do\n\n    before(:all) do\n      stub_request(:any, \"search.twitter.com/search.json?q=httparty\").to_return(:body =>   \"\\{\\\"results\\\"\\: 1\\}\", :status => 200) unless LIVE\n      Net::HTTP.http_logger_options = :default\n      Twitter::Search.new('httparty').fetch\n    end\n\n    it \"should give the connection\" do\n      Net::HTTP.http_logger.lines.should include(\"CONNECT: [\\\"search.twitter.com\\\", 80]\")\n    end\n\n    it \"should give GET uri and query string\" do\n      Net::HTTP.http_logger.lines.should include(\"GET /search.json?q=httparty\")\n    end\n\n    it \"should give the BODY response code\" do\n      Net::HTTP.http_logger.lines.should include(\"BODY: Net::HTTPOK\")\n    end\n  end\n\n\n  describe \"a get request with body option set to true\" do\n    before(:each) do\n      stub_request(:any, \"search.twitter.com/search.json?q=httparty\").to_return(:body =>   \"\\{\\\"results\\\"\\: 1\\}\", :status => 200) unless LIVE\n      Net::HTTP.http_logger_options = {:body => true}\n    end\n\n    it \"should give the body output\" do\n      Twitter::Search.new('httparty').fetch\n      Net::HTTP.http_logger.lines\n      Net::HTTP.http_logger.lines.grep(/BODY: \\{\\\"results\\\":/).should_not be_empty\n    end\n  end\n\n\n  describe \"a get request with trace option set to true\" do\n    before(:each) do\n      Net::HTTP.http_logger_options = {:trace => true}\n      stub_request(:any, \"search.twitter.com/search.json?q=httparty\").to_return(:body =>   \"\\{\\\"results\\\"\\: 1\\}\", :status => 200) unless LIVE\n    end\n\n    it \"should give the trace output\" do\n      Twitter::Search.new('httparty').fetch\n      Net::HTTP.http_logger.lines.grep(/TRACE: /).should_not be_empty\n    end\n  end\n\n  describe \"a post request with default options\" do\n    before(:all) do\n      Net::HTTP.http_logger_options = {:verbose => false}\n      stub_request(:any, \"search.twitter.com/search\").to_return(:body => \"\\{\\\"results\\\"\\: 1\\}\", :status => 200) unless LIVE\n      @connection = Net::HTTP.new('search.twitter.com')\n      @connection.post('/search','?q=hello')\n    end\n\n    it \"should give the post url\" do\n      Net::HTTP.http_logger.lines.should include(\"POST /search\")\n    end\n\n\n    if LIVE # only works if real live request \n      it \"should give the post params\" do\n        Net::HTTP.http_logger.lines.should include(\"PARAMS {\\\"?q\\\"=>[\\\"hello\\\"]} \")\n      end\n    end\n\n    it \"should give the BODY response code\" do\n      Net::HTTP.http_logger.lines.should include(\"BODY: Net::HTTPOK\")\n    end\n  end\n\n  after(:all) do\n    Net::HTTP.http_logger.reset!\n  end\nend\n"
  }
]