__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 305 305: def Route *routes_paths 306: Class.new { 307: meta_def(:__urls__) { 308: # < Route '/hello/world/([^\/]*)/id(\d*)', '/hello/(.*)', :agent => /Songbird (\d\.\d)[\d\/]*?/ 309: # # => [ {'/hello/world' => '([^\/]*)/id(\d*)', '/hello' => '(.*)'}, 310: # 2, 311: # <Capcode::Klass>, 312: # {:agent => /Songbird (\d\.\d)[\d\/]*?/} ] 313: hash_of_routes = {} 314: max_captures_for_routes = 0 315: routes_paths.each do |current_route_path| 316: if current_route_path.class == String 317: m = /\/([^\/]*\(.*)/.match( current_route_path ) 318: if m.nil? 319: 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) 320: hash_of_routes[current_route_path] = '' 321: else 322: _pre = m.pre_match 323: _pre = "/" if _pre.size == 0 324: raise Capcode::RouteError, "Route `#{_pre}' already defined with regexp `#{hash_of_routes[_pre]}' !", caller if hash_of_routes.keys.include?(_pre) 325: hash_of_routes[_pre] = m.captures[0] 326: 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 327: end 328: else 329: raise Capcode::ParameterError, "Bad route declaration !", caller 330: end 331: end 332: [hash_of_routes, max_captures_for_routes, self] 333: } 334: 335: # Hash containing all the request parameters (GET or POST) 336: def params 337: @request.params 338: end 339: 340: # Hash containing all the environment variables 341: def env 342: @env 343: end 344: 345: # Session hash 346: def session 347: @env['rack.session'] 348: end 349: 350: # Return the Rack::Request object 351: def request 352: @request 353: end 354: 355: # Return the Rack::Response object 356: def response 357: @response 358: end 359: 360: def call( e ) #:nodoc: 361: @env = e 362: @response = Rack::Response.new 363: @request = Rack::Request.new(@env) 364: 365: # __k = self.class.to_s.split( /::/ )[-1].downcase.to_sym 366: # @@__FILTERS.each do |f| 367: # proc = f.delete(:action) 368: # __run = true 369: # if f[:only] 370: # __run = f[:only].include?(__k) 371: # end 372: # if f[:except] 373: # __run = !f[:except].include?(__k) 374: # end 375: # 376: # # proc.call(self) if __run 377: # puts "call #{proc} for #{__k}" 378: # end 379: 380: # Check authz 381: authz_options = nil 382: if Capcode.__auth__ and Capcode.__auth__.size > 0 383: authz_options = Capcode.__auth__[@request.path]||nil 384: if authz_options.nil? 385: route = nil 386: 387: Capcode.__auth__.each do |r, o| 388: regexp = "^#{r.gsub(/\/$/, "")}([/]{1}.*)?$" 389: if Regexp.new(regexp).match( @request.path ) 390: if route.nil? or r.size > route.size 391: route = r 392: authz_options = o 393: end 394: end 395: end 396: end 397: end 398: 399: r = catch(:halt) { 400: unless authz_options.nil? 401: http_authentication( :type => authz_options[:type], :realm => authz_options[:realm], :opaque => authz_options[:realm] ) { 402: authz_options[:autz] 403: } 404: end 405: 406: finalPath = nil 407: finalArgs = nil 408: finalNArgs = nil 409: 410: aPath = @request.path.gsub( /^\//, "" ).split( "/" ) 411: self.class.__urls__[0].each do |p, r| 412: xPath = p.gsub( /^\//, "" ).split( "/" ) 413: if (xPath - aPath).size == 0 414: diffArgs = aPath - xPath 415: diffNArgs = diffArgs.size 416: if finalNArgs.nil? or finalNArgs > diffNArgs 417: finalPath = p 418: finalNArgs = diffNArgs 419: finalArgs = diffArgs 420: end 421: end 422: 423: end 424: 425: nargs = self.class.__urls__[1] 426: regexp = Regexp.new( self.class.__urls__[0][finalPath] ) 427: args = regexp.match( Rack::Utils.unescape(@request.path).gsub( Regexp.new( "^#{finalPath}" ), "" ).gsub( /^\//, "" ) ) 428: if args.nil? 429: raise Capcode::ParameterError, "Path info `#{@request.path_info}' does not match route regexp `#{regexp.source}'" 430: else 431: args = args.captures.map { |x| (x.size == 0)?nil:x } 432: end 433: 434: while args.size < nargs 435: args << nil 436: end 437: 438: case @env["REQUEST_METHOD"] 439: when "GET" 440: get( *args ) 441: when "POST" 442: _method = params.delete( "_method" ) { |_| "post" } 443: send( _method.downcase.to_sym, *args ) 444: else 445: _method = @env["REQUEST_METHOD"] 446: send( _method.downcase.to_sym, *args ) 447: end 448: } 449: if r.respond_to?(:to_ary) 450: @response.status = r.shift #r[0] 451: #r[1].each do |k,v| 452: r.shift.each do |k,v| 453: @response[k] = v 454: end 455: @response.body = r.shift #r[2] 456: else 457: @response.write r 458: end 459: 460: @response.finish 461: end 462: 463: include Capcode::Helpers 464: include Capcode::Views 465: } 466: end
Return the Rack App.
Options : see Capcode.set
Options set here replace the ones set globally
# File lib/capcode.rb, line 552 552: def application( args = {} ) 553: conf = configuration(args) 554: 555: Capcode.constants.each do |k| 556: begin 557: if eval "Capcode::#{k}.public_methods(true).include?( '__urls__' )" 558: hash_of_routes, max_captures_for_routes, klass = eval "Capcode::#{k}.__urls__" 559: hash_of_routes.keys.each do |current_route_path| 560: #raise Capcode::RouteError, "Route `#{current_route_path}' already define !", caller if @@__ROUTES.keys.include?(current_route_path) 561: raise Capcode::RouteError, "Route `#{current_route_path}' already define !", caller if Capcode.routes.keys.include?(current_route_path) 562: #@@__ROUTES[current_route_path] = klass.new 563: Capcode.routes[current_route_path] = klass.new 564: end 565: end 566: rescue => e 567: raise e.message 568: end 569: end 570: 571: # Set Static directory 572: #@@__STATIC_DIR = (conf[:static][0].chr == "/")?conf[:static]:"/"+conf[:static] unless conf[:static].nil? 573: Capcode.static = (conf[:static][0].chr == "/")?conf[:static]:"/"+conf[:static] unless conf[:static].nil? 574: 575: # Initialize Rack App 576: puts "** Map routes." if conf[:verbose] 577: #app = Rack::URLMap.new(@@__ROUTES) 578: app = Rack::URLMap.new(Capcode.routes) 579: puts "** Initialize static directory (#{conf[:static]})" if conf[:verbose] 580: app = Rack::Static.new( 581: app, 582: #:urls => [@@__STATIC_DIR], 583: :urls => [Capcode.static], 584: :root => File.expand_path(conf[:root]) 585: ) unless conf[:static].nil? 586: puts "** Initialize session" if conf[:verbose] 587: app = Rack::Session::Cookie.new( app, conf[:session] ) 588: app = Capcode::HTTPError.new(app) 589: app = Rack::ContentLength.new(app) 590: app = Rack::Lint.new(app) 591: app = Rack::ShowExceptions.new(app) 592: #app = Rack::Reloader.new(app) ## -- NE RELOAD QUE capcode.rb -- So !!! 593: # app = Rack::CommonLogger.new( app, Logger.new(conf[:log]) ) 594: 595: middlewares.each do |mw| 596: middleware, args, block = mw 597: puts "** Load middleware #{middleware}" if conf[:verbose] 598: if block 599: app = middleware.new( app, *args, &block ) 600: else 601: app = middleware.new( app, *args ) 602: end 603: end 604: 605: # Start database 606: if self.methods.include? "db_connect" 607: db_connect( conf[:db_config], conf[:log] ) 608: end 609: 610: if block_given? 611: yield( self ) 612: end 613: 614: return app 615: end
Hash containing all the environment variables
# File lib/capcode.rb, line 341 341: def env 342: @env 343: 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 509 509: def http_authentication( opts = {}, &b ) 510: options = { 511: :type => :basic, 512: :realm => "Capcode.app", 513: :opaque => "opaque", 514: :routes => "/" 515: }.merge( opts ) 516: 517: options[:autz] = b.call() 518: 519: @__auth__ ||= {} 520: 521: if options[:routes].class == Array 522: options[:routes].each do |r| 523: @__auth__[r] = options 524: end 525: else 526: @__auth__[options[:routes]] = options 527: end 528: end
Return the Rack::Request object
# File lib/capcode.rb, line 351 351: def request 352: @request 353: end
Return the Rack::Response object
# File lib/capcode.rb, line 356 356: def response 357: @response 358: end
Start your application.
Options : see Capcode.set
Options set here replace the ones set globally
# File lib/capcode.rb, line 622 622: def run( args = {} ) 623: conf = configuration(args) 624: 625: # Parse options 626: opts = OptionParser.new do |opts| 627: opts.banner = "Usage: #{File.basename($0)} [options]" 628: opts.separator "" 629: opts.separator "Specific options:" 630: 631: opts.on( "-C", "--console", "Run in console mode with IRB (default: false)" ) { 632: conf[:console] = true 633: } 634: opts.on( "-h", "--host HOSTNAME", "Host for web server to bind to (default: #{conf[:host]})" ) { |h| 635: conf[:host] = h 636: } 637: opts.on( "-p", "--port NUM", "Port for web server (default: #{conf[:port]})" ) { |p| 638: conf[:port] = p 639: } 640: opts.on( "-d", "--daemonize [true|false]", "Daemonize (default: #{conf[:daemonize]})" ) { |d| 641: conf[:daemonize] = d 642: } 643: opts.on( "-r", "--root PATH", "Working directory (default: #{conf[:root]})" ) { |w| 644: conf[:root] = w 645: } 646: opts.on( "-s", "--static PATH", "Static directory -- relative to the root directory (default: #{conf[:static]})" ) { |r| 647: conf[:static] = r 648: } 649: 650: opts.separator "" 651: opts.separator "Common options:" 652: 653: opts.on("-?", "--help", "Show this message") do 654: puts opts 655: exit 656: end 657: opts.on("-v", "--version", "Show versions") do 658: puts "Capcode version #{Capcode::CAPCOD_VERION} (ruby v#{RUBY_VERSION})" 659: exit 660: end 661: opts.on_tail( "-V", "--verbose", "Run in verbose mode" ) do 662: conf[:verbose] = true 663: end 664: end 665: 666: begin 667: opts.parse! ARGV 668: rescue OptionParser::ParseError => ex 669: puts "!! #{ex.message}" 670: puts "** use `#{File.basename($0)} --help` for more details..." 671: exit 1 672: end 673: 674: # Run in the Working directory 675: puts "** Go on root directory (#{File.expand_path(conf[:root])})" if conf[:verbose] 676: Dir.chdir( conf[:root] ) do 677: 678: # Check that mongrel exists 679: if conf[:server].nil? || conf[:server] == "mongrel" 680: begin 681: require 'mongrel' 682: conf[:server] = "mongrel" 683: rescue LoadError 684: puts "!! could not load mongrel. Falling back to webrick." 685: conf[:server] = "webrick" 686: end 687: end 688: 689: # From rackup !!! 690: if conf[:daemonize] 691: if /java/.match(RUBY_PLATFORM).nil? 692: if RUBY_VERSION < "1.9" 693: exit if fork 694: Process.setsid 695: exit if fork 696: # Dir.chdir "/" 697: File.umask 0000 698: STDIN.reopen "/dev/null" 699: STDOUT.reopen "/dev/null", "a" 700: STDERR.reopen "/dev/null", "a" 701: else 702: Process.daemon 703: end 704: else 705: puts "!! daemonize option unavailable on #{RUBY_PLATFORM} platform." 706: end 707: 708: File.open(conf[:pid], 'w'){ |f| f.write("#{Process.pid}") } 709: at_exit { File.delete(conf[:pid]) if File.exist?(conf[:pid]) } 710: end 711: 712: app = nil 713: if block_given? 714: app = application(conf) { yield( self ) } 715: else 716: app = application(conf) 717: end 718: app = Rack::CommonLogger.new( app, Logger.new(conf[:log]) ) 719: 720: if conf[:console] 721: puts "Run console..." 722: IRB.start 723: exit 724: end 725: 726: # Start server 727: case conf[:server].to_s 728: when "mongrel" 729: puts "** Starting Mongrel on #{conf[:host]}:#{conf[:port]}" 730: Rack::Handler::Mongrel.run( app, {:Port => conf[:port], :Host => conf[:host]} ) { |server| 731: trap "SIGINT", proc { server.stop } 732: } 733: when "webrick" 734: puts "** Starting WEBrick on #{conf[:host]}:#{conf[:port]}" 735: Rack::Handler::WEBrick.run( app, {:Port => conf[:port], :BindAddress => conf[:host]} ) { |server| 736: trap "SIGINT", proc { server.shutdown } 737: } 738: when "thin" 739: puts "** Starting Thin on #{conf[:host]}:#{conf[:port]}" 740: Rack::Handler::Thin.run( app, {:Port => conf[:port], :Host => conf[:host]} ) { |server| 741: trap "SIGINT", proc { server.stop } 742: } 743: end 744: end 745: end
Set global configuration options
Options :
It can exist specifics options depending on a renderer, a helper, …
Example :
module Capcode set :erb, "/path/to/erb/files" ... end
# File lib/capcode/configuration.rb, line 27 27: def set( key, value ) 28: config[key] = value 29: 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 488 488: def use(middleware, *args, &block) 489: middlewares << [middleware, args, block] 490: end