public
Description: Run multiple framework / rack app / wathever inside the same VM
Clone URL: git://github.com/macournoyer/rack_sandbox.git
macournoyer (author)
Fri Mar 21 12:51:03 -0700 2008
commit  95167f5720d92c1d2a3a02b9ba5963ac8aaa1cac
tree    7e2e5fa2883cb0730518ab567960c3e1df89d4aa
rack_sandbox / lib / rack / sandbox.rb
100644 63 lines (51 sloc) 1.518 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
require 'sandbox'
require 'sandbox/marshal'
 
module Rack
  class Sandbox
    def initialize(eval_code)
      @box = ::Sandbox.new(:init => :all)
    
      copy_globals
      copy_env
    
      # Load the adapter inside the sandbox
      @box.eval %{
require 'sandbox/binding'
require 'sandbox/marshal'
#{eval_code}
nil
}
    end
    
    def call(env)
      # Remove some values that can't be marshaled
      env.delete('rack.errors')
    
      # Call the adapter inside the sandbox,
      # the response will be marshaled and sent
      # back here in the jungle.
      @box.set :env, env
      @box.eval %{
status, headers, body = app.call(env)
# We ensure the response can be marshaled back to the
# jungle by converting it to a simpler object.
body_output = []
body.each { |l| body_output << l }
[status, headers, body_output]
}
    end
  
    protected
      # Copy some constants and global variables inside the Sandbox
      def copy_globals
        %w(
::File::ALT_SEPARATOR
::File::SEPARATOR
::File::PATH_SEPARATOR
$SAFE
).each { |v| @box.set v, eval(v) }
        # Copy loadpath
        $:.each { |i| @box.eval("$: << #{i.inspect}") }
      end
 
      # Copy the environment variables (+ENV+).
      def copy_env
        @box.set :ENV, {}
        ENV.each { |k,v| @box.eval("ENV[#{k.inspect}] = #{v.inspect}") }
      end
  end
end