nitro 0.27.0 → 0.28.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +276 -0
- data/ProjectInfo +4 -4
- data/README +9 -1
- data/Rakefile +1 -1
- data/doc/AUTHORS +30 -17
- data/doc/RELEASES +110 -23
- data/lib/glue/sweeper.rb +1 -1
- data/lib/glue/webfile.rb +1 -1
- data/lib/nitro.rb +1 -1
- data/lib/nitro/adapter/acgi.rb +5 -1
- data/lib/nitro/adapter/cgi.rb +4 -0
- data/lib/nitro/adapter/fastcgi.rb +12 -1
- data/lib/nitro/adapter/mongrel.rb +219 -0
- data/lib/nitro/adapter/scgi.rb +62 -69
- data/lib/nitro/caching.rb +6 -5
- data/lib/nitro/caching/actions.rb +14 -8
- data/lib/nitro/caching/fragments.rb +32 -17
- data/lib/nitro/caching/output.rb +10 -2
- data/lib/nitro/cgi.rb +7 -3
- data/lib/nitro/cgi/stream.rb +1 -3
- data/lib/nitro/compiler.rb +5 -4
- data/lib/nitro/compiler/errors.rb +1 -1
- data/lib/nitro/compiler/morphing.rb +2 -2
- data/lib/nitro/compiler/script.rb +1 -1
- data/lib/nitro/context.rb +8 -2
- data/lib/nitro/controller.rb +1 -1
- data/lib/nitro/dispatcher.rb +0 -2
- data/lib/nitro/element.rb +5 -5
- data/lib/nitro/flash.rb +1 -1
- data/lib/nitro/helper.rb +2 -2
- data/lib/nitro/helper/form.rb +1 -1
- data/lib/nitro/helper/form/controls.rb +2 -1
- data/lib/nitro/helper/javascript.rb +1 -1
- data/lib/nitro/helper/javascript/morphing.rb +1 -1
- data/lib/nitro/helper/layout.rb +1 -1
- data/lib/nitro/helper/pager.rb +7 -3
- data/lib/nitro/helper/rss.rb +1 -1
- data/lib/nitro/render.rb +1 -1
- data/lib/nitro/scaffolding.rb +26 -4
- data/lib/nitro/server/drb.rb +106 -0
- data/lib/nitro/server/runner.rb +23 -2
- data/lib/nitro/session.rb +33 -16
- data/lib/nitro/session/drb.rb +6 -20
- data/lib/nitro/session/file.rb +4 -49
- data/lib/nitro/session/memory.rb +16 -0
- data/lib/nitro/session/og.rb +4 -46
- data/src/part/admin/controller.rb +2 -3
- data/src/part/admin/template/index.xhtml +1 -1
- data/test/nitro/tc_cgi.rb +72 -3
- data/test/nitro/tc_render.rb +1 -1
- data/test/nitro/tc_session.rb +16 -15
- metadata +12 -14
- data/lib/nitro/caching/invalidation.rb +0 -25
- data/lib/nitro/caching/stores.rb +0 -94
- data/lib/nitro/helper/form/test.xhtml +0 -0
- data/lib/nitro/session/drbserver.rb +0 -84
@@ -0,0 +1,106 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'drb'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
require 'facet/synchash'
|
7
|
+
|
8
|
+
require 'glue'
|
9
|
+
require 'glue/cache/memory'
|
10
|
+
|
11
|
+
module Nitro
|
12
|
+
|
13
|
+
# A Drb server, typically used to host the application caches
|
14
|
+
# (sessions, application scoped variables, og cache, fragment
|
15
|
+
# cache, etc).
|
16
|
+
#
|
17
|
+
# === Example
|
18
|
+
#
|
19
|
+
# require 'nitro/server/drb
|
20
|
+
#
|
21
|
+
# class MyDrbServer < Nitro::DrbServer
|
22
|
+
# def setup_drb_objects
|
23
|
+
# ...
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# MyDrbServer.start
|
28
|
+
#--
|
29
|
+
# FIXME: should probably move to another directory (scripts?)
|
30
|
+
# TODO: Add some debuging support (overload synchash).
|
31
|
+
# TODO: Implement MemcacheServer.
|
32
|
+
# TODO: Better start/stop functionality.
|
33
|
+
#++
|
34
|
+
|
35
|
+
class DrbServer
|
36
|
+
|
37
|
+
# Parse the command line arguments.
|
38
|
+
|
39
|
+
def parse_options
|
40
|
+
parser = OptionParser.new do |opts|
|
41
|
+
opts.banner = "Usage: #$0 [options]"
|
42
|
+
opts.separator ''
|
43
|
+
opts.separator 'Specific options:'
|
44
|
+
|
45
|
+
opts.on('-D', '--debug', 'Run in debug mode.') do |p|
|
46
|
+
@debug = true
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on('-d', '--daemon', 'Run as daemon.') do |p|
|
50
|
+
@daemon = true
|
51
|
+
end
|
52
|
+
|
53
|
+
opts.on_tail('-h', '--help', 'Show this message.') do
|
54
|
+
puts opts
|
55
|
+
exit
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
begin
|
60
|
+
parser.parse!(ARGV)
|
61
|
+
rescue OptionParser::InvalidOption
|
62
|
+
puts 'Invalid option, pass the --help parameter to get help!'
|
63
|
+
exit
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Override in your application to setup your custom objects.
|
68
|
+
# The default implementation only creates a session store.
|
69
|
+
|
70
|
+
def setup_drb_objects
|
71
|
+
require 'nitro/session'
|
72
|
+
@session_cache = SyncHash.new
|
73
|
+
DRb.start_service("druby://#{Session.cache_address}:#{Session.cache_port}", @session_cache)
|
74
|
+
puts "Drb session cache at druby://#{Session.cache_address}:#{Session.cache_port}."
|
75
|
+
end
|
76
|
+
|
77
|
+
def setup_drb
|
78
|
+
setup_drb_objects()
|
79
|
+
DRb.thread.join
|
80
|
+
end
|
81
|
+
|
82
|
+
# Start the DRb server.
|
83
|
+
|
84
|
+
def start
|
85
|
+
parse_options
|
86
|
+
if @daemon
|
87
|
+
require 'daemons/daemonize'
|
88
|
+
Daemonize.daemonize()
|
89
|
+
end
|
90
|
+
setup_drb()
|
91
|
+
end
|
92
|
+
alias_method :start!, :start
|
93
|
+
|
94
|
+
# A helper method to start the DRb server.
|
95
|
+
|
96
|
+
def self.start
|
97
|
+
self.new.start
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
DrbServer.start if __FILE__ == $0
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
# * George Moschovitis <gm@navel.gr>
|
data/lib/nitro/server/runner.rb
CHANGED
@@ -3,7 +3,7 @@ require 'optparse'
|
|
3
3
|
require 'glue/configuration'
|
4
4
|
require 'nitro/compiler'
|
5
5
|
|
6
|
-
#require '
|
6
|
+
#require 'facet/kernel/autoreload'
|
7
7
|
require 'glue/autoreload'
|
8
8
|
|
9
9
|
module Nitro
|
@@ -128,6 +128,11 @@ class Runner
|
|
128
128
|
@server = :webrick
|
129
129
|
end
|
130
130
|
|
131
|
+
opts.on('-m', '--mongrel', 'Use the Mongrel Ruby server.') do
|
132
|
+
@server = :mongrel
|
133
|
+
# FIXME: handle logging.
|
134
|
+
end
|
135
|
+
|
131
136
|
opts.on('-l', '--lhttpd', 'Use a lighttpd server (FastCGI).') do
|
132
137
|
@server = :lhttpd
|
133
138
|
Logger.set(Logger.new('log/app.log'))
|
@@ -147,6 +152,10 @@ class Runner
|
|
147
152
|
@server = :cgi
|
148
153
|
Logger.set(Logger.new('log/app.log'))
|
149
154
|
end
|
155
|
+
|
156
|
+
opts.on('--scgi', 'Use the generic SCGI adapter') do
|
157
|
+
@server = :scgi
|
158
|
+
end
|
150
159
|
|
151
160
|
opts.on('-C', '--console', 'Start a console attached to an instance of the application.') do
|
152
161
|
if RUBY_PLATFORM =~ /mswin32/
|
@@ -307,10 +316,17 @@ class Runner
|
|
307
316
|
case @server
|
308
317
|
when :webrick
|
309
318
|
require 'nitro/adapter/webrick'
|
310
|
-
puts "==> Listening at #{server.address}:#{server.port}."
|
319
|
+
puts "==> Listening at #{server.address}:#{server.port}. [WEBRICK]"
|
311
320
|
puts "==> Press Ctrl-C to shutdown; Run with --help for options.\n\n"
|
312
321
|
Webrick.start(server)
|
313
322
|
|
323
|
+
when :mongrel
|
324
|
+
require 'nitro/adapter/mongrel'
|
325
|
+
puts "==> Listening at #{server.address}:#{server.port}. [MONGREL]"
|
326
|
+
puts "==> Press Ctrl-C to shutdown; Run with --help for options.\n\n"
|
327
|
+
|
328
|
+
Mongrel.start(server)
|
329
|
+
|
314
330
|
when :lhttpd
|
315
331
|
require 'nitro/adapter/fastcgi'
|
316
332
|
puts "==> Launching lighttpd (FastCGI)."
|
@@ -329,6 +345,11 @@ class Runner
|
|
329
345
|
when :cgi
|
330
346
|
require 'nitro/adapter/cgi'
|
331
347
|
puts "==> Using standard CGI. Please look into using Fast/Scgi"
|
348
|
+
|
349
|
+
|
350
|
+
when :scgi
|
351
|
+
require 'nitro/adapter/scgi'
|
352
|
+
SCGI.start(server)
|
332
353
|
|
333
354
|
when :acgi
|
334
355
|
require 'nitro/adapter/acgi'
|
data/lib/nitro/session.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'md5'
|
2
2
|
require 'webrick'
|
3
3
|
|
4
|
-
require '
|
5
|
-
require '
|
4
|
+
require 'facet/synchash'
|
5
|
+
require 'facet/times'
|
6
6
|
|
7
|
+
require 'glue'
|
7
8
|
require 'glue/attribute'
|
8
9
|
require 'glue/configuration'
|
9
10
|
require 'glue/logger'
|
@@ -24,7 +25,10 @@ module Nitro
|
|
24
25
|
# The session should be persistable to survive server
|
25
26
|
# shutdowns.
|
26
27
|
#
|
27
|
-
|
28
|
+
#--
|
29
|
+
# TODO: rehash of the session cookie
|
30
|
+
# TODO: store -> cache, reimplement helpers.
|
31
|
+
#++
|
28
32
|
|
29
33
|
class Session < Hash
|
30
34
|
include Expirable
|
@@ -45,15 +49,23 @@ class Session < Hash
|
|
45
49
|
# garbage collection after this time passes.
|
46
50
|
|
47
51
|
setting :keepalive, :default => 30.minutes, :doc => 'The session keepalive time'
|
52
|
+
|
53
|
+
# The address of the Session cache / store (if distibuted).
|
54
|
+
|
55
|
+
setting :cache_address, :default => '127.0.0.1', :doc => 'The address of the Session cache'
|
48
56
|
|
49
|
-
# The
|
57
|
+
# The port of the Session DRb cache / store (if distributed).
|
58
|
+
|
59
|
+
setting :cache_port, :default => 9069, :doc => 'The port of the Session cache'
|
50
60
|
|
51
|
-
|
61
|
+
# The sessions cache (store).
|
62
|
+
|
63
|
+
cattr_accessor :cache
|
52
64
|
|
53
65
|
class << self
|
54
66
|
|
55
|
-
# Set the session
|
56
|
-
# available:
|
67
|
+
# Set the session cache. The generalized caching system in
|
68
|
+
# Glue is used. The following options are available:
|
57
69
|
#
|
58
70
|
# * :memory [default]
|
59
71
|
# * :drb
|
@@ -61,20 +73,22 @@ class Session < Hash
|
|
61
73
|
# * :file (not safe yet with multiple process as in fastcgi)
|
62
74
|
# * :memcached (not available yet)
|
63
75
|
|
64
|
-
def
|
76
|
+
def cache_type=(cache_type)
|
65
77
|
# gmosx: RDoc friendly.
|
66
|
-
require 'nitro/session/' +
|
78
|
+
require 'nitro/session/' + cache_type.to_s
|
67
79
|
end
|
68
|
-
alias_method :
|
80
|
+
alias_method :set_cache_type, :cache_type=
|
81
|
+
alias_method :store_type=, :cache_type=
|
82
|
+
alias_method :set_store_type, :cache_type=
|
69
83
|
|
70
|
-
# Lookup the session in the
|
84
|
+
# Lookup the session in the cache by using the session
|
71
85
|
# cookie value as a key. If the session does not exist
|
72
|
-
# creates a new session, inserts it in the
|
86
|
+
# creates a new session, inserts it in the cache and
|
73
87
|
# appends a new session cookie in the response.
|
74
88
|
|
75
89
|
def lookup(context)
|
76
90
|
if session_id = context.cookies[Session.cookie_name]
|
77
|
-
session = Session.
|
91
|
+
session = Session.cache[session_id]
|
78
92
|
end
|
79
93
|
|
80
94
|
unless session
|
@@ -85,7 +99,7 @@ class Session < Hash
|
|
85
99
|
cookie.expires = Time.now + Session.keepalive
|
86
100
|
end
|
87
101
|
context.add_cookie(cookie)
|
88
|
-
Session.
|
102
|
+
Session.cache[session.session_id] = session
|
89
103
|
else
|
90
104
|
# Access ('touch') the existing session.
|
91
105
|
session.touch!
|
@@ -101,7 +115,7 @@ class Session < Hash
|
|
101
115
|
# gmosx: should be placed here.
|
102
116
|
#++
|
103
117
|
|
104
|
-
|
118
|
+
set_cache_type(:memory)
|
105
119
|
|
106
120
|
# The unique id of this session.
|
107
121
|
|
@@ -123,7 +137,7 @@ class Session < Hash
|
|
123
137
|
# in distributed and/or multiprocess setups.
|
124
138
|
|
125
139
|
def sync
|
126
|
-
Session.
|
140
|
+
Session.cache[@session_id] = self
|
127
141
|
end
|
128
142
|
alias_method :restore, :sync
|
129
143
|
|
@@ -139,6 +153,9 @@ protected
|
|
139
153
|
# increasing function like time is appropriate.
|
140
154
|
# Random may produce equal ids? add a prefix
|
141
155
|
# (SALT) to stop hackers from creating session_ids.
|
156
|
+
#--
|
157
|
+
# THINK: Is MD5 slow???
|
158
|
+
#++
|
142
159
|
|
143
160
|
def create_id
|
144
161
|
now = Time.now
|
data/lib/nitro/session/drb.rb
CHANGED
@@ -1,28 +1,14 @@
|
|
1
|
-
require 'drb'
|
2
|
-
|
3
|
-
require 'glue/configuration'
|
1
|
+
require 'glue/cache/drb'
|
4
2
|
require 'nitro/session'
|
5
3
|
|
6
|
-
Logger.debug 'Using Drb sessions.'
|
7
|
-
|
8
4
|
module Nitro
|
9
5
|
|
10
|
-
|
11
|
-
|
12
|
-
# The address of the Session DRb server.
|
13
|
-
|
14
|
-
setting :drb_address, :default => '127.0.0.1', :doc => 'The address of the Session DRb server'
|
15
|
-
|
16
|
-
# The port of the Session DRb server.
|
17
|
-
|
18
|
-
setting :drb_port, :default => 9069, :doc => 'The port of the Session DRb server'
|
19
|
-
|
20
|
-
end
|
6
|
+
Logger.debug "Using DRb sessions at #{Session.cache_address}:#{Session.cache_port}."
|
21
7
|
|
22
|
-
Session.
|
23
|
-
|
24
|
-
|
25
|
-
)
|
8
|
+
Session.cache = DrbCache.new(
|
9
|
+
:address => Session.cache_address,
|
10
|
+
:port => Session.cache_port
|
11
|
+
)
|
26
12
|
|
27
13
|
end
|
28
14
|
|
data/lib/nitro/session/file.rb
CHANGED
@@ -1,59 +1,14 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'glue/cache/file'
|
3
2
|
require 'nitro/session'
|
4
|
-
require 'fileutils'
|
5
|
-
require 'tmpdir'
|
6
3
|
|
7
4
|
module Nitro
|
8
5
|
|
9
|
-
|
10
|
-
#
|
11
|
-
# TODO: safe locking of files, because Nitro can be multiprocess
|
12
|
-
|
13
|
-
class FileSessionStore
|
14
|
-
setting :path, :default => "#{Dir.tmpdir}/nitro_session_#{Session.cookie_name}", :doc => 'The directory to store file session'
|
15
|
-
|
16
|
-
def initialize
|
17
|
-
@path = FileSessionStore.path
|
18
|
-
FileUtils.mkdir_p(@path)
|
19
|
-
end
|
20
|
-
|
21
|
-
def []=(k,v)
|
22
|
-
fn = File.join(@path, k.to_s)
|
23
|
-
encode_file(fn, v)
|
24
|
-
end
|
25
|
-
|
26
|
-
def [](k)
|
27
|
-
fn = File.join(@path, k.to_s)
|
28
|
-
return nil unless File.exists?(fn)
|
29
|
-
decode_file(fn)
|
30
|
-
end
|
31
|
-
|
32
|
-
def gc!
|
33
|
-
now = Time.now
|
34
|
-
all.each do |fn|
|
35
|
-
expire_time = File.stat(fn).atime + Session.keepalive
|
36
|
-
File.delete(fn) if now > expire_time
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def all
|
41
|
-
Dir.glob( File.join(@path, '*' ) )
|
42
|
-
end
|
43
|
-
|
44
|
-
private
|
45
|
-
|
46
|
-
def decode_file(fn)
|
47
|
-
Marshal.load( File.read(fn) )
|
48
|
-
end
|
6
|
+
# A Session manager that persists sessions on disk.
|
49
7
|
|
50
|
-
|
51
|
-
File.open(fn, "w") { |f| f.write(Marshal.dump(value)) }
|
52
|
-
end
|
8
|
+
Logger.debug "Using File sessions."
|
53
9
|
|
54
|
-
|
10
|
+
Session.cache = FileCache.new("session_#{Session.cookie_name}", Session.keepalive)
|
55
11
|
|
56
|
-
Session.store = FileSessionStore.new
|
57
12
|
end
|
58
13
|
|
59
14
|
# * Guillaume Pierronnet <guillaume.pierronnet@gmail.com>
|
data/lib/nitro/session/memory.rb
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
require 'glue/cache/memory'
|
2
|
+
require 'nitro/session'
|
3
|
+
|
4
|
+
module Nitro
|
5
|
+
|
6
|
+
Logger.debug "Using Memory sessions."
|
7
|
+
|
8
|
+
Session.cache = MemoryCache.new
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
# * George Moschovitis <gm@navel.gr>
|
13
|
+
|
14
|
+
=begin
|
15
|
+
|
1
16
|
module Nitro
|
2
17
|
|
3
18
|
class MemorySessionStore < SyncHash
|
@@ -18,3 +33,4 @@ module Nitro
|
|
18
33
|
end
|
19
34
|
|
20
35
|
# * George Moschovitis <gm@navel.gr>
|
36
|
+
=end
|
data/lib/nitro/session/og.rb
CHANGED
@@ -1,56 +1,14 @@
|
|
1
|
-
require 'og'
|
1
|
+
require 'glue/cache/og'
|
2
2
|
require 'nitro/session'
|
3
|
-
require 'base64'
|
4
3
|
|
5
4
|
module Nitro
|
6
5
|
|
7
|
-
|
8
|
-
prop_accessor :sessionid, String
|
9
|
-
prop_accessor :expires, Time
|
10
|
-
prop_accessor :content
|
11
|
-
end
|
6
|
+
# A Session manager that persists sessions on an Og store.
|
12
7
|
|
13
|
-
|
14
|
-
|
15
|
-
class OgSessionStore
|
8
|
+
Logger.debug "Using Og sessions."
|
16
9
|
|
17
|
-
|
18
|
-
unless s = OgSession.find_by_sessionid(k.to_s)
|
19
|
-
s = OgSession.new
|
20
|
-
s.sessionid = k.to_s
|
21
|
-
end
|
22
|
-
#s.content = v.to_yaml
|
23
|
-
s.content = encode(v)
|
24
|
-
s.save
|
25
|
-
end
|
10
|
+
Session.cache = OgCache.new("session_#{Session.cookie_name}", Session.keepalive)
|
26
11
|
|
27
|
-
def [](k)
|
28
|
-
s = OgSession.find_by_sessionid(k.to_s) and decode(s.content)
|
29
|
-
end
|
30
|
-
|
31
|
-
def gc!
|
32
|
-
now = Og.manager.store.quote(Time.now)
|
33
|
-
OgSession.find(:condition => "expires < #{now}").each {|s| s.delete }
|
34
|
-
end
|
35
|
-
|
36
|
-
def all
|
37
|
-
OgSession.all
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def encode(c)
|
43
|
-
Base64.encode64(Marshal.dump(c))
|
44
|
-
end
|
45
|
-
|
46
|
-
def decode(c)
|
47
|
-
Marshal::load(Base64.decode64(c))
|
48
|
-
#s.content = YAML::load(s.content)
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|
52
|
-
|
53
|
-
Session.store = OgSessionStore.new
|
54
12
|
end
|
55
13
|
|
56
14
|
# * Guillaume Pierronnet <guillaume.pierronnet@gmail.com>
|