typhoeus 0.4.2 → 0.5.0.alpha

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 (56) hide show
  1. data/CHANGELOG.md +86 -28
  2. data/Gemfile +17 -1
  3. data/README.md +20 -422
  4. data/Rakefile +21 -12
  5. data/lib/typhoeus.rb +58 -41
  6. data/lib/typhoeus/config.rb +14 -0
  7. data/lib/typhoeus/errors.rb +9 -0
  8. data/lib/typhoeus/errors/no_stub.rb +12 -0
  9. data/lib/typhoeus/errors/typhoeus_error.rb +8 -0
  10. data/lib/typhoeus/expectation.rb +126 -0
  11. data/lib/typhoeus/hydra.rb +31 -236
  12. data/lib/typhoeus/hydras/block_connection.rb +33 -0
  13. data/lib/typhoeus/hydras/easy_factory.rb +67 -0
  14. data/lib/typhoeus/hydras/easy_pool.rb +40 -0
  15. data/lib/typhoeus/hydras/memoizable.rb +53 -0
  16. data/lib/typhoeus/hydras/queueable.rb +46 -0
  17. data/lib/typhoeus/hydras/runnable.rb +18 -0
  18. data/lib/typhoeus/hydras/stubbable.rb +27 -0
  19. data/lib/typhoeus/request.rb +68 -243
  20. data/lib/typhoeus/requests/actions.rb +101 -0
  21. data/lib/typhoeus/requests/block_connection.rb +31 -0
  22. data/lib/typhoeus/requests/callbacks.rb +82 -0
  23. data/lib/typhoeus/requests/marshal.rb +21 -0
  24. data/lib/typhoeus/requests/memoizable.rb +36 -0
  25. data/lib/typhoeus/requests/operations.rb +52 -0
  26. data/lib/typhoeus/requests/responseable.rb +29 -0
  27. data/lib/typhoeus/requests/stubbable.rb +29 -0
  28. data/lib/typhoeus/response.rb +24 -118
  29. data/lib/typhoeus/responses/header.rb +50 -0
  30. data/lib/typhoeus/responses/informations.rb +43 -0
  31. data/lib/typhoeus/responses/legacy.rb +27 -0
  32. data/lib/typhoeus/responses/status.rb +78 -0
  33. data/lib/typhoeus/version.rb +3 -1
  34. metadata +34 -141
  35. data/lib/typhoeus/curl.rb +0 -453
  36. data/lib/typhoeus/easy.rb +0 -115
  37. data/lib/typhoeus/easy/auth.rb +0 -14
  38. data/lib/typhoeus/easy/callbacks.rb +0 -33
  39. data/lib/typhoeus/easy/ffi_helper.rb +0 -61
  40. data/lib/typhoeus/easy/infos.rb +0 -90
  41. data/lib/typhoeus/easy/options.rb +0 -115
  42. data/lib/typhoeus/easy/proxy.rb +0 -20
  43. data/lib/typhoeus/easy/ssl.rb +0 -82
  44. data/lib/typhoeus/filter.rb +0 -28
  45. data/lib/typhoeus/form.rb +0 -61
  46. data/lib/typhoeus/header.rb +0 -54
  47. data/lib/typhoeus/hydra/callbacks.rb +0 -24
  48. data/lib/typhoeus/hydra/connect_options.rb +0 -61
  49. data/lib/typhoeus/hydra/stubbing.rb +0 -68
  50. data/lib/typhoeus/hydra_mock.rb +0 -131
  51. data/lib/typhoeus/multi.rb +0 -146
  52. data/lib/typhoeus/param_processor.rb +0 -43
  53. data/lib/typhoeus/remote.rb +0 -306
  54. data/lib/typhoeus/remote_method.rb +0 -108
  55. data/lib/typhoeus/remote_proxy_object.rb +0 -50
  56. data/lib/typhoeus/utils.rb +0 -50
