net-http 0.1.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.
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: false
2
+ module Net::HTTP::ProxyDelta #:nodoc: internal use only
3
+ private
4
+
5
+ def conn_address
6
+ proxy_address()
7
+ end
8
+
9
+ def conn_port
10
+ proxy_port()
11
+ end
12
+
13
+ def edit_path(path)
14
+ use_ssl? ? path : "http://#{addr_port()}#{path}"
15
+ end
16
+ end
17
+
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: false
2
+ # HTTP request class.
3
+ # This class wraps together the request header and the request path.
4
+ # You cannot use this class directly. Instead, you should use one of its
5
+ # subclasses: Net::HTTP::Get, Net::HTTP::Post, Net::HTTP::Head.
6
+ #
7
+ class Net::HTTPRequest < Net::HTTPGenericRequest
8
+ # Creates an HTTP request object for +path+.
9
+ #
10
+ # +initheader+ are the default headers to use. Net::HTTP adds
11
+ # Accept-Encoding to enable compression of the response body unless
12
+ # Accept-Encoding or Range are supplied in +initheader+.
13
+
14
+ def initialize(path, initheader = nil)
15
+ super self.class::METHOD,
16
+ self.class::REQUEST_HAS_BODY,
17
+ self.class::RESPONSE_HAS_BODY,
18
+ path, initheader
19
+ end
20
+ end
21
+
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ # HTTP/1.1 methods --- RFC2616
4
+ #
5
+
6
+ # See Net::HTTPGenericRequest for attributes and methods.
7
+ # See Net::HTTP for usage examples.
8
+ class Net::HTTP::Get < Net::HTTPRequest
9
+ METHOD = 'GET'
10
+ REQUEST_HAS_BODY = false
11
+ RESPONSE_HAS_BODY = true
12
+ end
13
+
14
+ # See Net::HTTPGenericRequest for attributes and methods.
15
+ # See Net::HTTP for usage examples.
16
+ class Net::HTTP::Head < Net::HTTPRequest
17
+ METHOD = 'HEAD'
18
+ REQUEST_HAS_BODY = false
19
+ RESPONSE_HAS_BODY = false
20
+ end
21
+
22
+ # See Net::HTTPGenericRequest for attributes and methods.
23
+ # See Net::HTTP for usage examples.
24
+ class Net::HTTP::Post < Net::HTTPRequest
25
+ METHOD = 'POST'
26
+ REQUEST_HAS_BODY = true
27
+ RESPONSE_HAS_BODY = true
28
+ end
29
+
30
+ # See Net::HTTPGenericRequest for attributes and methods.
31
+ # See Net::HTTP for usage examples.
32
+ class Net::HTTP::Put < Net::HTTPRequest
33
+ METHOD = 'PUT'
34
+ REQUEST_HAS_BODY = true
35
+ RESPONSE_HAS_BODY = true
36
+ end
37
+
38
+ # See Net::HTTPGenericRequest for attributes and methods.
39
+ # See Net::HTTP for usage examples.
40
+ class Net::HTTP::Delete < Net::HTTPRequest
41
+ METHOD = 'DELETE'
42
+ REQUEST_HAS_BODY = false
43
+ RESPONSE_HAS_BODY = true
44
+ end
45
+
46
+ # See Net::HTTPGenericRequest for attributes and methods.
47
+ class Net::HTTP::Options < Net::HTTPRequest
48
+ METHOD = 'OPTIONS'
49
+ REQUEST_HAS_BODY = false
50
+ RESPONSE_HAS_BODY = true
51
+ end
52
+
53
+ # See Net::HTTPGenericRequest for attributes and methods.
54
+ class Net::HTTP::Trace < Net::HTTPRequest
55
+ METHOD = 'TRACE'
56
+ REQUEST_HAS_BODY = false
57
+ RESPONSE_HAS_BODY = true
58
+ end
59
+
60
+ #
61
+ # PATCH method --- RFC5789
62
+ #
63
+
64
+ # See Net::HTTPGenericRequest for attributes and methods.
65
+ class Net::HTTP::Patch < Net::HTTPRequest
66
+ METHOD = 'PATCH'
67
+ REQUEST_HAS_BODY = true
68
+ RESPONSE_HAS_BODY = true
69
+ end
70
+
71
+ #
72
+ # WebDAV methods --- RFC2518
73
+ #
74
+
75
+ # See Net::HTTPGenericRequest for attributes and methods.
76
+ class Net::HTTP::Propfind < Net::HTTPRequest
77
+ METHOD = 'PROPFIND'
78
+ REQUEST_HAS_BODY = true
79
+ RESPONSE_HAS_BODY = true
80
+ end
81
+
82
+ # See Net::HTTPGenericRequest for attributes and methods.
83
+ class Net::HTTP::Proppatch < Net::HTTPRequest
84
+ METHOD = 'PROPPATCH'
85
+ REQUEST_HAS_BODY = true
86
+ RESPONSE_HAS_BODY = true
87
+ end
88
+
89
+ # See Net::HTTPGenericRequest for attributes and methods.
90
+ class Net::HTTP::Mkcol < Net::HTTPRequest
91
+ METHOD = 'MKCOL'
92
+ REQUEST_HAS_BODY = true
93
+ RESPONSE_HAS_BODY = true
94
+ end
95
+
96
+ # See Net::HTTPGenericRequest for attributes and methods.
97
+ class Net::HTTP::Copy < Net::HTTPRequest
98
+ METHOD = 'COPY'
99
+ REQUEST_HAS_BODY = false
100
+ RESPONSE_HAS_BODY = true
101
+ end
102
+
103
+ # See Net::HTTPGenericRequest for attributes and methods.
104
+ class Net::HTTP::Move < Net::HTTPRequest
105
+ METHOD = 'MOVE'
106
+ REQUEST_HAS_BODY = false
107
+ RESPONSE_HAS_BODY = true
108
+ end
109
+
110
+ # See Net::HTTPGenericRequest for attributes and methods.
111
+ class Net::HTTP::Lock < Net::HTTPRequest
112
+ METHOD = 'LOCK'
113
+ REQUEST_HAS_BODY = true
114
+ RESPONSE_HAS_BODY = true
115
+ end
116
+
117
+ # See Net::HTTPGenericRequest for attributes and methods.
118
+ class Net::HTTP::Unlock < Net::HTTPRequest
119
+ METHOD = 'UNLOCK'
120
+ REQUEST_HAS_BODY = true
121
+ RESPONSE_HAS_BODY = true
122
+ end
123
+
@@ -0,0 +1,426 @@
1
+ # frozen_string_literal: false
2
+ # HTTP response class.
3
+ #
4
+ # This class wraps together the response header and the response body (the
5
+ # entity requested).
6
+ #
7
+ # It mixes in the HTTPHeader module, which provides access to response
8
+ # header values both via hash-like methods and via individual readers.
9
+ #
10
+ # Note that each possible HTTP response code defines its own
11
+ # HTTPResponse subclass. All classes are defined under the Net module.
12
+ # Indentation indicates inheritance. For a list of the classes see Net::HTTP.
13
+ #
14
+ # Correspondence <code>HTTP code => class</code> is stored in CODE_TO_OBJ
15
+ # constant:
16
+ #
17
+ # Net::HTTPResponse::CODE_TO_OBJ['404'] #=> Net::HTTPNotFound
18
+ #
19
+ class Net::HTTPResponse
20
+ class << self
21
+ # true if the response has a body.
22
+ def body_permitted?
23
+ self::HAS_BODY
24
+ end
25
+
26
+ def exception_type # :nodoc: internal use only
27
+ self::EXCEPTION_TYPE
28
+ end
29
+
30
+ def read_new(sock) #:nodoc: internal use only
31
+ httpv, code, msg = read_status_line(sock)
32
+ res = response_class(code).new(httpv, code, msg)
33
+ each_response_header(sock) do |k,v|
34
+ res.add_field k, v
35
+ end
36
+ res
37
+ end
38
+
39
+ private
40
+
41
+ def read_status_line(sock)
42
+ str = sock.readline
43
+ m = /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)(?:\s+(.*))?\z/in.match(str) or
44
+ raise Net::HTTPBadResponse, "wrong status line: #{str.dump}"
45
+ m.captures
46
+ end
47
+
48
+ def response_class(code)
49
+ CODE_TO_OBJ[code] or
50
+ CODE_CLASS_TO_OBJ[code[0,1]] or
51
+ Net::HTTPUnknownResponse
52
+ end
53
+
54
+ def each_response_header(sock)
55
+ key = value = nil
56
+ while true
57
+ line = sock.readuntil("\n", true).sub(/\s+\z/, '')
58
+ break if line.empty?
59
+ if line[0] == ?\s or line[0] == ?\t and value
60
+ value << ' ' unless value.empty?
61
+ value << line.strip
62
+ else
63
+ yield key, value if key
64
+ key, value = line.strip.split(/\s*:\s*/, 2)
65
+ raise Net::HTTPBadResponse, 'wrong header line format' if value.nil?
66
+ end
67
+ end
68
+ yield key, value if key
69
+ end
70
+ end
71
+
72
+ # next is to fix bug in RDoc, where the private inside class << self
73
+ # spills out.
74
+ public
75
+
76
+ include Net::HTTPHeader
77
+
78
+ def initialize(httpv, code, msg) #:nodoc: internal use only
79
+ @http_version = httpv
80
+ @code = code
81
+ @message = msg
82
+ initialize_http_header nil
83
+ @body = nil
84
+ @read = false
85
+ @uri = nil
86
+ @decode_content = false
87
+ end
88
+
89
+ # The HTTP version supported by the server.
90
+ attr_reader :http_version
91
+
92
+ # The HTTP result code string. For example, '302'. You can also
93
+ # determine the response type by examining which response subclass
94
+ # the response object is an instance of.
95
+ attr_reader :code
96
+
97
+ # The HTTP result message sent by the server. For example, 'Not Found'.
98
+ attr_reader :message
99
+ alias msg message # :nodoc: obsolete
100
+
101
+ # The URI used to fetch this response. The response URI is only available
102
+ # if a URI was used to create the request.
103
+ attr_reader :uri
104
+
105
+ # Set to true automatically when the request did not contain an
106
+ # Accept-Encoding header from the user.
107
+ attr_accessor :decode_content
108
+
109
+ def inspect
110
+ "#<#{self.class} #{@code} #{@message} readbody=#{@read}>"
111
+ end
112
+
113
+ #
114
+ # response <-> exception relationship
115
+ #
116
+
117
+ def code_type #:nodoc:
118
+ self.class
119
+ end
120
+
121
+ def error! #:nodoc:
122
+ message = @code
123
+ message += ' ' + @message.dump if @message
124
+ raise error_type().new(message, self)
125
+ end
126
+
127
+ def error_type #:nodoc:
128
+ self.class::EXCEPTION_TYPE
129
+ end
130
+
131
+ # Raises an HTTP error if the response is not 2xx (success).
132
+ def value
133
+ error! unless self.kind_of?(Net::HTTPSuccess)
134
+ end
135
+
136
+ def uri= uri # :nodoc:
137
+ @uri = uri.dup if uri
138
+ end
139
+
140
+ #
141
+ # header (for backward compatibility only; DO NOT USE)
142
+ #
143
+
144
+ def response #:nodoc:
145
+ warn "Net::HTTPResponse#response is obsolete", uplevel: 1 if $VERBOSE
146
+ self
147
+ end
148
+
149
+ def header #:nodoc:
150
+ warn "Net::HTTPResponse#header is obsolete", uplevel: 1 if $VERBOSE
151
+ self
152
+ end
153
+
154
+ def read_header #:nodoc:
155
+ warn "Net::HTTPResponse#read_header is obsolete", uplevel: 1 if $VERBOSE
156
+ self
157
+ end
158
+
159
+ #
160
+ # body
161
+ #
162
+
163
+ def reading_body(sock, reqmethodallowbody) #:nodoc: internal use only
164
+ @socket = sock
165
+ @body_exist = reqmethodallowbody && self.class.body_permitted?
166
+ begin
167
+ yield
168
+ self.body # ensure to read body
169
+ ensure
170
+ @socket = nil
171
+ end
172
+ end
173
+
174
+ # Gets the entity body returned by the remote HTTP server.
175
+ #
176
+ # If a block is given, the body is passed to the block, and
177
+ # the body is provided in fragments, as it is read in from the socket.
178
+ #
179
+ # If +dest+ argument is given, response is read into that variable,
180
+ # with <code>dest#<<</code> method (it could be String or IO, or any
181
+ # other object responding to <code><<</code>).
182
+ #
183
+ # Calling this method a second or subsequent time for the same
184
+ # HTTPResponse object will return the value already read.
185
+ #
186
+ # http.request_get('/index.html') {|res|
187
+ # puts res.read_body
188
+ # }
189
+ #
190
+ # http.request_get('/index.html') {|res|
191
+ # p res.read_body.object_id # 538149362
192
+ # p res.read_body.object_id # 538149362
193
+ # }
194
+ #
195
+ # # using iterator
196
+ # http.request_get('/index.html') {|res|
197
+ # res.read_body do |segment|
198
+ # print segment
199
+ # end
200
+ # }
201
+ #
202
+ def read_body(dest = nil, &block)
203
+ if @read
204
+ raise IOError, "#{self.class}\#read_body called twice" if dest or block
205
+ return @body
206
+ end
207
+ to = procdest(dest, block)
208
+ stream_check
209
+ if @body_exist
210
+ read_body_0 to
211
+ @body = to
212
+ else
213
+ @body = nil
214
+ end
215
+ @read = true
216
+
217
+ @body
218
+ end
219
+
220
+ # Returns the full entity body.
221
+ #
222
+ # Calling this method a second or subsequent time will return the
223
+ # string already read.
224
+ #
225
+ # http.request_get('/index.html') {|res|
226
+ # puts res.body
227
+ # }
228
+ #
229
+ # http.request_get('/index.html') {|res|
230
+ # p res.body.object_id # 538149362
231
+ # p res.body.object_id # 538149362
232
+ # }
233
+ #
234
+ def body
235
+ read_body()
236
+ end
237
+
238
+ # Because it may be necessary to modify the body, Eg, decompression
239
+ # this method facilitates that.
240
+ def body=(value)
241
+ @body = value
242
+ end
243
+
244
+ alias entity body #:nodoc: obsolete
245
+
246
+ private
247
+
248
+ ##
249
+ # Checks for a supported Content-Encoding header and yields an Inflate
250
+ # wrapper for this response's socket when zlib is present. If the
251
+ # Content-Encoding is not supported or zlib is missing, the plain socket is
252
+ # yielded.
253
+ #
254
+ # If a Content-Range header is present, a plain socket is yielded as the
255
+ # bytes in the range may not be a complete deflate block.
256
+
257
+ def inflater # :nodoc:
258
+ return yield @socket unless Net::HTTP::HAVE_ZLIB
259
+ return yield @socket unless @decode_content
260
+ return yield @socket if self['content-range']
261
+
262
+ v = self['content-encoding']
263
+ case v&.downcase
264
+ when 'deflate', 'gzip', 'x-gzip' then
265
+ self.delete 'content-encoding'
266
+
267
+ inflate_body_io = Inflater.new(@socket)
268
+
269
+ begin
270
+ yield inflate_body_io
271
+ ensure
272
+ orig_err = $!
273
+ begin
274
+ inflate_body_io.finish
275
+ rescue => err
276
+ raise orig_err || err
277
+ end
278
+ end
279
+ when 'none', 'identity' then
280
+ self.delete 'content-encoding'
281
+
282
+ yield @socket
283
+ else
284
+ yield @socket
285
+ end
286
+ end
287
+
288
+ def read_body_0(dest)
289
+ inflater do |inflate_body_io|
290
+ if chunked?
291
+ read_chunked dest, inflate_body_io
292
+ return
293
+ end
294
+
295
+ @socket = inflate_body_io
296
+
297
+ clen = content_length()
298
+ if clen
299
+ @socket.read clen, dest, true # ignore EOF
300
+ return
301
+ end
302
+ clen = range_length()
303
+ if clen
304
+ @socket.read clen, dest
305
+ return
306
+ end
307
+ @socket.read_all dest
308
+ end
309
+ end
310
+
311
+ ##
312
+ # read_chunked reads from +@socket+ for chunk-size, chunk-extension, CRLF,
313
+ # etc. and +chunk_data_io+ for chunk-data which may be deflate or gzip
314
+ # encoded.
315
+ #
316
+ # See RFC 2616 section 3.6.1 for definitions
317
+
318
+ def read_chunked(dest, chunk_data_io) # :nodoc:
319
+ total = 0
320
+ while true
321
+ line = @socket.readline
322
+ hexlen = line.slice(/[0-9a-fA-F]+/) or
323
+ raise Net::HTTPBadResponse, "wrong chunk size line: #{line}"
324
+ len = hexlen.hex
325
+ break if len == 0
326
+ begin
327
+ chunk_data_io.read len, dest
328
+ ensure
329
+ total += len
330
+ @socket.read 2 # \r\n
331
+ end
332
+ end
333
+ until @socket.readline.empty?
334
+ # none
335
+ end
336
+ end
337
+
338
+ def stream_check
339
+ raise IOError, 'attempt to read body out of block' if @socket.closed?
340
+ end
341
+
342
+ def procdest(dest, block)
343
+ raise ArgumentError, 'both arg and block given for HTTP method' if
344
+ dest and block
345
+ if block
346
+ Net::ReadAdapter.new(block)
347
+ else
348
+ dest || ''
349
+ end
350
+ end
351
+
352
+ ##
353
+ # Inflater is a wrapper around Net::BufferedIO that transparently inflates
354
+ # zlib and gzip streams.
355
+
356
+ class Inflater # :nodoc:
357
+
358
+ ##
359
+ # Creates a new Inflater wrapping +socket+
360
+
361
+ def initialize socket
362
+ @socket = socket
363
+ # zlib with automatic gzip detection
364
+ @inflate = Zlib::Inflate.new(32 + Zlib::MAX_WBITS)
365
+ end
366
+
367
+ ##
368
+ # Finishes the inflate stream.
369
+
370
+ def finish
371
+ return if @inflate.total_in == 0
372
+ @inflate.finish
373
+ end
374
+
375
+ ##
376
+ # Returns a Net::ReadAdapter that inflates each read chunk into +dest+.
377
+ #
378
+ # This allows a large response body to be inflated without storing the
379
+ # entire body in memory.
380
+
381
+ def inflate_adapter(dest)
382
+ if dest.respond_to?(:set_encoding)
383
+ dest.set_encoding(Encoding::ASCII_8BIT)
384
+ elsif dest.respond_to?(:force_encoding)
385
+ dest.force_encoding(Encoding::ASCII_8BIT)
386
+ end
387
+ block = proc do |compressed_chunk|
388
+ @inflate.inflate(compressed_chunk) do |chunk|
389
+ compressed_chunk.clear
390
+ dest << chunk
391
+ end
392
+ end
393
+
394
+ Net::ReadAdapter.new(block)
395
+ end
396
+
397
+ ##
398
+ # Reads +clen+ bytes from the socket, inflates them, then writes them to
399
+ # +dest+. +ignore_eof+ is passed down to Net::BufferedIO#read
400
+ #
401
+ # Unlike Net::BufferedIO#read, this method returns more than +clen+ bytes.
402
+ # At this time there is no way for a user of Net::HTTPResponse to read a
403
+ # specific number of bytes from the HTTP response body, so this internal
404
+ # API does not return the same number of bytes as were requested.
405
+ #
406
+ # See https://bugs.ruby-lang.org/issues/6492 for further discussion.
407
+
408
+ def read clen, dest, ignore_eof = false
409
+ temp_dest = inflate_adapter(dest)
410
+
411
+ @socket.read clen, temp_dest, ignore_eof
412
+ end
413
+
414
+ ##
415
+ # Reads the rest of the socket, inflates it, then writes it to +dest+.
416
+
417
+ def read_all dest
418
+ temp_dest = inflate_adapter(dest)
419
+
420
+ @socket.read_all temp_dest
421
+ end
422
+
423
+ end
424
+
425
+ end
426
+