sham_rack 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,7 @@
1
+ ## 27-Nov-2009 [mdub@dogbiscuit.org]
2
+
3
+ * Change of approach: extend rather than reimplement Net:HTTP. This should improve coverage of all the weird and wonderful ways of using the Net:HTTP API.
4
+
1
5
  ## 5-Jun-2009 [mdub@dogbiscuit.org]
2
6
 
3
7
  * Add support for Net::HTTP.get_response.
@@ -6,14 +6,16 @@ ShamRack plumbs Net:HTTP into [Rack][rack].
6
6
  What's it for, again?
7
7
  ---------------------
8
8
 
9
- Well, you can _test your HTTP client code_, using ShamRack to stub out an external web-service. Think of it as [FakeWeb][fakeweb] on steriods.
9
+ Well, it makes it easy to _stub out external (HTTP) services_, which is handy in development and testing environments, or when you want to _test your HTTP client code_.
10
10
 
11
- Or, you can _test your Rack application_ (or Sinatra, or Rails, or Merb) using arbitrary HTTP client libraries, to check interoperability. For instance, you could hit a local app using:
11
+ You can also use it to _test your Rack application_ (or Sinatra, or Rails, or Merb) using arbitrary HTTP client libraries, to check interoperability. For instance, you could test your app using:
12
12
 
13
13
  * [`rest-client`][rest-client]
14
14
  * [`httparty`][httparty]
15
15
  * [`oauth`][oauth]
16
16
 
17
+ all without having to boot it in a server.
18
+
17
19
  Installing it
18
20
  -------------
19
21
 
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
1
  require "rubygems"
2
2
  require "rake"
3
3
 
4
+ require File.dirname(__FILE__) + "/lib/sham_rack/version.rb"
5
+
4
6
  require "spec/rake/spectask"
5
7
 
6
8
  task "default" => "spec"
@@ -10,21 +12,8 @@ Spec::Rake::SpecTask.new do |t|
10
12
  t.spec_files = FileList['spec/**/*_spec.rb']
11
13
  end
12
14
 
13
- require "jeweler"
14
-
15
- Jeweler::Tasks.new do |g|
16
- g.name = "sham_rack"
17
- g.summary = "Net::HTTP-to-Rack plumbing"
18
- g.email = "mdub@dogbiscuit.org"
19
- g.homepage = "http://github.com/mdub/sham_rack"
20
- g.description = "ShamRack plumbs Net::HTTP directly into Rack, for quick and easy HTTP testing."
21
- g.authors = ["Mike Williams"]
22
- g.rubyforge_project = "shamrack"
23
- end
24
-
25
- Jeweler::RubyforgeTasks.new
26
-
27
15
  require 'rake/rdoctask'
16
+
28
17
  Rake::RDocTask.new do |rdoc|
29
18
  if File.exist?('VERSION.yml')
30
19
  config = YAML.load(File.read('VERSION.yml'))
@@ -34,7 +23,36 @@ Rake::RDocTask.new do |rdoc|
34
23
  end
35
24
 
36
25
  rdoc.rdoc_dir = 'rdoc'
37
- rdoc.title = "ShamRack #{version}"
26
+ rdoc.title = "ShamRack #{ShamRack::VERSION}"
38
27
  rdoc.main = "ShamRack"
39
28
  rdoc.rdoc_files.include('lib/**/*.rb')
40
29
  end