@@ -0,0 +1,101 @@
1
+ module Typhoeus
2
+ module Requests # :nodoc:
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 [ String ] url The url to request.
15
+ # @param [ options ] options The options.
16
+ #
17
+ # @return [ Response ] The response.
18
+ def get(url, options = {})
19
+ Request.run(url, options.merge(:method => :get))
20
+ end
21
+
22
+ # Make a post request.
23
+ #
24
+ # @example Make post request.
25
+ # Typhoeus.post("www.example.com")
26
+ #
27
+ # @param [ String ] url The url to request.
28
+ # @param [ options ] options The options.
29
+ #
30
+ # @return [ Response ] The response.
31
+ def post(url, options = {})
32
+ Request.run(url, options.merge(:method => :post))
33
+ end
34
+
35
+ # Make a put request.
36
+ #
37
+ # @example Make put request.
38
+ # Typhoeus.put("www.example.com")
39
+ #
40
+ # @param [ String ] url The url to request.
41
+ # @param [ options ] options The options.
42
+ #
43
+ # @return [ Response ] The response.
44
+ def put(url, options = {})
45
+ Request.run(url, options.merge(:method => :put))
46
+ end
47
+
48
+ # Make a delete request.
49
+ #
50
+ # @example Make delete request.
51
+ # Typhoeus.delete("www.example.com")
52
+ #
53
+ # @param [ String ] url The url to request.
54
+ # @param [ options ] options The options.
55
+ #
56
+ # @return [ Response ] The response.
57
+ def delete(url, options = {})
58
+ Request.run(url, options.merge(:method => :delete))
59
+ end
60
+
61
+ # Make a head request.
62
+ #
63
+ # @example Make head request.
64
+ # Typhoeus.head("www.example.com")
65
+ #
66
+ # @param [ String ] url The url to request.
67
+ # @param [ options ] options The options.
68
+ #
69
+ # @return [ Response ] The response.
70
+ def head(url, options = {})
71
+ Request.run(url, options.merge(:method => :head))
72
+ end
73
+
74
+ # Make a patch request.
75
+ #
76
+ # @example Make patch request.
77
+ # Typhoeus.patch("www.example.com")
78
+ #
79
+ # @param [ String ] url The url to request.
80
+ # @param [ options ] options The options.
81
+ #
82
+ # @return [ Response ] The response.
83
+ def patch(url, options = {})
84
+ Request.run(url, options.merge(:method => :patch))
85
+ end
86
+
87
+ # Make a options request.
88
+ #
89
+ # @example Make options request.
90
+ # Typhoeus.options("www.example.com")
91
+ #
92
+ # @param [ String ] url The url to request.
93
+ # @param [ options ] options The options.
94
+ #
95
+ # @return [ Response ] The response.
96
+ def options(url, options = {})
97
+ Request.run(url, options.merge(:method => :options))
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,31 @@
1
+ module Typhoeus
2
+ module Requests
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
+ module BlockConnection
15
+
16
+ # Overrides run in order to check before if block connection
17
+ # is turned on. If thats the case a NoStub error is
18
+ # raised.
19
+ #
20
+ # @example Run request.
21
+ # request.run
22
+ def run
23
+ if Typhoeus::Config.block_connection
24
+ raise Typhoeus::Errors::NoStub.new(self)
25
+ else
26
+ super
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,82 @@
1
+ module Typhoeus
2
+ module Requests
3
+
4
+ # This module contains the logic for the response callbacks.
5
+ # The on_complete callback is the only one at the moment.
6
+ #
7
+ # You can set multiple callbacks, which are then executed
8
+ # in the same order.
9
+ #
10
+ # request.on_complete { p 1 }
11
+ # request.on_complete { p 2 }
12
+ # request.execute_callbacks
13
+ # #=> 1
14
+ # #=> 2
15
+ #
16
+ # You can clear the callbacks:
17
+ #
18
+ # request.on_complete { p 1 }
19
+ # request.on_complete { p 2 }
20
+ # request.on_complete.clear
21
+ # request.execute_callbacks
22
+ # #=> []
23
+ module Callbacks
24
+
25
+ module Types
26
+ # Set on_complete callback.
27
+ #
28
+ # @example Set on_complete.
29
+ # request.on_complete { p "yay" }
30
+ #
31
+ # @param [ Block ] block The block to execute.
32
+ def on_complete(&block)
33
+ @on_complete ||= []
34
+ @on_complete << block if block_given?
35
+ @on_complete
36
+ end
37
+
38
+ # Set on_success callback.
39
+ #
40
+ # @example Set on_success.
41
+ # request.on_success { p "yay" }
42
+ #
43
+ # @param [ Block ] block The block to execute.
44
+ def on_success(&block)
45
+ @on_success ||= []
46
+ @on_success << block if block_given?
47
+ @on_success
48
+ end
49
+
50
+ # Set on_failure callback.
51
+ #
52
+ # @example Set on_failure.
53
+ # request.on_failure { p "yay" }
54
+ #
55
+ # @param [ Block ] block The block to execute.
56
+ def on_failure(&block)
57
+ @on_failure ||= []
58
+ @on_failure << block if block_given?
59
+ @on_failure
60
+ end
61
+ end
62
+
63
+ # Execute nessecary callback and yields response. This
64
+ # include in every case on_complete, on_success if
65
+ # successful and on_failure if not.
66
+ #
67
+ # @example Execute callbacks.
68
+ # request.execute_callbacks
69
+ def execute_callbacks
70
+ callbacks = Typhoeus.on_complete + on_complete
71
+
72
+ if response && response.success?
73
+ callbacks += Typhoeus.on_success + on_success
74
+ elsif response
75
+ callbacks += Typhoeus.on_failure + on_failure
76
+ end
77
+
78
+ callbacks.map{ |callback| callback.call(self.response) }
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,21 @@
1
+ module Typhoeus
2
+ module Requests
3
+
4
+ # This module contains custom serializer.
5
+ module Marshal
6
+
7
+ # Return the important data needed to serialize this Request, except the
8
+ # `on_complete` handler, since they cannot be marshalled.
9
+ def marshal_dump
10
+ (instance_variables - ['@on_complete', :@on_complete]).map do |name|
11
+ [name, instance_variable_get(name)]
12
+ end
13
+ end
14
+
15
+ # Load.
16
+ def marshal_load(attributes)
17
+ attributes.each { |name, value| instance_variable_set(name, value) }
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,36 @@
1
+ module Typhoeus
2
+ module Requests
3
+
4
+ # This module handles the GET request memoization
5
+ # on the request side. Memoization needs to be turned
6
+ # on:
7
+ # Typhoeus.configure do |config|
8
+ # config.memoize = true
9
+ # end
10
+ module Memoizable
11
+
12
+ # Override response setter and memoizes response
13
+ # if the request is memoizable.
14
+ #
15
+ # @param [ Response ] response The response to set.
16
+ #
17
+ # @example Set response.
18
+ # request.response = response
19
+ def response=(response)
20
+ hydra.memory[self] = response if memoizable?
21
+ super
22
+ end
23
+
24
+ # Return whether a request is memoizable.
25
+ #
26
+ # @example Is request memoizable?
27
+ # request.memoizable?
28
+ #
29
+ # @return [ Boolean ] Return true if memoizable, false else.
30
+ def memoizable?
31
+ Typhoeus::Config.memoize &&
32
+ (options[:method].nil? || options[:method] == :get)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,52 @@
1
+ module Typhoeus
2
+ module Requests
3
+
4
+ # This module contains everything what is necessary
5
+ # to make a single request.
6
+ module Operations
7
+
8
+ # :nodoc:
9
+ def self.included(base)
10
+ base.extend ClassMethods
11
+ end
12
+
13
+ module ClassMethods # :nodoc:
14
+
15
+ # Shortcut to perform a single request.
16
+ #
17
+ # @example Perform request.
18
+ # Request.run("www.example.com")
19
+ #
20
+ # @param [ String ] url The url to request.
21
+ # @param [ Hash ] options The options hash.
22
+ #
23
+ # @return [ Response ] The response.
24
+ def run(url, options = {})
25
+ new(url, options).run
26
+ end
27
+ end
28
+
29
+ # Run a request.
30
+ #
31
+ # @example Run a request.
32
+ # request.run
33
+ #
34
+ # @return [ Response ] The response.
35
+ def run
36
+ easy = Typhoeus.get_easy
37
+ easy.http_request(
38
+ url,
39
+ options.fetch(:method, :get),
40
+ options.reject{|k,_| k==:method}
41
+ )
42
+ easy.prepare
43
+ easy.perform
44
+ @response = Response.new(easy.to_hash)
45
+ @response.request = self
46
+ Typhoeus.release_easy(easy)
47
+ execute_callbacks
48
+ @response
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,29 @@
1
+ module Typhoeus
2
+ module Requests
3
+
4
+ # This module contains logic for having a reponse
5
+ # getter and setter.
6
+ module Responseable
7
+
8
+ # Set the response.
9
+ #
10
+ # @example Set response.
11
+ # request.response = response
12
+ #
13
+ # @param [ Response ] value The response to set.
14
+ def response=(value)
15
+ @response = value
16
+ end
17
+
18
+ # Return the response.
19
+ #
20
+ # @example Return response.
21
+ # request.response
22
+ #
23
+ # @return [ Response ] The response.
24
+ def response
25
+ @response ||= nil
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ module Typhoeus
2
+ module Requests
3
+
4
+ # This module handles stubbing on the request side.
5
+ # It plays well with the block_connection configuration,
6
+ # which raises when you make a request which is not stubbed.
7
+ module Stubbable
8
+
9
+ # Override run in order to check for matching expecations.
10
+ # When an expecation is found, super is not called. Instead a
11
+ # canned response is assigned to the request.
12
+ #
13
+ # @example Run the request.
14
+ # request.run
15
+ #
16
+ # @return [ Response ] The response.
17
+ def run
18
+ if expectation = Expectation.find_by(self)
19
+ @response = expectation.response
20
+ @response.mock = true
21
+ execute_callbacks
22
+ @response
23
+ else
24
+ super
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,123 +1,29 @@
1
- module Typhoeus
2
- class Response
3
- attr_accessor :request, :mock
4
- attr_reader :code, :headers, :body, :time,
5
- :requested_url, :requested_remote_method,
6
- :requested_http_method, :start_time,
7
- :effective_url, :start_transfer_time,
8
- :app_connect_time, :pretransfer_time,
9
- :connect_time, :name_lookup_time,
10
- :curl_return_code, :curl_error_message,
11
- :primary_ip, :redirect_count
12
-
13
- attr_writer :headers_hash
14
-
15
- def initialize(params = {})
16
- @code = params[:code]
17
- @curl_return_code = params[:curl_return_code]
18
- @curl_error_message = params[:curl_error_message]
19
- @status_message = params[:status_message]
20
- @http_version = params[:http_version]
21
- @headers = params[:headers]
22
- @body = params[:body]
23
- @time = params[:time]
24
- @requested_url = params[:requested_url]
25
- @requested_http_method = params[:requested_http_method]
26
- @start_time = params[:start_time]
27
- @start_transfer_time = params[:start_transfer_time]
28
- @app_connect_time = params[:app_connect_time]
29
- @pretransfer_time = params[:pretransfer_time]
30
- @connect_time = params[:connect_time]
31
- @name_lookup_time = params[:name_lookup_time]
32
- @request = params[:request]
33
- @effective_url = params[:effective_url]
34
- @primary_ip = params[:primary_ip]
35
- @redirect_count = params[:redirect_count]
36
- @mock = params[:mock] || false # default
37
- @headers_hash = Header.new(params[:headers_hash]) if params[:headers_hash]
38
- end
39
-
40
- # Returns true if this is a mock response.
41
- def mock?
42
- @mock
43
- end
44
-
45
- def headers
46
- @headers ||= @headers_hash ? construct_header_string : ''
47
- end
48
-
49
- def headers_hash
50
- @headers_hash ||= begin
51
- headers.split("\n").map {|o| o.strip}.inject(Typhoeus::Header.new) do |hash, o|
52
- if o.empty? || o =~ /^HTTP\/[\d\.]+/
53
- hash
54
- else
55
- i = o.index(":") || o.size
56
- key = o.slice(0, i)
57
- value = o.slice(i + 1, o.size)
58
- value = value.strip unless value.nil?
59
- if hash.key? key
60
- hash[key] = [hash[key], value].flatten
61
- else
62
- hash[key] = value
63
- end
64
-
65
- hash
66
- end
67
- end
68
- end
69
- end
70
-
71
- def status_message
72
- return @status_message if @status_message != nil
73
-
74
- # HTTP servers can choose not to include the explanation to HTTP codes. The RFC
75
- # states this (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4):
76
- # Except when responding to a HEAD request, the server SHOULD include an entity containing
77
- # an explanation of the error situation [...]
78
- # This means 'HTTP/1.1 404' is as valid as 'HTTP/1.1 404 Not Found' and we have to handle it.
1
+ require 'typhoeus/responses/header'
2
+ require 'typhoeus/responses/informations'
3
+ require 'typhoeus/responses/legacy'
4
+ require 'typhoeus/responses/status'
79
5
 
