faraday 1.0.0 → 2.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +299 -1
  3. data/LICENSE.md +1 -1
  4. data/README.md +35 -23
  5. data/Rakefile +3 -1
  6. data/examples/client_spec.rb +68 -14
  7. data/examples/client_test.rb +80 -15
  8. data/lib/faraday/adapter/test.rb +117 -52
  9. data/lib/faraday/adapter.rb +6 -20
  10. data/lib/faraday/adapter_registry.rb +3 -1
  11. data/lib/faraday/connection.rb +73 -132
  12. data/lib/faraday/encoders/flat_params_encoder.rb +9 -2
  13. data/lib/faraday/encoders/nested_params_encoder.rb +20 -8
  14. data/lib/faraday/error.rb +37 -8
  15. data/lib/faraday/logging/formatter.rb +28 -15
  16. data/lib/faraday/methods.rb +6 -0
  17. data/lib/faraday/middleware.rb +17 -5
  18. data/lib/faraday/middleware_registry.rb +17 -63
  19. data/lib/faraday/options/connection_options.rb +7 -6
  20. data/lib/faraday/options/env.rb +85 -62
  21. data/lib/faraday/options/proxy_options.rb +11 -3
  22. data/lib/faraday/options/request_options.rb +7 -6
  23. data/lib/faraday/options/ssl_options.rb +56 -45
  24. data/lib/faraday/options.rb +11 -14
  25. data/lib/faraday/rack_builder.rb +35 -32
  26. data/lib/faraday/request/authorization.rb +37 -36
  27. data/lib/faraday/request/instrumentation.rb +5 -1
  28. data/lib/faraday/request/json.rb +70 -0
  29. data/lib/faraday/request/url_encoded.rb +8 -2
  30. data/lib/faraday/request.rb +22 -29
  31. data/lib/faraday/response/json.rb +73 -0
  32. data/lib/faraday/response/logger.rb +8 -4
  33. data/lib/faraday/response/raise_error.rb +41 -3
  34. data/lib/faraday/response.rb +10 -23
  35. data/lib/faraday/utils/headers.rb +9 -4
  36. data/lib/faraday/utils.rb +22 -10
  37. data/lib/faraday/version.rb +5 -0
  38. data/lib/faraday.rb +49 -58
  39. data/spec/faraday/adapter/test_spec.rb +442 -0
  40. data/spec/faraday/connection_spec.rb +207 -90
  41. data/spec/faraday/error_spec.rb +45 -5
  42. data/spec/faraday/middleware_registry_spec.rb +31 -0
  43. data/spec/faraday/middleware_spec.rb +50 -6
  44. data/spec/faraday/options/env_spec.rb +8 -2
  45. data/spec/faraday/options/options_spec.rb +1 -1
  46. data/spec/faraday/options/proxy_options_spec.rb +15 -0
  47. data/spec/faraday/params_encoders/flat_spec.rb +8 -0
  48. data/spec/faraday/params_encoders/nested_spec.rb +16 -0
  49. data/spec/faraday/rack_builder_spec.rb +171 -50
  50. data/spec/faraday/request/authorization_spec.rb +54 -24
  51. data/spec/faraday/request/instrumentation_spec.rb +5 -7
  52. data/spec/faraday/request/json_spec.rb +199 -0
  53. data/spec/faraday/request/url_encoded_spec.rb +25 -2
  54. data/spec/faraday/request_spec.rb +11 -10
  55. data/spec/faraday/response/json_spec.rb +189 -0
  56. data/spec/faraday/response/logger_spec.rb +38 -0
  57. data/spec/faraday/response/raise_error_spec.rb +105 -0
  58. data/spec/faraday/response_spec.rb +3 -1
  59. data/spec/faraday/utils/headers_spec.rb +22 -4
  60. data/spec/faraday/utils_spec.rb +63 -1
  61. data/spec/faraday_spec.rb +8 -4
  62. data/spec/spec_helper.rb +6 -5
  63. data/spec/support/fake_safe_buffer.rb +1 -1
  64. data/spec/support/helper_methods.rb +0 -37
  65. data/spec/support/shared_examples/adapter.rb +4 -3
  66. data/spec/support/shared_examples/request_method.rb +60 -31
  67. metadata +19 -44
  68. data/UPGRADING.md +0 -55
  69. data/lib/faraday/adapter/em_http.rb +0 -285
  70. data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -62
  71. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -69
  72. data/lib/faraday/adapter/em_synchrony.rb +0 -150
  73. data/lib/faraday/adapter/excon.rb +0 -124
  74. data/lib/faraday/adapter/httpclient.rb +0 -151
  75. data/lib/faraday/adapter/net_http.rb +0 -209
  76. data/lib/faraday/adapter/net_http_persistent.rb +0 -91
  77. data/lib/faraday/adapter/patron.rb +0 -132
  78. data/lib/faraday/adapter/rack.rb +0 -75
  79. data/lib/faraday/adapter/typhoeus.rb +0 -15
  80. data/lib/faraday/autoload.rb +0 -95
  81. data/lib/faraday/dependency_loader.rb +0 -37
  82. data/lib/faraday/file_part.rb +0 -128
  83. data/lib/faraday/param_part.rb +0 -53
  84. data/lib/faraday/request/basic_authentication.rb +0 -20
  85. data/lib/faraday/request/multipart.rb +0 -99
  86. data/lib/faraday/request/retry.rb +0 -239
  87. data/lib/faraday/request/token_authentication.rb +0 -20
  88. data/spec/faraday/adapter/em_http_spec.rb +0 -47
  89. data/spec/faraday/adapter/em_synchrony_spec.rb +0 -16
  90. data/spec/faraday/adapter/excon_spec.rb +0 -49
  91. data/spec/faraday/adapter/httpclient_spec.rb +0 -73
  92. data/spec/faraday/adapter/net_http_persistent_spec.rb +0 -57
  93. data/spec/faraday/adapter/net_http_spec.rb +0 -64
  94. data/spec/faraday/adapter/patron_spec.rb +0 -18
  95. data/spec/faraday/adapter/rack_spec.rb +0 -8
  96. data/spec/faraday/adapter/typhoeus_spec.rb +0 -7
  97. data/spec/faraday/composite_read_io_spec.rb +0 -80
  98. data/spec/faraday/request/multipart_spec.rb +0 -274
  99. data/spec/faraday/request/retry_spec.rb +0 -242
  100. data/spec/faraday/response/middleware_spec.rb +0 -52
  101. data/spec/support/webmock_rack_app.rb +0 -68
