#!/usr/bin/ruby require 'sinatra/base' require 'haml' require 'RMagick' $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) require 'httpthumbnailer/thumbnailer' require 'httpthumbnailer/thumbnail_specs' sinatra = Sinatra.new sinatra.set :port, 3100 sinatra.set :bind, 'localhost' sinatra.set :environment, 'production' sinatra.set :server, ['mongrel'] sinatra.set :lock, true sinatra.set :boundary, "thumnail image data" sinatra.set :logging, true sinatra.set :debug, true sinatra.before do logger.level = Logger::DEBUG if settings.debug == true if $thumbnailer.nil? $thumbnailer = Thumbnailer.new(:logger => logger) $thumbnailer.method('crop') do |image, spec| image.resize_to_fill!(spec.width, spec.height) end $thumbnailer.method('fit') do |image, spec| image.resize_to_fit!(spec.width, spec.height) end $thumbnailer.method('pad') do |image, spec| image.resize_to_fit!(spec.width, spec.height) out = Magick::Image.new(spec.width, spec.height) { self.background_color = Magick::Pixel.new(Magick::MaxRGB, Magick::MaxRGB, Magick::MaxRGB, Magick::MaxRGB) # transparent }.composite!(image, Magick::CenterGravity, Magick::OverCompositeOp) image.destroy! out end end end sinatra.helpers do def plain_response(msg) headers "Content-Type" => "text/plain" body msg.gsub("\n", "\r\n") + "\r\n" end def plain_exception(exception) plain_response("Error: #{exception.class.name}: #{exception}") end end sinatra.get '/' do logger.info 'hello' end sinatra.get '/stats/images' do $thumbnailer.images.to_s end sinatra.put %r{^/thumbnail/(.*)} do |specs| thumbnail_specs = ThumbnailSpecs.from_uri(specs) $thumbnailer.load(request.body) do |original_image_handler| status 200 headers "Content-Type" => "multipart/mixed; boundary=\"#{settings.boundary}\"" stream do |out| # this is non blocking original_image_handler.use do |original_image| thumbnail_specs.each do |spec| logger.info "Thumbnailing: #{spec}" out << "--#{settings.boundary}\r\n" begin thumbnail_data = original_image.thumbnail(spec) out << "Content-Type: #{spec.mime}\r\n\r\n" out << thumbnail_data rescue => e logger.error "Thumbnailing error: #{e.class.name}: #{e}: \n#{e.backtrace.join("\n")}" out << "Content-Type: text/plain\r\n\r\n" out << "Error: #{e.class.name}: #{e}\r\n" ensure out << "\r\n" end end out << "--#{settings.boundary}--" end end end end sinatra.error Thumbnailer::UnsupportedMediaTypeError do plain_exception(env['sinatra.error']) halt 415 end sinatra.error 404 do plain_response("Resource '#{request.path_info}' not found") end sinatra.error do plain_exception(env['sinatra.error']) end begin sinatra.run! rescue Errno::EACCES, Errno::EADDRNOTAVAIL, SocketError => e puts "Error: failed to bind HTTP server socket (#{options[:bind]}): #{e}" exit 5 end