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 "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
|
||||||
|
|
||||||
|
|
||||||
|
|
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
|
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
0
test/filter_test.rb
Normal file
Loading…
Add table
Reference in a new issue