30
+
31
+ def after_requiring(lib, options = {})
32
+ begin
33
+ require(lib)
34
+ rescue LoadError
35
+ gem_name = options[:gem] || lib
36
+ $stderr.puts "WARNING: can't load #{lib}. Install it with: sudo gem install #{gem_name}"
37
+ return false
38
+ end
39
+ yield
40
+ end
41
+
42
+ after_requiring "jeweler" do
43
+
44
+ Jeweler::Tasks.new do |g|
45
+ g.name = "sham_rack"
46
+ g.version = ShamRack::VERSION
47
+ g.summary = "Net::HTTP-to-Rack plumbing"
48
+ g.email = "mdub@dogbiscuit.org"
49
+ g.homepage = "http://github.com/mdub/sham_rack"
50
+ g.description = "ShamRack plumbs Net::HTTP directly into Rack, for quick and easy HTTP testing."
51
+ g.authors = ["Mike Williams"]
52
+ g.rubyforge_project = "shamrack"
53
+ end
54
+
55
+ Jeweler::GemcutterTasks.new
56
+ # Jeweler::RubyforgeTasks.new
57
+
58
+ end
@@ -0,0 +1,49 @@
1
+ require "rubygems"
2
+
3
+ require "pathname"
4
+ dir = Pathname(__FILE__).parent
5
+ $LOAD_PATH.unshift(dir.parent + "lib")
6
+
7
+ require dir + "hello_app"
8
+ require "sham_rack"
9
+ require "restclient"
10
+
11
+ # mount an instance of the app using ShamRack
12
+ ShamRack.mount(HelloApp.new, "hello.sham")
13
+
14
+ # run another instance in a separate process
15
+ server_pid = fork do
16
+ puts "Starting HTTP server on port 3333"
17
+ $stdout = File.new('/dev/null', 'w')
18
+ HelloApp.run!(:port => 3333)
19
+ end
20
+
21
+ at_exit do
22
+ puts "Killing HTTP server"
23
+ Process.kill("TERM", server_pid)
24
+ Process.wait(server_pid)
25
+ end
26
+
27
+ puts "Waiting for server to come up"
28
+ begin
29
+ puts RestClient.get("http://localhost:3333/hello/stranger")
30
+ rescue SystemCallError => e
31
+ retry
32
+ end
33
+
34
+ iterations = (ARGV.shift || 1000).to_i
35
+
36
+ %w(hello.sham localhost:3333).each do |site|
37
+
38
+ start = Time.now
39
+
40
+ iterations.times do
41
+ x = RestClient.get("http://#{site}/hello/stranger").to_s
42
+ end
43
+
44
+ elapsed_time = (Time.now - start)
45
+ requests_per_second = iterations / elapsed_time.to_f
46
+
47
+ printf "%-20s #{iterations} requests in %f; %f per second\n", site, elapsed_time, requests_per_second
48
+
49
+ end
@@ -0,0 +1,10 @@
1
+ require "rubygems"
2
+ require "sinatra/base"
3
+
4
+ class HelloApp < Sinatra::Base
5
+
6
+ get "/hello/:subject" do
7
+ "Hello, #{params[:subject]}"
8
+ end
9
+
10
+ end
@@ -5,3 +5,4 @@
5
5
  module ShamRack; end
6
6
 
7
7
  require "sham_rack/core_ext/net/http"
8
+ require "sham_rack/version"
@@ -2,16 +2,19 @@ require "net/http"
2
2
  require "sham_rack/registry"
3
3
  require "sham_rack/http"
4
4
 
5
- module Net
5
+ class << Net::HTTP
6
6
 
7
- def HTTP.new(address, port = nil, *proxy_args)
8
- port ||= HTTP.default_port
7
+ alias :new_without_sham_rack :new
8
+
9
+ def new(address, port = nil, *proxy_args)
10
+ port ||= Net::HTTP.default_port
9
11
  rack_app = ShamRack.application_for(address, port)
12
+ http_object = new_without_sham_rack(address, port, *proxy_args)
10
13
  if rack_app
11
- ShamRack::HTTP.new(address, port, rack_app)
12
- else
13
- super(address, port, *proxy_args)
14
+ http_object.extend(ShamRack::HTTP::Extensions)
15
+ http_object.rack_app = rack_app
14
16
  end
17
+ http_object
15
18
  end
16
19
 
17
- end
20
+ end
@@ -1,120 +1,101 @@
1
1
  module ShamRack
2
-
3
- # a sham version of Net::HTTP
4
- class HTTP
5
-
6
- def initialize(address, port, rack_app)
7
- @address = address
8
- @port = port
9
- @rack_app = rack_app
10
- end
11
2
 
12
- attr_reader :address, :port, :rack_app
13
-
14
- attr_accessor :read_timeout, :open_timeout
15
- attr_accessor :use_ssl,:key, :cert, :ca_file, :ca_path, :verify_mode, :verify_callback, :verify_depth, :cert_store
3
+ module HTTP
16
4
 
17
- def start
18
- yield self
19
- end
5
+ module Extensions
20
6
 
21
- def request(req, body = nil)
22
- env = default_env
23
- env.merge!(path_env(req.path))
24
- env.merge!(method_env(req))
25
- env.merge!(header_env(req))
26
- env.merge!(io_env(req, body))
27
- response = build_response(@rack_app.call(env))
28
- yield response if block_given?
29
- return response
30
- end
31
-
32
- def request_get(path, initheader = nil, &block)
33
- request Net::HTTP::Get.new(path, initheader), &block
34
- end
7
+ attr_accessor :rack_app
35
8
 
36
- def request_head(path, initheader = nil, &block)
37
- request Net::HTTP::Head.new(path, initheader), &block
38
- end
9
+ attr_accessor :read_timeout, :open_timeout
10
+ attr_accessor :use_ssl,:key, :cert, :ca_file, :ca_path, :verify_mode, :verify_callback, :verify_depth, :cert_store
39
11
 
40
- def request_post(path, data, initheader = nil, &block)
41
- request Net::HTTP::Post.new(path, initheader), data, &block
42
- end
12
+ def start
13
+ yield self
14
+ end
43
15
 
