http 5.2.0 → 6.0.2

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 (128) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +110 -13
  4. data/http.gemspec +38 -35
  5. data/lib/http/base64.rb +22 -0
  6. data/lib/http/chainable/helpers.rb +62 -0
  7. data/lib/http/chainable/verbs.rb +136 -0
  8. data/lib/http/chainable.rb +249 -129
  9. data/lib/http/client.rb +158 -127
  10. data/lib/http/connection/internals.rb +141 -0
  11. data/lib/http/connection.rb +128 -97
  12. data/lib/http/content_type.rb +61 -6
  13. data/lib/http/errors.rb +41 -1
  14. data/lib/http/feature.rb +67 -6
  15. data/lib/http/features/auto_deflate.rb +124 -17
  16. data/lib/http/features/auto_inflate.rb +38 -15
  17. data/lib/http/features/caching/entry.rb +178 -0
  18. data/lib/http/features/caching/in_memory_store.rb +63 -0
  19. data/lib/http/features/caching.rb +216 -0
  20. data/lib/http/features/digest_auth.rb +234 -0
  21. data/lib/http/features/instrumentation.rb +97 -17
  22. data/lib/http/features/logging.rb +183 -5
  23. data/lib/http/features/normalize_uri.rb +17 -0
  24. data/lib/http/features/raise_error.rb +37 -0
  25. data/lib/http/form_data/composite_io.rb +106 -0
  26. data/lib/http/form_data/file.rb +95 -0
  27. data/lib/http/form_data/multipart/param.rb +62 -0
  28. data/lib/http/form_data/multipart.rb +106 -0
  29. data/lib/http/form_data/part.rb +52 -0
  30. data/lib/http/form_data/readable.rb +58 -0
  31. data/lib/http/form_data/urlencoded.rb +175 -0
  32. data/lib/http/form_data/version.rb +8 -0
  33. data/lib/http/form_data.rb +102 -0
  34. data/lib/http/headers/known.rb +3 -0
  35. data/lib/http/headers/normalizer.rb +50 -0
  36. data/lib/http/headers.rb +185 -92
  37. data/lib/http/mime_type/adapter.rb +24 -9
  38. data/lib/http/mime_type/json.rb +19 -4
  39. data/lib/http/mime_type.rb +21 -3
  40. data/lib/http/options/definitions.rb +189 -0
  41. data/lib/http/options.rb +172 -125
  42. data/lib/http/redirector.rb +80 -75
  43. data/lib/http/request/body.rb +87 -6
  44. data/lib/http/request/builder.rb +184 -0
  45. data/lib/http/request/proxy.rb +83 -0
  46. data/lib/http/request/writer.rb +78 -17
  47. data/lib/http/request.rb +216 -99
  48. data/lib/http/response/body.rb +103 -18
  49. data/lib/http/response/inflater.rb +35 -7
  50. data/lib/http/response/parser.rb +98 -4
  51. data/lib/http/response/status/reasons.rb +2 -4
  52. data/lib/http/response/status.rb +141 -31
  53. data/lib/http/response.rb +219 -61
  54. data/lib/http/retriable/delay_calculator.rb +91 -0
  55. data/lib/http/retriable/errors.rb +35 -0
  56. data/lib/http/retriable/performer.rb +197 -0
  57. data/lib/http/session.rb +280 -0
  58. data/lib/http/timeout/global.rb +147 -34
  59. data/lib/http/timeout/null.rb +155 -9
  60. data/lib/http/timeout/per_operation.rb +139 -18
  61. data/lib/http/uri/normalizer.rb +82 -0
  62. data/lib/http/uri/parsing.rb +182 -0
  63. data/lib/http/uri.rb +289 -124
  64. data/lib/http/version.rb +2 -1
  65. data/lib/http.rb +11 -1
  66. data/sig/http.rbs +1619 -0
  67. metadata +42 -175
  68. data/.github/workflows/ci.yml +0 -67
  69. data/.gitignore +0 -15
  70. data/.rspec +0 -1
  71. data/.rubocop/layout.yml +0 -8
  72. data/.rubocop/metrics.yml +0 -4
  73. data/.rubocop/style.yml +0 -32
  74. data/.rubocop.yml +0 -11
  75. data/.rubocop_todo.yml +0 -206
  76. data/.yardopts +0 -2
  77. data/CHANGELOG.md +0 -41
  78. data/CHANGES_OLD.md +0 -1002
  79. data/CONTRIBUTING.md +0 -26
  80. data/Gemfile +0 -50
  81. data/Guardfile +0 -18
  82. data/Rakefile +0 -64
  83. data/SECURITY.md +0 -17
  84. data/lib/http/headers/mixin.rb +0 -34
  85. data/logo.png +0 -0
  86. data/spec/lib/http/client_spec.rb +0 -556
  87. data/spec/lib/http/connection_spec.rb +0 -88
  88. data/spec/lib/http/content_type_spec.rb +0 -47
  89. data/spec/lib/http/features/auto_deflate_spec.rb +0 -77
  90. data/spec/lib/http/features/auto_inflate_spec.rb +0 -86
  91. data/spec/lib/http/features/instrumentation_spec.rb +0 -81
  92. data/spec/lib/http/features/logging_spec.rb +0 -65
  93. data/spec/lib/http/headers/mixin_spec.rb +0 -36
  94. data/spec/lib/http/headers_spec.rb +0 -527
  95. data/spec/lib/http/options/body_spec.rb +0 -15
  96. data/spec/lib/http/options/features_spec.rb +0 -33
  97. data/spec/lib/http/options/form_spec.rb +0 -15
  98. data/spec/lib/http/options/headers_spec.rb +0 -24
  99. data/spec/lib/http/options/json_spec.rb +0 -15
  100. data/spec/lib/http/options/merge_spec.rb +0 -68
  101. data/spec/lib/http/options/new_spec.rb +0 -30
  102. data/spec/lib/http/options/proxy_spec.rb +0 -20
  103. data/spec/lib/http/options_spec.rb +0 -13
  104. data/spec/lib/http/redirector_spec.rb +0 -529
  105. data/spec/lib/http/request/body_spec.rb +0 -211
  106. data/spec/lib/http/request/writer_spec.rb +0 -121
  107. data/spec/lib/http/request_spec.rb +0 -234
  108. data/spec/lib/http/response/body_spec.rb +0 -85
  109. data/spec/lib/http/response/parser_spec.rb +0 -74
  110. data/spec/lib/http/response/status_spec.rb +0 -253
  111. data/spec/lib/http/response_spec.rb +0 -262
  112. data/spec/lib/http/uri/normalizer_spec.rb +0 -95
  113. data/spec/lib/http/uri_spec.rb +0 -71
  114. data/spec/lib/http_spec.rb +0 -506
  115. data/spec/regression_specs.rb +0 -24
  116. data/spec/spec_helper.rb +0 -88
  117. data/spec/support/black_hole.rb +0 -13
  118. data/spec/support/capture_warning.rb +0 -10
  119. data/spec/support/dummy_server/servlet.rb +0 -190
  120. data/spec/support/dummy_server.rb +0 -43
  121. data/spec/support/fakeio.rb +0 -21
  122. data/spec/support/fuubar.rb +0 -21
  123. data/spec/support/http_handling_shared.rb +0 -190
  124. data/spec/support/proxy_server.rb +0 -39
  125. data/spec/support/servers/config.rb +0 -11
  126. data/spec/support/servers/runner.rb +0 -19
  127. data/spec/support/simplecov.rb +0 -19
  128. data/spec/support/ssl_helper.rb +0 -104
