typhoeus 0.4.2 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.rspec +4 -0
  4. data/.travis.yml +26 -0
  5. data/CHANGELOG.md +341 -28
  6. data/CONTRIBUTING.md +20 -0
  7. data/Gemfile +31 -2
  8. data/Guardfile +9 -0
  9. data/LICENSE +1 -1
  10. data/README.md +486 -357
  11. data/Rakefile +21 -12
  12. data/UPGRADE.md +55 -0
  13. data/lib/rack/typhoeus/middleware/params_decoder/helper.rb +76 -0
  14. data/lib/rack/typhoeus/middleware/params_decoder.rb +57 -0
  15. data/lib/rack/typhoeus.rb +1 -0
  16. data/lib/typhoeus/adapters/faraday.rb +180 -0
  17. data/lib/typhoeus/cache/dalli.rb +28 -0
  18. data/lib/typhoeus/cache/rails.rb +28 -0
  19. data/lib/typhoeus/cache/redis.rb +35 -0
  20. data/lib/typhoeus/config.rb +69 -0
  21. data/lib/typhoeus/easy_factory.rb +180 -0
  22. data/lib/typhoeus/errors/no_stub.rb +12 -0
  23. data/lib/typhoeus/errors/typhoeus_error.rb +8 -0
  24. data/lib/typhoeus/errors.rb +9 -0
  25. data/lib/typhoeus/expectation.rb +217 -0
  26. data/lib/typhoeus/hydra/addable.rb +23 -0
  27. data/lib/typhoeus/hydra/before.rb +31 -0
  28. data/lib/typhoeus/hydra/block_connection.rb +35 -0
  29. data/lib/typhoeus/hydra/cacheable.rb +15 -0
  30. data/lib/typhoeus/hydra/memoizable.rb +56 -0
  31. data/lib/typhoeus/hydra/queueable.rb +83 -0
  32. data/lib/typhoeus/hydra/runnable.rb +19 -0
  33. data/lib/typhoeus/hydra/stubbable.rb +28 -0
  34. data/lib/typhoeus/hydra.rb +84 -236
  35. data/lib/typhoeus/pool.rb +70 -0
  36. data/lib/typhoeus/railtie.rb +12 -0
  37. data/lib/typhoeus/request/actions.rb +125 -0
  38. data/lib/typhoeus/request/before.rb +30 -0
  39. data/lib/typhoeus/request/block_connection.rb +52 -0
  40. data/lib/typhoeus/request/cacheable.rb +38 -0
  41. data/lib/typhoeus/request/callbacks.rb +151 -0
  42. data/lib/typhoeus/request/marshal.rb +22 -0
  43. data/lib/typhoeus/request/memoizable.rb +38 -0
  44. data/lib/typhoeus/request/operations.rb +40 -0
  45. data/lib/typhoeus/request/responseable.rb +29 -0
  46. data/lib/typhoeus/request/streamable.rb +34 -0
  47. data/lib/typhoeus/request/stubbable.rb +30 -0
  48. data/lib/typhoeus/request.rb +186 -231
  49. data/lib/typhoeus/response/cacheable.rb +14 -0
  50. data/lib/typhoeus/response/header.rb +105 -0
  51. data/lib/typhoeus/response/informations.rb +248 -0
  52. data/lib/typhoeus/response/status.rb +106 -0
  53. data/lib/typhoeus/response.rb +60 -115
  54. data/lib/typhoeus/version.rb +3 -1
  55. data/lib/typhoeus.rb +126 -39
  56. data/perf/profile.rb +14 -0
  57. data/perf/vs_nethttp.rb +64 -0
  58. data/spec/rack/typhoeus/middleware/params_decoder/helper_spec.rb +156 -0
  59. data/spec/rack/typhoeus/middleware/params_decoder_spec.rb +31 -0
  60. data/spec/spec_helper.rb +29 -0
  61. data/spec/support/localhost_server.rb +94 -0
  62. data/spec/support/memory_cache.rb +15 -0
  63. data/spec/support/server.rb +116 -0
  64. data/spec/typhoeus/adapters/faraday_spec.rb +339 -0
  65. data/spec/typhoeus/cache/dalli_spec.rb +41 -0
  66. data/spec/typhoeus/cache/redis_spec.rb +41 -0
  67. data/spec/typhoeus/config_spec.rb +15 -0
  68. data/spec/typhoeus/easy_factory_spec.rb +143 -0
  69. data/spec/typhoeus/errors/no_stub_spec.rb +13 -0
  70. data/spec/typhoeus/expectation_spec.rb +280 -0
  71. data/spec/typhoeus/hydra/addable_spec.rb +22 -0
  72. data/spec/typhoeus/hydra/before_spec.rb +98 -0
  73. data/spec/typhoeus/hydra/block_connection_spec.rb +18 -0
  74. data/spec/typhoeus/hydra/cacheable_spec.rb +88 -0
  75. data/spec/typhoeus/hydra/memoizable_spec.rb +53 -0
  76. data/spec/typhoeus/hydra/queueable_spec.rb +98 -0
  77. data/spec/typhoeus/hydra/runnable_spec.rb +137 -0
  78. data/spec/typhoeus/hydra/stubbable_spec.rb +48 -0
  79. data/spec/typhoeus/hydra_spec.rb +22 -0
  80. data/spec/typhoeus/pool_spec.rb +137 -0
  81. data/spec/typhoeus/request/actions_spec.rb +19 -0
  82. data/spec/typhoeus/request/before_spec.rb +93 -0
  83. data/spec/typhoeus/request/block_connection_spec.rb +75 -0
  84. data/spec/typhoeus/request/cacheable_spec.rb +94 -0
  85. data/spec/typhoeus/request/callbacks_spec.rb +91 -0
  86. data/spec/typhoeus/request/marshal_spec.rb +60 -0
  87. data/spec/typhoeus/request/memoizable_spec.rb +34 -0
  88. data/spec/typhoeus/request/operations_spec.rb +101 -0
  89. data/spec/typhoeus/request/responseable_spec.rb +13 -0
  90. data/spec/typhoeus/request/stubbable_spec.rb +45 -0
  91. data/spec/typhoeus/request_spec.rb +232 -0
  92. data/spec/typhoeus/response/header_spec.rb +147 -0
  93. data/spec/typhoeus/response/informations_spec.rb +283 -0
  94. data/spec/typhoeus/response/status_spec.rb +256 -0
  95. data/spec/typhoeus/response_spec.rb +100 -0
  96. data/spec/typhoeus_spec.rb +105 -0
  97. data/typhoeus.gemspec +25 -0
  98. metadata +146 -158
  99. data/lib/typhoeus/curl.rb +0 -453
  100. data/lib/typhoeus/easy/auth.rb +0 -14
  101. data/lib/typhoeus/easy/callbacks.rb +0 -33
  102. data/lib/typhoeus/easy/ffi_helper.rb +0 -61
  103. data/lib/typhoeus/easy/infos.rb +0 -90
  104. data/lib/typhoeus/easy/options.rb +0 -115
  105. data/lib/typhoeus/easy/proxy.rb +0 -20
  106. data/lib/typhoeus/easy/ssl.rb +0 -82
  107. data/lib/typhoeus/easy.rb +0 -115
  108. data/lib/typhoeus/filter.rb +0 -28
  109. data/lib/typhoeus/form.rb +0 -61
  110. data/lib/typhoeus/header.rb +0 -54
  111. data/lib/typhoeus/hydra/callbacks.rb +0 -24
  112. data/lib/typhoeus/hydra/connect_options.rb +0 -61
  113. data/lib/typhoeus/hydra/stubbing.rb +0 -68
  114. data/lib/typhoeus/hydra_mock.rb +0 -131
  115. data/lib/typhoeus/multi.rb +0 -146
  116. data/lib/typhoeus/param_processor.rb +0 -43
  117. data/lib/typhoeus/remote.rb +0 -306
  118. data/lib/typhoeus/remote_method.rb +0 -108
  119. data/lib/typhoeus/remote_proxy_object.rb +0 -50
  120. data/lib/typhoeus/utils.rb +0 -50
