Capcode 0.9.9 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/README.rdoc +3 -0
  2. data/examples/rest.log +15 -0
  3. data/examples/static.rb +12 -0
  4. data/examples/static/static-index.html +1 -0
  5. data/lib/capcode.rb +14 -344
  6. data/lib/capcode/filters.rb +1 -0
  7. data/lib/capcode/helpers.rb +246 -0
  8. data/lib/capcode/http_error.rb +49 -0
  9. data/lib/capcode/static_files.rb +68 -0
  10. data/lib/capcode/version.rb +1 -1
  11. metadata +46 -61
  12. data/doc/rdoc/classes/Capcode.html +0 -1076
  13. data/doc/rdoc/classes/Capcode/Base.html +0 -136
  14. data/doc/rdoc/classes/Capcode/Configuration.html +0 -290
  15. data/doc/rdoc/classes/Capcode/HTTPError.html +0 -148
  16. data/doc/rdoc/classes/Capcode/Helpers.html +0 -674
  17. data/doc/rdoc/classes/Capcode/Helpers/Authorization.html +0 -219
  18. data/doc/rdoc/classes/Capcode/Resource.html +0 -111
  19. data/doc/rdoc/classes/Capcode/StaticFiles.html +0 -199
  20. data/doc/rdoc/classes/Capcode/Views.html +0 -112
  21. data/doc/rdoc/created.rid +0 -1
  22. data/doc/rdoc/files/AUTHORS.html +0 -107
  23. data/doc/rdoc/files/COPYING.html +0 -531
  24. data/doc/rdoc/files/README_rdoc.html +0 -887
  25. data/doc/rdoc/files/lib/capcode/base/db_rb.html +0 -101
  26. data/doc/rdoc/files/lib/capcode/configuration_rb.html +0 -101
  27. data/doc/rdoc/files/lib/capcode/filters_rb.html +0 -101
  28. data/doc/rdoc/files/lib/capcode/helpers/auth_rb.html +0 -101
  29. data/doc/rdoc/files/lib/capcode/render/text_rb.html +0 -101
  30. data/doc/rdoc/files/lib/capcode_rb.html +0 -144
  31. data/doc/rdoc/fr_class_index.html +0 -35
  32. data/doc/rdoc/fr_file_index.html +0 -35
  33. data/doc/rdoc/fr_method_index.html +0 -56
  34. data/doc/rdoc/index.html +0 -24
  35. data/doc/rdoc/rdoc-style.css +0 -208
  36. data/lib/capcode.rbSAVE +0 -881