@@ -6,8 +6,8 @@ module Faraday
6
6
  # client or server error responses.
7
7
  class RaiseError < Middleware
8
8
  # rubocop:disable Naming/ConstantName
9
- ClientErrorStatuses = (400...500).freeze
10
- ServerErrorStatuses = (500...600).freeze
9
+ ClientErrorStatuses = (400...500)
10
+ ServerErrorStatuses = (500...600)
11
11
  # rubocop:enable Naming/ConstantName
12
12
 
13
13
  def on_complete(env)
@@ -24,10 +24,14 @@ module Faraday
24
24
  # mimic the behavior that we get with proxy requests with HTTPS
25
25
  msg = %(407 "Proxy Authentication Required")
26
26
  raise Faraday::ProxyAuthError.new(msg, response_values(env))
27
+ when 408
28
+ raise Faraday::RequestTimeoutError, response_values(env)
27
29
  when 409
28
30
  raise Faraday::ConflictError, response_values(env)
29
31
  when 422
30
32
  raise Faraday::UnprocessableEntityError, response_values(env)
33
+ when 429
34
+ raise Faraday::TooManyRequestsError, response_values(env)
31
35
  when ClientErrorStatuses
32
36
  raise Faraday::ClientError, response_values(env)
33
37
  when ServerErrorStatuses
@@ -37,9 +41,43 @@ module Faraday
37
41
  end
38
42
  end
39
43
 
44
+ # Returns a hash of response data with the following keys:
45
+ # - status
46
+ # - headers
47
+ # - body
48
+ # - request
49
+ #
50
+ # The `request` key is omitted when the middleware is explicitly
51
+ # configured with the option `include_request: false`.
40
52
  def response_values(env)
41
- { status: env.status, headers: env.response_headers, body: env.body }
53
+ response = {
54
+ status: env.status,
55
+ headers: env.response_headers,
56
+ body: env.body
57
+ }
58
+
59
+ # Include the request data by default. If the middleware was explicitly
60
+ # configured to _not_ include request data, then omit it.
61
+ return response unless options.fetch(:include_request, true)
62
+
63
+ response.merge(
64
+ request: {
65
+ method: env.method,
66
+ url: env.url,
67
+ url_path: env.url.path,
68
+ params: query_params(env),
69
+ headers: env.request_headers,
70
+ body: env.request_body
71
+ }
72
+ )
73
+ end
74
+
75
+ def query_params(env)
76
+ env.request.params_encoder ||= Faraday::Utils.default_params_encoder
77
+ env.params_encoder.decode(env.url.query)
42
78
  end
