rubysl-net-http 1.0.1 → 2.0.4

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