Merge commit 'bmizerany/master'
This commit is contained in:
commit
b73450982a
|
@ -2,4 +2,5 @@ doc
|
|||
pkg
|
||||
*.log
|
||||
.DS_Store
|
||||
Manifest
|
||||
Manifest
|
||||
x.rb
|
479
lib/sinatra.rb
479
lib/sinatra.rb
|
@ -96,19 +96,15 @@ module Sinatra
|
|||
def options
|
||||
application.options
|
||||
end
|
||||
|
||||
|
||||
def application
|
||||
unless @app
|
||||
@app = Application.new
|
||||
Sinatra::Environment.setup!
|
||||
end
|
||||
@app
|
||||
@app ||= Application.new
|
||||
end
|
||||
|
||||
|
||||
def application=(app)
|
||||
@app = app
|
||||
end
|
||||
|
||||
|
||||
def port
|
||||
application.options.port
|
||||
end
|
||||
|
@ -116,14 +112,10 @@ module Sinatra
|
|||
def env
|
||||
application.options.env
|
||||
end
|
||||
|
||||
def build_application
|
||||
app = application
|
||||
app = Rack::Session::Cookie.new(app) if Sinatra.options.sessions == true
|
||||
app = Rack::CommonLogger.new(app) if Sinatra.options.logging == true
|
||||
app
|
||||
end
|
||||
|
||||
|
||||
# Deprecated: use application instead of build_application.
|
||||
alias :build_application :application
|
||||
|
||||
def server
|
||||
@server ||= case options.server
|
||||
when "mongrel"
|
||||
|
@ -145,11 +137,10 @@ module Sinatra
|
|||
end
|
||||
|
||||
def run
|
||||
|
||||
begin
|
||||
puts "== Sinatra has taken the stage on port #{port} for #{env} with backup by #{server.name}"
|
||||
require 'pp'
|
||||
server.run(build_application, :Port => port) do |server|
|
||||
server.run(application, :Port => port) do |server|
|
||||
trap(:INT) do
|
||||
server.stop
|
||||
puts "\n== Sinatra has ended his set (crowd applauds)"
|
||||
|
@ -158,9 +149,8 @@ module Sinatra
|
|||
rescue Errno::EADDRINUSE => e
|
||||
puts "== Someone is already performing on port #{port}!"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class Event
|
||||
|
||||
URI_CHAR = '[^/?:,&#\.]'.freeze unless defined?(URI_CHAR)
|
||||
|
@ -830,17 +820,83 @@ module Sinatra
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
# The Application class represents the top-level working area of a
|
||||
# Sinatra app. It provides the DSL for defining various aspects of the
|
||||
# application and implements a Rack compatible interface for dispatching
|
||||
# requests.
|
||||
#
|
||||
# Many of the instance methods defined in this class (#get, #post,
|
||||
# #put, #delete, #layout, #before, #error, #not_found, etc.) are
|
||||
# available at top-level scope. When invoked from top-level, the
|
||||
# messages are forwarded to the "default application" (accessible
|
||||
# at Sinatra::application).
|
||||
class Application
|
||||
|
||||
attr_reader :events, :errors, :templates, :filters
|
||||
attr_reader :clearables, :reloading
|
||||
|
||||
attr_writer :options
|
||||
|
||||
|
||||
# Hash of event handlers with request method keys and
|
||||
# arrays of potential handlers as values.
|
||||
attr_reader :events
|
||||
|
||||
# Hash of error handlers with error status codes as keys and
|
||||
# handlers as values.
|
||||
attr_reader :errors
|
||||
|
||||
# Hash of template name mappings.
|
||||
attr_reader :templates
|
||||
|
||||
# Hash of filters with event name keys (:before) and arrays of
|
||||
# handlers as values.
|
||||
attr_reader :filters
|
||||
|
||||
# Array of objects to clear during reload. The objects in this array
|
||||
# must respond to :clear.
|
||||
attr_reader :clearables
|
||||
|
||||
# Object including open attribute methods for modifying Application
|
||||
# configuration.
|
||||
attr_reader :options
|
||||
|
||||
# List of methods available from top-level scope. When invoked from
|
||||
# top-level the method is forwarded to the default application
|
||||
# (Sinatra::application).
|
||||
FORWARD_METHODS = %w[
|
||||
get put post delete head template layout before error not_found
|
||||
configures configure set_options set_option enable disable use
|
||||
]
|
||||
|
||||
# Create a new Application with a default configuration taken
|
||||
# from the default_options Hash.
|
||||
#
|
||||
# NOTE: A default Application is automatically created the first
|
||||
# time any of Sinatra's DSL related methods is invoked so there
|
||||
# is typically no need to create an instance explicitly. See
|
||||
# Sinatra::application for more information.
|
||||
def initialize
|
||||
@reloading = false
|
||||
@clearables = [
|
||||
@events = Hash.new { |hash, key| hash[key] = [] },
|
||||
@errors = Hash.new,
|
||||
@filters = Hash.new { |hash, key| hash[key] = [] },
|
||||
@templates = Hash.new,
|
||||
@middleware = []
|
||||
]
|
||||
@options = OpenStruct.new(self.class.default_options)
|
||||
load_default_configuration!
|
||||
end
|
||||
|
||||
# Hash of default application configuration options. When a new
|
||||
# Application is created, the #options object takes its initial values
|
||||
# from here.
|
||||
#
|
||||
# Changes to the default_options Hash effect only Application objects
|
||||
# created after the changes are made. For this reason, modifications to
|
||||
# the default_options Hash typically occur at the very beginning of a
|
||||
# file, before any DSL related functions are invoked.
|
||||
def self.default_options
|
||||
return @default_options unless @default_options.nil?
|
||||
root = File.expand_path(File.dirname($0))
|
||||
@@default_options ||= {
|
||||
@default_options = {
|
||||
:run => true,
|
||||
:port => 4567,
|
||||
:env => :development,
|
||||
|
@ -848,19 +904,18 @@ module Sinatra
|
|||
:views => root + '/views',
|
||||
:public => root + '/public',
|
||||
:sessions => false,
|
||||
:logging => true
|
||||
:logging => true,
|
||||
:raise_errors => false
|
||||
}
|
||||
end
|
||||
|
||||
def default_options
|
||||
self.class.default_options
|
||||
load_default_options_from_command_line!
|
||||
@default_options
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Load all options given on the command line
|
||||
# Search ARGV for command line arguments and update the
|
||||
# Sinatra::default_options Hash accordingly. This method is
|
||||
# invoked the first time the default_options Hash is accessed.
|
||||
# NOTE: Ignores --name so unit/spec tests can run individually
|
||||
def load_options!
|
||||
def self.load_default_options_from_command_line! #:nodoc:
|
||||
require 'optparse'
|
||||
OptionParser.new do |op|
|
||||
op.on('-p port') { |port| default_options[:port] = port }
|
||||
|
@ -870,39 +925,104 @@ module Sinatra
|
|||
end.parse!(ARGV.dup.select { |o| o !~ /--name/ })
|
||||
end
|
||||
|
||||
# Called immediately after the application is initialized or reloaded to
|
||||
# register default events. Events added here have dibs on requests since
|
||||
# they appear first in the list.
|
||||
def load_default_events!
|
||||
events[:get] << Static.new
|
||||
# Determine whether the application is in the process of being
|
||||
# reloaded.
|
||||
def reloading?
|
||||
@reloading == true
|
||||
end
|
||||
|
||||
def initialize
|
||||
@clearables = [
|
||||
@events = Hash.new { |hash, key| hash[key] = [] },
|
||||
@errors = Hash.new,
|
||||
@filters = Hash.new { |hash, key| hash[key] = [] },
|
||||
@templates = Hash.new
|
||||
]
|
||||
load_options!
|
||||
load_default_events!
|
||||
# Yield to the block for configuration if the current environment
|
||||
# matches any included in the +envs+ list. Always yield to the block
|
||||
# when no environment is specified.
|
||||
#
|
||||
# NOTE: configuration blocks are not executed during reloads.
|
||||
def configures(*envs, &b)
|
||||
return if reloading?
|
||||
yield self if envs.empty? || envs.include?(options.env)
|
||||
end
|
||||
|
||||
def define_event(method, path, options = {}, &b)
|
||||
events[method] << event = Event.new(path, options, &b)
|
||||
event
|
||||
alias :configure :configures
|
||||
|
||||
# When both +option+ and +value+ arguments are provided, set the option
|
||||
# specified. With a single Hash argument, set all options specified in
|
||||
# Hash. Options are available via the Application#options object.
|
||||
#
|
||||
# Setting individual options:
|
||||
# set :port, 80
|
||||
# set :env, :production
|
||||
# set :views, '/path/to/views'
|
||||
#
|
||||
# Setting multiple options:
|
||||
# set :port => 80,
|
||||
# :env => :production,
|
||||
# :views => '/path/to/views'
|
||||
#
|
||||
def set(option, value=self)
|
||||
if value == self && option.kind_of?(Hash)
|
||||
option.each { |key,val| set(key, val) }
|
||||
else
|
||||
options.send("#{option}=", value)
|
||||
end
|
||||
end
|
||||
|
||||
def define_template(name=:layout, &b)
|
||||
templates[name] = b
|
||||
|
||||
alias :set_option :set
|
||||
alias :set_options :set
|
||||
|
||||
# Enable the options specified by setting their values to true. For
|
||||
# example, to enable sessions and logging:
|
||||
# enable :sessions, :logging
|
||||
def enable(*opts)
|
||||
opts.each { |key| set(key, true) }
|
||||
end
|
||||
|
||||
def define_error(code, options = {}, &b)
|
||||
errors[code] = Error.new(code, &b)
|
||||
|
||||
# Disable the options specified by setting their values to false. For
|
||||
# example, to disable logging and automatic run:
|
||||
# disable :logging, :run
|
||||
def disable(*opts)
|
||||
opts.each { |key| set(key, false) }
|
||||
end
|
||||
|
||||
def define_filter(type, &b)
|
||||
filters[:before] << b
|
||||
|
||||
# Define an event handler for the given request method and path
|
||||
# spec. The block is executed when a request matches the method
|
||||
# and spec.
|
||||
#
|
||||
# NOTE: The #get, #post, #put, and #delete helper methods should
|
||||
# be used to define events when possible.
|
||||
def event(method, path, options = {}, &b)
|
||||
events[method].push(Event.new(path, options, &b)).last
|
||||
end
|
||||
|
||||
# Define an event handler for GET requests.
|
||||
def get(path, options={}, &b)
|
||||
event(:get, path, options, &b)
|
||||
end
|
||||
|
||||
# Define an event handler for POST requests.
|
||||
def post(path, options={}, &b)
|
||||
event(:post, path, options, &b)
|
||||
end
|
||||
|
||||
# Define an event handler for HEAD requests.
|
||||
def head(path, options={}, &b)
|
||||
event(:head, path, options, &b)
|
||||
end
|
||||
|
||||
# Define an event handler for PUT requests.
|
||||
#
|
||||
# NOTE: PUT events are triggered when the HTTP request method is
|
||||
# PUT and also when the request method is POST and the body includes a
|
||||
# "_method" parameter set to "PUT".
|
||||
def put(path, options={}, &b)
|
||||
event(:put, path, options, &b)
|
||||
end
|
||||
|
||||
# Define an event handler for DELETE requests.
|
||||
#
|
||||
# NOTE: DELETE events are triggered when the HTTP request method is
|
||||
# DELETE and also when the request method is POST and the body includes a
|
||||
# "_method" parameter set to "DELETE".
|
||||
def delete(path, options={}, &b)
|
||||
event(:delete, path, options, &b)
|
||||
end
|
||||
|
||||
# Visits and invokes each handler registered for the +request_method+ in
|
||||
|
@ -920,27 +1040,96 @@ module Sinatra
|
|||
errors[NotFound].invoke(request)
|
||||
end
|
||||
|
||||
def options
|
||||
@options ||= OpenStruct.new(default_options)
|
||||
|
||||
# Define a named template. The template may be referenced from
|
||||
# event handlers by passing the name as a Symbol to rendering
|
||||
# methods. The block is executed each time the template is rendered
|
||||
# and the resulting object is passed to the template handler.
|
||||
#
|
||||
# The following example defines a HAML template named hello and
|
||||
# invokes it from an event handler:
|
||||
#
|
||||
# template :hello do
|
||||
# "h1 Hello World!"
|
||||
# end
|
||||
#
|
||||
# get '/' do
|
||||
# haml :hello
|
||||
# end
|
||||
#
|
||||
def template(name, &b)
|
||||
templates[name] = b
|
||||
end
|
||||
|
||||
|
||||
# Define a layout template.
|
||||
def layout(name=:layout, &b)
|
||||
template(name, &b)
|
||||
end
|
||||
|
||||
# Define a custom error handler for the exception class +type+. The block
|
||||
# is invoked when the specified exception type is raised from an error
|
||||
# handler and can manipulate the response as needed:
|
||||
#
|
||||
# error MyCustomError do
|
||||
# status 500
|
||||
# 'So what happened was...' + request.env['sinatra.error'].message
|
||||
# end
|
||||
#
|
||||
# The Sinatra::ServerError handler is used by default when an exception
|
||||
# occurs and no matching error handler is found.
|
||||
def error(type=ServerError, options = {}, &b)
|
||||
errors[type] = Error.new(type, &b)
|
||||
end
|
||||
|
||||
# Define a custom error handler for '404 Not Found' responses. This is a
|
||||
# shorthand for:
|
||||
# error NotFound do
|
||||
# ..
|
||||
# end
|
||||
def not_found(options={}, &b)
|
||||
error NotFound, options, &b
|
||||
end
|
||||
|
||||
# Define a request filter. When +type+ is +:before+, execute the block
|
||||
# in the context of each request before matching event handlers.
|
||||
def filter(type, &b)
|
||||
filters[type] << b
|
||||
end
|
||||
|
||||
# Invoke the block in the context of each request before invoking
|
||||
# matching event handlers.
|
||||
def before(&b)
|
||||
filter :before, &b
|
||||
end
|
||||
|
||||
def development?
|
||||
options.env == :development
|
||||
end
|
||||
|
||||
# Clear all events, templates, filters, and error handlers
|
||||
# and then reload the application source file. This occurs
|
||||
# automatically before each request is processed in development.
|
||||
def reload!
|
||||
clearables.each(&:clear)
|
||||
Environment.setup!
|
||||
load_default_configuration!
|
||||
@pipeline = nil
|
||||
@reloading = true
|
||||
load_default_events!
|
||||
Kernel.load $0
|
||||
@reloading = false
|
||||
end
|
||||
|
||||
|
||||
# Determine whether the application is in the process of being
|
||||
# reloaded.
|
||||
def reloading?
|
||||
@reloading == true
|
||||
end
|
||||
|
||||
# Mutex instance used for thread synchronization.
|
||||
def mutex
|
||||
@@mutex ||= Mutex.new
|
||||
end
|
||||
|
||||
|
||||
# Yield to the block with thread synchronization
|
||||
def run_safely
|
||||
if options.mutex
|
||||
mutex.synchronize { yield }
|
||||
|
@ -948,16 +1137,74 @@ module Sinatra
|
|||
yield
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Add a piece of Rack middleware to the pipeline leading to the
|
||||
# application.
|
||||
def use(klass, *args, &block)
|
||||
fail "#{klass} must respond to 'new'" unless klass.respond_to?(:new)
|
||||
@pipeline = nil
|
||||
@middleware.push([ klass, args, block ]).last
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Rack middleware derived from current state of application options.
|
||||
# These components are plumbed in at the very beginning of the
|
||||
# pipeline.
|
||||
def optional_middleware
|
||||
[
|
||||
([ Rack::CommonLogger, [], nil ] if options.logging),
|
||||
([ Rack::Session::Cookie, [], nil ] if options.sessions)
|
||||
].compact
|
||||
end
|
||||
|
||||
# Rack middleware explicitly added to the application with #use. These
|
||||
# components are plumbed into the pipeline downstream from
|
||||
# #optional_middle.
|
||||
def explicit_middleware
|
||||
@middleware
|
||||
end
|
||||
|
||||
# All Rack middleware used to construct the pipeline.
|
||||
def middleware
|
||||
optional_middleware + explicit_middleware
|
||||
end
|
||||
|
||||
public
|
||||
|
||||
# An assembled pipeline of Rack middleware that leads eventually to
|
||||
# the Application#invoke method. The pipeline is built upon first
|
||||
# access. Defining new middleware with Application#use or manipulating
|
||||
# application options may cause the pipeline to be rebuilt.
|
||||
def pipeline
|
||||
@pipeline ||=
|
||||
middleware.inject(method(:dispatch)) do |app,(klass,args,block)|
|
||||
klass.new(app, *args, &block)
|
||||
end
|
||||
end
|
||||
|
||||
# Rack compatible request invocation interface.
|
||||
def call(env)
|
||||
reload! if development?
|
||||
pipeline.call(env)
|
||||
end
|
||||
|
||||
# Request invocation handler - called at the end of the Rack pipeline
|
||||
# for each request.
|
||||
#
|
||||
# 1. Create Rack::Request, Rack::Response helper objects.
|
||||
# 2. Lookup event handler based on request method and path.
|
||||
# 3. Create new EventContext to house event handler evaluation.
|
||||
# 4. Invoke each #before filter in context of EventContext object.
|
||||
# 5. Invoke event handler in context of EventContext object.
|
||||
# 6. Return response to Rack.
|
||||
#
|
||||
# See the Rack specification for detailed information on the
|
||||
# +env+ argument and return value.
|
||||
def dispatch(env)
|
||||
request = Rack::Request.new(env)
|
||||
result = lookup(request)
|
||||
context = EventContext.new(
|
||||
request,
|
||||
Rack::Response.new,
|
||||
result.params
|
||||
)
|
||||
context = EventContext.new(request, Rack::Response.new, result.params)
|
||||
context.status(result.status)
|
||||
begin
|
||||
returned = run_safely do
|
||||
|
@ -983,14 +1230,15 @@ module Sinatra
|
|||
context.body = body.kind_of?(String) ? [*body] : body
|
||||
context.finish
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
module Environment
|
||||
extend self
|
||||
|
||||
def setup!
|
||||
|
||||
# Called immediately after the application is initialized or reloaded to
|
||||
# register default events, templates, and error handlers.
|
||||
def load_default_configuration!
|
||||
|
||||
# The static event is always executed first.
|
||||
events[:get] << Static.new
|
||||
|
||||
# Default configuration for all environments.
|
||||
configure do
|
||||
error do
|
||||
raise request.env['sinatra.error'] if Sinatra.options.raise_errors
|
||||
|
@ -1087,50 +1335,27 @@ end<pre>
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
private :load_default_configuration!
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
def get(path, options ={}, &b)
|
||||
Sinatra.application.define_event(:get, path, options, &b)
|
||||
end
|
||||
|
||||
def post(path, options ={}, &b)
|
||||
Sinatra.application.define_event(:post, path, options, &b)
|
||||
end
|
||||
|
||||
def put(path, options ={}, &b)
|
||||
Sinatra.application.define_event(:put, path, options, &b)
|
||||
end
|
||||
|
||||
def delete(path, options ={}, &b)
|
||||
Sinatra.application.define_event(:delete, path, options, &b)
|
||||
end
|
||||
|
||||
def before(&b)
|
||||
Sinatra.application.define_filter(:before, &b)
|
||||
# Delegate DSLish methods to the currently active Sinatra::Application
|
||||
# instance.
|
||||
Sinatra::Application::FORWARD_METHODS.each do |method|
|
||||
eval(<<-EOS, binding, '(__DSL__)', 1)
|
||||
def #{method}(*args, &b)
|
||||
Sinatra.application.#{method}(*args, &b)
|
||||
end
|
||||
EOS
|
||||
end
|
||||
|
||||
def helpers(&b)
|
||||
Sinatra::EventContext.class_eval(&b)
|
||||
end
|
||||
|
||||
def error(type = Sinatra::ServerError, options = {}, &b)
|
||||
Sinatra.application.define_error(type, options, &b)
|
||||
end
|
||||
|
||||
def not_found(options = {}, &b)
|
||||
Sinatra.application.define_error(Sinatra::NotFound, options, &b)
|
||||
end
|
||||
|
||||
def layout(name = :layout, &b)
|
||||
Sinatra.application.define_template(name, &b)
|
||||
end
|
||||
|
||||
def template(name, &b)
|
||||
Sinatra.application.define_template(name, &b)
|
||||
end
|
||||
|
||||
def use_in_file_templates!
|
||||
require 'stringio'
|
||||
templates = IO.read(caller.first.split(':').first).split('__FILE__').last
|
||||
|
@ -1146,22 +1371,6 @@ def use_in_file_templates!
|
|||
end
|
||||
end
|
||||
|
||||
def configures(*envs, &b)
|
||||
yield if !Sinatra.application.reloading &&
|
||||
(envs.include?(Sinatra.application.options.env) ||
|
||||
envs.empty?)
|
||||
end
|
||||
alias :configure :configures
|
||||
|
||||
def set_options(opts)
|
||||
Sinatra::Application.default_options.merge!(opts)
|
||||
Sinatra.application.options = nil
|
||||
end
|
||||
|
||||
def set_option(key, value)
|
||||
set_options(key => value)
|
||||
end
|
||||
|
||||
def mime(ext, type)
|
||||
Rack::File::MIME_TYPES[ext.to_s] = type
|
||||
end
|
||||
|
|
|
@ -10,4 +10,4 @@ Sinatra::Application.default_options.merge!(
|
|||
:logging => false
|
||||
)
|
||||
|
||||
Sinatra.application.options = nil
|
||||
Sinatra.application = nil
|
||||
|
|
|
@ -5,7 +5,14 @@ context "Sinatra" do
|
|||
setup do
|
||||
Sinatra.application = nil
|
||||
end
|
||||
|
||||
|
||||
specify "should put all DSL methods on (main)" do
|
||||
object = Object.new
|
||||
Sinatra::Application::FORWARD_METHODS.each do |method|
|
||||
object.private_methods.should.include(method)
|
||||
end
|
||||
end
|
||||
|
||||
specify "should handle result of nil" do
|
||||
get '/' do
|
||||
nil
|
||||
|
|
|
@ -97,7 +97,53 @@ context "An app returns" do
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
context "Application#configure blocks" do
|
||||
|
||||
setup do
|
||||
Sinatra.application = nil
|
||||
end
|
||||
|
||||
specify "run when no environment specified" do
|
||||
ref = false
|
||||
configure { ref = true }
|
||||
ref.should.equal true
|
||||
end
|
||||
|
||||
specify "run when matching environment specified" do
|
||||
ref = false
|
||||
configure(:test) { ref = true }
|
||||
ref.should.equal true
|
||||
end
|
||||
|
||||
specify "do not run when no matching environment specified" do
|
||||
configure(:foo) { flunk "block should not have been executed" }
|
||||
configure(:development, :production, :foo) { flunk "block should not have been executed" }
|
||||
end
|
||||
|
||||
specify "accept multiple environments" do
|
||||
ref = false
|
||||
configure(:foo, :test, :bar) { ref = true }
|
||||
ref.should.equal true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "Default Application Configuration" do
|
||||
|
||||
specify "includes 404 and 500 error handlers" do
|
||||
Sinatra.application.errors.should.include(Sinatra::ServerError)
|
||||
Sinatra.application.errors[Sinatra::ServerError].should.not.be.nil
|
||||
Sinatra.application.errors.should.include(Sinatra::NotFound)
|
||||
Sinatra.application.errors[Sinatra::NotFound].should.not.be.nil
|
||||
end
|
||||
|
||||
specify "includes Static event" do
|
||||
assert Sinatra.application.events[:get].any? { |e| Sinatra::Static === e }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "Events in an app" do
|
||||
|
||||
setup do
|
||||
|
@ -173,3 +219,69 @@ context "Events in an app" do
|
|||
end
|
||||
|
||||
|
||||
context "Options in an app" do
|
||||
|
||||
setup do
|
||||
Sinatra.application = nil
|
||||
@app = Sinatra::application
|
||||
end
|
||||
|
||||
specify "can be set singly on app" do
|
||||
@app.set :foo, 1234
|
||||
@app.options.foo.should.equal 1234
|
||||
end
|
||||
|
||||
specify "can be set singly from top-level" do
|
||||
set_option :foo, 1234
|
||||
@app.options.foo.should.equal 1234
|
||||
end
|
||||
|
||||
specify "can be set multiply on app" do
|
||||
@app.options.foo.should.be.nil
|
||||
@app.set :foo => 1234,
|
||||
:bar => 'hello, world'
|
||||
@app.options.foo.should.equal 1234
|
||||
@app.options.bar.should.equal 'hello, world'
|
||||
end
|
||||
|
||||
specify "can be set multiply from top-level" do
|
||||
@app.options.foo.should.be.nil
|
||||
set_options :foo => 1234,
|
||||
:bar => 'hello, world'
|
||||
@app.options.foo.should.equal 1234
|
||||
@app.options.bar.should.equal 'hello, world'
|
||||
end
|
||||
|
||||
specify "can be enabled on app" do
|
||||
@app.options.foo.should.be.nil
|
||||
@app.enable :sessions, :foo, :bar
|
||||
@app.options.sessions.should.equal true
|
||||
@app.options.foo.should.equal true
|
||||
@app.options.bar.should.equal true
|
||||
end
|
||||
|
||||
specify "can be enabled from top-level" do
|
||||
@app.options.foo.should.be.nil
|
||||
enable :sessions, :foo, :bar
|
||||
@app.options.sessions.should.equal true
|
||||
@app.options.foo.should.equal true
|
||||
@app.options.bar.should.equal true
|
||||
end
|
||||
|
||||
specify "can be disabled on app" do
|
||||
@app.options.foo.should.be.nil
|
||||
@app.disable :sessions, :foo, :bar
|
||||
@app.options.sessions.should.equal false
|
||||
@app.options.foo.should.equal false
|
||||
@app.options.bar.should.equal false
|
||||
end
|
||||
|
||||
specify "can be enabled from top-level" do
|
||||
@app.options.foo.should.be.nil
|
||||
disable :sessions, :foo, :bar
|
||||
@app.options.sessions.should.equal false
|
||||
@app.options.foo.should.equal false
|
||||
@app.options.bar.should.equal false
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
require File.dirname(__FILE__) + '/helper'
|
||||
|
||||
class UpcaseMiddleware
|
||||
def initialize(app, *args, &block)
|
||||
@app = app
|
||||
@args = args
|
||||
@block = block
|
||||
end
|
||||
def call(env)
|
||||
env['PATH_INFO'] = env['PATH_INFO'].to_s.upcase
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
|
||||
context "Middleware Pipelines" do
|
||||
|
||||
setup do
|
||||
Sinatra.application = nil
|
||||
@app = Sinatra.application
|
||||
end
|
||||
|
||||
teardown do
|
||||
Sinatra.application = nil
|
||||
end
|
||||
|
||||
specify "includes default middleware with options set" do
|
||||
@app.set_options :sessions => true, :logging => true
|
||||
@app.send(:optional_middleware).should.include([Rack::Session::Cookie, [], nil])
|
||||
@app.send(:optional_middleware).should.include([Rack::CommonLogger, [], nil])
|
||||
end
|
||||
|
||||
specify "does not include default middleware with options unset" do
|
||||
@app.set_options :sessions => false, :logging => false
|
||||
@app.send(:optional_middleware).should.not.include([Rack::Session::Cookie, [], nil])
|
||||
@app.send(:optional_middleware).should.not.include([Rack::CommonLogger, [], nil])
|
||||
end
|
||||
|
||||
specify "includes only optional middleware when no explicit middleware added" do
|
||||
@app.set_options :sessions => true, :logging => true
|
||||
@app.send(:middleware).should.equal @app.send(:optional_middleware)
|
||||
end
|
||||
|
||||
specify "should clear middleware before reload" do
|
||||
@app.clearables.should.include(@app.send(:explicit_middleware))
|
||||
end
|
||||
|
||||
specify "should add middleware with use" do
|
||||
block = Proc.new { |env| }
|
||||
@app.use UpcaseMiddleware
|
||||
@app.use UpcaseMiddleware, "foo", "bar"
|
||||
@app.use UpcaseMiddleware, "foo", "bar", &block
|
||||
@app.send(:middleware).should.include([UpcaseMiddleware, [], nil])
|
||||
@app.send(:middleware).should.include([UpcaseMiddleware, ["foo", "bar"], nil])
|
||||
@app.send(:middleware).should.include([UpcaseMiddleware, ["foo", "bar"], block])
|
||||
end
|
||||
|
||||
specify "should run middleware added with use" do
|
||||
get('/foo') { "FAIL!" }
|
||||
get('/FOO') { "PASS!" }
|
||||
use UpcaseMiddleware
|
||||
get_it '/foo'
|
||||
should.be.ok
|
||||
body.should.equal "PASS!"
|
||||
end
|
||||
|
||||
end
|
|
@ -1,10 +1,10 @@
|
|||
require File.dirname(__FILE__) + '/helper'
|
||||
|
||||
context "Sessions" do
|
||||
|
||||
specify "should be off by default" do
|
||||
Sinatra.application = nil
|
||||
|
||||
setup { Sinatra.application = nil }
|
||||
|
||||
specify "should be off by default" do
|
||||
get '/asdf' do
|
||||
session[:test] = true
|
||||
"asdf"
|
||||
|
@ -18,10 +18,9 @@ context "Sessions" do
|
|||
assert ok?
|
||||
assert !include?('Set-Cookie')
|
||||
end
|
||||
|
||||
|
||||
specify "should be able to store data accross requests" do
|
||||
set_options(:sessions => true)
|
||||
Sinatra.application = nil
|
||||
set_option :sessions, true
|
||||
|
||||
get '/foo' do
|
||||
session[:test] = true
|
||||
|
|
Loading…
Reference in New Issue