oahu-dragonfly 0.8.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.
- data/.rspec +1 -0
- data/.yardopts +24 -0
- data/Gemfile +30 -0
- data/History.md +323 -0
- data/LICENSE +20 -0
- data/README.md +88 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/config.ru +14 -0
- data/docs.watchr +1 -0
- data/dragonfly.gemspec +297 -0
- data/extra_docs/Analysers.md +66 -0
- data/extra_docs/Caching.md +23 -0
- data/extra_docs/Configuration.md +124 -0
- data/extra_docs/Couch.md +49 -0
- data/extra_docs/DataStorage.md +153 -0
- data/extra_docs/Encoding.md +67 -0
- data/extra_docs/GeneralUsage.md +121 -0
- data/extra_docs/Generators.md +60 -0
- data/extra_docs/Heroku.md +50 -0
- data/extra_docs/ImageMagick.md +125 -0
- data/extra_docs/Index.md +33 -0
- data/extra_docs/MimeTypes.md +40 -0
- data/extra_docs/Models.md +272 -0
- data/extra_docs/Mongo.md +45 -0
- data/extra_docs/Processing.md +77 -0
- data/extra_docs/Rack.md +52 -0
- data/extra_docs/Rails2.md +57 -0
- data/extra_docs/Rails3.md +62 -0
- data/extra_docs/Sinatra.md +25 -0
- data/extra_docs/URLs.md +169 -0
- data/features/images.feature +47 -0
- data/features/no_processing.feature +14 -0
- data/features/rails_3.0.5.feature +8 -0
- data/features/steps/common_steps.rb +8 -0
- data/features/steps/dragonfly_steps.rb +66 -0
- data/features/steps/rails_steps.rb +28 -0
- data/features/support/env.rb +13 -0
- data/features/support/setup.rb +32 -0
- data/fixtures/rails_3.0.5/files/app/models/album.rb +7 -0
- data/fixtures/rails_3.0.5/files/app/views/albums/new.html.erb +7 -0
- data/fixtures/rails_3.0.5/files/app/views/albums/show.html.erb +6 -0
- data/fixtures/rails_3.0.5/files/config/initializers/dragonfly.rb +4 -0
- data/fixtures/rails_3.0.5/files/features/manage_album_images.feature +38 -0
- data/fixtures/rails_3.0.5/files/features/step_definitions/helper_steps.rb +7 -0
- data/fixtures/rails_3.0.5/files/features/step_definitions/image_steps.rb +25 -0
- data/fixtures/rails_3.0.5/files/features/support/paths.rb +17 -0
- data/fixtures/rails_3.0.5/files/features/text_images.feature +7 -0
- data/fixtures/rails_3.0.5/template.rb +20 -0
- data/irbrc.rb +18 -0
- data/lib/dragonfly.rb +55 -0
- data/lib/dragonfly/active_model_extensions.rb +13 -0
- data/lib/dragonfly/active_model_extensions/attachment.rb +250 -0
- data/lib/dragonfly/active_model_extensions/attachment_class_methods.rb +148 -0
- data/lib/dragonfly/active_model_extensions/class_methods.rb +95 -0
- data/lib/dragonfly/active_model_extensions/instance_methods.rb +28 -0
- data/lib/dragonfly/active_model_extensions/validations.rb +41 -0
- data/lib/dragonfly/analyser.rb +58 -0
- data/lib/dragonfly/analysis/file_command_analyser.rb +32 -0
- data/lib/dragonfly/analysis/image_magick_analyser.rb +6 -0
- data/lib/dragonfly/app.rb +172 -0
- data/lib/dragonfly/config/heroku.rb +19 -0
- data/lib/dragonfly/config/image_magick.rb +6 -0
- data/lib/dragonfly/config/rails.rb +20 -0
- data/lib/dragonfly/configurable.rb +207 -0
- data/lib/dragonfly/core_ext/array.rb +7 -0
- data/lib/dragonfly/core_ext/hash.rb +7 -0
- data/lib/dragonfly/core_ext/object.rb +12 -0
- data/lib/dragonfly/core_ext/string.rb +9 -0
- data/lib/dragonfly/core_ext/symbol.rb +9 -0
- data/lib/dragonfly/data_storage.rb +9 -0
- data/lib/dragonfly/data_storage/couch_data_store.rb +64 -0
- data/lib/dragonfly/data_storage/file_data_store.rb +141 -0
- data/lib/dragonfly/data_storage/mongo_data_store.rb +86 -0
- data/lib/dragonfly/data_storage/s3data_store.rb +145 -0
- data/lib/dragonfly/encoder.rb +13 -0
- data/lib/dragonfly/encoding/image_magick_encoder.rb +6 -0
- data/lib/dragonfly/function_manager.rb +71 -0
- data/lib/dragonfly/generation/image_magick_generator.rb +6 -0
- data/lib/dragonfly/generator.rb +9 -0
- data/lib/dragonfly/hash_with_css_style_keys.rb +21 -0
- data/lib/dragonfly/image_magick/analyser.rb +51 -0
- data/lib/dragonfly/image_magick/config.rb +41 -0
- data/lib/dragonfly/image_magick/encoder.rb +57 -0
- data/lib/dragonfly/image_magick/generator.rb +145 -0
- data/lib/dragonfly/image_magick/processor.rb +99 -0
- data/lib/dragonfly/image_magick/utils.rb +72 -0
- data/lib/dragonfly/image_magick_utils.rb +4 -0
- data/lib/dragonfly/job.rb +451 -0
- data/lib/dragonfly/job_builder.rb +39 -0
- data/lib/dragonfly/job_definitions.rb +26 -0
- data/lib/dragonfly/job_endpoint.rb +15 -0
- data/lib/dragonfly/loggable.rb +28 -0
- data/lib/dragonfly/middleware.rb +20 -0
- data/lib/dragonfly/processing/image_magick_processor.rb +6 -0
- data/lib/dragonfly/processor.rb +9 -0
- data/lib/dragonfly/rails/images.rb +27 -0
- data/lib/dragonfly/response.rb +97 -0
- data/lib/dragonfly/routed_endpoint.rb +40 -0
- data/lib/dragonfly/serializer.rb +32 -0
- data/lib/dragonfly/server.rb +113 -0
- data/lib/dragonfly/simple_cache.rb +23 -0
- data/lib/dragonfly/temp_object.rb +175 -0
- data/lib/dragonfly/url_mapper.rb +78 -0
- data/samples/beach.png +0 -0
- data/samples/egg.png +0 -0
- data/samples/round.gif +0 -0
- data/samples/sample.docx +0 -0
- data/samples/taj.jpg +0 -0
- data/spec/dragonfly/active_model_extensions/model_spec.rb +1426 -0
- data/spec/dragonfly/active_model_extensions/spec_helper.rb +91 -0
- data/spec/dragonfly/analyser_spec.rb +123 -0
- data/spec/dragonfly/analysis/file_command_analyser_spec.rb +48 -0
- data/spec/dragonfly/app_spec.rb +135 -0
- data/spec/dragonfly/configurable_spec.rb +461 -0
- data/spec/dragonfly/core_ext/array_spec.rb +19 -0
- data/spec/dragonfly/core_ext/hash_spec.rb +19 -0
- data/spec/dragonfly/core_ext/string_spec.rb +17 -0
- data/spec/dragonfly/core_ext/symbol_spec.rb +17 -0
- data/spec/dragonfly/data_storage/couch_data_store_spec.rb +76 -0
- data/spec/dragonfly/data_storage/file_data_store_spec.rb +296 -0
- data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +57 -0
- data/spec/dragonfly/data_storage/s3_data_store_spec.rb +258 -0
- data/spec/dragonfly/data_storage/shared_data_store_examples.rb +77 -0
- data/spec/dragonfly/function_manager_spec.rb +154 -0
- data/spec/dragonfly/hash_with_css_style_keys_spec.rb +24 -0
- data/spec/dragonfly/image_magick/analyser_spec.rb +64 -0
- data/spec/dragonfly/image_magick/encoder_spec.rb +41 -0
- data/spec/dragonfly/image_magick/generator_spec.rb +172 -0
- data/spec/dragonfly/image_magick/processor_spec.rb +233 -0
- data/spec/dragonfly/image_magick/utils_spec.rb +18 -0
- data/spec/dragonfly/job_builder_spec.rb +37 -0
- data/spec/dragonfly/job_definitions_spec.rb +35 -0
- data/spec/dragonfly/job_endpoint_spec.rb +173 -0
- data/spec/dragonfly/job_spec.rb +1046 -0
- data/spec/dragonfly/loggable_spec.rb +80 -0
- data/spec/dragonfly/middleware_spec.rb +47 -0
- data/spec/dragonfly/routed_endpoint_spec.rb +48 -0
- data/spec/dragonfly/serializer_spec.rb +61 -0
- data/spec/dragonfly/server_spec.rb +278 -0
- data/spec/dragonfly/simple_cache_spec.rb +27 -0
- data/spec/dragonfly/temp_object_spec.rb +306 -0
- data/spec/dragonfly/url_mapper_spec.rb +126 -0
- data/spec/functional/deprecations_spec.rb +51 -0
- data/spec/functional/image_magick_app_spec.rb +27 -0
- data/spec/functional/model_urls_spec.rb +85 -0
- data/spec/functional/remote_on_the_fly_spec.rb +51 -0
- data/spec/functional/to_response_spec.rb +31 -0
- data/spec/spec_helper.rb +51 -0
- data/spec/support/argument_matchers.rb +19 -0
- data/spec/support/image_matchers.rb +47 -0
- data/spec/support/simple_matchers.rb +53 -0
- data/yard/handlers/configurable_attr_handler.rb +38 -0
- data/yard/setup.rb +15 -0
- data/yard/templates/default/fulldoc/html/css/common.css +107 -0
- data/yard/templates/default/layout/html/layout.erb +89 -0
- data/yard/templates/default/module/html/configuration_summary.erb +31 -0
- data/yard/templates/default/module/setup.rb +17 -0
- metadata +544 -0
data/extra_docs/Mongo.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Mongo
|
|
2
|
+
=====
|
|
3
|
+
Dragonfly can be used with any ActiveModel-compatible model, therefore libraries like [Mongoid](http://mongoid.org) work out of the box.
|
|
4
|
+
|
|
5
|
+
Furthermore, Mongo DB has support for storing blob-like objects directly in the database (using MongoDB 'GridFS'),
|
|
6
|
+
so you can make use of this with the supplied {Dragonfly::DataStorage::MongoDataStore MongoDataStore}.
|
|
7
|
+
|
|
8
|
+
For more info about ActiveModel, see {file:Models}.
|
|
9
|
+
|
|
10
|
+
For more info about using the Mongo data store, see {file:DataStorage}.
|
|
11
|
+
|
|
12
|
+
Example setup in Rails, using Mongoid
|
|
13
|
+
-------------------------------------
|
|
14
|
+
In config/initializers/dragonfly.rb:
|
|
15
|
+
|
|
16
|
+
require 'dragonfly'
|
|
17
|
+
|
|
18
|
+
app = Dragonfly[:images]
|
|
19
|
+
|
|
20
|
+
# Get database name from config/mongoid.yml
|
|
21
|
+
db = YAML.load_file(Rails.root.join('config/mongoid.yml'))[Rails.env]['database']
|
|
22
|
+
|
|
23
|
+
# Configure to use ImageMagick, Rails defaults, and the Mongo data store
|
|
24
|
+
app.configure_with(:imagemagick)
|
|
25
|
+
app.configure_with(:rails) do |c|
|
|
26
|
+
c.datastore = Dragonfly::DataStorage::MongoDataStore.new :database => db
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Allow all mongoid models to use the macro 'image_accessor'
|
|
30
|
+
app.define_macro_on_include(Mongoid::Document, :image_accessor)
|
|
31
|
+
|
|
32
|
+
# ... any other setup, see Rails docs
|
|
33
|
+
|
|
34
|
+
Then in models:
|
|
35
|
+
|
|
36
|
+
class Album
|
|
37
|
+
include Mongoid::Document
|
|
38
|
+
|
|
39
|
+
field :cover_image_uid
|
|
40
|
+
image_accessor :cover_image
|
|
41
|
+
|
|
42
|
+
# ...
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
See {file:Models} for more info.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
Processing
|
|
2
|
+
==========
|
|
3
|
+
Registered processors allow you to modify data, e.g. resizing an image.
|
|
4
|
+
|
|
5
|
+
You can register as many processors as you like.
|
|
6
|
+
|
|
7
|
+
Let's say we have a Dragonfly app
|
|
8
|
+
|
|
9
|
+
app = Dragonfly[:images]
|
|
10
|
+
|
|
11
|
+
and an image object (actually a {Dragonfly::Job Job} object)...
|
|
12
|
+
|
|
13
|
+
image = app.fetch('some/uid')
|
|
14
|
+
|
|
15
|
+
...OR a Dragonfly model accessor...
|
|
16
|
+
|
|
17
|
+
image = @album.cover_image
|
|
18
|
+
|
|
19
|
+
We can process it using any processing methods that have been registered with the processor.
|
|
20
|
+
|
|
21
|
+
Lazy evaluation
|
|
22
|
+
---------------
|
|
23
|
+
|
|
24
|
+
new_image = image.process(:some_method)
|
|
25
|
+
|
|
26
|
+
doesn't actually do anything until you call something on the returned {Dragonfly::Job Job} object, like `url`, `data`, etc.
|
|
27
|
+
|
|
28
|
+
Bang method
|
|
29
|
+
-----------
|
|
30
|
+
|
|
31
|
+
image.process!(:some_method)
|
|
32
|
+
|
|
33
|
+
modifies the image object itself, rather than returning a new object.
|
|
34
|
+
|
|
35
|
+
ImageMagick Processor
|
|
36
|
+
---------------------
|
|
37
|
+
See {file:ImageMagick}.
|
|
38
|
+
|
|
39
|
+
Custom Processors
|
|
40
|
+
-----------------
|
|
41
|
+
|
|
42
|
+
To register a single custom processor:
|
|
43
|
+
|
|
44
|
+
app.processor.add :watermark do |temp_object, *args|
|
|
45
|
+
# use temp_object.data, temp_object.path, temp_object.file, etc.
|
|
46
|
+
SomeLibrary.add_watermark(temp_object.data, 'some/watermark/file.png')
|
|
47
|
+
# return a String, Pathname, File or Tempfile
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
new_image = image.process(:watermark)
|
|
51
|
+
|
|
52
|
+
You can create a class like the ImageMagick one above, in which case all public methods will be counted as processing methods.
|
|
53
|
+
Each method takes the temp_object as its argument, plus any other args.
|
|
54
|
+
|
|
55
|
+
class MyProcessor
|
|
56
|
+
|
|
57
|
+
def coolify(temp_object, opts={})
|
|
58
|
+
SomeLib.coolify(temp_object.data, opts)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def uglify(temp_object, ugliness)
|
|
62
|
+
`uglify -i #{temp_object.path} -u #{ugliness}`
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def my_helper_method
|
|
68
|
+
# do stuff
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
app.processor.register(MyProcessor)
|
|
74
|
+
|
|
75
|
+
new_image = image.coolify(:some => :args)
|
|
76
|
+
|
|
77
|
+
new_image = image.uglify(:loads)
|
data/extra_docs/Rack.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
Rack
|
|
2
|
+
====
|
|
3
|
+
For more info about using Rack applications, see the docs at {http://rack.rubyforge.org/}
|
|
4
|
+
|
|
5
|
+
Basic usage involves storing data (e.g. images),
|
|
6
|
+
then serving it in some form.
|
|
7
|
+
|
|
8
|
+
A basic rackup file `config.ru`:
|
|
9
|
+
|
|
10
|
+
require 'rubygems'
|
|
11
|
+
require 'dragonfly'
|
|
12
|
+
|
|
13
|
+
Dragonfly[:my_app_name].configure do |c|
|
|
14
|
+
# ... configuration here
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
run Dragonfly:App[:my_app_name]
|
|
18
|
+
|
|
19
|
+
See {file:Configuration} for more details.
|
|
20
|
+
|
|
21
|
+
The basic flow is instantiate an app -> configure it -> run it.
|
|
22
|
+
|
|
23
|
+
Example: Using to serve resized images
|
|
24
|
+
--------------------------------------
|
|
25
|
+
|
|
26
|
+
`config.ru`:
|
|
27
|
+
|
|
28
|
+
require 'rubygems'
|
|
29
|
+
require 'dragonfly'
|
|
30
|
+
|
|
31
|
+
app = Dragonfly[:images].configure_with(:imagemagick)
|
|
32
|
+
|
|
33
|
+
run app
|
|
34
|
+
|
|
35
|
+
This enables the app to use all the ImageMagick goodies provided by Dragonfly (see {file:Configuration}).
|
|
36
|
+
By default the {Dragonfly::DataStorage::FileDataStore file data store} is used.
|
|
37
|
+
|
|
38
|
+
In the console:
|
|
39
|
+
|
|
40
|
+
app = Dragonfly[:images]
|
|
41
|
+
|
|
42
|
+
# Store
|
|
43
|
+
uid = app.store(File.new('path/to/image.png')) # ===> unique uid
|
|
44
|
+
|
|
45
|
+
# Get the url for a thumbnail
|
|
46
|
+
url = app.fetch(uid).thumb('400x300').url # ===> "/media/BAhbBlsHOgZmIg9hc..."
|
|
47
|
+
|
|
48
|
+
Now when we visit the url `/media/BAhbBlsHOgZmIg9hc...` in the browser, we get a resized image!
|
|
49
|
+
|
|
50
|
+
Mounting in Rack
|
|
51
|
+
----------------
|
|
52
|
+
See {file:URLs}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
Using With Rails 2.3
|
|
2
|
+
====================
|
|
3
|
+
|
|
4
|
+
**NOTE: RAILS 2.3 IS NOT SUPPORTED IN NEW VERSIONS OF DRAGONFLY SO PLEASE USE VERSION 0.8.2**
|
|
5
|
+
|
|
6
|
+
Setting up the quick way
|
|
7
|
+
------------------------
|
|
8
|
+
config/initializers/dragonfly.rb:
|
|
9
|
+
|
|
10
|
+
require 'dragonfly/rails/images'
|
|
11
|
+
|
|
12
|
+
Setting up the more explicit way
|
|
13
|
+
--------------------------------
|
|
14
|
+
You can do the above explicitly.
|
|
15
|
+
|
|
16
|
+
config/initializers/dragonfly.rb:
|
|
17
|
+
|
|
18
|
+
require 'dragonfly'
|
|
19
|
+
|
|
20
|
+
app = Dragonfly[:images]
|
|
21
|
+
app.configure_with(:imagemagick)
|
|
22
|
+
app.configure_with(:rails)
|
|
23
|
+
|
|
24
|
+
app.define_macro(ActiveRecord::Base, :image_accessor)
|
|
25
|
+
|
|
26
|
+
environment.rb:
|
|
27
|
+
|
|
28
|
+
config.middleware.insert_after 'Rack::Lock', 'Dragonfly::Middleware', :images, '/media'
|
|
29
|
+
config.middleware.insert_before 'Dragonfly::Middleware', 'Rack::Cache', {
|
|
30
|
+
:verbose => true,
|
|
31
|
+
:metastore => "file:#{Rails.root}/tmp/dragonfly/cache/meta",
|
|
32
|
+
:entitystore => "file:#{Rails.root}/tmp/dragonfly/cache/body"
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
Gems
|
|
36
|
+
----
|
|
37
|
+
environment.rb
|
|
38
|
+
|
|
39
|
+
config.gem 'dragonfly', '0.8.2'
|
|
40
|
+
config.gem 'rack-cache', :lib => 'rack/cache'
|
|
41
|
+
|
|
42
|
+
Capistrano
|
|
43
|
+
----------
|
|
44
|
+
If using Capistrano with the above, you probably will want to keep the cache between deploys, so in deploy.rb:
|
|
45
|
+
|
|
46
|
+
namespace :dragonfly do
|
|
47
|
+
desc "Symlink the Rack::Cache files"
|
|
48
|
+
task :symlink, :roles => [:app] do
|
|
49
|
+
run "mkdir -p #{shared_path}/tmp/dragonfly && ln -nfs #{shared_path}/tmp/dragonfly #{release_path}/tmp/dragonfly"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
after 'deploy:update_code', 'dragonfly:symlink'
|
|
53
|
+
|
|
54
|
+
Use it!
|
|
55
|
+
-------
|
|
56
|
+
|
|
57
|
+
To see what you can do with the model accessors, see {file:Models}.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
Using With Rails 3
|
|
2
|
+
==================
|
|
3
|
+
|
|
4
|
+
Setting up the quick way
|
|
5
|
+
------------------------
|
|
6
|
+
config/initializers/dragonfly.rb:
|
|
7
|
+
|
|
8
|
+
require 'dragonfly/rails/images'
|
|
9
|
+
|
|
10
|
+
Setting up the more explicit way
|
|
11
|
+
--------------------------------
|
|
12
|
+
You can do the above explicitly.
|
|
13
|
+
|
|
14
|
+
config/initializers/dragonfly.rb:
|
|
15
|
+
|
|
16
|
+
require 'dragonfly'
|
|
17
|
+
|
|
18
|
+
app = Dragonfly[:images]
|
|
19
|
+
app.configure_with(:imagemagick)
|
|
20
|
+
app.configure_with(:rails)
|
|
21
|
+
|
|
22
|
+
app.define_macro(ActiveRecord::Base, :image_accessor)
|
|
23
|
+
|
|
24
|
+
application.rb:
|
|
25
|
+
|
|
26
|
+
config.middleware.insert_after 'Rack::Lock', 'Dragonfly::Middleware', :images
|
|
27
|
+
config.middleware.insert_before 'Dragonfly::Middleware', 'Rack::Cache', {
|
|
28
|
+
:verbose => true,
|
|
29
|
+
:metastore => "file:#{Rails.root}/tmp/dragonfly/cache/meta",
|
|
30
|
+
:entitystore => "file:#{Rails.root}/tmp/dragonfly/cache/body"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
Gemfile
|
|
34
|
+
-------
|
|
35
|
+
|
|
36
|
+
gem 'dragonfly', '~>0.8.2'
|
|
37
|
+
gem 'rack-cache', :require => 'rack/cache'
|
|
38
|
+
|
|
39
|
+
Capistrano
|
|
40
|
+
----------
|
|
41
|
+
If using Capistrano with the above, you probably will want to keep the cache between deploys, so in deploy.rb:
|
|
42
|
+
|
|
43
|
+
namespace :dragonfly do
|
|
44
|
+
desc "Symlink the Rack::Cache files"
|
|
45
|
+
task :symlink, :roles => [:app] do
|
|
46
|
+
run "mkdir -p #{shared_path}/tmp/dragonfly && ln -nfs #{shared_path}/tmp/dragonfly #{release_path}/tmp/dragonfly"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
after 'deploy:update_code', 'dragonfly:symlink'
|
|
50
|
+
|
|
51
|
+
Use it!
|
|
52
|
+
-------
|
|
53
|
+
|
|
54
|
+
To see what you can do with the model accessors, see {file:Models}.
|
|
55
|
+
|
|
56
|
+
Mounting in routes.rb
|
|
57
|
+
---------------------
|
|
58
|
+
Instead of mounting as a middleware, you could skip that bit and mount directly in the routes.rb file:
|
|
59
|
+
|
|
60
|
+
match '/media/*:dragonfly', :to => Dragonfly[:images]
|
|
61
|
+
|
|
62
|
+
Make sure the the path prefix matches the Dragonfly app's configured url_path_prefix (which is /media by default for Rails).
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
Sinatra
|
|
2
|
+
=======
|
|
3
|
+
You can use {Dragonfly::Job Job}'s `to_response` method like so:
|
|
4
|
+
|
|
5
|
+
app = Dragonfly[:images].configure_with(:imagemagick)
|
|
6
|
+
|
|
7
|
+
get '/images/:size.:format' do |size, format|
|
|
8
|
+
app.fetch_file('~/some/image.png').thumb(size).encode(format).to_response(env)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
`to_response` returns a rack-style response array with status, headers and body.
|
|
12
|
+
|
|
13
|
+
NOTE: uids from the datastore currently have slashes and dots in them so may cause problems when using ':uid' as
|
|
14
|
+
a path segment.
|
|
15
|
+
|
|
16
|
+
or you can mount as a middleware, like in rails:
|
|
17
|
+
|
|
18
|
+
Dragonfly[:images].configure_with(:imagemagick) do |c|
|
|
19
|
+
c.url_path_prefix = '/media'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
use Dragonfly::Middleware, :images
|
|
23
|
+
|
|
24
|
+
get '/' #... do
|
|
25
|
+
# ...
|
data/extra_docs/URLs.md
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
URLs
|
|
2
|
+
====
|
|
3
|
+
|
|
4
|
+
We can get urls for any kind of job:
|
|
5
|
+
|
|
6
|
+
app = Dragonfly[:images]
|
|
7
|
+
|
|
8
|
+
app.fetch('my_uid').process(:flip).url # "/BAhbBlsH..."
|
|
9
|
+
app.generate(:text, 'hello').thumb('500x302').gif.url # "/BAhbCFsHOgZ..."
|
|
10
|
+
|
|
11
|
+
Path prefix
|
|
12
|
+
-----------
|
|
13
|
+
If the app is mounted with a path prefix (such as when using in Rails), then we need to add this prefix
|
|
14
|
+
to the urls:
|
|
15
|
+
|
|
16
|
+
app.url_path_prefix = '/media'
|
|
17
|
+
|
|
18
|
+
(or done in a configuration block).
|
|
19
|
+
|
|
20
|
+
app.fetch('my_uid').url # "/media/BAhbBlsH..."
|
|
21
|
+
|
|
22
|
+
This is done for you when using {file:Configuration Rails defaults}.
|
|
23
|
+
|
|
24
|
+
You can override it using
|
|
25
|
+
|
|
26
|
+
app.fetch('my_uid').url(:path_prefix => '/images') # "/images/BAhbBlsH..."
|
|
27
|
+
|
|
28
|
+
Host
|
|
29
|
+
----
|
|
30
|
+
You can also set a host for the urls
|
|
31
|
+
|
|
32
|
+
app.url_host = 'http://some.host'
|
|
33
|
+
app.fetch('my_uid').url # "http://some.host/BAhb..."
|
|
34
|
+
|
|
35
|
+
app.fetch('my_uid').url(:host => 'http://localhost:80') # "http://localhost:80/BAh..."
|
|
36
|
+
|
|
37
|
+
Suffix
|
|
38
|
+
------
|
|
39
|
+
You can set a suffix for the urls (for example if some other component behaves badly with urls that have no file extension).
|
|
40
|
+
|
|
41
|
+
Note that this has no effect on the response.
|
|
42
|
+
|
|
43
|
+
app.url_suffix = '.jpg'
|
|
44
|
+
app.fetch('some/uid').url # "...b21lL3VpZA.jpg"
|
|
45
|
+
|
|
46
|
+
You can also pass it a block, that yields the {Dragonfly::Job Job}, for example:
|
|
47
|
+
|
|
48
|
+
app.url_suffix = proc{|job|
|
|
49
|
+
"/#{job.uid_basename}#{job.encoded_extname || job.uid_extname}"
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
app.fetch('2007/painting.pdf').url # "...eS5ib2R5/painting.pdf"
|
|
53
|
+
app.fetch('2007/painting.pdf').encode(:png).url # "...gZlOgbmc/painting.png"
|
|
54
|
+
|
|
55
|
+
And you can override it:
|
|
56
|
+
|
|
57
|
+
app.fetch('some/uid').url(:suffix => '/yellowbelly') # "...b21lL3VpZA/yellowbelly"
|
|
58
|
+
|
|
59
|
+
Content-Disposition
|
|
60
|
+
-------------------
|
|
61
|
+
You can manually set the content-disposition of the response:
|
|
62
|
+
|
|
63
|
+
app.content_disposition = :attachment # should be :inline or :attachment (or :hidden)
|
|
64
|
+
|
|
65
|
+
`:attachment` tells the browser to download it, `:inline` tells it to display in-browser if possible.
|
|
66
|
+
|
|
67
|
+
You can also use a block:
|
|
68
|
+
|
|
69
|
+
app.content_disposition = proc{|job, request|
|
|
70
|
+
if job.format == :jpg || request['d'] == 'inline' # request is a Rack::Request object
|
|
71
|
+
:inline
|
|
72
|
+
else
|
|
73
|
+
:attachment
|
|
74
|
+
end
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
Downloaded filename
|
|
78
|
+
-------------------
|
|
79
|
+
To specify the filename the browser uses for 'Save As' dialogues:
|
|
80
|
+
|
|
81
|
+
app.content_filename = proc{|job, request|
|
|
82
|
+
"#{job.basename}_#{job.process_steps.first.name}.#{job.encoded_format || job.ext}"
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
This will for example give the following filenames for the following jobs:
|
|
86
|
+
|
|
87
|
+
app.fetch('some/tree.png').process(:greyscale) # -> 'tree_greyscale.png'
|
|
88
|
+
app.fetch('some/tree.png').process(:greyscale).gif # -> 'tree_greyscale.gif'
|
|
89
|
+
|
|
90
|
+
By default the original filename is used, with a modified extension if it's been encoded.
|
|
91
|
+
|
|
92
|
+
Routed Endpoints
|
|
93
|
+
----------------
|
|
94
|
+
You can also use a number of Rack-based routers and create Dragonfly endpoints.
|
|
95
|
+
|
|
96
|
+
If we have an app set up for using ImageMagick:
|
|
97
|
+
|
|
98
|
+
app = Dragonfly[:images].configure_with(:imagemagick)
|
|
99
|
+
|
|
100
|
+
Then to get the url '/text/hello' to display the text "hello"...
|
|
101
|
+
|
|
102
|
+
Rails 3 (routes.rb):
|
|
103
|
+
|
|
104
|
+
match '/text/:text' => app.endpoint{|params, app|
|
|
105
|
+
app.generate(:text, params[:text])
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
{http://github.com/josh/rack-mount Rack-Mount}:
|
|
109
|
+
|
|
110
|
+
Routes = Rack::Mount::RouteSet.new do |set|
|
|
111
|
+
|
|
112
|
+
set.add_route app.endpoint{|params, a| a.generate(:text, params[:text]) },
|
|
113
|
+
:path_info => %r{/text/(?:<text>.+)}
|
|
114
|
+
|
|
115
|
+
# ...
|
|
116
|
+
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
{http://github.com/joshbuddy/usher Usher}:
|
|
120
|
+
|
|
121
|
+
routes = Usher::Interface.for(:rack) do
|
|
122
|
+
add('/text/:text').to app.endpoint{|params, app|
|
|
123
|
+
app.generate(:text, params[:text])
|
|
124
|
+
}
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
{http://github.com/joshbuddy/http_router HTTP Router}:
|
|
128
|
+
|
|
129
|
+
r = HttpRouter.new
|
|
130
|
+
r.add('/text/:text').to app.endpoint{|params, app|
|
|
131
|
+
app.generate(:text, params[:text])
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
In each case the url will need to be generated by the router of choice, or manually.
|
|
135
|
+
|
|
136
|
+
Simple Endpoints
|
|
137
|
+
----------------
|
|
138
|
+
{Dragonfly::Job Job} objects can also be turned straight into Rack endpoints using `to_app`, e.g. in Rails 3:
|
|
139
|
+
|
|
140
|
+
match '/beach' => app.fetch_file('~/some/image.png').thumb('100x100#').jpg.to_app
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
Denial-of-service attacks
|
|
144
|
+
-------------------------
|
|
145
|
+
Although the standard urls are fairly cryptic, a malicious person who knows the Dragonfly source code could potentially
|
|
146
|
+
work out how to generate urls to spam your server with heavy requests, e.g. resize to 100000 by 100000 pixels.
|
|
147
|
+
|
|
148
|
+
Therefore the app can be protected by requiring the presence of a "DOS-protection" SHA in the urls:
|
|
149
|
+
|
|
150
|
+
app.configure do |c|
|
|
151
|
+
c.protect_from_dos_attacks = true
|
|
152
|
+
c.secret = 'You should supply some random secret here'
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
Then the standard generated urls will have a SHA query parameter attached:
|
|
156
|
+
|
|
157
|
+
app.fetch('my_uid').url # "/BAhbBlsHOgZmIghzZGY?s=df76ba27"
|
|
158
|
+
|
|
159
|
+
Any requests without the correct SHA parameter result in a 400 (bad parameters) error response.
|
|
160
|
+
|
|
161
|
+
You can also validate for a correct SHA using routed endpoints:
|
|
162
|
+
|
|
163
|
+
match '/text/:text' => app.endpoint{|params, app|
|
|
164
|
+
app.generate(:text, params[:text]).validate_sha!(params[:sha])
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
... where obviously you need to pass in a 'sha' parameter to the url, which can be found using
|
|
168
|
+
|
|
169
|
+
app.generate(:text, 'some text').sha
|