camping 1.5.180 → 2.0.rc0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/CHANGELOG +35 -0
  2. data/README +43 -68
  3. data/Rakefile +155 -86
  4. data/bin/camping +64 -246
  5. data/book/01_introduction +19 -0
  6. data/book/02_getting_started +443 -0
  7. data/book/51_upgrading +93 -0
  8. data/doc/api.html +1953 -0
  9. data/doc/book.html +73 -0
  10. data/doc/book/01_introduction.html +57 -0
  11. data/doc/book/02_getting_started.html +573 -0
  12. data/doc/book/51_upgrading.html +146 -0
  13. data/doc/created.rid +1 -0
  14. data/{extras → doc/images}/Camping.gif +0 -0
  15. data/doc/images/loadingAnimation.gif +0 -0
  16. data/{extras → doc/images}/permalink.gif +0 -0
  17. data/doc/index.html +148 -0
  18. data/doc/js/camping.js +79 -0
  19. data/doc/js/jquery.js +32 -0
  20. data/doc/rdoc.css +117 -0
  21. data/examples/blog.rb +280 -181
  22. data/extras/images/badge.gif +0 -0
  23. data/extras/images/boys-life.png +0 -0
  24. data/extras/images/deerputer.png +0 -0
  25. data/extras/images/diagram.png +0 -0
  26. data/extras/images/hill.png +0 -0
  27. data/extras/images/i-wish.png +0 -0
  28. data/extras/images/latl.png +0 -0
  29. data/extras/images/little-wheels.png +0 -0
  30. data/extras/images/square-badge.png +0 -0
  31. data/extras/images/uniform.png +0 -0
  32. data/extras/images/whale-bounce.png +0 -0
  33. data/extras/rdoc/generator/singledarkfish.rb +205 -0
  34. data/extras/rdoc/generator/template/flipbook/images/Camping.gif +0 -0
  35. data/extras/rdoc/generator/template/flipbook/images/loadingAnimation.gif +0 -0
  36. data/extras/rdoc/generator/template/flipbook/images/permalink.gif +0 -0
  37. data/extras/rdoc/generator/template/flipbook/js/camping.js +79 -0
  38. data/extras/rdoc/generator/template/flipbook/js/jquery.js +32 -0
  39. data/extras/rdoc/generator/template/flipbook/page.rhtml +30 -0
  40. data/extras/rdoc/generator/template/flipbook/rdoc.css +117 -0
  41. data/extras/rdoc/generator/template/flipbook/readme.rhtml +31 -0
  42. data/extras/rdoc/generator/template/flipbook/reference.rhtml +71 -0
  43. data/extras/rdoc/generator/template/flipbook/toc.rhtml +43 -0
  44. data/lib/camping-unabridged.rb +420 -481
  45. data/lib/camping.rb +40 -55
  46. data/lib/camping/{db.rb → ar.rb} +5 -8
  47. data/lib/camping/mab.rb +26 -0
  48. data/lib/camping/reloader.rb +175 -147
  49. data/lib/camping/server.rb +178 -0
  50. data/lib/camping/session.rb +34 -121
  51. data/test/apps/env_debug.rb +65 -0
  52. data/test/apps/forms.rb +95 -0
  53. data/test/apps/forward_to_other_controller.rb +60 -0
  54. data/test/apps/migrations.rb +97 -0
  55. data/test/apps/misc.rb +86 -0
  56. data/test/apps/sessions.rb +38 -0
  57. metadata +120 -80
  58. data/doc/camping.1.gz +0 -0
  59. data/examples/campsh.rb +0 -630
  60. data/examples/tepee.rb +0 -242
  61. data/extras/flipbook_rdoc.rb +0 -491
  62. data/lib/camping/fastcgi.rb +0 -244
  63. data/lib/camping/webrick.rb +0 -65
  64. data/test/test_xhtml_trans.rb +0 -55
