mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* lib/open-uri.rb: validate option names.
:content_length_proc and :progress_proc option implemented. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5012 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
f14589947e
commit
483ac56440
2 changed files with 127 additions and 8 deletions
|
@ -1,3 +1,8 @@
|
|||
Mon Nov 24 17:00:00 2003 Tanaka Akira <akr@m17n.org>
|
||||
|
||||
* lib/open-uri.rb: validate option names.
|
||||
:content_length_proc and :progress_proc option implemented.
|
||||
|
||||
Mon Nov 24 14:53:10 2003 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||
|
||||
* bcc32/Makefile.sub, win32/Makefile.sub, wince/Makefile.sub
|
||||
|
|
130
lib/open-uri.rb
130
lib/open-uri.rb
|
@ -91,6 +91,22 @@ module Kernel
|
|||
end
|
||||
|
||||
module OpenURI
|
||||
Options = {
|
||||
:proxy => true,
|
||||
:progress_proc => true,
|
||||
:content_length_proc => true,
|
||||
}
|
||||
|
||||
|
||||
def OpenURI.check_options(options) # :nodoc:
|
||||
options.each {|k, v|
|
||||
next unless Symbol === k
|
||||
unless Options.include? k
|
||||
raise ArgumentError, "unrecognized option: #{k}"
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def OpenURI.scan_open_optional_arguments(*rest) # :nodoc:
|
||||
if !rest.empty? && (String === rest.first || Integer === rest.first)
|
||||
mode = rest.shift
|
||||
|
@ -106,6 +122,8 @@ module OpenURI
|
|||
mode, perm, rest = OpenURI.scan_open_optional_arguments(*rest)
|
||||
options = rest.shift if !rest.empty? && Hash === rest.first
|
||||
raise ArgumentError.new("extra arguments") if !rest.empty?
|
||||
options ||= {}
|
||||
OpenURI.check_options(options)
|
||||
|
||||
unless mode == nil ||
|
||||
mode == 'r' || mode == 'rb' ||
|
||||
|
@ -113,7 +131,7 @@ module OpenURI
|
|||
raise ArgumentError.new("invalid access mode #{mode} (#{uri.class} resource is read only.)")
|
||||
end
|
||||
|
||||
io = open_loop(uri, options || {})
|
||||
io = open_loop(uri, options)
|
||||
if block_given?
|
||||
begin
|
||||
yield io
|
||||
|
@ -316,12 +334,90 @@ module OpenURI
|
|||
|
||||
# Mixin for HTTP and FTP URIs.
|
||||
module OpenRead
|
||||
# opens the URI.
|
||||
# OpenURI::OpenRead#open provides `open' for URI::HTTP and URI::FTP.
|
||||
#
|
||||
# OpenURI::OpenRead#open takes optional 3 arguments as:
|
||||
# OpenURI::OpenRead#open([mode [, perm]] [, options]) [{|io| ... }]
|
||||
#
|
||||
# `mode', `perm' is same as Kernel#open.
|
||||
#
|
||||
# However, `mode' must be read mode because OpenURI::OpenRead#open doesn't
|
||||
# support write mode (yet).
|
||||
# Also `perm' is just ignored because it is meaningful only for file
|
||||
# creation.
|
||||
#
|
||||
# `options' must be a hash.
|
||||
#
|
||||
# Each pairs which key is a string in the hash specify a extra header
|
||||
# field for HTTP.
|
||||
# I.e. it is ignored for FTP without HTTP proxy.
|
||||
#
|
||||
# The hash may include other option which key is a symbol:
|
||||
#
|
||||
# :proxy => "http://proxy.foo.com:8000/"
|
||||
# :proxy => URI.parse("http://proxy.foo.com:8000/")
|
||||
# :proxy => true
|
||||
# :proxy => false
|
||||
# :proxy => nil
|
||||
#
|
||||
# If :proxy option is specified, the value should be String, URI,
|
||||
# boolean or nil.
|
||||
# When String or URI is given, it is treated as proxy URI.
|
||||
# When true is given or the option itself is not specified,
|
||||
# environment variable `scheme_proxy'(or `SCHEME_PROXY') is examined.
|
||||
# `scheme' is replaced by `http' or `ftp'.
|
||||
# When false or nil is given, the environment variables are ignored and
|
||||
# connection will be made to a server directly.
|
||||
#
|
||||
# :content_length_proc => lambda {|content_length| ... }
|
||||
#
|
||||
# If :content_length_proc option is specified, the option value procedure
|
||||
# is called before actual transfer is started.
|
||||
# It takes one argument which is expected content length in bytes.
|
||||
#
|
||||
# If two or more transfer is done by HTTP redirection, the procedure
|
||||
# is called only one for a last transfer.
|
||||
#
|
||||
# When expected content length is unknown, the procedure is called with
|
||||
# nil.
|
||||
# It is happen when HTTP response has no Content-Length header.
|
||||
#
|
||||
# :progress_proc => lambda {|size| ...}
|
||||
#
|
||||
# If :progress_proc option is specified, the proc is called with one
|
||||
# argument each time when `open' gets content fragment from network.
|
||||
# The argument `size' `size' is a accumulated transfered size in bytes.
|
||||
#
|
||||
# If two or more transfer is done by HTTP redirection, the procedure
|
||||
# is called only one for a last transfer.
|
||||
#
|
||||
# :progress_proc and :content_length_proc are intended to be used for
|
||||
# progress bar.
|
||||
# For example, it can be implemented as follows using Ruby/ProgressBar.
|
||||
#
|
||||
# pbar = nil
|
||||
# open("http://...",
|
||||
# :content_length_proc => lambda {|t|
|
||||
# if t && 0 < t
|
||||
# pbar = ProgressBar.new("...", t)
|
||||
# pbar.file_transfer_mode
|
||||
# end
|
||||
# },
|
||||
# :progress_proc => lambda {|s|
|
||||
# pbar.set s if pbar
|
||||
# }) {|f| ... }
|
||||
#
|
||||
# OpenURI::OpenRead#open returns an IO like object if block is not given.
|
||||
# Otherwise it yields the IO object and return the value of the block.
|
||||
# The IO object is extended with OpenURI::Meta.
|
||||
def open(*rest, &block)
|
||||
OpenURI.open_uri(self, *rest, &block)
|
||||
end
|
||||
|
||||
# reads a content of the URI.
|
||||
# OpenURI::OpenRead#read([options]) reads a content referenced by self and
|
||||
# returns the content as string.
|
||||
# The string is extended with OpenURI::Meta.
|
||||
# The argument `options' is same as OpenURI::OpenRead#open.
|
||||
def read(options={})
|
||||
self.open(options) {|f|
|
||||
str = f.read
|
||||
|
@ -369,11 +465,25 @@ module URI
|
|||
options.each {|k, v| header[k] = v if String === k }
|
||||
|
||||
require 'net/http'
|
||||
resp = Net::HTTP.start(self.host, self.port) {|http|
|
||||
http.get(uri.to_s, header) {|str|
|
||||
buf << str
|
||||
}
|
||||
}
|
||||
resp = nil
|
||||
Net::HTTP.start(self.host, self.port) {|http|
|
||||
http.request_get(uri.to_s, header) {|response|
|
||||
resp = response
|
||||
if options[:content_length_proc] && Net::HTTPSuccess === resp
|
||||
if resp.key?('Content-Length')
|
||||
options[:content_length_proc].call(resp['Content-Length'].to_i)
|
||||
else
|
||||
options[:content_length_proc].call(nil)
|
||||
end
|
||||
end
|
||||
resp.read_body {|str|
|
||||
buf << str
|
||||
if options[:progress_proc] && Net::HTTPSuccess === resp
|
||||
options[:progress_proc].call(buf.size)
|
||||
end
|
||||
}
|
||||
}
|
||||
}
|
||||
io = buf.io
|
||||
io.rewind
|
||||
io.status = [resp.code, resp.message]
|
||||
|
@ -403,8 +513,12 @@ module URI
|
|||
|
||||
ftp = Net::FTP.open(self.host)
|
||||
ftp.login(user, passwd)
|
||||
if options[:content_length_proc]
|
||||
options[:content_length_proc].call(ftp.size(self.path))
|
||||
end
|
||||
ftp.getbinaryfile(self.path, '/dev/null', Net::FTP::DEFAULT_BLOCKSIZE) {|str|
|
||||
buf << str
|
||||
options[:progress_proc].call(buf.size) if options[:progress_proc]
|
||||
}
|
||||
ftp.close
|
||||
buf.io.rewind
|
||||
|
|
Loading…
Reference in a new issue