1
1
# frozen_string_literal: false
2
- # The HTTPHeader module defines methods for reading and writing
3
- # HTTP headers.
4
2
#
5
- # It is used as a mixin by other classes, to provide hash-like
6
- # access to HTTP header values. Unlike raw hash access, HTTPHeader
7
- # provides access via case-insensitive keys. It also provides
8
- # methods for accessing commonly-used HTTP header values in more
9
- # convenient formats.
3
+ # The \HTTPHeader module provides access to \HTTP headers.
4
+ # The headers are a hash-like collection of key/value pairs called _fields_.
5
+ #
6
+ # The module is included in:
7
+ #
8
+ # - Net::HTTPGenericRequest (and therefore Net::HTTPRequest).
9
+ # - Net::HTTPResponse.
10
+ #
11
+ # == About the Examples
12
+ #
13
+ # :include: doc/net-http/examples.rdoc
14
+ #
15
+ # == Fields
16
+ #
17
+ # A header field is a key/value pair.
18
+ #
19
+ # === Field Keys
20
+ #
21
+ # A field key may be:
22
+ #
23
+ # - A string: Key <tt>'Accept'</tt> is treated as if it were
24
+ # <tt>'Accept'.downcase</tt>; i.e., <tt>'accept'</tt>.
25
+ # - A symbol: Key <tt>:Accept</tt> is treated as if it were
26
+ # <tt>:Accept.to_s.downcase</tt>; i.e., <tt>'accept'</tt>.
27
+ #
28
+ # Examples:
29
+ #
30
+ # req = Net::HTTP::Get.new(uri)
31
+ # req[:accept] # => "*/*"
32
+ # req['Accept'] # => "*/*"
33
+ # req['ACCEPT'] # => "*/*"
34
+ #
35
+ # req['accept'] = 'text/html'
36
+ # req[:accept] = 'text/html'
37
+ # req['ACCEPT'] = 'text/html'
38
+ #
39
+ # === Field Values
40
+ #
41
+ # A field value may be returned as an array of strings or as a string:
42
+ #
43
+ # - These methods return field values as arrays:
44
+ #
45
+ # - #get_fields: Returns the array value for the given key,
46
+ # or +nil+ if it does not exist.
47
+ # - #to_hash: Returns a hash of all header fields:
48
+ # each key is a field name; its value is the array value for the field.
49
+ #
50
+ # - These methods return field values as string;
51
+ # the string value for a field is equivalent to
52
+ # <tt>self[key.downcase.to_s].join(', '))</tt>:
53
+ #
54
+ # - #[]: Returns the string value for the given key,
55
+ # or +nil+ if it does not exist.
56
+ # - #fetch: Like #[], but accepts a default value
57
+ # to be returned if the key does not exist.
58
+ #
59
+ # The field value may be set:
60
+ #
61
+ # - #[]=: Sets the value for the given key;
62
+ # the given value may be a string, a symbol, an array, or a hash.
63
+ # - #add_field: Adds a given value to a value for the given key
64
+ # (not overwriting the existing value).
65
+ # - #delete: Deletes the field for the given key.
66
+ #
67
+ # Example field values:
68
+ #
69
+ # - \String:
70
+ #
71
+ # req['Accept'] = 'text/html' # => "text/html"
72
+ # req['Accept'] # => "text/html"
73
+ # req.get_fields('Accept') # => ["text/html"]
74
+ #
75
+ # - \Symbol:
76
+ #
77
+ # req['Accept'] = :text # => :text
78
+ # req['Accept'] # => "text"
79
+ # req.get_fields('Accept') # => ["text"]
80
+ #
81
+ # - Simple array:
82
+ #
83
+ # req[:foo] = %w[bar baz bat]
84
+ # req[:foo] # => "bar, baz, bat"
85
+ # req.get_fields(:foo) # => ["bar", "baz", "bat"]
86
+ #
87
+ # - Simple hash:
88
+ #
89
+ # req[:foo] = {bar: 0, baz: 1, bat: 2}
90
+ # req[:foo] # => "bar, 0, baz, 1, bat, 2"
91
+ # req.get_fields(:foo) # => ["bar", "0", "baz", "1", "bat", "2"]
92
+ #
93
+ # - Nested:
94
+ #
95
+ # req[:foo] = [%w[bar baz], {bat: 0, bam: 1}]
96
+ # req[:foo] # => "bar, baz, bat, 0, bam, 1"
97
+ # req.get_fields(:foo) # => ["bar", "baz", "bat", "0", "bam", "1"]
98
+ #
99
+ # req[:foo] = {bar: %w[baz bat], bam: {bah: 0, bad: 1}}
100
+ # req[:foo] # => "bar, baz, bat, bam, bah, 0, bad, 1"
101
+ # req.get_fields(:foo) # => ["bar", "baz", "bat", "bam", "bah", "0", "bad", "1"]
102
+ #
103
+ # == Convenience Methods
104
+ #
105
+ # Various convenience methods retrieve values, set values, query values,
106
+ # set form values, or iterate over fields.
107
+ #
108
+ # === Getters
109
+ #
110
+ # - #[]: Returns the string value for the given field.
111
+ # - #content_length: Returns the integer value of field <tt>'Content-Length'</tt>.
112
+ # - #content_range: Returns the Range value of field <tt>'Content-Range'</tt>.
113
+ # - #content_type: Returns the string value of field <tt>'Content-Type'</tt>.
114
+ # - #main_type: Returns first part of the string value of field <tt>'Content-Type'</tt>.
115
+ # - #sub_type: Returns second part of the string value of field <tt>'Content-Type'</tt>.
116
+ # - #range: Returns an array of Range objects of field <tt>'Range'</tt>, or +nil+.
117
+ # - #range_length: Returns the integer length of the range given in field <tt>'Content-Range'</tt>.
118
+ # - #type_params: Returns the string parameters for <tt>'Content-Type'</tt>.
119
+ #
120
+ # === Setters
121
+ #
122
+ # - #[]=: Sets the string or array value for the given field.
123
+ # - #basic_auth: Sets the string authorization header for <tt>'Authorization'</tt>.
124
+ # - #content_length=: Sets the integer length for field <tt>'Content-Length</tt>.
125
+ # - #content_type=: Sets the string value for field <tt>'Content-Type'</tt>.
126
+ # - #proxy_basic_auth: Sets the string authorization header for <tt>'Proxy-Authorization'</tt>.
127
+ # - #range=: Sets the value for field +'Range'+.
128
+ #
129
+ # === Queries
130
+ #
131
+ # - #chunked?: Returns whether field <tt>'Transfer-Encoding'</tt> is set to <tt>'chunked'</tt>.
132
+ # - #connection_close?: Returns whether field <tt>'Connection'</tt> is set to <tt>'close'</tt>.
133
+ # - #connection_keep_alive?: Returns whether field <tt>'Connection'</tt> is set to <tt>'keep-alive'</tt>.
134
+ # - #key?: Returns whether a given field exists.
135
+ #
136
+ # === Form Setters
137
+ #
138
+ # - #set_form: Sets an HTML form data set.
139
+ # - #set_form_data: Sets header fields and a body from HTML form data.
140
+ #
141
+ # === Iterators
142
+ #
143
+ # - #each_capitalized: Passes each field capitalized-name/value pair to the block.
144
+ # - #each_capitalized_name: Passes each capitalized field name to the block.
145
+ # - #each_header: Passes each field name/value pair to the block.
146
+ # - #each_name: Passes each field name to the block.
147
+ # - #each_value: Passes each field value to the block.
10
148
#
11
149
module Net ::HTTPHeader
12
150
13
- def initialize_http_header ( initheader )
151
+ def initialize_http_header ( initheader ) #:nodoc:
14
152
@header = { }
15
153
return unless initheader
16
154
initheader . each do |key , value |
@@ -33,14 +171,30 @@ def size #:nodoc: obsolete
33
171
34
172
alias length size #:nodoc: obsolete
35
173
36
- # Returns the header field corresponding to the case-insensitive key.
37
- # For example, a key of "Content-Type" might return "text/html"
174
+ # Returns the string field value for the case-insensitive field +key+,
175
+ # or +nil+ if there is no such key;
176
+ # see {Fields}[rdoc-ref:Net::HTTPHeader@Fields]:
177
+ #
178
+ # req = Net::HTTP::Get.new(uri)
179
+ # req['Accept'] # => "*/*"
180
+ # req['Foo'] = %w[bar baz bat]
181
+ # req['Foo'] # => "bar, baz, bat"
182
+ # res['Nosuch'] # => nil
183
+ #
38
184
def []( key )
39
185
a = @header [ key . downcase . to_s ] or return nil
40
186
a . join ( ', ' )
41
187
end
42
188
43
- # Sets the header field corresponding to the case-insensitive key.
189
+ # Sets the value for the case-insensitive +key+ to +val+,
190
+ # overwriting the previous value if the field exists;
191
+ # see {Fields}[rdoc-ref:Net::HTTPHeader@Fields]:
192
+ #
193
+ # req = Net::HTTP::Get.new(uri)
194
+ # req['Accept'] # => "*/*"
195
+ # req['Accept'] = 'text/html'
196
+ # req['Accept'] # => "text/html"
197
+ #
44
198
def []=( key , val )
45
199
unless val
46
200
@header . delete key . downcase . to_s
@@ -49,20 +203,18 @@ def []=(key, val)
49
203
set_field ( key , val )
50
204
end
51
205
52
- # [Ruby 1.8.3]
53
- # Adds a value to a named header field, instead of replacing its value.
54
- # Second argument +val+ must be a String.
55
- # See also #[]=, #[] and #get_fields.
206
+ # Adds value +val+ to the value array for field +key+ if the field exists;
207
+ # creates the field with the given +key+ and +val+ if it does not exist.
208
+ # see {Fields}[rdoc-ref:Net::HTTPHeader@Fields]:
56
209
#
57
- # request.add_field 'X-My-Header', 'a'
58
- # p request['X-My-Header'] #=> "a"
59
- # p request.get_fields('X-My-Header') #=> ["a"]
60
- # request.add_field 'X-My-Header', 'b'
61
- # p request['X-My-Header'] #=> "a, b"
62
- # p request.get_fields('X-My-Header') #=> ["a", "b"]
63
- # request.add_field 'X-My-Header', 'c'
64
- # p request['X-My-Header'] #=> "a, b, c"
65
- # p request.get_fields('X-My-Header') #=> ["a", "b", "c"]
210
+ # req = Net::HTTP::Get.new(uri)
211
+ # req.add_field('Foo', 'bar')
212
+ # req['Foo'] # => "bar"
213
+ # req.add_field('Foo', 'baz')
214
+ # req['Foo'] # => "bar, baz"
215
+ # req.add_field('Foo', %w[baz bam])
216
+ # req['Foo'] # => "bar, baz, baz, bam"
217
+ # req.get_fields('Foo') # => ["bar", "baz", "baz", "bam"]
66
218
#
67
219
def add_field ( key , val )
68
220
stringified_downcased_key = key . downcase . to_s
@@ -101,41 +253,65 @@ def add_field(key, val)
101
253
end
102
254
end
103
255
104
- # [Ruby 1.8.3]
105
- # Returns an array of header field strings corresponding to the
106
- # case-insensitive +key+. This method allows you to get duplicated
107
- # header fields without any processing. See also #[].
256
+ # Returns the array field value for the given +key+,
257
+ # or +nil+ if there is no such field;
258
+ # see {Fields}[rdoc-ref:Net::HTTPHeader@Fields]:
108
259
#
109
- # p response.get_fields('Set-Cookie')
110
- # #=> ["session=al98axx; expires=Fri, 31-Dec-1999 23:58:23",
111
- # "query=rubyscript; expires=Fri, 31-Dec-1999 23:58:23"]
112
- # p response['Set-Cookie']
113
- # #=> "session=al98axx; expires=Fri, 31-Dec-1999 23:58:23, query=rubyscript; expires=Fri, 31-Dec-1999 23:58:23"
260
+ # req = Net::HTTP::Get.new(uri)
261
+ # req['Foo'] = 'bar'
262
+ # req.get_fields('Foo') # => ["bar"]
263
+ # req.add_field('Foo', 'baz')
264
+ # req.get_fields('Foo') # => ["bar", "baz"]
265
+ # req.get_fields('Nosuch') # => nil
114
266
#
115
267
def get_fields ( key )
116
268
stringified_downcased_key = key . downcase . to_s
117
269
return nil unless @header [ stringified_downcased_key ]
118
270
@header [ stringified_downcased_key ] . dup
119
271
end
120
272
121
- # Returns the header field corresponding to the case-insensitive key.
122
- # Returns the default value +args+, or the result of the block, or
123
- # raises an IndexError if there's no header field named +key+
124
- # See Hash#fetch
273
+ # :call-seq
274
+ # fetch(key, default_val = nil) {|key| ... } -> object
275
+ # fetch(key, default_val = nil) -> value or default_val
276
+ #
277
+ # With a block, returns the string value for +key+ if it exists;
278
+ # otherwise returns the value of the block;
279
+ # ignores the +default_val+;
280
+ # see {Fields}[rdoc-ref:Net::HTTPHeader@Fields]:
281
+ #
282
+ # req = Net::HTTP::Get.new(uri)
283
+ # req['Foo'] = 'bar'
284
+ # req.fetch('Foo') {|key| key.capitalize } # => "bar"
285
+ # req.fetch('Nosuch') {|key| key.capitalize } # => "Nosuch"
286
+ #
287
+ # With no block, returns the string value for +key+ if it exists;
288
+ # otherwise, returns +default_val+ if it was given;
289
+ # otherwise raises an exception:
290
+ #
291
+ # req.fetch('Foo') # => "bar"
292
+ # req.fetch('Nosuch', :baz) # => :baz
293
+ # req.fetch('Nosuch') # Raises KeyError.
294
+ #
125
295
def fetch ( key , *args , &block ) #:yield: +key+
126
296
a = @header . fetch ( key . downcase . to_s , *args , &block )
127
297
a . kind_of? ( Array ) ? a . join ( ', ' ) : a
128
298
end
129
299
130
- # Iterates through the header names and values, passing in the name
131
- # and value to the code block supplied.
300
+ # Calls the block with each key/value pair:
132
301
#
133
- # Returns an enumerator if no block is given.
302
+ # req = Net::HTTP::Get.new(uri)
303
+ # req.each_header {|key, value| p [key, value] }
134
304
#
135
- # Example :
305
+ # Output :
136
306
#
137
- # response.header.each_header {|key,value| puts "#{key} = #{value}" }
307
+ # ["accept-encoding", "gzip;q=1.0,deflate;q=0.6,identity;q=0.3"]
308
+ # ["accept", "*/*"]
309
+ # ["user-agent", "Ruby"]
310
+ # ["host", "jsonplaceholder.typicode.com"]
311
+ #
312
+ # Returns an enumerator if no block is given.
138
313
#
314
+ # Net::HTTPHeader#each is an alias for Net::HTTPHeader#each_header.
139
315
def each_header #:yield: +key+, +value+
140
316
block_given? or return enum_for ( __method__ ) { @header . size }
141
317
@header . each do |k , va |
@@ -145,23 +321,42 @@ def each_header #:yield: +key+, +value+
145
321
146
322
alias each each_header
147
323
148
- # Iterates through the header names in the header, passing
149
- # each header name to the code block.
324
+ # Calls the block with each field key:
325
+ #
326
+ # req = Net::HTTP::Get.new(uri)
327
+ # req.each_key {|key| p key }
328
+ #
329
+ # Output:
330
+ #
331
+ # "accept-encoding"
332
+ # "accept"
333
+ # "user-agent"
334
+ # "host"
150
335
#
151
336
# Returns an enumerator if no block is given.
337
+ #
338
+ # Net::HTTPHeader#each_name is an alias for Net::HTTPHeader#each_key.
152
339
def each_name ( &block ) #:yield: +key+
153
340
block_given? or return enum_for ( __method__ ) { @header . size }
154
341
@header . each_key ( &block )
155
342
end
156
343
157
344
alias each_key each_name
158
345
159
- # Iterates through the header names in the header, passing
160
- # capitalized header names to the code block.
346
+ # Calls the block with each capitalized field name:
161
347
#
162
- # Note that header names are capitalized systematically;
163
- # capitalization may not match that used by the remote HTTP
164
- # server in its response.
348
+ # req = Net::HTTP::Get.new(uri)
349
+ # req.each_capitalized_name {|key| p key }
350
+ #
351
+ # Output:
352
+ #
353
+ # "Accept-Encoding"
354
+ # "Accept"
355
+ # "User-Agent"
356
+ # "Host"
357
+ #
358
+ # The capitalization is system-dependent;
359
+ # see {Case Mapping}[https://docs.ruby-lang.org/en/master/case_mapping_rdoc.html].
165
360
#
166
361
# Returns an enumerator if no block is given.
167
362
def each_capitalized_name #:yield: +key+
@@ -208,6 +403,8 @@ def to_hash
208
403
# server in its response.
209
404
#
210
405
# Returns an enumerator if no block is given.
406
+ #
407
+ # Net::HTTPHeader#canonical_each is an alias for Net::HTTPHeader#each_capitalized.
211
408
def each_capitalized
212
409
block_given? or return enum_for ( __method__ ) { @header . size }
213
410
@header . each do |k , v |
@@ -394,7 +591,9 @@ def type_params
394
591
# Sets the content type in an HTTP header.
395
592
# The +type+ should be a full HTTP content type, e.g. "text/html".
396
593
# The +params+ are an optional Hash of parameters to add after the
397
- # content type, e.g. {'charset' => 'iso-8859-1'}
594
+ # content type, e.g. {'charset' => 'iso-8859-1'}.
595
+ #
596
+ # Net::HTTPHeader#content_type= is an alias for Net::HTTPHeader#set_content_type.
398
597
def set_content_type ( type , params = { } )
399
598
@header [ 'content-type' ] = [ type + params . map { |k , v |"; #{ k } =#{ v } " } . join ( '' ) ]
400
599
end
@@ -414,6 +613,7 @@ def set_content_type(type, params = {})
414
613
# http.form_data = {"q" => ["ruby", "perl"], "lang" => "en"}
415
614
# http.set_form_data({"q" => "ruby", "lang" => "en"}, ';')
416
615
#
616
+ # Net::HTTPHeader#form_data= is an alias for Net::HTTPHeader#set_form_data.
417
617
def set_form_data ( params , sep = '&' )
418
618
query = URI . encode_www_form ( params )
419
619
query . gsub! ( /&/ , sep ) if sep != '&'
0 commit comments