Module: Aspera::UriReader

Defined in:
lib/aspera/uri_reader.rb

Overview

Read content from a URI; supported schemes: file:, http:, https:, data:

file: URL convention

Two equivalent forms are accepted:

file:///relative/path    -> relative path "relative/path"
file:////absolute/path   -> absolute path "/absolute/path"

A shorter form is also accepted (no authority component):

file:relative/path       -> relative path "relative/path"
file:/absolute/path      -> absolute path "/absolute/path"

The short form is consistent with RFC 8089 (file:/// = absolute, file: = relative). Both forms are handled identically by this module. The canonical form built by UriReader.file_url uses the file:/// prefix.

Class Method Summary collapse

Class Method Details

.file?(url) ⇒ Boolean

Returns true if url uses the file: scheme recognised by this module.

Returns:

  • (Boolean)

    true if url uses the file: scheme recognised by this module



35
36
37
# File 'lib/aspera/uri_reader.rb', line 35

def file?(url)
  url.start_with?(SCHEME_FILE_PFX1)
end

.file_path(url) ⇒ String

Extract the file-system path from a file: URL. Accepts both the canonical file:/// form and the short file: form. Returns the literal path (relative or absolute) without working-directory expansion.

Parameters:

  • url (String)

    a file: URL (canonical or short form)

Returns:

  • (String)

    the literal path encoded in the URL



52
53
54
55
56
57
# File 'lib/aspera/uri_reader.rb', line 52

def file_path(url)
  Aspera.assert(file?(url)) { "use format: #{file_url('<path>')}" }
  # Strip canonical prefix "file:///" first (covers relative and absolute canonical forms).
  # If absent, strip only the short "file:" prefix.
  return url.start_with?(SCHEME_FILE_PFX2) ? url.delete_prefix(SCHEME_FILE_PFX2) : url.delete_prefix(SCHEME_FILE_PFX1)
end

.file_url(path) ⇒ String

Build a file: URL from path. A relative path yields file:///path; an absolute path yields file:////path.

Parameters:

  • path (String)

    relative or absolute file-system path

Returns:

  • (String)

    corresponding file: URL



43
44
45
# File 'lib/aspera/uri_reader.rb', line 43

def file_url(path)
  return "#{SCHEME_FILE_PFX2}#{path}"
end

.read(uri_to_read) ⇒ Object

Read content from a URI and return it as a String. Supported schemes: http, https, data, file, and bare paths (no scheme). For file: URLs the path is extracted via file_path to respect the module convention (see module-level documentation). Ruby's URI parser is not used for file: URLs because it interprets the three-slash prefix differently (it always produces an absolute path). Bare paths (no scheme) are passed to File.read directly; leading /~/, /./, /../ are expanded via File.expand_path after stripping the synthetic leading slash added by URI.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/aspera/uri_reader.rb', line 67

def read(uri_to_read)
  # Handle file: URLs directly to honour the file:///relative vs file:////absolute convention.
  return File.read(file_path(uri_to_read)) if file?(uri_to_read)
  uri = URI.parse(uri_to_read)
  case uri.scheme
  when 'http', 'https'
    return Rest.new(base_url: uri_to_read, redirect_max: 5).read(nil, headers: {'Accept' => '*/*'})
  when 'data'
    , encoded_data = uri.opaque.split(',', 2)
    if .end_with?(';base64')
      Base64.decode64(encoded_data)
    else
      URI.decode_www_form_component(encoded_data)
    end
  when NilClass
    local_file_path = uri.path
    Aspera.assert(!local_file_path.nil?, type: Error) { 'URL shall have a path, check syntax' }
    local_file_path = File.expand_path(local_file_path.gsub(%r{^/}, '')) if %r{^/(~|.|..)/}.match?(local_file_path)
    return File.read(local_file_path)
  else Aspera.error_unexpected_value(uri.scheme) { "scheme for [#{uri_to_read}]" }
  end
end

.read_as_file(url) ⇒ String

Return the local file-system path for the content at url, downloading to a temp file if needed. For file: URLs the path is extracted directly (no download). For data: and http(s): URLs the content is written to a temporary file and its path is returned.

Returns:

  • (String)

    local path to a file containing the URL content



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/aspera/uri_reader.rb', line 94

def read_as_file(url)
  if url.start_with?(SCHEME_FILE_PFX1)
    # file: scheme: extract the literal path encoded in the URL (relative or absolute).
    return file_path(url)
  elsif url.start_with?('data:')
    # download to temp file
    # auto-delete on exit
    temp_file = TempFileManager.instance.new_file_path_global('uri_reader')
    File.write(temp_file, read(url), binmode: true)
    return temp_file
  else
    # download to temp file
    # auto-delete on exit
    temp_file = TempFileManager.instance.new_file_path_global(suffix: File.basename(url))
    Aspera::Rest.new(base_url: url, redirect_max: 3).call(operation: 'GET', save_to: temp_file)
    return temp_file
  end
end