typhoeus 0.4.2 → 0.5.0.alpha

Sign up to get free protection for your applications and to get access to all the features.
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