44
- def request_put(path, data, initheader = nil, &block)
45
- request Net::HTTP::Put.new(path, initheader), data, &block
46
- end
16
+ def request(req, body = nil)
17
+ env = default_env
18
+ env.merge!(path_env(req.path))
19
+ env.merge!(method_env(req))
20
+ env.merge!(header_env(req))
21
+ env.merge!(io_env(req, body))
22
+ response = build_response(@rack_app.call(env))
23
+ yield response if block_given?
24
+ return response
25
+ end
47
26
 
48
- private
49
-
50
- def default_env
51
- {
52
- "SCRIPT_NAME" => "",
53
- "SERVER_NAME" => @address,
54
- "SERVER_PORT" => @port.to_s,
55
- "rack.version" => [0,1],
56
- "rack.url_scheme" => "http",
57
- "rack.multithread" => true,
58
- "rack.multiprocess" => true,
59
- "rack.run_once" => false
60
- }
61
- end
62
-
63
- def method_env(request)
64
- {
65
- "REQUEST_METHOD" => request.method
66
- }
67
- end
68
-
69
- def io_env(request, body)
70
- raise(ArgumentError, "both request.body and body argument were provided") if (request.body && body)
71
- body ||= request.body || ""
72
- {
73
- "rack.input" => StringIO.new(body),
74
- "rack.errors" => $stderr
75
- }
76
- end
77
-
78
- def path_env(path)
79
- uri = URI.parse(path)
80
- {
81
- "PATH_INFO" => uri.path,
82
- "QUERY_STRING" => (uri.query || ""),
83
- }
84
- end
85
-
86
- def header_env(request)
87
- result = {}
88
- request.each do |header, content|
89
- result["HTTP_" + header.upcase.gsub('-', '_')] = content
27
+ private
28
+
29
+ def default_env
30
+ {
31
+ "SCRIPT_NAME" => "",
32
+ "SERVER_NAME" => @address,
33
+ "SERVER_PORT" => @port.to_s,
34
+ "rack.version" => [0,1],
35
+ "rack.url_scheme" => "http",
36
+ "rack.multithread" => true,
37
+ "rack.multiprocess" => true,
38
+ "rack.run_once" => false
39
+ }
90
40
  end
91
- %w(TYPE LENGTH).each do |x|
92
- result["CONTENT_#{x}"] = result.delete("HTTP_CONTENT_#{x}") if result.has_key?("HTTP_CONTENT_#{x}")
41
+
42
+ def method_env(request)
43
+ {
44
+ "REQUEST_METHOD" => request.method
45
+ }
93
46
  end
94
- return result
95
- end
96
-
97
- def build_response(rack_response)
98
- status, headers, body = rack_response
99
- code, message = status.to_s.split(" ", 2)
100
- response = Net::HTTPResponse.send(:response_class, code).new("Sham", code, message)
101
- response.instance_variable_set(:@body, assemble_body(body))
102
- response.instance_variable_set(:@read, true)
103
- headers.each do |k,v|
104
- response.add_field(k, v)
47
+
48
+ def io_env(request, body)
49
+ raise(ArgumentError, "both request.body and body argument were provided") if (request.body && body)
50
+ body ||= request.body || ""
51
+ {
52
+ "rack.input" => StringIO.new(body),
53
+ "rack.errors" => $stderr
54
+ }
55
+ end
56
+
57
+ def path_env(path)
58
+ uri = URI.parse(path)
59
+ {
60
+ "PATH_INFO" => uri.path,
61
+ "QUERY_STRING" => (uri.query || ""),
62
+ }
63
+ end
64
+
65
+ def header_env(request)
66
+ result = {}
67
+ request.each do |header, content|
68
+ result["HTTP_" + header.upcase.gsub('-', '_')] = content
69
+ end
70
+ %w(TYPE LENGTH).each do |x|
71
+ result["CONTENT_#{x}"] = result.delete("HTTP_CONTENT_#{x}") if result.has_key?("HTTP_CONTENT_#{x}")
72
+ end
73
+ return result
74
+ end
75
+
76
+ def build_response(rack_response)
77
+ status, headers, body = rack_response
78
+ code, message = status.to_s.split(" ", 2)
79
+ response = Net::HTTPResponse.send(:response_class, code).new("Sham", code, message)
80
+ response.instance_variable_set(:@body, assemble_body(body))
81
+ response.instance_variable_set(:@read, true)
82
+ headers.each do |k,v|
83
+ response.add_field(k, v)
84
+ end
85
+ response.extend ShamRack::ResponseExtensions
86
+ return response
87
+ end
88
+
89
+ def assemble_body(body)
90
+ content = ""
91
+ body.each { |fragment| content << fragment }
92
+ return content
105
93
  end
