dragonfly 1.4.0 → 1.4.2
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/Gemfile +6 -0
- data/History.md +13 -1
- data/README.md +5 -1
- data/dev/test.ru +1 -1
- data/dragonfly.gemspec +2 -1
- data/lib/dragonfly/middleware.rb +2 -1
- data/lib/dragonfly/response.rb +11 -10
- data/lib/dragonfly/routed_endpoint.rb +1 -1
- data/lib/dragonfly/server.rb +7 -7
- data/lib/dragonfly/version.rb +1 -1
- data/spec/dragonfly/app_spec.rb +1 -1
- data/spec/dragonfly/configurable_spec.rb +4 -4
- data/spec/dragonfly/content_spec.rb +1 -1
- data/spec/dragonfly/file_data_store_spec.rb +2 -2
- data/spec/dragonfly/job/fetch_url_spec.rb +1 -1
- data/spec/dragonfly/job_endpoint_spec.rb +32 -26
- data/spec/dragonfly/middleware_spec.rb +15 -6
- data/spec/dragonfly/model/active_record_spec.rb +2 -2
- data/spec/dragonfly/model/model_spec.rb +1 -1
- data/spec/dragonfly/server_spec.rb +4 -4
- data/spec/dragonfly/temp_object_spec.rb +5 -5
- data/spec/functional/to_response_spec.rb +2 -2
- data/spec/functional/urls_spec.rb +1 -1
- data/spec/spec_helper.rb +6 -0
- data/spec/support/image_matchers.rb +1 -1
- metadata +19 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a21082636a15ad436d2ee93b887de5347733de38d670411c7aabb084afee9f7f
|
|
4
|
+
data.tar.gz: cc68822a3c32077c576fed5ca215952983af2e49038103c661ea95ef8a3703b7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 80e0fb82c3d0b3551da0036e7e19a688aa94a0525b4128139f1e4f288f18ff73427e556ff49a84b7165dfdbd600648469a1f6ac135603f75f538472ddc84863b
|
|
7
|
+
data.tar.gz: 6514c3a64cbffd11cad972dc8d2aeabe39da7a9bc4744b20743703d70f34e9e7a3fb3a67198bbbd001a86073f546e89f55684083c48b098b512229846a5ab9e1
|
data/Gemfile
CHANGED
|
@@ -5,4 +5,10 @@ gemspec
|
|
|
5
5
|
group :development do
|
|
6
6
|
gem 'pry'
|
|
7
7
|
gem 'rake'
|
|
8
|
+
# No longer in the standard library as of ruby 4.0
|
|
9
|
+
# (needed by rack/mock and activerecord respectively)
|
|
10
|
+
gem 'cgi'
|
|
11
|
+
gem 'benchmark'
|
|
12
|
+
# Needed by irb, and no longer a default gem as of ruby 4.0
|
|
13
|
+
gem 'rdoc'
|
|
8
14
|
end
|
data/History.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# 1.4.2 (2026-07-21)
|
|
2
|
+
|
|
3
|
+
## Fixes
|
|
4
|
+
|
|
5
|
+
- Security fix for CRLF filename header injection in servers that don't sanitize
|
|
6
|
+
|
|
7
|
+
# 1.4.1 (2025-01-03)
|
|
8
|
+
|
|
9
|
+
## Fixes
|
|
10
|
+
|
|
11
|
+
- Added ostruct dependency as Ruby 3.5 will remove it from stdlib
|
|
12
|
+
|
|
1
13
|
# 1.4.0 (2021-05-19)
|
|
2
14
|
|
|
3
15
|
## Changes
|
|
@@ -6,7 +18,7 @@
|
|
|
6
18
|
|
|
7
19
|
## Fixes
|
|
8
20
|
|
|
9
|
-
- Better security for all job steps with parameter validations
|
|
21
|
+
- Better security for all job steps with parameter validations - addresses CVE-2021-33564
|
|
10
22
|
|
|
11
23
|
# 1.3.0 (2021-01-09)
|
|
12
24
|
|
data/README.md
CHANGED
|
@@ -47,7 +47,7 @@ Installation
|
|
|
47
47
|
|
|
48
48
|
or in your Gemfile
|
|
49
49
|
```ruby
|
|
50
|
-
gem 'dragonfly', '~> 1.
|
|
50
|
+
gem 'dragonfly', '~> 1.4.2'
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
Require with
|
|
@@ -72,6 +72,10 @@ See [the Add-ons wiki](http://github.com/markevans/dragonfly/wiki/Dragonfly-add-
|
|
|
72
72
|
|
|
73
73
|
Please feel free to contribute!!
|
|
74
74
|
|
|
75
|
+
Security notice!
|
|
76
|
+
=================
|
|
77
|
+
If you have set `verify_urls` to `false` (which is **not** recommended) then you should upgrade to version `1.4.x` for a security fix ([CVE-2021-33564](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-33564)).
|
|
78
|
+
|
|
75
79
|
Issues
|
|
76
80
|
======
|
|
77
81
|
Please use the <a href="http://github.com/markevans/dragonfly/issues">github issue tracker</a> if you have any issues.
|
data/dev/test.ru
CHANGED
data/dragonfly.gemspec
CHANGED
|
@@ -25,9 +25,10 @@ Gem::Specification.new do |spec|
|
|
|
25
25
|
spec.add_runtime_dependency("rack", ">= 1.3")
|
|
26
26
|
spec.add_runtime_dependency("multi_json", "~> 1.0")
|
|
27
27
|
spec.add_runtime_dependency("addressable", "~> 2.3")
|
|
28
|
+
spec.add_runtime_dependency("ostruct", "~> 0.6.1")
|
|
28
29
|
|
|
29
30
|
# Development dependencies
|
|
30
|
-
spec.add_development_dependency("rspec", "~>
|
|
31
|
+
spec.add_development_dependency("rspec", "~> 3.0")
|
|
31
32
|
spec.add_development_dependency("webmock")
|
|
32
33
|
spec.add_development_dependency("activemodel")
|
|
33
34
|
if RUBY_PLATFORM == "java"
|
data/lib/dragonfly/middleware.rb
CHANGED
|
@@ -10,7 +10,8 @@ module Dragonfly
|
|
|
10
10
|
|
|
11
11
|
def call(env)
|
|
12
12
|
response = Dragonfly.app(@dragonfly_app_name).call(env)
|
|
13
|
-
|
|
13
|
+
headers = response[1].transform_keys(&:downcase)
|
|
14
|
+
if headers['x-cascade'] == 'pass'
|
|
14
15
|
@app.call(env)
|
|
15
16
|
else
|
|
16
17
|
response
|
data/lib/dragonfly/response.rb
CHANGED
|
@@ -26,10 +26,10 @@ module Dragonfly
|
|
|
26
26
|
end
|
|
27
27
|
rescue Job::Fetch::NotFound => e
|
|
28
28
|
Dragonfly.warn(e.message)
|
|
29
|
-
[404, {"
|
|
29
|
+
[404, {"content-type" => "text/plain"}, ["Not found"]]
|
|
30
30
|
rescue RuntimeError => e
|
|
31
31
|
Dragonfly.warn("caught error - #{e.message}")
|
|
32
|
-
[500, {"
|
|
32
|
+
[500, {"content-type" => "text/plain"}, ["Internal Server Error"]]
|
|
33
33
|
end
|
|
34
34
|
log_response(response)
|
|
35
35
|
response
|
|
@@ -65,8 +65,8 @@ module Dragonfly
|
|
|
65
65
|
|
|
66
66
|
def method_not_allowed_headers
|
|
67
67
|
{
|
|
68
|
-
'
|
|
69
|
-
'
|
|
68
|
+
'content-type' => 'text/plain',
|
|
69
|
+
'allow' => 'GET, HEAD'
|
|
70
70
|
}
|
|
71
71
|
end
|
|
72
72
|
|
|
@@ -78,16 +78,16 @@ module Dragonfly
|
|
|
78
78
|
|
|
79
79
|
def standard_headers
|
|
80
80
|
{
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
81
|
+
"content-type" => job.mime_type,
|
|
82
|
+
"content-length" => job.size.to_s,
|
|
83
|
+
"content-disposition" => filename_string
|
|
84
84
|
}
|
|
85
85
|
end
|
|
86
86
|
|
|
87
87
|
def cache_headers
|
|
88
88
|
{
|
|
89
|
-
"
|
|
90
|
-
"
|
|
89
|
+
"cache-control" => "public, max-age=31536000", # (1 year)
|
|
90
|
+
"etag" => %("#{job.signature}")
|
|
91
91
|
}
|
|
92
92
|
end
|
|
93
93
|
|
|
@@ -99,7 +99,8 @@ module Dragonfly
|
|
|
99
99
|
|
|
100
100
|
def filename_string
|
|
101
101
|
return unless job.name
|
|
102
|
-
|
|
102
|
+
name = job.name.gsub(/[\r\n]/, "")
|
|
103
|
+
filename = request_from_msie? ? CGI.escape(name) : name
|
|
103
104
|
%(filename="#{filename}")
|
|
104
105
|
end
|
|
105
106
|
|
data/lib/dragonfly/server.rb
CHANGED
|
@@ -59,18 +59,18 @@ module Dragonfly
|
|
|
59
59
|
response.to_response
|
|
60
60
|
end
|
|
61
61
|
else
|
|
62
|
-
[404, {'
|
|
62
|
+
[404, {'content-type' => 'text/plain', 'x-cascade' => 'pass'}, ['Not found']]
|
|
63
63
|
end
|
|
64
64
|
rescue Job::NoSHAGiven => e
|
|
65
|
-
[400, {"
|
|
65
|
+
[400, {"content-type" => 'text/plain'}, ["You need to give a SHA parameter"]]
|
|
66
66
|
rescue Job::IncorrectSHA => e
|
|
67
|
-
[400, {"
|
|
67
|
+
[400, {"content-type" => 'text/plain'}, ["The SHA parameter you gave is incorrect"]]
|
|
68
68
|
rescue JobNotAllowed => e
|
|
69
69
|
Dragonfly.warn(e.message)
|
|
70
|
-
[403, {"
|
|
70
|
+
[403, {"content-type" => 'text/plain'}, ["Forbidden"]]
|
|
71
71
|
rescue Serializer::BadString, Serializer::MaliciousString, Job::InvalidArray => e
|
|
72
72
|
Dragonfly.warn(e.message)
|
|
73
|
-
[404, {'
|
|
73
|
+
[404, {'content-type' => 'text/plain'}, ['Not found']]
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
def url_for(job, opts={})
|
|
@@ -111,8 +111,8 @@ module Dragonfly
|
|
|
111
111
|
V
|
|
112
112
|
DRAGONFLY
|
|
113
113
|
[200, {
|
|
114
|
-
'
|
|
115
|
-
'
|
|
114
|
+
'content-type' => 'text/plain',
|
|
115
|
+
'content-size' => body.bytesize.to_s
|
|
116
116
|
},
|
|
117
117
|
[body]
|
|
118
118
|
]
|
data/lib/dragonfly/version.rb
CHANGED
data/spec/dragonfly/app_spec.rb
CHANGED
|
@@ -138,7 +138,7 @@ describe Dragonfly::App do
|
|
|
138
138
|
}.should raise_error(NotImplementedError)
|
|
139
139
|
end
|
|
140
140
|
it "should correctly call it if the datastore provides it" do
|
|
141
|
-
@app.datastore.should_receive(:url_for).with('some_uid', :some => :opts).and_return 'http://egg.head'
|
|
141
|
+
@app.datastore.should_receive(:url_for).with('some_uid', {:some => :opts}).and_return 'http://egg.head'
|
|
142
142
|
@app.remote_url_for('some_uid', :some => :opts).should == 'http://egg.head'
|
|
143
143
|
end
|
|
144
144
|
end
|
|
@@ -65,7 +65,7 @@ describe Dragonfly::Configurable do
|
|
|
65
65
|
configurer = Dragonfly::Configurable::Configurer.new do
|
|
66
66
|
meth :jobby, :nobby
|
|
67
67
|
end
|
|
68
|
-
obj.should_receive(:jobby).with('beans', :make => 5)
|
|
68
|
+
obj.should_receive(:jobby).with('beans', {:make => 5})
|
|
69
69
|
obj.should_receive(:nobby).with(['nuts'])
|
|
70
70
|
configurer.configure(obj) do
|
|
71
71
|
jobby 'beans', :make => 5
|
|
@@ -79,7 +79,7 @@ describe Dragonfly::Configurable do
|
|
|
79
79
|
end
|
|
80
80
|
egg = double('egg')
|
|
81
81
|
obj.should_receive(:egg).and_return(egg)
|
|
82
|
-
egg.should_receive(:jobby).with('beans', :make => 5)
|
|
82
|
+
egg.should_receive(:jobby).with('beans', {:make => 5})
|
|
83
83
|
configurer.configure(obj) do
|
|
84
84
|
jobby 'beans', :make => 5
|
|
85
85
|
end
|
|
@@ -93,7 +93,7 @@ describe Dragonfly::Configurable do
|
|
|
93
93
|
|
|
94
94
|
it "provides 'plugin' for using plugins" do
|
|
95
95
|
pluggy = double('plugin')
|
|
96
|
-
pluggy.should_receive(:call).with(obj, :a, 'few' => ['args'])
|
|
96
|
+
pluggy.should_receive(:call).with(obj, :a, {'few' => ['args']})
|
|
97
97
|
configurer.configure(obj) do
|
|
98
98
|
plugin pluggy, :a, 'few' => ['args']
|
|
99
99
|
end
|
|
@@ -101,7 +101,7 @@ describe Dragonfly::Configurable do
|
|
|
101
101
|
|
|
102
102
|
it "allows using 'plugin' with symbols" do
|
|
103
103
|
pluggy = double('plugin')
|
|
104
|
-
pluggy.should_receive(:call).with(obj, :a, 'few' => ['args'])
|
|
104
|
+
pluggy.should_receive(:call).with(obj, :a, {'few' => ['args']})
|
|
105
105
|
configurer.register_plugin(:pluggy){ pluggy }
|
|
106
106
|
configurer.configure(obj) do
|
|
107
107
|
plugin :pluggy, :a, 'few' => ['args']
|
|
@@ -320,7 +320,7 @@ describe Dragonfly::Content do
|
|
|
320
320
|
end
|
|
321
321
|
|
|
322
322
|
it "allows passing options" do
|
|
323
|
-
app.datastore.should_receive(:write).with(content, :hello => 'there')
|
|
323
|
+
app.datastore.should_receive(:write).with(content, {:hello => 'there'})
|
|
324
324
|
content.store(:hello => 'there')
|
|
325
325
|
end
|
|
326
326
|
end
|
|
@@ -9,11 +9,11 @@ describe Dragonfly::FileDataStore do
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def assert_exists(path)
|
|
12
|
-
File.
|
|
12
|
+
File.exist?(path).should be_truthy
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def assert_does_not_exist(path)
|
|
16
|
-
File.
|
|
16
|
+
File.exist?(path).should be_falsey
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def assert_contains(dir, filepattern)
|
|
@@ -21,7 +21,7 @@ describe Dragonfly::Job::FetchUrl do
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
it "should set the mime_type when returned by the request" do
|
|
24
|
-
stub_request(:get, %r{http://thing\.com.*}).to_return(:body => '<ok />', :headers => {'
|
|
24
|
+
stub_request(:get, %r{http://thing\.com.*}).to_return(:body => '<ok />', :headers => {'content-type' => 'text/html'})
|
|
25
25
|
expect(job.fetch_url('http://place.com').mime_type).to eq('application/octet-stream')
|
|
26
26
|
expect(job.fetch_url('http://thing.com').mime_type).to eq('text/html')
|
|
27
27
|
end
|
|
@@ -50,22 +50,22 @@ describe Dragonfly::JobEndpoint do
|
|
|
50
50
|
it "should return a correct response to a successful GET request" do
|
|
51
51
|
response = make_request(@job)
|
|
52
52
|
response.status.should == 200
|
|
53
|
-
response['
|
|
54
|
-
response['
|
|
55
|
-
response['
|
|
56
|
-
response['
|
|
57
|
-
response['
|
|
53
|
+
response['etag'].should =~ /^"\w+"$/
|
|
54
|
+
response['cache-control'].should == "public, max-age=31536000"
|
|
55
|
+
response['content-type'].should == 'text/plain'
|
|
56
|
+
response['content-length'].should == '6'
|
|
57
|
+
response['content-disposition'].should == 'filename="gung.txt"'
|
|
58
58
|
response.body.should == 'GUNGLE'
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
it "should return the correct headers and no content to a successful HEAD request" do
|
|
62
62
|
response = make_request(@job, :method => :head)
|
|
63
63
|
response.status.should == 200
|
|
64
|
-
response['
|
|
65
|
-
response['
|
|
66
|
-
response['
|
|
67
|
-
response['
|
|
68
|
-
response['
|
|
64
|
+
response['etag'].should =~ /^"\w+"$/
|
|
65
|
+
response['cache-control'].should == "public, max-age=31536000"
|
|
66
|
+
response['content-type'].should == 'text/plain'
|
|
67
|
+
response['content-length'].should == '6'
|
|
68
|
+
response['content-disposition'].should == 'filename="gung.txt"'
|
|
69
69
|
response.body.should == ''
|
|
70
70
|
end
|
|
71
71
|
|
|
@@ -74,8 +74,8 @@ describe Dragonfly::JobEndpoint do
|
|
|
74
74
|
it "should return a 405 error for a #{method} request" do
|
|
75
75
|
response = make_request(@job, :method => method)
|
|
76
76
|
response.status.should == 405
|
|
77
|
-
response['
|
|
78
|
-
response['
|
|
77
|
+
response['allow'].should == "GET, HEAD"
|
|
78
|
+
response['content-type'].should == 'text/plain'
|
|
79
79
|
response.body.should == "method not allowed"
|
|
80
80
|
end
|
|
81
81
|
|
|
@@ -102,12 +102,18 @@ describe Dragonfly::JobEndpoint do
|
|
|
102
102
|
|
|
103
103
|
it "doesn't encode utf8 characters" do
|
|
104
104
|
response = make_request(@job)
|
|
105
|
-
response['
|
|
105
|
+
response['content-disposition'].should == 'filename="güng.txt"'
|
|
106
106
|
end
|
|
107
107
|
|
|
108
108
|
it "does encode them if the request is from IE" do
|
|
109
109
|
response = make_request(@job, 'HTTP_USER_AGENT' => "Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; el-GR)")
|
|
110
|
-
response['
|
|
110
|
+
response['content-disposition'].should == 'filename="g%C3%BCng.txt"'
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "doesn't allow \\r or \\n characters" do
|
|
114
|
+
@job.name = "\nthis\nis\r\na\n\rbad\rone\r.txt"
|
|
115
|
+
response = make_request(@job)
|
|
116
|
+
response['content-disposition'].should == 'filename="thisisabadone.txt"'
|
|
111
117
|
end
|
|
112
118
|
end
|
|
113
119
|
|
|
@@ -121,7 +127,7 @@ describe Dragonfly::JobEndpoint do
|
|
|
121
127
|
describe "ETag" do
|
|
122
128
|
it "should return an ETag" do
|
|
123
129
|
response = make_request(@job)
|
|
124
|
-
response.headers['
|
|
130
|
+
response.headers['etag'].should =~ /^"\w+"$/
|
|
125
131
|
end
|
|
126
132
|
|
|
127
133
|
[
|
|
@@ -134,8 +140,8 @@ describe Dragonfly::JobEndpoint do
|
|
|
134
140
|
@job.should_receive(:signature).at_least(:once).and_return('dingle')
|
|
135
141
|
response = make_request(@job, 'HTTP_IF_NONE_MATCH' => header)
|
|
136
142
|
response.status.should == 304
|
|
137
|
-
response['
|
|
138
|
-
response['
|
|
143
|
+
response['etag'].should == '"dingle"'
|
|
144
|
+
response['cache-control'].should == "public, max-age=31536000"
|
|
139
145
|
response.body.should be_empty
|
|
140
146
|
end
|
|
141
147
|
end
|
|
@@ -151,25 +157,25 @@ describe Dragonfly::JobEndpoint do
|
|
|
151
157
|
@app.configure{ response_header 'This-is', 'brill' }
|
|
152
158
|
end
|
|
153
159
|
it "should allow specifying custom headers" do
|
|
154
|
-
make_request(@job).headers['
|
|
160
|
+
make_request(@job).headers['this-is'].should == 'brill'
|
|
155
161
|
end
|
|
156
162
|
it "should not interfere with other headers" do
|
|
157
|
-
make_request(@job).headers['
|
|
163
|
+
make_request(@job).headers['content-length'].should == '6'
|
|
158
164
|
end
|
|
159
165
|
it "should allow overridding other headers" do
|
|
160
|
-
@app.response_headers['
|
|
161
|
-
make_request(@job).headers['
|
|
166
|
+
@app.response_headers['cache-control'] = 'try me'
|
|
167
|
+
make_request(@job).headers['cache-control'].should == 'try me'
|
|
162
168
|
end
|
|
163
169
|
it "should allow giving a proc" do
|
|
164
|
-
@app.response_headers['
|
|
165
|
-
[job.basename.reverse.upcase, request['a'], headers['
|
|
170
|
+
@app.response_headers['cache-control'] = proc{|job, request, headers|
|
|
171
|
+
[job.basename.reverse.upcase, request.params['a'], headers['cache-control'].chars.first].join(',')
|
|
166
172
|
}
|
|
167
173
|
response = make_request(@job, 'QUERY_STRING' => 'a=egg')
|
|
168
|
-
response['
|
|
174
|
+
response['cache-control'].should == 'GNUG,egg,p'
|
|
169
175
|
end
|
|
170
176
|
it "should allow removing by setting to nil" do
|
|
171
|
-
@app.response_headers['
|
|
172
|
-
make_request(@job).headers.should_not have_key('
|
|
177
|
+
@app.response_headers['cache-control'] = nil
|
|
178
|
+
make_request(@job).headers.should_not have_key('cache-control')
|
|
173
179
|
end
|
|
174
180
|
end
|
|
175
181
|
|
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
|
2
2
|
require 'rack'
|
|
3
3
|
|
|
4
4
|
def dummy_rack_app
|
|
5
|
-
lambda{|env| [200, {"
|
|
5
|
+
lambda{|env| [200, {"content-type" => "text/html"}, ["dummy_rack_app body"]] }
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
describe Dragonfly::Middleware do
|
|
@@ -19,9 +19,18 @@ describe Dragonfly::Middleware do
|
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
it "should pass through if the app returns
|
|
22
|
+
it "should pass through if the app returns x-cascade: pass" do
|
|
23
23
|
Dragonfly.app.should_receive(:call).and_return(
|
|
24
|
-
[404, {"
|
|
24
|
+
[404, {"content-type" => 'text/plain', 'x-cascade' => 'pass'}, ['Not found']]
|
|
25
|
+
)
|
|
26
|
+
response = make_request(@stack, '/media/hello.png?howare=you')
|
|
27
|
+
response.body.should == 'dummy_rack_app body'
|
|
28
|
+
response.status.should == 200
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should still pass through using deprecated uppercase X-Cascade: pass" do
|
|
32
|
+
Dragonfly.app.should_receive(:call).and_return(
|
|
33
|
+
[404, {"content-type" => 'text/plain', 'X-Cascade' => 'pass'}, ['Not found']]
|
|
25
34
|
)
|
|
26
35
|
response = make_request(@stack, '/media/hello.png?howare=you')
|
|
27
36
|
response.body.should == 'dummy_rack_app body'
|
|
@@ -30,7 +39,7 @@ describe Dragonfly::Middleware do
|
|
|
30
39
|
|
|
31
40
|
it "should return a 404 if the app returns a 404" do
|
|
32
41
|
Dragonfly.app.should_receive(:call).and_return(
|
|
33
|
-
[404, {"
|
|
42
|
+
[404, {"content-type" => 'text/plain'}, ['Not found']]
|
|
34
43
|
)
|
|
35
44
|
response = make_request(@stack, '/media/hello.png?howare=you')
|
|
36
45
|
response.status.should == 404
|
|
@@ -38,7 +47,7 @@ describe Dragonfly::Middleware do
|
|
|
38
47
|
|
|
39
48
|
it "should return as per the dragonfly app if the app returns a 200" do
|
|
40
49
|
Dragonfly.app.should_receive(:call).and_return(
|
|
41
|
-
[200, {"
|
|
50
|
+
[200, {"content-type" => 'text/plain'}, ['ABCD']]
|
|
42
51
|
)
|
|
43
52
|
response = make_request(@stack, '/media/hello.png?howare=you')
|
|
44
53
|
response.status.should == 200
|
|
@@ -57,7 +66,7 @@ describe Dragonfly::Middleware do
|
|
|
57
66
|
it "should use the specified dragonfly app" do
|
|
58
67
|
Dragonfly.app.should_not_receive(:call)
|
|
59
68
|
Dragonfly.app(:images).should_receive(:call).and_return([
|
|
60
|
-
200, {"
|
|
69
|
+
200, {"content-type" => 'text/plain'}, ['booboo']
|
|
61
70
|
])
|
|
62
71
|
response = make_request(@stack, '/media/hello.png?howare=you')
|
|
63
72
|
response.body.should == 'booboo'
|
|
@@ -9,7 +9,7 @@ unless RUBY_PLATFORM == "java"
|
|
|
9
9
|
let! :dragonfly_app do test_app(:test_ar) end
|
|
10
10
|
|
|
11
11
|
before :all do
|
|
12
|
-
|
|
12
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
|
13
13
|
|
|
14
14
|
ActiveRecord::Migration.verbose = false
|
|
15
15
|
|
|
@@ -27,7 +27,7 @@ unless RUBY_PLATFORM == "java"
|
|
|
27
27
|
|
|
28
28
|
after :all do
|
|
29
29
|
Photo.destroy_all
|
|
30
|
-
ActiveRecord::Base.remove_connection(
|
|
30
|
+
ActiveRecord::Base.remove_connection()
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
describe "destroying" do
|
|
@@ -367,7 +367,7 @@ describe "models" do
|
|
|
367
367
|
describe "remote_url" do
|
|
368
368
|
it "should give the remote url if the uid is set" do
|
|
369
369
|
@item.preview_image_uid = 'some/uid'
|
|
370
|
-
@app.should_receive(:remote_url_for).with('some/uid', :some => 'param').and_return('http://egg.nog')
|
|
370
|
+
@app.should_receive(:remote_url_for).with('some/uid', {:some => 'param'}).and_return('http://egg.nog')
|
|
371
371
|
@item.preview_image.remote_url(:some => 'param').should == 'http://egg.nog'
|
|
372
372
|
end
|
|
373
373
|
it "should return nil if the content is not yet saved" do
|
|
@@ -81,7 +81,7 @@ describe Dragonfly::Server do
|
|
|
81
81
|
response.status.should == 404
|
|
82
82
|
response.body.should == 'Not found'
|
|
83
83
|
response.content_type.should == 'text/plain'
|
|
84
|
-
response.headers['
|
|
84
|
+
response.headers['x-cascade'].should == 'pass'
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
87
|
|
|
@@ -90,7 +90,7 @@ describe Dragonfly::Server do
|
|
|
90
90
|
response.status.should == 404
|
|
91
91
|
response.body.should == 'Not found'
|
|
92
92
|
response.content_type.should == 'text/plain'
|
|
93
|
-
response.headers['
|
|
93
|
+
response.headers['x-cascade'].should be_nil
|
|
94
94
|
end
|
|
95
95
|
|
|
96
96
|
it "should return a 404 when the url isn't known at all" do
|
|
@@ -98,7 +98,7 @@ describe Dragonfly::Server do
|
|
|
98
98
|
response.status.should == 404
|
|
99
99
|
response.body.should == 'Not found'
|
|
100
100
|
response.content_type.should == 'text/plain'
|
|
101
|
-
response.headers['
|
|
101
|
+
response.headers['x-cascade'].should == 'pass'
|
|
102
102
|
end
|
|
103
103
|
|
|
104
104
|
it "should return a 404 when the url is a well-encoded but bad array" do
|
|
@@ -107,7 +107,7 @@ describe Dragonfly::Server do
|
|
|
107
107
|
response.status.should == 404
|
|
108
108
|
response.body.should == 'Not found'
|
|
109
109
|
response.content_type.should == 'text/plain'
|
|
110
|
-
response.headers['
|
|
110
|
+
response.headers['x-cascade'].should be_nil
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
it "should return a 403 Forbidden when someone uses fetch_url" do
|
|
@@ -111,14 +111,14 @@ describe Dragonfly::TempObject do
|
|
|
111
111
|
describe "to_file" do
|
|
112
112
|
before(:each) do
|
|
113
113
|
@filename = 'tmp/eggnog.txt'
|
|
114
|
-
FileUtils.rm_f(@filename) if File.
|
|
114
|
+
FileUtils.rm_f(@filename) if File.exist?(@filename)
|
|
115
115
|
end
|
|
116
116
|
after(:each) do
|
|
117
|
-
FileUtils.rm_f(@filename) if File.
|
|
117
|
+
FileUtils.rm_f(@filename) if File.exist?(@filename)
|
|
118
118
|
end
|
|
119
119
|
it "should write to a file" do
|
|
120
120
|
@temp_object.to_file(@filename)
|
|
121
|
-
File.
|
|
121
|
+
File.exist?(@filename).should be_truthy
|
|
122
122
|
end
|
|
123
123
|
it "should write the correct data to the file" do
|
|
124
124
|
@temp_object.to_file(@filename)
|
|
@@ -140,12 +140,12 @@ describe Dragonfly::TempObject do
|
|
|
140
140
|
it "should create intermediate subdirs" do
|
|
141
141
|
filename = 'tmp/gog/mcgee'
|
|
142
142
|
@temp_object.to_file(filename)
|
|
143
|
-
File.
|
|
143
|
+
File.exist?(filename).should be_truthy
|
|
144
144
|
FileUtils.rm_rf('tmp/gog')
|
|
145
145
|
end
|
|
146
146
|
it "should allow not creating intermediate subdirs" do
|
|
147
147
|
filename = 'tmp/gog/mcgee'
|
|
148
|
-
expect{ @temp_object.to_file(filename, :mkdirs => false) }.to raise_error()
|
|
148
|
+
expect{ @temp_object.to_file(filename, :mkdirs => false) }.to raise_error(/No such file or directory/)
|
|
149
149
|
end
|
|
150
150
|
end
|
|
151
151
|
|
|
@@ -15,7 +15,7 @@ describe "getting rack response directly" do
|
|
|
15
15
|
response.should be_a(Array)
|
|
16
16
|
response.length.should == 3
|
|
17
17
|
response[0].should == 200
|
|
18
|
-
response[1]['
|
|
18
|
+
response[1]['content-type'].should == 'application/octet-stream'
|
|
19
19
|
response[2].data.should == 'bunheads'
|
|
20
20
|
end
|
|
21
21
|
|
|
@@ -24,7 +24,7 @@ describe "getting rack response directly" do
|
|
|
24
24
|
response.should be_a(Array)
|
|
25
25
|
response.length.should == 3
|
|
26
26
|
response[0].should == 405
|
|
27
|
-
response[1]['
|
|
27
|
+
response[1]['content-type'].should == 'text/plain'
|
|
28
28
|
response[2].should == ["method not allowed"]
|
|
29
29
|
end
|
|
30
30
|
|
|
@@ -6,7 +6,7 @@ describe "urls" do
|
|
|
6
6
|
Dragonfly::Response.should_receive(:new).with(
|
|
7
7
|
satisfy{|job| job.to_a == array },
|
|
8
8
|
instance_of(Hash)
|
|
9
|
-
).and_return(double('response', :to_response => [200, {'
|
|
9
|
+
).and_return(double('response', :to_response => [200, {'content-type' => 'text/plain'}, ["OK"]]))
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
let (:app) {
|
data/spec/spec_helper.rb
CHANGED
|
@@ -17,6 +17,12 @@ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
|
|
17
17
|
SAMPLES_DIR = Pathname.new(File.expand_path("../../samples", __FILE__))
|
|
18
18
|
|
|
19
19
|
RSpec.configure do |c|
|
|
20
|
+
c.expect_with(:rspec) do |expectations|
|
|
21
|
+
expectations.syntax = [:should, :expect]
|
|
22
|
+
end
|
|
23
|
+
c.mock_with(:rspec) do |mocks|
|
|
24
|
+
mocks.syntax = [:should, :expect]
|
|
25
|
+
end
|
|
20
26
|
c.include ModelHelpers
|
|
21
27
|
c.include RackHelpers
|
|
22
28
|
end
|
|
@@ -22,7 +22,7 @@ end
|
|
|
22
22
|
match do |actual|
|
|
23
23
|
value.should === image_properties(actual)[property]
|
|
24
24
|
end
|
|
25
|
-
|
|
25
|
+
failure_message do |actual|
|
|
26
26
|
"expected image to have #{property} #{value.inspect}, but it had #{image_properties(actual)[property].inspect}"
|
|
27
27
|
end
|
|
28
28
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dragonfly
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.4.
|
|
4
|
+
version: 1.4.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mark Evans
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: rack
|
|
@@ -52,20 +51,34 @@ dependencies:
|
|
|
52
51
|
- - "~>"
|
|
53
52
|
- !ruby/object:Gem::Version
|
|
54
53
|
version: '2.3'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: ostruct
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: 0.6.1
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: 0.6.1
|
|
55
68
|
- !ruby/object:Gem::Dependency
|
|
56
69
|
name: rspec
|
|
57
70
|
requirement: !ruby/object:Gem::Requirement
|
|
58
71
|
requirements:
|
|
59
72
|
- - "~>"
|
|
60
73
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: '
|
|
74
|
+
version: '3.0'
|
|
62
75
|
type: :development
|
|
63
76
|
prerelease: false
|
|
64
77
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
78
|
requirements:
|
|
66
79
|
- - "~>"
|
|
67
80
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: '
|
|
81
|
+
version: '3.0'
|
|
69
82
|
- !ruby/object:Gem::Dependency
|
|
70
83
|
name: webmock
|
|
71
84
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -271,7 +284,6 @@ homepage: http://github.com/markevans/dragonfly
|
|
|
271
284
|
licenses:
|
|
272
285
|
- MIT
|
|
273
286
|
metadata: {}
|
|
274
|
-
post_install_message:
|
|
275
287
|
rdoc_options: []
|
|
276
288
|
require_paths:
|
|
277
289
|
- lib
|
|
@@ -286,8 +298,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
286
298
|
- !ruby/object:Gem::Version
|
|
287
299
|
version: '0'
|
|
288
300
|
requirements: []
|
|
289
|
-
rubygems_version:
|
|
290
|
-
signing_key:
|
|
301
|
+
rubygems_version: 4.0.10
|
|
291
302
|
specification_version: 4
|
|
292
303
|
summary: Ideal gem for handling attachments in Rails, Sinatra and Rack applications.
|
|
293
304
|
test_files:
|