Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
  • 18 commits
  • 13 files changed
  • 0 commit comments
  • 2 contributors
View
3  .travis.yml
@@ -2,4 +2,5 @@ bundler_args: "--without development"
script: "bundle exec rspec spec"
rvm:
- 1.8.7
- - 1.9.2
+ - 1.9.2
+ - 1.9.3
View
8 Gemfile
@@ -1,16 +1,14 @@
source 'http://rubygems.org'
-gem 'sinatra', '~> 1.2.1', :require => 'sinatra/base'
-gem 'sinatra-synchrony', '~> 0.2.0', :require => 'sinatra/synchrony', :platforms => [:ruby_19, :jruby]
-gem 'dragonfly', '~> 0.9.1'
+gem 'sinatra', '~> 1.2', :require => 'sinatra/base'
+gem 'dragonfly', '~> 0.9.5'
gem 'addressable', '~> 2.2', :require => 'addressable/uri'
-gem 'httparty', '~> 0.7.3'
+gem 'httparty', '~> 0.8.1'
gem 'activesupport', '>= 2.0.0', :require => false
group :development do
gem 'jeweler', '~> 1.5'
- gem 'rcov', '>= 0'
end
group :development, :test do
View
87 Gemfile.lock
@@ -1,65 +1,52 @@
GEM
remote: http://rubygems.org/
specs:
- activesupport (3.1.0)
+ activesupport (3.2.0)
+ i18n (~> 0.6)
multi_json (~> 1.0)
addressable (2.2.6)
- async-rack (0.5.1)
- rack (~> 1.1)
- crack (0.1.8)
+ crack (0.3.1)
diff-lcs (1.1.3)
- dragonfly (0.9.8)
+ dragonfly (0.9.10)
rack
- em-http-request (1.0.0)
- addressable (>= 2.2.3)
- em-socksify
- eventmachine (>= 1.0.0.beta.3)
- http_parser.rb (>= 0.5.2)
- em-resolv-replace (1.1.1)
- em-socksify (0.1.0)
- eventmachine
- em-synchrony (1.0.0)
- eventmachine (>= 1.0.0.beta.1)
- eventmachine (1.0.0.beta.3)
git (1.2.5)
- http_parser.rb (0.5.2)
- httparty (0.7.8)
- crack (= 0.1.8)
+ httparty (0.8.1)
+ multi_json
+ multi_xml
+ i18n (0.6.0)
imagesize (0.1.1)
- jeweler (1.6.4)
+ jeweler (1.8.3)
bundler (~> 1.0)
git (>= 1.2.5)
rake
- multi_json (1.0.3)
- newrelic_rpm (3.1.2)
- rack (1.3.2)
- rack-fiber_pool (0.9.2)
+ rdoc
+ json (1.6.5)
+ multi_json (1.0.4)
+ multi_xml (0.4.1)
+ newrelic_rpm (3.3.1)
+ rack (1.4.1)
+ rack-protection (1.2.0)
+ rack
rack-test (0.6.1)
rack (>= 1.0)
- rake (0.9.2)
- rcov (0.9.10)
- rspec (2.6.0)
- rspec-core (~> 2.6.0)
- rspec-expectations (~> 2.6.0)
- rspec-mocks (~> 2.6.0)
- rspec-core (2.6.4)
- rspec-expectations (2.6.0)
+ rake (0.9.2.2)
+ rdoc (3.12)
+ json (~> 1.4)
+ rspec (2.8.0)
+ rspec-core (~> 2.8.0)
+ rspec-expectations (~> 2.8.0)
+ rspec-mocks (~> 2.8.0)
+ rspec-core (2.8.0)
+ rspec-expectations (2.8.0)
diff-lcs (~> 1.1.2)
- rspec-mocks (2.6.0)
- sinatra (1.2.6)
- rack (~> 1.1)
- tilt (< 2.0, >= 1.2.2)
- sinatra-synchrony (0.2.0)
- async-rack (>= 0.5.1)
- em-http-request (= 1.0.0)
- em-resolv-replace (>= 1.1.1)
- em-synchrony (= 1.0.0)
- eventmachine (= 1.0.0.beta.3)
- rack-fiber_pool (= 0.9.2)
- sinatra (>= 1.0)
+ rspec-mocks (2.8.0)
+ sinatra (1.3.2)
+ rack (~> 1.3, >= 1.3.6)
+ rack-protection (~> 1.2)
+ tilt (~> 1.3, >= 1.3.3)
tilt (1.3.3)
- webmock (1.7.6)
- addressable (> 2.2.5, ~> 2.2)
+ webmock (1.7.10)
+ addressable (~> 2.2, > 2.2.5)
crack (>= 0.1.7)
PLATFORMS
@@ -68,14 +55,12 @@ PLATFORMS
DEPENDENCIES
activesupport (>= 2.0.0)
addressable (~> 2.2)
- dragonfly (~> 0.9.1)
- httparty (~> 0.7.3)
+ dragonfly (~> 0.9.5)
+ httparty (~> 0.8.1)
imagesize (~> 0.1)
jeweler (~> 1.5)
newrelic_rpm
rack-test
- rcov
rspec (~> 2.4)
- sinatra (~> 1.2.1)
- sinatra-synchrony (~> 0.2.0)
+ sinatra (~> 1.2)
webmock (~> 1.6)
View
17 HISTORY.md
@@ -1,6 +1,21 @@
This gem respects [semantic versioning](http://semver.org/).
-# 1.3.0 (9/5/11)
+# 1.4.0 (1/26/12)
+
+[commits](https://github.com/afeld/magickly/compare/v1.3.0...v1.4.0)
+
+* SECURITY: don't pass cookies to image request (tolsen)
+* removed async support (for now) - needs more extensive testing
+* added /q syntax as alternative to query params (tolsen)
+* added JCN effect
+
+# 1.2.1 (12/21/11)
+
+[commits](https://github.com/afeld/magickly/compare/v1.2.0...v1.2.1)
+
+* made compatible w/ Dragonfly v0.9.8 (tolsen)
+
+# 1.3.0 (9/5/11) - YANKED
[commits](https://github.com/afeld/magickly/compare/v1.2.0...v1.3.0)
View
22 README.md
@@ -88,6 +88,12 @@ where *threshold* is a value between 0 and 100.
[http://magickly.jux.com/?src=http://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/Imagemagick-logo.png/200px-Imagemagick-logo.png&halftone=60](http://magickly.jux.com/?src=http://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/Imagemagick-logo.png/200px-Imagemagick-logo.png&halftone=60)
+### jcn=true
+
+![JCN imagemagick logo](http://magickly.jux.com/?src=http://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/Imagemagick-logo.png/200px-Imagemagick-logo.png&jcn=true)
+
+[http://magickly.jux.com/?src=http://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/Imagemagick-logo.png/200px-Imagemagick-logo.png&jcn=true](http://magickly.jux.com/?src=http://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/Imagemagick-logo.png/200px-Imagemagick-logo.png&jcn=true)
+
### resize=*geometry*
![resized imagemagick logo](http://magickly.jux.com/?src=http://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/Imagemagick-logo.png/200px-Imagemagick-logo.png&resize=100x100)
@@ -128,6 +134,22 @@ where *threshold* is a value between 0 and 100.
[http://magickly.jux.com/?src=http://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/Imagemagick-logo.png/200px-Imagemagick-logo.png&two_color=true](http://magickly.jux.com/?src=http://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/Imagemagick-logo.png/200px-Imagemagick-logo.png&two_color=true)
+## Alternate Syntax
+
+Some CDNs are jerks and don't respect query params on resources (_ahem_ CLOUDFRONT _ahem_) when caching. To use this syntax:
+
+* replace the question mark that starts the query string (`?`) with `q/`
+* replace the ampersands (`&`) and equals signs (`=`) with forward slashes (`/`)
+* make sure the `src` is encoded - this can be done in Javascript with `encodeURIComponent()`
+
+Therefore, instead of
+
+ http://magickly.jux.com/?src=http://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/Imagemagick-logo.png/200px-Imagemagick-logo.png&thumb=200x100
+
+the new URL would be
+
+ http://magickly.jux.com/q/src/http%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Fthumb%2F0%2F0d%2FImagemagick-logo.png%2F200px-Imagemagick-logo.png/thumb/200x100
+
## Analyzers
Magickly v1.2.0 introduces the ability to retrieve image properties via a REST API. For example, to retrieve the number of colors in the photo, visit:
View
2  VERSION
@@ -1 +1 @@
-1.3.0
+1.4.0
View
4 lib/dragonfly/data_storage/remote_data_store.rb
@@ -7,14 +7,12 @@ module DataStorage
class RemoteDataStore
include Configurable
- configurable_attr :cookie_str
-
def store(temp_object, opts={})
raise "Sorry friend, this datastore is read-only."
end
def retrieve(uid)
- response = HTTParty.get uid, :headers => {'cookie' => cookie_str || ''}, :timeout => 3
+ response = HTTParty.get uid, :timeout => 3
unless response.ok?
#raise Forbidden if response.code == 403
raise DataNotFound
View
12 lib/magickly.rb
@@ -3,11 +3,6 @@
require 'active_support/ordered_hash'
require 'sinatra/base'
-unless RUBY_VERSION.start_with? '1.8'
- require 'sinatra/synchrony'
- Sinatra::Synchrony.overload_tcpsocket!
-end
-
require 'addressable/uri'
require 'dragonfly'
Dir["#{File.dirname(__FILE__)}/dragonfly/**/*.rb"].each {|file| require file }
@@ -22,11 +17,8 @@ module Magickly
c.datastore = Dragonfly::DataStorage::RemoteDataStore.new
c.log = Logger.new($stdout)
- begin
- c.log_commands = true
- rescue Dragonfly::Configurable::BadConfigAttribute
- # seems this config param was removed from Dragonfly ~v0.98
- end
+ # seems this config param was removed from Dragonfly ~v0.9.8
+ # c.log_commands = true
end
class << self
View
57 lib/magickly/app.rb
@@ -1,7 +1,5 @@
module Magickly
class App < Sinatra::Base
- register Sinatra::Synchrony unless RUBY_VERSION.start_with? '1.8'
-
RESERVED_PARAMS = ['src']
DEMO_IMAGE = 'http://farm4.static.flickr.com/3351/3450592233_c29fde01ef_z.jpg'
@@ -21,11 +19,6 @@ class App < Sinatra::Base
redirect request.url.sub(request_host_with_port, app_host), 301
end
- Magickly.dragonfly.datastore.configure do |d|
- # pass cookies to subsequent request
- d.cookie_str = request.env["rack.request.cookie_string"]
- end
-
# parse query params so they are ordered
@options = ActiveSupport::OrderedHash.new
request.query_string.split('&').each do |e|
@@ -35,21 +28,28 @@ class App < Sinatra::Base
end
get '/' do
- src = params['src']
+ process_src_or_display_demo params[:src], @options
+ end
+
+ get '/q/*' do
+ src = nil
+ opts = ActiveSupport::OrderedHash.new
+ splat = request.path_info.sub /^\/q\//, ''
- if src
- # process image
- url = uri_to_url(src)
- image = Magickly.process_src(url, @options)
- image.to_response(env)
- else
- # display demo page
-
- # get combined list of jobs and processor methods
- @methods = ( Magickly.dragonfly.job_methods | Magickly.dragonfly.processor_methods )
- @methods.sort!{|m1, m2| m1.to_s <=> m2.to_s }
- erb :index
+ splat.split('/').each_slice(2) do |k, v|
+ if RESERVED_PARAMS.include? k
+ if k == 'src'
+ src = URI.unescape(v)
+ # slashes come in double-escaped by Apache so we
+ # need to unescape again
+ src = URI.unescape(src) if src =~ /%2F/
+ end
+ else
+ opts[k] = URI.unescape(v)
+ end
end
+
+ process_src_or_display_demo src, opts
end
get '/analyze' do
@@ -77,7 +77,22 @@ class App < Sinatra::Base
"Please provide an image URL with the src parameter."
end
end
-
+
+ def process_src_or_display_demo src, options
+ if src
+ # process image
+ url = uri_to_url src
+ image = Magickly.process_src(url, options)
+ image.to_response(env)
+ else
+ # display demo page
+
+ # get combined list of jobs and processor methods
+ @methods = ( Magickly.dragonfly.job_methods | Magickly.dragonfly.processor_methods )
+ @methods.sort!{|m1, m2| m1.to_s <=> m2.to_s }
+ erb :index
+ end
+ end
def uri_to_url(uri)
url = Addressable::URI.parse(uri)
View
6 lib/shortcuts.rb
@@ -46,6 +46,12 @@
lomo_mask = File.join(File.dirname(__FILE__), 'images', 'lomo_mask.png')
process :convert, "\\( +clone -unsharp 1 -contrast -contrast -modulate #{modulate_params} \\( #{lomo_mask} -resize #{@job.width}x#{@job.height}\\! \\) -compose overlay -composite \\) -compose multiply -composite"
end
+
+ # thanks to Jesse Chan-Norris - http://jcn.me/
+ c.job :jcn do
+ process :greyscale
+ @job = @job.halftone(99)
+ end
## thanks to Fred Weinhaus (http://www.fmwconcepts.com/imagemagick) for the following: ##
View
31 magickly.gemspec
@@ -5,11 +5,11 @@
Gem::Specification.new do |s|
s.name = "magickly"
- s.version = "1.3.0"
+ s.version = "1.4.0"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Aidan Feldman"]
- s.date = "2011-09-05"
+ s.date = "2012-01-26"
s.description = "A service for image manipulation - built as an extensible wrapper of Imagemagick which handles caching, c/o the Dragonfly gem."
s.email = "aidan.feldman@gmail.com"
s.extra_rdoc_files = [
@@ -29,7 +29,6 @@ Gem::Specification.new do |s|
"Rakefile",
"VERSION",
"config.ru",
- "lib/dragonfly/app.rb",
"lib/dragonfly/data_storage/remote_data_store.rb",
"lib/images/lomo_mask.png",
"lib/magickly.rb",
@@ -53,48 +52,42 @@ Gem::Specification.new do |s|
s.homepage = "http://github.com/afeld/magickly"
s.licenses = ["MIT"]
s.require_paths = ["lib"]
- s.rubygems_version = "1.8.10"
+ s.rubygems_version = "1.8.15"
s.summary = "image manipulation as a (plugin-able) service"
if s.respond_to? :specification_version then
s.specification_version = 3
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
- s.add_runtime_dependency(%q<sinatra>, ["~> 1.2.1"])
- s.add_runtime_dependency(%q<sinatra-synchrony>, ["~> 0.2.0"])
- s.add_runtime_dependency(%q<dragonfly>, ["~> 0.9.1"])
+ s.add_runtime_dependency(%q<sinatra>, ["~> 1.2"])
+ s.add_runtime_dependency(%q<dragonfly>, ["~> 0.9.5"])
s.add_runtime_dependency(%q<addressable>, ["~> 2.2"])
- s.add_runtime_dependency(%q<httparty>, ["~> 0.7.3"])
+ s.add_runtime_dependency(%q<httparty>, ["~> 0.8.1"])
s.add_runtime_dependency(%q<activesupport>, [">= 2.0.0"])
s.add_development_dependency(%q<jeweler>, ["~> 1.5"])
- s.add_development_dependency(%q<rcov>, [">= 0"])
s.add_development_dependency(%q<rack-test>, [">= 0"])
s.add_development_dependency(%q<rspec>, ["~> 2.4"])
s.add_development_dependency(%q<webmock>, ["~> 1.6"])
s.add_development_dependency(%q<imagesize>, ["~> 0.1"])
else
- s.add_dependency(%q<sinatra>, ["~> 1.2.1"])
- s.add_dependency(%q<sinatra-synchrony>, ["~> 0.2.0"])
- s.add_dependency(%q<dragonfly>, ["~> 0.9.1"])
+ s.add_dependency(%q<sinatra>, ["~> 1.2"])
+ s.add_dependency(%q<dragonfly>, ["~> 0.9.5"])
s.add_dependency(%q<addressable>, ["~> 2.2"])
- s.add_dependency(%q<httparty>, ["~> 0.7.3"])
+ s.add_dependency(%q<httparty>, ["~> 0.8.1"])
s.add_dependency(%q<activesupport>, [">= 2.0.0"])
s.add_dependency(%q<jeweler>, ["~> 1.5"])
- s.add_dependency(%q<rcov>, [">= 0"])
s.add_dependency(%q<rack-test>, [">= 0"])
s.add_dependency(%q<rspec>, ["~> 2.4"])
s.add_dependency(%q<webmock>, ["~> 1.6"])
s.add_dependency(%q<imagesize>, ["~> 0.1"])
end
else
- s.add_dependency(%q<sinatra>, ["~> 1.2.1"])
- s.add_dependency(%q<sinatra-synchrony>, ["~> 0.2.0"])
- s.add_dependency(%q<dragonfly>, ["~> 0.9.1"])
+ s.add_dependency(%q<sinatra>, ["~> 1.2"])
+ s.add_dependency(%q<dragonfly>, ["~> 0.9.5"])
s.add_dependency(%q<addressable>, ["~> 2.2"])
- s.add_dependency(%q<httparty>, ["~> 0.7.3"])
+ s.add_dependency(%q<httparty>, ["~> 0.8.1"])
s.add_dependency(%q<activesupport>, [">= 2.0.0"])
s.add_dependency(%q<jeweler>, ["~> 1.5"])
- s.add_dependency(%q<rcov>, [">= 0"])
s.add_dependency(%q<rack-test>, [">= 0"])
s.add_dependency(%q<rspec>, ["~> 2.4"])
s.add_dependency(%q<webmock>, ["~> 1.6"])
View
19 spec/requests/magickly_app_spec.rb
@@ -1,4 +1,5 @@
require 'spec_helper'
+require 'uri'
describe Magickly::App do
include Rack::Test::Methods
@@ -10,6 +11,7 @@ def app
def setup_image(host='http://www.foo.com')
@image_filename = 'imagemagick.png'
@image_url = "#{host}/#{@image_filename}"
+ @escaped_image_url = URI.escape @image_url, URI::REGEXP::PATTERN::RESERVED
@image_path = File.join(File.dirname(__FILE__), '..', 'support', @image_filename)
stub_request(:get, @image_url).to_return(:body => File.new(@image_path))
end
@@ -93,13 +95,28 @@ def setup_image(host='http://www.foo.com')
process :thumb, size
end
end
-
+
get "/?src=#{@image_url}&#{shortcut}=#{width}x"
last_response.should be_ok
ImageSize.new(last_response.body).get_width.should eq width
end
end
+
+ describe "GET /q" do
+
+ it "resizes an image" do
+ setup_image
+ width = 100
+
+ get "/q/src/#{@escaped_image_url}/resize/#{width}x"
+
+ a_request(:get, @image_url).should have_been_made.once
+ last_response.should be_ok
+ ImageSize.new(last_response.body).get_width.should eq width
+ end
+
+ end
describe "GET /analyze" do
it "retrieves the mime_type of an image" do
View
4 spec/spec_helper.rb
@@ -1,5 +1,3 @@
-ENV['RACK_ENV'] = 'test'
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
$LOAD_PATH.unshift(File.dirname(__FILE__))
require 'magickly'
@@ -8,8 +6,6 @@
require 'webmock/rspec'
require 'image_size'
-Sinatra::Synchrony.patch_tests! unless RUBY_VERSION.start_with? '1.8'
-
# Requires supporting files with custom matchers and macros, etc,
# in ./support/ and its subdirectories.
# Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}

No commit comments for this range

Something went wrong with that request. Please try again.