rubytus 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.editorconfig +10 -0
- data/.gitignore +18 -0
- data/.simplecov +6 -0
- data/.travis.yml +8 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +20 -0
- data/README.md +57 -0
- data/Rakefile +10 -0
- data/bin/rubytusd +13 -0
- data/lib/rubytus.rb +3 -0
- data/lib/rubytus/api.rb +79 -0
- data/lib/rubytus/command.rb +72 -0
- data/lib/rubytus/common.rb +11 -0
- data/lib/rubytus/constants.rb +33 -0
- data/lib/rubytus/error.rb +4 -0
- data/lib/rubytus/helpers.rb +82 -0
- data/lib/rubytus/info.rb +31 -0
- data/lib/rubytus/middlewares/storage_barrier.rb +36 -0
- data/lib/rubytus/middlewares/tus_barrier.rb +36 -0
- data/lib/rubytus/request.rb +102 -0
- data/lib/rubytus/storage.rb +117 -0
- data/lib/rubytus/version.rb +3 -0
- data/rubytus.gemspec +31 -0
- data/test/rubytus/test_command.rb +249 -0
- data/test/rubytus/test_command_runner.rb +123 -0
- data/test/rubytus/test_helpers.rb +57 -0
- data/test/rubytus/test_storage.rb +94 -0
- data/test/rubytus/test_version.rb +7 -0
- data/test/test_helper.rb +79 -0
- metadata +227 -0
data/lib/rubytus/info.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Rubytus
|
4
|
+
class Info < Hash
|
5
|
+
def initialize(args = {})
|
6
|
+
self['Offset'] = args[:offset] || 0
|
7
|
+
self['FinalLength'] = args[:final_length] || 0
|
8
|
+
self['Meta'] = args[:meta] || nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def offset=(value)
|
12
|
+
self['Offset'] = value.to_i
|
13
|
+
end
|
14
|
+
|
15
|
+
def offset
|
16
|
+
self['Offset']
|
17
|
+
end
|
18
|
+
|
19
|
+
def final_length=(value)
|
20
|
+
self['FinalLength'] = value.to_i
|
21
|
+
end
|
22
|
+
|
23
|
+
def final_length
|
24
|
+
self['FinalLength']
|
25
|
+
end
|
26
|
+
|
27
|
+
def remaining_length
|
28
|
+
final_length - offset
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'rubytus/error'
|
2
|
+
|
3
|
+
module Rubytus
|
4
|
+
module Middlewares
|
5
|
+
class StorageBarrier
|
6
|
+
include Rubytus::Constants
|
7
|
+
include Goliath::Rack::AsyncMiddleware
|
8
|
+
|
9
|
+
def post_process(env, status, headers, body)
|
10
|
+
status = STATUS_OK
|
11
|
+
action = env['api.action']
|
12
|
+
storage = env['api.options'][:storage]
|
13
|
+
|
14
|
+
begin
|
15
|
+
case action
|
16
|
+
when :create
|
17
|
+
status = STATUS_CREATED
|
18
|
+
headers['Location'] = env['api.resource_url']
|
19
|
+
storage.create_file(env['api.uid'], env['api.final_length'])
|
20
|
+
|
21
|
+
when :head
|
22
|
+
info = storage.read_info(env['api.uid'])
|
23
|
+
headers['Offset'] = info.offset.to_s
|
24
|
+
|
25
|
+
when :get
|
26
|
+
body = storage.read_file(env['api.uid'])
|
27
|
+
end
|
28
|
+
rescue PermissionError => e
|
29
|
+
raise Goliath::Validation::Error.new(500, e.message)
|
30
|
+
end
|
31
|
+
|
32
|
+
[status, headers, body]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Rubytus
|
2
|
+
module Middlewares
|
3
|
+
class TusBarrier
|
4
|
+
include Rubytus::Constants
|
5
|
+
include Goliath::Rack::AsyncMiddleware
|
6
|
+
|
7
|
+
def post_process(env, status, headers, body)
|
8
|
+
request = Rubytus::Request.new(env)
|
9
|
+
|
10
|
+
if request.collection?
|
11
|
+
unless request.options? || request.post?
|
12
|
+
status = STATUS_NOT_ALLOWED
|
13
|
+
body = "#{request.request_method} used against file creation url. Only POST is allowed."
|
14
|
+
headers['Allow'] = 'POST'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
if request.resource?
|
19
|
+
unless request.options? || request.head? || request.patch? || request.get?
|
20
|
+
status = STATUS_NOT_ALLOWED
|
21
|
+
allowed = 'HEAD,PATCH'
|
22
|
+
body = "#{request.request_method} used against file creation url. Allowed: #{allowed}"
|
23
|
+
headers['Allow'] = allowed
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
if request.unknown?
|
28
|
+
status = STATUS_NOT_FOUND
|
29
|
+
body = "Unknown url: #{request.path_info} - does not match file pattern"
|
30
|
+
end
|
31
|
+
|
32
|
+
[status, headers, body]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'rubytus/constants'
|
2
|
+
require 'rubytus/common'
|
3
|
+
|
4
|
+
module Rubytus
|
5
|
+
class Request
|
6
|
+
include Rubytus::Constants
|
7
|
+
include Rubytus::Common
|
8
|
+
|
9
|
+
def initialize(env)
|
10
|
+
@env = env
|
11
|
+
end
|
12
|
+
|
13
|
+
def get?; request_method == 'GET'; end
|
14
|
+
def post?; request_method == 'POST'; end
|
15
|
+
def head?; request_method == 'HEAD'; end
|
16
|
+
def patch?; request_method == 'PATCH'; end
|
17
|
+
def options?; request_method == 'OPTIONS'; end
|
18
|
+
|
19
|
+
def resumable_content_type?
|
20
|
+
content_type == RESUMABLE_CONTENT_TYPE
|
21
|
+
end
|
22
|
+
|
23
|
+
def unknown?
|
24
|
+
!collection? && !resource?
|
25
|
+
end
|
26
|
+
|
27
|
+
def collection?
|
28
|
+
path_info.chomp('/') == base_path.chomp('/')
|
29
|
+
end
|
30
|
+
|
31
|
+
def resource?
|
32
|
+
!!(resource_uid =~ RESOURCE_UID_REGEX)
|
33
|
+
end
|
34
|
+
|
35
|
+
def resource_uid
|
36
|
+
rpath = path_info.dup
|
37
|
+
rpath.slice!(base_path)
|
38
|
+
rpath
|
39
|
+
end
|
40
|
+
|
41
|
+
def resource_url(uid)
|
42
|
+
"#{scheme}://#{host_with_port}#{base_path}#{uid}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def final_length
|
46
|
+
fetch_positive_header('HTTP_FINAL_LENGTH')
|
47
|
+
end
|
48
|
+
|
49
|
+
def offset
|
50
|
+
fetch_positive_header('HTTP_OFFSET')
|
51
|
+
end
|
52
|
+
|
53
|
+
def base_path
|
54
|
+
@env['api.options'][:base_path]
|
55
|
+
end
|
56
|
+
|
57
|
+
def scheme
|
58
|
+
@env['HTTPS'] ? 'https' : 'http'
|
59
|
+
end
|
60
|
+
|
61
|
+
def path_info
|
62
|
+
@env['PATH_INFO']
|
63
|
+
end
|
64
|
+
|
65
|
+
def host_with_port
|
66
|
+
@env['HTTP_HOST'] || "#{@env['SERVER_NAME']}:#{@env['SERVER_PORT']}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def request_method
|
70
|
+
@env['REQUEST_METHOD']
|
71
|
+
end
|
72
|
+
|
73
|
+
def content_type
|
74
|
+
@env['CONTENT_TYPE']
|
75
|
+
end
|
76
|
+
|
77
|
+
def content_length
|
78
|
+
@env['CONTENT_LENGTH'].to_i
|
79
|
+
end
|
80
|
+
|
81
|
+
protected
|
82
|
+
def fetch_positive_header(header_name)
|
83
|
+
header_val = @env[header_name] || ''
|
84
|
+
value = header_val.to_i
|
85
|
+
header_orig = normalize_header_name(header_name)
|
86
|
+
|
87
|
+
if header_val.empty?
|
88
|
+
error!(STATUS_BAD_REQUEST, "#{header_orig} header must not be empty")
|
89
|
+
end
|
90
|
+
|
91
|
+
if value < 0
|
92
|
+
error!(STATUS_BAD_REQUEST, "#{header_orig} header must be > 0")
|
93
|
+
end
|
94
|
+
|
95
|
+
value
|
96
|
+
end
|
97
|
+
|
98
|
+
def normalize_header_name(header_name)
|
99
|
+
header_name.gsub('HTTP_', '').split('_').map(&:capitalize).join('-')
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'rubytus/info'
|
3
|
+
require 'rubytus/error'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
module Rubytus
|
7
|
+
module StorageHelper
|
8
|
+
def validates_data_dir(data_dir)
|
9
|
+
if Pathname.new(data_dir).relative?
|
10
|
+
data_dir = File.join(ENV['PWD'], data_dir)
|
11
|
+
end
|
12
|
+
|
13
|
+
begin
|
14
|
+
unless File.directory?(data_dir)
|
15
|
+
Dir.mkdir(data_dir)
|
16
|
+
end
|
17
|
+
rescue SystemCallError => _
|
18
|
+
raise PermissionError, "Couldn't create `data_dir` in #{data_dir}"
|
19
|
+
end
|
20
|
+
|
21
|
+
unless File.world_writable?(data_dir)
|
22
|
+
begin
|
23
|
+
File.chmod(0777, data_dir)
|
24
|
+
rescue Errno::EPERM
|
25
|
+
raise PermissionError, "Couldn't make `data_dir` in #{data_dir} writable"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
data_dir
|
30
|
+
end
|
31
|
+
|
32
|
+
def file_path(uid)
|
33
|
+
File.join(@options[:data_dir], "#{uid}.bin")
|
34
|
+
end
|
35
|
+
|
36
|
+
def info_path(uid)
|
37
|
+
File.join(@options[:data_dir], "#{uid}.info")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Storage
|
42
|
+
include StorageHelper
|
43
|
+
|
44
|
+
def initialize(options)
|
45
|
+
@options = options
|
46
|
+
end
|
47
|
+
|
48
|
+
def create_file(uid, final_length)
|
49
|
+
fpath = file_path(uid)
|
50
|
+
ipath = info_path(uid)
|
51
|
+
info = Rubytus::Info.new
|
52
|
+
info.final_length = final_length
|
53
|
+
|
54
|
+
begin
|
55
|
+
File.open(fpath, 'w') {}
|
56
|
+
File.open(ipath, 'w') do |f|
|
57
|
+
f.write(info.to_json)
|
58
|
+
end
|
59
|
+
rescue SystemCallError => e
|
60
|
+
raise(PermissionError, e.message) if e.class.name.start_with?('Errno::')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def read_file(uid)
|
65
|
+
fpath = file_path(uid)
|
66
|
+
|
67
|
+
begin
|
68
|
+
f = File.open(fpath, 'rb')
|
69
|
+
f.read
|
70
|
+
rescue SystemCallError => e
|
71
|
+
raise(PermissionError, e.message) if e.class.name.start_with?('Errno::')
|
72
|
+
ensure
|
73
|
+
f.close unless f.nil?
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def patch_file(uid, data, offset = nil)
|
78
|
+
fpath = file_path(uid)
|
79
|
+
begin
|
80
|
+
f = File.open(fpath, 'r+b')
|
81
|
+
f.sync = true
|
82
|
+
f.seek(offset) unless offset.nil?
|
83
|
+
f.write(data)
|
84
|
+
size = f.size
|
85
|
+
f.close
|
86
|
+
update_info(uid, size)
|
87
|
+
rescue SystemCallError => e
|
88
|
+
raise(PermissionError, e.message) if e.class.name.start_with?('Errno::')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def read_info(uid)
|
93
|
+
ipath = info_path(uid)
|
94
|
+
|
95
|
+
begin
|
96
|
+
data = File.open(ipath, 'r') { |f| f.read }
|
97
|
+
JSON.parse(data, :object_class => Rubytus::Info)
|
98
|
+
rescue SystemCallError => e
|
99
|
+
raise(PermissionError, e.message) if e.class.name.start_with?('Errno::')
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def update_info(uid, offset)
|
104
|
+
ipath = info_path(uid)
|
105
|
+
info = read_info(uid)
|
106
|
+
info.offset = offset
|
107
|
+
|
108
|
+
begin
|
109
|
+
File.open(ipath, 'w') do |f|
|
110
|
+
f.write(info.to_json)
|
111
|
+
end
|
112
|
+
rescue SystemCallError => e
|
113
|
+
raise(PermissionError, e.message) if e.class.name.start_with?('Errno::')
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
data/rubytus.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rubytus/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "rubytus"
|
8
|
+
spec.version = Rubytus::VERSION
|
9
|
+
spec.authors = ["Alif Rachmawadi"]
|
10
|
+
spec.email = ["subosito@gmail.com"]
|
11
|
+
spec.description = %q{Resumable upload protocol implementation in Ruby}
|
12
|
+
spec.summary = %q{Resumable upload protocol implementation in Ruby}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "minitest"
|
24
|
+
spec.add_development_dependency "rr"
|
25
|
+
spec.add_development_dependency "simplecov"
|
26
|
+
spec.add_development_dependency "em-http-request"
|
27
|
+
spec.add_development_dependency "pry"
|
28
|
+
spec.add_development_dependency "coveralls"
|
29
|
+
|
30
|
+
spec.add_runtime_dependency "goliath", "~> 1.0.3"
|
31
|
+
end
|
@@ -0,0 +1,249 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'rubytus/command'
|
3
|
+
require 'rubytus/info'
|
4
|
+
|
5
|
+
class TestRubytusCommand < MiniTest::Test
|
6
|
+
include Rubytus::Mock
|
7
|
+
include Rubytus::StorageHelper
|
8
|
+
include Goliath::TestHelper
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@err = Proc.new { assert false, 'API request failed' }
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_get_request_for_root
|
15
|
+
params = { :path => '/' }
|
16
|
+
|
17
|
+
with_api(Rubytus::Command, default_options) do
|
18
|
+
get_request(params, @err) do |c|
|
19
|
+
assert_equal 404, c.response_header.status
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_options_request_for_collection
|
25
|
+
params = { :path => '/uploads/' }
|
26
|
+
|
27
|
+
with_api(Rubytus::Command, default_options) do
|
28
|
+
options_request(params, @err) do |c|
|
29
|
+
assert_equal 200, c.response_header.status
|
30
|
+
assert_equal '', c.response
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_get_request_for_collection
|
36
|
+
params = { :path => '/uploads/' }
|
37
|
+
|
38
|
+
with_api(Rubytus::Command, default_options) do
|
39
|
+
get_request(params, @err) do |c|
|
40
|
+
assert_equal 405, c.response_header.status
|
41
|
+
assert_equal 'POST', c.response_header['ALLOW']
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_post_request_for_collection_without_final_length
|
47
|
+
params = { :path => '/uploads/' }
|
48
|
+
|
49
|
+
with_api(Rubytus::Command, default_options) do
|
50
|
+
post_request(params, @err) do |c|
|
51
|
+
assert_equal 400, c.response_header.status
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_post_request_for_collection_with_negative_final_length
|
57
|
+
params = {
|
58
|
+
:path => '/uploads/',
|
59
|
+
:head => { 'Final-Length' => '-1'}
|
60
|
+
}
|
61
|
+
|
62
|
+
with_api(Rubytus::Command, default_options) do
|
63
|
+
post_request(params, @err) do |c|
|
64
|
+
assert_equal 400, c.response_header.status
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_post_request_for_collection
|
70
|
+
params = {
|
71
|
+
:path => '/uploads/',
|
72
|
+
:head => { 'Final-Length' => '10' }
|
73
|
+
}
|
74
|
+
|
75
|
+
with_api(Rubytus::Command, default_options) do
|
76
|
+
post_request(params, @err) do |c|
|
77
|
+
assert_equal 201, c.response_header.status
|
78
|
+
assert c.response_header.location
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_put_request_for_resource
|
84
|
+
with_api(Rubytus::Command, default_options) do
|
85
|
+
put_request({ :path => "/uploads/#{uid}" }, @err) do |c|
|
86
|
+
assert_equal 405, c.response_header.status
|
87
|
+
assert_equal 'HEAD,PATCH', c.response_header['ALLOW']
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_patch_request_for_resource_without_valid_content_type
|
93
|
+
params = {
|
94
|
+
:path => "/uploads/#{uid}",
|
95
|
+
:body => 'abc',
|
96
|
+
:head => {
|
97
|
+
'Offset' => '0',
|
98
|
+
'Content-Type' => 'plain/text'
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
with_api(Rubytus::Command, default_options) do
|
103
|
+
patch_request(params, @err) do |c|
|
104
|
+
assert_equal 400, c.response_header.status
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_patch_request_for_resource
|
110
|
+
options = default_options
|
111
|
+
ruid = uid
|
112
|
+
|
113
|
+
validates_data_dir(options[:data_dir])
|
114
|
+
|
115
|
+
storage = Rubytus::Storage.new(options)
|
116
|
+
storage.create_file(ruid, 3)
|
117
|
+
|
118
|
+
params = {
|
119
|
+
:path => "/uploads/#{ruid}",
|
120
|
+
:body => 'abc',
|
121
|
+
:head => {
|
122
|
+
'Offset' => '0',
|
123
|
+
'Content-Type' => 'application/offset+octet-stream'
|
124
|
+
}
|
125
|
+
}
|
126
|
+
|
127
|
+
with_api(Rubytus::Command, options) do
|
128
|
+
patch_request(params, @err) do |c|
|
129
|
+
assert_equal 200, c.response_header.status
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_patch_request_for_resource_exceed_offset
|
135
|
+
ruid = uid
|
136
|
+
info = Rubytus::Info.new(:offset => 0)
|
137
|
+
|
138
|
+
any_instance_of(Rubytus::Storage) do |klass|
|
139
|
+
stub(klass).read_info(ruid) { info }
|
140
|
+
end
|
141
|
+
|
142
|
+
params = {
|
143
|
+
:path => "/uploads/#{ruid}",
|
144
|
+
:body => 'abc',
|
145
|
+
:head => {
|
146
|
+
'Offset' => '3',
|
147
|
+
'Content-Type' => 'application/offset+octet-stream'
|
148
|
+
}
|
149
|
+
}
|
150
|
+
|
151
|
+
with_api(Rubytus::Command, default_options) do
|
152
|
+
patch_request(params, @err) do |c|
|
153
|
+
assert_equal 403, c.response_header.status
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_patch_request_for_resource_exceed_remaining_length
|
159
|
+
ruid = uid
|
160
|
+
info = Rubytus::Info.new(:offset => 0, :final_length => 2)
|
161
|
+
|
162
|
+
any_instance_of(Rubytus::Storage) do |klass|
|
163
|
+
stub(klass).read_info(ruid) { info }
|
164
|
+
end
|
165
|
+
|
166
|
+
params = {
|
167
|
+
:path => "/uploads/#{ruid}",
|
168
|
+
:body => 'abcdef',
|
169
|
+
:head => {
|
170
|
+
'Offset' => '0',
|
171
|
+
'Content-Type' => 'application/offset+octet-stream'
|
172
|
+
}
|
173
|
+
}
|
174
|
+
|
175
|
+
with_api(Rubytus::Command, default_options) do
|
176
|
+
patch_request(params, @err) do |c|
|
177
|
+
assert_equal 403, c.response_header.status
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def test_patch_request_for_resource_failure
|
183
|
+
options = read_only_options
|
184
|
+
params = {
|
185
|
+
:path => "/uploads/#{uid}",
|
186
|
+
:body => 'abc',
|
187
|
+
:head => {
|
188
|
+
'Offset' => '0',
|
189
|
+
'Content-Type' => 'application/offset+octet-stream'
|
190
|
+
}
|
191
|
+
}
|
192
|
+
|
193
|
+
any_instance_of(Rubytus::Command) do |klass|
|
194
|
+
stub(klass).setup { true }
|
195
|
+
stub(klass).storage { Rubytus::Storage.new(options) }
|
196
|
+
end
|
197
|
+
|
198
|
+
with_api(Rubytus::Command, options) do
|
199
|
+
patch_request(params, @err) do |c|
|
200
|
+
assert_equal 500, c.response_header.status
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def test_head_request_for_resource
|
206
|
+
ruid = uid
|
207
|
+
info = Rubytus::Info.new(:offset => 3)
|
208
|
+
|
209
|
+
any_instance_of(Rubytus::Storage) do |klass|
|
210
|
+
stub(klass).read_info(ruid) { info }
|
211
|
+
end
|
212
|
+
|
213
|
+
with_api(Rubytus::Command, default_options) do
|
214
|
+
head_request({ :path => "/uploads/#{ruid}" }, @err) do |c|
|
215
|
+
assert_equal 200, c.response_header.status
|
216
|
+
assert_equal '3', c.response_header['OFFSET']
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def test_get_request_for_resource_failure
|
222
|
+
ruid = uid
|
223
|
+
|
224
|
+
any_instance_of(Rubytus::Storage) do |klass|
|
225
|
+
stub(klass).read_file(ruid) { raise Rubytus::PermissionError }
|
226
|
+
end
|
227
|
+
|
228
|
+
with_api(Rubytus::Command, default_options) do
|
229
|
+
get_request({ :path => "/uploads/#{ruid}" }, @err) do |c|
|
230
|
+
assert_equal 500, c.response_header.status
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_get_request_for_resource
|
236
|
+
ruid = uid
|
237
|
+
|
238
|
+
any_instance_of(Rubytus::Storage) do |klass|
|
239
|
+
stub(klass).read_file(ruid) { 'abc' }
|
240
|
+
end
|
241
|
+
|
242
|
+
with_api(Rubytus::Command, default_options) do
|
243
|
+
get_request({ :path => "/uploads/#{ruid}" }, @err) do |c|
|
244
|
+
assert_equal 200, c.response_header.status
|
245
|
+
assert_equal 'abc', c.response
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|