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>
|
Mon Nov 24 14:53:10 2003 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||||
|
|
||||||
* bcc32/Makefile.sub, win32/Makefile.sub, wince/Makefile.sub
|
* bcc32/Makefile.sub, win32/Makefile.sub, wince/Makefile.sub
|
||||||
|
|
124
lib/open-uri.rb
124
lib/open-uri.rb
|
@ -91,6 +91,22 @@ module Kernel
|
||||||
end
|
end
|
||||||
|
|
||||||
module OpenURI
|
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:
|
def OpenURI.scan_open_optional_arguments(*rest) # :nodoc:
|
||||||
if !rest.empty? && (String === rest.first || Integer === rest.first)
|
if !rest.empty? && (String === rest.first || Integer === rest.first)
|
||||||
mode = rest.shift
|
mode = rest.shift
|
||||||
|
@ -106,6 +122,8 @@ module OpenURI
|
||||||
mode, perm, rest = OpenURI.scan_open_optional_arguments(*rest)
|
mode, perm, rest = OpenURI.scan_open_optional_arguments(*rest)
|
||||||
options = rest.shift if !rest.empty? && Hash === rest.first
|
options = rest.shift if !rest.empty? && Hash === rest.first
|
||||||
raise ArgumentError.new("extra arguments") if !rest.empty?
|
raise ArgumentError.new("extra arguments") if !rest.empty?
|
||||||
|
options ||= {}
|
||||||
|
OpenURI.check_options(options)
|
||||||
|
|
||||||
unless mode == nil ||
|
unless mode == nil ||
|
||||||
mode == 'r' || mode == 'rb' ||
|
mode == 'r' || mode == 'rb' ||
|
||||||
|
@ -113,7 +131,7 @@ module OpenURI
|
||||||
raise ArgumentError.new("invalid access mode #{mode} (#{uri.class} resource is read only.)")
|
raise ArgumentError.new("invalid access mode #{mode} (#{uri.class} resource is read only.)")
|
||||||
end
|
end
|
||||||
|
|
||||||
io = open_loop(uri, options || {})
|
io = open_loop(uri, options)
|
||||||
if block_given?
|
if block_given?
|
||||||
begin
|
begin
|
||||||
yield io
|
yield io
|
||||||
|
@ -316,12 +334,90 @@ module OpenURI
|
||||||
|
|
||||||
# Mixin for HTTP and FTP URIs.
|
# Mixin for HTTP and FTP URIs.
|
||||||
module OpenRead
|
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)
|
def open(*rest, &block)
|
||||||
OpenURI.open_uri(self, *rest, &block)
|
OpenURI.open_uri(self, *rest, &block)
|
||||||
end
|
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={})
|
def read(options={})
|
||||||
self.open(options) {|f|
|
self.open(options) {|f|
|
||||||
str = f.read
|
str = f.read
|
||||||
|
@ -369,9 +465,23 @@ module URI
|
||||||
options.each {|k, v| header[k] = v if String === k }
|
options.each {|k, v| header[k] = v if String === k }
|
||||||
|
|
||||||
require 'net/http'
|
require 'net/http'
|
||||||
resp = Net::HTTP.start(self.host, self.port) {|http|
|
resp = nil
|
||||||
http.get(uri.to_s, header) {|str|
|
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
|
buf << str
|
||||||
|
if options[:progress_proc] && Net::HTTPSuccess === resp
|
||||||
|
options[:progress_proc].call(buf.size)
|
||||||
|
end
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
io = buf.io
|
io = buf.io
|
||||||
|
@ -403,8 +513,12 @@ module URI
|
||||||
|
|
||||||
ftp = Net::FTP.open(self.host)
|
ftp = Net::FTP.open(self.host)
|
||||||
ftp.login(user, passwd)
|
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|
|
ftp.getbinaryfile(self.path, '/dev/null', Net::FTP::DEFAULT_BLOCKSIZE) {|str|
|
||||||
buf << str
|
buf << str
|
||||||
|
options[:progress_proc].call(buf.size) if options[:progress_proc]
|
||||||
}
|
}
|
||||||
ftp.close
|
ftp.close
|
||||||
buf.io.rewind
|
buf.io.rewind
|
||||||
|
|
Loading…
Reference in a new issue