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)
Tue Feb 26 16:43:06 -0800 2008
commit  85308837b343711aa4fbd9777bf7fb2bd8f5a033
tree    e8eba3698f96ac4c60515b96cc891d8d5f6e2370
parent  9c5ab1c13e9097b4f25bd84a4d25c563a51a4eba
ebb / ruby_lib / rails_adapter.rb
100644 134 lines (103 sloc) 4.068 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
# 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
class RailsAdapter
  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