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