strelka 0.0.1.pre.187 → 0.0.1.pre.193
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/ChangeLog +94 -26
- data/Manifest.txt +4 -2
- data/examples/apps/ws-echo +17 -0
- data/lib/strelka/app.rb +26 -24
- data/lib/strelka/app/auth.rb +2 -1
- data/lib/strelka/app/errors.rb +1 -1
- data/lib/strelka/app/filters.rb +1 -1
- data/lib/strelka/app/negotiation.rb +1 -1
- data/lib/strelka/app/parameters.rb +2 -2
- data/lib/strelka/app/restresources.rb +1 -1
- data/lib/strelka/app/routing.rb +3 -2
- data/lib/strelka/app/sessions.rb +3 -3
- data/lib/strelka/app/templating.rb +3 -3
- data/lib/strelka/authprovider.rb +2 -10
- data/lib/strelka/behavior/plugin.rb +3 -3
- data/lib/strelka/httprequest.rb +5 -2
- data/lib/strelka/httprequest/session.rb +3 -2
- data/lib/strelka/httpresponse/session.rb +8 -9
- data/lib/strelka/mixins.rb +15 -0
- data/lib/strelka/plugins.rb +257 -0
- data/lib/strelka/router/default.rb +27 -2
- data/lib/strelka/session.rb +20 -2
- data/lib/strelka/session/db.rb +20 -10
- data/lib/strelka/session/default.rb +41 -18
- data/spec/lib/helpers.rb +1 -1
- data/spec/strelka/app/auth_spec.rb +1 -1
- data/spec/strelka/app/errors_spec.rb +1 -1
- data/spec/strelka/app/filters_spec.rb +1 -1
- data/spec/strelka/app/negotiation_spec.rb +1 -1
- data/spec/strelka/app/parameters_spec.rb +1 -1
- data/spec/strelka/app/restresources_spec.rb +1 -1
- data/spec/strelka/app/routing_spec.rb +4 -1
- data/spec/strelka/app/sessions_spec.rb +63 -17
- data/spec/strelka/app/templating_spec.rb +1 -1
- data/spec/strelka/app_spec.rb +13 -5
- data/spec/strelka/httprequest/session_spec.rb +44 -23
- data/spec/strelka/httprequest_spec.rb +21 -0
- data/spec/strelka/httpresponse/session_spec.rb +143 -0
- data/spec/strelka/{app/plugins_spec.rb → plugins_spec.rb} +64 -53
- data/spec/strelka/router/default_spec.rb +15 -0
- data/spec/strelka/router/exclusive_spec.rb +14 -0
- data/spec/strelka/session/db_spec.rb +11 -0
- data/spec/strelka/session/default_spec.rb +10 -2
- metadata +119 -37
- metadata.gz.sig +0 -0
- data/lib/strelka/app/plugins.rb +0 -284
@@ -7,7 +7,7 @@ require 'inversion'
|
|
7
7
|
require 'strelka' unless defined?( Strelka )
|
8
8
|
require 'strelka/app' unless defined?( Strelka::App )
|
9
9
|
|
10
|
-
require 'strelka/
|
10
|
+
require 'strelka/plugins'
|
11
11
|
|
12
12
|
|
13
13
|
# A templated content-generation plugin for Strelka::Apps. It uses the
|
@@ -88,7 +88,7 @@ require 'strelka/app/plugins'
|
|
88
88
|
#
|
89
89
|
module Strelka::App::Templating
|
90
90
|
include Strelka::Constants
|
91
|
-
extend Strelka::
|
91
|
+
extend Strelka::Plugin
|
92
92
|
|
93
93
|
run_before :routing, :negotiation, :errors
|
94
94
|
run_after :filters
|
@@ -109,7 +109,7 @@ module Strelka::App::Templating
|
|
109
109
|
def inherited( subclass )
|
110
110
|
super
|
111
111
|
subclass.instance_variable_set( :@template_map, @template_map.dup )
|
112
|
-
subclass.instance_variable_set( :@layout_template, @layout_template.dup )
|
112
|
+
subclass.instance_variable_set( :@layout_template, @layout_template.dup ) if @layout_template
|
113
113
|
end
|
114
114
|
|
115
115
|
|
data/lib/strelka/authprovider.rb
CHANGED
@@ -44,7 +44,8 @@ class Strelka::AuthProvider
|
|
44
44
|
include PluginFactory,
|
45
45
|
Strelka::Loggable,
|
46
46
|
Strelka::Constants,
|
47
|
-
|
47
|
+
Strelka::AbstractClass,
|
48
|
+
Strelka::ResponseHelpers
|
48
49
|
|
49
50
|
|
50
51
|
### PluginFactory API -- return the Array of directories to search for concrete
|
@@ -109,14 +110,5 @@ class Strelka::AuthProvider
|
|
109
110
|
end
|
110
111
|
|
111
112
|
|
112
|
-
### Abort the current execution and return a response with the specified
|
113
|
-
### http_status code immediately. The specified +message+ will be logged,
|
114
|
-
### and will be included in any message that is returned as part of the
|
115
|
-
### response. The +headers+ hash will be used to set response headers.
|
116
|
-
def finish_with( http_status, message, headers={} )
|
117
|
-
status_info = { :status => http_status, :message => message, :headers => headers }
|
118
|
-
throw :finish, status_info
|
119
|
-
end
|
120
|
-
|
121
113
|
end # class Strelka::AuthProvider
|
122
114
|
|
@@ -6,7 +6,7 @@ require 'rspec'
|
|
6
6
|
|
7
7
|
require 'strelka'
|
8
8
|
require 'strelka/app'
|
9
|
-
require 'strelka/
|
9
|
+
require 'strelka/plugins'
|
10
10
|
|
11
11
|
|
12
12
|
# This is a shared behavior for specs which different Strelka::App
|
@@ -29,8 +29,8 @@ shared_examples_for "A Strelka::App Plugin" do
|
|
29
29
|
end
|
30
30
|
|
31
31
|
|
32
|
-
it "extends Strelka::
|
33
|
-
plugin.should be_a( Strelka::
|
32
|
+
it "extends Strelka::Plugin" do
|
33
|
+
plugin.should be_a( Strelka::Plugin )
|
34
34
|
end
|
35
35
|
|
36
36
|
end
|
data/lib/strelka/httprequest.rb
CHANGED
@@ -14,7 +14,8 @@ require 'strelka/cookieset'
|
|
14
14
|
# An HTTP request class.
|
15
15
|
class Strelka::HTTPRequest < Mongrel2::HTTPRequest
|
16
16
|
include Strelka::Loggable,
|
17
|
-
Strelka::Constants
|
17
|
+
Strelka::Constants,
|
18
|
+
Strelka::ResponseHelpers
|
18
19
|
|
19
20
|
# Set Mongrel2 to use Strelka's request class for HTTP requests
|
20
21
|
register_request_type( self, *HTTP::RFC2616_VERBS )
|
@@ -163,8 +164,10 @@ class Strelka::HTTPRequest < Mongrel2::HTTPRequest
|
|
163
164
|
### Return a Hash of request form data.
|
164
165
|
def parse_form_data
|
165
166
|
case self.headers.content_type
|
167
|
+
when nil
|
168
|
+
finish_with( HTTP::BAD_REQUEST, "Malformed request (no content type?)" )
|
166
169
|
when 'application/x-www-form-urlencoded'
|
167
|
-
|
170
|
+
return merge_query_args( URI.decode_www_form(self.body) )
|
168
171
|
when 'application/json', 'text/javascript'
|
169
172
|
return Yajl.load( self.body )
|
170
173
|
when 'text/x-yaml', 'application/x-yaml'
|
@@ -43,10 +43,11 @@ module Strelka::HTTPRequest::Session
|
|
43
43
|
end
|
44
44
|
|
45
45
|
|
46
|
-
### Returns +true+ if the request
|
46
|
+
### Returns +true+ if the request has an associated session object.
|
47
47
|
def session?
|
48
|
-
return
|
48
|
+
return @session || Strelka::App::Sessions.session_class.has_session_for?( self )
|
49
49
|
end
|
50
|
+
alias_method :has_session?, :session?
|
50
51
|
|
51
52
|
|
52
53
|
### Return the session associated with the request, creating it if necessary.
|
@@ -57,13 +57,10 @@ module Strelka::HTTPResponse::Session
|
|
57
57
|
# new blank session.
|
58
58
|
if self.request.session?
|
59
59
|
self.log.debug "Getting the request's session."
|
60
|
-
|
60
|
+
self.session = request.session
|
61
61
|
else
|
62
62
|
self.log.debug "No session loaded in the request; creating it in the response."
|
63
|
-
|
64
|
-
@session = sessionclass.load_or_create( self.request )
|
65
|
-
@session.namespace = self.session_namespace
|
66
|
-
request.session = @session
|
63
|
+
self.session = Strelka::App::Sessions.session_class.new
|
67
64
|
end
|
68
65
|
end
|
69
66
|
|
@@ -73,9 +70,11 @@ module Strelka::HTTPResponse::Session
|
|
73
70
|
|
74
71
|
### Set the request's session object.
|
75
72
|
def session=( new_session )
|
73
|
+
self.log.debug "Setting session to %p in namespace %p" % [ new_session, self.session_namespace ]
|
76
74
|
new_session.namespace = self.session_namespace
|
77
75
|
@session = new_session
|
78
|
-
|
76
|
+
self.log.debug " session is: %p" % [ @session ]
|
77
|
+
# request.session = new_session # should it set the session in the request too?
|
79
78
|
end
|
80
79
|
|
81
80
|
|
@@ -83,15 +82,15 @@ module Strelka::HTTPResponse::Session
|
|
83
82
|
def session?
|
84
83
|
return @session || self.request.session?
|
85
84
|
end
|
85
|
+
alias_method :has_session?, :session?
|
86
86
|
|
87
87
|
|
88
88
|
### Tell the associated session to save itself and set up the session ID in the
|
89
89
|
### response, if one exists.
|
90
90
|
def save_session
|
91
91
|
if self.session?
|
92
|
-
session
|
93
|
-
self.
|
94
|
-
session.save( self )
|
92
|
+
self.log.debug "Saving session: %p" % [ self.session ]
|
93
|
+
self.session.save( self )
|
95
94
|
else
|
96
95
|
self.log.debug "No session to save."
|
97
96
|
end
|
data/lib/strelka/mixins.rb
CHANGED
@@ -333,6 +333,21 @@ module Strelka
|
|
333
333
|
|
334
334
|
end # module MethodUtilities
|
335
335
|
|
336
|
+
|
337
|
+
# A collection of functions for generating responses.
|
338
|
+
module ResponseHelpers
|
339
|
+
|
340
|
+
### Abort the current execution and return a response with the specified
|
341
|
+
### http_status code immediately. The specified +message+ will be logged,
|
342
|
+
### and will be included in any message that is returned as part of the
|
343
|
+
### response. The +headers+ hash will be used to set response headers.
|
344
|
+
def finish_with( http_status, message, headers={} )
|
345
|
+
status_info = { :status => http_status, :message => message, :headers => headers }
|
346
|
+
throw :finish, status_info
|
347
|
+
end
|
348
|
+
|
349
|
+
end # module ResponseHelpers
|
350
|
+
|
336
351
|
end # module Strelka
|
337
352
|
|
338
353
|
# vim: set nosta noet ts=4 sw=4:
|
@@ -0,0 +1,257 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# vim: set nosta noet ts=4 sw=4:
|
3
|
+
# encoding: utf-8
|
4
|
+
|
5
|
+
require 'set'
|
6
|
+
require 'tsort'
|
7
|
+
|
8
|
+
require 'strelka' unless defined?( Strelka )
|
9
|
+
require 'strelka/mixins'
|
10
|
+
|
11
|
+
module Strelka
|
12
|
+
extend Strelka::MethodUtilities
|
13
|
+
|
14
|
+
# A topologically-sorted hash for plugin management
|
15
|
+
class PluginRegistry < Hash
|
16
|
+
include TSort
|
17
|
+
alias_method :tsort_each_node, :each_key
|
18
|
+
def tsort_each_child( node, &block )
|
19
|
+
mod = fetch( node ) { [] }
|
20
|
+
if mod.respond_to?( :successors )
|
21
|
+
mod.successors.each( &block )
|
22
|
+
else
|
23
|
+
mod.each( &block )
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
# Plugin Module extension -- adds registration, load-order support, etc.
|
30
|
+
module Plugin
|
31
|
+
|
32
|
+
### Extension hook -- Extend the given object with methods for setting it
|
33
|
+
### up as a plugin for its containing namespace.
|
34
|
+
def self::extended( object )
|
35
|
+
super
|
36
|
+
|
37
|
+
# Find the plugin's namespace container, which will be the
|
38
|
+
# pluggable class/module
|
39
|
+
pluggable_name = object.name.split( '::' )[ 0..-2 ]
|
40
|
+
pluggable = pluggable_name.inject( Object ) do |mod, name|
|
41
|
+
mod.const_get( name )
|
42
|
+
end
|
43
|
+
|
44
|
+
Strelka.log.debug "Extending %p as a Strelka::Plugin for %p" % [ object, pluggable ]
|
45
|
+
object.successors = Set.new
|
46
|
+
object.pluggable = pluggable
|
47
|
+
|
48
|
+
# Register any pending dependencies for the newly-loaded plugin
|
49
|
+
name = object.plugin_name
|
50
|
+
if (( deps = pluggable.loaded_plugins[name] ))
|
51
|
+
Strelka.log.debug " installing deferred deps for %p" % [ name ]
|
52
|
+
object.run_after( *deps )
|
53
|
+
end
|
54
|
+
|
55
|
+
Strelka.log.debug " adding %p (%p) to the plugin registry for %p" %
|
56
|
+
[ name, object, pluggable ]
|
57
|
+
pluggable.loaded_plugins[ name ] = object
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
#############################################################
|
62
|
+
### A P P E N D E D M E T H O D S
|
63
|
+
#############################################################
|
64
|
+
|
65
|
+
# An Array that tracks which plugins should be installed after itself.
|
66
|
+
attr_accessor :successors
|
67
|
+
|
68
|
+
# The Class/Module that this plugin belongs to
|
69
|
+
attr_accessor :pluggable
|
70
|
+
|
71
|
+
|
72
|
+
### Return the name of the receiving plugin
|
73
|
+
def plugin_name
|
74
|
+
name = self.name || "anonymous#{self.object_id}"
|
75
|
+
name.sub!( /.*::/, '' )
|
76
|
+
return name.downcase.to_sym
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
### Register the receiver as needing to be run before +other_plugins+ for requests, and
|
81
|
+
### *after* them for responses.
|
82
|
+
def run_before( *other_plugins )
|
83
|
+
name = self.plugin_name
|
84
|
+
other_plugins.each do |other_name|
|
85
|
+
self.pluggable.loaded_plugins[ other_name ] ||= []
|
86
|
+
mod = self.pluggable.loaded_plugins[ other_name ]
|
87
|
+
|
88
|
+
if mod.respond_to?( :run_after )
|
89
|
+
mod.run_after( name )
|
90
|
+
else
|
91
|
+
Strelka.log.debug "%p plugin not yet loaded; setting up pending deps" % [ other_name ]
|
92
|
+
mod << name
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
### Register the receiver as needing to be run after +other_plugins+ for requests, and
|
99
|
+
### *before* them for responses.
|
100
|
+
def run_after( *other_plugins )
|
101
|
+
Strelka.log.debug " %p will run after %p" % [ self, other_plugins ]
|
102
|
+
self.successors.merge( other_plugins )
|
103
|
+
end
|
104
|
+
|
105
|
+
end # module Plugin
|
106
|
+
|
107
|
+
|
108
|
+
# Module API for the plugin system. This mixin adds the ability to load
|
109
|
+
# and install plugins into the extended object.
|
110
|
+
module PluginLoader
|
111
|
+
|
112
|
+
### Extension callback -- initialize some data structures in the extended
|
113
|
+
### object.
|
114
|
+
def self::extended( mod )
|
115
|
+
super
|
116
|
+
mod.loaded_plugins = Strelka::PluginRegistry.new
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
##
|
121
|
+
# The Hash of loaded plugin modules, keyed by their downcased and symbolified
|
122
|
+
# name (e.g., Strelka::App::Templating => :templating)
|
123
|
+
attr_accessor :loaded_plugins
|
124
|
+
|
125
|
+
##
|
126
|
+
# If plugins have already been installed, this will be the call frame
|
127
|
+
# they were first installed from. This is used to warn about installing
|
128
|
+
# plugins twice.
|
129
|
+
attr_accessor :plugins_installed_from
|
130
|
+
|
131
|
+
|
132
|
+
### Returns +true+ if the plugins for the extended app class have already
|
133
|
+
### been installed.
|
134
|
+
def plugins_installed?
|
135
|
+
return !self.plugins_installed_from.nil?
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
### Extension callback -- add instance variables to extending objects.
|
140
|
+
def inherited( subclass )
|
141
|
+
super
|
142
|
+
@plugins ||= []
|
143
|
+
subclass.loaded_plugins = self.loaded_plugins
|
144
|
+
subclass.plugins_installed_from = nil
|
145
|
+
subclass.instance_variable_set( :@plugins, @plugins.dup )
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
### Load the plugins with the given +names+ and install them.
|
150
|
+
def plugins( *names )
|
151
|
+
Strelka.log.info "Adding plugins: %s" % [ names.flatten.map(&:to_s).join(', ') ]
|
152
|
+
|
153
|
+
# Load the associated Plugin Module objects
|
154
|
+
names.flatten.each {|name| self.load_plugin(name) }
|
155
|
+
|
156
|
+
# Add the name/s to the list of mixins to apply on startup
|
157
|
+
@plugins |= names
|
158
|
+
|
159
|
+
# Install the declarative half of the plugin immediately
|
160
|
+
names.each do |name|
|
161
|
+
plugin = nil
|
162
|
+
|
163
|
+
if name.is_a?( Module )
|
164
|
+
plugin = name
|
165
|
+
else
|
166
|
+
plugin = self.loaded_plugins[ name ]
|
167
|
+
end
|
168
|
+
|
169
|
+
Strelka.log.debug " registering %p" % [ name ]
|
170
|
+
self.register_plugin( plugin )
|
171
|
+
end
|
172
|
+
end
|
173
|
+
alias_method :plugin, :plugins
|
174
|
+
|
175
|
+
|
176
|
+
### Load the plugin with the given +name+
|
177
|
+
def load_plugin( name )
|
178
|
+
|
179
|
+
# Just return Modules as-is
|
180
|
+
return name if name.is_a?( Strelka::Plugin )
|
181
|
+
mod = self.loaded_plugins[ name.to_sym ]
|
182
|
+
|
183
|
+
unless mod.is_a?( Module )
|
184
|
+
prefix = self.name.gsub( /::/, File::PATH_SEPARATOR )
|
185
|
+
Strelka.log.debug "Loading plugin from #{prefix}/#{name}"
|
186
|
+
require "#{prefix}/#{name}"
|
187
|
+
mod = self.loaded_plugins[ name.to_sym ] or
|
188
|
+
raise "#{name} plugin didn't load correctly."
|
189
|
+
end
|
190
|
+
|
191
|
+
return mod
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
### Register the plugin +mod+ in the receiving class. This adds any
|
196
|
+
### declaratives and class-level data necessary for configuring the
|
197
|
+
### plugin.
|
198
|
+
def register_plugin( mod )
|
199
|
+
if mod.const_defined?( :ClassMethods )
|
200
|
+
cm_mod = mod.const_get(:ClassMethods)
|
201
|
+
Strelka.log.debug " adding class methods from %p" % [ cm_mod ]
|
202
|
+
|
203
|
+
extend( cm_mod )
|
204
|
+
cm_mod.instance_variables.each do |ivar|
|
205
|
+
Strelka.log.debug " copying class instance variable %s" % [ ivar ]
|
206
|
+
ival = cm_mod.instance_variable_get( ivar )
|
207
|
+
|
208
|
+
# Don't duplicate modules/classes or immediates
|
209
|
+
instance_variable_set( ivar, Strelka::DataUtilities.deep_copy(ival) )
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
|
215
|
+
### Install the mixin part of plugins immediately before the first instance
|
216
|
+
### is created.
|
217
|
+
def new( * )
|
218
|
+
self.install_plugins unless self.plugins_installed?
|
219
|
+
super
|
220
|
+
end
|
221
|
+
|
222
|
+
|
223
|
+
### Install the mixin part of the plugin, in the order determined by
|
224
|
+
### the plugin registry based on the run_before and run_after specifications
|
225
|
+
### of the plugins themselves.
|
226
|
+
def install_plugins
|
227
|
+
if self.plugins_installed?
|
228
|
+
Strelka.log.warn "Plugins were already installed for %p from %p" %
|
229
|
+
[ self, self.plugins_installed_from ]
|
230
|
+
Strelka.log.info "I'll attempt to install any new ones, but plugin ordering"
|
231
|
+
Strelka.log.info "and other functionality might exhibit strange behavior."
|
232
|
+
else
|
233
|
+
Strelka.log.info "Installing plugins for %p." % [ self ]
|
234
|
+
end
|
235
|
+
|
236
|
+
sorted_plugins = self.loaded_plugins.tsort.reverse
|
237
|
+
|
238
|
+
sorted_plugins.each do |name|
|
239
|
+
mod = self.loaded_plugins[ name ]
|
240
|
+
|
241
|
+
unless @plugins.include?( name ) || @plugins.include?( mod )
|
242
|
+
Strelka.log.debug " skipping %s" % [ name ]
|
243
|
+
next
|
244
|
+
end
|
245
|
+
|
246
|
+
Strelka.log.info " including %p." % [ mod ]
|
247
|
+
include( mod )
|
248
|
+
end
|
249
|
+
|
250
|
+
self.plugins_installed_from = caller( 1 ).first
|
251
|
+
end
|
252
|
+
|
253
|
+
end # module PluginLoader
|
254
|
+
|
255
|
+
end # class Strelka
|
256
|
+
|
257
|
+
|
@@ -8,7 +8,9 @@ require 'strelka/router'
|
|
8
8
|
|
9
9
|
# Simple (dumb?) request router for Strelka::App-based applications.
|
10
10
|
class Strelka::Router::Default < Strelka::Router
|
11
|
-
include Strelka::Loggable
|
11
|
+
include Strelka::Loggable,
|
12
|
+
Strelka::Constants,
|
13
|
+
Strelka::ResponseHelpers
|
12
14
|
|
13
15
|
### Create a new router that will route requests according to the specified
|
14
16
|
### +routes+. Each route is a tuple of the form:
|
@@ -20,6 +22,8 @@ class Strelka::Router::Default < Strelka::Router
|
|
20
22
|
### ]
|
21
23
|
def initialize( routes=[], options={} )
|
22
24
|
@routes = Hash.new {|hash, verb| hash[verb] = {} }
|
25
|
+
# :FIXME: Either call #add_route for each route in 'routes', or eliminate
|
26
|
+
# the parameter
|
23
27
|
|
24
28
|
super
|
25
29
|
end
|
@@ -52,7 +56,8 @@ class Strelka::Router::Default < Strelka::Router
|
|
52
56
|
path.slice!( 0, 1 ) if path.start_with?( '/' ) # Strip the leading '/'
|
53
57
|
|
54
58
|
self.log.debug "Looking for a route for: %p %p" % [ verb, path ]
|
55
|
-
verbroutes = @routes[ verb ]
|
59
|
+
verbroutes = @routes[ verb ]
|
60
|
+
return self.allowed_response( path ) if verbroutes.empty?
|
56
61
|
match = self.find_longest_match( verbroutes.keys, path ) or return nil
|
57
62
|
self.log.debug " longest match result: %p" % [ match ]
|
58
63
|
|
@@ -76,6 +81,26 @@ class Strelka::Router::Default < Strelka::Router
|
|
76
81
|
end
|
77
82
|
|
78
83
|
|
84
|
+
### If the specified +path+ matches a valid route, then respond with a
|
85
|
+
### 405 (Method Not Allowed) with the allowed HTTP verbs. Otherwise, return
|
86
|
+
### +nil+.
|
87
|
+
def allowed_response( path )
|
88
|
+
allowed_verbs = []
|
89
|
+
|
90
|
+
routes = @routes.each do |verb, verbroutes|
|
91
|
+
allowed_verbs << verb if self.find_longest_match( verbroutes.keys, path )
|
92
|
+
end
|
93
|
+
allowed_verbs << :HEAD if allowed_verbs.include?( :GET )
|
94
|
+
|
95
|
+
self.log.debug "Allowed methods for path %s: %p" % [ path, allowed_verbs ]
|
96
|
+
return nil if allowed_verbs.empty?
|
97
|
+
|
98
|
+
allowed_hdr = allowed_verbs.map {|verb| verb.to_s.upcase }.join( ', ' )
|
99
|
+
finish_with( HTTP::METHOD_NOT_ALLOWED, 'Method not allowed.', allow: allowed_hdr )
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
|
79
104
|
#########
|
80
105
|
protected
|
81
106
|
#########
|