Class Camping::Server
In: lib/camping/server.rb
Parent: Object

The Camping Server (for development)

Camping includes a pretty nifty server which is built for development. It follows these rules:

  • Load all Camping apps in a directory or a file.
  • Load new apps that appear in that directory or that file.
  • Mount those apps according to their name. (e.g. Blog is mounted at /blog.)
  • Run each app‘s create method upon startup.
  • Reload the app if its modification time changes.
  • Reload the app if it requires any files under the same directory and one of their modification times changes.
  • Support the X-Sendfile header.

Run it like this:

  camping examples/        # Mounts all apps in that directory
  camping blog.rb          # Mounts Blog at /

And visit localhost:3301/ in your browser.

Methods

app   apps   call   connect   find_scripts   index_page   new   reload!   start  

Classes and Modules

Class Camping::Server::XSendfile

Attributes

conf  [RW] 
reloader  [R] 

Public Class methods

[Source]

    # File lib/camping/server.rb, line 29
29:   def initialize(conf, paths)
30:     @conf = conf
31:     @paths = paths
32:     @reloader = Camping::Reloader.new
33:     connect(@conf.database) if @conf.database
34:   end

Public Instance methods

[Source]

     # File lib/camping/server.rb, line 90
 90:   def app
 91:     reload!
 92:     all_apps = apps
 93:     rapp = case all_apps.length
 94:     when 0
 95:       proc{|env|[200,{'Content-Type'=>'text/html'},index_page([])]}
 96:     when 1
 97:       apps.values.first
 98:     else
 99:       hash = {
100:         "/" => proc {|env|[200,{'Content-Type'=>'text/html'},index_page(all_apps)]}
101:       }
102:       all_apps.each do |mount, wrapp|
103:         # We're doing @reloader.reload! ourself, so we don't need the wrapper.
104:         app = wrapp.app
105:         hash["/#{mount}"] = app
106:         hash["/code/#{mount}"] = proc do |env|
107:           [200,{'Content-Type'=>'text/plain','X-Sendfile'=>wrapp.script.file},'']
108:         end
109:       end
110:       Rack::URLMap.new(hash)
111:     end
112:     rapp = Rack::ContentLength.new(rapp)
113:     rapp = Rack::Lint.new(rapp)
114:     rapp = XSendfile.new(rapp)
115:     rapp = Rack::ShowExceptions.new(rapp)
116:   end

[Source]

     # File lib/camping/server.rb, line 118
118:   def apps
119:     @reloader.apps.inject({}) do |h, (mount, wrapp)|
120:       h[mount.to_s.downcase] = wrapp
121:       h
122:     end
123:   end

[Source]

     # File lib/camping/server.rb, line 125
125:   def call(env)
126:     app.call(env)
127:   end

[Source]

    # File lib/camping/server.rb, line 36
36:   def connect(db)
37:     unless Camping.autoload?(:Models)
38:       Camping::Models::Base.establish_connection(db)
39:     end
40:   end

[Source]

    # File lib/camping/server.rb, line 42
42:   def find_scripts
43:     scripts = @paths.map do |path|
44:       case
45:       when File.file?(path)
46:         path
47:       when File.directory?(path)
48:         Dir[File.join(path, '*.rb')]
49:       end
50:     end.flatten.compact
51:     @reloader.update(*scripts)
52:   end

[Source]

    # File lib/camping/server.rb, line 54
54:   def index_page(apps)
55:     welcome = "You are Camping"
56:     header = "<html>\n<head>\n<title>\#{welcome}</title>\n<style type=\"text/css\">\nbody {\nfont-family: verdana, arial, sans-serif;\npadding: 10px 40px;\nmargin: 0;\n}\nh1, h2, h3, h4, h5, h6 {\nfont-family: utopia, georgia, serif;\n}\n</style>\n</head>\n<body>\n<h1>\#{welcome}</h1>\n"
57:     footer = '</body></html>'
58:     main = if apps.empty?
59:       "<p>Good day.  I'm sorry, but I could not find any Camping apps. "\
60:       "You might want to take a look at the console to see if any errors "\
61:       "have been raised.</p>"
62:     else
63:       "<p>Good day.  These are the Camping apps you've mounted.</p><ul>" + 
64:       apps.map do |mount, app|
65:         "<li><h3 style=\"display: inline\"><a href=\"/#{mount}\">#{app}</a></h3><small> / <a href=\"/code/#{mount}\">View source</a></small></li>"
66:       end.join("\n") + '</ul>'
67:     end
68:     
69:     header + main + footer
70:   end

[Source]

     # File lib/camping/server.rb, line 149
149:   def reload!
150:     find_scripts
151:     @reloader.reload!
152:   end

[Source]

     # File lib/camping/server.rb, line 129
129:   def start
130:     handler, conf = case @conf.server
131:     when "console"
132:       puts "** Starting console"
133:       reload!
134:       this = self; eval("self", TOPLEVEL_BINDING).meta_def(:reload!) { this.reload!; nil }
135:       ARGV.clear
136:       IRB.start
137:       exit
138:     when "mongrel"
139:       puts "** Starting Mongrel on #{@conf.host}:#{@conf.port}"
140:       [Rack::Handler::Mongrel, {:Port => @conf.port, :Host => @conf.host}]
141:     when "webrick"
142:       puts "** Starting WEBrick on #{@conf.host}:#{@conf.port}"
143:       [Rack::Handler::WEBrick, {:Port => @conf.port, :BindAddress => @conf.host}]
144:     end
145:     reload!
146:     handler.run(self, conf) 
147:   end

[Validate]