data/lib/http/headers.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  require "forwardable"
4
4
 
5
5
  require "http/errors"
6
- require "http/headers/mixin"
6
+ require "http/headers/normalizer"
7
7
  require "http/headers/known"
8
8
 
9
9
  module HTTP
@@ -12,14 +12,57 @@ module HTTP
12
12
  extend Forwardable
13
13
  include Enumerable
14
14
 
15
- # Matches HTTP header names when in "Canonical-Http-Format"
16
- CANONICAL_NAME_RE = /\A[A-Z][a-z]*(?:-[A-Z][a-z]*)*\z/.freeze
15
+ class << self
16
+ # Coerces given object into Headers
17
+ #
18
+ # @example
19
+ # headers = HTTP::Headers.coerce("Content-Type" => "text/plain")
20
+ #
21
+ # @raise [Error] if object can't be coerced
22
+ # @param [#to_hash, #to_h, #to_a] object
23
+ # @return [Headers]
24
+ # @api public
25
+ def coerce(object)
26
+ object = if object.respond_to?(:to_hash) then object.to_hash
27
+ elsif object.respond_to?(:to_h) then object.to_h
28
+ elsif object.respond_to?(:to_a) then object.to_a
29
+ else raise Error, "Can't coerce #{object.inspect} to Headers"
30
+ end
17
31
 
