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