Take the 2008 Git User's Survey and help out! [ hide ]

ry / ebb fork watch download tarball
public
Description: web server
Homepage: http://ebb.rubyforge.org
Clone URL: git://github.com/ry/ebb.git
Search Repo:
Ryan Dahl (author)
Sun Feb 24 17:46:11 -0800 2008
commit  5b6d59ac6933821590e887157931a712a88e95c4
tree    b8524885e855add8e5223e22b348d3803d4895e1
parent  1fce3d5204583fde37459771e75d65a5f926db26
ebb / ruby_lib / rails_adapter.rb
100644 138 lines (107 sloc) 4.564 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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# This as been submitted to Rack as a patch, tested and everything.
# Bug Christian Neukirchen at chneukirchen@gmail.com to apply the patch!
 
require 'cgi'
require 'rubygems'
require 'rack'
 
# Adapter to run a Rails app with any supported Rack handler.
# By default it will try to load the Rails application in the
# current directory in the development environment.
# Options:
# root: Root directory of the Rails app
# env: Rails environment to run in (development, production or test)
# Based on http://fuzed.rubyforge.org/ Rails adapter
module Rack
  module Adapter
    class Rails
      def initialize(options={})
        @root = options[:root] || Dir.pwd
        @env = options[:env] || 'development'
        
        load_application
        
        @file_server = Rack::File.new(::File.join(RAILS_ROOT, "public"))
      end
      
      def load_application
        ENV['RAILS_ENV'] = @env
 
        require "#{@root}/config/environment"
        require 'dispatcher'
      end
      
      # TODO refactor this in File#can_serve?(path) ??
      def file?(path)
        full_path = ::File.join(@file_server.root, Utils.unescape(path))
        ::File.file?(full_path) && ::File.readable?(full_path)
      end
      
      def call(env)
        # Serve the file if it's there
        return @file_server.call(env) if file?(env['PATH_INFO'])
        
        request = Request.new(env)
        response = Response.new
        
        session_options = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS
        cgi = CGIWrapper.new(request, response)
    
        Dispatcher.dispatch(cgi, session_options, response)
 
        response.finish
      end
    
      protected
        
        class CGIWrapper < ::CGI
          def initialize(request, response, *args)
            @request = request
            @response = response
            @args = *args
            @input = request.body
 
            super *args
          end
        
          def header(options = "text/html")
            if options.is_a?(String)
              @response['Content-Type'] = options unless @response['Content-Type']
            else
              @response['Content-Length'] = options.delete('Content-Length').to_s if options['Content-Length']
            
              @response['Content-Type'] = options.delete('type') || "text/html"
              @response['Content-Type'] += "; charset=" + options.delete('charset') if options['charset']
                        
              @response['Content-Language'] = options.delete('language') if options['language']
              @response['Expires'] = options.delete('expires') if options['expires']
 
              @response.status = options.delete('Status') if options['Status']
        
              options.each { |k,v| @response[k] = v }
            
              # Convert 'cookie' header to 'Set-Cookie' headers.
              # According to http://www.faqs.org/rfcs/rfc2109.html:
              # the Set-Cookie response header comprises the token
              # Set-Cookie:, followed by a comma-separated list of
              # one or more cookies.
              if cookie = @response.header.delete('Cookie')
                cookies = case cookie
                  when Array then cookie.collect { |c| c.to_s }.join(', ')
                  when Hash then cookie.collect { |_, c| c.to_s }.join(', ')
                  else cookie.to_s
                end
        
                cookies << ', ' + @output_cookies.each { |c| c.to_s }.join(', ') if @output_cookies
                
                @response['Set-Cookie'] = cookies
              end
            end
        
            ""
          end
                        
          def params
            @params ||= @request.params
          end
        
          def cookies
            @request.cookies
          end
        
          def query_string
            @request.query_string
          end
          
          # Used to wrap the normal args variable used inside CGI.
          def args
            @args
          end
    
          # Used to wrap the normal env_table variable used inside CGI.
          def env_table
            @request.env
          end
    
          # Used to wrap the normal stdinput variable used inside CGI.
          def stdinput
            @input
          end
        
          def stdoutput
            STDERR.puts "stdoutput should not be used."
            @response.body
          end
      end
    end
  end
end