@@ -1,244 +0,0 @@
1
- # == About camping/fastcgi.rb
2
- #
3
- # Camping works very well with FastCGI, since your application is only loaded
4
- # once -- when FastCGI starts. In addition, this class lets you mount several
5
- # Camping apps under a single FastCGI process, to help save memory costs.
6
- #
7
- # So where do you use the Camping::FastCGI class? Use it in your application's
8
- # postamble and then you can point your web server directly at your application.
9
- # See Camping::FastCGI docs for more.
10
- require 'camping'
11
- require 'fcgi'
12
-
13
- module Camping
14
- # Camping::FastCGI is a small class for hooking one or more Camping apps up to
15
- # FastCGI. Generally, you'll use this class in your application's postamble.
16
- #
17
- # == The Smallest Example
18
- #
19
- # if __FILE__ == $0
20
- # require 'camping/fastcgi'
21
- # Camping::FastCGI.start(YourApp)
22
- # end
23
- #
24
- # This example is stripped down to the basics. The postamble has no database
25
- # connection. It just loads this class and calls Camping::FastCGI.start.
26
- #
27
- # Now, in Lighttpd or Apache, you can point to your app's file, which will
28
- # be executed, only to discover that your app now speaks the FastCGI protocol.
29
- #
30
- # Here's a sample lighttpd.conf (tested with Lighttpd 1.4.11) to serve as example:
31
- #
32
- # server.port = 3044
33
- # server.bind = "127.0.0.1"
34
- # server.modules = ( "mod_fastcgi" )
35
- # server.document-root = "/var/www/camping/blog/"
36
- # server.errorlog = "/var/www/camping/blog/error.log"
37
- #
38
- # #### fastcgi module
39
- # fastcgi.server = ( "/" => (
40
- # "localhost" => (
41
- # "socket" => "/tmp/camping-blog.socket",
42
- # "bin-path" => "/var/www/camping/blog/blog.rb",
43
- # "check-local" => "disable",
44
- # "max-procs" => 1 ) ) )
45
- #
46
- # The file <tt>/var/www/camping/blog/blog.rb</tt> is the Camping app with
47
- # the postamble.
48
- #
49
- # == Mounting Many Apps
50
- #
51
- # require 'camping/fastcgi'
52
- # fast = Camping::FastCGI.new
53
- # fast.mount("/blog", Blog)
54
- # fast.mount("/tepee", Tepee)
55
- # fast.mount("/", Index)
56
- # fast.start
57
- #
58
- class FastCGI
59
- CHUNK_SIZE=(4 * 1024)
60
-
61
- attr_reader :mounts
62
-
63
- # Creates a Camping::FastCGI class with empty mounts.
64
- def initialize
65
- @mounts = {}
66
- end
67
- # Mounts a Camping application. The +dir+ being the name of the directory
68
- # to serve as the application's root. The +app+ is a Camping class.
69
- def mount(dir, app)
70
- dir.gsub!(/\/{2,}/, '/')
71
- dir.gsub!(/\/+$/, '')
72
- @mounts[dir] = app
73
- end
74
-
75
- #
76
- # Starts the FastCGI main loop.
77
- def start(&blk)
78
- FCGI.each do |req|
79
- camp_do(req, &blk)
80
- end
81
- end
82
-
83
- # A simple single-app starter mechanism
84
- #
85
- # Camping::FastCGI.start(Blog)
86
- #
87
- def self.start(app)
88
- cf = Camping::FastCGI.new
89
- cf.mount("/", app)
90
- cf.start
91
- end
92
-
93
- # Serve an entire directory of Camping apps. (See
94
- # http://code.whytheluckystiff.net/camping/wiki/TheCampingServer.)
95
- #
96
- # Use this method inside your FastCGI dispatcher:
97
- #
98
- # #!/usr/local/bin/ruby
99
- # require 'rubygems'
100
- # require 'camping/fastcgi'
101
- # Camping::Models::Base.establish_connection :adapter => 'sqlite3', :database => "/path/to/db"
102
- # Camping::FastCGI.serve("/home/why/cvs/camping/examples")
103
- #
104
- def self.serve(path, index=nil)
105
- require 'camping/reloader'
106
- if File.directory? path
107
- fast = Camping::FastCGI.new
108
- script_load = proc do |script|
109
- app = Camping::Reloader.new(script)
110
- fast.mount("/#{app.mount}", app)
111
- app
112
- end
113
- Dir[File.join(path, '*.rb')].each &script_load
114
- fast.mount("/", index) if index
115
-
116
- fast.start do |dir, app|
117
- Dir[File.join(path, dir, '*.rb')].each do |script|
118
- smount = "/" + File.basename(script, '.rb')
119
- script_load[script] unless fast.mounts.has_key? smount
120
- end
121
- end
122
- else
123
- start(Camping::Reloader.new(path))
124
- end
125
- end
126
-
127
- private
128
-
129
- def camp_do(req)
130
- root, path, dir, app = "/"
131
- if ENV['FORCE_ROOT'] and ENV['FORCE_ROOT'].to_i == 1
132
- path = req.env['SCRIPT_NAME']
133
- else
134
- root = req.env['SCRIPT_NAME']
135
- path = req.env['PATH_INFO']
136
- end
137
-
138
- dir, app = @mounts.max { |a,b| match(path, a[0]) <=> match(path, b[0]) }
139
- unless dir and app
140
- dir, app = '/', Camping
141
- end
142
- yield dir, app if block_given?
143
-
144
- req.env['SERVER_SCRIPT_NAME'] = req.env['SCRIPT_NAME']
145
- req.env['SERVER_PATH_INFO'] = req.env['PATH_INFO']
146
- req.env['SCRIPT_NAME'] = File.join(root, dir)
147
- req.env['PATH_INFO'] = path.gsub(/^#{dir}/, '')
148
-
149
- controller = app.run(SeekStream.new(req.in), req.env)
150
- sendfile = nil
151
- headers = {}
152
- controller.headers.each do |k, v|
153
- if k =~ /^X-SENDFILE$/i and !ENV['SERVER_X_SENDFILE']
154
- sendfile = v
155
- else
156
- headers[k] = v
157
- end
158
- end
159
-
160
- body = controller.body
161
- controller.body = ""
162
- controller.headers = headers
163
-
164
- req.out << controller.to_s
165
- if sendfile
166
- File.open(sendfile, "rb") do |f|
167
- while chunk = f.read(CHUNK_SIZE) and chunk.length > 0
168
- req.out << chunk
169
- end
170
- end
171
- elsif body.respond_to? :read
172
- while chunk = body.read(CHUNK_SIZE) and chunk.length > 0
173
- req.out << chunk
174
- end
175
- body.close if body.respond_to? :close
176
- else
177
- req.out << body.to_s
178
- end
179
- rescue Exception => e
180
- req.out << server_error(root, path, exc, req)
181
- ensure
182
- req.finish
183
- end
184
-
185
- def server_error(root, path, exc, req)
186
- "Content-Type: text/html\r\n\r\n" +
187
- "<h1>Camping Problem!</h1>" +
188
- "<h2><strong>#{root}</strong>#{path}</h2>" +
189
- "<h3>#{exc.class} #{esc exc.message}</h3>" +
190
- "<ul>" + exc.backtrace.map { |bt| "<li>#{esc bt}</li>" }.join + "</ul>" +
191
- "<hr /><p>#{req.env.inspect}</p>"
192
- end
193
-
194
- def match(path, mount)
195
- m = path.match(/^#{Regexp::quote mount}(\/|$)/)
196
- if m; m.end(0)
197
- else -1
198
- end
199
- end
200
-
201
- def esc(str)
202
- str.gsub(/&/n, '&amp;').gsub(/\"/n, '&quot;').gsub(/>/n, '&gt;').gsub(/</n, '&lt;')
203
- end
204
-
205
- class SeekStream
206
- def initialize(stream)
207
- @last_read = ""
208
- @stream = stream
209
- @buffer = ""
210
- end
211
- def eof?
212
- @buffer.empty? && @stream.eof?
213
- end
214
- def each
215
- while true
216
- pull(1024) until eof? or @buffer.index("\n")
217
- return nil if eof?
218
- yield @buffer.slice!(0..(@buffer.index("\n") || -1))
219
- end
220
- end
221
- def pull(len)
222
- @buffer += @stream.read(len).to_s
223
- end
224
- def read(len = 16384)
225
- pull(len)
226
- @last_read =
227
- if eof?
228
- nil
229
- else
230
- @buffer.slice!(0...len)
231
- end
232
- end
233
- def seek(len, typ)
234
- raise NotImplementedError, "only IO::SEEK_CUR is supported with SeekStream" if typ != IO::SEEK_CUR
235
- raise NotImplementedError, "only rewinding is supported with SeekStream" if len > 0
236
- raise NotImplementedError, "rewinding #{-len} past the buffer #{@last_read.size} start not supported with SeekStream" if -len > @last_read.size
237
- @buffer = @last_read[len..-1] + @buffer
238
- @last_read = ""
239
- self
240
- end
241
- end
242
-
243
- end
244
- end
@@ -1,65 +0,0 @@
1
- # == About camping/webrick.rb
2
- #
3
- # For many who have Ruby installed, Camping and WEBrick is a great option.
4
- # It's definitely the easiest configuration, however some performance is sacrificed.
5
- # For better speed, check out Mongrel at http://mongrel.rubyforge.org/, which comes
6
- # with Camping hooks and is supported by the Camping Tool.
7
- require 'camping'
8
- require 'webrick/httpservlet/abstract.rb'
9
-
10
- module WEBrick
11
- # WEBrick::CampingHandler is a very simple handle for hosting Camping apps in
12
- # a WEBrick server. It's used much like any other WEBrick handler.
13
- #
14
- # == Mounting a Camping App
15
- #
16
- # Assuming Camping.goes(:Blog), the Blog application can be mounted alongside
17
- # other WEBrick mounts.
18
- #
19
- # s = WEBrick::HTTPServer.new(:BindAddress => host, :Port => port)
20
- # s.mount "/blog", WEBrick::CampingHandler, Blog
21
- # s.mount_proc("/") { ... }
22
- #
23
- # == How Does it Compare?
24
- #
25
- # Compared to other handlers, WEBrick is well-equipped in terms of features.
26
- #
27
- # * The <tt>X-Sendfile</tt> header is supported, along with etags and
28
- # modification time headers for the file served. Since this handler
29
- # is a subclass of WEBrick::HTTPServlet::DefaultFileHandler, all of its
30
- # logic is used.
31
- # * IO is streaming up and down. When you upload a file, it is streamed to
32
- # the server's filesystem. When you download a file, it is streamed to
33
- # your browser.
34
- #
35
- # While WEBrick is a bit slower than Mongrel and FastCGI options, it's
36
- # a decent choice, for sure!
37
- class CampingHandler < WEBrick::HTTPServlet::DefaultFileHandler
38
- # Creates a CampingHandler, which answers for the application within +klass+.
39
- def initialize(server, klass)
40
- super(server, klass)
41
- @klass = klass
42
- end
43
- # Handler for WEBrick requests (also aliased as do_POST).
44
- def service(req, resp)
45
- controller = @klass.run((req.body and StringIO.new(req.body)), req.meta_vars)
46
- resp.status = controller.status
47
- @local_path = nil
48
- controller.headers.each do |k, v|
49
- if k =~ /^X-SENDFILE$/i
50
- @local_path = v
51
- else
52
- [*v].each do |vi|
53
- resp[k] = vi
54
- end
55
- end
56
- end
57
-
58
- if @local_path
59
- do_GET(req, resp)
60
- else
61
- resp.body = controller.body.to_s
62
- end
63
- end
64
- end
65
- end
@@ -1,55 +0,0 @@
1
- require 'mosquito'
2
-
3
- Camping.goes :XhtmlTrans
4
-
5
- module XhtmlTrans
6
- module Controllers
7
- class WithLayout < R '/with_layout'
8
- def get
9
- render :with_layout
10
- end
11
- end
12
-
13
- class WithoutLayout < R '/without_layout'
14
- def get
15
- render :_without_layout
16
- end
17
- end
18
- end
19
-
20
- module Views
21
- def layout
22
- xhtml_transitional do
23
- head do title "title" end
24
- body do capture { yield } end
25
- end
26
- end
27
-
28
- def with_layout
29
- h1 "With layout"
30
- end
31
-
32
- def _without_layout
33
- xhtml_transitional do
34
- head do title "title" end
35
- body do h1 "Without layout" end
36
- end
37
- end
38
- end
39
- end
40
-
41
- class XhtmlTransTest < Camping::FunctionalTest
42
- def test_with_layout
43
- get '/with_layout'
44
-
45
- assert(@response.body =~ /DOCTYPE/, "No doctype defined")
46
- end
47
-
48
- def test_without_layout
49
- get '/without_layout'
50
-
51
- assert(@response.body =~ /DOCTYPE/, "No doctype defined")
52
- end
53
-
54
- end
55
-