80
- # Regexp doc: http://rubular.com/r/eAr1oVYsVa
81
- if first_header_line != nil and first_header_line[/\d{3} (.*)$/, 1] != nil
82
- @status_message = first_header_line[/\d{3} (.*)$/, 1].chomp
83
- else
84
- @status_message = nil
85
- end
86
- end
87
-
88
- def http_version
89
- @http_version ||= first_header_line ? first_header_line[/HTTP\/(\S+)/, 1] : nil
90
- end
91
-
92
- def success?
93
- @code >= 200 && @code < 300
94
- end
95
-
96
- def modified?
97
- @code != 304
98
- end
6
+ module Typhoeus
99
7
 
100
- def timed_out?
101
- curl_return_code == 28
8
+ # This class respresents the response.
9
+ class Response
10
+ include Responses::Informations
11
+ include Responses::Legacy
12
+ include Responses::Status
13
+
14
+ attr_accessor :request, :options, :mock
15
+
16
+ # Create a new response.
17
+ #
18
+ # @example Create a response.
19
+ # Response.new
20
+ #
21
+ # @param [ Hash ] options The options hash.
22
+ #
23
+ # @return [ Response ] The new response.
24
+ def initialize(options = {})
25
+ @options = options
26
+ @header = options[:header]
102
27
  end
103
-
104
- private
105
-
106
- def first_header_line
107
- @first_header_line ||= @headers.to_s.split("\n").first
108
- end
109
-
110
- def construct_header_string
111
- lines = ["HTTP/#{http_version} #{code} #{status_message}"]
112
-
113
- @headers_hash.each do |key, values|
114
- [values].flatten.each do |value|
115
- lines << "#{key}: #{value}"
116
- end
117
- end
118
-
119
- lines << '' << ''
120
- lines.join("\r\n")
121
- end
122
28
  end
123
29
  end