⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 open-uri.rb

📁 Amarok是一款在LINUX或其他类UNIX操作系统中运行的音频播放器软件。 经过两年开发后
💻 RB
📖 第 1 页 / 共 2 页
字号:
#= open-uri.rb##open-uri.rb is easy-to-use wrapper for net/http, net/https and net/ftp.##== Example##It is possible to open http/https/ftp URL as usual a file:##  open("http://www.ruby-lang.org/") {|f|#    f.each_line {|line| p line}#  }##The opened file has several methods for meta information as follows since#it is extended by OpenURI::Meta.##  open("http://www.ruby-lang.org/en") {|f|#    f.each_line {|line| p line}#    p f.base_uri         # <URI::HTTP:0x40e6ef2 URL:http://www.ruby-lang.org/en/>#    p f.content_type     # "text/html"#    p f.charset          # "iso-8859-1"#    p f.content_encoding # []#    p f.last_modified    # Thu Dec 05 02:45:02 UTC 2002#  }##Additional header fields can be specified by an optional hash argument.##  open("http://www.ruby-lang.org/en/",#    "User-Agent" => "Ruby/#{RUBY_VERSION}",#    "From" => "foo@bar.invalid",#    "Referer" => "http://www.ruby-lang.org/") {|f|#    ...#  }##The environment variables such as http_proxy, https_proxy and ftp_proxy#are in effect by default.  :proxy => nil disables proxy.##  open("http://www.ruby-lang.org/en/raa.html",#    :proxy => nil) {|f|#    ...#  }##URI objects can be opened in similar way.##  uri = URI.parse("http://www.ruby-lang.org/en/")#  uri.open {|f|#    ...#  }##URI objects can be read directly.#The returned string is also extended by OpenURI::Meta.##  str = uri.read#  p str.base_uri##Author:: Tanaka Akira <akr@m17n.org>#--# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.# All rights reserved.# See LICENSE.txt for permissions.#++require 'uri'require 'stringio'require 'time'module Kernel  private  alias open_uri_original_open open # :nodoc:  # makes possible to open various resources including URIs.  # If the first argument respond to `open' method,  # the method is called with the rest arguments.  #  # If the first argument is a string which begins with xxx://,  # it is parsed by URI.parse.  If the parsed object respond to `open' method,  # the method is called with the rest arguments.  #  # Otherwise original open is called.  #  # Since open-uri.rb provides URI::HTTP#open, URI::HTTPS#open and  # URI::FTP#open,  # Kernel[#.]open can accepts such URIs and strings which begins with  # http://, https:// and ftp://.  # In these case, the opened file object is extended by OpenURI::Meta.  def open(name, *rest, &block) # :doc:    if name.respond_to?(:open)      name.open(*rest, &block)    elsif name.respond_to?(:to_str) &&          %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ name &&          (uri = URI.parse(name)).respond_to?(:open)      uri.open(*rest, &block)    else      open_uri_original_open(name, *rest, &block)    end  end  module_function :openendmodule OpenURI  Options = {    :proxy => true,    :proxy_http_basic_authentication => true,    :progress_proc => true,    :content_length_proc => true,    :http_basic_authentication => true,    :read_timeout => 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      if !rest.empty? && Integer === rest.first        perm = rest.shift      end    end    return mode, perm, rest  end  def OpenURI.open_uri(name, *rest) # :nodoc:    uri = URI::Generic === name ? name : URI.parse(name)    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' ||           mode == File::RDONLY      raise ArgumentError.new("invalid access mode #{mode} (#{uri.class} resource is read only.)")    end    io = open_loop(uri, options)    if block_given?      begin        yield io      ensure        io.close      end    else      io    end  end  def OpenURI.open_loop(uri, options) # :nodoc:    proxy_opts = []    proxy_opts << :proxy_http_basic_authentication if options.include? :proxy_http_basic_authentication    proxy_opts << :proxy if options.include? :proxy    proxy_opts.compact!    if 1 < proxy_opts.length      raise ArgumentError, "multiple proxy options specified"    end    case proxy_opts.first    when :proxy_http_basic_authentication      opt_proxy, proxy_user, proxy_pass = options.fetch(:proxy_http_basic_authentication)      proxy_user = proxy_user.to_str      proxy_pass = proxy_pass.to_str      if opt_proxy == true        raise ArgumentError.new("Invalid authenticated proxy option: #{options[:proxy_http_basic_authentication].inspect}")      end    when :proxy      opt_proxy = options.fetch(:proxy)      proxy_user = nil      proxy_pass = nil    when nil      opt_proxy = true      proxy_user = nil      proxy_pass = nil    end    case opt_proxy    when true      find_proxy = lambda {|u| pxy = u.find_proxy; pxy ? [pxy, nil, nil] : nil}    when nil, false      find_proxy = lambda {|u| nil}    when String      opt_proxy = URI.parse(opt_proxy)      find_proxy = lambda {|u| [opt_proxy, proxy_user, proxy_pass]}    when URI::Generic      find_proxy = lambda {|u| [opt_proxy, proxy_user, proxy_pass]}    else      raise ArgumentError.new("Invalid proxy option: #{opt_proxy}")    end    uri_set = {}    buf = nil    while true      redirect = catch(:open_uri_redirect) {        buf = Buffer.new        uri.buffer_open(buf, find_proxy.call(uri), options)        nil      }      if redirect        if redirect.relative?          # Although it violates RFC2616, Location: field may have relative          # URI.  It is converted to absolute URI using uri as a base URI.          redirect = uri + redirect        end        unless OpenURI.redirectable?(uri, redirect)          raise "redirection forbidden: #{uri} -> #{redirect}"        end        if options.include? :http_basic_authentication          # send authentication only for the URI directly specified.          options = options.dup          options.delete :http_basic_authentication        end        uri = redirect        raise "HTTP redirection loop: #{uri}" if uri_set.include? uri.to_s        uri_set[uri.to_s] = true      else        break      end    end    io = buf.io    io.base_uri = uri    io  end  def OpenURI.redirectable?(uri1, uri2) # :nodoc:    # This test is intended to forbid a redirection from http://... to    # file:///etc/passwd.    # However this is ad hoc.  It should be extensible/configurable.    uri1.scheme.downcase == uri2.scheme.downcase ||    (/\A(?:http|ftp)\z/i =~ uri1.scheme && /\A(?:http|ftp)\z/i =~ uri2.scheme)  end  def OpenURI.open_http(buf, target, proxy, options) # :nodoc:    if proxy      proxy_uri, proxy_user, proxy_pass = proxy      raise "Non-HTTP proxy URI: #{proxy_uri}" if proxy_uri.class != URI::HTTP    end    if target.userinfo && "1.9.0" <= RUBY_VERSION      # don't raise for 1.8 because compatibility.      raise ArgumentError, "userinfo not supported.  [RFC3986]"    end    header = {}    options.each {|k, v| header[k] = v if String === k }    require 'net/http'    klass = Net::HTTP    if URI::HTTP === target      # HTTP or HTTPS      if proxy        if proxy_user && proxy_pass          klass = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port, proxy_user, proxy_pass)        else          klass = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port)        end      end      target_host = target.host      target_port = target.port      request_uri = target.request_uri    else      # FTP over HTTP proxy      target_host = proxy_uri.host      target_port = proxy_uri.port      request_uri = target.to_s      if proxy_user && proxy_pass        header["Proxy-Authorization"] = 'Basic ' + ["#{proxy_user}:#{proxy_pass}"].pack('m').delete("\r\n")      end    end    http = klass.new(target_host, target_port)    if target.class == URI::HTTPS      require 'net/https'      http.use_ssl = true      http.verify_mode = OpenSSL::SSL::VERIFY_PEER      store = OpenSSL::X509::Store.new      store.set_default_paths      http.cert_store = store    end    if options.include? :read_timeout      http.read_timeout = options[:read_timeout]    end    resp = nil    http.start {      if target.class == URI::HTTPS        # xxx: information hiding violation        sock = http.instance_variable_get(:@socket)        if sock.respond_to?(:io)          sock = sock.io # 1.9        else          sock = sock.instance_variable_get(:@socket) # 1.8        end        sock.post_connection_check(target_host)      end      req = Net::HTTP::Get.new(request_uri, header)      if options.include? :http_basic_authentication        user, pass = options[:http_basic_authentication]        req.basic_auth user, pass      end      http.request(req) {|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]    resp.each {|name,value| buf.io.meta_add_field name, value }    case resp    when Net::HTTPSuccess    when Net::HTTPMovedPermanently, # 301         Net::HTTPFound, # 302         Net::HTTPSeeOther, # 303         Net::HTTPTemporaryRedirect # 307      throw :open_uri_redirect, URI.parse(resp['location'])    else      raise OpenURI::HTTPError.new(io.status.join(' '), io)    end  end  class HTTPError < StandardError    def initialize(message, io)      super(message)      @io = io    end    attr_reader :io  end  class Buffer # :nodoc:    def initialize      @io = StringIO.new      @size = 0    end    attr_reader :size    StringMax = 10240    def <<(str)      @io << str      @size += str.length      if StringIO === @io && StringMax < @size        require 'tempfile'        io = Tempfile.new('open-uri')        io.binmode        Meta.init io, @io if @io.respond_to? :meta        io << @io.string        @io = io      end    end    def io      Meta.init @io unless @io.respond_to? :meta      @io    end  end  # Mixin for holding meta-information.  module Meta    def Meta.init(obj, src=nil) # :nodoc:      obj.extend Meta      obj.instance_eval {        @base_uri = nil        @meta = {}      }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -