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 +43 -0
- data/lib/artifice/passthru.rb +2 -0
- data/lib/artifice-passthru.rb +98 -0
- metadata +82 -0
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,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
|
+
|