43
79
  end
44
80
  end
45
81
  end
82
+
83
+ Faraday::Response.register_middleware(raise_error: Faraday::Response::RaiseError)
@@ -5,28 +5,9 @@ require 'forwardable'
5
5
  module Faraday
6
6
  # Response represents an HTTP response from making an HTTP request.
7
7
  class Response
8
- # Used for simple response middleware.
9
- class Middleware < Faraday::Middleware
10
- def call(env)
11
- @app.call(env).on_complete do |environment|
12
- on_complete(environment)
13
- end
14
- end
15
-
16
- # Override this to modify the environment after the response has finished.
17
- # Calls the `parse` method if defined
18
- def on_complete(env)
19
- env.body = parse(env.body) if respond_to?(:parse) && env.parse_body?
20
- end
21
- end
22
-
23
8
  extend Forwardable
24
9
  extend MiddlewareRegistry
25
10
 
26
- register_middleware File.expand_path('response', __dir__),
27
- raise_error: [:RaiseError, 'raise_error'],
28
- logger: [:Logger, 'logger']
29
-
30
11
  def initialize(env = nil)
31
12
  @env = Env.from(env) if env
32
13
  @on_complete_callbacks = []
@@ -45,6 +26,7 @@ module Faraday
45
26
  def headers
46
27
  finished? ? env.response_headers : {}
47
28
  end
29
+
48
30
  def_delegator :headers, :[]
49
31
 
50
32
  def body
@@ -56,10 +38,10 @@ module Faraday
56
38
  end
57
39
 
58
40
  def on_complete(&block)
59
- if !finished?
60
- @on_complete_callbacks << block
61
- else
41
+ if finished?
62
42
  yield(env)
43
+ else
44
+ @on_complete_callbacks << block
63
45
  end
64
46
  self
65
47
  end
@@ -79,7 +61,8 @@ module Faraday
79
61
  def to_hash
80
62
  {
81
63
  status: env.status, body: env.body,
82
- response_headers: env.response_headers
64
+ response_headers: env.response_headers,
65
+ url: env.url
83
66
  }
84
67
  end
85
68
 
@@ -102,3 +85,7 @@ module Faraday
102
85
  end
103
86
  end
104
87
  end
88
+
89
+ require 'faraday/response/json'
90
+ require 'faraday/response/logger'
91
+ require 'faraday/response/raise_error'
@@ -105,16 +105,16 @@ module Faraday
105
105
  end
106
106
 
107
107
  def to_hash
108
- ::Hash.new.update(self)
108
+ {}.update(self)
109
109
  end
110
110
 
111
111
  def parse(header_string)
112
112
  return unless header_string && !header_string.empty?
113
113
 
114
- headers = header_string.split(/\r\n/)
114
+ headers = header_string.split("\r\n")
115
115
 
116
116
  # Find the last set of response headers.
117
- start_index = headers.rindex { |x| x.match(%r{^HTTP/}) } || 0
117
+ start_index = headers.rindex { |x| x.start_with?('HTTP/') } || 0
118
118
  last_response = headers.slice(start_index, headers.size)
119
119
 
120
120
  last_response
@@ -132,7 +132,12 @@ module Faraday
132
132
 
133
133
  # Join multiple values with a comma.
134
134
  def add_parsed(key, value)
135
- self[key] ? self[key] << ', ' << value : self[key] = value
135
+ if key?(key)
136
+ self[key] = self[key].to_s
137
+ self[key] << ', ' << value
138
+ else
139
+ self[key] = value
140
+ end
136
141
  end
137
142
  end
138
143
  end
data/lib/faraday/utils.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'uri'
3
4
  require 'faraday/utils/headers'
4
5
  require 'faraday/utils/params_hash'
5
6
 
@@ -16,19 +17,27 @@ module Faraday
16
17
  NestedParamsEncoder.encode(params)
17
18
  end
18
19
 
