| 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 396
396: def Route *routes_paths
397: create_path = routes_paths[0].nil?
398: Class.new {
399: meta_def(:__urls__) {
400: routes_paths = ['/'+self.to_s.gsub( /^Capcode::/, "" ).underscore] if create_path == true
401: # < Route '/hello/world/([^\/]*)/id(\d*)', '/hello/(.*)', :agent => /Songbird (\d\.\d)[\d\/]*?/
402: # # => [ {
403: # '/hello/world' => {
404: # :regexp => '([^\/]*)/id(\d*)',
405: # :route => '/hello/world/([^\/]*)/id(\d*)',
406: # :nargs => 2
407: # },
408: # '/hello/world' => {
409: # :regexp => '(.*)',
410: # :route => '/hello/(.*)',
411: # :nargs => 1
412: # }
413: # },
414: # 2,
415: # <Capcode::Klass>,
416: # {:agent => /Songbird (\d\.\d)[\d\/]*?/} ]
417: hash_of_routes = {}
418: max_captures_for_routes = 0
419: routes_paths.each do |current_route_path|
420: if current_route_path.class == String
421: m = /\/([^\/]*\(.*)/.match( current_route_path )
422: if m.nil?
423: 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)
424: hash_of_routes[current_route_path] = {
425: :regexp => '',
426: :route => current_route_path,
427: :nargs => 0
428: }
429: else
430: _pre = m.pre_match
431: _pre = "/" if _pre.size == 0
432: raise Capcode::RouteError, "Route `#{_pre}' already defined with regexp `#{hash_of_routes[_pre]}' !", caller if hash_of_routes.keys.include?(_pre)
433: captures_for_routes = Regexp.new(m.captures[0]).number_of_captures
434:
435: hash_of_routes[_pre] = {
436: :regexp => m.captures[0],
437: :route => current_route_path,
438: :nargs => captures_for_routes
439: }
440: max_captures_for_routes = captures_for_routes if max_captures_for_routes < captures_for_routes
441: end
442: else
443: raise Capcode::ParameterError, "Bad route declaration !", caller
444: end
445: end
446: [hash_of_routes, max_captures_for_routes, self]
447: }
448:
449: # Hash containing all the request parameters (GET or POST)
450: def params
451: @request.params
452: end
453:
454: # Hash containing all the environment variables
455: def env
456: @env
457: end
458:
459: # Session hash
460: def session
461: @env['rack.session']
462: end
463:
464: # Return the Rack::Request object
465: def request
466: @request
467: end
468:
469: # Return the Rack::Response object
470: def response
471: @response
472: end
473:
474: def call( e ) #:nodoc:
475: @env = e
476: @response = Rack::Response.new
477: @request = Rack::Request.new(@env)
478:
479: # Check authz
480: authz_options = nil
481: if Capcode.__auth__ and Capcode.__auth__.size > 0
482: authz_options = Capcode.__auth__[@request.path]||nil
483: if authz_options.nil?
484: route = nil
485:
486: Capcode.__auth__.each do |r, o|
487: regexp = "^#{r.gsub(/\/$/, "")}([/]{1}.*)?$"
488: if Regexp.new(regexp).match( @request.path )
489: if route.nil? or r.size > route.size
490: route = r
491: authz_options = o
492: end
493: end
494: end
495: end
496: end
497:
498: r = catch(:halt) {
499: unless authz_options.nil?
500: http_authentication( :type => authz_options[:type], :realm => authz_options[:realm], :opaque => authz_options[:realm] ) {
501: authz_options[:autz]
502: }
503: end
504:
505: max_match_size = self.class.__urls__[1]
506: match_distance = self.class.__urls__[1]
507:
508: result_route = nil
509: result_nargs = nil
510: result_args = []
511:
512: self.class.__urls__[0].each do |route, data|
513: regexp = Regexp.new("^"+data[:route]+"$")
514:
515: matching = regexp.match(@request.path)
516: next if matching.nil?
517:
518: result_args = matching.to_a
519: result_args.shift
520: match_size = matching.size - 1
521:
522: if match_size == max_match_size
523: # OK Terminé
524: result_route = data[:route]
525: result_nargs = data[:nargs]
526:
527: break
528: elsif max_match_size > match_size and match_distance > max_match_size - match_size
529: match_distance = max_match_size - match_size
530:
531: result_route = data[:route]
532: result_nargs = data[:nargs]
533: end
534: end
535:
536: return [404, {'Content-Type' => 'text/plain'}, "Not Found: #{@request.path}"] if result_route.nil?
537:
538: result_args = result_args + Array.new(max_match_size - result_nargs)
539:
540: filter_output = Capcode::Filter.execute( self )
541:
542: if( filter_output.nil? )
543: # case @env["REQUEST_METHOD"]
544: # when "GET"
545: # get( *args )
546: # when "POST"
547: # _method = params.delete( "_method" ) { |_| "post" }
548: # send( _method.downcase.to_sym, *args )
549: # else
550: # _method = @env["REQUEST_METHOD"]
551: # send( _method.downcase.to_sym, *args )
552: # end
553: begin
554: _method = params.delete( "_method" ) { |_| @env["REQUEST_METHOD"] }
555: if self.class.method_defined?( _method.downcase.to_sym )
556: # send( _method.downcase.to_sym, *args )
557: send( _method.downcase.to_sym, *result_args )
558: else
559: # any( *args )
560: any( *result_args )
561: end
562: rescue => e
563: raise e.class, e.to_s
564: end
565: else
566: filter_output
567: end
568: }
569:
570: if r.respond_to?(:to_ary)
571: @response.status = r.shift #r[0]
572: #r[1].each do |k,v|
573: r.shift.each do |k,v|
574: @response[k] = v
575: end
576: @response.write r.shift #r[2]
577: else
578: @response.write r
579: end
580:
581: @response.finish
582: end
583:
584: include Capcode::Helpers
585: include Capcode::Views
586: }
587: end
Return the Rack App.
Options : see Capcode::Configuration.set
Options set here replace the ones set globally
# File lib/capcode.rb, line 656
656: def application( args = {} )
657: Capcode::Configuration.configuration(args)
658: Capcode::Configuration.print_debug if Capcode::Configuration.get(:verbose)
659:
660: Capcode.constants.clone.delete_if {|k|
661: not( Capcode.const_get(k).to_s =~ /Capcode/ ) or [
662: "Filter",
663: "Helpers",
664: "RouteError",
665: "Views",
666: "ParameterError",
667: "HTTPError",
668: "StaticFiles",
669: "Configuration",
670: "MissingLibrary",
671: "Route",
672: "RenderError"
673: ].include?(k)
674: }.each do |k|
675: begin
676: if eval "Capcode::#{k}.public_methods(true).include?( '__urls__' )"
677: hash_of_routes, max_captures_for_routes, klass = eval "Capcode::#{k}.__urls__"
678: hash_of_routes.keys.each do |current_route_path|
679: raise Capcode::RouteError, "Route `#{current_route_path}' already define !", caller if Capcode.routes.keys.include?(current_route_path)
680: Capcode.routes[current_route_path] = klass
681: end
682: end
683: rescue => e
684: raise e.message
685: end
686: end
687:
688: # Set Static directory
689: Capcode.static = (Capcode::Configuration.get(:static)[0].chr == "/")?Capcode::Configuration.get(:static):"/"+Capcode::Configuration.get(:static) unless Capcode::Configuration.get(:static).nil?
690:
691: # Initialize Rack App
692: puts "** Map routes." if Capcode::Configuration.get(:verbose)
693: # app = Rack::URLMap.new(Capcode.routes)
694: app = Capcode::Ext::Rack::URLMap.new(Capcode.routes)
695: puts "** Initialize static directory (#{Capcode.static}) in #{File.expand_path(Capcode::Configuration.get(:root))}" if Capcode::Configuration.get(:verbose)
696: app = Rack::Static.new(
697: app,
698: #:urls => [@@__STATIC_DIR],
699: :urls => [Capcode.static],
700: :root => File.expand_path(Capcode::Configuration.get(:root))
701: ) unless Capcode::Configuration.get(:static).nil?
702: puts "** Initialize session" if Capcode::Configuration.get(:verbose)
703: app = Rack::Session::Cookie.new( app, Capcode::Configuration.get(:session) )
704: app = Capcode::StaticFiles.new(app)
705: app = Capcode::HTTPError.new(app)
706: app = Rack::ContentLength.new(app)
707: app = Rack::Lint.new(app)
708: app = Rack::ShowExceptions.new(app)
709: #app = Rack::Reloader.new(app) ## -- NE RELOAD QUE capcode.rb -- So !!!
710: app = Rack::CommonLogger.new( app, @cclogger = Logger.new(Capcode::Configuration.get(:log)) )
711:
712: middlewares.each do |mw|
713: middleware, args, block = mw
714: puts "** Load middleware #{middleware}" if Capcode::Configuration.get(:verbose)
715: if block
716: app = middleware.new( app, *args, &block )
717: else
718: app = middleware.new( app, *args )
719: end
720: end
721:
722: # Start database
723: if self.methods.include? "db_connect"
724: db_connect( Capcode::Configuration.get(:db_config), Capcode::Configuration.get(:log) )
725: end
726:
727: if block_given?
728: puts "** Execute block" if Capcode::Configuration.get(:verbose)
729: yield( self )
730: end
731:
732: return app
733: 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 455
455: def env
456: @env
457: 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 630
630: def http_authentication( opts = {}, &b )
631: options = {
632: :type => :basic,
633: :realm => "Capcode.app",
634: :opaque => "opaque",
635: :routes => "/"
636: }.merge( opts )
637:
638: options[:autz] = b.call()
639:
640: @__auth__ ||= {}
641:
642: if options[:routes].class == Array
643: options[:routes].each do |r|
644: @__auth__[r] = options
645: end
646: else
647: @__auth__[options[:routes]] = options
648: end
649: end
Return the Rack::Request object
# File lib/capcode.rb, line 465
465: def request
466: @request
467: end
Return the Rack::Response object
# File lib/capcode.rb, line 470
470: def response
471: @response
472: end
Start your application.
Options : see Capcode::Configuration.set
Options set here replace the ones set globally
# File lib/capcode.rb, line 740
740: def run( args = {} )
741: Capcode::Configuration.configuration(args)
742:
743: # Parse options
744: opts = OptionParser.new do |opts|
745: opts.banner = "Usage: #{File.basename($0)} [options]"
746: opts.separator ""
747: opts.separator "Specific options:"
748:
749: opts.on( "-C", "--console", "Run in console mode with IRB (default: false)" ) {
750: Capcode::Configuration.set :console, true
751: }
752: opts.on( "-h", "--host HOSTNAME", "Host for web server to bind to (default: #{Capcode::Configuration.get(:host)})" ) { |h|
753: Capcode::Configuration.set :host, h
754: }
755: opts.on( "-p", "--port NUM", "Port for web server (default: #{Capcode::Configuration.get(:port)})" ) { |p|
756: Capcode::Configuration.set :port, p
757: }
758: opts.on( "-d", "--daemonize [true|false]", "Daemonize (default: #{Capcode::Configuration.get(:daemonize)})" ) { |d|
759: Capcode::Configuration.set :daemonize, d
760: }
761: opts.on( "-r", "--root PATH", "Working directory (default: #{Capcode::Configuration.get(:root)})" ) { |w|
762: Capcode::Configuration.set :root, w
763: }
764: opts.on( "-s", "--static PATH", "Static directory -- relative to the root directory (default: #{Capcode::Configuration.get(:static)})" ) { |r|
765: Capcode::Configuration.set :static, r
766: }
767: opts.on( "-S", "--server SERVER", "Server to use (default: #{Capcode::Configuration.get(:server)})" ) { |r|
768: Capcode::Configuration.set :server, r
769: }
770:
771: opts.separator ""
772: opts.separator "Common options:"
773:
774: opts.on("-?", "--help", "Show this message") do
775: puts opts
776: exit
777: end
778: opts.on("-v", "--version", "Show versions") do
779: puts "Capcode version #{Capcode::CAPCOD_VERION} (ruby v#{RUBY_VERSION})"
780: exit
781: end
782: opts.on_tail( "-V", "--verbose", "Run in verbose mode" ) do
783: Capcode::Configuration.set :verbose, true
784: end
785: end
786:
787: begin
788: opts.parse! ARGV
789: rescue OptionParser::ParseError => ex
790: puts "!! #{ex.message}"
791: puts "** use `#{File.basename($0)} --help` for more details..."
792: exit 1
793: end
794:
795: # Run in the Working directory
796: puts "** Go on root directory (#{File.expand_path(Capcode::Configuration.get(:root))})" if Capcode::Configuration.get(:verbose)
797: Dir.chdir( Capcode::Configuration.get(:root) ) do
798:
799: # Check that mongrel exists
800: if Capcode::Configuration.get(:server).nil? || Capcode::Configuration.get(:server) == "mongrel"
801: begin
802: require 'mongrel'
803: Capcode::Configuration.set :server, :mongrel
804: rescue LoadError
805: puts "!! could not load mongrel. Falling back to webrick."
806: Capcode::Configuration.set :server, :webrick
807: end
808: end
809:
810: # From rackup !!!
811: if Capcode::Configuration.get(:daemonize)
812: if /java/.match(RUBY_PLATFORM).nil?
813: if RUBY_VERSION < "1.9"
814: exit if fork
815: Process.setsid
816: exit if fork
817: # Dir.chdir "/"
818: File.umask 0000
819: STDIN.reopen "/dev/null"
820: STDOUT.reopen "/dev/null", "a"
821: STDERR.reopen "/dev/null", "a"
822: else
823: Process.daemon
824: end
825: else
826: puts "!! daemonize option unavailable on #{RUBY_PLATFORM} platform."
827: end
828:
829: File.open(Capcode::Configuration.get(:pid), 'w'){ |f| f.write("#{Process.pid}") }
830: at_exit { File.delete(Capcode::Configuration.get(:pid)) if File.exist?(Capcode::Configuration.get(:pid)) }
831: end
832:
833: app = nil
834: if block_given?
835: app = application(Capcode::Configuration.get) { yield( self ) }
836: else
837: app = application(Capcode::Configuration.get)
838: end
839:
840: if Capcode::Configuration.get(:console)
841: puts "Run console..."
842: IRB.start
843: exit
844: end
845:
846: # Start server
847: case Capcode::Configuration.get(:server).to_s
848: when "mongrel"
849: puts "** Starting Mongrel on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
850: Rack::Handler::Mongrel.run( app, {:Port => Capcode::Configuration.get(:port), :Host => Capcode::Configuration.get(:host)} ) { |server|
851: trap "SIGINT", proc { server.stop }
852: }
853: when "webrick"
854: puts "** Starting WEBrick on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
855: Rack::Handler::WEBrick.run( app, {:Port => Capcode::Configuration.get(:port), :BindAddress => Capcode::Configuration.get(:host)} ) { |server|
856: trap "SIGINT", proc { server.shutdown }
857: }
858: when "thin"
859: puts "** Starting Thin on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
860: Rack::Handler::Thin.run( app, {:Port => Capcode::Configuration.get(:port), :Host => Capcode::Configuration.get(:host)} ) { |server|
861: trap "SIGINT", proc { server.stop }
862: }
863: when "unicorn"
864: require 'unicorn/launcher'
865: puts "** Starting Unicorn on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
866: Unicorn.run( app, {:listeners => ["#{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"]} )
867: when "rainbows"
868: require 'unicorn/launcher'
869: require 'rainbows'
870: puts "** Starting Rainbow on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
871: Rainbows.run( app, {:listeners => ["#{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"]} )
872: when "control_tower"
873: require 'control_tower'
874: puts "** Starting ControlTower on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
875: ControlTower::Server.new( app, {:host => Capcode::Configuration.get(:host), :port => Capcode::Configuration.get(:port)} ).start
876: end
877: end
878: 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 609
609: def use(middleware, *args, &block)
610: middlewares << [middleware, args, block]
611: end