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