@@ -1,881 +0,0 @@
1
- # Please read the README.rdoc file !
2
-
3
- require 'rubygems'
4
- require 'rack'
5
- require 'rack/mime'
6
- require 'logger'
7
- Logger.class_eval { alias :write :<< } unless Logger.instance_methods.include? "write"
8
- require 'optparse'
9
- require 'irb'
10
- require 'capcode/version'
11
- require 'capcode/core_ext'
12
- require 'capcode/helpers/auth'
13
- require 'capcode/render/text'
14
- require 'capcode/configuration'
15
- require 'capcode/filters'
16
- require 'capcode/ext/rack/urlmap'
17
-
18
- module Capcode
19
- class ParameterError < ArgumentError #:nodoc: all
20
- end
21
-
22
- class RouteError < ArgumentError #:nodoc: all
23
- end
24
-
25
- class RenderError < ArgumentError #:nodoc: all
26
- end
27
-
28
- class MissingLibrary < Exception #:nodoc: all
29
- end
30
-
31
- # Views is an empty module in which you can store your markaby or xml views.
32
- module Views; end
33
-
34
- # Helpers contains methods available in your controllers
35
- module Helpers
36
- def self.args
37
- @args ||= nil
38
- end
39
- def self.args=(x)
40
- @args = x
41
- end
42
-
43
- # Render a view
44
- #
45
- # render's parameter can be a Hash or a string. Passing a string is equivalent to do
46
- # render( :text => string )
47
- #
48
- # If you want to use a specific renderer, use one of this options :
49
- #
50
- # * :markaby => :my_func : :my_func must be defined in Capcode::Views
51
- # * :erb => :my_erb_file : this suppose that's my_erb_file.rhtml exist in erb_path
52
- # * :haml => :my_haml_file : this suppose that's my_haml_file.haml exist in haml_path
53
- # * :sass => :my_sass_file : this suppose that's my_sass_file.sass exist in sass_path
54
- # * :text => "my text"
55
- # * :json => MyObject : this suppose that's MyObject respond to .to_json
56
- # * :static => "my_file.xxx" : this suppose that's my_file.xxx exist in the static directory
57
- # * :xml => :my_func : :my_func must be defined in Capcode::Views
58
- # * :webdav => /path/to/root
59
- #
60
- # Or you can use a "HTTP code" renderer :
61
- #
62
- # render 200 => "Ok", :server => "Capcode #{Capcode::CAPCOD_VERION}", ...
63
- #
64
- # If you want to use a specific layout, you can specify it with option
65
- # :layout
66
- #
67
- # If you want to change the Content-Type, you can specify it with option
68
- # :content_type
69
- # Note that this will not work with the JSON renderer
70
- #
71
- # If you use the WebDav renderer, you can use the option
72
- # :resource_class (see http://github.com/georgi/rack_dav for more informations)
73
- def render( hash )
74
- if hash.class == Hash
75
- render_type = nil
76
- possible_code_renderer = nil
77
-
78
- hash.keys.each do |key|
79
- begin
80
- gem "capcode-render-#{key.to_s}"
81
- require "capcode/render/#{key.to_s}"
82
- rescue Gem::LoadError
83
- nil
84
- rescue LoadError
85
- raise Capcode::RenderError, "Hum... The #{key} renderer is malformated! Please try to install a new version or use an other renderer!", caller
86
- end
87
-
88
- if self.respond_to?("render_#{key.to_s}")
89
- unless render_type.nil?
90
- raise Capcode::RenderError, "Can't use multiple renderer (`#{render_type}' and `#{key}') !", caller
91
- end
92
- render_type = key
93
- end
94
-
95
- if key.class == Fixnum
96
- possible_code_renderer = key
97
- end
98
- end
99
-
100
- if render_type.nil? and possible_code_renderer.nil?
101
- raise Capcode::RenderError, "Renderer type not specified!", caller
102
- end
103
-
104
- unless self.respond_to?("render_#{render_type.to_s}")
105
- if possible_code_renderer.nil?
106
- raise Capcode::RenderError, "#{render_type} renderer not present ! please require 'capcode/render/#{render_type}'", caller
107
- else
108
- code = possible_code_renderer
109
- body = hash.delete(possible_code_renderer)
110
- header = {}
111
- hash.each do |k, v|
112
- k = k.to_s.split(/_/).map{|e| e.capitalize}.join("-")
113
- header[k] = v
114
- end
115
-
116
- [code, header, body]
117
- end
118
- else
119
- render_name = hash.delete(render_type)
120
- content_type = hash.delete(:content_type)
121
- unless content_type.nil?
122
- @response['Content-Type'] = content_type
123
- end
124
-
125
- begin
126
- self.send( "render_#{render_type.to_s}", render_name, hash )
127
- rescue => e
128
- raise Capcode::RenderError, "Error rendering `#{render_type.to_s}' : #{e.message}", caller
129
- end
130
- end
131
- else
132
- render( :text => hash )
133
- end
134
- end
135
-
136
- # Help you to return a JSON response
137
- #
138
- # module Capcode
139
- # class JsonResponse < Route '/json/([^\/]*)/(.*)'
140
- # def get( arg1, arg2 )
141
- # json( { :1 => arg1, :2 => arg2 })
142
- # end
143
- # end
144
- # end
145
- #
146
- # <b>DEPRECATED</b>, please use <tt>render( :json => o )</tt>
147
- def json( d ) ## DELETE THIS IN 1.0.0
148
- warn( "json is deprecated and will be removed in version 1.0, please use `render( :json => ... )'" )
149
- render :json => d
150
- end
151
-
152
- # Send a redirect response
153
- #
154
- # module Capcode
155
- # class Hello < Route '/hello/(.*)'
156
- # def get( you )
157
- # if you.nil?
158
- # redirect( WhoAreYou )
159
- # else
160
- # ...
161
- # end
162
- # end
163
- # end
164
- # end
165
- #
166
- # The first parameter can be a controller class name
167
- #
168
- # redirect( MyController )
169
- #
170
- # it can be a string path
171
- #
172
- # redirect( "/path/to/my/resource" )
173
- #
174
- # it can be an http status code (by default <tt>redirect</tt> use the http status code 302)
175
- #
176
- # redirect( 304, MyController )
177
- #
178
- # For more informations about HTTP status, see http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection
179
- def redirect( klass, *a )
180
- httpCode = 302
181
-
182
- if( klass.class == Fixnum )
183
- httpCode = klass
184
- klass = a.shift
185
- end
186
-
187
- [httpCode, {'Location' => URL(klass, *a)}, '']
188
- end
189
-
190
- # Builds an URL route to a controller or a path
191
- #
192
- # if you declare the controller Hello :
193
- #
194
- # module Capcode
195
- # class Hello < Route '/hello/(.*)'
196
- # ...
197
- # end
198
- # end
199
- #
200
- # then
201
- #
202
- # URL( Capcode::Hello, "you" ) # => /hello/you
203
- def URL( klass, *a )
204
- path = nil
205
- result = {}
206
-
207
- a = a.delete_if{ |x| x.nil? }
208
-
209
- if klass.class == Class
210
- klass.__urls__[0].each do |cpath, regexp|
211
- data = a.clone
212
-
213
- n = Regexp.new( regexp ).number_of_captures
214
- equart = (a.size - n).abs
215
-
216
- rtable = regexp.dup.gsub( /\\\(/, "" ).gsub( /\\\)/, "" ).split( /\([^\)]*\)/ )
217
- rtable.each do |r|
218
- if r == ""
219
- cpath = cpath + "/#{data.shift}"
220
- else
221
- cpath = cpath + "/#{r}"
222
- end
223
- end
224
-
225
- cpath = (cpath + "/" + data.join( "/" )) if data.size > 0
226
- cpath = cpath.gsub( /(\/){2,}/, "/" )
227
- result[equart] = cpath
228
- end
229
-
230
- path = result[result.keys.min]
231
- else
232
- path = klass
233
- end
234
-
235
- (ENV['RACK_BASE_URI']||'')+path
236
- end
237
-
238
- # Calling content_for stores a block of markup in an identifier.
239
- #
240
- # module Capcode
241
- # class ContentFor < Route '/'
242
- # def get
243
- # render( :markaby => :page, :layout => :layout )
244
- # end
245
- # end
246
- # end
247
- #
248
- # module Capcode::Views
249
- # def layout
250
- # html do
251
- # head do
252
- # yield :header
253
- # end
254
- # body do
255
- # yield :content
256
- # end
257
- # end
258
- # end
259
- #
260
- # def page
261
- # content_for :header do
262
- # title "This is the title!"
263
- # end
264
- #
265
- # content_for :content do
266
- # p "this is the content!"
267
- # end
268
- # end
269
- # end
270
- def content_for( x )
271
- if Capcode::Helpers.args.map{|_| _.to_s }.include?(x.to_s)
272
- yield
273
- end
274
- end
275
-
276
- # Return information about the static directory
277
- #
278
- # * <tt>static[:uri]</tt> give the static URI
279
- # * <tt>static[:path]</tt> give the path to the static directory on the server
280
- def static
281
- {
282
- :uri => Capcode.static,
283
- :path => File.expand_path( File.join(Capcode::Configuration.get(:root), Capcode::Configuration.get(:static) ) )
284
- }
285
- end
286
-
287
- # Use the Rack logger
288
- #
289
- # log.write( "This is a log !" )
290
- def log
291
- Capcode.logger || env['rack.errors']
292
- end
293
-
294
- include Authorization
295
- end
296
-
297
- include Rack
298
-
299
- # HTTPError help you to create your own 404, 500 and/or 501 response
300
- #
301
- # To create a custom 404 reponse, create a fonction HTTPError.r404 in
302
- # your application :
303
- #
304
- # module Capcode
305
- # class HTTPError
306
- # def r404(f)
307
- # "#{f} not found :("
308
- # end
309
- # end
310
- # end
311
- #
312
- # the rXXX method can also receive a second optional parameter corresponding
313
- # of the header's Hash :
314
- #
315
- # module Capcode
316
- # class HTTPError
317
- # def r404(f, h)
318
- # h['Content-Type'] = 'text/plain'
319
- # "You are here ---> X (#{f} point)"
320
- # end
321
- # end
322
- # end
323
- #
324
- # Do the same (r500, r501, r403) to customize 500, 501, 403 errors
325
- class HTTPError
326
- def initialize(app) #:nodoc:
327
- @app = app
328
- end
329
-
330
- def call(env) #:nodoc:
331
- status, headers, body = @app.call(env)
332
- if self.methods.include? "r#{status}"
333
- headers.delete('Content-Type') if headers.keys.include?('Content-Type')
334
- body = begin
335
- self.send( "r#{status}", env['REQUEST_PATH'], headers )
336
- rescue
337
- self.send( "r#{status}", env['REQUEST_PATH'] )
338
- end
339
- headers['Content-Length'] = body.length.to_s
340
- headers['Content-Type'] = "text/html" unless headers.keys.include?('Content-Type')
341
- end
342
-
343
- [status, headers, body]
344
- end
345
- end
346
-
347
- class StaticFiles
348
- def initialize(app)
349
- @app = app
350
- end
351
-
352
- def call(env)
353
- static = File.expand_path( File.join(Capcode::Configuration.get(:root), Capcode::Configuration.get(:static) ) )
354
- file = File.join(static, env['REQUEST_PATH'].split("/") )
355
- file = File.join(file, "index.html" ) if File.directory?(file)
356
- if File.exist?(file)
357
- body = [::File.read(file)]
358
- header = {
359
- "Last-Modified" => ::File.mtime(file).httpdate,
360
- "Content-Type" => ::Rack::Mime.mime_type(::File.extname(file), 'text/plain'),
361
- "Content-Length" => body.first.size.to_s
362
- }
363
- return [200, header, body]
364
- else
365
- return @app.call(env)
366
- end
367
-
368
- return @app.call(env)
369
- end
370
- end
371
-
372
- class << self
373
- attr :__auth__, true #:nodoc:
374
-
375
- # Add routes to a controller class
376
- #
377
- # module Capcode
378
- # class Hello < Route '/hello/(.*)', '/hello/([^#]*)#(.*)'
379
- # def get( arg1, arg2 )
380
- # ...
381
- # end
382
- # end
383
- # end
384
- #
385
- # In the <tt>get</tt> method, you will receive the maximum of parameters declared
386
- # by the routes. In this example, you will receive 2 parameters. So if you
387
- # go to <tt>/hello/world#friend</tt> then <tt>arg1</tt> will be set to <tt>world</tt> and <tt>arg2</tt>
388
- # will be set to <tt>friend</tt>. Now if you go to <tt>/hello/you</tt>, then <tt>arg1</tt> will
389
- # be set to <tt>you</tt> and <tt>arg2</tt> will be set to <tt>nil</tt>
390
- #
391
- # If the regexp in the route does not match, all arguments will be <tt>nil</tt>
392
- def Route *routes_paths
393
- create_path = routes_paths[0].nil?
394
- Class.new {
395
- meta_def(:__urls__) {
396
- routes_paths = ['/'+self.to_s.gsub( /^Capcode::/, "" ).underscore] if create_path == true
397
- # < Route '/hello/world/([^\/]*)/id(\d*)', '/hello/(.*)', :agent => /Songbird (\d\.\d)[\d\/]*?/
398
- # # => [ {'/hello/world' => '([^\/]*)/id(\d*)', '/hello' => '(.*)'},
399
- # 2,
400
- # <Capcode::Klass>,
401
- # {:agent => /Songbird (\d\.\d)[\d\/]*?/} ]
402
- hash_of_routes = {}
403
- max_captures_for_routes = 0
404
- routes_paths.each do |current_route_path|
405
- if current_route_path.class == String
406
- m = /\/([^\/]*\(.*)/.match( current_route_path )
407
- if m.nil?
408
- 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)
409
- hash_of_routes[current_route_path] = ''
410
- else
411
- _pre = m.pre_match
412
- _pre = "/" if _pre.size == 0
413
- raise Capcode::RouteError, "Route `#{_pre}' already defined with regexp `#{hash_of_routes[_pre]}' !", caller if hash_of_routes.keys.include?(_pre)
414
- hash_of_routes[_pre] = m.captures[0]
415
- 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
416
- end
417
- else
418
- raise Capcode::ParameterError, "Bad route declaration !", caller
419
- end
420
- end
421
- [hash_of_routes, max_captures_for_routes, self]
422
- }
423
-
424
- # Hash containing all the request parameters (GET or POST)
425
- def params
426
- @request.params
427
- end
428
-
429
- # Hash containing all the environment variables
430
- def env
431
- @env
432
- end
433
-
434
- # Session hash
435
- def session
436
- @env['rack.session']
437
- end
438
-
439
- # Return the Rack::Request object
440
- def request
441
- @request
442
- end
443
-
444
- # Return the Rack::Response object
445
- def response
446
- @response
447
- end
448
-
449
- def call( e ) #:nodoc:
450
- @env = e
451
- @response = Rack::Response.new
452
- @request = Rack::Request.new(@env)
453
-
454
- # Check authz
455
- authz_options = nil
456
- if Capcode.__auth__ and Capcode.__auth__.size > 0
457
- authz_options = Capcode.__auth__[@request.path]||nil
458
- if authz_options.nil?
459
- route = nil
460
-
461
- Capcode.__auth__.each do |r, o|
462
- regexp = "^#{r.gsub(/\/$/, "")}([/]{1}.*)?$"
463
- if Regexp.new(regexp).match( @request.path )
464
- if route.nil? or r.size > route.size
465
- route = r
466
- authz_options = o
467
- end
468
- end
469
- end
470
- end
471
- end
472
-
473
- r = catch(:halt) {
474
- unless authz_options.nil?
475
- http_authentication( :type => authz_options[:type], :realm => authz_options[:realm], :opaque => authz_options[:realm] ) {
476
- authz_options[:autz]
477
- }
478
- end
479
-
480
- finalPath = nil
481
- finalArgs = nil
482
- finalNArgs = nil
483
-
484
- aPath = @request.path.gsub( /^\//, "" ).split( "/" )
485
- print "aPath = "; p aPath
486
- self.class.__urls__[0].each do |p, r|
487
- puts "p = #{p}, r = #{r}"
488
- xPath = p.gsub( /^\//, "" ).split( "/" )
489
- puts "xPath = "; p xPath
490
- if (xPath - aPath).size == 0
491
- diffArgs = aPath - xPath
492
- diffNArgs = diffArgs.size # -1 ##################################### Why ?
493
- if finalNArgs.nil? or finalNArgs > diffNArgs
494
- finalPath = p
495
- finalNArgs = diffNArgs
496
- finalArgs = diffArgs
497
- end
498
- end
499
- end
500
-
501
- puts "finalPath = #{finalPath}"
502
- puts "finalNArgs = #{finalNArgs}"
503
- require 'pp'
504
- pp self.class.__urls__
505
- puts "self.class.__urls__[1] = #{self.class.__urls__[1]}"
506
- puts "finalArgs = "; pp finalArgs
507
-
508
- if finalNArgs > self.class.__urls__[1]
509
- return [404, {'Content-Type' => 'text/plain'}, "Not Found: #{@request.path}"]
510
- end
511
-
512
- nargs = self.class.__urls__[1]
513
- regexp = Regexp.new( self.class.__urls__[0][finalPath] )
514
- args = regexp.match( Rack::Utils.unescape(@request.path).gsub( Regexp.new( "^#{finalPath}" ), "" ).gsub( /^\//, "" ) )
515
- if args.nil?
516
- raise Capcode::ParameterError, "Path info `#{@request.path_info}' does not match route regexp `#{regexp.source}'"
517
- else
518
- args = args.captures.map { |x| (x.size == 0)?nil:x }
519
- end
520
-
521
- while args.size < nargs
522
- args << nil
523
- end
524
-
525
- filter_output = Capcode::Filter.execute( self )
526
-
527
- if( filter_output.nil? )
528
- # case @env["REQUEST_METHOD"]
529
- # when "GET"
530
- # get( *args )
531
- # when "POST"
532
- # _method = params.delete( "_method" ) { |_| "post" }
533
- # send( _method.downcase.to_sym, *args )
534
- # else
535
- # _method = @env["REQUEST_METHOD"]
536
- # send( _method.downcase.to_sym, *args )
537
- # end
538
- begin
539
- _method = params.delete( "_method" ) { |_| @env["REQUEST_METHOD"] }
540
- if self.class.method_defined?( _method.downcase.to_sym )
541
- send( _method.downcase.to_sym, *args )
542
- else
543
- any( *args )
544
- end
545
- rescue => e
546
- raise e.class, e.to_s
547
- end
548
- else
549
- filter_output
550
- end
551
- }
552
-
553
- if r.respond_to?(:to_ary)
554
- @response.status = r.shift #r[0]
555
- #r[1].each do |k,v|
556
- r.shift.each do |k,v|
557
- @response[k] = v
558
- end
559
- @response.write r.shift #r[2]
560
- else
561
- @response.write r
562
- end
563
-
564
- @response.finish
565
- end
566
-
567
- include Capcode::Helpers
568
- include Capcode::Views
569
- }
570
- end
571
- Capcode::Route = Capcode::Route(nil)
572
-
573
- # This method help you to map and URL to a Rack or What you want Helper
574
- #
575
- # Capcode.map( "/file" ) do
576
- # Rack::File.new( "." )
577
- # end
578
- def map( route, &b )
579
- Capcode.routes[route] = yield
580
- end
581
-
582
- # This method allow you to use a Rack middleware
583
- #
584
- # Example :
585
- #
586
- # module Capcode
587
- # ...
588
- # use Rack::Codehighlighter, :coderay, :element => "pre",
589
- # :pattern => /\A:::(\w+)\s*\n/, :logging => false
590
- # ...
591
- # end
592
- def use(middleware, *args, &block)
593
- middlewares << [middleware, args, block]
594
- end
595
- def middlewares #:nodoc:
596
- @middlewares ||= []
597
- end
598
-
599
- # Allow you to add and HTTP Authentication (Basic or Digest) to controllers for or specific route
600
- #
601
- # Options :
602
- # * <tt>:type</tt> : Authentication type (<tt>:basic</tt> or <tt>:digest</tt>) - default : <tt>:basic</tt>
603
- # * <tt>:realm</tt> : realm ;) - default : "Capcode.app"
604
- # * <tt>:opaque</tt> : Your secret passphrase. You MUST set it if you use Digest Auth - default : "opaque"
605
- # * <tt>:routes</tt> : Routes - default : "/"
606
- #
607
- # The block must return a Hash of username => password like that :
608
- # {
609
- # "user1" => "pass1",
610
- # "user2" => "pass2",
611
- # # ...
612
- # }
613
- def http_authentication( opts = {}, &b )
614
- options = {
615
- :type => :basic,
616
- :realm => "Capcode.app",
617
- :opaque => "opaque",
618
- :routes => "/"
619
- }.merge( opts )
620
-
621
- options[:autz] = b.call()
622
-
623
- @__auth__ ||= {}
624
-
625
- if options[:routes].class == Array
626
- options[:routes].each do |r|
627
- @__auth__[r] = options
628
- end
629
- else
630
- @__auth__[options[:routes]] = options
631
- end
632
- end
633
-
634
- # Return the Rack App.
635
- #
636
- # Options : see Capcode::Configuration.set
637
- #
638
- # Options set here replace the ones set globally
639
- def application( args = {} )
640
- Capcode::Configuration.configuration(args)
641
- Capcode::Configuration.print_debug if Capcode::Configuration.get(:verbose)
642
-
643
- Capcode.constants.clone.delete_if {|k|
644
- not( Capcode.const_get(k).to_s =~ /Capcode/ ) or [
645
- "Filter",
646
- "Helpers",
647
- "RouteError",
648
- "Views",
649
- "ParameterError",
650
- "HTTPError",
651
- "StaticFiles",
652
- "Configuration",
653
- "MissingLibrary",
654
- "Route",
655
- "RenderError"
656
- ].include?(k)
657
- }.each do |k|
658
- begin
659
- if eval "Capcode::#{k}.public_methods(true).include?( '__urls__' )"
660
- hash_of_routes, max_captures_for_routes, klass = eval "Capcode::#{k}.__urls__"
661
- hash_of_routes.keys.each do |current_route_path|
662
- #raise Capcode::RouteError, "Route `#{current_route_path}' already define !", caller if @@__ROUTES.keys.include?(current_route_path)
663
- raise Capcode::RouteError, "Route `#{current_route_path}' already define !", caller if Capcode.routes.keys.include?(current_route_path)
664
- # Capcode.routes[current_route_path] = klass.new
665
- Capcode.routes[current_route_path] = klass
666
- end
667
- end
668
- rescue => e
669
- raise e.message
670
- end
671
- end
672
-
673
- # Set Static directory
674
- Capcode.static = (Capcode::Configuration.get(:static)[0].chr == "/")?Capcode::Configuration.get(:static):"/"+Capcode::Configuration.get(:static) unless Capcode::Configuration.get(:static).nil?
675
-
676
- # Initialize Rack App
677
- puts "** Map routes." if Capcode::Configuration.get(:verbose)
678
- # app = Rack::URLMap.new(Capcode.routes)
679
- app = Capcode::Ext::Rack::URLMap.new(Capcode.routes)
680
- puts "** Initialize static directory (#{Capcode.static}) in #{File.expand_path(Capcode::Configuration.get(:root))}" if Capcode::Configuration.get(:verbose)
681
- app = Rack::Static.new(
682
- app,
683
- #:urls => [@@__STATIC_DIR],
684
- :urls => [Capcode.static],
685
- :root => File.expand_path(Capcode::Configuration.get(:root))
686
- ) unless Capcode::Configuration.get(:static).nil?
687
- puts "** Initialize session" if Capcode::Configuration.get(:verbose)
688
- app = Rack::Session::Cookie.new( app, Capcode::Configuration.get(:session) )
689
- app = Capcode::StaticFiles.new(app)
690
- app = Capcode::HTTPError.new(app)
691
- app = Rack::ContentLength.new(app)
692
- app = Rack::Lint.new(app)
693
- app = Rack::ShowExceptions.new(app)
694
- #app = Rack::Reloader.new(app) ## -- NE RELOAD QUE capcode.rb -- So !!!
695
- app = Rack::CommonLogger.new( app, @cclogger = Logger.new(Capcode::Configuration.get(:log)) )
696
-
697
- middlewares.each do |mw|
698
- middleware, args, block = mw
699
- puts "** Load middleware #{middleware}" if Capcode::Configuration.get(:verbose)
700
- if block
701
- app = middleware.new( app, *args, &block )
702
- else
703
- app = middleware.new( app, *args )
704
- end
705
- end
706
-
707
- # Start database
708
- if self.methods.include? "db_connect"
709
- db_connect( Capcode::Configuration.get(:db_config), Capcode::Configuration.get(:log) )
710
- end
711
-
712
- if block_given?
713
- puts "** Execute block" if Capcode::Configuration.get(:verbose)
714
- yield( self )
715
- end
716
-
717
- return app
718
- end
719
-
720
- # Start your application.
721
- #
722
- # Options : see Capcode::Configuration.set
723
- #
724
- # Options set here replace the ones set globally
725
- def run( args = {} )
726
- Capcode::Configuration.configuration(args)
727
-
728
- # Parse options
729
- opts = OptionParser.new do |opts|
730
- opts.banner = "Usage: #{File.basename($0)} [options]"
731
- opts.separator ""
732
- opts.separator "Specific options:"
733
-
734
- opts.on( "-C", "--console", "Run in console mode with IRB (default: false)" ) {
735
- Capcode::Configuration.set :console, true
736
- }
737
- opts.on( "-h", "--host HOSTNAME", "Host for web server to bind to (default: #{Capcode::Configuration.get(:host)})" ) { |h|
738
- Capcode::Configuration.set :host, h
739
- }
740
- opts.on( "-p", "--port NUM", "Port for web server (default: #{Capcode::Configuration.get(:port)})" ) { |p|
741
- Capcode::Configuration.set :port, p
742
- }
743
- opts.on( "-d", "--daemonize [true|false]", "Daemonize (default: #{Capcode::Configuration.get(:daemonize)})" ) { |d|
744
- Capcode::Configuration.set :daemonize, d
745
- }
746
- opts.on( "-r", "--root PATH", "Working directory (default: #{Capcode::Configuration.get(:root)})" ) { |w|
747
- Capcode::Configuration.set :root, w
748
- }
749
- opts.on( "-s", "--static PATH", "Static directory -- relative to the root directory (default: #{Capcode::Configuration.get(:static)})" ) { |r|
750
- Capcode::Configuration.set :static, r
751
- }
752
- opts.on( "-S", "--server SERVER", "Server to use (default: #{Capcode::Configuration.get(:server)})" ) { |r|
753
- Capcode::Configuration.set :server, r
754
- }
755
-
756
- opts.separator ""
757
- opts.separator "Common options:"
758
-
759
- opts.on("-?", "--help", "Show this message") do
760
- puts opts
761
- exit
762
- end
763
- opts.on("-v", "--version", "Show versions") do
764
- puts "Capcode version #{Capcode::CAPCOD_VERION} (ruby v#{RUBY_VERSION})"
765
- exit
766
- end
767
- opts.on_tail( "-V", "--verbose", "Run in verbose mode" ) do
768
- Capcode::Configuration.set :verbose, true
769
- end
770
- end
771
-
772
- begin
773
- opts.parse! ARGV
774
- rescue OptionParser::ParseError => ex
775
- puts "!! #{ex.message}"
776
- puts "** use `#{File.basename($0)} --help` for more details..."
777
- exit 1
778
- end
779
-
780
- # Run in the Working directory
781
- puts "** Go on root directory (#{File.expand_path(Capcode::Configuration.get(:root))})" if Capcode::Configuration.get(:verbose)
782
- Dir.chdir( Capcode::Configuration.get(:root) ) do
783
-
784
- # Check that mongrel exists
785
- if Capcode::Configuration.get(:server).nil? || Capcode::Configuration.get(:server) == "mongrel"
786
- begin
787
- require 'mongrel'
788
- Capcode::Configuration.set :server, :mongrel
789
- rescue LoadError
790
- puts "!! could not load mongrel. Falling back to webrick."
791
- Capcode::Configuration.set :server, :webrick
792
- end
793
- end
794
-
795
- # From rackup !!!
796
- if Capcode::Configuration.get(:daemonize)
797
- if /java/.match(RUBY_PLATFORM).nil?
798
- if RUBY_VERSION < "1.9"
799
- exit if fork
800
- Process.setsid
801
- exit if fork
802
- # Dir.chdir "/"
803
- File.umask 0000
804
- STDIN.reopen "/dev/null"
805
- STDOUT.reopen "/dev/null", "a"
806
- STDERR.reopen "/dev/null", "a"
807
- else
808
- Process.daemon
809
- end
810
- else
811
- puts "!! daemonize option unavailable on #{RUBY_PLATFORM} platform."
812
- end
813
-
814
- File.open(Capcode::Configuration.get(:pid), 'w'){ |f| f.write("#{Process.pid}") }
815
- at_exit { File.delete(Capcode::Configuration.get(:pid)) if File.exist?(Capcode::Configuration.get(:pid)) }
816
- end
817
-
818
- app = nil
819
- if block_given?
820
- app = application(Capcode::Configuration.get) { yield( self ) }
821
- else
822
- app = application(Capcode::Configuration.get)
823
- end
824
-
825
- if Capcode::Configuration.get(:console)
826
- puts "Run console..."
827
- IRB.start
828
- exit
829
- end
830
-
831
- # Start server
832
- case Capcode::Configuration.get(:server).to_s
833
- when "mongrel"
834
- puts "** Starting Mongrel on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
835
- Rack::Handler::Mongrel.run( app, {:Port => Capcode::Configuration.get(:port), :Host => Capcode::Configuration.get(:host)} ) { |server|
836
- trap "SIGINT", proc { server.stop }
837
- }
838
- when "webrick"
839
- puts "** Starting WEBrick on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
840
- Rack::Handler::WEBrick.run( app, {:Port => Capcode::Configuration.get(:port), :BindAddress => Capcode::Configuration.get(:host)} ) { |server|
841
- trap "SIGINT", proc { server.shutdown }
842
- }
843
- when "thin"
844
- puts "** Starting Thin on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
845
- Rack::Handler::Thin.run( app, {:Port => Capcode::Configuration.get(:port), :Host => Capcode::Configuration.get(:host)} ) { |server|
846
- trap "SIGINT", proc { server.stop }
847
- }
848
- when "unicorn"
849
- require 'unicorn/launcher'
850
- puts "** Starting Unicorn on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
851
- Unicorn.run( app, {:listeners => ["#{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"]} )
852
- when "rainbows"
853
- require 'unicorn/launcher'
854
- require 'rainbows'
855
- puts "** Starting Rainbow on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
856
- Rainbows.run( app, {:listeners => ["#{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"]} )
857
- when "control_tower"
858
- require 'control_tower'
859
- puts "** Starting ControlTower on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
860
- ControlTower::Server.new( app, {:host => Capcode::Configuration.get(:host), :port => Capcode::Configuration.get(:port)} ).start
861
- end
862
- end
863
- end
864
-
865
- def routes #:nodoc:
866
- @routes ||= {}
867
- end
868
-
869
- def logger
870
- @cclogger
871
- end
872
-
873
- def static #:nodoc:
874
- @static_dir ||= nil
875
- end
876
- def static=(x) #:nodoc:
877
- @static_dir = x
878
- end
879
-
880
- end
881
- end