@@ -0,0 +1,28 @@
1
+ module Typhoeus
2
+ class Hydra
3
+
4
+ # This module handles stubbing on the hydra side.
5
+ # It plays well with the block_connection configuration,
6
+ # which raises when you make a request which is not stubbed.
7
+ #
8
+ # @api private
9
+ module Stubbable
10
+
11
+ # Override add in order to check for matching expecations.
12
+ # When an expecation is found, super is not called. Instead a
13
+ # canned response is assigned to the request.
14
+ #
15
+ # @example Add the request.
16
+ # hydra.add(request)
17
+ def add(request)
18
+ if response = Expectation.response_for(request)
19
+ request.execute_headers_callbacks(response)
20
+ request.on_body.each{ |callback| callback.call(response.body, response) }
21
+ request.finish(response)
22
+ else
23
+ super
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,247 +1,95 @@
1
- require 'typhoeus/hydra/callbacks'
2
- require 'typhoeus/hydra/connect_options'
3
- require 'typhoeus/hydra/stubbing'
1
+ require 'typhoeus/hydra/addable'
2
+ require 'typhoeus/hydra/before'
3
+ require 'typhoeus/hydra/cacheable'
4
+ require 'typhoeus/hydra/block_connection'
5
+ require 'typhoeus/hydra/memoizable'
6
+ require 'typhoeus/hydra/queueable'
7
+ require 'typhoeus/hydra/runnable'
8
+ require 'typhoeus/hydra/stubbable'
4
9
 
