mirror of
https://github.com/sinatra/sinatra
synced 2023-03-27 23:18:01 -04:00
filters
This commit is contained in:
parent
2a0dce589e
commit
cfa0b14570
5 changed files with 132 additions and 2 deletions
|
@ -2,6 +2,8 @@ require "rubygems"
|
|||
require "rack"
|
||||
|
||||
require 'sinatra/mime_types'
|
||||
require 'sinatra/send_file_mixin'
|
||||
require 'sinatra/halt_results'
|
||||
|
||||
def silence_warnings
|
||||
old_verbose, $VERBOSE = $VERBOSE, nil
|
||||
|
@ -70,6 +72,10 @@ module Sinatra
|
|||
@params ||= request.params.merge(route_params).symbolize_keys
|
||||
end
|
||||
|
||||
def complete(b)
|
||||
self.instance_eval(&b)
|
||||
end
|
||||
|
||||
def method_missing(name, *args)
|
||||
if args.size == 1 && response.respond_to?("#{name}=")
|
||||
response.send("#{name}=", args.first)
|
||||
|
@ -99,6 +105,10 @@ module Sinatra
|
|||
end
|
||||
end
|
||||
|
||||
def filters
|
||||
@filters ||= Hash.new { |hash, key| hash[key] = [] }
|
||||
end
|
||||
|
||||
def config
|
||||
@config ||= @default_config.dup
|
||||
end
|
||||
|
@ -153,9 +163,8 @@ module Sinatra
|
|||
context = EventContext.new(request, response, route.params)
|
||||
context.status = nil
|
||||
begin
|
||||
result = context.instance_eval(&route.block)
|
||||
context = handle_with_filters(context, &route.block)
|
||||
context.status ||= route.default_status
|
||||
context.body = Array(result.to_s)
|
||||
context.finish
|
||||
rescue => e
|
||||
raise e if config[:raise_errors]
|
||||
|
@ -175,6 +184,19 @@ module Sinatra
|
|||
routes[code] = Error.new(code, &b)
|
||||
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
|
||||
|
||||
URI_CHAR = '[^/?:,&#]'.freeze unless defined?(URI_CHAR)
|
||||
|
@ -247,3 +269,7 @@ def helpers(&b)
|
|||
end
|
||||
|
||||
Sinatra.setup_default_events!
|
||||
|
||||
Sinatra::EventContext.send :include, Sinatra::SendFileMixin
|
||||
|
||||
|
||||
|
|
30
lib/sinatra/halt_results.rb
Normal file
30
lib/sinatra/halt_results.rb
Normal 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
|
72
lib/sinatra/send_file_mixin.rb
Normal file
72
lib/sinatra/send_file_mixin.rb
Normal 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
|
|
@ -9,9 +9,11 @@ context "Event's DSL" do
|
|||
end
|
||||
|
||||
get_it '/'
|
||||
should.be.ok
|
||||
body.should.equal 'hello from me'
|
||||
|
||||
get_it '/foo'
|
||||
should.be.ok
|
||||
body.should.equal 'hello from me'
|
||||
|
||||
end
|
||||
|
|
0
test/filter_test.rb
Normal file
0
test/filter_test.rb
Normal file
Loading…
Add table
Reference in a new issue