waves-edge 2009.03.10.13.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/waves +30 -0
- data/doc/HISTORY +1 -0
- data/doc/LICENSE +22 -0
- data/doc/README +1 -0
- data/doc/VERSION +1 -0
- data/lib/caches/file.rb +48 -0
- data/lib/caches/memcached.rb +40 -0
- data/lib/caches/simple.rb +25 -0
- data/lib/caches/synchronized.rb +25 -0
- data/lib/commands/console.rb +35 -0
- data/lib/commands/generate.rb +52 -0
- data/lib/commands/help.rb +5 -0
- data/lib/commands/server.rb +68 -0
- data/lib/dispatchers/base.rb +68 -0
- data/lib/dispatchers/default.rb +25 -0
- data/lib/ext/float.rb +13 -0
- data/lib/ext/hash.rb +31 -0
- data/lib/ext/integer.rb +27 -0
- data/lib/ext/kernel.rb +20 -0
- data/lib/ext/module.rb +20 -0
- data/lib/ext/object.rb +33 -0
- data/lib/ext/string.rb +20 -0
- data/lib/ext/symbol.rb +11 -0
- data/lib/ext/tempfile.rb +5 -0
- data/lib/foundations/classic.rb +59 -0
- data/lib/foundations/compact.rb +52 -0
- data/lib/helpers/basic.rb +11 -0
- data/lib/helpers/doc_type.rb +34 -0
- data/lib/helpers/extended.rb +21 -0
- data/lib/helpers/form.rb +42 -0
- data/lib/helpers/formatting.rb +30 -0
- data/lib/helpers/layouts.rb +37 -0
- data/lib/helpers/model.rb +37 -0
- data/lib/helpers/view.rb +22 -0
- data/lib/layers/inflect/english.rb +35 -0
- data/lib/layers/mvc.rb +41 -0
- data/lib/layers/mvc/controllers.rb +41 -0
- data/lib/layers/mvc/extensions.rb +52 -0
- data/lib/layers/orm/migration.rb +79 -0
- data/lib/layers/orm/providers/active_record.rb +84 -0
- data/lib/layers/orm/providers/active_record/migrations/empty.rb.erb +9 -0
- data/lib/layers/orm/providers/active_record/tasks/generate.rb +28 -0
- data/lib/layers/orm/providers/active_record/tasks/schema.rb +22 -0
- data/lib/layers/orm/providers/data_mapper.rb +37 -0
- data/lib/layers/orm/providers/filebase.rb +25 -0
- data/lib/layers/orm/providers/sequel.rb +87 -0
- data/lib/layers/orm/providers/sequel/migrations/empty.rb.erb +9 -0
- data/lib/layers/orm/providers/sequel/tasks/generate.rb +30 -0
- data/lib/layers/orm/providers/sequel/tasks/schema.rb +16 -0
- data/lib/layers/renderers/erubis.rb +52 -0
- data/lib/layers/renderers/haml.rb +67 -0
- data/lib/layers/renderers/markaby.rb +41 -0
- data/lib/matchers/accept.rb +21 -0
- data/lib/matchers/base.rb +30 -0
- data/lib/matchers/content_type.rb +17 -0
- data/lib/matchers/path.rb +67 -0
- data/lib/matchers/query.rb +21 -0
- data/lib/matchers/request.rb +27 -0
- data/lib/matchers/resource.rb +19 -0
- data/lib/matchers/traits.rb +19 -0
- data/lib/matchers/uri.rb +20 -0
- data/lib/renderers/mixin.rb +13 -0
- data/lib/resources/mixin.rb +136 -0
- data/lib/resources/paths.rb +132 -0
- data/lib/runtime/configuration.rb +100 -0
- data/lib/runtime/console.rb +23 -0
- data/lib/runtime/logger.rb +35 -0
- data/lib/runtime/mime_types.rb +536 -0
- data/lib/runtime/mocks.rb +14 -0
- data/lib/runtime/monitor.rb +32 -0
- data/lib/runtime/request.rb +152 -0
- data/lib/runtime/response.rb +43 -0
- data/lib/runtime/response_mixin.rb +54 -0
- data/lib/runtime/runtime.rb +69 -0
- data/lib/runtime/server.rb +20 -0
- data/lib/runtime/session.rb +27 -0
- data/lib/runtime/worker.rb +86 -0
- data/lib/servers/base.rb +42 -0
- data/lib/servers/mongrel.rb +13 -0
- data/lib/servers/webrick.rb +13 -0
- data/lib/tasks/gem.rb +32 -0
- data/lib/tasks/generate.rb +85 -0
- data/lib/views/errors.rb +49 -0
- data/lib/views/mixin.rb +64 -0
- data/lib/waves.rb +63 -0
- data/samples/blog/Rakefile +25 -0
- data/samples/blog/configurations/default.rb +11 -0
- data/samples/blog/configurations/development.rb +29 -0
- data/samples/blog/configurations/production.rb +26 -0
- data/samples/blog/models/comment.rb +23 -0
- data/samples/blog/models/entry.rb +31 -0
- data/samples/blog/public/css/site.css +13 -0
- data/samples/blog/public/javascript/jquery-1.2.6.min.js +32 -0
- data/samples/blog/public/javascript/site.js +13 -0
- data/samples/blog/resources/entry.rb +39 -0
- data/samples/blog/resources/map.rb +9 -0
- data/samples/blog/schema/migrations/001_initial_schema.rb +17 -0
- data/samples/blog/schema/migrations/002_add_comments.rb +18 -0
- data/samples/blog/schema/migrations/templates/empty.rb.erb +9 -0
- data/samples/blog/startup.rb +8 -0
- data/samples/blog/templates/comment/add.mab +12 -0
- data/samples/blog/templates/comment/list.mab +6 -0
- data/samples/blog/templates/entry/edit.mab +14 -0
- data/samples/blog/templates/entry/list.mab +16 -0
- data/samples/blog/templates/entry/show.mab +18 -0
- data/samples/blog/templates/entry/summary.mab +9 -0
- data/samples/blog/templates/errors/not_found_404.mab +7 -0
- data/samples/blog/templates/errors/server_error_500.mab +2 -0
- data/samples/blog/templates/layouts/default.mab +19 -0
- data/samples/blog/templates/waves/status.mab +85 -0
- data/templates/classic/Rakefile +90 -0
- data/templates/classic/configurations/default.rb.erb +9 -0
- data/templates/classic/configurations/development.rb.erb +26 -0
- data/templates/classic/configurations/production.rb.erb +29 -0
- data/templates/classic/controllers/.gitignore +0 -0
- data/templates/classic/helpers/.gitignore +0 -0
- data/templates/classic/lib/tasks/.gitignore +0 -0
- data/templates/classic/models/.gitignore +0 -0
- data/templates/classic/public/css/.gitignore +0 -0
- data/templates/classic/public/flash/.gitignore +0 -0
- data/templates/classic/public/images/.gitignore +0 -0
- data/templates/classic/public/javascript/.gitignore +0 -0
- data/templates/classic/resources/.gitignore +0 -0
- data/templates/classic/resources/map.rb.erb +8 -0
- data/templates/classic/schema/migrations/.gitignore +0 -0
- data/templates/classic/startup.rb.erb +11 -0
- data/templates/classic/templates/errors/not_found_404.mab +7 -0
- data/templates/classic/templates/errors/server_error_500.mab +7 -0
- data/templates/classic/templates/layouts/default.mab +14 -0
- data/templates/classic/tmp/sessions/.gitignore +0 -0
- data/templates/classic/views/.gitignore +0 -0
- data/templates/compact/startup.rb.erb +11 -0
- data/test/ext/object.rb +55 -0
- data/test/ext/shortcuts.rb +73 -0
- data/test/helpers.rb +17 -0
- data/test/match/accept.rb +34 -0
- data/test/match/methods.rb +22 -0
- data/test/match/params.rb +33 -0
- data/test/match/path.rb +106 -0
- data/test/match/query.rb +40 -0
- data/test/process/request.rb +75 -0
- data/test/process/resource.rb +53 -0
- data/test/resources/path.rb +166 -0
- data/test/runtime/configurations.rb +19 -0
- data/test/runtime/request.rb +63 -0
- data/test/runtime/response.rb +55 -0
- data/test/views/views.rb +34 -0
- metadata +394 -0
data/bin/waves
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
# WARNING: This strange preamble might look easy to clean-up, but it is needed
|
|
4
|
+
# to work with older versions of gems (< 1.2).
|
|
5
|
+
|
|
6
|
+
require 'rubygems'
|
|
7
|
+
|
|
8
|
+
WAVES = "#{File.dirname(__FILE__)}/.." unless defined? WAVES
|
|
9
|
+
|
|
10
|
+
waves = [
|
|
11
|
+
WAVES, ENV['WAVES'], './waves'
|
|
12
|
+
].compact.map { |dir| File.join(dir, 'lib') }.find { |d|
|
|
13
|
+
File.exist? File.join( d, 'waves.rb' )
|
|
14
|
+
}
|
|
15
|
+
if waves
|
|
16
|
+
$: << waves
|
|
17
|
+
waves = File.join( waves, 'waves' )
|
|
18
|
+
else
|
|
19
|
+
waves = 'waves'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
require waves
|
|
23
|
+
|
|
24
|
+
puts "** Waves #{Waves.version} **"
|
|
25
|
+
|
|
26
|
+
begin
|
|
27
|
+
require "commands/#{ARGV.first}"
|
|
28
|
+
rescue LoadError => e
|
|
29
|
+
require "commands/help"
|
|
30
|
+
end
|
data/doc/HISTORY
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
See http://github.com/dyoder/waves/tree/master
|
data/doc/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2007-8 Dan Yoder
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
|
4
|
+
obtaining a copy of this software and associated documentation
|
|
5
|
+
files (the "Software"), to deal in the Software without
|
|
6
|
+
restriction, including without limitation the rights to use,
|
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the
|
|
9
|
+
Software is furnished to do so, subject to the following
|
|
10
|
+
conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be
|
|
13
|
+
included in all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/doc/README
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
To find out more about Waves, visit our Web site, http://rubywaves.com.
|
data/doc/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.8.2
|
data/lib/caches/file.rb
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require 'caches/synchronized'
|
|
2
|
+
|
|
3
|
+
module Waves
|
|
4
|
+
module Caches
|
|
5
|
+
|
|
6
|
+
class File < Simple
|
|
7
|
+
|
|
8
|
+
def initialize( args )
|
|
9
|
+
raise ArgumentError, ":directory is nil" if args[ :directory ].nil?
|
|
10
|
+
@directory = args[ :directory ] ; @keys = []
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def store( key, value )
|
|
14
|
+
@keys << key
|
|
15
|
+
::File.open( @directory / key, 'w') { |f| Marshal.dump( value, f ) }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def delete( key )
|
|
19
|
+
if @keys.include? key
|
|
20
|
+
::File.delete( @directory / key )
|
|
21
|
+
@keys.delete( key )
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def clear
|
|
26
|
+
@keys.each { |key| delete( key ) }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def fetch( key )
|
|
30
|
+
Marshal.load( ::File.read( @directory / key ) ) if @keys.include?( key )
|
|
31
|
+
rescue ArgumentError
|
|
32
|
+
nil
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class SynchronizedFile < Synchronized
|
|
38
|
+
|
|
39
|
+
def initialize( args )
|
|
40
|
+
super( File.new( args ) )
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'memcached'
|
|
2
|
+
module Waves
|
|
3
|
+
module Caches
|
|
4
|
+
class Memcached < Simple
|
|
5
|
+
|
|
6
|
+
def initialize( args )
|
|
7
|
+
raise ArgumentError, ":servers is nil" if args[ :servers ].nil?
|
|
8
|
+
@cache = ::Memcached.new( args[ :servers ], args[ :options ] || {} )
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def store( key,value, ttl = 0, marshal = true )
|
|
12
|
+
cache = @cache.clone; cache.add( key.to_s, value, ttl, marshal ); cache.destroy
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def fetch( key )
|
|
16
|
+
cache = @cache.clone; cache.get( key.to_s ); cache.destroy
|
|
17
|
+
rescue ::Memcached::NotFound => e
|
|
18
|
+
nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def delete( key )
|
|
22
|
+
cache = @cache.clone; cache.delete( key.to_s ); cache.destroy
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def clear
|
|
26
|
+
cache = @cache.clone; cache.flush; cache.destroy
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class SynchronizedMemcached < Synchronized
|
|
32
|
+
|
|
33
|
+
def initialize( args )
|
|
34
|
+
super( Memcached.new( args ) )
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Waves
|
|
2
|
+
|
|
3
|
+
module Caches
|
|
4
|
+
|
|
5
|
+
#
|
|
6
|
+
# This class is more or less here to establish the basic interface for caching and for
|
|
7
|
+
# lightweight caching that doesn't require a dedicated caching process.
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
class Simple
|
|
11
|
+
|
|
12
|
+
def initialize( hash = {} ) ; @cache = hash ; end
|
|
13
|
+
def [](key) ; fetch(key) ; end
|
|
14
|
+
def []=( key, value ) ; store( key, value ) ; end
|
|
15
|
+
def exists?( key ) ; fetch(key) == nil ? false : true ; end
|
|
16
|
+
alias :exist? :exists?
|
|
17
|
+
def store( key, val ) ; @cache[ key ] = val ; end
|
|
18
|
+
def fetch( key ) ; @cache[ key ] ; end
|
|
19
|
+
def delete( key ) ; @cache.delete( key ) ; end
|
|
20
|
+
def clear ; @cache = {} ; end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
|
|
2
|
+
module Waves
|
|
3
|
+
|
|
4
|
+
module Caches
|
|
5
|
+
|
|
6
|
+
#
|
|
7
|
+
# This is just a proxy for the real cache, but adds Waves synchronization
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
class Synchronized
|
|
11
|
+
|
|
12
|
+
def initialize( cache ) ; @cache = cache ; end
|
|
13
|
+
def [](key) ; @cache.fetch(key) ; end
|
|
14
|
+
def []=( key, value ) ; @cache.store( key, value ) ; end
|
|
15
|
+
def exists?( key ) ; @cache.has_key?( key ) ; end
|
|
16
|
+
alias :exist? :exists?
|
|
17
|
+
def store( key, val ) ; synchronize { @cache.store( key, value ) }; end
|
|
18
|
+
def fetch( keys ) ; @cache.fetch( key ) ; end
|
|
19
|
+
def delete( key ) ; synchronize { @cache.delete( key ) } ; end
|
|
20
|
+
def clear ; synchronize { @cache.clear } ; end
|
|
21
|
+
def synchronize( &block ) ; Waves.synchronize( &block ) ; end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'choice'
|
|
2
|
+
|
|
3
|
+
Choice.options do
|
|
4
|
+
header 'Run waves in console mode.'
|
|
5
|
+
header ''
|
|
6
|
+
option :mode do
|
|
7
|
+
short '-c'
|
|
8
|
+
long '--config=CONFIG'
|
|
9
|
+
desc 'Configuration to use.'
|
|
10
|
+
desc 'Defaults to development.'
|
|
11
|
+
cast Symbol
|
|
12
|
+
end
|
|
13
|
+
separator ''
|
|
14
|
+
option :startup do
|
|
15
|
+
short '-s'
|
|
16
|
+
long '--startup'
|
|
17
|
+
desc 'Startup file to load.'
|
|
18
|
+
desc 'Defaults to "startup.rb"'
|
|
19
|
+
end
|
|
20
|
+
separator ''
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
require 'runtime/console'
|
|
24
|
+
|
|
25
|
+
begin
|
|
26
|
+
console = Waves::Console.load( Choice.choices )
|
|
27
|
+
Object.send(:define_method, :waves) { console }
|
|
28
|
+
require 'irb'
|
|
29
|
+
require 'irb/completion'
|
|
30
|
+
ARGV.clear
|
|
31
|
+
Waves.log.info "Runtime console starting ..."
|
|
32
|
+
IRB.start
|
|
33
|
+
rescue LoadError => e
|
|
34
|
+
puts e.message
|
|
35
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require 'choice'
|
|
2
|
+
require 'rakegen'
|
|
3
|
+
|
|
4
|
+
waves = File.expand_path( File.dirname( __FILE__ ) / '..' / '..' )
|
|
5
|
+
orms = Dir[ waves / :lib / :layers / :orm / :providers / '*.rb' ].map { |path| File.basename( path, '.rb' )}
|
|
6
|
+
templates = Dir[ waves / :templates / '*' ].map { |path| File.basename( path ) }
|
|
7
|
+
|
|
8
|
+
Choice.options do
|
|
9
|
+
|
|
10
|
+
option :help do
|
|
11
|
+
long '--help'
|
|
12
|
+
desc 'Show this message'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
option :orm do
|
|
16
|
+
short '-o'
|
|
17
|
+
long '--orm=ORM'
|
|
18
|
+
desc "Select an ORM (currently supported: #{orms * ', '} )"
|
|
19
|
+
valid orms
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
option :template do
|
|
23
|
+
short '-t'
|
|
24
|
+
long '--template=TEMPLATE'
|
|
25
|
+
desc "Select a template for your app (options: #{templates * ', '})."
|
|
26
|
+
valid templates
|
|
27
|
+
default 'classic'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
option :name, :required => true do
|
|
31
|
+
short '-n'
|
|
32
|
+
long '--name'
|
|
33
|
+
desc "Select a name for the application. Use only letters, numbers, dashes, or underscores."
|
|
34
|
+
validate /^[\w\d\-]+$/
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
options = Choice.choices
|
|
40
|
+
|
|
41
|
+
puts "** Creating new Waves application ..."
|
|
42
|
+
|
|
43
|
+
# why do i have to do this?
|
|
44
|
+
FileUtils.mkdir( File.expand_path( options.name ) )
|
|
45
|
+
|
|
46
|
+
generator = Rakegen.new("generate") do |gen|
|
|
47
|
+
gen.source = waves / :templates / options.template
|
|
48
|
+
gen.target = File.expand_path( options.name )
|
|
49
|
+
gen.template_assigns = options.merge( :name => options.name.gsub('-','_').camel_case )
|
|
50
|
+
end.invoke
|
|
51
|
+
|
|
52
|
+
puts "** Application created!"
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
require 'choice'
|
|
2
|
+
|
|
3
|
+
Choice.options do
|
|
4
|
+
header 'Run a waves application server.'
|
|
5
|
+
header ''
|
|
6
|
+
option :port do
|
|
7
|
+
short '-p'
|
|
8
|
+
long '--port=PORT'
|
|
9
|
+
desc 'Port to listen on.'
|
|
10
|
+
desc 'Defaults to value given in configuration.'
|
|
11
|
+
cast Integer
|
|
12
|
+
end
|
|
13
|
+
separator ''
|
|
14
|
+
option :host do
|
|
15
|
+
short '-h'
|
|
16
|
+
long '--host=HOST'
|
|
17
|
+
desc 'Host or IP address of the host to bind.'
|
|
18
|
+
desc 'Defaults to value given in configuration.'
|
|
19
|
+
end
|
|
20
|
+
separator ''
|
|
21
|
+
option :mode do
|
|
22
|
+
short '-c'
|
|
23
|
+
long '--config=CONFIG'
|
|
24
|
+
desc 'Configuration to use.'
|
|
25
|
+
desc 'Defaults to development.'
|
|
26
|
+
cast Symbol
|
|
27
|
+
end
|
|
28
|
+
separator ''
|
|
29
|
+
option :directory do
|
|
30
|
+
short '-D'
|
|
31
|
+
long '--dir=DIR'
|
|
32
|
+
desc 'Directory containing the application.'
|
|
33
|
+
desc 'Defaults to the current directory.'
|
|
34
|
+
end
|
|
35
|
+
separator ''
|
|
36
|
+
option :daemon do
|
|
37
|
+
short '-d'
|
|
38
|
+
long '--daemon'
|
|
39
|
+
desc 'Run as a daemon.'
|
|
40
|
+
end
|
|
41
|
+
separator ''
|
|
42
|
+
option :turbo do
|
|
43
|
+
short '-t'
|
|
44
|
+
long '--turbo'
|
|
45
|
+
desc 'For thread-safe applications, run without dispatch level mutex.'
|
|
46
|
+
end
|
|
47
|
+
separator ''
|
|
48
|
+
option :debugger do
|
|
49
|
+
short '-u'
|
|
50
|
+
long '--debugger'
|
|
51
|
+
desc 'Enable ruby-debug.'
|
|
52
|
+
end
|
|
53
|
+
separator ''
|
|
54
|
+
option :startup do
|
|
55
|
+
short '-s'
|
|
56
|
+
long '--startup=PATH'
|
|
57
|
+
desc 'Startup file to load.'
|
|
58
|
+
desc 'Defaults to "startup.rb"'
|
|
59
|
+
end
|
|
60
|
+
separator ''
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
require 'runtime/server'
|
|
64
|
+
begin
|
|
65
|
+
Waves::Server.run( Choice.choices )
|
|
66
|
+
rescue LoadError => e
|
|
67
|
+
puts e.message
|
|
68
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module Waves
|
|
2
|
+
|
|
3
|
+
module Dispatchers
|
|
4
|
+
|
|
5
|
+
class NotFoundError < RuntimeError ; end
|
|
6
|
+
class Unauthorized < RuntimeError; end
|
|
7
|
+
class BadRequest < RuntimeError; end
|
|
8
|
+
|
|
9
|
+
# Redirect exceptions are rescued by the Waves dispatcher and used to set the
|
|
10
|
+
# response status and location.
|
|
11
|
+
class Redirect < SignalException
|
|
12
|
+
attr_reader :path, :status
|
|
13
|
+
def initialize( path, status = '302' )
|
|
14
|
+
@path = path
|
|
15
|
+
@status = status
|
|
16
|
+
end
|
|
17
|
+
def message
|
|
18
|
+
"location: #{@path} status: #{@status}"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
#
|
|
23
|
+
# Waves::Dispatchers::Base provides the basic request processing structure
|
|
24
|
+
# for a Rack application. It creates a Waves request, determines whether
|
|
25
|
+
# to enclose the request processing in a mutex benchmarks it, logs it,
|
|
26
|
+
# and handles redirects. Derived classes need only process the request
|
|
27
|
+
# within the +safe+ method, which must take a Waves::Request and return
|
|
28
|
+
# a Waves::Response.
|
|
29
|
+
#
|
|
30
|
+
|
|
31
|
+
class Base
|
|
32
|
+
|
|
33
|
+
# As with any Rack application, a Waves dispatcher must provide a call method
|
|
34
|
+
# that takes an +env+ hash.
|
|
35
|
+
def call( env )
|
|
36
|
+
response = if Waves.synchronize? or Waves.debug?
|
|
37
|
+
Waves.synchronize { Waves.reload ; _call( env ) }
|
|
38
|
+
else
|
|
39
|
+
_call( env )
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Called by event driven servers like thin and ebb. Returns true if
|
|
44
|
+
# the server should run the request in a separate thread.
|
|
45
|
+
def deferred?( env ) ; Waves.config.resource.new( Waves::Request.new( env ) ).deferred? ; end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def _call( env )
|
|
50
|
+
request = Waves::Request.new( env )
|
|
51
|
+
response = request.response
|
|
52
|
+
t = Benchmark.realtime do
|
|
53
|
+
begin
|
|
54
|
+
safe( request )
|
|
55
|
+
rescue Dispatchers::Redirect => redirect
|
|
56
|
+
response.status = redirect.status
|
|
57
|
+
response.location = redirect.path
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
Waves::Logger.info "#{request.method}: #{request.url} handled in #{(t*1000).round} ms."
|
|
61
|
+
response.finish
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Waves
|
|
2
|
+
|
|
3
|
+
module Dispatchers
|
|
4
|
+
|
|
5
|
+
class Default < Base
|
|
6
|
+
|
|
7
|
+
# Takes a Waves::Request and returns a Waves::Response
|
|
8
|
+
def safe( request )
|
|
9
|
+
# set a default content type -- this can be overridden by the resource
|
|
10
|
+
request.response.content_type = request.accept.default
|
|
11
|
+
resource = Waves.config.resource.new( request )
|
|
12
|
+
if request.response.body.empty?
|
|
13
|
+
request.response.write resource.process.to_s
|
|
14
|
+
else
|
|
15
|
+
resource.process
|
|
16
|
+
end
|
|
17
|
+
# okay, we've handled the request, now write the response unless it was already done
|
|
18
|
+
request.response.finish
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|