refile 0.3.0 → 0.4.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
- data/.rubocop.yml +56 -0
- data/.travis.yml +11 -0
- data/Gemfile +1 -1
- data/History.md +15 -0
- data/README.md +41 -5
- data/Rakefile +4 -1
- data/config/locales/en.yml +2 -0
- data/config/routes.rb +4 -2
- data/lib/refile/app.rb +96 -71
- data/lib/refile/attacher.rb +115 -0
- data/lib/refile/attachment/active_record.rb +5 -5
- data/lib/refile/attachment.rb +50 -117
- data/lib/refile/backend/file_system.rb +3 -3
- data/lib/refile/backend/s3.rb +7 -12
- data/lib/refile/file.rb +1 -3
- data/lib/refile/image_processing.rb +6 -3
- data/lib/refile/rails/attachment_helper.rb +18 -21
- data/lib/refile/rails.rb +2 -1
- data/lib/refile/random_hasher.rb +9 -8
- data/lib/refile/signature.rb +16 -0
- data/lib/refile/version.rb +1 -1
- data/lib/refile.rb +59 -1
- data/refile.gemspec +10 -6
- data/spec/refile/app_spec.rb +28 -4
- data/spec/refile/attachment_spec.rb +134 -33
- data/spec/refile/backend_examples.rb +7 -11
- data/spec/refile/features/direct_upload_spec.rb +0 -1
- data/spec/refile/features/normal_upload_spec.rb +21 -0
- data/spec/refile/features/presigned_upload_spec.rb +0 -1
- data/spec/refile/rails/attachment_helper_spec.rb +61 -0
- data/spec/refile/spec_helper.rb +26 -20
- data/spec/refile/test_app/app/controllers/normal_posts_controller.rb +10 -1
- data/spec/refile/test_app/app/controllers/presigned_posts_controller.rb +1 -0
- data/spec/refile/test_app/app/models/post.rb +1 -1
- data/spec/refile/test_app/app/views/normal_posts/index.html +5 -0
- data/spec/refile/test_app/app/views/normal_posts/show.html.erb +2 -0
- data/spec/refile/test_app/config/routes.rb +1 -1
- data/spec/refile/test_app.rb +13 -6
- data/spec/refile_spec.rb +39 -0
- metadata +51 -2
data/lib/refile/attachment.rb
CHANGED
@@ -1,89 +1,5 @@
|
|
1
1
|
module Refile
|
2
2
|
module Attachment
|
3
|
-
# @api private
|
4
|
-
class Attachment
|
5
|
-
attr_reader :record, :name, :cache, :store, :cache_id, :options, :errors
|
6
|
-
attr_accessor :remove
|
7
|
-
|
8
|
-
def initialize(record, name, **options)
|
9
|
-
@record = record
|
10
|
-
@name = name
|
11
|
-
@options = options
|
12
|
-
@cache = Refile.backends.fetch(@options[:cache].to_s)
|
13
|
-
@store = Refile.backends.fetch(@options[:store].to_s)
|
14
|
-
@errors = []
|
15
|
-
end
|
16
|
-
|
17
|
-
def id
|
18
|
-
record.send(:"#{name}_id")
|
19
|
-
end
|
20
|
-
|
21
|
-
def id=(id)
|
22
|
-
record.send(:"#{name}_id=", id)
|
23
|
-
end
|
24
|
-
|
25
|
-
def file
|
26
|
-
if cached?
|
27
|
-
cache.get(cache_id)
|
28
|
-
elsif id and not id == ""
|
29
|
-
store.get(id)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def file=(uploadable)
|
34
|
-
@cache_file = cache.upload(uploadable)
|
35
|
-
@cache_id = @cache_file.id
|
36
|
-
@errors = []
|
37
|
-
rescue Refile::Invalid
|
38
|
-
@errors = [:too_large]
|
39
|
-
raise if @options[:raise_errors]
|
40
|
-
end
|
41
|
-
|
42
|
-
def download(url)
|
43
|
-
if url and not url == ""
|
44
|
-
raw_response = RestClient::Request.new(method: :get, url: url, raw_response: true).execute
|
45
|
-
self.file = raw_response.file
|
46
|
-
end
|
47
|
-
rescue RestClient::Exception
|
48
|
-
@errors = [:download_failed]
|
49
|
-
raise if @options[:raise_errors]
|
50
|
-
end
|
51
|
-
|
52
|
-
def cache_id=(id)
|
53
|
-
@cache_id = id unless @cache_file
|
54
|
-
end
|
55
|
-
|
56
|
-
def store!
|
57
|
-
if remove?
|
58
|
-
delete!
|
59
|
-
elsif cached?
|
60
|
-
file = store.upload(cache.get(cache_id))
|
61
|
-
delete!
|
62
|
-
self.id = file.id
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def delete!
|
67
|
-
if cached?
|
68
|
-
cache.delete(cache_id)
|
69
|
-
@cache_id = nil
|
70
|
-
@cache_file = nil
|
71
|
-
end
|
72
|
-
store.delete(id) if id
|
73
|
-
self.id = nil
|
74
|
-
end
|
75
|
-
|
76
|
-
def remove?
|
77
|
-
remove and remove != "" and remove !~ /\A0|false$\z/
|
78
|
-
end
|
79
|
-
|
80
|
-
private
|
81
|
-
|
82
|
-
def cached?
|
83
|
-
cache_id and not cache_id == ""
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
3
|
# Macro which generates accessors for the given column which make it
|
88
4
|
# possible to upload and retrieve previously uploaded files through the
|
89
5
|
# generated accessors.
|
@@ -92,50 +8,67 @@ module Refile
|
|
92
8
|
# should immediately raise an error, or save the error and defer handling
|
93
9
|
# it until later.
|
94
10
|
#
|
95
|
-
# @param [String] name
|
96
|
-
# @param [#to_s] cache
|
97
|
-
# @param [#to_s] store
|
98
|
-
# @param [true, false] raise_errors
|
99
|
-
|
100
|
-
|
11
|
+
# @param [String] name Name of the column which accessor are generated for
|
12
|
+
# @param [#to_s] cache Name of a backend in +Refile.backends+ to use as transient cache
|
13
|
+
# @param [#to_s] store Name of a backend in +Refile.backends+ to use as permanent store
|
14
|
+
# @param [true, false] raise_errors Whether to raise errors in case an invalid file is assigned
|
15
|
+
# @param [:image, nil] type The type of file that can be uploaded, currently +:image+ is the
|
16
|
+
# only valid value and restricts uploads to JPEG, PNG and GIF images
|
17
|
+
# @param [String, Array<String>, nil] extension Limit the uploaded file to the given extension or list of extensions
|
18
|
+
# @param [String, Array<String>, nil] content_type Limit the uploaded file to the given content type or list of content types
|
19
|
+
# @ignore
|
20
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
21
|
+
def attachment(name, cache: :cache, store: :store, raise_errors: true, type: nil, extension: nil, content_type: nil)
|
22
|
+
mod = Module.new do
|
23
|
+
attacher = :"#{name}_attacher"
|
24
|
+
|
25
|
+
define_method attacher do
|
26
|
+
ivar = :"@#{attacher}"
|
27
|
+
instance_variable_get(ivar) or begin
|
28
|
+
instance_variable_set(ivar, Attacher.new(self, name,
|
29
|
+
cache: cache,
|
30
|
+
store: store,
|
31
|
+
raise_errors: raise_errors,
|
32
|
+
type: type,
|
33
|
+
extension: extension,
|
34
|
+
content_type: content_type
|
35
|
+
))
|
36
|
+
end
|
37
|
+
end
|
101
38
|
|
102
|
-
|
103
|
-
|
104
|
-
instance_variable_get(ivar) or begin
|
105
|
-
instance_variable_set(ivar, Attachment.new(self, name, cache: cache, store: store, raise_errors: raise_errors))
|
39
|
+
define_method "#{name}=" do |uploadable|
|
40
|
+
send(attacher).cache!(uploadable)
|
106
41
|
end
|
107
|
-
end
|
108
42
|
|
109
|
-
|
110
|
-
|
111
|
-
|
43
|
+
define_method name do
|
44
|
+
send(attacher).get
|
45
|
+
end
|
112
46
|
|
113
|
-
|
114
|
-
|
115
|
-
|
47
|
+
define_method "#{name}_cache_id=" do |cache_id|
|
48
|
+
send(attacher).cache_id = cache_id
|
49
|
+
end
|
116
50
|
|
117
|
-
|
118
|
-
|
119
|
-
|
51
|
+
define_method "#{name}_cache_id" do
|
52
|
+
send(attacher).cache_id
|
53
|
+
end
|
120
54
|
|
121
|
-
|
122
|
-
|
123
|
-
|
55
|
+
define_method "remove_#{name}=" do |remove|
|
56
|
+
send(attacher).remove = remove
|
57
|
+
end
|
124
58
|
|
125
|
-
|
126
|
-
|
127
|
-
|
59
|
+
define_method "remove_#{name}" do
|
60
|
+
send(attacher).remove
|
61
|
+
end
|
128
62
|
|
129
|
-
|
130
|
-
|
131
|
-
|
63
|
+
define_method "remote_#{name}_url=" do |url|
|
64
|
+
send(attacher).download(url)
|
65
|
+
end
|
132
66
|
|
133
|
-
|
134
|
-
|
67
|
+
define_method "remote_#{name}_url" do
|
68
|
+
end
|
135
69
|
end
|
136
70
|
|
137
|
-
|
138
|
-
end
|
71
|
+
include mod
|
139
72
|
end
|
140
73
|
end
|
141
74
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Refile
|
2
2
|
module Backend
|
3
3
|
class FileSystem
|
4
|
-
attr_reader :directory
|
4
|
+
attr_reader :directory, :max_size
|
5
5
|
|
6
6
|
def initialize(directory, max_size: nil, hasher: Refile::RandomHasher.new)
|
7
7
|
@hasher = hasher
|
@@ -53,11 +53,11 @@ module Refile
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def exists?(id)
|
56
|
-
::File.
|
56
|
+
::File.exist?(path(id))
|
57
57
|
end
|
58
58
|
|
59
59
|
def clear!(confirm = nil)
|
60
|
-
raise
|
60
|
+
raise Refile::Confirm unless confirm == :confirm
|
61
61
|
FileUtils.rm_rf(@directory)
|
62
62
|
FileUtils.mkdir_p(@directory)
|
63
63
|
end
|
data/lib/refile/backend/s3.rb
CHANGED
@@ -2,10 +2,8 @@ require "aws-sdk"
|
|
2
2
|
|
3
3
|
module Refile
|
4
4
|
module Backend
|
5
|
-
|
6
5
|
# A refile backend which stores files in Amazon S3
|
7
6
|
class S3
|
8
|
-
|
9
7
|
# Emulates an IO-object like interface on top of S3Object#read. To avoid
|
10
8
|
# memory allocations and unnecessary complexity, this treats the `length`
|
11
9
|
# parameter to read as a boolean flag instead. If given, it will read the
|
@@ -21,9 +19,7 @@ module Refile
|
|
21
19
|
result = if length
|
22
20
|
raise "closed" if @closed
|
23
21
|
|
24
|
-
unless eof? # sets @peek
|
25
|
-
@peek
|
26
|
-
end
|
22
|
+
@peek unless eof? # sets @peek
|
27
23
|
else
|
28
24
|
@object.read
|
29
25
|
end
|
@@ -55,14 +51,13 @@ module Refile
|
|
55
51
|
end
|
56
52
|
end
|
57
53
|
|
58
|
-
|
59
|
-
|
60
|
-
attr_reader :access_key_id
|
54
|
+
attr_reader :access_key_id, :max_size
|
61
55
|
|
62
|
-
def initialize(access_key_id:, secret_access_key:, bucket:, max_size: nil, prefix: nil, hasher: Refile::RandomHasher.new)
|
56
|
+
def initialize(access_key_id:, secret_access_key:, bucket:, max_size: nil, prefix: nil, hasher: Refile::RandomHasher.new, **s3_options)
|
63
57
|
@access_key_id = access_key_id
|
64
58
|
@secret_access_key = secret_access_key
|
65
|
-
@
|
59
|
+
@s3_options = { access_key_id: access_key_id, secret_access_key: secret_access_key }.merge s3_options
|
60
|
+
@s3 = AWS::S3.new @s3_options
|
66
61
|
@bucket_name = bucket
|
67
62
|
@bucket = @s3.buckets[@bucket_name]
|
68
63
|
@hasher = hasher
|
@@ -113,7 +108,7 @@ module Refile
|
|
113
108
|
end
|
114
109
|
|
115
110
|
def clear!(confirm = nil)
|
116
|
-
raise
|
111
|
+
raise Refile::Confirm unless confirm == :confirm
|
117
112
|
@bucket.objects.with_prefix(@prefix).delete_all
|
118
113
|
end
|
119
114
|
|
@@ -121,7 +116,7 @@ module Refile
|
|
121
116
|
id = RandomHasher.new.hash
|
122
117
|
signature = @bucket.presigned_post(key: [*@prefix, id].join("/"))
|
123
118
|
signature.where(content_length: @max_size) if @max_size
|
124
|
-
Signature.new("file", id, signature.url.to_s, signature.fields)
|
119
|
+
Signature.new(as: "file", id: id, url: signature.url.to_s, fields: signature.fields)
|
125
120
|
end
|
126
121
|
|
127
122
|
def object(id)
|
data/lib/refile/file.rb
CHANGED
@@ -19,14 +19,17 @@ module Refile
|
|
19
19
|
img.resize "#{width}x#{height}"
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
# @ignore
|
23
|
+
# rubocop:disable Metrics/AbcSize
|
24
|
+
# FIXME: test and rewrite to simpler implementation!
|
25
|
+
def fill(img, width, height, gravity = "Center")
|
23
26
|
width = width.to_i
|
24
27
|
height = height.to_i
|
25
28
|
cols, rows = img[:dimensions]
|
26
29
|
img.combine_options do |cmd|
|
27
30
|
if width != cols || height != rows
|
28
|
-
scale_x = width/cols.to_f
|
29
|
-
scale_y = height/rows.to_f
|
31
|
+
scale_x = width / cols.to_f
|
32
|
+
scale_y = height / rows.to_f
|
30
33
|
if scale_x >= scale_y
|
31
34
|
cols = (scale_x * (cols + 0.5)).round
|
32
35
|
rows = (scale_x * (rows + 0.5)).round
|
@@ -1,58 +1,55 @@
|
|
1
1
|
module Refile
|
2
2
|
module AttachmentHelper
|
3
|
-
def attachment_url(record, name, *args, filename: nil, format: nil)
|
3
|
+
def attachment_url(record, name, *args, filename: nil, format: nil, host: nil)
|
4
4
|
file = record.send(name)
|
5
5
|
return unless file
|
6
6
|
|
7
7
|
filename ||= name.to_s
|
8
8
|
|
9
9
|
backend_name = Refile.backends.key(file.backend)
|
10
|
-
host = Refile.host || request.base_url
|
10
|
+
host = host || Refile.host || request.base_url
|
11
11
|
|
12
12
|
filename = filename.parameterize("_")
|
13
13
|
filename << "." << format.to_s if format
|
14
14
|
|
15
|
-
::File.join(host, main_app.refile_app_path, backend_name, *args.map(&:to_s), file.id, filename)
|
15
|
+
::File.join(host, main_app.refile_app_path, backend_name, *args.map(&:to_s), file.id.to_s, filename)
|
16
16
|
end
|
17
17
|
|
18
|
-
def attachment_image_tag(record, name, *args, fallback: nil, format: nil, **options)
|
18
|
+
def attachment_image_tag(record, name, *args, fallback: nil, format: nil, host: nil, **options)
|
19
19
|
file = record.send(name)
|
20
20
|
classes = ["attachment", record.class.model_name.singular, name, *options[:class]]
|
21
21
|
|
22
22
|
if file
|
23
|
-
image_tag(attachment_url(record, name, *args, format: format), options.merge(class: classes))
|
23
|
+
image_tag(attachment_url(record, name, *args, format: format, host: host), options.merge(class: classes))
|
24
24
|
elsif fallback
|
25
25
|
classes << "fallback"
|
26
26
|
image_tag(fallback, options.merge(class: classes))
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
# @ignore
|
31
|
+
# rubocop:disable Metrics/AbcSize
|
30
32
|
def attachment_field(object_name, method, options = {})
|
33
|
+
options[:data] ||= {}
|
34
|
+
|
31
35
|
if options[:object]
|
32
|
-
|
36
|
+
attacher = options[:object].send(:"#{method}_attacher")
|
37
|
+
options[:accept] = attacher.accept
|
33
38
|
|
34
39
|
if options[:direct]
|
35
|
-
host = Refile.host || request.base_url
|
36
|
-
backend_name = Refile.backends.key(cache)
|
40
|
+
host = options[:host] || Refile.host || request.base_url
|
41
|
+
backend_name = Refile.backends.key(attacher.cache)
|
37
42
|
|
38
|
-
|
39
|
-
options[:data]
|
40
|
-
options[:data][:as] = "file"
|
41
|
-
options[:data][:url] = ::File.join(host, main_app.refile_app_path, backend_name)
|
43
|
+
url = ::File.join(host, main_app.refile_app_path, backend_name)
|
44
|
+
options[:data].merge!(direct: true, as: "file", url: url)
|
42
45
|
end
|
43
46
|
|
44
|
-
if options[:presigned] and cache.respond_to?(:presign)
|
45
|
-
|
46
|
-
options[:data] ||= {}
|
47
|
-
options[:data][:direct] = true
|
48
|
-
options[:data][:id] = signature.id
|
49
|
-
options[:data][:url] = signature.url
|
50
|
-
options[:data][:fields] = signature.fields
|
51
|
-
options[:data][:as] = signature.as
|
47
|
+
if options[:presigned] and attacher.cache.respond_to?(:presign)
|
48
|
+
options[:data].merge!(direct: true).merge!(attacher.cache.presign.as_json)
|
52
49
|
end
|
53
50
|
end
|
54
51
|
hidden_field(object_name, :"#{method}_cache_id", options.slice(:object)) +
|
55
|
-
|
52
|
+
file_field(object_name, method, options)
|
56
53
|
end
|
57
54
|
end
|
58
55
|
end
|
data/lib/refile/rails.rb
CHANGED
data/lib/refile/random_hasher.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
1
|
+
module Refile
|
2
|
+
# A file hasher which ignores the file contents and always returns a random string.
|
3
|
+
class RandomHasher
|
4
|
+
# Generate a random string
|
5
|
+
#
|
6
|
+
# @return [String]
|
7
|
+
def hash(_uploadable = nil)
|
8
|
+
SecureRandom.hex(30)
|
9
|
+
end
|
9
10
|
end
|
10
11
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Refile
|
2
|
+
class Signature
|
3
|
+
attr_reader :as, :id, :url, :fields
|
4
|
+
|
5
|
+
def initialize(as:, id:, url:, fields:)
|
6
|
+
@as = as
|
7
|
+
@id = id
|
8
|
+
@url = url
|
9
|
+
@fields = fields
|
10
|
+
end
|
11
|
+
|
12
|
+
def as_json(*)
|
13
|
+
{ as: @as, id: @id, url: @url, fields: @fields }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/refile/version.rb
CHANGED
data/lib/refile.rb
CHANGED
@@ -2,12 +2,20 @@ require "uri"
|
|
2
2
|
require "fileutils"
|
3
3
|
require "tempfile"
|
4
4
|
require "rest_client"
|
5
|
+
require "logger"
|
6
|
+
require "mime/types"
|
5
7
|
|
6
8
|
module Refile
|
7
9
|
class Invalid < StandardError; end
|
10
|
+
class Confirm < StandardError
|
11
|
+
def message
|
12
|
+
"are you sure? this will remove all files in the backend, call as \
|
13
|
+
`clear!(:confirm)` if you're sure you want to do this"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
ONE_YEAR_IN_SECONDS = 31_557_600
|
8
17
|
|
9
18
|
class << self
|
10
|
-
|
11
19
|
# The number of bytes to read when files are streamed. Refile
|
12
20
|
# uses this in a couple of places where files should be streamed
|
13
21
|
# in a memory efficient way instead of reading the entire file into
|
@@ -40,6 +48,29 @@ module Refile
|
|
40
48
|
# @return [Array[String]]
|
41
49
|
attr_accessor :direct_upload
|
42
50
|
|
51
|
+
# Logger that should be used by rack application
|
52
|
+
#
|
53
|
+
# @return [Logger]
|
54
|
+
attr_accessor :logger
|
55
|
+
|
56
|
+
# Value for Access-Control-Allow-Origin header
|
57
|
+
#
|
58
|
+
# @return [String]
|
59
|
+
attr_accessor :allow_origin
|
60
|
+
|
61
|
+
# Value for Cache-Control: max-age=<value in seconds> header
|
62
|
+
attr_accessor :content_max_age
|
63
|
+
|
64
|
+
# Where should the rack application be mounted?
|
65
|
+
# The default is 'attachments'
|
66
|
+
attr_accessor :mount_point
|
67
|
+
|
68
|
+
# Should the rack application be automounted in a Rails app?
|
69
|
+
# The default is true.
|
70
|
+
# If set to false then Refile.app should be mounted in the Rails application
|
71
|
+
# routes.rb with the options `at: Refile.mount_point, as: :refile_app`
|
72
|
+
attr_accessor :automount
|
73
|
+
|
43
74
|
# A global registry of backends.
|
44
75
|
#
|
45
76
|
# @return [Hash{String => Backend}]
|
@@ -146,9 +177,31 @@ module Refile
|
|
146
177
|
end
|
147
178
|
true
|
148
179
|
end
|
180
|
+
|
181
|
+
def extract_filename(uploadable)
|
182
|
+
path = if uploadable.respond_to?(:original_filename)
|
183
|
+
uploadable.original_filename
|
184
|
+
elsif uploadable.respond_to?(:path)
|
185
|
+
uploadable.path
|
186
|
+
end
|
187
|
+
::File.basename(path) if path
|
188
|
+
end
|
189
|
+
|
190
|
+
def extract_content_type(uploadable)
|
191
|
+
if uploadable.respond_to?(:content_type)
|
192
|
+
uploadable.content_type
|
193
|
+
else
|
194
|
+
filename = extract_filename(uploadable)
|
195
|
+
if filename
|
196
|
+
content_type = MIME::Types.of(filename).first
|
197
|
+
content_type.to_s if content_type
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
149
201
|
end
|
150
202
|
|
151
203
|
require "refile/version"
|
204
|
+
require "refile/attacher"
|
152
205
|
require "refile/attachment"
|
153
206
|
require "refile/random_hasher"
|
154
207
|
require "refile/file"
|
@@ -162,4 +215,9 @@ Refile.configure do |config|
|
|
162
215
|
# one?
|
163
216
|
config.read_chunk_size = 3000
|
164
217
|
config.direct_upload = ["cache"]
|
218
|
+
config.allow_origin = "*"
|
219
|
+
config.logger = Logger.new(STDOUT)
|
220
|
+
config.mount_point = "attachments"
|
221
|
+
config.automount = true
|
222
|
+
config.content_max_age = Refile::ONE_YEAR_IN_SECONDS
|
165
223
|
end
|
data/refile.gemspec
CHANGED
@@ -1,24 +1,27 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
lib = File.expand_path(
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
4
|
+
require "refile/version"
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "refile"
|
8
8
|
spec.version = Refile::VERSION
|
9
9
|
spec.authors = ["Jonas Nicklas"]
|
10
10
|
spec.email = ["jonas.nicklas@gmail.com"]
|
11
|
-
spec.summary =
|
11
|
+
spec.summary = "Simple and powerful file upload library"
|
12
12
|
spec.homepage = ""
|
13
13
|
spec.license = "MIT"
|
14
14
|
|
15
15
|
spec.files = `git ls-files -z`.split("\x0")
|
16
|
-
spec.executables = spec.files.grep(
|
17
|
-
spec.test_files = spec.files.grep(
|
18
|
-
spec.require_paths = [
|
16
|
+
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(/^(test|spec|features)\//)
|
18
|
+
spec.require_paths = %w[lib spec]
|
19
19
|
|
20
20
|
spec.required_ruby_version = ">= 2.1.0"
|
21
|
+
|
21
22
|
spec.add_dependency "rest-client", "~> 1.7.2"
|
23
|
+
spec.add_dependency "sinatra", "~> 1.4.5"
|
24
|
+
spec.add_dependency "mime-types"
|
22
25
|
|
23
26
|
spec.add_development_dependency "webmock", "~> 1.20.4"
|
24
27
|
spec.add_development_dependency "bundler", "~> 1.6"
|
@@ -34,4 +37,5 @@ Gem::Specification.new do |spec|
|
|
34
37
|
spec.add_development_dependency "sqlite3"
|
35
38
|
spec.add_development_dependency "selenium-webdriver"
|
36
39
|
spec.add_development_dependency "yard"
|
40
|
+
spec.add_development_dependency "rubocop"
|
37
41
|
end
|
data/spec/refile/app_spec.rb
CHANGED
@@ -18,11 +18,12 @@ describe Refile::App do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it "returns a 404 if the file doesn't exist" do
|
21
|
-
|
21
|
+
Refile.store.upload(StringIO.new("hello"))
|
22
22
|
|
23
23
|
get "/store/doesnotexist/hello"
|
24
24
|
|
25
25
|
expect(last_response.status).to eq(404)
|
26
|
+
expect(last_response.content_type).to eq("text/plain;charset=utf-8")
|
26
27
|
expect(last_response.body).to eq("not found")
|
27
28
|
end
|
28
29
|
|
@@ -32,12 +33,13 @@ describe Refile::App do
|
|
32
33
|
get "/doesnotexist/#{file.id}/hello"
|
33
34
|
|
34
35
|
expect(last_response.status).to eq(404)
|
36
|
+
expect(last_response.content_type).to eq("text/plain;charset=utf-8")
|
35
37
|
expect(last_response.body).to eq("not found")
|
36
38
|
end
|
37
39
|
|
38
40
|
context "with allow origin" do
|
39
|
-
|
40
|
-
Refile
|
41
|
+
before(:each) do
|
42
|
+
allow(Refile).to receive(:allow_origin).and_return("example.com")
|
41
43
|
end
|
42
44
|
|
43
45
|
it "sets CORS header" do
|
@@ -51,12 +53,31 @@ describe Refile::App do
|
|
51
53
|
end
|
52
54
|
end
|
53
55
|
|
56
|
+
it "returns a 200 for head requests" do
|
57
|
+
file = Refile.store.upload(StringIO.new("hello"))
|
58
|
+
|
59
|
+
head "/store/#{file.id}/hello"
|
60
|
+
|
61
|
+
expect(last_response.status).to eq(200)
|
62
|
+
expect(last_response.body).to be_empty
|
63
|
+
end
|
64
|
+
|
65
|
+
it "returns a 404 for head requests if the file doesn't exist" do
|
66
|
+
Refile.store.upload(StringIO.new("hello"))
|
67
|
+
|
68
|
+
head "/store/doesnotexist/hello"
|
69
|
+
|
70
|
+
expect(last_response.status).to eq(404)
|
71
|
+
expect(last_response.body).to be_empty
|
72
|
+
end
|
73
|
+
|
54
74
|
it "returns a 404 for non get requests" do
|
55
75
|
file = Refile.store.upload(StringIO.new("hello"))
|
56
76
|
|
57
77
|
post "/store/#{file.id}/hello"
|
58
78
|
|
59
79
|
expect(last_response.status).to eq(404)
|
80
|
+
expect(last_response.content_type).to eq("text/plain;charset=utf-8")
|
60
81
|
expect(last_response.body).to eq("not found")
|
61
82
|
end
|
62
83
|
end
|
@@ -68,6 +89,7 @@ describe Refile::App do
|
|
68
89
|
get "/store/doesnotexist/#{file.id}/hello"
|
69
90
|
|
70
91
|
expect(last_response.status).to eq(404)
|
92
|
+
expect(last_response.content_type).to eq("text/plain;charset=utf-8")
|
71
93
|
expect(last_response.body).to eq("not found")
|
72
94
|
end
|
73
95
|
|
@@ -114,6 +136,7 @@ describe Refile::App do
|
|
114
136
|
post "/store", file: file
|
115
137
|
|
116
138
|
expect(last_response.status).to eq(404)
|
139
|
+
expect(last_response.content_type).to eq("text/plain;charset=utf-8")
|
117
140
|
expect(last_response.body).to eq("not found")
|
118
141
|
end
|
119
142
|
|
@@ -130,6 +153,7 @@ describe Refile::App do
|
|
130
153
|
get "/store"
|
131
154
|
|
132
155
|
expect(last_response.status).to eq(404)
|
156
|
+
expect(last_response.content_type).to eq("text/plain;charset=utf-8")
|
133
157
|
expect(last_response.body).to eq("not found")
|
134
158
|
end
|
135
159
|
|
@@ -137,7 +161,7 @@ describe Refile::App do
|
|
137
161
|
get "/"
|
138
162
|
|
139
163
|
expect(last_response.status).to eq(404)
|
164
|
+
expect(last_response.content_type).to eq("text/plain;charset=utf-8")
|
140
165
|
expect(last_response.body).to eq("not found")
|
141
166
|
end
|
142
167
|
end
|
143
|
-
|