artifice-passthru 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ Artifice::Passthru
2
+ ==================
3
+
4
+ [Artifice][] is a great way to mock HTTP requests in your Ruby applications,
5
+ sending all Net::HTTP requests to a Rack application.
6
+
7
+ That's great until you find that, for one reason or another, you *actually* need
8
+ to make **real** HTTP requests!
9
+
10
+ There are a few reasons why you might need to do this:
11
+
12
+ - You want to test that real HTTP requests work
13
+ - Your test suite uses HTTP to communicate with its testing tools (eg. Capybara/Selenium requires HTTP)
14
+ - Your test suite calls lots of real APIs and you want to iteratively refactor it to use Artifice
15
+ - ?
16
+
17
+ Usage
18
+ -----
19
+
20
+ ```ruby
21
+ require 'artifice/passthru'
22
+
23
+ # If you want to give a class or module (and all of its subclasses)
24
+ # access to the real Net::HTTP, you can #use_real_net_http
25
+ Artifice.use_real_net_http MyModule
26
+
27
+ Artifice.activate_with lambda { |env|
28
+ if env['SERVER_NAME'] == 'api.twitter.com'
29
+ # Inside of your Artifice Rack application, you can call Artifice.passthru! which:
30
+ # - looks at the current Artifice request
31
+ # - makes a real HTTP request
32
+ # - returns a Rack response representing the actual HTTP response that was returned
33
+ Artifice.passthru! # <--- will make the real HTTP call and return the response
34
+ else
35
+ # return faked responses using your Rack application as you normally would
36
+ [ 200, {}, ['Hi!'] ]
37
+ end
38
+ }
39
+ ```
40
+
41
+ That's all!
42
+
43
+ [artifice]: https://github.com/wycats/artifice
@@ -0,0 +1,2 @@
1
+ # Helper file allowing you to: require 'artifice/passthru'
2
+ require File.dirname(__FILE__) + '/../artifice-passthru'
@@ -0,0 +1,98 @@
1
+ require 'artifice' unless defined? Artifice
2
+
3
+ module Artifice # :nodoc:
4
+
5
+ # Artifice.passthru! returns a Rack response created by making a *real* Net::HTTP
6
+ # request (using the Artifice::Passthru.last_request_info) and then turning
7
+ # the resulting Net::HTTPResponse object into a Rack response (which Artifice expects).
8
+ def self.passthru!
9
+ Artifice::Passthru.make_real_request_and_return_response!
10
+ end
11
+
12
+ # Given a constant (class or module), this gives it access to the *real* Net::HTTP so
13
+ # every request made from within this class/module will use the real Net::HTTP
14
+ def self.use_real_net_http class_or_module
15
+ Artifice::Passthru.setup_to_use_real_net_http class_or_module
16
+ end
17
+
18
+ # Artifice Passthru
19
+ module Passthru
20
+
21
+ # Simple class for storing information about the last #request that was made,
22
+ # allowing us to recreate the request
23
+ class RequestInfo
24
+ attr_accessor :address, :port, :request, :body, :block
25
+
26
+ def initialize address, port, req, body, block
27
+ self.address = address
28
+ self.port = port
29
+ self.request = req
30
+ self.body = body
31
+ self.block = block
32
+ end
33
+ end
34
+
35
+ # When Artifice::Passthru is included into Artifice::Net::HTTP, it uses "alias_method_chain"
36
+ # to override the #request method so we can get the arguments that were passed.
37
+ def self.included base
38
+ base.class_eval do
39
+ alias_method :request_without_passthru_argument_tracking, :request
40
+ alias_method :request, :request_with_passthru_argument_tracking
41
+ end
42
+ end
43
+
44
+ # Returns the last information that were passed to Net::HTTP#request (which Artifice hijacked)
45
+ # so we can use these arguments to fire off a real request, if necessary.
46
+ def self.last_request_info
47
+ Thread.current[:artifice_passthru_arguments]
48
+ end
49
+
50
+ # Accepts and stores the last information that were passed to Net::HTTP#request (which Artifice hijacked)
51
+ # so we can use these arguments to fire off a real request, if necessary.
52
+ def self.last_request_info= request_info
53
+ Thread.current[:artifice_passthru_arguments] = request_info
54
+ end
55
+
56
+ # Makes a real Net::HTTP request and returns the response, converted to a Rack response
57
+ def self.make_real_request_and_return_response!
58
+ raise 'Artifice.passthru! was called but no previous Artifice request was found to make via real Net::HTTP' if last_request_info.nil?
59
+ to_rack_response make_real_request(last_request_info)
60
+ end
61
+
62
+ # Given a Net::HTTPResponse, returns a Rack response
63
+ def self.to_rack_response net_http_response
64
+ # There's some voodoo magic going on that makes the real Net::HTTP#request method populate our response body for us?
65
+ headers = net_http_response.instance_variable_get('@header').inject({}){|all,this| all[this.first] = this.last.join("\n"); all }
66
+ [ net_http_response.code, headers, [net_http_response.body] ]
67
+ end
68
+
69
+ # Given the last_request_info (that would normally be passed to Net::HTTP#request),
70
+ # makes a real request and returns the Net::HTTPResponse
71
+ def self.make_real_request request_info
72
+ http = Artifice::NET_HTTP.new request_info.address, request_info.port
73
+ http.request request_info.request, request_info.body, &request_info.block
74
+ end
75
+
76
+ # Given a constant (class or module), this gives it access to the *real* Net::HTTP so
77
+ # every request made from within this class/module will use the real Net::HTTP
78
+ #
79
+ # Taken from: http://matschaffer.com/2011/04/net-http-mock-cucumber/
80
+ def self.setup_to_use_real_net_http class_or_module
81
+ class_or_module.class_eval %{
82
+ Net = ::Net.dup
83
+ module Net
84
+ HTTP = Artifice::NET_HTTP
85
+ end
86
+ }
87
+ end
88
+
89
+ # Simply stores the arguments that are passed and then calls "super" (request_without_passthru_argument_tracking)
90
+ def request_with_passthru_argument_tracking req, body = nil, &block
91
+ Artifice::Passthru.last_request_info = RequestInfo.new address, port, req, body, block
92
+ request_without_passthru_argument_tracking req, body, &block
93
+ end
94
+ end
95
+ end
96
+
97
+ # Inject our #request method override into Artifice's implementation of Net::HTTP
98
+ Artifice::Net::HTTP.send :include, Artifice::Passthru
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: artifice-passthru
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - remi
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-06-28 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: artifice
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ description: Artifice extension that allows you to let certain requests pass thru to use HTTP
36
+ email: remi@remitaylor.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - README.md
45
+ - lib/artifice/passthru.rb
46
+ - lib/artifice-passthru.rb
47
+ has_rdoc: true
48
+ homepage: https://github.com/remi/artifice-passthru
49
+ licenses: []
50
+
51
+ post_install_message:
52
+ rdoc_options: []
53
+
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ requirements: []
75
+
76
+ rubyforge_project:
77
+ rubygems_version: 1.6.2
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: Easily use real Net::HTTP with Artifice
81
+ test_files: []
82
+