18
- # Matches valid header field name according to RFC.
19
- # @see http://tools.ietf.org/html/rfc7230#section-3.2
20
- COMPLIANT_NAME_RE = /\A[A-Za-z0-9!#$%&'*+\-.^_`|~]+\z/.freeze
32
+ headers = new
33
+ object.each { |k, v| headers.add k, v }
34
+ headers
35
+ end
36
+ # @!method [](object)
37
+ # Coerces given object into Headers
38
+ #
39
+ # @example
40
+ # headers = HTTP::Headers["Content-Type" => "text/plain"]
41
+ #
42
+ # @see .coerce
43
+ # @return [Headers]
44
+ # @api public
45
+ alias [] coerce
46
+
47
+ # Returns the shared normalizer instance
48
+ #
49
+ # @example
50
+ # HTTP::Headers.normalizer
51
+ #
52
+ # @return [Headers::Normalizer]
53
+ # @api public
54
+ def normalizer
55
+ @normalizer ||= Normalizer.new #: Headers::Normalizer
56
+ end
57
+ end
21
58
 
22
- # Class constructor.
59
+ # Creates a new empty headers container
60
+ #
61
+ # @example
62
+ # headers = HTTP::Headers.new
63
+ #
64
+ # @return [Headers]
65
+ # @api public
23
66
  def initialize
24
67
  # The @pile stores each header value using a three element array:
25
68
  # 0 - the normalized header key, used for lookup
@@ -28,26 +71,46 @@ module HTTP
28
71
  @pile = []
29
72
  end
30
73
 
31
- # Sets header.
74
+ # Sets header, replacing any existing values
75
+ #
76
+ # @example
77
+ # headers.set("Content-Type", "text/plain")
32
78
  #
33
79
  # @param (see #add)
34
80
  # @return [void]
81
+ # @api public
35
82
  def set(name, value)
36
83
  delete(name)
37
84
  add(name, value)
38
85
  end
86
+ # @!method []=(name, value)
87
+ # Sets header, replacing any existing values
88
+ #
89
+ # @example
90
+ # headers["Content-Type"] = "text/plain"
91
+ #
92
+ # @see #set
93
+ # @return [void]
94
+ # @api public
39
95
  alias []= set
40
96
 
41
- # Removes header.
97
+ # Removes header with the given name
98
+ #
99
+ # @example
100
+ # headers.delete("Content-Type")
42
101
  #
43
102
  # @param [#to_s] name header name
44
103
  # @return [void]
104
+ # @api public
45
105
  def delete(name)
46
- name = normalize_header name.to_s
47
- @pile.delete_if { |k, _| k == name }
106
+ name = normalize_header name
107
+ @pile.delete_if { |k, _| k.eql?(name) }
48
108
  end
49
109
 
50
- # Appends header.
110
+ # Appends header value(s) to the given name
111
+ #
112
+ # @example
113
+ # headers.add("Accept", "text/html")
51
114
  #
52
115
  # @param [String, Symbol] name header name. When specified as a string, the
53
116
  # name is sent as-is. When specified as a symbol, the name is converted
@@ -57,16 +120,11 @@ module HTTP
57
120
  # is sent as `"auth_key"`.
58
121
  # @param [Array<#to_s>, #to_s] value header value(s) to be appended
59
122
  # @return [void]
123
+ # @api public
60
124
  def add(name, value)
61
- lookup_name = normalize_header(name.to_s)
62
- wire_name = case name
63
- when String
64
- name
65
- when Symbol
66
- lookup_name
67
- else
68
- raise HTTP::HeaderError, "HTTP header must be a String or Symbol: #{name.inspect}"
69
- end
125
+ lookup_name = normalize_header(name)
126
+ wire_name = wire_name_for(name, lookup_name)
127
+
70
128
  Array(value).each do |v|
71
129
  @pile << [
72
130
  lookup_name,
@@ -76,173 +134,208 @@ module HTTP
76
134
  end
77
135
  end
78
136
 
79
- # Returns list of header values if any.
137
+ # Returns list of header values if any
138
+ #
139
+ # @example
140
+ # headers.get("Content-Type")
80
141
  #
81
142
  # @return [Array<String>]
143
+ # @api public
82
144
  def get(name)
83
- name = normalize_header name.to_s
84
- @pile.select { |k, _| k == name }.map { |_, _, v| v }
145
+ name = normalize_header name
146
+ @pile.filter_map { |k, _, v| v if k.eql?(name) }
85
147
  end
86
148
 
87
- # Smart version of {#get}.
149
+ # Smart version of {#get}
150
+ #
151
+ # @example
152
+ # headers["Content-Type"]
88
153
  #
89
154
  # @return [nil] if header was not set
90
155
  # @return [String] if header has exactly one value
91
156
  # @return [Array<String>] if header has more than one value
157
+ # @api public
92
158
  def [](name)
93
159
  values = get(name)
160
+ return if values.empty?
94
161
 
95
- case values.count
96
- when 0 then nil
97
- when 1 then values.first
98
- else values
99
- end
162
+ return values unless values.one?
163
+
164
+ values.join
100
165
  end
101
166
 
102
- # Tells whenever header with given `name` is set or not.
167
+ # Tells whether header with given name is set
168
+ #
169
+ # @example
170
+ # headers.include?("Content-Type")
103
171
  #
104
172
  # @return [Boolean]
173
+ # @api public
105
174
  def include?(name)
106
- name = normalize_header name.to_s
107
- @pile.any? { |k, _| k == name }
175
+ name = normalize_header name
176
+ @pile.any? { |k, _| k.eql?(name) }
108
177
  end
109
178
 
110
179
  # Returns Rack-compatible headers Hash
111
180
  #
181
+ # @example
182
+ # headers.to_h
183
+ #
112
184
  # @return [Hash]
185
+ # @api public
113
186
  def to_h
114
187
  keys.to_h { |k| [k, self[k]] }
115
188
  end
189
+ # @!method to_hash
190
+ # @see #to_h
191
+ # @return [Hash]
116
192
  alias to_hash to_h
117
193
 
118
- # Returns headers key/value pairs.
194
+ # Pattern matching interface
119
195
  #
120
- # @return [Array<[String, String]>]
121
- def to_a
122
- @pile.map { |item| item[1..2] }
196
+ # @example
197
+ # headers.deconstruct_keys(%i[content_type])
198
+ #
199
+ # @param keys [Array<Symbol>, nil] keys to extract, or nil for all
200
+ # @return [Hash{Symbol => Object}]
201
+ # @api public
202
+ def deconstruct_keys(keys)
203
+ hash = @pile.map { |_, k, _| k }.to_h { |k| [k.tr("A-Z-", "a-z_").to_sym, self[k]] }
204
+ keys ? hash.slice(*keys) : hash
123
205
  end
124
206
 
125
- # Returns human-readable representation of `self` instance.
207
+ # Returns human-readable representation of self instance
208
+ #
209
+ # @example
210
+ # headers.inspect
126
211
  #
127
212
  # @return [String]
128
- def inspect
129
- "#<#{self.class} #{to_h.inspect}>"
130
- end
213
+ # @api public
214
+ def inspect = "#<#{self.class}>"
131
215
 
132
- # Returns list of header names.
216
+ # Returns list of header names
217
+ #
218
+ # @example
219
+ # headers.keys
133
220
  #
134
221
  # @return [Array<String>]
222
+ # @api public
135
223
  def keys
136
224
  @pile.map { |_, k, _| k }.uniq
137
225
  end
138
226
 
139
- # Compares headers to another Headers or Array of key/value pairs
227
+ # Compares headers to another Headers or Array of pairs
228
+ #
229
+ # @example
230
+ # headers == other_headers
140
231
  #
141
232
  # @return [Boolean]
233
+ # @api public
142
234
  def ==(other)
143
235
  return false unless other.respond_to? :to_a
144
236
 
145
- to_a == other.to_a
237
+ to_a.eql?(other.to_a)
146
238
  end
147
239
 
148
- # Calls the given block once for each key/value pair in headers container.
240
+ # Calls the given block once for each key/value pair
241
+ #
242
+ # @example
243
+ # headers.each { |name, value| puts "#{name}: #{value}" }
149
244
  #
150
245
  # @return [Enumerator] if no block given
151
246
  # @return [Headers] self-reference
247
+ # @api public
152
248
  def each
153
- return to_enum(__method__) unless block_given?
249
+ return to_enum unless block_given?
154
250
 
155
- @pile.each { |item| yield(item[1..2]) }
251
+ @pile.each { |item| yield(item.drop(1)) }
156
252
  self
157
253
  end
158
254
 
159
255
  # @!method empty?
160
- # Returns `true` if `self` has no key/value pairs
256
+ # Returns true if self has no key/value pairs
257
+ #
258
+ # @example
259
+ # headers.empty?
161
260
  #
162
261
  # @return [Boolean]
262
+ # @api public
163
263
  def_delegator :@pile, :empty?
164
264
 
165
265
  # @!method hash
166
- # Compute a hash-code for this headers container.
167
- # Two containers with the same content will have the same hash code.
266
+ # Computes a hash-code for this headers container
267
+ #
268
+ # @example
269
+ # headers.hash
168
270
  #
169
271
  # @see http://www.ruby-doc.org/core/Object.html#method-i-hash
170
272
  # @return [Fixnum]
273
+ # @api public
171
274
  def_delegator :@pile, :hash
172
275
 
173
- # Properly clones internal key/value storage.
276
+ # Properly clones internal key/value storage
174
277
  #
278
+ # @return [void]
175
279
  # @api private
176
- def initialize_copy(orig)
177
- super
280
+ def initialize_copy(_orig)
178
281
  @pile = @pile.map(&:dup)
179
282
  end
180
283
 
181
- # Merges `other` headers into `self`.
284
+ # Merges other headers into self
285
+ #
286
+ # @example
287
+ # headers.merge!("Accept" => "text/html")
182
288
  #
183
289
  # @see #merge
184
290
  # @return [void]
291
+ # @api public
185
292
  def merge!(other)
186
- self.class.coerce(other).to_h.each { |name, values| set name, values }
293
+ coerced = self.class.coerce(other)
294
+ names = coerced.keys
295
+ names.each { |name| set name, coerced.get(name) }
187
296
  end
188
297
 
189
- # Returns new instance with `other` headers merged in.
298
+ # Returns new instance with other headers merged in
299
+ #
300
+ # @example
301
+ # new_headers = headers.merge("Accept" => "text/html")
190
302
  #
191
303
  # @see #merge!
192
304
  # @return [Headers]
305
+ # @api public
193
306
  def merge(other)
194
307
  dup.tap { |dupped| dupped.merge! other }
195
308
  end
196
309
 
197
- class << self
198
- # Coerces given `object` into Headers.
199
- #
200
- # @raise [Error] if object can't be coerced
201
- # @param [#to_hash, #to_h, #to_a] object
202
- # @return [Headers]
203
- def coerce(object)
204
- unless object.is_a? self
205
- object = case
206
- when object.respond_to?(:to_hash) then object.to_hash
207
- when object.respond_to?(:to_h) then object.to_h
208
- when object.respond_to?(:to_a) then object.to_a
209
- else raise Error, "Can't coerce #{object.inspect} to Headers"
210
- end
211
- end
310
+ private
212
311
 
213
- headers = new
214
- object.each { |k, v| headers.add k, v }
215
- headers
312
+ # Returns the wire name for a header
313
+ #
314
+ # @return [String]
315
+ # @api private
316
+ def wire_name_for(name, lookup_name)
317
+ case name
318
+ when String then name
319
+ when Symbol then lookup_name
320
+ else raise HeaderError, "HTTP header must be a String or Symbol: #{name.inspect}"
216
321
  end
217
- alias [] coerce
218
322
  end
219
323
 
220
- private
221
-
222
- # Transforms `name` to canonical HTTP header capitalization
324
+ # Transforms name to canonical HTTP header capitalization
223
325
  #
224
- # @param [String] name
225
- # @raise [HeaderError] if normalized name does not
226
- # match {HEADER_NAME_RE}
227
- # @return [String] canonical HTTP header name
228
- def normalize_header(name)
229
- return name if name =~ CANONICAL_NAME_RE
230
-
231
- normalized = name.split(/[\-_]/).each(&:capitalize!).join("-")
232
-
233
- return normalized if normalized =~ COMPLIANT_NAME_RE
234
-
235
- raise HeaderError, "Invalid HTTP header field name: #{name.inspect}"
236
- end
326
+ # @return [String]
327
+ # @api private
328
+ def normalize_header(name) = self.class.normalizer.call(name)
237
329
 
238
330
  # Ensures there is no new line character in the header value
239
331
  #
240
332
  # @param [String] value
241
333
  # @raise [HeaderError] if value includes new line character
242
334
  # @return [String] stringified header value
335
+ # @api private
243
336
  def validate_value(value)
244
337
  v = value.to_s
245
- return v unless v.include?("\n")
338
+ return v unless v.include?("\n") || v.include?("\r")
246
339
 
247
340
  raise HeaderError, "Invalid HTTP header field value: #{v.inspect}"
248
341
  end
@@ -11,18 +11,33 @@ module HTTP
11
11
 
12
12
  class << self
13
13
  extend Forwardable
14
- def_delegators :instance, :encode, :decode
14
+
15
+ def_delegators :instance, :encode, :decode # steep:ignore
16
+ end
17
+
18
+ # Encodes data into the MIME type format
19
+ #
20
+ # @example
21
+ # adapter.encode("foo" => "bar")
22
+ #
23
+ # @return [String] encoded representation
24
+ # @raise [Error] if not implemented by subclass
25
+ # @api public
26
+ def encode(*)
27
+ raise Error, "#{self.class} does not supports #encode"
15
28
  end
16
29
 
17
- # rubocop:disable Style/DocumentDynamicEvalDefinition
18
- %w[encode decode].each do |operation|
19
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
20
- def #{operation}(*)
21
- fail Error, "\#{self.class} does not supports ##{operation}"
22
- end
23
- RUBY
30
+ # Decodes data from the MIME type format
31
+ #
32
+ # @example
33
+ # adapter.decode("{\"foo\":\"bar\"}")
34
+ #
35
+ # @return [Object] decoded data
36
+ # @raise [Error] if not implemented by subclass
37
+ # @api public
38
+ def decode(*)
39
+ raise Error, "#{self.class} does not supports #decode"
24
40
  end
25
- # rubocop:enable Style/DocumentDynamicEvalDefinition
26
41
  end
27
42
  end
28
43
  end
@@ -4,17 +4,32 @@ require "json"
4
4
  require "http/mime_type/adapter"
5
5
 
6
6
  module HTTP
7
+ # MIME type registry and adapter interface
7
8
  module MimeType
8
9
  # JSON encode/decode MIME type adapter
9
10
  class JSON < Adapter
10
11
  # Encodes object to JSON
12
+ #
13
+ # @example
14
+ # adapter = HTTP::MimeType::JSON.new
15
+ # adapter.encode(foo: "bar")
16
+ #
17
+ # @param [Object] obj object to encode
18
+ # @api public
19
+ # @return [String]
11
20
  def encode(obj)
12
- return obj.to_json if obj.respond_to?(:to_json)
13
-
14
- ::JSON.dump obj
21
+ obj.to_json
15
22
  end
16
23
 
17
- # Decodes JSON
24
+ # Decodes JSON string into Ruby object
25
+ #
26
+ # @example
27
+ # adapter = HTTP::MimeType::JSON.new
28
+ # adapter.decode('{"foo":"bar"}')
29
+ #
30
+ # @param [String] str JSON string to decode
31
+ # @api public
32
+ # @return [Object]
18
33
  def decode(str)
19
34
  ::JSON.parse str
20
35
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "http/errors"
4
+
3
5
  module HTTP
4
6
  # MIME type encode/decode adapters
5
7
  module MimeType
@@ -24,6 +26,7 @@ module HTTP
24
26
  #
25
27
  # @param [#to_s] type
26
28
  # @param [#encode, #decode] adapter
29
+ # @api public
27
30
  # @return [void]
28
31
  def register_adapter(type, adapter)
29
32
  adapters[type.to_s] = adapter
@@ -31,11 +34,15 @@ module HTTP
31
34
 
32
35
  # Returns adapter associated with MIME type
33
36
  #
37
+ # @example
38
+ # HTTP::MimeType["application/json"]
39
+ #
34
40
  # @param [#to_s] type
35
41
  # @raise [Error] if no adapter found
42
+ # @api public
36
43
  # @return [Class]
37
44
  def [](type)
38
- adapters[normalize type] || raise(Error, "Unknown MIME type: #{type}")
45
+ adapters[normalize type] || raise(UnsupportedMimeTypeError, "Unknown MIME type: #{type}")
39
46
  end
40
47
 
41
48
  # Register a shortcut for MIME type
@@ -46,6 +53,7 @@ module HTTP
46
53
  #
47
54
  # @param [#to_s] type
48
55
  # @param [#to_sym] shortcut
56
+ # @api public
49
57
  # @return [void]
50
58
  def register_alias(type, shortcut)
51
59
  aliases[shortcut.to_sym] = type.to_s
@@ -53,7 +61,11 @@ module HTTP
53
61
 
54
62
  # Resolves type by shortcut if possible
55
63
  #
64
+ # @example
65
+ # HTTP::MimeType.normalize(:json)
66
+ #
56
67
  # @param [#to_s] type
68
+ # @api public
57
69
  # @return [String]
58
70
  def normalize(type)
59
71
  aliases.fetch type, type.to_s
@@ -61,12 +73,18 @@ module HTTP
61
73
 
62
74
  private
63
75
 
64
- # :nodoc:
76
+ # Returns the adapters registry hash
77
+ #
78
+ # @api private
79
+ # @return [Hash]
65
80
  def adapters
66
81
  @adapters ||= {}
67
82
  end
68
83
 
69
- # :nodoc:
84
+ # Returns the aliases registry hash
85
+ #
86
+ # @api private
87
+ # @return [Hash]
70
88
  def aliases
71
89
  @aliases ||= {}
72
90
  end