| 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 |
| Route | = | Capcode::Route(nil) |
| __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 368
368: def Route *routes_paths
369: create_path = routes_paths[0].nil?
370: Class.new {
371: meta_def(:__urls__) {
372: routes_paths = ['/'+self.to_s.gsub( /^Capcode::/, "" ).underscore] if create_path == true
373: # < Route '/hello/world/([^\/]*)/id(\d*)', '/hello/(.*)', :agent => /Songbird (\d\.\d)[\d\/]*?/
374: # # => [ {'/hello/world' => '([^\/]*)/id(\d*)', '/hello' => '(.*)'},
375: # 2,
376: # <Capcode::Klass>,
377: # {:agent => /Songbird (\d\.\d)[\d\/]*?/} ]
378: hash_of_routes = {}
379: max_captures_for_routes = 0
380: routes_paths.each do |current_route_path|
381: if current_route_path.class == String
382: m = /\/([^\/]*\(.*)/.match( current_route_path )
383: if m.nil?
384: 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)
385: hash_of_routes[current_route_path] = ''
386: else
387: _pre = m.pre_match
388: _pre = "/" if _pre.size == 0
389: raise Capcode::RouteError, "Route `#{_pre}' already defined with regexp `#{hash_of_routes[_pre]}' !", caller if hash_of_routes.keys.include?(_pre)
390: hash_of_routes[_pre] = m.captures[0]
391: 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
392: end
393: else
394: raise Capcode::ParameterError, "Bad route declaration !", caller
395: end
396: end
397: [hash_of_routes, max_captures_for_routes, self]
398: }
399:
400: # Hash containing all the request parameters (GET or POST)
401: def params
402: @request.params
403: end
404:
405: # Hash containing all the environment variables
406: def env
407: @env
408: end
409:
410: # Session hash
411: def session
412: @env['rack.session']
413: end
414:
415: # Return the Rack::Request object
416: def request
417: @request
418: end
419:
420: # Return the Rack::Response object
421: def response
422: @response
423: end
424:
425: def call( e ) #:nodoc:
426: @env = e
427: @response = Rack::Response.new
428: @request = Rack::Request.new(@env)
429:
430: # Check authz
431: authz_options = nil
432: if Capcode.__auth__ and Capcode.__auth__.size > 0
433: authz_options = Capcode.__auth__[@request.path]||nil
434: if authz_options.nil?
435: route = nil
436:
437: Capcode.__auth__.each do |r, o|
438: regexp = "^#{r.gsub(/\/$/, "")}([/]{1}.*)?$"
439: if Regexp.new(regexp).match( @request.path )
440: if route.nil? or r.size > route.size
441: route = r
442: authz_options = o
443: end
444: end
445: end
446: end
447: end
448:
449: r = catch(:halt) {
450: unless authz_options.nil?
451: http_authentication( :type => authz_options[:type], :realm => authz_options[:realm], :opaque => authz_options[:realm] ) {
452: authz_options[:autz]
453: }
454: end
455:
456: finalPath = nil
457: finalArgs = nil
458: finalNArgs = nil
459:
460: aPath = @request.path.gsub( /^\//, "" ).split( "/" )
461: self.class.__urls__[0].each do |p, r|
462: xPath = p.gsub( /^\//, "" ).split( "/" )
463: if (xPath - aPath).size == 0
464: diffArgs = aPath - xPath
465: diffNArgs = diffArgs.size - 1
466: if finalNArgs.nil? or finalNArgs > diffNArgs
467: finalPath = p
468: finalNArgs = diffNArgs
469: finalArgs = diffArgs
470: end
471: end
472: end
473:
474: if finalNArgs > self.class.__urls__[1]
475: return [404, {'Content-Type' => 'text/plain'}, "Not Found: #{@request.path}"]
476: end
477:
478: nargs = self.class.__urls__[1]
479: regexp = Regexp.new( self.class.__urls__[0][finalPath] )
480: args = regexp.match( Rack::Utils.unescape(@request.path).gsub( Regexp.new( "^#{finalPath}" ), "" ).gsub( /^\//, "" ) )
481: if args.nil?
482: raise Capcode::ParameterError, "Path info `#{@request.path_info}' does not match route regexp `#{regexp.source}'"
483: else
484: args = args.captures.map { |x| (x.size == 0)?nil:x }
485: end
486:
487: while args.size < nargs
488: args << nil
489: end
490:
491: filter_output = Capcode::Filter.execute( self )
492:
493: if( filter_output.nil? )
494: # case @env["REQUEST_METHOD"]
495: # when "GET"
496: # get( *args )
497: # when "POST"
498: # _method = params.delete( "_method" ) { |_| "post" }
499: # send( _method.downcase.to_sym, *args )
500: # else
501: # _method = @env["REQUEST_METHOD"]
502: # send( _method.downcase.to_sym, *args )
503: # end
504: begin
505: _method = params.delete( "_method" ) { |_| @env["REQUEST_METHOD"] }
506: if self.class.method_defined?( _method.downcase.to_sym )
507: send( _method.downcase.to_sym, *args )
508: else
509: any( *args )
510: end
511: rescue => e
512: raise e.class, e.to_s
513: end
514: else
515: filter_output
516: end
517: }
518:
519: if r.respond_to?(:to_ary)
520: @response.status = r.shift #r[0]
521: #r[1].each do |k,v|
522: r.shift.each do |k,v|
523: @response[k] = v
524: end
525: @response.write r.shift #r[2]
526: else
527: @response.write r
528: end
529:
530: @response.finish
531: end
532:
533: include Capcode::Helpers
534: include Capcode::Views
535: }
536: end
Return the Rack App.
Options : see Capcode::Configuration.set
Options set here replace the ones set globally
# File lib/capcode.rb, line 605
605: def application( args = {} )
606: Capcode::Configuration.configuration(args)
607: Capcode::Configuration.print_debug if Capcode::Configuration.get(:verbose)
608:
609: Capcode.constants.clone.delete_if {|k|
610: not( Capcode.const_get(k).to_s =~ /Capcode/ ) or [
611: "Filter",
612: "Helpers",
613: "RouteError",
614: "Views",
615: "ParameterError",
616: "HTTPError",
617: "Configuration",
618: "MissingLibrary",
619: "Route",
620: "RenderError"
621: ].include?(k)
622: }.each do |k|
623: begin
624: if eval "Capcode::#{k}.public_methods(true).include?( '__urls__' )"
625: hash_of_routes, max_captures_for_routes, klass = eval "Capcode::#{k}.__urls__"
626: hash_of_routes.keys.each do |current_route_path|
627: #raise Capcode::RouteError, "Route `#{current_route_path}' already define !", caller if @@__ROUTES.keys.include?(current_route_path)
628: raise Capcode::RouteError, "Route `#{current_route_path}' already define !", caller if Capcode.routes.keys.include?(current_route_path)
629: # Capcode.routes[current_route_path] = klass.new
630: Capcode.routes[current_route_path] = klass
631: end
632: end
633: rescue => e
634: raise e.message
635: end
636: end
637:
638: # Set Static directory
639: Capcode.static = (Capcode::Configuration.get(:static)[0].chr == "/")?Capcode::Configuration.get(:static):"/"+Capcode::Configuration.get(:static) unless Capcode::Configuration.get(:static).nil?
640:
641: # Initialize Rack App
642: puts "** Map routes." if Capcode::Configuration.get(:verbose)
643: # app = Rack::URLMap.new(Capcode.routes)
644: app = Capcode::Ext::Rack::URLMap.new(Capcode.routes)
645: puts "** Initialize static directory (#{Capcode.static}) in #{File.expand_path(Capcode::Configuration.get(:root))}" if Capcode::Configuration.get(:verbose)
646: app = Rack::Static.new(
647: app,
648: #:urls => [@@__STATIC_DIR],
649: :urls => [Capcode.static],
650: :root => File.expand_path(Capcode::Configuration.get(:root))
651: ) unless Capcode::Configuration.get(:static).nil?
652: puts "** Initialize session" if Capcode::Configuration.get(:verbose)
653: app = Rack::Session::Cookie.new( app, Capcode::Configuration.get(:session) )
654: app = Capcode::HTTPError.new(app)
655: app = Rack::ContentLength.new(app)
656: app = Rack::Lint.new(app)
657: app = Rack::ShowExceptions.new(app)
658: #app = Rack::Reloader.new(app) ## -- NE RELOAD QUE capcode.rb -- So !!!
659: app = Rack::CommonLogger.new( app, @cclogger = Logger.new(Capcode::Configuration.get(:log)) )
660:
661: middlewares.each do |mw|
662: middleware, args, block = mw
663: puts "** Load middleware #{middleware}" if Capcode::Configuration.get(:verbose)
664: if block
665: app = middleware.new( app, *args, &block )
666: else
667: app = middleware.new( app, *args )
668: end
669: end
670:
671: # Start database
672: if self.methods.include? "db_connect"
673: db_connect( Capcode::Configuration.get(:db_config), Capcode::Configuration.get(:log) )
674: end
675:
676: if block_given?
677: puts "** Execute block" if Capcode::Configuration.get(:verbose)
678: yield( self )
679: end
680:
681: return app
682: 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: Capcode::Filter.ordered_actions << action
17:
18: opts.each do |k, v|
19: Capcode::Filter.filters[action][k] = v
20: end
21: end
Hash containing all the environment variables
# File lib/capcode.rb, line 406
406: def env
407: @env
408: 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 579
579: def http_authentication( opts = {}, &b )
580: options = {
581: :type => :basic,
582: :realm => "Capcode.app",
583: :opaque => "opaque",
584: :routes => "/"
585: }.merge( opts )
586:
587: options[:autz] = b.call()
588:
589: @__auth__ ||= {}
590:
591: if options[:routes].class == Array
592: options[:routes].each do |r|
593: @__auth__[r] = options
594: end
595: else
596: @__auth__[options[:routes]] = options
597: end
598: end
Return the Rack::Request object
# File lib/capcode.rb, line 416
416: def request
417: @request
418: end
Return the Rack::Response object
# File lib/capcode.rb, line 421
421: def response
422: @response
423: end
Start your application.
Options : see Capcode::Configuration.set
Options set here replace the ones set globally
# File lib/capcode.rb, line 689
689: def run( args = {} )
690: Capcode::Configuration.configuration(args)
691:
692: # Parse options
693: opts = OptionParser.new do |opts|
694: opts.banner = "Usage: #{File.basename($0)} [options]"
695: opts.separator ""
696: opts.separator "Specific options:"
697:
698: opts.on( "-C", "--console", "Run in console mode with IRB (default: false)" ) {
699: Capcode::Configuration.set :console, true
700: }
701: opts.on( "-h", "--host HOSTNAME", "Host for web server to bind to (default: #{Capcode::Configuration.get(:host)})" ) { |h|
702: Capcode::Configuration.set :host, h
703: }
704: opts.on( "-p", "--port NUM", "Port for web server (default: #{Capcode::Configuration.get(:port)})" ) { |p|
705: Capcode::Configuration.set :port, p
706: }
707: opts.on( "-d", "--daemonize [true|false]", "Daemonize (default: #{Capcode::Configuration.get(:daemonize)})" ) { |d|
708: Capcode::Configuration.set :daemonize, d
709: }
710: opts.on( "-r", "--root PATH", "Working directory (default: #{Capcode::Configuration.get(:root)})" ) { |w|
711: Capcode::Configuration.set :root, w
712: }
713: opts.on( "-s", "--static PATH", "Static directory -- relative to the root directory (default: #{Capcode::Configuration.get(:static)})" ) { |r|
714: Capcode::Configuration.set :static, r
715: }
716: opts.on( "-S", "--server SERVER", "Server to use (default: #{Capcode::Configuration.get(:server)})" ) { |r|
717: Capcode::Configuration.set :server, r
718: }
719:
720: opts.separator ""
721: opts.separator "Common options:"
722:
723: opts.on("-?", "--help", "Show this message") do
724: puts opts
725: exit
726: end
727: opts.on("-v", "--version", "Show versions") do
728: puts "Capcode version #{Capcode::CAPCOD_VERION} (ruby v#{RUBY_VERSION})"
729: exit
730: end
731: opts.on_tail( "-V", "--verbose", "Run in verbose mode" ) do
732: Capcode::Configuration.set :verbose, true
733: end
734: end
735:
736: begin
737: opts.parse! ARGV
738: rescue OptionParser::ParseError => ex
739: puts "!! #{ex.message}"
740: puts "** use `#{File.basename($0)} --help` for more details..."
741: exit 1
742: end
743:
744: # Run in the Working directory
745: puts "** Go on root directory (#{File.expand_path(Capcode::Configuration.get(:root))})" if Capcode::Configuration.get(:verbose)
746: Dir.chdir( Capcode::Configuration.get(:root) ) do
747:
748: # Check that mongrel exists
749: if Capcode::Configuration.get(:server).nil? || Capcode::Configuration.get(:server) == "mongrel"
750: begin
751: require 'mongrel'
752: Capcode::Configuration.set :server, :mongrel
753: rescue LoadError
754: puts "!! could not load mongrel. Falling back to webrick."
755: Capcode::Configuration.set :server, :webrick
756: end
757: end
758:
759: # From rackup !!!
760: if Capcode::Configuration.get(:daemonize)
761: if /java/.match(RUBY_PLATFORM).nil?
762: if RUBY_VERSION < "1.9"
763: exit if fork
764: Process.setsid
765: exit if fork
766: # Dir.chdir "/"
767: File.umask 0000
768: STDIN.reopen "/dev/null"
769: STDOUT.reopen "/dev/null", "a"
770: STDERR.reopen "/dev/null", "a"
771: else
772: Process.daemon
773: end
774: else
775: puts "!! daemonize option unavailable on #{RUBY_PLATFORM} platform."
776: end
777:
778: File.open(Capcode::Configuration.get(:pid), 'w'){ |f| f.write("#{Process.pid}") }
779: at_exit { File.delete(Capcode::Configuration.get(:pid)) if File.exist?(Capcode::Configuration.get(:pid)) }
780: end
781:
782: app = nil
783: if block_given?
784: app = application(Capcode::Configuration.get) { yield( self ) }
785: else
786: app = application(Capcode::Configuration.get)
787: end
788:
789: if Capcode::Configuration.get(:console)
790: puts "Run console..."
791: IRB.start
792: exit
793: end
794:
795: # Start server
796: case Capcode::Configuration.get(:server).to_s
797: when "mongrel"
798: puts "** Starting Mongrel on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
799: Rack::Handler::Mongrel.run( app, {:Port => Capcode::Configuration.get(:port), :Host => Capcode::Configuration.get(:host)} ) { |server|
800: trap "SIGINT", proc { server.stop }
801: }
802: when "webrick"
803: puts "** Starting WEBrick on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
804: Rack::Handler::WEBrick.run( app, {:Port => Capcode::Configuration.get(:port), :BindAddress => Capcode::Configuration.get(:host)} ) { |server|
805: trap "SIGINT", proc { server.shutdown }
806: }
807: when "thin"
808: puts "** Starting Thin on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
809: Rack::Handler::Thin.run( app, {:Port => Capcode::Configuration.get(:port), :Host => Capcode::Configuration.get(:host)} ) { |server|
810: trap "SIGINT", proc { server.stop }
811: }
812: when "unicorn"
813: require 'unicorn/launcher'
814: puts "** Starting Unicorn on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
815: Unicorn.run( app, {:listeners => ["#{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"]} )
816: when "rainbows"
817: require 'unicorn/launcher'
818: require 'rainbows'
819: puts "** Starting Rainbow on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
820: Rainbows.run( app, {:listeners => ["#{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"]} )
821: end
822: end
823: 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 558
558: def use(middleware, *args, &block)
559: middlewares << [middleware, args, block]
560: end