Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

add the main project files

  • Loading branch information...
commit 8dbbee4aa4eaa8cef3f96e747d03211b059435d0 0 parents
@martinbtt authored
115 Rakefile
@@ -0,0 +1,115 @@
+require "rubygems"
+require "rake/gempackagetask"
+require "rake/rdoctask"
+
+task :default => :spec
+
+require "spec"
+require "spec/rake/spectask"
+Spec::Rake::SpecTask.new do |t|
+ t.spec_opts = %w(--format specdoc --colour)
+ t.libs = ["spec"]
+end
+
+# This builds the actual gem. For details of what all these options
+# mean, and other ones you can add, check the documentation here:
+#
+# http://rubygems.org/read/chapter/20
+#
+spec = Gem::Specification.new do |s|
+
+ # Change these as appropriate
+ s.name = "nethttp-spy"
+ s.version = "0.1.0"
+ s.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."
+ s.author = "Martin Sadler"
+ s.email = "martin@beyondthetype.com"
+ s.homepage = "http://beyondthetype.com"
+
+ s.has_rdoc = true
+ s.extra_rdoc_files = %w(readme.markdown)
+ s.rdoc_options = %w(--main readme.markdown)
+
+ # Add any extra files to include in the gem
+ s.files = %w(readme.markdown spy.rb) + Dir.glob("{spec,lib,examples}/**/*")
+
+ s.require_paths = ["lib"]
+
+ # If you want to depend on other gems, add them here, along with any
+ # relevant versions
+ # s.add_dependency("some_other_gem", "~> 0.1.0")
+
+ s.add_development_dependency("rspec") # add any other gems for testing/development
+ s.add_development_dependency("twitter")
+
+ # If you want to publish automatically to rubyforge, you'll may need
+ # to tweak this, and the publishing task below too.
+ s.rubyforge_project = "nethttp-spy"
+end
+
+# This task actually builds the gem. We also regenerate a static
+# .gemspec file, which is useful if something (i.e. GitHub) will
+# be automatically building a gem for this project. If you're not
+# using GitHub, edit as appropriate.
+Rake::GemPackageTask.new(spec) do |pkg|
+ pkg.gem_spec = spec
+
+ # Generate the gemspec file for github.
+ file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
+ File.open(file, "w") {|f| f << spec.to_ruby }
+end
+
+# Generate documentation
+Rake::RDocTask.new do |rd|
+ rd.main = "readme.markdown"
+ rd.rdoc_files.include("readme.markdown", "lib/**/*.rb")
+ rd.rdoc_dir = "rdoc"
+end
+
+desc 'Clear out RDoc and generated packages'
+task :clean => [:clobber_rdoc, :clobber_package] do
+ rm "#{spec.name}.gemspec"
+end
+
+# If you want to publish to RubyForge automatically, here's a simple
+# task to help do that. If you don't, just get rid of this.
+# Be sure to set up your Rubyforge account details with the Rubyforge
+# gem; you'll need to run `rubyforge setup` and `rubyforge config` at
+# the very least.
+begin
+ require "rake/contrib/sshpublisher"
+ namespace :rubyforge do
+
+ desc "Release gem and RDoc documentation to RubyForge"
+ task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
+
+ namespace :release do
+ desc "Release a new version of this gem"
+ task :gem => [:package] do
+ require 'rubyforge'
+ rubyforge = RubyForge.new
+ rubyforge.configure
+ rubyforge.login
+ rubyforge.userconfig['release_notes'] = spec.summary
+ path_to_gem = File.join(File.dirname(__FILE__), "pkg", "#{spec.name}-#{spec.version}.gem")
+ puts "Publishing #{spec.name}-#{spec.version.to_s} to Rubyforge..."
+ rubyforge.add_release(spec.rubyforge_project, spec.name, spec.version.to_s, path_to_gem)
+ end
+
+ desc "Publish RDoc to RubyForge."
+ task :docs => [:rdoc] do
+ config = YAML.load(
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
+ )
+
+ host = "#{config['username']}@rubyforge.org"
+ remote_dir = "/var/www/gforge-projects/nethttp-spy/" # Should be the same as the rubyforge project name
+ local_dir = 'rdoc'
+
+ Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
+ end
+ end
+ end
+rescue LoadError
+ puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
+end
14 examples/fogbugz.rb
@@ -0,0 +1,14 @@
+# Just showing an example of something other than Twitter.
+require 'rubygems'
+require 'fogbugz-api' # sudo gem install austinmoody-fogbugz-api
+require File.expand_path(File.join(File.dirname(__FILE__),'..','lib','spy'))
+
+config = {:username => "yourusername",
+ :password => "yourpass",
+ :domain => "yourdomain.fogbugz.com"
+ }
+
+Net::HTTP.http_logger_options = {:body => true, :trace => false}
+
+@fogbugz = FogBugz.new(config[:domain],true) # create instance
+@fogbugz.logon(config[:username],config[:password]) # logs into FogBugz and sets *token*
8 examples/google.rb
@@ -0,0 +1,8 @@
+# Just showing an example of something other than Twitter.
+# Garb lets you access the Google Analytics API
+require 'rubygems'
+require 'garb'
+require File.expand_path(File.join(File.dirname(__FILE__),'..','lib','spy'))
+
+Net::HTTP.http_logger_options = {:body => false, :trace => false, :verbose => false}
+Garb::Session.login('yourgoogleusername', 'yourpassword')
7 examples/twitter-calltrace.rb
@@ -0,0 +1,7 @@
+# See where the external API calls take place within the gem you are using with the :trace option
+require 'rubygems'
+require 'twitter'
+require File.expand_path(File.join(File.dirname(__FILE__),'..','lib','spy'))
+
+Net::HTTP.http_logger_options = {:trace => true}
+Twitter::Search.new('httparty').each { |r| r }
8 examples/twitter-customlog.rb
@@ -0,0 +1,8 @@
+# By default the logger outputs to STDOUT, it's easy to change this to a file if you like
+# Great to capture and then use for testing with tools like FakeWeb when combined with :body => true
+require 'rubygems'
+require 'twitter'
+require File.expand_path(File.join(File.dirname(__FILE__),'..','lib','spy'))
+
+Net::HTTP.http_logger = Logger.new('twitter.log')
+Twitter::Search.new('httparty').each { |r| r }
6 examples/twitter-simple.rb
@@ -0,0 +1,6 @@
+# Simplist example. All you need to do is include the spy lib for it to start doing the right thing
+require 'rubygems'
+require 'twitter'
+require File.expand_path(File.join(File.dirname(__FILE__),'..','lib','spy'))
+
+Twitter::Search.new('httparty').each { |r| r }
7 examples/twitter-verbose.rb
@@ -0,0 +1,7 @@
+# Net::HTTP has it's own logging/debug functionality. Turn on :verbose to show the full raw HTTP communication
+require 'rubygems'
+require 'twitter'
+require File.expand_path(File.join(File.dirname(__FILE__),'..','lib','spy'))
+
+Net::HTTP.http_logger_options = {:verbose => true}
+Twitter::Search.new('httparty').each { |r| r }
7 examples/twitter-withbody.rb
@@ -0,0 +1,7 @@
+# Display the full response/request body. Usually just the response code is shown.
+require 'rubygems'
+require 'twitter'
+require File.expand_path(File.join(File.dirname(__FILE__),'..','lib','spy'))
+
+Net::HTTP.http_logger_options = {:body => true}
+Twitter::Search.new('httparty').each { |r| r }
50 lib/spy.rb
@@ -0,0 +1,50 @@
+require 'net/https'
+require 'logger'
+require 'cgi'
+
+# HTTP SPY
+module Net
+ class HTTP
+ alias :old_initialize :initialize
+ alias :old_request :request
+
+ class << self
+ attr_accessor :http_logger
+ attr_accessor :http_logger_options
+ end
+
+ def initialize(*args, &block)
+ self.class.http_logger_options ||= {}
+ defaults = {:body => false, :trace => false, :verbose => false}
+ self.class.http_logger_options = (self.class.http_logger_options == :default) ? defaults : self.class.http_logger_options
+ @logger_options = defaults.merge(self.class.http_logger_options)
+
+ self.class.http_logger.info "CONNECT: #{args.inspect}" if !@logger_options[:verbose]
+
+ old_initialize(*args, &block)
+ @debug_output = self.class.http_logger if @logger_options[:verbose]
+ end
+
+
+ def request(*args, &block)
+ unless started? || @logger_options[:verbose]
+ req = args[0].class::METHOD
+ self.class.http_logger.info "#{req} #{args[0].path}"
+ end
+
+ result = old_request(*args, &block)
+ unless started? || @logger_options[:verbose]
+
+ self.class.http_logger.info "PARAMS #{CGI.parse(args[0].body).inspect} " if args[0].body && req != 'CONNECT'
+ self.class.http_logger.info "TRACE: #{caller.reverse}" if @logger_options[:trace]
+ self.class.http_logger.info "BODY: #{ @logger_options[:body] ? result.body : result.class.name}"
+ end
+ result
+ end
+
+
+ end
+
+end
+
+Net::HTTP.http_logger = Logger.new(STDOUT)
35 nethttp-spy.gemspec
@@ -0,0 +1,35 @@
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+ s.name = %q{nethttp-spy}
+ s.version = "0.1.0"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+ s.authors = ["Martin Sadler"]
+ s.date = %q{2009-05-07}
+ s.email = %q{martin@beyondthetype.com}
+ s.extra_rdoc_files = ["readme.markdown"]
+ s.files = ["readme.markdown", "spy.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/spy_spec.rb", "lib/spy.rb", "examples/fogbugz.rb", "examples/google.rb", "examples/twitter-calltrace.rb", "examples/twitter-customlog.rb", "examples/twitter-simple.rb", "examples/twitter-verbose.rb", "examples/twitter-withbody.rb"]
+ s.homepage = %q{http://beyondthetype.com}
+ s.rdoc_options = ["--main", "readme.markdown"]
+ s.require_paths = ["lib"]
+ s.rubyforge_project = %q{nethttp-spy}
+ s.rubygems_version = %q{1.3.3}
+ 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.}
+
+ if s.respond_to? :specification_version then
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+ s.specification_version = 3
+
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+ s.add_development_dependency(%q<rspec>, [">= 0"])
+ s.add_development_dependency(%q<twitter>, [">= 0"])
+ else
+ s.add_dependency(%q<rspec>, [">= 0"])
+ s.add_dependency(%q<twitter>, [">= 0"])
+ end
+ else
+ s.add_dependency(%q<rspec>, [">= 0"])
+ s.add_dependency(%q<twitter>, [">= 0"])
+ end
+end
56 readme.markdown
@@ -0,0 +1,56 @@
+== About
+
+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.
+
+== Installation
+
+> sudo gem install martinbtt-net-http-spy
+
+== Example Usage
+
+ require 'rubygems'
+ require 'twitter'
+ require 'http-spy'
+
+ Twitter::Search.new('httparty').each { |r| r }
+ # Outputs...
+ -- : CONNECT: ["search.twitter.com", 80]
+ -- : GET /search.json?q=httparty
+ -- : BODY: Net::HTTPOK
+
+
+See the examples folder for more.
+
+== Further Options
+
+# Show the call trace to the originating line of code in the third party gem
+Net::HTTP.http_logger_options = {:trace => true}
+
+# Output the body of the request
+Net::HTTP.http_logger_options = {:body => true}
+
+# Show the full raw HTTP output
+Net::HTTP.http_logger_options = {:verbose => true}
+
+# Change the logger. By default HTTP spy logs to STDOUT
+Net::HTTP.http_logger = Logger.new('twitter.log')
+
+== Bonus Points
+
+Use it to grab sample data for FakeWeb = testing goodness.
+
+== Notes
+
+This is a pretty early release. I'm sure there is plenty that can be done to improve compatibility
+as several libraries call Net::HTTP in a slightly different way.
+Feel free to fork and send in pull requests/patches.
+
+== Find Me
+
+Martin Sadler (martin -- at -- beyondthetype.com)
+
+Blog: http://www.beyondthetype.com
+Follow: http://twitter.com/martinbtt
+Code: http://github.com/martinbtt
+Recommend: http://www.workingwithrails.com/person/5152-martin-sadler
3  spec/spec.opts
@@ -0,0 +1,3 @@
+--format
+ progress
+--colour
32 spec/spec_helper.rb
@@ -0,0 +1,32 @@
+require 'rubygems'
+gem 'rspec'
+require 'spec'
+require 'net/http'
+require 'open-uri'
+require 'twitter'
+require 'mechanize'
+
+require File.join(File.dirname(__FILE__), '..', 'lib', 'spy')
+
+
+class DummyLogger
+
+ attr_accessor :lines
+
+ def initialize
+ reset!
+ end
+
+ def <<(msg)
+ @lines << msg
+ end
+
+ def info(msg)
+ @lines << msg
+ end
+
+ def reset!
+ @lines = []
+ end
+
+end
93 spec/spy_spec.rb
@@ -0,0 +1,93 @@
+require File.join(File.dirname(__FILE__), 'spec_helper')
+
+# Bare bones spec to make sure the core functionality is working
+describe "Net:HTTP Spying on" do
+ before(:all) do
+ Net::HTTP.http_logger = DummyLogger.new()
+ end
+
+ describe "a get request with default options" do
+
+ before(:all) do
+ Net::HTTP.http_logger.reset!
+ Twitter::Search.new('httparty').each { |r| r }
+ Net::HTTP.http_logger_options = :default
+
+ end
+
+ it "should give the connection" do
+ Net::HTTP.http_logger.lines.should include("CONNECT: [\"search.twitter.com\", 80]")
+ end
+
+ it "should give GET uri and query string" do
+ Net::HTTP.http_logger.lines.should include("GET /search.json?q=httparty")
+ end
+
+ it "should give the BODY response code" do
+ Net::HTTP.http_logger.lines.should include("BODY: Net::HTTPOK")
+ end
+
+
+
+ end
+
+
+ describe "a get request with body option set to true" do
+
+ before(:each) do
+ Net::HTTP.http_logger.reset!
+ Net::HTTP.http_logger_options = {:body => true}
+ end
+
+
+ it "should give the body output" do
+ Twitter::Search.new('httparty').each { |r| r }
+ Net::HTTP.http_logger.lines.grep(/BODY: \{\"results\":/).should_not be_empty
+ end
+
+ end
+
+
+ describe "a get request with trace option set to true" do
+
+ before(:each) do
+ Net::HTTP.http_logger.reset!
+ Net::HTTP.http_logger_options = {:trace => true}
+ end
+
+
+ it "should give the trace output" do
+ Twitter::Search.new('httparty').each { |r| r }
+ Net::HTTP.http_logger.lines.grep(/TRACE: /).should_not be_empty
+ end
+
+ end
+
+ describe "a post request with default options" do
+
+ before(:all) do
+ Net::HTTP.http_logger.reset!
+ @connection = Net::HTTP.new('http://search.twitter.com')
+ @connection.post('/','?q=hello')
+ end
+
+
+ it "should give the post uri" do
+ Net::HTTP.http_logger.lines.should include("POST /")
+ end
+
+ it "should give the post params" do
+ Net::HTTP.http_logger.lines.should include("PARAMS {\"?q\"=>[\"hello\"]} ")
+ end
+
+ it "should give the BODY response code" do
+ Net::HTTP.http_logger.lines.should include("BODY: Net::HTTPFound")
+ end
+
+
+ end
+
+
+
+
+end
68 spy.rb
@@ -0,0 +1,68 @@
+# require 'net/https'
+# require 'logger'
+# require 'cgi'
+#
+# # HTTP SPY
+# module Net
+# class HTTP
+# alias :old_initialize :initialize
+# alias :old_post :post
+# # alias :old_get :get
+# alias :old_request :request
+#
+# class << self
+# attr_accessor :http_logger
+# attr_accessor :http_logger_options
+# end
+#
+# def initialize(*args, &block)
+# @logger_options = self.class.http_logger_options ||= {:hide_body => true}
+#
+#
+# self.class.http_logger.info "CONNECT: #{args.inspect}" if !@logger_options[:verbose]
+#
+# old_initialize(*args, &block)
+# @debug_output = self.class.http_logger if @logger_options[:verbose]
+#
+# end
+#
+#
+# # def get(*args, &block)
+# # self.class.http_logger.info "GET: #{args}"# if self.class.http_logger_only.include?(:get)
+# # result = old_get(*args, &block)
+# # self.class.http_logger.info "BODY: #{result.body}" #if self.class.http_logger_only.include?(:body)
+# # result
+# # end
+# #
+# # def post(*args, &block)
+# # self.class.http_logger.info "POST: #{args}" #if self.class.http_logger_only.include?(:post)
+# # result = old_post(*args, &block)
+# # self.class.http_logger.info "BODY: #{result.body}" #if self.class.http_logger_only.include?(:body)
+# # result
+# # end
+#
+#
+# def request(*args, &block)
+# unless started? || @logger_options[:verbose]
+# req = args[0].class::METHOD
+# self.class.http_logger.info "#{req} #{args[0].path}"
+# self.class.http_logger.info "PARAMS #{CGI.parse(args[0].body).inspect} " if args[0].body && req != 'CONNECT'
+# self.class.http_logger.info "TRACE: #{caller.reverse}" if @logger_options[:calltrace]
+# end
+#
+# result = old_request(*args, &block)
+#
+# unless started? || @logger_options[:verbose]
+# self.class.http_logger.info "BODY: #{ @logger_options[:hide_body] ? result.class.name : result.body}"
+# end
+# result
+# end
+#
+#
+# end
+#
+# end
+#
+# # Usage
+# # Great for testing
+# Net::HTTP.http_logger = Logger.new(STDOUT)
Please sign in to comment.
Something went wrong with that request. Please try again.