aspera-cli 4.25.0.pre2 → 4.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +3 -0
- data/CONTRIBUTING.md +60 -18
- data/README.md +164 -133
- data/lib/aspera/agent/factory.rb +9 -6
- data/lib/aspera/agent/transferd.rb +4 -4
- data/lib/aspera/api/aoc.rb +33 -24
- data/lib/aspera/api/ats.rb +1 -0
- data/lib/aspera/api/faspex.rb +11 -5
- data/lib/aspera/ascmd.rb +1 -1
- data/lib/aspera/ascp/installation.rb +5 -5
- data/lib/aspera/cli/formatter.rb +15 -62
- data/lib/aspera/cli/manager.rb +8 -42
- data/lib/aspera/cli/plugins/aoc.rb +48 -30
- data/lib/aspera/cli/plugins/ats.rb +30 -36
- data/lib/aspera/cli/plugins/base.rb +6 -6
- data/lib/aspera/cli/plugins/config.rb +5 -4
- data/lib/aspera/cli/plugins/faspex.rb +5 -3
- data/lib/aspera/cli/plugins/faspex5.rb +10 -8
- data/lib/aspera/cli/plugins/faspio.rb +3 -1
- data/lib/aspera/cli/plugins/node.rb +9 -6
- data/lib/aspera/cli/plugins/oauth.rb +12 -11
- data/lib/aspera/cli/plugins/preview.rb +2 -2
- data/lib/aspera/cli/transfer_agent.rb +1 -2
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/command_line_builder.rb +5 -5
- data/lib/aspera/dot_container.rb +108 -0
- data/lib/aspera/id_generator.rb +7 -10
- data/lib/aspera/oauth/base.rb +25 -38
- data/lib/aspera/oauth/factory.rb +5 -6
- data/lib/aspera/oauth/generic.rb +1 -1
- data/lib/aspera/oauth/jwt.rb +1 -1
- data/lib/aspera/oauth/url_json.rb +4 -3
- data/lib/aspera/oauth/web.rb +2 -2
- data/lib/aspera/preview/file_types.rb +1 -1
- data/lib/aspera/rest.rb +5 -2
- data/lib/aspera/ssh.rb +6 -5
- data/lib/aspera/sync/conf.schema.yaml +2 -2
- data/lib/aspera/transfer/parameters.rb +6 -6
- data/lib/aspera/transfer/spec.schema.yaml +3 -3
- data/lib/aspera/transfer/spec_doc.rb +11 -21
- data/lib/aspera/uri_reader.rb +17 -3
- data.tar.gz.sig +0 -0
- metadata +2 -1
- metadata.gz.sig +0 -0
data/lib/aspera/oauth/base.rb
CHANGED
|
@@ -14,50 +14,38 @@ module Aspera
|
|
|
14
14
|
# Bearer Token Usage: https://tools.ietf.org/html/rfc6750
|
|
15
15
|
class Base
|
|
16
16
|
Aspera.require_method!(:create_token)
|
|
17
|
-
# @param
|
|
18
|
-
# @param
|
|
19
|
-
# @param
|
|
20
|
-
# @param
|
|
21
|
-
# @param
|
|
22
|
-
# @param
|
|
23
|
-
# @param token_field [String] Field in result that contains the token
|
|
24
|
-
# @param cache_ids [Array, nil] List of unique identifiers for cache id generation
|
|
17
|
+
# @param params [Hash] Parameters for token creation (client_id, client_secret, scope, etc...)
|
|
18
|
+
# @param use_query [Boolean] Provide parameters in query instead of body
|
|
19
|
+
# @param path_token [String] API end point to create a token from base URL
|
|
20
|
+
# @param token_field [String] Field in result that contains the token
|
|
21
|
+
# @param cache_ids [Array] List of unique identifiers for cache id generation
|
|
22
|
+
# @param **rest_params [Hash] Parameters for REST
|
|
25
23
|
def initialize(
|
|
26
|
-
|
|
27
|
-
client_secret: nil,
|
|
28
|
-
scope: nil,
|
|
24
|
+
params: {},
|
|
29
25
|
use_query: false,
|
|
30
26
|
path_token: 'token',
|
|
31
27
|
token_field: Factory::TOKEN_FIELD,
|
|
32
|
-
cache_ids:
|
|
28
|
+
cache_ids: [],
|
|
33
29
|
**rest_params
|
|
34
30
|
)
|
|
31
|
+
Aspera.assert_type(params, Hash)
|
|
32
|
+
Aspera.assert_type(cache_ids, Array)
|
|
35
33
|
# This is the OAuth API
|
|
36
34
|
@api = Rest.new(**rest_params)
|
|
37
|
-
@
|
|
38
|
-
@token_cache_id = nil
|
|
35
|
+
@params = params.dup.freeze
|
|
39
36
|
@path_token = path_token
|
|
40
37
|
@token_field = token_field
|
|
41
|
-
@client_id = client_id
|
|
42
|
-
@client_secret = client_secret
|
|
43
38
|
@use_query = use_query
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
# TODO: this shall be done in class, using cache_ids
|
|
47
|
-
@base_cache_ids.push(@api.auth_params[:username]) if @api.auth_params.key?(:username)
|
|
48
|
-
@base_cache_ids.compact!
|
|
49
|
-
@base_cache_ids.freeze
|
|
50
|
-
self.scope = scope
|
|
39
|
+
# TODO: :username and :scope shall be done in class, using cache_ids
|
|
40
|
+
@token_cache_id = Factory.cache_id(@api.base_url, self.class, cache_ids, rest_params[:username], @params[:scope])
|
|
51
41
|
end
|
|
52
42
|
|
|
53
|
-
#
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
attr_reader :scope, :api, :path_token, :client_id
|
|
43
|
+
# The OAuth API Object
|
|
44
|
+
attr_reader :api
|
|
45
|
+
# Sub path to generate token
|
|
46
|
+
attr_reader :path_token
|
|
47
|
+
# Parameters to generate token
|
|
48
|
+
attr_reader :params
|
|
61
49
|
|
|
62
50
|
# Helper method to create token as per RFC
|
|
63
51
|
# @return [HTTPResponse]
|
|
@@ -68,17 +56,16 @@ module Aspera
|
|
|
68
56
|
return @api.create(@path_token, creation_params, content_type: Rest::MIME_WWW, ret: :resp)
|
|
69
57
|
end
|
|
70
58
|
|
|
59
|
+
# Create base parameters for token creation calls
|
|
71
60
|
# @param add_secret [Boolean] Add secret in default call parameters
|
|
72
61
|
# @return [Hash] Optional general parameters
|
|
73
|
-
def
|
|
74
|
-
call_params =
|
|
75
|
-
call_params
|
|
76
|
-
call_params[:client_id] = @client_id unless @client_id.nil?
|
|
77
|
-
call_params[:client_secret] = @client_secret unless !add_secret || @client_id.nil? || @client_secret.nil?
|
|
62
|
+
def base_params(add_secret: false)
|
|
63
|
+
call_params = @params.dup
|
|
64
|
+
call_params.delete(:client_secret) unless add_secret
|
|
78
65
|
return call_params
|
|
79
66
|
end
|
|
80
67
|
|
|
81
|
-
# @return value suitable for Authorization header
|
|
68
|
+
# @return [String] value suitable for Authorization header
|
|
82
69
|
def authorization(**kwargs)
|
|
83
70
|
return OAuth::Factory.bearer_authorization(token(**kwargs))
|
|
84
71
|
end
|
|
@@ -114,7 +101,7 @@ module Aspera
|
|
|
114
101
|
if !refresh_token.nil?
|
|
115
102
|
Log.log.info{"refresh token=[#{refresh_token}]".bg_green}
|
|
116
103
|
begin
|
|
117
|
-
http = create_token_call(
|
|
104
|
+
http = create_token_call(base_params(add_secret: true).merge(grant_type: 'refresh_token', refresh_token: refresh_token))
|
|
118
105
|
# Save only if success
|
|
119
106
|
json_data = http.body
|
|
120
107
|
token_data = JSON.parse(json_data)
|
data/lib/aspera/oauth/factory.rb
CHANGED
|
@@ -36,14 +36,13 @@ module Aspera
|
|
|
36
36
|
return authorization[SPACE_BEARER_AUTH_SCHEME.length..-1]
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
+
# Generate a unique cache id for a token creator
|
|
40
|
+
# @param url [String] Base URL of the OAuth server
|
|
41
|
+
# @param creator_class [Class] Class of the token creator
|
|
42
|
+
# @param params [Array] List of parameters (can be nested) to uniquely identify the token
|
|
39
43
|
# @return a unique cache identifier
|
|
40
44
|
def cache_id(url, creator_class, *params)
|
|
41
|
-
return IdGenerator.from_list(
|
|
42
|
-
PERSIST_CATEGORY_TOKEN,
|
|
43
|
-
url,
|
|
44
|
-
Factory.class_to_id(creator_class)
|
|
45
|
-
] +
|
|
46
|
-
params)
|
|
45
|
+
return IdGenerator.from_list(PERSIST_CATEGORY_TOKEN, url, Factory.class_to_id(creator_class), params)
|
|
47
46
|
end
|
|
48
47
|
|
|
49
48
|
# @return snake version of class name
|
data/lib/aspera/oauth/generic.rb
CHANGED
data/lib/aspera/oauth/jwt.rb
CHANGED
|
@@ -61,7 +61,7 @@ module Aspera
|
|
|
61
61
|
Log.log.debug{"private=[#{@private_key_obj}]"}
|
|
62
62
|
assertion = JWT.encode(jwt_payload, @private_key_obj, 'RS256', @headers)
|
|
63
63
|
Log.log.debug{"assertion=[#{assertion}]"}
|
|
64
|
-
return create_token_call(
|
|
64
|
+
return create_token_call(base_params.merge(grant_type: GRANT_TYPE, assertion: assertion))
|
|
65
65
|
end
|
|
66
66
|
end
|
|
67
67
|
Factory.instance.register_token_creator(Jwt)
|
|
@@ -6,8 +6,9 @@ module Aspera
|
|
|
6
6
|
module OAuth
|
|
7
7
|
# This class is used to create a token using a JSON body and a URL
|
|
8
8
|
class UrlJson < Base
|
|
9
|
-
# @param url
|
|
10
|
-
# @param json
|
|
9
|
+
# @param url [Hash] Query parameters to send
|
|
10
|
+
# @param json [Hash] Body parameters to send as JSON
|
|
11
|
+
# @param generic_params [Hash] Generic parameters for OAuth::Base
|
|
11
12
|
def initialize(
|
|
12
13
|
url:,
|
|
13
14
|
json:,
|
|
@@ -22,7 +23,7 @@ module Aspera
|
|
|
22
23
|
api.call(
|
|
23
24
|
operation: 'POST',
|
|
24
25
|
subpath: path_token,
|
|
25
|
-
query: @query.merge(scope: scope), # scope is here because it may change over time (node)
|
|
26
|
+
query: @query.merge(scope: params[:scope]), # scope is here because it may change over time (node)
|
|
26
27
|
content_type: Rest::MIME_JSON,
|
|
27
28
|
body: @body,
|
|
28
29
|
headers: {'Accept' => Rest::MIME_JSON},
|
data/lib/aspera/oauth/web.rb
CHANGED
|
@@ -32,7 +32,7 @@ module Aspera
|
|
|
32
32
|
random_state = SecureRandom.uuid
|
|
33
33
|
login_page_url = Rest.build_uri(
|
|
34
34
|
"#{api.base_url}/#{@path_authorize}",
|
|
35
|
-
|
|
35
|
+
base_params.merge(response_type: 'code', redirect_uri: @redirect_uri, state: random_state)
|
|
36
36
|
)
|
|
37
37
|
# here, we need a human to authorize on a web page
|
|
38
38
|
Log.log.info{"login_page_url=#{login_page_url}".bg_red.gray}
|
|
@@ -44,7 +44,7 @@ module Aspera
|
|
|
44
44
|
received_params = web_server.received_request
|
|
45
45
|
Aspera.assert(random_state.eql?(received_params['state'])){'wrong received state'}
|
|
46
46
|
# exchange code for token
|
|
47
|
-
return create_token_call(
|
|
47
|
+
return create_token_call(base_params(add_secret: true).merge(
|
|
48
48
|
grant_type: 'authorization_code',
|
|
49
49
|
code: received_params['code'],
|
|
50
50
|
redirect_uri: @redirect_uri
|
|
@@ -53,7 +53,7 @@ module Aspera
|
|
|
53
53
|
|
|
54
54
|
private_constant :SUPPORTED_MIME_TYPES
|
|
55
55
|
|
|
56
|
-
# @attr use_mimemagic [
|
|
56
|
+
# @attr use_mimemagic [Boolean] `true` to use mimemagic to determine real mime type based on file content
|
|
57
57
|
attr_accessor :use_mimemagic
|
|
58
58
|
|
|
59
59
|
def initialize
|
data/lib/aspera/rest.rb
CHANGED
|
@@ -307,9 +307,12 @@ module Aspera
|
|
|
307
307
|
# @param body [Hash, String] body parameters
|
|
308
308
|
# @param headers [Hash] additional headers (override Content-Type)
|
|
309
309
|
# @param save_to_file [String, nil](filepath)
|
|
310
|
-
# @param exception [
|
|
310
|
+
# @param exception [Boolean] `true`, error raise exception
|
|
311
311
|
# @param ret [:data, :resp, :both] Tell to return only data, only http response, or both
|
|
312
|
-
# @return [
|
|
312
|
+
# @return [(HTTPResponse,Hash)] If ret is :both
|
|
313
|
+
# @return [HTTPResponse] If ret is :resp
|
|
314
|
+
# @return [Hash] If ret is :data
|
|
315
|
+
# @raise [RestCallError] on error if `exception` is true
|
|
313
316
|
def call(
|
|
314
317
|
operation:,
|
|
315
318
|
subpath: nil,
|
data/lib/aspera/ssh.rb
CHANGED
|
@@ -35,16 +35,17 @@ module Aspera
|
|
|
35
35
|
# ssh_options: same as Net::SSH.start
|
|
36
36
|
# see: https://net-ssh.github.io/net-ssh/classes/Net/SSH.html#method-c-start
|
|
37
37
|
def initialize(host, username, ssh_options)
|
|
38
|
-
Log.log.debug{"ssh:#{username}@#{host}"}
|
|
39
|
-
Log.log.debug{"ssh_options:#{ssh_options}"}
|
|
40
38
|
Aspera.assert_type(host, String)
|
|
41
39
|
Aspera.assert_type(username, String)
|
|
42
40
|
Aspera.assert_type(ssh_options, Hash)
|
|
43
|
-
ssh_options[:use_agent] = false unless ssh_options.key?(:use_agent)
|
|
44
41
|
@host = host
|
|
45
42
|
@username = username
|
|
46
|
-
@ssh_options = ssh_options
|
|
47
|
-
@ssh_options[:logger] = Log.log
|
|
43
|
+
@ssh_options = ssh_options.dup
|
|
44
|
+
@ssh_options[:logger] = Log.log unless @ssh_options.key?(:logger)
|
|
45
|
+
@ssh_options[:verbose] = :warn unless @ssh_options.key?(:verbose)
|
|
46
|
+
@ssh_options[:use_agent] = false unless @ssh_options.key?(:use_agent)
|
|
47
|
+
Log.log.debug{"ssh:#{@username}@#{@host}"}
|
|
48
|
+
Log.dump(:ssh_options, @ssh_options)
|
|
48
49
|
end
|
|
49
50
|
|
|
50
51
|
# Anything on stderr raises an exception
|
|
@@ -4,8 +4,8 @@ description: Async session description, identical to `asyncs` Node API.
|
|
|
4
4
|
$comment: >-
|
|
5
5
|
This is a YAML version of the original JSON schema from asyncs API.
|
|
6
6
|
It is modified with special `x-` fields.
|
|
7
|
-
x-ts-name [
|
|
8
|
-
x-ts-convert [String]
|
|
7
|
+
x-ts-name [Boolean,String] `true` if same name in transfer spec, else real name in transfer spec
|
|
8
|
+
x-ts-convert [String] Name of methods to convert value from transfer spec to `conf`
|
|
9
9
|
`x-` fields are also documented in `command_line_builder.rb`
|
|
10
10
|
type: object
|
|
11
11
|
required:
|
|
@@ -45,12 +45,12 @@ module Aspera
|
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
-
# @param job_spec [Hash]
|
|
49
|
-
# @param ascp_args [Array]
|
|
50
|
-
# @param quiet [
|
|
51
|
-
# @param trusted_certs [Array]
|
|
52
|
-
# @param client_ssh_key [
|
|
53
|
-
# @param check_ignore_cb [Proc]
|
|
48
|
+
# @param job_spec [Hash] Transfer spec
|
|
49
|
+
# @param ascp_args [Array] Other ascp args
|
|
50
|
+
# @param quiet [Boolean] Remove ascp output
|
|
51
|
+
# @param trusted_certs [Array] Trusted certificates
|
|
52
|
+
# @param client_ssh_key [:rsa,:dsa] :rsa or :dsa
|
|
53
|
+
# @param check_ignore_cb [Proc] Callback
|
|
54
54
|
def initialize(
|
|
55
55
|
job_spec,
|
|
56
56
|
ascp_args: nil,
|
|
@@ -7,8 +7,8 @@ $comment: >-
|
|
|
7
7
|
The following extensions are used for mapping to ascp arguments.
|
|
8
8
|
x-cli-envvar [String] Name of env var
|
|
9
9
|
x-cli-option [String] Command line option (starts with "-"), or `true`: same as ts, or `false`: not an option
|
|
10
|
-
x-cli-switch [
|
|
11
|
-
x-cli-special [
|
|
10
|
+
x-cli-switch [Boolean] `true` if option has no arg, else by default option has a value
|
|
11
|
+
x-cli-special [Boolean] `true` if not anaged by command line generator (special handling: option or argument)
|
|
12
12
|
x-cli-convert [String,Hash] Method name for Convert object or Conversion Hash for enum: ts to arg
|
|
13
13
|
x-agents [Array] Supported agents (for doc only), if not specified: all
|
|
14
14
|
x-deprecation [String] Deprecation message for doc
|
|
@@ -106,7 +106,7 @@ properties:
|
|
|
106
106
|
delete_source:
|
|
107
107
|
$comment: "TODO: implement"
|
|
108
108
|
description: >-
|
|
109
|
-
Remove
|
|
109
|
+
Remove transferred source files after transfer success.
|
|
110
110
|
Equivalent to `remove_after_transfer` + `remove_empty_directories` + `remove_empty_source_directory`.
|
|
111
111
|
Take precedence over those.
|
|
112
112
|
type: boolean
|
|
@@ -8,20 +8,14 @@ module Aspera
|
|
|
8
8
|
# Generate documentation from Schema, for Transfer Spec, or async Conf spec
|
|
9
9
|
class SpecDoc
|
|
10
10
|
class << self
|
|
11
|
-
#
|
|
12
|
-
def agent_to_short(agent_sym)
|
|
13
|
-
agent_sym.to_sym.eql?(:direct) ? :a : agent_sym.to_s[0].to_sym
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# @param formatter [Cli::Formatter] Formatter to use, methods: markdown, tick, check_row
|
|
11
|
+
# @param formatter [Cli::Formatter] Formatter to use, methods: markdown_text, tick, check_row
|
|
17
12
|
# @param include_option [Boolean] `true` : include CLI options
|
|
18
13
|
# @param agent_columns [Boolean] `true` : include agents columns
|
|
19
14
|
# @param schema [Hash] The JSON spec
|
|
20
15
|
# @return [Array] a table suitable to display in manual
|
|
21
16
|
def man_table(formatter, include_option: false, agent_columns: true, schema: Spec::SCHEMA)
|
|
22
|
-
col_local = agent_to_short(:direct)
|
|
23
17
|
cols = %i[name type description]
|
|
24
|
-
cols.insert(-2, *
|
|
18
|
+
cols.insert(-2, *Agent::Factory::ALL.values.map{ |i| i[:short]}.sort) if agent_columns
|
|
25
19
|
rows = []
|
|
26
20
|
schema['properties'].each do |name, info|
|
|
27
21
|
rows.concat(man_table(formatter, include_option: include_option, agent_columns: agent_columns, schema: info).last.map{ |h| h.merge(name: "#{name}.#{h[:name]}")}) if info['type'].eql?('object') && info['properties']
|
|
@@ -35,25 +29,25 @@ module Aspera
|
|
|
35
29
|
# Render Markdown formatting and split lines
|
|
36
30
|
columns[:description] =
|
|
37
31
|
info['description']
|
|
38
|
-
.gsub(Markdown::FORMATS){formatter.
|
|
32
|
+
.gsub(Markdown::FORMATS){formatter.markdown_text(Regexp.last_match)}
|
|
39
33
|
.split("\n") if info.key?('description')
|
|
40
34
|
columns[:description].unshift("DEPRECATED: #{info['x-deprecation']}") if info.key?('x-deprecation')
|
|
41
35
|
# Add flags for supported agents in doc
|
|
42
36
|
agents = []
|
|
43
|
-
|
|
44
|
-
agents.push(
|
|
37
|
+
Agent::Factory::ALL.each_key do |sym|
|
|
38
|
+
agents.push(sym) if info['x-agents'].nil? || info['x-agents'].include?(sym.to_s)
|
|
45
39
|
end
|
|
46
|
-
Aspera.assert(agents.include?(
|
|
40
|
+
Aspera.assert(agents.include?(:direct)){"#{name}: x-cli-option requires agent direct (or nil)"} if info['x-cli-option']
|
|
47
41
|
if agent_columns
|
|
48
|
-
|
|
49
|
-
columns[
|
|
42
|
+
Agent::Factory::ALL.each do |sym, names|
|
|
43
|
+
columns[names[:short]] = formatter.tick(agents.include?(sym))
|
|
50
44
|
end
|
|
51
45
|
else
|
|
52
|
-
columns[:description].push("(#{agents.map
|
|
46
|
+
columns[:description].push("(#{agents.map{ |i| Agent::Factory::ALL[i][:short].to_s.upcase}.sort.join(', ')})") unless agents.length.eql?(Agent::Factory::ALL.length)
|
|
53
47
|
end
|
|
54
48
|
# Only keep lines that are usable in supported agents
|
|
55
49
|
next false if agents.empty?
|
|
56
|
-
columns[:description].push("Allowed values: #{info['enum'].map{ |v| formatter.
|
|
50
|
+
columns[:description].push("Allowed values: #{info['enum'].map{ |v| formatter.markdown_text("`#{v}`")}.join(', ')}") if info.key?('enum')
|
|
57
51
|
if include_option
|
|
58
52
|
envvar_prefix = ''
|
|
59
53
|
cli_option =
|
|
@@ -70,17 +64,13 @@ module Aspera
|
|
|
70
64
|
"#{info['x-cli-option']}#{sep}#{"(#{conversion_tag})" if conversion_tag}#{arg_type}"
|
|
71
65
|
end
|
|
72
66
|
short = info.key?('x-cli-short') ? "(#{info['x-cli-short']})" : nil
|
|
73
|
-
columns[:description].push("(#{'special:' if info['x-cli-special']}#{envvar_prefix}#{formatter.
|
|
67
|
+
columns[:description].push("(#{'special:' if info['x-cli-special']}#{envvar_prefix}#{formatter.markdown_text("`#{cli_option}`")})#{short}") if cli_option
|
|
74
68
|
end
|
|
75
69
|
rows.push(formatter.check_row(columns))
|
|
76
70
|
end
|
|
77
71
|
[cols, rows.sort_by{ |i| i[:name]}]
|
|
78
72
|
end
|
|
79
73
|
end
|
|
80
|
-
# Agents shown in manual for parameters (sub list)
|
|
81
|
-
AGENT_LIST = Agent::Factory.instance.list.map do |agent_sym|
|
|
82
|
-
[agent_sym, agent_sym.to_s.capitalize, agent_to_short(agent_sym)]
|
|
83
|
-
end.sort_by(&:last).freeze
|
|
84
74
|
end
|
|
85
75
|
end
|
|
86
76
|
end
|
data/lib/aspera/uri_reader.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'uri'
|
|
4
|
+
require 'base64'
|
|
4
5
|
require 'aspera/assert'
|
|
5
6
|
require 'aspera/rest'
|
|
6
7
|
require 'aspera/temp_file_manager'
|
|
@@ -19,6 +20,13 @@ module Aspera
|
|
|
19
20
|
case uri.scheme
|
|
20
21
|
when 'http', 'https'
|
|
21
22
|
return Rest.new(base_url: uri_to_read, redirect_max: 5).read(nil, headers: {'Accept' => '*/*'})
|
|
23
|
+
when 'data'
|
|
24
|
+
metadata, encoded_data = uri.opaque.split(',', 2)
|
|
25
|
+
if metadata.end_with?(';base64')
|
|
26
|
+
Base64.decode64(encoded_data)
|
|
27
|
+
else
|
|
28
|
+
URI.decode_www_form_component(encoded_data)
|
|
29
|
+
end
|
|
22
30
|
when SCHEME_FILE, NilClass
|
|
23
31
|
local_file_path = uri.path
|
|
24
32
|
raise Error, 'URL shall have a path, check syntax' if local_file_path.nil?
|
|
@@ -35,12 +43,18 @@ module Aspera
|
|
|
35
43
|
# require specific file scheme: the path part is "relative", or absolute if there are 4 slash
|
|
36
44
|
raise "use format: #{SCHEME_FILE_PFX2}<path>" unless url.start_with?(SCHEME_FILE_PFX2)
|
|
37
45
|
return File.expand_path(url[SCHEME_FILE_PFX2.length..-1])
|
|
46
|
+
elsif url.start_with?('data:')
|
|
47
|
+
# download to temp file
|
|
48
|
+
# auto-delete on exit
|
|
49
|
+
temp_file = TempFileManager.instance.new_file_path_global('uri_reader')
|
|
50
|
+
File.write(temp_file, read(url), binmode: true)
|
|
51
|
+
return temp_file
|
|
38
52
|
else
|
|
39
53
|
# download to temp file
|
|
40
54
|
# auto-delete on exit
|
|
41
|
-
|
|
42
|
-
Aspera::Rest.new(base_url: url, redirect_max: 3).call(operation: 'GET', save_to_file:
|
|
43
|
-
return
|
|
55
|
+
temp_file = TempFileManager.instance.new_file_path_global(suffix: File.basename(url))
|
|
56
|
+
Aspera::Rest.new(base_url: url, redirect_max: 3).call(operation: 'GET', save_to_file: temp_file)
|
|
57
|
+
return temp_file
|
|
44
58
|
end
|
|
45
59
|
end
|
|
46
60
|
end
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: aspera-cli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.25.0
|
|
4
|
+
version: 4.25.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Laurent Martin
|
|
@@ -367,6 +367,7 @@ files:
|
|
|
367
367
|
- lib/aspera/data/5
|
|
368
368
|
- lib/aspera/data/6
|
|
369
369
|
- lib/aspera/data_repository.rb
|
|
370
|
+
- lib/aspera/dot_container.rb
|
|
370
371
|
- lib/aspera/environment.rb
|
|
371
372
|
- lib/aspera/faspex_gw.rb
|
|
372
373
|
- lib/aspera/faspex_postproc.rb
|
metadata.gz.sig
CHANGED
|
Binary file
|