rubytus 0.1.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.
- 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
|