artifice 0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+