artifice 0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/LICENSE +22 -0
  2. data/lib/artifice.rb +131 -0
  3. metadata +76 -0
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2010 Yehuda Katz
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,131 @@
1
+ require "rack/test"
2
+ require "net/http"
3
+ require "net/https"
4
+
5
+ module Artifice
6
+ NET_HTTP = ::Net::HTTP
7
+
8
+ # Activate Artifice with a particular Rack endpoint.
9
+ #
10
+ # Calling this method will replace the Net::HTTP system
11
+ # with a replacement that routes all requests to the
12
+ # Rack endpoint.
13
+ #
14
+ # @param [#call] endpoint A valid Rack endpoint
15
+ # @yield An optional block that uses Net::HTTP
16
+ # In this case, Artifice will be used only for
17
+ # the duration of the block
18
+ def self.activate_with(endpoint)
19
+ Net::HTTP.endpoint = endpoint
20
+ replace_net_http(Artifice::Net::HTTP)
21
+
22
+ if block_given?
23
+ yield
24
+ deactivate
25
+ end
26
+ end
27
+
28
+ # Deactivate the Artifice replacement.
29
+ def self.deactivate
30
+ replace_net_http(NET_HTTP)
31
+ end
32
+
33
+ private
34
+ def self.replace_net_http(value)
35
+ ::Net.class_eval do
36
+ remove_const(:HTTP)
37
+ const_set(:HTTP, value)
38
+ end
39
+ end
40
+
41
+ module Net
42
+ # This is an internal object that can receive Rack requests
43
+ # to the application using the Rack::Test API
44
+ class RackRequest
45
+ include Rack::Test::Methods
46
+ attr_reader :app
47
+
48
+ def initialize(app)
49
+ @app = app
50
+ end
51
+ end
52
+
53
+ class HTTP < ::Net::HTTP
54
+ class << self
55
+ attr_accessor :endpoint
56
+ end
57
+
58
+ # Net::HTTP uses a @newimpl instance variable to decide whether
59
+ # to use a legacy implementation. Since we are subclassing
60
+ # Net::HTTP, we must set it
61
+ @newimpl = true
62
+
63
+ # We don't need to connect, so blank out this method
64
+ def connect
65
+ end
66
+
67
+ # Replace the Net::HTTP request method with a method
68
+ # that converts the request into a Rack request and
69
+ # dispatches it to the Rack endpoint.
70
+ #
71
+ # @param [Net::HTTPRequest] req A Net::HTTPRequest
72
+ # object, or one if its subclasses
73
+ # @param [optional, String, #read] body This should
74
+ # be sent as "rack.input". If it's a String, it will
75
+ # be converted to a StringIO.
76
+ # @return [Net::HTTPResponse]
77
+ #
78
+ # @yield [Net::HTTPResponse] If a block is provided,
79
+ # this method will yield the Net::HTTPResponse to
80
+ # it after the body is read.
81
+ def request(req, body = nil, &block)
82
+ rack_request = RackRequest.new(self.class.endpoint)
83
+
84
+ req.each_header do |header, value|
85
+ rack_request.header(header, value)
86
+ end
87
+
88
+ scheme = use_ssl? ? "https" : "http"
89
+ prefix = "#{scheme}://#{addr_port}"
90
+
91
+ response = rack_request.request("#{prefix}#{req.path}",
92
+ {:method => req.method, :input => body})
93
+
94
+ make_net_http_response(response, &block)
95
+ end
96
+
97
+ private
98
+
99
+ # This method takes a Rack response and creates a Net::HTTPResponse
100
+ # Instead of trying to mock HTTPResponse directly, we just convert
101
+ # the Rack response into a String that looks like a normal HTTP
102
+ # response and call Net::HTTPResponse.read_new
103
+ #
104
+ # @param [Array(#to_i, Hash, #each)] response a Rack response
105
+ # @return [Net::HTTPResponse]
106
+ # @yield [Net::HTTPResponse] If a block is provided, yield the
107
+ # response to it after the body is read
108
+ def make_net_http_response(response)
109
+ status, headers, body = response.status, response.headers, response.body
110
+
111
+ response_string = []
112
+ response_string << "HTTP/1.1 #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}"
113
+
114
+ headers.each do |header, value|
115
+ response_string << "#{header}: #{value}"
116
+ end
117
+
118
+ response_string << "" << body
119
+
120
+ response_io = ::Net::BufferedIO.new(StringIO.new(response_string.join("\n")))
121
+ res = ::Net::HTTPResponse.read_new(response_io)
122
+
123
+ res.reading_body(response_io, true) do
124
+ yield res if block_given?
125
+ end
126
+
127
+ res
128
+ end
129
+ end
130
+ end
131
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: artifice
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 5
8
+ version: "0.5"
9
+ platform: ruby
10
+ authors:
11
+ - Yehuda Katz
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+
16
+ date: 2010-03-24 00:00:00 -07:00
17
+ default_executable:
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: rack-test
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ segments:
27
+ - 0
28
+ version: "0"
29
+ type: :runtime
30
+ version_requirements: *id001
31
+ description: Replaces Net::HTTP with a subclass that routes all requests to a Rack application
32
+ email: wycats@gmail.com
33
+ executables: []
34
+
35
+ extensions: []
36
+
37
+ extra_rdoc_files: []
38
+
39
+ files:
40
+ - LICENSE
41
+ - lib/artifice.rb
42
+ has_rdoc: true
43
+ homepage: http://www.yehudakatz.com
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options:
48
+ - --exclude
49
+ - .
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 1
58
+ - 8
59
+ - 6
60
+ version: 1.8.6
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ requirements: []
69
+
70
+ rubyforge_project: artifice
71
+ rubygems_version: 1.3.6
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: Use a Rack application for mock HTTP requests
75
+ test_files: []
76
+