5
10
  module Typhoeus
6
- class Hydra
7
- include ConnectOptions
8
- include Stubbing
9
- extend Callbacks
10
-
11
- def initialize(options = {})
12
- @memoize_requests = true
13
- @multi = Multi.new
14
- @easy_pool = []
15
- initial_pool_size = options[:initial_pool_size] || 10
16
- @max_concurrency = options[:max_concurrency] || 200
17
- initial_pool_size.times { @easy_pool << Easy.new }
18
- @memoized_requests = {}
19
- @retrieved_from_cache = {}
20
- @queued_requests = []
21
- @running_requests = 0
22
-
23
- self.stubs = []
24
- @active_stubs = []
25
- end
26
-
27
- def self.hydra
28
- @hydra ||= new
29
- end
30
11
 
31
- def self.hydra=(val)
32
- @hydra = val
12
+ # Hydra manages making parallel HTTP requests. This
13
+ # is achieved by using libcurls multi interface:
14
+ # http://curl.haxx.se/libcurl/c/libcurl-multi.html
15
+ # The benefits are that you don't have to worry running
16
+ # the requests by yourself.
17
+ #
18
+ # Hydra will also handle how many requests you can
19
+ # make in parallel. Things will get flakey if you
20
+ # try to make too many requests at the same time.
21
+ # The built in limit is 200. When more requests than
22
+ # that are queued up, hydra will save them for later
23
+ # and start the requests as others are finished. You
24
+ # can raise or lower the concurrency limit through
25
+ # the Hydra constructor.
26
+ #
27
+ # Regarding the asynchronous behavior of the hydra,
28
+ # it is important to know that this is completely hidden
29
+ # from the developer and you are free to apply
30
+ # whatever technique you want to your code. That should not
31
+ # conflict with libcurls internal concurrency mechanism.
32
+ #
33
+ # @example Use the hydra to do multiple requests.
34
+ # hydra = Typhoeus::Hydra.new
35
+ # requests = (0..9).map{ Typhoeus::Request.new("www.example.com") }
36
+ # requests.each{ |request| hydra.queue(request) }
37
+ # hydra.run
38
+ #
39
+ # @note Callbacks are going to delay the request
40
+ # execution.
41
+ class Hydra
42
+ include Hydra::Addable
43
+ include Hydra::Runnable
44
+ include Hydra::Memoizable
45
+ include Hydra::Cacheable
46
+ include Hydra::BlockConnection
47
+ include Hydra::Stubbable
48
+ include Hydra::Before
49
+ include Hydra::Queueable
50
+
51
+ # @example Set max_concurrency.
52
+ # Typhoeus::Hydra.new(max_concurrency: 20)
53
+ attr_accessor :max_concurrency
54
+
55
+ # @api private
56
+ attr_reader :multi
57
+
58
+ class << self
59
+
60
+ # Returns a memoized hydra instance.
61
+ #
62
+ # @example Get a hydra.
63
+ # Typhoeus::Hydra.hydra
64
+ #
65
+ # @return [Typhoeus::Hydra] A new hydra.
66
+ def hydra
67
+ Thread.current[:typhoeus_hydra] ||= new
68
+ end
33
69
  end
