strelka 0.0.1.pre.187 → 0.0.1.pre.193
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
#########
|