| Module | Capcode |
| In: |
lib/capcode.rb
lib/capcode/base/db.rb lib/capcode/configuration.rb lib/capcode/filters.rb lib/capcode/render/text.rb lib/capcode/helpers/auth.rb |
| __auth__ | [RW] |
Add routes to a controller class
module Capcode
class Hello < Route '/hello/(.*)', '/hello/([^#]*)#(.*)'
def get( arg1, arg2 )
...
end
end
end
In the get method, you will receive the maximum of parameters declared by the routes. In this example, you will receive 2 parameters. So if you go to /hello/world#friend then arg1 will be set to world and arg2 will be set to friend. Now if you go to /hello/you, then arg1 will be set to you and arg2 will be set to nil
If the regexp in the route does not match, all arguments will be nil
# File lib/capcode.rb, line 334
334: def Route *routes_paths
335: Class.new {
336: meta_def(:__urls__) {
337: # < Route '/hello/world/([^\/]*)/id(\d*)', '/hello/(.*)', :agent => /Songbird (\d\.\d)[\d\/]*?/
338: # # => [ {'/hello/world' => '([^\/]*)/id(\d*)', '/hello' => '(.*)'},
339: # 2,
340: # <Capcode::Klass>,
341: # {:agent => /Songbird (\d\.\d)[\d\/]*?/} ]
342: hash_of_routes = {}
343: max_captures_for_routes = 0
344: routes_paths.each do |current_route_path|
345: if current_route_path.class == String
346: m = /\/([^\/]*\(.*)/.match( current_route_path )
347: if m.nil?
348: raise Capcode::RouteError, "Route `#{current_route_path}' already defined with regexp `#{hash_of_routes[current_route_path]}' !", caller if hash_of_routes.keys.include?(current_route_path)
349: hash_of_routes[current_route_path] = ''
350: else
351: _pre = m.pre_match
352: _pre = "/" if _pre.size == 0
353: raise Capcode::RouteError, "Route `#{_pre}' already defined with regexp `#{hash_of_routes[_pre]}' !", caller if hash_of_routes.keys.include?(_pre)
354: hash_of_routes[_pre] = m.captures[0]
355: max_captures_for_routes = Regexp.new(m.captures[0]).number_of_captures if max_captures_for_routes < Regexp.new(m.captures[0]).number_of_captures
356: end
357: else
358: raise Capcode::ParameterError, "Bad route declaration !", caller
359: end
360: end
361: [hash_of_routes, max_captures_for_routes, self]
362: }
363:
364: # Hash containing all the request parameters (GET or POST)
365: def params
366: @request.params
367: end
368:
369: # Hash containing all the environment variables
370: def env
371: @env
372: end
373:
374: # Session hash
375: def session
376: @env['rack.session']
377: end
378:
379: # Return the Rack::Request object
380: def request
381: @request
382: end
383:
384: # Return the Rack::Response object
385: def response
386: @response
387: end
388:
389: def call( e ) #:nodoc:
390: @env = e
391: @response = Rack::Response.new
392: @request = Rack::Request.new(@env)
393:
394: # __k = self.class.to_s.split( /::/ )[-1].downcase.to_sym
395: # @@__FILTERS.each do |f|
396: # proc = f.delete(:action)
397: # __run = true
398: # if f[:only]
399: # __run = f[:only].include?(__k)
400: # end
401: # if f[:except]
402: # __run = !f[:except].include?(__k)
403: # end
404: #
405: # # proc.call(self) if __run
406: # puts "call #{proc} for #{__k}"
407: # end
408:
409: # Check authz
410: authz_options = nil
411: if Capcode.__auth__ and Capcode.__auth__.size > 0
412: authz_options = Capcode.__auth__[@request.path]||nil
413: if authz_options.nil?
414: route = nil
415:
416: Capcode.__auth__.each do |r, o|
417: regexp = "^#{r.gsub(/\/$/, "")}([/]{1}.*)?$"
418: if Regexp.new(regexp).match( @request.path )
419: if route.nil? or r.size > route.size
420: route = r
421: authz_options = o
422: end
423: end
424: end
425: end
426: end
427:
428: r = catch(:halt) {
429: unless authz_options.nil?
430: http_authentication( :type => authz_options[:type], :realm => authz_options[:realm], :opaque => authz_options[:realm] ) {
431: authz_options[:autz]
432: }
433: end
434:
435: finalPath = nil
436: finalArgs = nil
437: finalNArgs = nil
438:
439: aPath = @request.path.gsub( /^\//, "" ).split( "/" )
440: self.class.__urls__[0].each do |p, r|
441: xPath = p.gsub( /^\//, "" ).split( "/" )
442: if (xPath - aPath).size == 0
443: diffArgs = aPath - xPath
444: diffNArgs = diffArgs.size
445: if finalNArgs.nil? or finalNArgs > diffNArgs
446: finalPath = p
447: finalNArgs = diffNArgs
448: finalArgs = diffArgs
449: end
450: end
451:
452: end
453:
454: nargs = self.class.__urls__[1]
455: regexp = Regexp.new( self.class.__urls__[0][finalPath] )
456: args = regexp.match( Rack::Utils.unescape(@request.path).gsub( Regexp.new( "^#{finalPath}" ), "" ).gsub( /^\//, "" ) )
457: if args.nil?
458: raise Capcode::ParameterError, "Path info `#{@request.path_info}' does not match route regexp `#{regexp.source}'"
459: else
460: args = args.captures.map { |x| (x.size == 0)?nil:x }
461: end
462:
463: while args.size < nargs
464: args << nil
465: end
466:
467: filter_output = Capcode::Filter.execute( self )
468:
469: if( filter_output.nil? )
470: case @env["REQUEST_METHOD"]
471: when "GET"
472: get( *args )
473: when "POST"
474: _method = params.delete( "_method" ) { |_| "post" }
475: send( _method.downcase.to_sym, *args )
476: else
477: _method = @env["REQUEST_METHOD"]
478: send( _method.downcase.to_sym, *args )
479: end
480: else
481: filter_output
482: end
483: }
484: if r.respond_to?(:to_ary)
485: @response.status = r.shift #r[0]
486: #r[1].each do |k,v|
487: r.shift.each do |k,v|
488: @response[k] = v
489: end
490: @response.body = r.shift #r[2]
491: else
492: @response.write r
493: end
494:
495: @response.finish
496: end
497:
498: include Capcode::Helpers
499: include Capcode::Views
500: }
501: end
Return the Rack App.
Options : see Capcode::Configuration.set
Options set here replace the ones set globally
# File lib/capcode.rb, line 570
570: def application( args = {} )
571: Capcode::Configuration.configuration(args)
572:
573: Capcode.constants.each do |k|
574: begin
575: if eval "Capcode::#{k}.public_methods(true).include?( '__urls__' )"
576: hash_of_routes, max_captures_for_routes, klass = eval "Capcode::#{k}.__urls__"
577: hash_of_routes.keys.each do |current_route_path|
578: #raise Capcode::RouteError, "Route `#{current_route_path}' already define !", caller if @@__ROUTES.keys.include?(current_route_path)
579: raise Capcode::RouteError, "Route `#{current_route_path}' already define !", caller if Capcode.routes.keys.include?(current_route_path)
580: #@@__ROUTES[current_route_path] = klass.new
581: Capcode.routes[current_route_path] = klass.new
582: end
583: end
584: rescue => e
585: raise e.message
586: end
587: end
588:
589: # Set Static directory
590: #@@__STATIC_DIR = (conf[:static][0].chr == "/")?conf[:static]:"/"+conf[:static] unless conf[:static].nil?
591: Capcode.static = (Capcode::Configuration.get(:static)[0].chr == "/")?Capcode::Configuration.get(:static):"/"+Capcode::Configuration.get(:static) unless Capcode::Configuration.get(:static).nil?
592:
593: # Initialize Rack App
594: puts "** Map routes." if Capcode::Configuration.get(:verbose)
595: #app = Rack::URLMap.new(@@__ROUTES)
596: app = Rack::URLMap.new(Capcode.routes)
597: puts "** Initialize static directory (#{Capcode.static}) in #{File.expand_path(Capcode::Configuration.get(:root))}" if Capcode::Configuration.get(:verbose)
598: app = Rack::Static.new(
599: app,
600: #:urls => [@@__STATIC_DIR],
601: :urls => [Capcode.static],
602: :root => File.expand_path(Capcode::Configuration.get(:root))
603: ) unless Capcode::Configuration.get(:static).nil?
604: puts "** Initialize session" if Capcode::Configuration.get(:verbose)
605: app = Rack::Session::Cookie.new( app, Capcode::Configuration.get(:session) )
606: app = Capcode::HTTPError.new(app)
607: app = Rack::ContentLength.new(app)
608: app = Rack::Lint.new(app)
609: app = Rack::ShowExceptions.new(app)
610: #app = Rack::Reloader.new(app) ## -- NE RELOAD QUE capcode.rb -- So !!!
611: # app = Rack::CommonLogger.new( app, Logger.new(conf[:log]) )
612:
613: middlewares.each do |mw|
614: middleware, args, block = mw
615: puts "** Load middleware #{middleware}" if Capcode::Configuration.get(:verbose)
616: if block
617: app = middleware.new( app, *args, &block )
618: else
619: app = middleware.new( app, *args )
620: end
621: end
622:
623: # Start database
624: if self.methods.include? "db_connect"
625: db_connect( Capcode::Configuration.get(:db_config), Capcode::Configuration.get(:log) )
626: end
627:
628: if block_given?
629: yield( self )
630: end
631:
632: return app
633: end
Add a before filter :
module Capcode
before_filter :my_global_action
before_filter :need_login, :except => [:Login]
before_filter :check_mail, :only => [:MailBox]
# ...
end
If the action return nil, the normal get or post will be executed, else no.
# File lib/capcode/filters.rb, line 14
14: def before_filter( action, opts = {} )
15: Capcode::Filter.filters[action] = { }
16:
17: opts.each do |k, v|
18: Capcode::Filter.filters[action][k] = v
19: end
20: end
Hash containing all the environment variables
# File lib/capcode.rb, line 370
370: def env
371: @env
372: end
Allow you to add and HTTP Authentication (Basic or Digest) to controllers for or specific route
Options :
The block must return a Hash of username => password like that :
{
"user1" => "pass1",
"user2" => "pass2",
# ...
}
# File lib/capcode.rb, line 544
544: def http_authentication( opts = {}, &b )
545: options = {
546: :type => :basic,
547: :realm => "Capcode.app",
548: :opaque => "opaque",
549: :routes => "/"
550: }.merge( opts )
551:
552: options[:autz] = b.call()
553:
554: @__auth__ ||= {}
555:
556: if options[:routes].class == Array
557: options[:routes].each do |r|
558: @__auth__[r] = options
559: end
560: else
561: @__auth__[options[:routes]] = options
562: end
563: end
Return the Rack::Request object
# File lib/capcode.rb, line 380
380: def request
381: @request
382: end
Return the Rack::Response object
# File lib/capcode.rb, line 385
385: def response
386: @response
387: end
Start your application.
Options : see Capcode::Configuration.set
Options set here replace the ones set globally
# File lib/capcode.rb, line 640
640: def run( args = {} )
641: Capcode::Configuration.configuration(args)
642:
643: # Parse options
644: opts = OptionParser.new do |opts|
645: opts.banner = "Usage: #{File.basename($0)} [options]"
646: opts.separator ""
647: opts.separator "Specific options:"
648:
649: opts.on( "-C", "--console", "Run in console mode with IRB (default: false)" ) {
650: Capcode::Configuration.set :console, true
651: }
652: opts.on( "-h", "--host HOSTNAME", "Host for web server to bind to (default: #{Capcode::Configuration.get(:host)})" ) { |h|
653: Capcode::Configuration.set :host, h
654: }
655: opts.on( "-p", "--port NUM", "Port for web server (default: #{Capcode::Configuration.get(:port)})" ) { |p|
656: Capcode::Configuration.set :port, p
657: }
658: opts.on( "-d", "--daemonize [true|false]", "Daemonize (default: #{Capcode::Configuration.get(:daemonize)})" ) { |d|
659: Capcode::Configuration.set :daemonize, d
660: }
661: opts.on( "-r", "--root PATH", "Working directory (default: #{Capcode::Configuration.get(:root)})" ) { |w|
662: Capcode::Configuration.set :root, w
663: }
664: opts.on( "-s", "--static PATH", "Static directory -- relative to the root directory (default: #{Capcode::Configuration.get(:static)})" ) { |r|
665: Capcode::Configuration.set :static, r
666: }
667:
668: opts.separator ""
669: opts.separator "Common options:"
670:
671: opts.on("-?", "--help", "Show this message") do
672: puts opts
673: exit
674: end
675: opts.on("-v", "--version", "Show versions") do
676: puts "Capcode version #{Capcode::CAPCOD_VERION} (ruby v#{RUBY_VERSION})"
677: exit
678: end
679: opts.on_tail( "-V", "--verbose", "Run in verbose mode" ) do
680: Capcode::Configuration.set :verbose, true
681: end
682: end
683:
684: begin
685: opts.parse! ARGV
686: rescue OptionParser::ParseError => ex
687: puts "!! #{ex.message}"
688: puts "** use `#{File.basename($0)} --help` for more details..."
689: exit 1
690: end
691:
692: # Run in the Working directory
693: puts "** Go on root directory (#{File.expand_path(Capcode::Configuration.get(:root))})" if Capcode::Configuration.get(:verbose)
694: Dir.chdir( Capcode::Configuration.get(:root) ) do
695:
696: # Check that mongrel exists
697: if Capcode::Configuration.get(:server).nil? || Capcode::Configuration.get(:server) == "mongrel"
698: begin
699: require 'mongrel'
700: Capcode::Configuration.set :server, :mongrel
701: rescue LoadError
702: puts "!! could not load mongrel. Falling back to webrick."
703: Capcode::Configuration.set :server, :webrick
704: end
705: end
706:
707: # From rackup !!!
708: if Capcode::Configuration.get(:daemonize)
709: if /java/.match(RUBY_PLATFORM).nil?
710: if RUBY_VERSION < "1.9"
711: exit if fork
712: Process.setsid
713: exit if fork
714: # Dir.chdir "/"
715: File.umask 0000
716: STDIN.reopen "/dev/null"
717: STDOUT.reopen "/dev/null", "a"
718: STDERR.reopen "/dev/null", "a"
719: else
720: Process.daemon
721: end
722: else
723: puts "!! daemonize option unavailable on #{RUBY_PLATFORM} platform."
724: end
725:
726: File.open(Capcode::Configuration.get(:pid), 'w'){ |f| f.write("#{Process.pid}") }
727: at_exit { File.delete(Capcode::Configuration.get(:pid)) if File.exist?(Capcode::Configuration.get(:pid)) }
728: end
729:
730: app = nil
731: if block_given?
732: app = application(Capcode::Configuration.get) { yield( self ) }
733: else
734: app = application(Capcode::Configuration.get)
735: end
736: app = Rack::CommonLogger.new( app, Logger.new(Capcode::Configuration.get(:log)) )
737:
738: if Capcode::Configuration.get(:console)
739: puts "Run console..."
740: IRB.start
741: exit
742: end
743:
744: # Start server
745: case Capcode::Configuration.get(:server).to_s
746: when "mongrel"
747: puts "** Starting Mongrel on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
748: Rack::Handler::Mongrel.run( app, {:Port => Capcode::Configuration.get(:port), :Host => Capcode::Configuration.get(:host)} ) { |server|
749: trap "SIGINT", proc { server.stop }
750: }
751: when "webrick"
752: puts "** Starting WEBrick on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
753: Rack::Handler::WEBrick.run( app, {:Port => Capcode::Configuration.get(:port), :BindAddress => Capcode::Configuration.get(:host)} ) { |server|
754: trap "SIGINT", proc { server.shutdown }
755: }
756: when "thin"
757: puts "** Starting Thin on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
758: Rack::Handler::Thin.run( app, {:Port => Capcode::Configuration.get(:port), :Host => Capcode::Configuration.get(:host)} ) { |server|
759: trap "SIGINT", proc { server.stop }
760: }
761: end
762: end
763: end
# File lib/capcode/configuration.rb, line 3 3: def set(key, value, opts = {}); Configuration.set(key, value, opts); end
This method allow you to use a Rack middleware
Example :
module Capcode
...
use Rack::Codehighlighter, :coderay, :element => "pre",
:pattern => /\A:::(\w+)\s*\n/, :logging => false
...
end
# File lib/capcode.rb, line 523
523: def use(middleware, *args, &block)
524: middlewares << [middleware, args, block]
525: end