34
70
 
71
+ # Create a new hydra. All
72
+ # {http://rubydoc.info/github/typhoeus/ethon/Ethon/Multi#initialize-instance_method Ethon::Multi#initialize}
73
+ # options are also available.
35
74
  #
36
- # Abort the run on a best-effort basis.
75
+ # @example Create a hydra.
76
+ # Typhoeus::Hydra.new
37
77
  #
38
- # It won't abort the current burst of @max_concurrency requests,
39
- # however it won't fire the rest of the queued requests so the run
40
- # will be aborted as soon as possible...
78
+ # @example Create a hydra with max_concurrency.
79
+ # Typhoeus::Hydra.new(max_concurrency: 20)
41
80
  #
42
- def abort
43
- @queued_requests.clear
44
- end
45
-
46
- def clear_cache_callbacks
47
- @cache_setter = nil
48
- @cache_getter = nil
49
- end
50
-
51
- def fire_and_forget
52
- @queued_requests.each {|r| queue(r, false)}
53
- @multi.fire_and_forget
54
- end
55
-
56
- def queue(request, obey_concurrency_limit = true)
57
- return if assign_to_stub(request)
58
-
59
- # At this point, we are running over live HTTP. Make sure we haven't
60
- # disabled live requests.
61
- check_allow_net_connect!(request)
62
-
63
- if @running_requests >= @max_concurrency && obey_concurrency_limit
64
- @queued_requests << request
65
- else
66
- if request.method == :get
67
- if @memoize_requests && @memoized_requests.key?(request.url)
68
- if response = @retrieved_from_cache[request.url]
69
- request.response = response
70
- request.call_handlers
71
- else
72
- @memoized_requests[request.url] << request
73
- end
74
- else
75
- @memoized_requests[request.url] = [] if @memoize_requests
76
- get_from_cache_or_queue(request)
77
- end
78
- else
79
- get_from_cache_or_queue(request)
80
- end
81
- end
82
- end
83
-
84
- def run
85
- while !@active_stubs.empty?
86
- m = @active_stubs.first
87
- while request = m.requests.shift
88
- response = m.response
89
- response.request = request
90
- handle_request(request, response)
91
- end
92
- @active_stubs.delete(m)
93
- end
94
-
95
- @multi.perform
96
- ensure
97
- @multi.reset_easy_handles{|easy| release_easy_object(easy)}
98
- @memoized_requests = {}
99
- @retrieved_from_cache = {}
100
- @running_requests = 0
101
- end
102
-
103
- def disable_memoization
104
- @memoize_requests = false
105
- end
106
-
107
- def cache_getter(&block)
108
- @cache_getter = block
109
- end
110
-
111
- def cache_setter(&block)
112
- @cache_setter = block
113
- end
114
-
115
- def on_complete(&block)
116
- @on_complete = block
117
- end
118
-
119
- def on_complete=(proc)
120
- @on_complete = proc
121
- end
122
-
123
- private
124
-
125
- def get_from_cache_or_queue(request)
126
- if @cache_getter
127
- val = @cache_getter.call(request)
128
- if val
129
- @retrieved_from_cache[request.url] = val
130
- queue_next
131
- handle_request(request, val, false)
132
- else
133
- @multi.add(get_easy_object(request))
134
- end
135
- else
136
- @multi.add(get_easy_object(request))
137
- end
138
- end
139
-
140
- def get_easy_object(request)
141
- @running_requests += 1
142
-
143
- easy = @easy_pool.pop || Easy.new
144
- easy.verbose = request.verbose
145
- if request.username || request.password
146
- auth = { :username => request.username, :password => request.password }
147
- auth[:method] = request.auth_method if request.auth_method
148
- easy.auth = auth
149
- end
150
-
151
- if request.proxy
152
- proxy = { :server => request.proxy }
153
- proxy[:type] = request.proxy_type if request.proxy_type
154
- easy.proxy = proxy if request.proxy
155
- end
156
-
157
- if request.proxy_username || request.proxy_password
158
- auth = { :username => request.proxy_username, :password => request.proxy_password }
159
- auth[:method] = request.proxy_auth_method if request.proxy_auth_method
160
- easy.proxy_auth = auth
161
- end
162
-
163
- easy.url = request.url
164
- easy.method = request.method
165
- easy.params = request.params if [:post, :put].include?(request.method) && !request.params.nil?
166
- easy.headers = request.headers if request.headers
167
- easy.request_body = request.body if [:post, :put].include?(request.method) && !request.body.nil?
168
- easy.timeout = request.timeout if request.timeout
169
- easy.connect_timeout = request.connect_timeout if request.connect_timeout
170
- easy.interface = request.interface if request.interface
171
- easy.follow_location = request.follow_location if request.follow_location
172
- easy.max_redirects = request.max_redirects if request.max_redirects
173
- easy.disable_ssl_peer_verification if request.disable_ssl_peer_verification
174
- easy.disable_ssl_host_verification if request.disable_ssl_host_verification
175
- easy.ssl_cert = request.ssl_cert
176
- easy.ssl_cert_type = request.ssl_cert_type
177
- easy.ssl_key = request.ssl_key
178
- easy.ssl_key_type = request.ssl_key_type
179
- easy.ssl_key_password = request.ssl_key_password
180
- easy.ssl_cacert = request.ssl_cacert
181
- easy.ssl_capath = request.ssl_capath
182
- easy.ssl_version = request.ssl_version || :default
183
- easy.verbose = request.verbose
184
-
185
- easy.on_success do |easy|
186
- queue_next
187
- handle_request(request, response_from_easy(easy, request))
188
- release_easy_object(easy)
189
- end
190
- easy.on_failure do |easy|
191
- queue_next
192
- handle_request(request, response_from_easy(easy, request))
193
- release_easy_object(easy)
194
- end
195
- easy.set_headers
196
- easy
197
- end
198
-
199
- def queue_next
200
- @running_requests -= 1
201
- queue(@queued_requests.shift) unless @queued_requests.empty?
202
- end
203
-
204
- def release_easy_object(easy)
205
- easy.reset
206
- @easy_pool.push easy
207
- end
208
-
209
- def handle_request(request, response, live_request = true)
210
- request.response = response
211
-
212
- self.class.run_global_hooks_for(:after_request_before_on_complete,
213
- request)
214
-
215
- if live_request && request.cache_timeout && @cache_setter
216
- @cache_setter.call(request)
217
- end
218
- @on_complete.call(response) if @on_complete
219
-
220
- request.call_handlers
221
- if requests = @memoized_requests[request.url]
222
- requests.each do |r|
223
- r.response = response
224
- r.call_handlers
225
- end
226
- end
227
- end
228
-
229
- def response_from_easy(easy, request)
230
- Response.new(:code => easy.response_code,
231
- :headers => easy.response_header,
232
- :body => easy.response_body,
233
- :time => easy.total_time_taken,
234
- :start_transfer_time => easy.start_transfer_time,
235
- :app_connect_time => easy.app_connect_time,
236
- :pretransfer_time => easy.pretransfer_time,
237
- :connect_time => easy.connect_time,
238
- :name_lookup_time => easy.name_lookup_time,
239
- :effective_url => easy.effective_url,
240
- :primary_ip => easy.primary_ip,
241
- :curl_return_code => easy.curl_return_code,
242
- :curl_error_message => easy.curl_error_message,
243
- :redirect_count => easy.redirect_count,
244
- :request => request)
81
+ # @param [ Hash ] options The options hash.
82
+ #
83
+ # @option options :max_concurrency [ Integer ] Number
84
+ # of max concurrent connections to create. Default is
85
+ # 200.
86
+ #
87
+ # @see http://rubydoc.info/github/typhoeus/ethon/Ethon/Multi#initialize-instance_method
88
+ # Ethon::Multi#initialize
89
+ def initialize(options = {})
90
+ @options = options
91
+ @max_concurrency = Integer(@options.fetch(:max_concurrency, 200))
92
+ @multi = Ethon::Multi.new(options.reject{|k,_| k==:max_concurrency})
245
93
  end