106
- response.extend ShamRack::ResponseExtensions
107
- return response
108
- end
109
94
 
110
- def assemble_body(body)
111
- content = ""
112
- body.each { |fragment| content << fragment }
113
- return content
114
95
  end
115
-
96
+
116
97
  end
117
-
98
+
118
99
  module ResponseExtensions
119
100
 
120
101
  def read_body(dest = nil)
@@ -122,7 +103,7 @@ module ShamRack
122
103
  dest << @body if dest
123
104
  return @body
124
105
  end
125
-
106
+
126
107
  end
127
108
 
128
109
  end
@@ -0,0 +1,3 @@
1
+ module ShamRack
2
+ VERSION = "1.2.0"
3
+ end
@@ -1,12 +1,15 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
1
4
  # -*- encoding: utf-8 -*-
2
5
 
3
6
  Gem::Specification.new do |s|
4
7
  s.name = %q{sham_rack}
5
- s.version = "1.1.2"
8
+ s.version = "1.2.0"
6
9
 
7
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
11
  s.authors = ["Mike Williams"]
9
- s.date = %q{2009-06-05}
12
+ s.date = %q{2009-11-27}
10
13
  s.description = %q{ShamRack plumbs Net::HTTP directly into Rack, for quick and easy HTTP testing.}
11
14
  s.email = %q{mdub@dogbiscuit.org}
12
15
  s.extra_rdoc_files = [
@@ -17,21 +20,22 @@ Gem::Specification.new do |s|
17
20
  "CHANGES.markdown",
18
21
  "README.markdown",
19
22
  "Rakefile",
20
- "VERSION.yml",
23
+ "benchmark/benchmark.rb",
24
+ "benchmark/hello_app.rb",
21
25
  "lib/sham_rack.rb",
22
26
  "lib/sham_rack/core_ext/net/http.rb",
23
27
  "lib/sham_rack/http.rb",
24
28
  "lib/sham_rack/registry.rb",
29
+ "lib/sham_rack/version.rb",
25
30
  "sham_rack.gemspec",
26
31
  "spec/sham_rack_spec.rb",
27
32
  "spec/spec_helper.rb"
28
33
  ]
29
- s.has_rdoc = true
30
34
  s.homepage = %q{http://github.com/mdub/sham_rack}
31
35
  s.rdoc_options = ["--charset=UTF-8"]
32
36
  s.require_paths = ["lib"]
33
37
  s.rubyforge_project = %q{shamrack}
34
- s.rubygems_version = %q{1.3.2}
38
+ s.rubygems_version = %q{1.3.5}
35
39
  s.summary = %q{Net::HTTP-to-Rack plumbing}
36
40
  s.test_files = [
37
41
  "spec/sham_rack_spec.rb",
@@ -48,3 +52,4 @@ Gem::Specification.new do |s|
48
52
  else
49
53
  end
50
54
  end
55
+
@@ -238,6 +238,17 @@ describe ShamRack do
238
238
 
239
239
  end
240
240
 
241
+ it "supports POST using Net::HTTP" do
242
+
243
+ Net::HTTP.start("env.xyz") do |http|
244
+ http.post("/resource", "q=rack")
245
+ end
246
+
247
+ env["REQUEST_METHOD"].should == "POST"
248
+ env["rack.input"].read.should == "q=rack"
249
+
250
+ end
251
+
241
252
  it "supports PUT" do
242
253
 
243
254
  RestClient.put("http://env.xyz/thing1", "stuff", :content_type => "text/plain")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sham_rack
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Williams
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-05 00:00:00 +10:00
12
+ date: 2009-11-27 00:00:00 +11:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -26,11 +26,13 @@ files:
26
26
  - CHANGES.markdown
27
27
  - README.markdown
28
28
  - Rakefile
29
- - VERSION.yml
29
+ - benchmark/benchmark.rb
30
+ - benchmark/hello_app.rb
30
31
  - lib/sham_rack.rb
31
32
  - lib/sham_rack/core_ext/net/http.rb
32
33
  - lib/sham_rack/http.rb
33
34
  - lib/sham_rack/registry.rb
35
+ - lib/sham_rack/version.rb
34
36
  - sham_rack.gemspec
35
37
  - spec/sham_rack_spec.rb
36
38
  - spec/spec_helper.rb
@@ -58,7 +60,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
58
60
  requirements: []
59
61
 
60
62
  rubyforge_project: shamrack
61
- rubygems_version: 1.3.2
63
+ rubygems_version: 1.3.5
62
64
  signing_key:
63
65
  specification_version: 3
64
66
  summary: Net::HTTP-to-Rack plumbing
@@ -1,4 +0,0 @@
1
- ---
2
- :major: 1
3
- :minor: 1
4
- :patch: 2