19
- ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/.freeze
20
+ def default_space_encoding
21
+ @default_space_encoding ||= '+'
22
+ end
23
+
24
+ class << self
25
+ attr_writer :default_space_encoding
26
+ end
27
+
28
+ ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/
20
29
 
21
30
  def escape(str)
22
31
  str.to_s.gsub(ESCAPE_RE) do |match|
23
- '%' + match.unpack('H2' * match.bytesize).join('%').upcase
24
- end.tr(' ', '+')
32
+ "%#{match.unpack('H2' * match.bytesize).join('%').upcase}"
33
+ end.gsub(' ', default_space_encoding)
25
34
  end
26
35
 
27
36
  def unescape(str)
28
37
  CGI.unescape str.to_s
29
38
  end
30
39
 
31
- DEFAULT_SEP = /[&;] */n.freeze
40
+ DEFAULT_SEP = /[&;] */n
32
41
 
33
42
  # Adapted from Rack
34
43
  def parse_query(query)
@@ -43,6 +52,12 @@ module Faraday
43
52
  @default_params_encoder ||= NestedParamsEncoder
44
53
  end
45
54
 
55
+ def basic_header_from(login, pass)
56
+ value = ["#{login}:#{pass}"].pack('m') # Base64 encoding
57
+ value.delete!("\n")
58
+ "Basic #{value}"
59
+ end
60
+
46
61
  class << self
47
62
  attr_writer :default_params_encoder
48
63
  end
@@ -63,10 +78,7 @@ module Faraday
63
78
  end
64
79
 
65
80
  def default_uri_parser
66
- @default_uri_parser ||= begin
67
- require 'uri'
68
- Kernel.method(:URI)
69
- end
81
+ @default_uri_parser ||= Kernel.method(:URI)
70
82
  end
71
83
 
72
84
  def default_uri_parser=(parser)
@@ -81,14 +93,14 @@ module Faraday
81
93
  # the path with the query string sorted.
82
94
  def normalize_path(url)
83
95
  url = URI(url)
84
- (url.path.start_with?('/') ? url.path : '/' + url.path) +
96
+ (url.path.start_with?('/') ? url.path : "/#{url.path}") +
85
97
  (url.query ? "?#{sort_query_params(url.query)}" : '')
86
98
  end
87
99
 
88
100
  # Recursive hash update
89
101
  def deep_merge!(target, hash)
90
102
  hash.each do |key, value|
91
- target[key] = if value.is_a?(Hash) && target[key].is_a?(Hash)
103
+ target[key] = if value.is_a?(Hash) && (target[key].is_a?(Hash) || target[key].is_a?(Options))
92
104
  deep_merge(target[key], value)
93
105
  else
94
106
  value
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Faraday
4
+ VERSION = '2.9.0'
5
+ end
data/lib/faraday.rb CHANGED
@@ -1,11 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'cgi'
4
+ require 'date'
4
5
  require 'set'
5
6
  require 'forwardable'
7
+ require 'faraday/version'
8
+ require 'faraday/methods'
9
+ require 'faraday/error'
6
10
  require 'faraday/middleware_registry'
7
- require 'faraday/dependency_loader'
8
-
11
+ require 'faraday/utils'
12
+ require 'faraday/options'
13
+ require 'faraday/connection'
14
+ require 'faraday/rack_builder'
15
+ require 'faraday/parameters'
16
+ require 'faraday/middleware'
17
+ require 'faraday/adapter'
18
+ require 'faraday/request'
19
+ require 'faraday/response'
20
+ require 'faraday/net_http'
9
21
  # This is the main namespace for Faraday.
10
22
  #
11
23
  # It provides methods to create {Connection} objects, and HTTP-related
@@ -19,9 +31,7 @@ require 'faraday/dependency_loader'
19
31
  # conn.get '/'
20
32
  #
21
33
  module Faraday
22
- VERSION = '1.0.0'
23
- METHODS_WITH_QUERY = %w[get head delete trace].freeze
24
- METHODS_WITH_BODY = %w[post put patch].freeze
34
+ CONTENT_TYPE = 'Content-Type'
25
35
 
26
36
  class << self
27
37
  # The root path that Faraday is being loaded from.
@@ -44,6 +54,10 @@ module Faraday
44
54
  # @return [Symbol] the new default_adapter.
45
55
  attr_reader :default_adapter
46
56
 