246
94
  end
247
95
  end
@@ -0,0 +1,70 @@
1
+ require 'thread'
2
+
3
+ module Typhoeus
4
+
5
+ # The easy pool stores already initialized
6
+ # easy handles for future use. This is useful
7
+ # because creating them is expensive.
8
+ #
9
+ # @api private
10
+ module Pool
11
+ @mutex = Mutex.new
12
+ @pid = Process.pid
13
+
14
+ # Releases easy into the pool. The easy handle is
15
+ # reset before it gets back in.
16
+ #
17
+ # @example Release easy.
18
+ # Typhoeus::Pool.release(easy)
19
+ def self.release(easy)
20
+ easy.cookielist = "flush" # dump all known cookies to 'cookiejar'
21
+ easy.cookielist = "all" # remove all cookies from memory for this handle
22
+ easy.reset
23
+ @mutex.synchronize { easies << easy }
24
+ end
25
+
26
+ # Return an easy from the pool.
27
+ #
28
+ # @example Return easy.
29
+ # Typhoeus::Pool.get
30
+ #
31
+ # @return [ Ethon::Easy ] The easy.
32
+ def self.get
33
+ @mutex.synchronize do
34
+ if @pid == Process.pid
35
+ easies.pop
36
+ else
37
+ # Process has forked. Clear all easies to avoid sockets being
38
+ # shared between processes.
39
+ @pid = Process.pid
40
+ easies.clear
41
+ nil
42
+ end
43
+ end || Ethon::Easy.new
44
+ end
45
+
46
+ # Clear the pool
47
+ def self.clear
48
+ @mutex.synchronize { easies.clear }
49
+ end
50
+
51
+ # Use yielded easy, will be released automatically afterwards.
52
+ #
53
+ # @example Use easy.
54
+ # Typhoeus::Pool.with_easy do |easy|
55
+ # # use easy
56
+ # end
57
+ def self.with_easy(&block)
58
+ easy = get
59
+ yield easy
60
+ ensure
61
+ release(easy) if easy
62
+ end
63
+
64
+ private
65
+
66
+ def self.easies
67
+ @easies ||= []
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,12 @@
1
+ require "typhoeus"
2
+
3
+ module Rails
4
+ module Typhoeus
5
+ class Railtie < Rails::Railtie
6
+ # Need to include the Typhoeus middleware.
7
+ initializer "include the identity map" do |app|
8
+ app.config.middleware.use "Rack::Typhoeus::Middleware::ParamsDecoder"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,125 @@
1
+ module Typhoeus
2
+ class Request
3
+
4
+ # Module containing logic about shortcuts to
5
+ # http methods. Like
6
+ # Typhoeus.get("www.example.com")
7
+ module Actions
8
+
9
+ # Make a get request.
10
+ #
11
+ # @example Make get request.
12
+ # Typhoeus.get("www.example.com")
13
+ #
14
+ # @param (see Typhoeus::Request#initialize)
15
+ #
16
+ # @option (see Typhoeus::Request#initialize)
17
+ #
18
+ # @return (see Typhoeus::Response#initialize)
19
+ #
20
+ # @note (see Typhoeus::Request#initialize)
21
+ def get(base_url, options = {})
22
+ Request.new(base_url, options.merge(:method => :get)).run
23
+ end
24
+
25
+ # Make a post request.
26
+ #
27
+ # @example Make post request.
28
+ # Typhoeus.post("www.example.com")
29
+ #
30
+ # @param (see Typhoeus::Request#initialize)
31
+ #
32
+ # @option (see Typhoeus::Request#initialize)
33
+ #
34
+ # @return (see Typhoeus::Response#initialize)
35
+ #
36
+ # @note (see Typhoeus::Request#initialize)
37
+ def post(base_url, options = {})
38
+ Request.new(base_url, options.merge(:method => :post)).run
39
+ end
40
+
41
+ # Make a put request.
42
+ #
43
+ # @example Make put request.
44
+ # Typhoeus.put("www.example.com")
45
+ #
46
+ # @param (see Typhoeus::Request#initialize)
47
+ #
48
+ # @option options :params [ Hash ] Params hash which
49
+ # is attached to the base_url.
50
+ # @option options :body [ Hash ] Body hash which
51
+ # becomes a PUT request body.
52
+ #
53
+ # @return (see Typhoeus::Response#initialize)
54
+ #
55
+ # @note (see Typhoeus::Request#initialize)
56
+ def put(base_url, options = {})
57
+ Request.new(base_url, options.merge(:method => :put)).run
58
+ end
59
+
60
+ # Make a delete request.
61
+ #
62
+ # @example Make delete request.
63
+ # Typhoeus.delete("www.example.com")
64
+ #
65
+ # @param (see Typhoeus::Request#initialize)
66
+ #
67
+ # @option (see Typhoeus::Request#initialize)
68
+ #
69
+ # @return (see Typhoeus::Response#initialize)
70
+ #
71
+ # @note (see Typhoeus::Request#initialize)
72
+ def delete(base_url, options = {})
73
+ Request.new(base_url, options.merge(:method => :delete)).run
74
+ end
75
+
76
+ # Make a head request.
77
+ #
78
+ # @example Make head request.
79
+ # Typhoeus.head("www.example.com")
80
+ #
81
+ # @param (see Typhoeus::Request#initialize)
82
+ #
83
+ # @option (see Typhoeus::Request#initialize)
84
+ #
85
+ # @return (see Typhoeus::Response#initialize)
86
+ #
87
+ # @note (see Typhoeus::Request#initialize)
88
+ def head(base_url, options = {})
89
+ Request.new(base_url, options.merge(:method => :head)).run
90
+ end
91
+
92
+ # Make a patch request.
93
+ #
94
+ # @example Make patch request.
95
+ # Typhoeus.patch("www.example.com")
96
+ #
97
+ # @param (see Typhoeus::Request#initialize)
98
+ #
99
+ # @option (see Typhoeus::Request#initialize)
100
+ #
101
+ # @return (see Typhoeus::Response#initialize)
102
+ #
103
+ # @note (see Typhoeus::Request#initialize)
104
+ def patch(base_url, options = {})
105
+ Request.new(base_url, options.merge(:method => :patch)).run
106
+ end
107
+
108
+ # Make a options request.
109
+ #
110
+ # @example Make options request.
111
+ # Typhoeus.options("www.example.com")
112
+ #
113
+ # @param (see Typhoeus::Request#initialize)
114
+ #
115
+ # @option (see Typhoeus::Request#initialize)
116
+ #
117
+ # @return (see Typhoeus::Response#initialize)
118
+ #
119
+ # @note (see Typhoeus::Request#initialize)
120
+ def options(base_url, options = {})
121
+ Request.new(base_url, options.merge(:method => :options)).run
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,30 @@
1
+ module Typhoeus
2
+ class Request
3
+
4
+ # This module provides a way to hook into before
5
+ # a request runs. This is very powerful
6
+ # and you should be careful because when you accidently
7
+ # return a falsy value the request won't be executed.
8
+ #
9
+ # @api private
10
+ module Before
11
+
12
+ # Overrride run in order to execute callbacks in
13
+ # Typhoeus.before. Will break and return when a
14
+ # callback returns nil or false. Calls super
15
+ # otherwise.
16
+ #
17
+ # @example Run the request.
18
+ # request.run
19
+ def run
20
+ Typhoeus.before.each do |callback|
21
+ value = callback.call(self)
22
+ if value.nil? || value == false || value.is_a?(Response)
23
+ return response
24
+ end
25
+ end
26
+ super
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,52 @@
1
+ module Typhoeus
2
+ class Request
3
+
4
+ # This module handles the blocked connection request mode on
5
+ # the request side, where only stubbed requests
6
+ # are allowed.
7
+ # Connection blocking needs to be turned on:
8
+ # Typhoeus.configure do |config|
9
+ # config.block_connection = true
10
+ # end
11
+ #
12
+ # When trying to do real requests a NoStub error
13
+ # is raised.
14
+ #
15
+ # @api private
16
+ module BlockConnection
17
+
18
+ # Overrides run in order to check before if block connection
19
+ # is turned on. If thats the case a NoStub error is
20
+ # raised.
21
+ #
22
+ # @example Run request.
23
+ # request.run
24
+ #
25
+ # @raise [Typhoeus::Errors::NoStub] If connection is blocked
26
+ # and no stub defined.
27
+ def run
28
+ if blocked?
29
+ raise Typhoeus::Errors::NoStub.new(self)
30
+ else
31
+ super
32
+ end
33
+ end
34
+
35
+ # Returns wether a request is blocked or not. Takes
36
+ # request.block_connection and Typhoeus::Config.block_connection
37
+ # into consideration.
38
+ #
39
+ # @example Blocked?
40
+ # request.blocked?
41
+ #
42
+ # @return [ Boolean ] True if blocked, false else.
43
+ def blocked?
44
+ if block_connection.nil?
45
+ Typhoeus::Config.block_connection
46
+ else
47
+ block_connection
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,38 @@
1
+ module Typhoeus
2
+ class Request
3
+ module Cacheable
4
+ def response=(response)
5
+ cache.set(self, response) if cacheable? && !response.cached?
6
+ super
7
+ end
8
+
9
+ def cacheable?
10
+ cache
11
+ end
12
+
13
+ def run
14
+ if response = cached_response
15
+ response.cached = true
16
+ finish(response)
17
+ else
18
+ super
19
+ end
20
+ end
21
+
22
+ def cached_response
23
+ cacheable? && cache.get(self)
24
+ end
25
+
26
+ def cache_ttl
27
+ options[:cache_ttl]
28
+ end
29
+
30
+ private
31
+
32
+ def cache
33
+ return nil if options[:cache] === false
34
+ options[:cache] || Typhoeus::Config.cache
35
+ end
36
+ end
37
+ end
38
+ end