diff --git a/lib/sinatra.rb b/lib/sinatra.rb index 3b2acded..2f54dca2 100644 --- a/lib/sinatra.rb +++ b/lib/sinatra.rb @@ -37,7 +37,10 @@ Sinatra::Loader.load_files Dir.glob(SINATRA_ROOT + '/lib/sinatra/core_ext/*.rb') Sinatra::Loader.load_files Dir.glob(SINATRA_ROOT + '/lib/sinatra/*.rb') Sinatra::Loader.load_files Dir.glob(SINATRA_ROOT + '/vendor/*/init.rb') -Sinatra::Environment.setup! -Sinatra::Irb.start! if Sinatra::Options.console +Sinatra::Environment.prepare -at_exit { Sinatra::Server.new.start unless Sinatra::Server.running } +at_exit do + Sinatra::Environment.prepare_loggers unless Sinatra::Options.environment == :test + Sinatra::Irb.start! if Sinatra::Options.console + Sinatra::Server.new.start unless Sinatra::Server.running +end diff --git a/lib/sinatra/dsl.rb b/lib/sinatra/dsl.rb index 6d5508db..07b7063a 100644 --- a/lib/sinatra/dsl.rb +++ b/lib/sinatra/dsl.rb @@ -17,9 +17,9 @@ module Kernel end def static(path, root) - Sinatra::StaticEvent.new(path, File.join(File.dirname($0) + root)) + Sinatra::StaticEvent.new(path, root) end - + %w(test development production).each do |env| module_eval <<-end_eval def #{env} diff --git a/lib/sinatra/environment.rb b/lib/sinatra/environment.rb index 705088f9..ce9fe863 100644 --- a/lib/sinatra/environment.rb +++ b/lib/sinatra/environment.rb @@ -2,12 +2,11 @@ module Sinatra module Environment extend self - def setup! + def prepare Options.parse!(ARGV) - set_loggers end - def set_loggers(logger = Logger.new(open(Options.log_file, 'w'))) + def prepare_loggers(logger = Logger.new(open(Options.log_file, 'w'))) [Server, EventContext, Event, Dispatcher].each do |klass| klass.logger = logger end diff --git a/lib/sinatra/event.rb b/lib/sinatra/event.rb index 7a6666b3..36947bc3 100644 --- a/lib/sinatra/event.rb +++ b/lib/sinatra/event.rb @@ -164,35 +164,94 @@ module Sinatra class StaticEvent < Event def initialize(path, root, register = true) + @root = root super(:get, path, register) - @root = File.expand_path(root) end def recognize(path) - canserve = File.dirname(path) == @path - @filename = File.join(@root, path.gsub(/^#{@path}/, '')) - canserve && File.exists?(@filename) + File.exists?(physical_path_for(path)) + end + + def physical_path_for(path) + path.gsub(/^#{@path}/, @root) end def attend(request) - puts 'attend ' + self.inspect - @body = self + @filename = physical_path_for(request.path_info) + context = EventContext.new(request) + context.body self + context.header 'Content-Type' => MIME_TYPES[File.extname(@filename)[1..-1]] + context.header 'Content-Length' => File.size(@filename).to_s + context end - def status; 200; end - - def headers; {}; end - - def body; @body; end - def each - File.open(@filename, "rb") { |file| + File.open(@filename, "rb") do |file| while part = file.read(8192) yield part end - } + end end - - end + + # :stopdoc: + # From WEBrick. + MIME_TYPES = { + "ai" => "application/postscript", + "asc" => "text/plain", + "avi" => "video/x-msvideo", + "bin" => "application/octet-stream", + "bmp" => "image/bmp", + "class" => "application/octet-stream", + "cer" => "application/pkix-cert", + "crl" => "application/pkix-crl", + "crt" => "application/x-x509-ca-cert", + #"crl" => "application/x-pkcs7-crl", + "css" => "text/css", + "dms" => "application/octet-stream", + "doc" => "application/msword", + "dvi" => "application/x-dvi", + "eps" => "application/postscript", + "etx" => "text/x-setext", + "exe" => "application/octet-stream", + "gif" => "image/gif", + "htm" => "text/html", + "html" => "text/html", + "jpe" => "image/jpeg", + "jpeg" => "image/jpeg", + "jpg" => "image/jpeg", + "lha" => "application/octet-stream", + "lzh" => "application/octet-stream", + "mov" => "video/quicktime", + "mpe" => "video/mpeg", + "mpeg" => "video/mpeg", + "mpg" => "video/mpeg", + "pbm" => "image/x-portable-bitmap", + "pdf" => "application/pdf", + "pgm" => "image/x-portable-graymap", + "png" => "image/png", + "pnm" => "image/x-portable-anymap", + "ppm" => "image/x-portable-pixmap", + "ppt" => "application/vnd.ms-powerpoint", + "ps" => "application/postscript", + "qt" => "video/quicktime", + "ras" => "image/x-cmu-raster", + "rb" => "text/plain", + "rd" => "text/plain", + "rtf" => "application/rtf", + "sgm" => "text/sgml", + "sgml" => "text/sgml", + "tif" => "image/tiff", + "tiff" => "image/tiff", + "txt" => "text/plain", + "xbm" => "image/x-xbitmap", + "xls" => "application/vnd.ms-excel", + "xml" => "text/xml", + "xpm" => "image/x-xpixmap", + "xwd" => "image/x-xwindowdump", + "zip" => "application/zip", + } + # :startdoc: + + end end diff --git a/test/helper.rb b/test/helper.rb index d8a77f13..b4a27124 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -10,6 +10,7 @@ end Sinatra::Server.running = true Sinatra::Options.set_environment :test +Sinatra::Environment.prepare_loggers class Test::Unit::TestCase include Sinatra::TestMethods diff --git a/test/sinatra/event_test.rb b/test/sinatra/event_test.rb index d76c03f3..fb43dd2c 100644 --- a/test/sinatra/event_test.rb +++ b/test/sinatra/event_test.rb @@ -7,7 +7,7 @@ describe "Event" do end it "should return 500 if exception thrown" do - Sinatra::Environment.set_loggers stub_everything + Sinatra::Environment.prepare_loggers stub_everything event = Sinatra::Event.new(:get, '/') do raise 'whaaaa!' @@ -19,7 +19,7 @@ describe "Event" do end it "custom error if present" do - Sinatra::Environment.set_loggers stub_everything + Sinatra::Environment.prepare_loggers stub_everything event = Sinatra::Event.new(:get, '404') do body 'custom 404' diff --git a/test/sinatra/static_files/foo.txt b/test/sinatra/static_files/foo.txt new file mode 100644 index 00000000..7cc4bc43 --- /dev/null +++ b/test/sinatra/static_files/foo.txt @@ -0,0 +1 @@ +You found foo! \ No newline at end of file diff --git a/test/sinatra/static_files_test.rb b/test/sinatra/static_files_test.rb new file mode 100644 index 00000000..b7a59b14 --- /dev/null +++ b/test/sinatra/static_files_test.rb @@ -0,0 +1,41 @@ +require File.dirname(__FILE__) + '/../helper' +require 'stringio' + +context "StaticEvent" do + + before(:each) do + Sinatra::EventManager.reset! + end + + specify "recognizes paths prefixed with it's path" do + File.expects(:exists?).with('/x/bar/test.jpg').returns(true) + Sinatra::StaticEvent.new('/foo', '/x/bar').recognize('/foo/test.jpg').should.equal true + + File.expects(:exists?).with('/x/bar/test.jpg').returns(false) + Sinatra::StaticEvent.new('/foo', '/x/bar').recognize('/foo/test.jpg').should.equal false + end + + specify "sets headers for file type" do + File.expects(:open).with('/x/bar/test.jpg', 'rb').returns(StringIO.new) + File.expects(:size).with('/x/bar/test.jpg').returns(255) + result = Sinatra::StaticEvent.new('/foo', '/x/bar').attend(stub(:path_info => '/foo/test.jpg')) + result.headers.should.equal 'Content-Type' => 'image/jpeg', 'Content-Length' => '255' + result.body.each { } + end + +end + +context "StaticEvent (In full context)" do + + specify "should serve a static file" do + e = static '/x', root = File.dirname(__FILE__) + '/static_files' + + File.read(e.physical_path_for('/x/foo.txt')).should.equal 'You found foo!' + + get_it '/x/foo.txt' + + status.should.equal 200 + body.should.equal 'You found foo!' + end + +end \ No newline at end of file