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

Methods

Route   application   env   http_authentication   map   params   request   response   run   session   set   use  

Included Modules

Rack Capcode::Helpers Capcode::Views

Classes and Modules

Module Capcode::Helpers
Module Capcode::Resource
Module Capcode::Views
Class Capcode::Base
Class Capcode::Configuration
Class Capcode::HTTPError

Attributes

__auth__  [RW] 

Public Class methods

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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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 :

  • :type : Authentication type (:basic or :digest) - default : :basic
  • :realm : realm ;) - default : "Capcode.app"
  • :opaque : Your secret passphrase. You MUST set it if you use Digest Auth - default : "opaque"
  • :routes : Routes - default : "/"

The block must return a Hash of username => password like that :

  {
    "user1" => "pass1",
    "user2" => "pass2",
    # ...
  }

[Source]

     # 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

This method help you to map and URL to a Rack or What you want Helper

  Capcode.map( "/file" ) do
    Rack::File.new( "." )
  end

[Source]

     # File lib/capcode.rb, line 484
484:     def map( route, &b )
485:       #@@__ROUTES[route] = yield
486:       Capcode.routes[route] = yield
487:     end

Hash containing all the request parameters (GET or POST)

[Source]

     # File lib/capcode.rb, line 347
347:         def params
348:           @request.params
349:         end

Return the Rack::Request object

[Source]

     # File lib/capcode.rb, line 362
362:         def request
363:           @request
364:         end

Return the Rack::Response object

[Source]

     # 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

[Source]

     # 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

Session hash

[Source]

     # File lib/capcode.rb, line 357
357:         def session
358:           @env['rack.session']
359:         end

[Source]

   # 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

[Source]

     # File lib/capcode.rb, line 499
499:     def use(middleware, *args, &block)
500:       middlewares << [middleware, args, block]
501:     end

[Validate]