Skip to content

Path with spaces throws a bad URI(is not URI?) error #687

Open
@marcamillion

Description

@marcamillion

Expected behavior

When a Rails or Sprockets project is placed in a directory with spaces in the folder names in the path, it shouldn't throw any errors. It should just escape the path name and work like normal.

Actual behavior

Once you put your project in a folder that has spaces in the path name, it throws the following error:

bad URI(is not URI?): "file-digest:///Users/username/Company Name Dropbox/User Name/ProjectName/myapp/app/assets/config/bootstrap"`

System configuration

  • Sprockets 4.0.2 (also been able to replicate it in 3.7.2)
  • Ruby 2.7.1 (also been able to replicate it in 2.5.1)
  • Rails 6.0.3.2 (also been able to replicate it in 5.2.4.3)

Example App (Reproduction)

I have successfully created a failing test on a fork of Sprockets. You can simply pull the following branch, run bundle exec rake test and you will see the failing test.

This is what you should see:

Finished in 46.357470s, 19.4143 runs/s, 84.9701 assertions/s.

  1) Error:
TestURIUtils#test_split_file_uri:
URI::InvalidURIError: bad URI(is not URI?): "file:///usr/Company Name Dropbox/local/bin/myapp/assets"
    /.rvm/rubies/ruby-2.7.1/lib/ruby/2.7.0/uri/rfc3986_parser.rb:67:in `split'
    /.rvm/rubies/ruby-2.7.1/lib/ruby/2.7.0/uri/common.rb:197:in `split'
    /sprockets/lib/sprockets/uri_utils.rb:49:in `split_file_uri'
    /sprockets/test/test_uri_utils.rb:39:in `test_split_file_uri'

900 runs, 3939 assertions, 0 failures, 1 errors, 4 skips

You have skipped tests. Run with --verbose for details.
rake aborted!
Command failed with status (1)
/.rvm/gems/ruby-2.7.1@myapp/gems/rake-12.3.3/exe/rake:27:in `<top (required)>'
/.rvm/gems/ruby-2.7.1@myapp/bin/ruby_executable_hooks:24:in `eval'
/.rvm/gems/ruby-2.7.1@myapp/bin/ruby_executable_hooks:24:in `<main>'
Tasks: TOP => test
(See full trace by running task with --trace)

Steps Taken To Begin Fixing

I have isolated the problem to the following method:

    def split_file_uri(uri)
      # We need to parse out any potential spaces in the path
      scheme, _, host, _, _, path, _, query, _ = URI.split(uri)

      path = URI::Generic::DEFAULT_PARSER.unescape(path)
      path.force_encoding(Encoding::UTF_8)

      # Hack for parsing Windows "/C:/Users/IEUser" paths
      if File::ALT_SEPARATOR && path[2] == ':'
        path = path[1..-1]
      end

      [scheme, host, path, query]
    end

One solution I have tried is to essentially escape uri at the beginning of the method, so I inserted this line at the top of that method:

      uri = URI::Generic::DEFAULT_PARSER.escape(uri)

The issue this creates is that it escapes paths that were previously escaped, e.g. the following test from test/test_uri_utils.rb has begun to fail with that fix:

    parts = split_file_uri("file:///usr/local/bin/ruby%20on%20rails")
    assert_equal ['file', nil, '/usr/local/bin/ruby on rails', nil], parts

Primarily because it returns the original string as a URI, i.e. file:///usr/local/bin/ruby%20on%20rails, as opposed to the unescaped version.

The reason this is the case is because the first thing it does is now escapes the previously escaped string and then unescapes that double escaped string, which reverts it to the original string.

There are also other Failures, Errors & Skips that this small change has created.

So rather than digging much further, I figured I would reach out for some help.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions