1
0
Fork 0
mirror of https://github.com/sinatra/sinatra synced 2023-03-27 23:18:01 -04:00
This commit is contained in:
Blake Mizerany 2007-11-24 16:34:15 -08:00
parent 2a0dce589e
commit cfa0b14570
5 changed files with 132 additions and 2 deletions

View file

@ -2,6 +2,8 @@ require "rubygems"
require "rack" require "rack"
require 'sinatra/mime_types' require 'sinatra/mime_types'
require 'sinatra/send_file_mixin'
require 'sinatra/halt_results'
def silence_warnings def silence_warnings
old_verbose, $VERBOSE = $VERBOSE, nil old_verbose, $VERBOSE = $VERBOSE, nil
@ -70,6 +72,10 @@ module Sinatra
@params ||= request.params.merge(route_params).symbolize_keys @params ||= request.params.merge(route_params).symbolize_keys
end end
def complete(b)
self.instance_eval(&b)
end
def method_missing(name, *args) def method_missing(name, *args)
if args.size == 1 && response.respond_to?("#{name}=") if args.size == 1 && response.respond_to?("#{name}=")
response.send("#{name}=", args.first) response.send("#{name}=", args.first)
@ -99,6 +105,10 @@ module Sinatra
end end
end end
def filters
@filters ||= Hash.new { |hash, key| hash[key] = [] }
end
def config def config
@config ||= @default_config.dup @config ||= @default_config.dup
end end
@ -153,9 +163,8 @@ module Sinatra
context = EventContext.new(request, response, route.params) context = EventContext.new(request, response, route.params)
context.status = nil context.status = nil
begin begin
result = context.instance_eval(&route.block) context = handle_with_filters(context, &route.block)
context.status ||= route.default_status context.status ||= route.default_status
context.body = Array(result.to_s)
context.finish context.finish
rescue => e rescue => e
raise e if config[:raise_errors] raise e if config[:raise_errors]
@ -175,6 +184,19 @@ module Sinatra
routes[code] = Error.new(code, &b) routes[code] = Error.new(code, &b)
end end
protected
def handle_with_filters(cx, &b)
caught = catch(:halt) do
filters[:before].each { |x| cx.instance_eval(&x) }
[:complete, b]
end
result = caught.to_result(cx)
filters[:after].each { |x| cx.instance_eval(&x) }
cx.body Array(result.to_s)
cx
end
class Route class Route
URI_CHAR = '[^/?:,&#]'.freeze unless defined?(URI_CHAR) URI_CHAR = '[^/?:,&#]'.freeze unless defined?(URI_CHAR)
@ -247,3 +269,7 @@ def helpers(&b)
end end
Sinatra.setup_default_events! Sinatra.setup_default_events!
Sinatra::EventContext.send :include, Sinatra::SendFileMixin

View file

@ -0,0 +1,30 @@
class Proc
def to_result(cx, *args)
cx.instance_eval(&self)
end
end
class String
def to_result(cx, *args)
cx.body self
end
end
class Array
def to_result(cx, *args)
self.shift.to_result(cx, *self)
end
end
class Symbol
def to_result(cx, *args)
cx.send(self, *args)
end
end
class Fixnum
def to_result(cx, *args)
cx.status self
cx.body args.first
end
end

View file

@ -0,0 +1,72 @@
module Sinatra
def default_send_file_options
@default_send_file_options ||= {
:type => 'application/octet-stream'.freeze,
:disposition => 'attachment'.freeze
}.freeze
end
# Adapted from Merb greatness
module SendFileMixin
# redirect to another url It can be like /foo/bar
# for redirecting within your same app. Or it can
# be a fully qualified url to another site.
def redirect(url)
# MERB_LOGGER.info("Redirecting to: #{url}")
status(302)
headers.merge!({'Location'=> url})
return ''
end
# pass in a path to a file and this will set the
# right headers and let mongrel do its thang and
# serve the static file directly.
def send_file(file, opts={})
opts.update(Sinatra.default_send_file_options.merge(opts))
disposition = opts[:disposition].dup || 'attachment'
disposition << %(; filename="#{opts[:filename] ? opts[:filename] : File.basename(file)}")
headers.update(
'Content-Type' => opts[:type].strip, # fixes a problem with extra '\r' with some browsers
'Content-Disposition' => disposition,
'Content-Transfer-Encoding' => 'binary',
'X-SENDFILE' => file
)
return
end
# stream_file( { :filename => file_name,
# :type => content_type,
# :content_length => content_length }) do
# AWS::S3::S3Object.stream(user.folder_name + "-" + user_file.unique_id, bucket_name) do |chunk|
# response.write chunk
# end
# end
def stream_file(opts={}, &stream)
opts.update(Merb::Const::DEFAULT_SEND_FILE_OPTIONS.merge(opts))
disposition = opts[:disposition].dup || 'attachment'
disposition << %(; filename="#{opts[:filename]}")
response.headers.update(
'Content-Type' => opts[:type].strip, # fixes a problem with extra '\r' with some browsers
'Content-Disposition' => disposition,
'Content-Transfer-Encoding' => 'binary',
'CONTENT-LENGTH' => opts[:content_length]
)
response.send_status(opts[:content_length])
response.send_header
stream
end
# This uses nginx X-Accel-Redirect header to send
# a file directly from nginx. See the nginx wiki:
# http://wiki.codemongers.com/NginxXSendfile
def nginx_send_file(file)
headers['X-Accel-Redirect'] = File.expand_path(file)
return
end
end
end

View file

@ -9,9 +9,11 @@ context "Event's DSL" do
end end
get_it '/' get_it '/'
should.be.ok
body.should.equal 'hello from me' body.should.equal 'hello from me'
get_it '/foo' get_it '/foo'
should.be.ok
body.should.equal 'hello from me' body.should.equal 'hello from me'
end end

0
test/filter_test.rb Normal file
View file