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