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