net-http 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+