57
+ # Option for the default_adapter
58
+ # @return [Hash] default_adapter options
59
+ attr_accessor :default_adapter_options
60
+
47
61
  # Documented below, see default_connection
48
62
  attr_writer :default_connection
49
63
 
@@ -80,23 +94,10 @@ module Faraday
80
94
  # params: { page: 1 }
81
95
  # # => Faraday::Connection to http://faraday.com?page=1
82
96
  def new(url = nil, options = {}, &block)
83
- options = default_connection_options.merge(options)
97
+ options = Utils.deep_merge(default_connection_options, options)
84
98
  Faraday::Connection.new(url, options, &block)
85
99
  end
86
100
 
87
- # @private
88
- # Internal: Requires internal Faraday libraries.
89
- #
90
- # @param libs [Array] one or more relative String names to Faraday classes.
91
- # @return [void]
92
- def require_libs(*libs)
93
- libs.each do |lib|
94
- require "#{lib_path}/#{lib}"
95
- end
96
- end
97
-
98
- alias require_lib require_libs
99
-
100
101
  # Documented elsewhere, see default_adapter reader
101
102
  def default_adapter=(adapter)
102
103
  @default_connection = nil
@@ -107,6 +108,34 @@ module Faraday
107
108
  default_connection.respond_to?(symbol, include_private) || super
108
109
  end
109
110
 
111
+ # @overload default_connection
112
+ # Gets the default connection used for simple scripts.
113
+ # @return [Faraday::Connection] a connection configured with
114
+ # the default_adapter.
115
+ # @overload default_connection=(connection)
116
+ # @param connection [Faraday::Connection]
117
+ # Sets the default {Faraday::Connection} for simple scripts that
118
+ # access the Faraday constant directly, such as
119
+ # <code>Faraday.get "https://faraday.com"</code>.
120
+ def default_connection
121
+ @default_connection ||= Connection.new(default_connection_options)
122
+ end
123
+
124
+ # Gets the default connection options used when calling {Faraday#new}.
125
+ #
126
+ # @return [Faraday::ConnectionOptions]
127
+ def default_connection_options
128
+ @default_connection_options ||= ConnectionOptions.new
129
+ end
130
+
131
+ # Sets the default options used when calling {Faraday#new}.
132
+ #
133
+ # @param options [Hash, Faraday::ConnectionOptions]
134
+ def default_connection_options=(options)
135
+ @default_connection = nil
136
+ @default_connection_options = ConnectionOptions.from(options)
137
+ end
138
+
110
139
  private
111
140
 
112
141
  # Internal: Proxies method calls on the Faraday constant to
@@ -124,43 +153,5 @@ module Faraday
124
153
  self.root_path = File.expand_path __dir__
125
154
  self.lib_path = File.expand_path 'faraday', __dir__
126
155
  self.default_adapter = :net_http
127
-
128
- # @overload default_connection
129
- # Gets the default connection used for simple scripts.
130
- # @return [Faraday::Connection] a connection configured with
131
- # the default_adapter.
132
- # @overload default_connection=(connection)
133
- # @param connection [Faraday::Connection]
134
- # Sets the default {Faraday::Connection} for simple scripts that
135
- # access the Faraday constant directly, such as
136
- # <code>Faraday.get "https://faraday.com"</code>.
137
- def self.default_connection
138
- @default_connection ||= Connection.new(default_connection_options)
139
- end
140
-
141
- # Gets the default connection options used when calling {Faraday#new}.
142
- #
143
- # @return [Faraday::ConnectionOptions]
144
- def self.default_connection_options
145
- @default_connection_options ||= ConnectionOptions.new
146
- end
147
-
148
- # Sets the default options used when calling {Faraday#new}.
149
- #
150
- # @param options [Hash, Faraday::ConnectionOptions]
151
- def self.default_connection_options=(options)
152
- @default_connection = nil
153
- @default_connection_options = ConnectionOptions.from(options)
154
- end
155
-
156
- unless const_defined? :Timer
157
- require 'timeout'
158
- Timer = Timeout
159
- end
160
-
161
- require_libs 'utils', 'options', 'connection', 'rack_builder', 'parameters',
162
- 'middleware', 'adapter', 'request', 'response', 'error',
163
- 'file_part', 'param_part'
164
-
165
- require_lib 'autoload' unless ENV['FARADAY_NO_AUTOLOAD']
156
+ self.default_adapter_options = {}
166
157
  end