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