Class: Maveric
- Inherits:
-
Object
- Object
- Maveric
- Includes:
- Mongrel::HttpHandlerPlugin
- Defined in:
- lib/maveric.rb,
lib/maveric/mongrel.rb,
lib/maveric/sessions.rb
Overview
Includes Mongrel::HttpHandlerPlugin into Maveric, allowing the use of Maveric subclasses as HttpHandlers in the context of Mongrel.
Defined Under Namespace
Modules: Models, Views Classes: Controller, Route, SimpleSessions, WEBrickServlet
Constant Summary collapse
- VERSION =
Implementation details.
'0.4.0'
- EOL =
Standard end of line for HTTP
"\r\n"
- MP_BOUND_REGEX =
Group 1 wil contain a boundary for multipart/form-data bodies.
/\Amultipart\/form-data.*boundary=\"?([^\";, ]+)\"?/n
Instance Attribute Summary collapse
-
#options ⇒ Object
readonly
Returns the value of attribute options.
-
#routes ⇒ Object
readonly
Returns the value of attribute routes.
Class Method Summary collapse
-
.FCGI(maveric, opts = {}) ⇒ Object
Maveric::FCGI(MyMaveric.new).
-
.inherited(klass) ⇒ Object
Sets up a new Maveric with everything it needs for normal operation.
-
.nested_controllers(realm = self, stk = []) ⇒ Object
A recursive method to hunt out subclasses of Controller nested within a Maveric subclass.
-
.parse_multipart(boundary, body) ⇒ Object
Parse a multipart/form-data entity.
-
.prepare_env(action = nil, opts = {}, &block) ⇒ Object
Actions are kept in an array to maintain running order.
-
.query_parse(qs, delim = '&;') ⇒ Object
Parses a query string by breaking it up around the delimiting characters.
-
.session(id) ⇒ Object
Return a session via Session#session.
-
.sessions ⇒ Object
Return the standard session set.
Instance Method Summary collapse
-
#add_route(controller, path, opts = {}) ⇒ Object
Passes arguments to ::Maveric::Route.new and adds the result to @routes.
-
#dispatch(req_body = $stdin, env = ENV, opts = {}) ⇒ Object
Maveric’s cue to start doing the heavy lifting.
-
#error(err = $!) ⇒ Object
Override for custom error handling and/or styling.
-
#initialize(opts = {}) ⇒ Maveric
constructor
Sets @options from
opts
and initializes @routes. -
#match(path) ⇒ Object
Returns the first non nil result of Route#match across @routes.
-
#path_to(controller, args = {}) ⇒ Object
Returns the first non nil result of Route#path_to across the subset of.
-
#prepare_env(*a, &b) ⇒ Object
Alias to Maveric.prepare_env.
-
#prepare_environment(env) ⇒ Object
env
should be a normal environment hash derived from HTTP. -
#process(request, response) ⇒ Object
Runs #dispatch on the request and filters the resulting Controller instance to the
response
object. -
#request_begins(params) ⇒ Object
Runs #prepare_enviroment on the env to get things moving.
- #set_session(env) ⇒ Object
Constructor Details
#initialize(opts = {}) ⇒ Maveric
Sets @options from opts
and initializes @routes. Adds routes from nested Controllers.
262 263 264 265 266 267 268 269 270 271 |
# File 'lib/maveric.rb', line 262 def initialize opts={} @options = {:path_prefix => self.class.to_path(true)} @options.update opts @routes = Set.new self.class.nested_controllers.each do |cont| routes = cont.routes routes ||= [[cont.to_path(0).sub(/^#{self.class.to_path(0)}\/?/,'/'),{}]] routes.each {|route,ropts| add_route cont, route, ropts } end end |
Instance Attribute Details
#options ⇒ Object (readonly)
Returns the value of attribute options.
294 295 296 |
# File 'lib/maveric.rb', line 294 def @options end |
#routes ⇒ Object (readonly)
Returns the value of attribute routes.
294 295 296 |
# File 'lib/maveric.rb', line 294 def routes @routes end |
Class Method Details
.FCGI(maveric, opts = {}) ⇒ Object
Maveric::FCGI(MyMaveric.new)
7 8 9 10 11 12 13 14 15 16 17 18 |
# File 'lib/maveric/fastcgi.rb', line 7 def Maveric.FCGI maveric, opts={} ::FCGI.each do |req| req.out << "Status: 200 OK" + ::Maveric::EOL*2 if $DEBUG req.out << response = begin maveric.dispatch(req.in, req.env).to_http rescue "Status: 500 Server Error omgwtf!"+::Maveric::EOL*2+ "#{$!}\n#{$!.backtrace*"\n"}" end req.finish end end |
.inherited(klass) ⇒ Object
Sets up a new Maveric with everything it needs for normal operation. Many things are either copied or included from it’s parent. Models and Views are included by their respective modules.
219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/maveric.rb', line 219 def inherited klass super parent = self klass.class_eval do const_set(:Models, Module.new). module_eval { include parent::Models } const_set(:Views, Module.new). module_eval { include parent::Views } @prepare_env = parent.prepare_env.dup end end |
.nested_controllers(realm = self, stk = []) ⇒ Object
A recursive method to hunt out subclasses of Controller nested within a Maveric subclass. Used in the setting up of autoroutes. Disregards everything within a nested Maveric subclass.
204 205 206 207 208 209 210 211 212 213 |
# File 'lib/maveric.rb', line 204 def nested_controllers realm=self, stk=[] stk << realm #We don't need to visit the same thing twice. realm.constants.map do |c| next if stk.include?(c = realm.const_get(c)) or not c.is_a? Module a = [] a << c if c < ::Maveric::Controller a += nested_controllers c, stk unless c < ::Maveric a end.compact.flatten end |
.parse_multipart(boundary, body) ⇒ Object
Parse a multipart/form-data entity. Adapated from cgi.rb. The body argument may either be a StringIO or a IO of subclass thereof.
Might need to be rehauled to match query_parse’s behaviour.
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/maveric.rb', line 170 def parse_multipart boundary, body values = {} bound = /(?:\r?\n|\A)#{Regexp::quote('--'+boundary)}(?:--)?\r$/ until body.eof? fv = {} until body.eof? or /^#{EOL}$/ =~ l case l = body.readline when /^Content-Type: (.+?)(\r$|\Z)/m fv[:type] = $1 when /^Content-Disposition: form-data;/ $'.scan(/(?:\s(\w+)="([^"]+)")/) {|w| fv[w[0].intern] = w[1] } end end o = fv[:filename] ? '' : fv[:tempfile] = Tempfile.new('MVC').binmode body.inject do |buf, line| o << buf.chomp and break if bound =~ line o << buf line end # Merb and Camping do it faster. fv[:tempfile].rewind if fv.key? :tempfile values[fv[:name]] = fv.key?(:filename) ? fv : o end body.rewind rescue nil # FCGI::Stream fun. values end |
.prepare_env(action = nil, opts = {}, &block) ⇒ Object
Actions are kept in an array to maintain running order.
This is where you’d add environmental preprocessors to a Maveric. Please note that actions are copied to subclasses at definition time.
If action
is a Symbol and no block is provided, in #prepare_environment, the corresponding method is called with the environment hash as an argument. If a block is given then that block will be called with the environment hash as the single argument.
Additional arguments honored include :test, which should be a Proc that accepts a single argument. The argument will be the environment hash and the boolean result of the block will determine if the action will be run upon the environment.
247 248 249 250 251 |
# File 'lib/maveric.rb', line 247 def prepare_env action=nil, opts={}, &block if action.is_a? Symbol @prepare_env << opts.update(:name => action, :run => block) else @prepare_env end end |
.query_parse(qs, delim = '&;') ⇒ Object
Parses a query string by breaking it up around the delimiting characters. You can also use this to parse cookies by changing the characters used in the second parameter (which defaults to ‘;,’).
This will return a hash of parameters, values being contained in an array. As a warning, the default value is an empty array, not nil.
157 158 159 160 161 162 163 |
# File 'lib/maveric.rb', line 157 def query_parse(qs, delim = '&;') (qs||'').split(/[#{delim}] */n).inject({}) { |h,p| k, v = URI.decode(p).split('=',2) (h[k]||=[]) << v h } end |
.session(id) ⇒ Object
Return a session via Session#session
88 89 90 |
# File 'lib/maveric/sessions.rb', line 88 def self.session id @sessions.session id end |
.sessions ⇒ Object
Return the standard session set.
83 84 85 |
# File 'lib/maveric/sessions.rb', line 83 def self.sessions @sessions end |
Instance Method Details
#add_route(controller, path, opts = {}) ⇒ Object
Passes arguments to ::Maveric::Route.new and adds the result to @routes.
274 275 276 |
# File 'lib/maveric.rb', line 274 def add_route controller, path, opts={} @routes << ::Maveric::Route.new(controller, path, opts) end |
#dispatch(req_body = $stdin, env = ENV, opts = {}) ⇒ Object
Maveric’s cue to start doing the heavy lifting. env
should be a hash with the typical assignments from an HTTP environment or crying and whining will ensue. req_body
should be an IO compatible instance.
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 |
# File 'lib/maveric.rb', line 300 def dispatch req_body=$stdin, env=ENV, opts={} begin prepare_environment env unless env.key? :maveric raise RuntimeError, [404, "Page not found."] unless env[:route] # If this is a POST request we need to load data from the body if env['REQUEST_METHOD'] =~ /^post$/i params = env.key?(:multipart_boundary) ? parse_multipart(env[:multipart_boundary], req_body) : ::Maveric.query_parse(req_body.read) env[:params].update params end env[:route].controller.new(req_body, env, opts) rescue StandardError => e error(e) end end |
#error(err = $!) ⇒ Object
Override for custom error handling and/or styling.
320 321 322 |
# File 'lib/maveric.rb', line 320 def error err=$! err end |
#match(path) ⇒ Object
Returns the first non nil result of Route#match across @routes. Will remove the option setting of :path_prefix form the beginning of the path.
281 282 283 284 285 |
# File 'lib/maveric.rb', line 281 def match path path = path.sub(/^#{@options[:path_prefix]}\/?/, '/') if \ @options.key? :path_prefix @routes.eject {|route| route.match path } end |
#path_to(controller, args = {}) ⇒ Object
Returns the first non nil result of Route#path_to across the subset of
290 291 292 |
# File 'lib/maveric.rb', line 290 def path_to controller, args={} @routes.eject {|route| route.controller == controller and route.path_to args } end |
#prepare_env(*a, &b) ⇒ Object
Alias to Maveric.prepare_env
255 256 257 |
# File 'lib/maveric.rb', line 255 def prepare_env(*a, &b) self.class.prepare_env(*a, &b) end |
#prepare_environment(env) ⇒ Object
env
should be a normal environment hash derived from HTTP. Run through actions specified by Maveric.prepare_env in the order stated, testing env against act if present to determine if it will be used, and runs the action on env.
329 330 331 332 333 334 335 336 337 338 339 |
# File 'lib/maveric.rb', line 329 def prepare_environment env # DEV-NOTE: This method is seperated from prepare_env, in contrast to # #before and #after in Controller, due to the fact one Maveric instance # exists for each service, rather than for each occurance of env per # request. env.update :maveric => self prepare_env.each do |act| next unless act[:test].nil? or act[:test][env] (act[:run] || method(act[:name]))[env] end end |
#process(request, response) ⇒ Object
Runs #dispatch on the request and filters the resulting Controller instance to the response
object.
12 13 14 15 16 17 18 |
# File 'lib/maveric/mongrel.rb', line 12 def process request, response reply = dispatch request.body, request.params response.start reply.status do |head,out| reply.headers.each {|k,v| head[k] = v } out.write reply.body end end |
#request_begins(params) ⇒ Object
Runs #prepare_enviroment on the env to get things moving.
21 22 23 |
# File 'lib/maveric/mongrel.rb', line 21 def request_begins params prepare_environment params end |
#set_session(env) ⇒ Object
95 96 97 98 |
# File 'lib/maveric/sessions.rb', line 95 def set_session env session_id = env[:cookies][::Maveric::SimpleSessions::COOKIE_NAME].first env[:session] = ::Maveric.session session_id end |