macournoyer / thin

A very fast & simple Ruby web server

This URL has Read+Write access

commit  1d1faea0401103e2d16cfb38b19d7fd133053cb5
tree    fbcf407c7fe50067672e6b993de7a5d2af1a398b
parent  8968de296a0edc8a233ae8d7d2717615f0305815
thin / lib / rack / adapter / rails.rb
ed73729b » macournoyer 2008-01-02 Resolving some merge problems 1 require 'cgi'
2
3 # Adapter to run a Rails app with any supported Rack handler.
4 # By default it will try to load the Rails application in the
5 # current directory in the development environment.
13bb5800 » grempe 2008-03-20 Minor documentation change ... 6 #
ed73729b » macournoyer 2008-01-02 Resolving some merge problems 7 # Options:
8 # root: Root directory of the Rails app
13bb5800 » grempe 2008-03-20 Minor documentation change ... 9 # environment: Rails environment to run in (development [default], production or test)
10 # prefix: Set the relative URL root.
11 #
ed73729b » macournoyer 2008-01-02 Resolving some merge problems 12 # Based on http://fuzed.rubyforge.org/ Rails adapter
13 module Rack
14 module Adapter
15 class Rails
1d1faea0 » macournoyer 2008-04-02 Serve static file only on G... 16 FILE_METHODS = %w(GET HEAD).freeze
17
ed73729b » macournoyer 2008-01-02 Resolving some merge problems 18 def initialize(options={})
d0e2e14d » macournoyer 2008-01-13 Add prefix option to thin s... 19 @root = options[:root] || Dir.pwd
20 @env = options[:environment] || 'development'
21 @prefix = options[:prefix]
ed73729b » macournoyer 2008-01-02 Resolving some merge problems 22
23 load_application
24
25 @file_server = Rack::File.new(::File.join(RAILS_ROOT, "public"))
26 end
27
28 def load_application
29 ENV['RAILS_ENV'] = @env
30
31 require "#{@root}/config/environment"
32 require 'dispatcher'
d0e2e14d » macournoyer 2008-01-13 Add prefix option to thin s... 33
34 ActionController::AbstractRequest.relative_url_root = @prefix if @prefix
ed73729b » macournoyer 2008-01-02 Resolving some merge problems 35 end
36
37 # TODO refactor this in File#can_serve?(path) ??
6b31acff » macournoyer 2008-01-06 Add URL rewriting to Rails ... 38 def file_exist?(path)
ed73729b » macournoyer 2008-01-02 Resolving some merge problems 39 full_path = ::File.join(@file_server.root, Utils.unescape(path))
40 ::File.file?(full_path) && ::File.readable?(full_path)
41 end
42
6b31acff » macournoyer 2008-01-06 Add URL rewriting to Rails ... 43 def serve_file(env)
44 @file_server.call(env)
45 end
46
47 def serve_rails(env)
ed73729b » macournoyer 2008-01-02 Resolving some merge problems 48 request = Request.new(env)
49 response = Response.new
50
51 session_options = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS
52 cgi = CGIWrapper.new(request, response)
53
54 Dispatcher.dispatch(cgi, session_options, response)
55
56 response.finish
57 end
6b31acff » macournoyer 2008-01-06 Add URL rewriting to Rails ... 58
59 def call(env)
60 path = env['PATH_INFO'].chomp('/')
1d1faea0 » macournoyer 2008-04-02 Serve static file only on G... 61 method = env['REQUEST_METHOD']
6b31acff » macournoyer 2008-01-06 Add URL rewriting to Rails ... 62 cached_path = (path.empty? ? 'index' : path) + ActionController::Base.page_cache_extension
63
1d1faea0 » macournoyer 2008-04-02 Serve static file only on G... 64 if FILE_METHODS.include?(method)
65 if file_exist?(path) # Serve the file if it's there
66 return serve_file(env)
67 elsif file_exist?(cached_path) # Serve the page cache if it's there
68 env['PATH_INFO'] = cached_path
69 return serve_file(env)
70 end
6b31acff » macournoyer 2008-01-06 Add URL rewriting to Rails ... 71 end
1d1faea0 » macournoyer 2008-04-02 Serve static file only on G... 72
73 # No static file, let Rails handle it
74 serve_rails(env)
6b31acff » macournoyer 2008-01-06 Add URL rewriting to Rails ... 75 end
ed73729b » macournoyer 2008-01-02 Resolving some merge problems 76
77 protected
78
79 class CGIWrapper < ::CGI
80 def initialize(request, response, *args)
81 @request = request
82 @response = response
83 @args = *args
84 @input = request.body
85
86 super *args
87 end
88
89 def header(options = "text/html")
90 if options.is_a?(String)
91 @response['Content-Type'] = options unless @response['Content-Type']
92 else
93 @response['Content-Length'] = options.delete('Content-Length').to_s if options['Content-Length']
94
95 @response['Content-Type'] = options.delete('type') || "text/html"
96 @response['Content-Type'] += "; charset=" + options.delete('charset') if options['charset']
97
98 @response['Content-Language'] = options.delete('language') if options['language']
99 @response['Expires'] = options.delete('expires') if options['expires']
100
101 @response.status = options.delete('Status') if options['Status']
cfd4a7ae » macournoyer 2008-01-05 Fix Set-Cookie headers in R... 102
ed73729b » macournoyer 2008-01-02 Resolving some merge problems 103 # Convert 'cookie' header to 'Set-Cookie' headers.
96ef5249 » macournoyer 2008-01-06 * Fix bug in multiline resp... 104 # Because Set-Cookie header can appear more the once in the response body,
105 # we store it in a line break seperated string that will be translated to
106 # multiple Set-Cookie header by the handler.
cfd4a7ae » macournoyer 2008-01-05 Fix Set-Cookie headers in R... 107 if cookie = options.delete('cookie')
96ef5249 » macournoyer 2008-01-06 * Fix bug in multiline resp... 108 cookies = []
cfd4a7ae » macournoyer 2008-01-05 Fix Set-Cookie headers in R... 109
110 case cookie
96ef5249 » macournoyer 2008-01-06 * Fix bug in multiline resp... 111 when Array then cookie.each { |c| cookies << c.to_s }
112 when Hash then cookie.each { |_, c| cookies << c.to_s }
113 else cookies << cookie.to_s
ed73729b » macournoyer 2008-01-02 Resolving some merge problems 114 end
115
96ef5249 » macournoyer 2008-01-06 * Fix bug in multiline resp... 116 @output_cookies.each { |c| cookies << c.to_s } if @output_cookies
117
118 @response['Set-Cookie'] = [@response['Set-Cookie'], cookies].compact.join("\n")
ed73729b » macournoyer 2008-01-02 Resolving some merge problems 119 end
cfd4a7ae » macournoyer 2008-01-05 Fix Set-Cookie headers in R... 120
121 options.each { |k,v| @response[k] = v }
ed73729b » macournoyer 2008-01-02 Resolving some merge problems 122 end
cfd4a7ae » macournoyer 2008-01-05 Fix Set-Cookie headers in R... 123
ed73729b » macournoyer 2008-01-02 Resolving some merge problems 124 ""
125 end
126
127 def params
128 @params ||= @request.params
129 end
130
131 def cookies
132 @request.cookies
133 end
134
135 def query_string
136 @request.query_string
137 end
138
139 # Used to wrap the normal args variable used inside CGI.
140 def args
141 @args
142 end
143
144 # Used to wrap the normal env_table variable used inside CGI.
145 def env_table
146 @request.env
147 end
148
149 # Used to wrap the normal stdinput variable used inside CGI.
150 def stdinput
151 @input
152 end
153
154 def stdoutput
155 STDERR.puts "stdoutput should not be used."
156 @response.body
157 end
158 end
159 end
160 end
161 end