Issue #8544 has been updated by naruse (Yui NARUSE).


Experimental implementation is below, it needs error handling and rdoc and tests.

diff --git a/lib/open-uri.rb b/lib/open-uri.rb
index 32f0662..21af81b 100644
--- a/lib/open-uri.rb
+++ b/lib/open-uri.rb
@@ -781,4 +781,20 @@ module URI
 
     include OpenURI::OpenRead
   end
+
+  class File
+    def buffer_open(buf, proxy, options) # :nodoc:
+      if self.host && self.host.downcase != 'localhost'
+        raise ArgumentError, "URI::File#open can't open remote file"
+      end
+      begin
+        raise if options[:mode].nil?
+      rescue
+        options[:mode] = IO::RDONLY
+      end
+      buf.instance_variable_set :@io, ::File.open(self.path, options)
+    end
+
+    include OpenURI::OpenRead
+  end
 end
diff --git a/lib/uri.rb b/lib/uri.rb
index 2e136eb..19bd1d6 100644
--- a/lib/uri.rb
+++ b/lib/uri.rb
@@ -103,6 +103,7 @@ end
 
 require 'uri/common'
 require 'uri/generic'
+require 'uri/file'
 require 'uri/ftp'
 require 'uri/http'
 require 'uri/https'
diff --git a/lib/uri/file.rb b/lib/uri/file.rb
new file mode 100644
index 0000000..b6806fb
--- /dev/null
+++ b/lib/uri/file.rb
@@ -0,0 +1,91 @@
+# = uri/file.rb
+#
+# Author:: Akira Yamada <akira / ruby-lang.org>
+# License:: You can redistribute it and/or modify it under the same term as Ruby.
+# Revision:: $Id$
+#
+# See URI for general documentation
+#
+
+require 'uri/generic'
+
+module URI
+
+  #
+  # File URI syntax is defined by RFCXXXX section X.X.
+  #
+  class File < Generic
+    #
+    # An Array of the available components for URI::File
+    #
+    COMPONENT = [
+      :scheme,
+      :userinfo, :host,
+      :path
+    ].freeze
+
+    #
+    # == Description
+    #
+    # Creates a new URI::File object from components, with syntax checking.
+    #
+    # The components accepted are +userinfo+, +host+, +path+ and
+    # +typecode+.
+    #
+    # The components should be provided either as an Array, or as a Hash
+    # with keys formed by preceding the component names with a colon.
+    #
+    # If an Array is used, the components must be passed in the order
+    # [userinfo, host, port, path, typecode]
+    #
+    # If the path supplied is absolute, it will be escaped in order to
+    # make it absolute in the URI. Examples:
+    #
+    #     require 'uri'
+    #
+    #     uri = URI::File.build(['user:password', 'ftp.example.com', nil,
+    #       '/path/file.> zip', 'i'])
+    #     puts uri.to_s  ->  ftp://user:password / ftp.example.com/%2Fpath/file.zip;type=a
+    #
+    #     uri2 = URI::File.build({:host => 'ftp.example.com',
+    #       :path => 'ruby/src'})
+    #     puts uri2.to_s  ->  ftp://ftp.example.com/ruby/src
+    #
+    def self.build(args)
+
+      tmp = Util::make_components_hash(self, args)
+
+      return super(tmp)
+    end
+
+    #
+    # == Description
+    #
+    # Creates a new URI::File object from generic URL components with no
+    # syntax checking.
+    #
+    # Unlike build(), this method does not escape the path component as
+    # required by RFC1738; instead it is treated as per RFC2396.
+    #
+    # Arguments are +scheme+, +host+, +path+,
+    # +query+ and +fragment+, in that order.
+    #
+    def initialize(*arg)
+      super(*arg)
+      if @port
+        raise InvalidURIError, "a file URI can't have port"
+      end
+      if @password
+        raise InvalidURIError, "a file URI can't have password"
+      end
+    end
+
+    # Returns a String representation of the URI::File
+    def to_s
+      str = super
+
+      return str
+    end
+  end
+  @@schemes['FILE'] = File
+end

----------------------------------------
Feature #8544: OpenURI should open 'file://' URIs
https://bugs.ruby-lang.org/issues/8544#change-40172

Author: silasdavis (Silas Davis)
Status: Open
Priority: Normal
Assignee: 
Category: core
Target version: next minor


The following code prints the contents of '/tmp/file.txt':

require 'open-uri'
open('/tmp/file.txt').read {|f| puts f.read }

which although useful should probably fail since a unix file path is not a URI, and therefore might shield data problems in a system

However the following should produce the same output and is a URI, but fails:

open('file:///tmp/file.txt').read {|f| puts f.read }

I note that the documentation for open-uri does explain that it is a wrapper for http, https, and ftp, but to deserve its name it should open such URIs as specified in this RFC: http://tools.ietf.org/html/rfc1630. This coupled with the fact that it already does open files, but not by a URI specification.



-- 
http://bugs.ruby-lang.org/