rubysl-net-http 1.0.1 → 2.0.4

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