net-http 0.9.1 → 0.10.0
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.
- checksums.yaml +4 -4
- data/README.md +2 -0
- data/lib/net/http/generic_request.rb +10 -1
- data/lib/net/http/header.rb +56 -15
- data/lib/net/http/request.rb +1 -0
- data/lib/net/http/requests.rb +59 -24
- data/lib/net/http/response.rb +40 -15
- data/lib/net/http.rb +73 -14
- data/sig/manifest.yaml +3 -0
- data/sig/net-http.rbs +5635 -0
- metadata +70 -48
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7ef5db5bbe7d235bad14b04a257948207798e176d4f1d03029801615aa26823c
|
|
4
|
+
data.tar.gz: 1677b07e53a693f5d784a39e4d76a447868b5d435f3269561ccc772dd0345d10
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fd9e8e4ec27ff431f0a36acde5d6caecdebf34c5a625a6023b02bade546e7133bb6b12b3a0594d6cb3c5824577e093ef8677a209b9b35a2ee727b5b1906bf77e
|
|
7
|
+
data.tar.gz: b04a6747ae31dedd05716b221f9c9a6e668587cd025094f91f4b7c487feb85d769d4b8ff0d22ee55a79b96755324e447094579bf2306fc3acb363bb547e38b3d
|
data/README.md
CHANGED
|
@@ -81,6 +81,8 @@ res = Net::HTTP.post_form(uri, 'q' => ['ruby', 'perl'], 'max' => '50')
|
|
|
81
81
|
puts res.body
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
+
See the [documentation](https://docs.ruby-lang.org/en/master/Net/HTTP.html) for more details.
|
|
85
|
+
|
|
84
86
|
## Development
|
|
85
87
|
|
|
86
88
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
@@ -336,6 +336,9 @@ class Net::HTTPGenericRequest
|
|
|
336
336
|
boundary = opt[:boundary]
|
|
337
337
|
require 'securerandom' unless defined?(SecureRandom)
|
|
338
338
|
boundary ||= SecureRandom.urlsafe_base64(40)
|
|
339
|
+
if /[\r\n]/.match?(boundary.to_s)
|
|
340
|
+
raise ArgumentError, "multipart boundary cannot include CR/LF"
|
|
341
|
+
end
|
|
339
342
|
chunked_p = chunked?
|
|
340
343
|
|
|
341
344
|
buf = +''
|
|
@@ -349,7 +352,10 @@ class Net::HTTPGenericRequest
|
|
|
349
352
|
buf << "--#{boundary}\r\n"
|
|
350
353
|
if filename
|
|
351
354
|
filename = quote_string(filename, charset)
|
|
352
|
-
type = h[:content_type] || 'application/octet-stream'
|
|
355
|
+
type = (h[:content_type] || 'application/octet-stream').to_s
|
|
356
|
+
if /[\r\n]/.match?(type)
|
|
357
|
+
raise ArgumentError, "field content type cannot include CR/LF"
|
|
358
|
+
end
|
|
353
359
|
buf << "Content-Disposition: form-data; " \
|
|
354
360
|
"name=\"#{key}\"; filename=\"#{filename}\"\r\n" \
|
|
355
361
|
"Content-Type: #{type}\r\n\r\n"
|
|
@@ -384,6 +390,9 @@ class Net::HTTPGenericRequest
|
|
|
384
390
|
|
|
385
391
|
def quote_string(str, charset)
|
|
386
392
|
str = str.encode(charset, fallback:->(c){'&#%d;'%c.encode("UTF-8").ord}) if charset
|
|
393
|
+
if /[\r\n]/.match?(str)
|
|
394
|
+
raise ArgumentError, "multipart field name or filename cannot include CR/LF"
|
|
395
|
+
end
|
|
387
396
|
str.gsub(/[\\"]/, '\\\\\&')
|
|
388
397
|
end
|
|
389
398
|
|
data/lib/net/http/header.rb
CHANGED
|
@@ -193,11 +193,9 @@ module Net::HTTPHeader
|
|
|
193
193
|
warn "net/http: nil HTTP header: #{key}", uplevel: 3 if $VERBOSE
|
|
194
194
|
else
|
|
195
195
|
value = value.strip # raise error for invalid byte sequences
|
|
196
|
-
|
|
197
|
-
raise ArgumentError, "too long (#{key.bytesize} bytes) header: #{key[0, 30].inspect}..."
|
|
198
|
-
end
|
|
196
|
+
validate_field_name(key)
|
|
199
197
|
if value.to_s.bytesize > MAX_FIELD_LENGTH
|
|
200
|
-
raise ArgumentError, "header #{key} has too long field value: #{value.bytesize}"
|
|
198
|
+
raise ArgumentError, "header #{key} has too long field value: #{value.bytesize} bytes (limit #{MAX_FIELD_LENGTH})"
|
|
201
199
|
end
|
|
202
200
|
if value.count("\r\n") > 0
|
|
203
201
|
raise ArgumentError, "header #{key} has field value #{value.inspect}, this cannot include CR/LF"
|
|
@@ -263,21 +261,34 @@ module Net::HTTPHeader
|
|
|
263
261
|
def add_field(key, val)
|
|
264
262
|
stringified_downcased_key = key.downcase.to_s
|
|
265
263
|
if @header.key?(stringified_downcased_key)
|
|
266
|
-
append_field_value(@header[stringified_downcased_key], val)
|
|
264
|
+
append_field_value(@header[stringified_downcased_key], val, key)
|
|
267
265
|
else
|
|
268
266
|
set_field(key, val)
|
|
269
267
|
end
|
|
270
268
|
end
|
|
271
269
|
|
|
272
270
|
# :stopdoc:
|
|
271
|
+
private def validate_field_name(key)
|
|
272
|
+
if key.to_s.bytesize > MAX_KEY_LENGTH
|
|
273
|
+
raise ArgumentError, "too long (#{key.to_s.bytesize} bytes) header: #{key.to_s[0, 30].inspect}..."
|
|
274
|
+
end
|
|
275
|
+
if /[\x00-\x1f\x7f:]/n.match?(key.to_s.b)
|
|
276
|
+
raise ArgumentError, "header field name cannot include control characters or colon: #{key.to_s[0, 30].inspect}"
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
273
280
|
private def set_field(key, val)
|
|
281
|
+
validate_field_name(key)
|
|
274
282
|
case val
|
|
275
283
|
when Enumerable
|
|
276
284
|
ary = []
|
|
277
|
-
append_field_value(ary, val)
|
|
285
|
+
append_field_value(ary, val, key)
|
|
278
286
|
@header[key.downcase.to_s] = ary
|
|
279
287
|
else
|
|
280
288
|
val = val.to_s # for compatibility use to_s instead of to_str
|
|
289
|
+
if val.bytesize > MAX_FIELD_LENGTH
|
|
290
|
+
raise ArgumentError, "header #{key} has too long field value: #{val.bytesize} bytes (limit #{MAX_FIELD_LENGTH})"
|
|
291
|
+
end
|
|
281
292
|
if val.b.count("\r\n") > 0
|
|
282
293
|
raise ArgumentError, 'header field value cannot include CR/LF'
|
|
283
294
|
end
|
|
@@ -285,12 +296,15 @@ module Net::HTTPHeader
|
|
|
285
296
|
end
|
|
286
297
|
end
|
|
287
298
|
|
|
288
|
-
private def append_field_value(ary, val)
|
|
299
|
+
private def append_field_value(ary, val, key)
|
|
289
300
|
case val
|
|
290
301
|
when Enumerable
|
|
291
|
-
val.each{|x| append_field_value(ary, x)}
|
|
302
|
+
val.each{|x| append_field_value(ary, x, key)}
|
|
292
303
|
else
|
|
293
304
|
val = val.to_s
|
|
305
|
+
if val.bytesize > MAX_FIELD_LENGTH
|
|
306
|
+
raise ArgumentError, "header #{key} has too long field value: #{val.bytesize} bytes (limit #{MAX_FIELD_LENGTH})"
|
|
307
|
+
end
|
|
294
308
|
if /[\r\n]/n.match?(val.b)
|
|
295
309
|
raise ArgumentError, 'header field value cannot include CR/LF'
|
|
296
310
|
end
|
|
@@ -617,11 +631,35 @@ module Net::HTTPHeader
|
|
|
617
631
|
# res = Net::HTTP.get_response(hostname, '/todos/1')
|
|
618
632
|
# res.content_length # => nil
|
|
619
633
|
#
|
|
634
|
+
# The value must consist of digits only.
|
|
635
|
+
# Multiple <tt>'Content-Length'</tt> values are accepted
|
|
636
|
+
# only when they are all identical;
|
|
637
|
+
# otherwise Net::HTTPHeaderSyntaxError is raised.
|
|
638
|
+
# See {RFC 9110 Section 8.6}[https://www.rfc-editor.org/rfc/rfc9110.html#section-8.6].
|
|
620
639
|
def content_length
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
640
|
+
values = @header['content-length']
|
|
641
|
+
return nil if values.nil?
|
|
642
|
+
|
|
643
|
+
lengths = []
|
|
644
|
+
values.each do |value|
|
|
645
|
+
value = value.strip
|
|
646
|
+
if value.empty?
|
|
647
|
+
raise Net::HTTPHeaderSyntaxError,
|
|
648
|
+
"empty Content-Length value"
|
|
649
|
+
end
|
|
650
|
+
lengths.concat(value.split(/\s*,\s*/, -1))
|
|
651
|
+
end
|
|
652
|
+
if lengths.uniq.size != 1
|
|
653
|
+
raise Net::HTTPHeaderSyntaxError,
|
|
654
|
+
"Content-Length has multiple different values: " +
|
|
655
|
+
values.join(", ")
|
|
656
|
+
end
|
|
657
|
+
length = lengths.first
|
|
658
|
+
unless /\A\d+\z/.match?(length)
|
|
659
|
+
raise Net::HTTPHeaderSyntaxError,
|
|
660
|
+
"wrong Content-Length format: #{length}"
|
|
661
|
+
end
|
|
662
|
+
length.to_i
|
|
625
663
|
end
|
|
626
664
|
|
|
627
665
|
# Sets the value of field <tt>'Content-Length'</tt> to the given numeric;
|
|
@@ -647,7 +685,7 @@ module Net::HTTPHeader
|
|
|
647
685
|
end
|
|
648
686
|
|
|
649
687
|
# Returns +true+ if field <tt>'Transfer-Encoding'</tt>
|
|
650
|
-
# exists and has
|
|
688
|
+
# exists and has <tt>'chunked'</tt> as its final transfer coding,
|
|
651
689
|
# +false+ otherwise;
|
|
652
690
|
# see {Transfer-Encoding response header}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#transfer-encoding-response-header]:
|
|
653
691
|
#
|
|
@@ -655,10 +693,13 @@ module Net::HTTPHeader
|
|
|
655
693
|
# res['Transfer-Encoding'] # => "chunked"
|
|
656
694
|
# res.chunked? # => true
|
|
657
695
|
#
|
|
696
|
+
# <tt>'gzip, chunked'</tt> is chunked but <tt>'chunked, gzip'</tt> is not,
|
|
697
|
+
# because only the final transfer coding frames the message.
|
|
698
|
+
# See {RFC 9112 Section 6.3}[https://www.rfc-editor.org/rfc/rfc9112.html#section-6.3].
|
|
658
699
|
def chunked?
|
|
659
700
|
return false unless @header['transfer-encoding']
|
|
660
701
|
field = self['Transfer-Encoding']
|
|
661
|
-
(/(?:\A|[^\-\w])chunked(?![\-\w])/i =~ field) ? true : false
|
|
702
|
+
(/(?:\A|[^\-\w])chunked(?![\-\w])\s*(?:,\s*)*\z/i =~ field) ? true : false
|
|
662
703
|
end
|
|
663
704
|
|
|
664
705
|
# Returns a Range object representing the value of field
|
|
@@ -774,7 +815,7 @@ module Net::HTTPHeader
|
|
|
774
815
|
#
|
|
775
816
|
# Net::HTTPHeader#content_type= is an alias for Net::HTTPHeader#set_content_type.
|
|
776
817
|
def set_content_type(type, params = {})
|
|
777
|
-
|
|
818
|
+
set_field('Content-Type', type + params.map{|k,v|"; #{k}=#{v}"}.join(''))
|
|
778
819
|
end
|
|
779
820
|
|
|
780
821
|
alias content_type= set_content_type
|
data/lib/net/http/request.rb
CHANGED
data/lib/net/http/requests.rb
CHANGED
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
#
|
|
20
20
|
# - Request body: optional.
|
|
21
21
|
# - Response body: yes.
|
|
22
|
-
# - {Safe}[https://en.wikipedia.org/wiki/
|
|
23
|
-
# - {Idempotent}[https://en.wikipedia.org/wiki/
|
|
24
|
-
# - {Cacheable}[https://en.wikipedia.org/wiki/
|
|
22
|
+
# - {Safe}[https://en.wikipedia.org/wiki/HTTP#Safe_method]: yes.
|
|
23
|
+
# - {Idempotent}[https://en.wikipedia.org/wiki/HTTP#Idempotent_method]: yes.
|
|
24
|
+
# - {Cacheable}[https://en.wikipedia.org/wiki/HTTP#Cacheable_method]: yes.
|
|
25
25
|
#
|
|
26
26
|
# Related:
|
|
27
27
|
#
|
|
@@ -52,9 +52,9 @@ end
|
|
|
52
52
|
#
|
|
53
53
|
# - Request body: optional.
|
|
54
54
|
# - Response body: no.
|
|
55
|
-
# - {Safe}[https://en.wikipedia.org/wiki/
|
|
56
|
-
# - {Idempotent}[https://en.wikipedia.org/wiki/
|
|
57
|
-
# - {Cacheable}[https://en.wikipedia.org/wiki/
|
|
55
|
+
# - {Safe}[https://en.wikipedia.org/wiki/HTTP#Safe_method]: yes.
|
|
56
|
+
# - {Idempotent}[https://en.wikipedia.org/wiki/HTTP#Idempotent_method]: yes.
|
|
57
|
+
# - {Cacheable}[https://en.wikipedia.org/wiki/HTTP#Cacheable_method]: yes.
|
|
58
58
|
#
|
|
59
59
|
# Related:
|
|
60
60
|
#
|
|
@@ -87,9 +87,9 @@ end
|
|
|
87
87
|
#
|
|
88
88
|
# - Request body: yes.
|
|
89
89
|
# - Response body: yes.
|
|
90
|
-
# - {Safe}[https://en.wikipedia.org/wiki/
|
|
91
|
-
# - {Idempotent}[https://en.wikipedia.org/wiki/
|
|
92
|
-
# - {Cacheable}[https://en.wikipedia.org/wiki/
|
|
90
|
+
# - {Safe}[https://en.wikipedia.org/wiki/HTTP#Safe_method]: no.
|
|
91
|
+
# - {Idempotent}[https://en.wikipedia.org/wiki/HTTP#Idempotent_method]: no.
|
|
92
|
+
# - {Cacheable}[https://en.wikipedia.org/wiki/HTTP#Cacheable_method]: yes.
|
|
93
93
|
#
|
|
94
94
|
# Related:
|
|
95
95
|
#
|
|
@@ -123,9 +123,9 @@ end
|
|
|
123
123
|
#
|
|
124
124
|
# - Request body: yes.
|
|
125
125
|
# - Response body: yes.
|
|
126
|
-
# - {Safe}[https://en.wikipedia.org/wiki/
|
|
127
|
-
# - {Idempotent}[https://en.wikipedia.org/wiki/
|
|
128
|
-
# - {Cacheable}[https://en.wikipedia.org/wiki/
|
|
126
|
+
# - {Safe}[https://en.wikipedia.org/wiki/HTTP#Safe_method]: no.
|
|
127
|
+
# - {Idempotent}[https://en.wikipedia.org/wiki/HTTP#Idempotent_method]: yes.
|
|
128
|
+
# - {Cacheable}[https://en.wikipedia.org/wiki/HTTP#Cacheable_method]: no.
|
|
129
129
|
#
|
|
130
130
|
# Related:
|
|
131
131
|
#
|
|
@@ -157,9 +157,9 @@ end
|
|
|
157
157
|
#
|
|
158
158
|
# - Request body: optional.
|
|
159
159
|
# - Response body: yes.
|
|
160
|
-
# - {Safe}[https://en.wikipedia.org/wiki/
|
|
161
|
-
# - {Idempotent}[https://en.wikipedia.org/wiki/
|
|
162
|
-
# - {Cacheable}[https://en.wikipedia.org/wiki/
|
|
160
|
+
# - {Safe}[https://en.wikipedia.org/wiki/HTTP#Safe_method]: no.
|
|
161
|
+
# - {Idempotent}[https://en.wikipedia.org/wiki/HTTP#Idempotent_method]: yes.
|
|
162
|
+
# - {Cacheable}[https://en.wikipedia.org/wiki/HTTP#Cacheable_method]: no.
|
|
163
163
|
#
|
|
164
164
|
# Related:
|
|
165
165
|
#
|
|
@@ -189,9 +189,9 @@ end
|
|
|
189
189
|
#
|
|
190
190
|
# - Request body: optional.
|
|
191
191
|
# - Response body: yes.
|
|
192
|
-
# - {Safe}[https://en.wikipedia.org/wiki/
|
|
193
|
-
# - {Idempotent}[https://en.wikipedia.org/wiki/
|
|
194
|
-
# - {Cacheable}[https://en.wikipedia.org/wiki/
|
|
192
|
+
# - {Safe}[https://en.wikipedia.org/wiki/HTTP#Safe_method]: yes.
|
|
193
|
+
# - {Idempotent}[https://en.wikipedia.org/wiki/HTTP#Idempotent_method]: yes.
|
|
194
|
+
# - {Cacheable}[https://en.wikipedia.org/wiki/HTTP#Cacheable_method]: no.
|
|
195
195
|
#
|
|
196
196
|
# Related:
|
|
197
197
|
#
|
|
@@ -221,9 +221,9 @@ end
|
|
|
221
221
|
#
|
|
222
222
|
# - Request body: no.
|
|
223
223
|
# - Response body: yes.
|
|
224
|
-
# - {Safe}[https://en.wikipedia.org/wiki/
|
|
225
|
-
# - {Idempotent}[https://en.wikipedia.org/wiki/
|
|
226
|
-
# - {Cacheable}[https://en.wikipedia.org/wiki/
|
|
224
|
+
# - {Safe}[https://en.wikipedia.org/wiki/HTTP#Safe_method]: yes.
|
|
225
|
+
# - {Idempotent}[https://en.wikipedia.org/wiki/HTTP#Idempotent_method]: yes.
|
|
226
|
+
# - {Cacheable}[https://en.wikipedia.org/wiki/HTTP#Cacheable_method]: no.
|
|
227
227
|
#
|
|
228
228
|
# Related:
|
|
229
229
|
#
|
|
@@ -256,9 +256,9 @@ end
|
|
|
256
256
|
#
|
|
257
257
|
# - Request body: yes.
|
|
258
258
|
# - Response body: yes.
|
|
259
|
-
# - {Safe}[https://en.wikipedia.org/wiki/
|
|
260
|
-
# - {Idempotent}[https://en.wikipedia.org/wiki/
|
|
261
|
-
# - {Cacheable}[https://en.wikipedia.org/wiki/
|
|
259
|
+
# - {Safe}[https://en.wikipedia.org/wiki/HTTP#Safe_method]: no.
|
|
260
|
+
# - {Idempotent}[https://en.wikipedia.org/wiki/HTTP#Idempotent_method]: no.
|
|
261
|
+
# - {Cacheable}[https://en.wikipedia.org/wiki/HTTP#Cacheable_method]: no.
|
|
262
262
|
#
|
|
263
263
|
# Related:
|
|
264
264
|
#
|
|
@@ -271,6 +271,41 @@ class Net::HTTP::Patch < Net::HTTPRequest
|
|
|
271
271
|
RESPONSE_HAS_BODY = true
|
|
272
272
|
end
|
|
273
273
|
|
|
274
|
+
# \Class for representing
|
|
275
|
+
# {HTTP method QUERY}[https://www.rfc-editor.org/rfc/rfc10008.html]:
|
|
276
|
+
#
|
|
277
|
+
# require 'net/http'
|
|
278
|
+
# uri = URI('http://example.com')
|
|
279
|
+
# hostname = uri.hostname # => "example.com"
|
|
280
|
+
# uri.path = '/posts'
|
|
281
|
+
# req = Net::HTTP::Query.new(uri) # => #<Net::HTTP::Query QUERY>
|
|
282
|
+
# req.body = '{"title": "foo","body": "bar","userId": 1}'
|
|
283
|
+
# req.content_type = 'application/json'
|
|
284
|
+
# res = Net::HTTP.start(hostname) do |http|
|
|
285
|
+
# http.request(req)
|
|
286
|
+
# end
|
|
287
|
+
#
|
|
288
|
+
# See {Request Headers}[rdoc-ref:Net::HTTPRequest@Request+Headers].
|
|
289
|
+
#
|
|
290
|
+
# Properties:
|
|
291
|
+
#
|
|
292
|
+
# - Request body: yes.
|
|
293
|
+
# - Response body: yes.
|
|
294
|
+
# - {Safe}[https://en.wikipedia.org/wiki/HTTP#Safe_method]: yes.
|
|
295
|
+
# - {Idempotent}[https://en.wikipedia.org/wiki/HTTP#Idempotent_method]: yes.
|
|
296
|
+
# - {Cacheable}[https://en.wikipedia.org/wiki/HTTP#Cacheable_method]: yes.
|
|
297
|
+
#
|
|
298
|
+
# Related:
|
|
299
|
+
#
|
|
300
|
+
# - Net::HTTP#query: sends +QUERY+ request, returns response object.
|
|
301
|
+
#
|
|
302
|
+
class Net::HTTP::Query < Net::HTTPRequest
|
|
303
|
+
# :stopdoc:
|
|
304
|
+
METHOD = 'QUERY'
|
|
305
|
+
REQUEST_HAS_BODY = true
|
|
306
|
+
RESPONSE_HAS_BODY = true
|
|
307
|
+
end
|
|
308
|
+
|
|
274
309
|
#
|
|
275
310
|
# WebDAV methods --- RFC2518
|
|
276
311
|
#
|
data/lib/net/http/response.rb
CHANGED
|
@@ -133,6 +133,13 @@
|
|
|
133
133
|
# there is a protocol error.
|
|
134
134
|
#
|
|
135
135
|
class Net::HTTPResponse
|
|
136
|
+
# The maximum total size in bytes of the response header.
|
|
137
|
+
MAX_RESPONSE_HEADER_LENGTH = 1024 * 1024 # 1 MiB
|
|
138
|
+
|
|
139
|
+
# The maximum number of informational (1xx) responses accepted before the
|
|
140
|
+
# final response.
|
|
141
|
+
MAX_INFORMATIONAL_RESPONSES = 100
|
|
142
|
+
|
|
136
143
|
class << self
|
|
137
144
|
# true if the response has a body.
|
|
138
145
|
def body_permitted?
|
|
@@ -152,11 +159,17 @@ class Net::HTTPResponse
|
|
|
152
159
|
res
|
|
153
160
|
end
|
|
154
161
|
|
|
162
|
+
def read_line(sock, limit, ignore_eof = false) #:nodoc: internal use only
|
|
163
|
+
sock.readuntil("\n", ignore_eof, limit: limit)
|
|
164
|
+
rescue Net::ReadLimitExceeded
|
|
165
|
+
raise Net::HTTPBadResponse, 'response line too long'
|
|
166
|
+
end
|
|
167
|
+
|
|
155
168
|
private
|
|
156
169
|
# :stopdoc:
|
|
157
170
|
|
|
158
171
|
def read_status_line(sock)
|
|
159
|
-
str = sock.
|
|
172
|
+
str = read_line(sock, MAX_RESPONSE_HEADER_LENGTH).chop
|
|
160
173
|
m = /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)(?:\s+(.*))?\z/in.match(str) or
|
|
161
174
|
raise Net::HTTPBadResponse, "wrong status line: #{str.dump}"
|
|
162
175
|
m.captures
|
|
@@ -170,12 +183,19 @@ class Net::HTTPResponse
|
|
|
170
183
|
|
|
171
184
|
def each_response_header(sock)
|
|
172
185
|
key = value = nil
|
|
186
|
+
remaining = MAX_RESPONSE_HEADER_LENGTH
|
|
173
187
|
while true
|
|
174
|
-
line = sock
|
|
188
|
+
line = read_line(sock, MAX_RESPONSE_HEADER_LENGTH, true)
|
|
189
|
+
remaining -= line.bytesize
|
|
190
|
+
raise Net::HTTPBadResponse, 'response header too large' if remaining < 0
|
|
191
|
+
line = line.chomp
|
|
175
192
|
break if line.empty?
|
|
176
193
|
if line[0] == ?\s or line[0] == ?\t and value
|
|
177
|
-
|
|
178
|
-
|
|
194
|
+
folded = line.strip
|
|
195
|
+
unless folded.empty?
|
|
196
|
+
value << ' ' unless value.empty?
|
|
197
|
+
value << folded
|
|
198
|
+
end
|
|
179
199
|
else
|
|
180
200
|
yield key, value if key
|
|
181
201
|
key, value = line.strip.split(/\s*:\s*/, 2)
|
|
@@ -599,15 +619,20 @@ class Net::HTTPResponse
|
|
|
599
619
|
|
|
600
620
|
@socket = inflate_body_io
|
|
601
621
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
622
|
+
# Transfer-Encoding overrides Content-Length, so a body that is not
|
|
623
|
+
# chunk-framed runs until the server closes the connection.
|
|
624
|
+
# See RFC 9112 Section 6.3.
|
|
625
|
+
unless @header['transfer-encoding']
|
|
626
|
+
clen = content_length()
|
|
627
|
+
if clen
|
|
628
|
+
@socket.read clen, dest, @ignore_eof
|
|
629
|
+
return
|
|
630
|
+
end
|
|
631
|
+
clen = range_length()
|
|
632
|
+
if clen
|
|
633
|
+
@socket.read clen, dest
|
|
634
|
+
return
|
|
635
|
+
end
|
|
611
636
|
end
|
|
612
637
|
@socket.read_all dest
|
|
613
638
|
end
|
|
@@ -623,7 +648,7 @@ class Net::HTTPResponse
|
|
|
623
648
|
def read_chunked(dest, chunk_data_io) # :nodoc:
|
|
624
649
|
total = 0
|
|
625
650
|
while true
|
|
626
|
-
line = @socket.
|
|
651
|
+
line = self.class.read_line(@socket, MAX_RESPONSE_HEADER_LENGTH).chop
|
|
627
652
|
hexlen = line.slice(/[0-9a-fA-F]+/) or
|
|
628
653
|
raise Net::HTTPBadResponse, "wrong chunk size line: #{line}"
|
|
629
654
|
len = hexlen.hex
|
|
@@ -635,7 +660,7 @@ class Net::HTTPResponse
|
|
|
635
660
|
@socket.read 2 # \r\n
|
|
636
661
|
end
|
|
637
662
|
end
|
|
638
|
-
until @socket.
|
|
663
|
+
until self.class.read_line(@socket, MAX_RESPONSE_HEADER_LENGTH).chop.empty?
|
|
639
664
|
# none
|
|
640
665
|
end
|
|
641
666
|
end
|
data/lib/net/http.rb
CHANGED
|
@@ -37,7 +37,7 @@ module Net #:nodoc:
|
|
|
37
37
|
# For information about \HTTP, see:
|
|
38
38
|
#
|
|
39
39
|
# - {Hypertext Transfer Protocol}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol].
|
|
40
|
-
# - {
|
|
40
|
+
# - {Technology}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Technology].
|
|
41
41
|
#
|
|
42
42
|
# == About the Examples
|
|
43
43
|
#
|
|
@@ -72,7 +72,7 @@ module Net #:nodoc:
|
|
|
72
72
|
#
|
|
73
73
|
# - If performance is important, consider using sessions, which lower request overhead.
|
|
74
74
|
# This {session}[rdoc-ref:Net::HTTP@Sessions] has multiple requests for
|
|
75
|
-
# {HTTP methods}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#
|
|
75
|
+
# {HTTP methods}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Method]
|
|
76
76
|
# and {WebDAV methods}[https://en.wikipedia.org/wiki/WebDAV#Implementation]:
|
|
77
77
|
#
|
|
78
78
|
# Net::HTTP.start(hostname) do |http|
|
|
@@ -82,6 +82,7 @@ module Net #:nodoc:
|
|
|
82
82
|
# body = 'Some text'
|
|
83
83
|
# http.post(path, body) # Can also have a block.
|
|
84
84
|
# http.put(path, body)
|
|
85
|
+
# http.query(path, body) # Can also have a block.
|
|
85
86
|
# http.delete(path)
|
|
86
87
|
# http.options(path)
|
|
87
88
|
# http.trace(path)
|
|
@@ -198,7 +199,7 @@ module Net #:nodoc:
|
|
|
198
199
|
# In the block, you can use these instance methods,
|
|
199
200
|
# each of which that sends a single request:
|
|
200
201
|
#
|
|
201
|
-
# - {HTTP methods}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#
|
|
202
|
+
# - {HTTP methods}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Method]:
|
|
202
203
|
#
|
|
203
204
|
# - #get, #request_get: GET.
|
|
204
205
|
# - #head, #request_head: HEAD.
|
|
@@ -207,6 +208,7 @@ module Net #:nodoc:
|
|
|
207
208
|
# - #options: OPTIONS.
|
|
208
209
|
# - #trace: TRACE.
|
|
209
210
|
# - #patch: PATCH.
|
|
211
|
+
# - #query, #request_query: QUERY.
|
|
210
212
|
#
|
|
211
213
|
# - {WebDAV methods}[https://en.wikipedia.org/wiki/WebDAV#Implementation]:
|
|
212
214
|
#
|
|
@@ -447,7 +449,7 @@ module Net #:nodoc:
|
|
|
447
449
|
# if the response has header <tt>'Content-Range'</tt>.
|
|
448
450
|
#
|
|
449
451
|
# Otherwise decompression (or not) depends on the value of header
|
|
450
|
-
# {Content-Encoding}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#
|
|
452
|
+
# {Content-Encoding}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Content-Encoding_2]:
|
|
451
453
|
#
|
|
452
454
|
# - <tt>'deflate'</tt>, <tt>'gzip'</tt>, or <tt>'x-gzip'</tt>:
|
|
453
455
|
# decompresses the body and deletes the header.
|
|
@@ -460,7 +462,7 @@ module Net #:nodoc:
|
|
|
460
462
|
#
|
|
461
463
|
# First, what's elsewhere. Class Net::HTTP:
|
|
462
464
|
#
|
|
463
|
-
# - Inherits from {class Object}[https://docs.ruby-lang.org/en/master/Object.html#class-
|
|
465
|
+
# - Inherits from {class Object}[https://docs.ruby-lang.org/en/master/Object.html#class-object-whats-here].
|
|
464
466
|
#
|
|
465
467
|
# This is a categorized summary of methods and attributes.
|
|
466
468
|
#
|
|
@@ -553,6 +555,8 @@ module Net #:nodoc:
|
|
|
553
555
|
# Sends a PROPPATCH request and returns a response object.
|
|
554
556
|
# - {#put}[rdoc-ref:Net::HTTP#put]:
|
|
555
557
|
# Sends a PUT request and returns a response object.
|
|
558
|
+
# - {#query}[rdoc-ref:Net::HTTP#query]:
|
|
559
|
+
# Sends a QUERY request and returns a response object.
|
|
556
560
|
# - {#request}[rdoc-ref:Net::HTTP#request]:
|
|
557
561
|
# Sends a request and returns a response object.
|
|
558
562
|
# - {#request_get}[rdoc-ref:Net::HTTP#request_get]:
|
|
@@ -724,7 +728,7 @@ module Net #:nodoc:
|
|
|
724
728
|
class HTTP < Protocol
|
|
725
729
|
|
|
726
730
|
# :stopdoc:
|
|
727
|
-
VERSION = "0.
|
|
731
|
+
VERSION = "0.10.0"
|
|
728
732
|
HTTPVersion = '1.1'
|
|
729
733
|
begin
|
|
730
734
|
require 'zlib'
|
|
@@ -1304,7 +1308,7 @@ module Net #:nodoc:
|
|
|
1304
1308
|
|
|
1305
1309
|
# Sets whether to determine the proxy from environment variable
|
|
1306
1310
|
# '<tt>ENV['http_proxy']</tt>';
|
|
1307
|
-
# see {Proxy Using ENV
|
|
1311
|
+
# see {Proxy Using ENV}[rdoc-ref:Net::HTTP@Proxy+Using+ENVHTTPProxy].
|
|
1308
1312
|
attr_writer :proxy_from_env
|
|
1309
1313
|
|
|
1310
1314
|
# Sets the proxy address;
|
|
@@ -1550,11 +1554,11 @@ module Net #:nodoc:
|
|
|
1550
1554
|
attr_accessor :cert_store
|
|
1551
1555
|
|
|
1552
1556
|
# Sets or returns the available SSL ciphers.
|
|
1553
|
-
# See {OpenSSL::SSL::SSLContext#ciphers=}[OpenSSL
|
|
1557
|
+
# See {OpenSSL::SSL::SSLContext#ciphers=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-ciphers-3D].
|
|
1554
1558
|
attr_accessor :ciphers
|
|
1555
1559
|
|
|
1556
1560
|
# Sets or returns the extra X509 certificates to be added to the certificate chain.
|
|
1557
|
-
# See {OpenSSL::SSL::SSLContext#add_certificate}[OpenSSL
|
|
1561
|
+
# See {OpenSSL::SSL::SSLContext#add_certificate}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-add_certificate].
|
|
1558
1562
|
attr_accessor :extra_chain_cert
|
|
1559
1563
|
|
|
1560
1564
|
# Sets or returns the OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
|
|
@@ -1564,15 +1568,15 @@ module Net #:nodoc:
|
|
|
1564
1568
|
attr_accessor :ssl_timeout
|
|
1565
1569
|
|
|
1566
1570
|
# Sets or returns the SSL version.
|
|
1567
|
-
# See {OpenSSL::SSL::SSLContext#ssl_version=}[OpenSSL
|
|
1571
|
+
# See {OpenSSL::SSL::SSLContext#ssl_version=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-ssl_version-3D].
|
|
1568
1572
|
attr_accessor :ssl_version
|
|
1569
1573
|
|
|
1570
1574
|
# Sets or returns the minimum SSL version.
|
|
1571
|
-
# See {OpenSSL::SSL::SSLContext#min_version=}[OpenSSL
|
|
1575
|
+
# See {OpenSSL::SSL::SSLContext#min_version=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-min_version-3D].
|
|
1572
1576
|
attr_accessor :min_version
|
|
1573
1577
|
|
|
1574
1578
|
# Sets or returns the maximum SSL version.
|
|
1575
|
-
# See {OpenSSL::SSL::SSLContext#max_version=}[OpenSSL
|
|
1579
|
+
# See {OpenSSL::SSL::SSLContext#max_version=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-max_version-3D].
|
|
1576
1580
|
attr_accessor :max_version
|
|
1577
1581
|
|
|
1578
1582
|
# Sets or returns the callback for the server certification verification.
|
|
@@ -1588,7 +1592,7 @@ module Net #:nodoc:
|
|
|
1588
1592
|
|
|
1589
1593
|
# Sets or returns whether to verify that the server certificate is valid
|
|
1590
1594
|
# for the hostname.
|
|
1591
|
-
# See {OpenSSL::SSL::SSLContext#verify_hostname=}[OpenSSL
|
|
1595
|
+
# See {OpenSSL::SSL::SSLContext#verify_hostname=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#attribute-i-verify_hostname].
|
|
1592
1596
|
attr_accessor :verify_hostname
|
|
1593
1597
|
|
|
1594
1598
|
# Returns the X509 certificate chain (an array of strings)
|
|
@@ -2101,6 +2105,25 @@ module Net #:nodoc:
|
|
|
2101
2105
|
send_entity(path, data, initheader, dest, Patch, &block)
|
|
2102
2106
|
end
|
|
2103
2107
|
|
|
2108
|
+
# Sends a QUERY request to the server;
|
|
2109
|
+
# returns an instance of a subclass of Net::HTTPResponse.
|
|
2110
|
+
#
|
|
2111
|
+
# The request is based on the Net::HTTP::Query object
|
|
2112
|
+
# created from string +path+, string +data+, and initial headers hash +initheader+.
|
|
2113
|
+
#
|
|
2114
|
+
# data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
|
|
2115
|
+
# http = Net::HTTP.new(hostname)
|
|
2116
|
+
# http.query('/todos/1', data) # => #<Net::HTTPOK 200 OK readbody=true>
|
|
2117
|
+
#
|
|
2118
|
+
# Related:
|
|
2119
|
+
#
|
|
2120
|
+
# - Net::HTTP::Query: request class for \HTTP method QUERY.
|
|
2121
|
+
# - Net::HTTP.query: sends QUERY request, returns response body.
|
|
2122
|
+
#
|
|
2123
|
+
def query(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+
|
|
2124
|
+
send_entity(path, data, initheader, dest, Query, &block)
|
|
2125
|
+
end
|
|
2126
|
+
|
|
2104
2127
|
# Sends a PUT request to the server;
|
|
2105
2128
|
# returns an instance of a subclass of Net::HTTPResponse.
|
|
2106
2129
|
#
|
|
@@ -2335,6 +2358,36 @@ module Net #:nodoc:
|
|
|
2335
2358
|
request Put.new(path, initheader), data, &block
|
|
2336
2359
|
end
|
|
2337
2360
|
|
|
2361
|
+
# Sends a QUERY request to the server;
|
|
2362
|
+
# returns an instance of a subclass of Net::HTTPResponse.
|
|
2363
|
+
#
|
|
2364
|
+
# The request is based on the Net::HTTP::Query object
|
|
2365
|
+
# created from string +path+, string +body+, and initial headers hash +initheader+.
|
|
2366
|
+
#
|
|
2367
|
+
# http = Net::HTTP.new(hostname)
|
|
2368
|
+
# http.query('/todos/1', 'xyzzy')
|
|
2369
|
+
# # => #<Net::HTTPOK 200 OK readbody=true>
|
|
2370
|
+
#
|
|
2371
|
+
# With no block given, returns the response object:
|
|
2372
|
+
#
|
|
2373
|
+
# http = Net::HTTP.new(hostname)
|
|
2374
|
+
# http.request_query('/todos') # => #<Net::HTTPOK 200 OK readbody=true>
|
|
2375
|
+
#
|
|
2376
|
+
# With a block given, calls the block with the response object
|
|
2377
|
+
# and returns the response object:
|
|
2378
|
+
#
|
|
2379
|
+
# http.request_query('/todos') do |res|
|
|
2380
|
+
# p res
|
|
2381
|
+
# end # => #<Net::HTTPOK 200 OK readbody=true>
|
|
2382
|
+
#
|
|
2383
|
+
# Output:
|
|
2384
|
+
#
|
|
2385
|
+
# #<Net::HTTPOK 200 OK readbody=false>
|
|
2386
|
+
#
|
|
2387
|
+
def request_query(path, data, initheader = nil, &block) # :yield: +response+
|
|
2388
|
+
request Query.new(path, initheader), data, &block
|
|
2389
|
+
end
|
|
2390
|
+
|
|
2338
2391
|
alias get2 request_get #:nodoc: obsolete
|
|
2339
2392
|
alias head2 request_head #:nodoc: obsolete
|
|
2340
2393
|
alias post2 request_post #:nodoc: obsolete
|
|
@@ -2430,7 +2483,7 @@ module Net #:nodoc:
|
|
|
2430
2483
|
|
|
2431
2484
|
# :stopdoc:
|
|
2432
2485
|
|
|
2433
|
-
IDEMPOTENT_METHODS_ = %w/GET HEAD PUT DELETE OPTIONS TRACE/.freeze # :nodoc:
|
|
2486
|
+
IDEMPOTENT_METHODS_ = %w/GET HEAD PUT DELETE OPTIONS TRACE QUERY/.freeze # :nodoc:
|
|
2434
2487
|
|
|
2435
2488
|
def transport_request(req)
|
|
2436
2489
|
count = 0
|
|
@@ -2444,11 +2497,17 @@ module Net #:nodoc:
|
|
|
2444
2497
|
# still read the received response.
|
|
2445
2498
|
end
|
|
2446
2499
|
|
|
2500
|
+
informational_count = 0
|
|
2447
2501
|
begin
|
|
2448
2502
|
res = HTTPResponse.read_new(@socket)
|
|
2449
2503
|
res.decode_content = req.decode_content
|
|
2450
2504
|
res.body_encoding = @response_body_encoding
|
|
2451
2505
|
res.ignore_eof = @ignore_eof
|
|
2506
|
+
if res.kind_of?(HTTPInformation)
|
|
2507
|
+
informational_count += 1
|
|
2508
|
+
raise HTTPBadResponse, 'too many informational responses' if
|
|
2509
|
+
informational_count > HTTPResponse::MAX_INFORMATIONAL_RESPONSES
|
|
2510
|
+
end
|
|
2452
2511
|
end while res.kind_of?(HTTPInformation)
|
|
2453
2512
|
|
|
2454
2513
|
res.uri = req.uri
|
data/sig/manifest.yaml
ADDED