ajp-rails 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +504 -0
- data/Install.en +231 -0
- data/Install.ja +250 -0
- data/NEWS.en +6 -0
- data/NEWS.ja +6 -0
- data/README.en +80 -0
- data/README.ja +77 -0
- data/Rakefile +22 -0
- data/ajp-rails.gemspec +24 -0
- data/bin/ajp-rails.rb +4 -0
- data/example/example.config.yml +5 -0
- data/example/example.htaccess +30 -0
- data/example/example.workers.proerties +11 -0
- data/lib/ajp-rails/ajp_rails_dispatcher.rb +40 -0
- data/lib/ajp-rails/rails-runner.rb +162 -0
- data/lib/ajp-rails/rails-wrapper.rb +289 -0
- data/setup.rb +1585 -0
- metadata +64 -0
data/bin/ajp-rails.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
# Assumes that follwing are set in ServerConfig or VirtualHost
|
3
|
+
# JkMount /ajp-mounted/* ajprails
|
4
|
+
# JkEnvVar SERVER_SOFTWARE NONE
|
5
|
+
|
6
|
+
|
7
|
+
Options +FollowSymLinks
|
8
|
+
|
9
|
+
# If you don't want Rails to look in certain directories,
|
10
|
+
# use the following rewrite rules so that Apache won't rewrite certain requests
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
# RewriteCond %{REQUEST_URI} ^/notrails.*
|
14
|
+
# RewriteRule .* - [L]
|
15
|
+
|
16
|
+
# Redirect all requests not available on the filesystem to Rails
|
17
|
+
RewriteEngine On
|
18
|
+
RewriteBase /example
|
19
|
+
RewriteRule ^$ index.html [QSA]
|
20
|
+
RewriteRule ^([^.]+)$ $1.html [QSA]
|
21
|
+
RewriteCond %{REQUEST_FILENAME} !-f
|
22
|
+
RewriteRule ^(.*)$ /ajp-mounted/$1 [QSA,L]
|
23
|
+
|
24
|
+
# In case Rails experiences terminal errors
|
25
|
+
# Instead of displaying this message you can supply a file here which will be rendered instead
|
26
|
+
#
|
27
|
+
# Example:
|
28
|
+
# ErrorDocument 500 /500.html
|
29
|
+
|
30
|
+
ErrorDocument 500 "<h2>Application error</h2>Rails application failed to start properly"
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'dispatcher'
|
2
|
+
require 'net/ajp13/server'
|
3
|
+
require File.dirname(__FILE__) + File::SEPARATOR + 'rails-wrapper.rb'
|
4
|
+
|
5
|
+
class AjpRailsDispatcher < Dispatcher
|
6
|
+
class << self
|
7
|
+
# Dispatch the given AJP request, using the given session options, and
|
8
|
+
# returns the response object.
|
9
|
+
#--
|
10
|
+
# Be sure to handle the exceptions it raises
|
11
|
+
# on multipart requests (EOFError and ArgumentError).
|
12
|
+
#++
|
13
|
+
def dispatch(ajp_req, session_options, server_environments)
|
14
|
+
request = AjpRailsRequest.new(ajp_req, session_options, server_environments)
|
15
|
+
response = AjpRailsResponse.new
|
16
|
+
prepare_application
|
17
|
+
ActionController::Routing::Routes.recognize!(request).process(request, response).to_ajp_response(ajp_req.output_cookies)
|
18
|
+
rescue Object => exception
|
19
|
+
puts exception.message + ":" + exception.backtrace.join("\n")
|
20
|
+
failsafe_response(500) do
|
21
|
+
ActionController::Base.process_with_exception(request, AjpRailsResponse.new, exception).to_ajp_response(ajp_req.output_cookies)
|
22
|
+
end
|
23
|
+
ensure
|
24
|
+
# Do not give a failsafe response here.
|
25
|
+
reset_after_dispatch
|
26
|
+
end
|
27
|
+
|
28
|
+
# If the block raises, send status code as a last-ditch response.
|
29
|
+
def failsafe_response(status)
|
30
|
+
yield
|
31
|
+
rescue Object
|
32
|
+
begin
|
33
|
+
Net::AJP13::Response.new(status)
|
34
|
+
rescue Object
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
@@ -0,0 +1,162 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2006 Yugui <yugui@yugui.sakura.ne.jp>
|
3
|
+
#
|
4
|
+
# This program is free software; you can redistribute it and/or
|
5
|
+
# modify it under the terms of the GNU Lesser General Public
|
6
|
+
# License as published by the Free Software Foundation; version 2.1
|
7
|
+
# of the License
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this program; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
17
|
+
#++
|
18
|
+
require 'rubygems' rescue nil
|
19
|
+
require 'optparse'
|
20
|
+
require File.dirname(__FILE__) + File::SEPARATOR + 'ajp_rails_dispatcher.rb'
|
21
|
+
|
22
|
+
#
|
23
|
+
# AJP server that dispatches AJP requests into Rails.
|
24
|
+
#
|
25
|
+
class RailsRunner < Net::AJP13::Server
|
26
|
+
# +option+:: Hash which contains server-wide options.
|
27
|
+
def initialize(options)
|
28
|
+
super(options['BIND_IP'], options['AJP_PORT'])
|
29
|
+
@environment_options = options
|
30
|
+
end
|
31
|
+
|
32
|
+
# Dispatches +request+ into Rails and returns Net::AJP13::Response object
|
33
|
+
# which contains the result of Rails processing.
|
34
|
+
#
|
35
|
+
# +request+:: Net::AJP13::Request object
|
36
|
+
def process_request(request)
|
37
|
+
logger.debug("processing #{request.path}")
|
38
|
+
response = AjpRailsDispatcher.dispatch(request, AjpRailsRequest::DEFAULT_SESSION_OPTIONS, @environment_options)
|
39
|
+
logger.debug("processed #{request.path}: #{response.code} #{response.message}")
|
40
|
+
response
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Maps long option names to internal hash keys.
|
45
|
+
OPTION_NAMES_TO_INTERNAL_NAMES = {
|
46
|
+
'port' => 'AJP_PORT',
|
47
|
+
'host' => 'BIND_IP',
|
48
|
+
'environment' => 'RAILS_ENV',
|
49
|
+
'location' => 'APP_LOCATION',
|
50
|
+
'directory' => 'APP_DIRECTORY',
|
51
|
+
'prefix' => 'DISPATCHER_PREFIX',
|
52
|
+
'suffix' => 'DISPATCHER_SUFFIX',
|
53
|
+
'daemon' => 'IS_DAEMON'
|
54
|
+
}
|
55
|
+
|
56
|
+
DEFAULT_OPTIONS = {
|
57
|
+
OPTION_NAMES_TO_INTERNAL_NAMES['environment'] =>
|
58
|
+
ENV['RAILS_ENV'] || 'production',
|
59
|
+
OPTION_NAMES_TO_INTERNAL_NAMES['port'] => Net::AJP13::Constants::DEFAULT_PORT,
|
60
|
+
OPTION_NAMES_TO_INTERNAL_NAMES['host'] => '127.0.0.1',
|
61
|
+
OPTION_NAMES_TO_INTERNAL_NAMES['location'] => '/',
|
62
|
+
OPTION_NAMES_TO_INTERNAL_NAMES['directory'] => '.'
|
63
|
+
}
|
64
|
+
|
65
|
+
# Parses command line options.
|
66
|
+
#
|
67
|
+
# Merges external configuration file into DEFAULT_OPTIONS if a file specified,
|
68
|
+
# and merges command line options, and returns merged options.
|
69
|
+
#
|
70
|
+
def parse_options
|
71
|
+
opts = DEFAULT_OPTIONS.dup
|
72
|
+
|
73
|
+
cmd_opts = {}
|
74
|
+
parser = OptionParser.new
|
75
|
+
parser.on('-p PORT', '--port=PORT',
|
76
|
+
"Listens to the specified port.\n" +
|
77
|
+
"Default: #{opts[OPTION_NAMES_TO_INTERNAL_NAMES['port']]}") { |v|
|
78
|
+
cmd_opts[OPTION_NAMES_TO_INTERNAL_NAMES['port']] = v
|
79
|
+
}
|
80
|
+
parser.on('-h IP', '--host=IP',
|
81
|
+
"Binds rails to the specified ip.\n" +
|
82
|
+
"Default: #{opts[OPTION_NAMES_TO_INTERNAL_NAMES['host']]}") {
|
83
|
+
cmd_opts[OPTION_NAMES_TO_INTERNAL_NAMES['host']] = v
|
84
|
+
}
|
85
|
+
parser.on('-e RAILS_ENV', '--environment=RAILS_ENV',
|
86
|
+
"Specifies the environment to run this server under (test/development/production).\n" +
|
87
|
+
"Default: ENV['RAILS_ENV'] || 'production'") { |v|
|
88
|
+
cmd_opts[OPTION_NAMES_TO_INTERNAL_NAMES['environment']] = v
|
89
|
+
}
|
90
|
+
parser.on('-l LOCATION', '--location=LOCATION',
|
91
|
+
"The base of the application's virtual path.\n" +
|
92
|
+
"Default: /") { |v|
|
93
|
+
cmd_opts[OPTION_NAMES_TO_INTERNAL_NAMES['location']] = v
|
94
|
+
}
|
95
|
+
parser.on('-d DIRECTORY', '--directory=DIRECTORY',
|
96
|
+
"The base of the application's physical path\n" +
|
97
|
+
"Default: #{opts[OPTION_NAMES_TO_INTERNAL_NAMES['directory']]}") { |v|
|
98
|
+
cmd_opts[OPTION_NAMES_TO_INTERNAL_NAMES['directory']] = v
|
99
|
+
}
|
100
|
+
parser.on('--prefix=PREFIX',
|
101
|
+
"The prefix of the ajp-mounted URLs.") { |v|
|
102
|
+
cmd_opts[OPTION_NAMES_TO_INTERNAL_NAMES['prefix']] = v
|
103
|
+
}
|
104
|
+
parser.on('--suffix=SUFFIX',
|
105
|
+
"The suffix of the ajp-mounted URLs.") { |v|
|
106
|
+
cmd_opts[OPTION_NAMES_TO_INTERNAL_NAMES['suffix']] = v
|
107
|
+
}
|
108
|
+
parser.on('--daemon', "Makes Rails run as a daemon") {|v|
|
109
|
+
cmd_opts[OPTION_NAMES_TO_INTERNAL_NAMES['daemon']] = v
|
110
|
+
}
|
111
|
+
|
112
|
+
parser.on('-c FILE', '--config=FILE',
|
113
|
+
'Reads options from the specified file. ' +
|
114
|
+
'The file must be YAML file.') {|value|
|
115
|
+
cmd_opts['config'] = value
|
116
|
+
}
|
117
|
+
parser.parse(ARGV)
|
118
|
+
|
119
|
+
if path = cmd_opts['config']
|
120
|
+
cmd_opts.delete('config')
|
121
|
+
if FileTest::file? path then
|
122
|
+
require 'yaml'
|
123
|
+
YAML.load_file(path).each do |key, value|
|
124
|
+
name = OPTION_NAMES_TO_INTERNAL_NAMES[key]
|
125
|
+
opts[name || key] = value
|
126
|
+
end
|
127
|
+
else
|
128
|
+
warn("Not a exsiting regular file: #{path}")
|
129
|
+
exit(1)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
opts.merge(cmd_opts)
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
options = parse_options
|
138
|
+
|
139
|
+
if is_daemon = options[OPTION_NAMES_TO_INTERNAL_NAMES['daemon']]
|
140
|
+
options.delete(OPTION_NAMES_TO_INTERNAL_NAMES['daemon'])
|
141
|
+
|
142
|
+
exit if Process.fork
|
143
|
+
Process.setsid
|
144
|
+
exit if Process.fork
|
145
|
+
File.umask(0)
|
146
|
+
end
|
147
|
+
|
148
|
+
raise if defined?(RAILS_ENV)
|
149
|
+
::RAILS_ENV = options['RAILS_ENV'].dup
|
150
|
+
|
151
|
+
Dir.chdir options[OPTION_NAMES_TO_INTERNAL_NAMES['directory']]
|
152
|
+
require 'config/environment'
|
153
|
+
|
154
|
+
if is_daemon
|
155
|
+
Dir.chdir('/')
|
156
|
+
STDIN.reopen('/dev/null')
|
157
|
+
STDOUT.reopen('/dev/null', 'w')
|
158
|
+
STDERR.reopen('/dev/null', 'w')
|
159
|
+
end
|
160
|
+
|
161
|
+
runner = RailsRunner.new(options)
|
162
|
+
runner.start
|
@@ -0,0 +1,289 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2004 David Heinemeier Hansson
|
3
|
+
# Copyright (c) 2006 Yugui <yugui@yugui.sakura.ne.jp>
|
4
|
+
#
|
5
|
+
# This program is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License as published by the Free Software Foundation; version 2.1
|
8
|
+
# of the License
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
# Lesser General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
16
|
+
# License along with this program; if not, write to the Free Software
|
17
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
18
|
+
#
|
19
|
+
#--
|
20
|
+
#
|
21
|
+
# AjpRailsRequest is based on lib/action_controller/cgi_process.rb which is
|
22
|
+
# distributed as a port of actionpack 1.1.12.
|
23
|
+
# The original file is avaiable here;
|
24
|
+
# http://rubyforge.org/frs/?group_id=249&release_id=3791
|
25
|
+
#
|
26
|
+
# The following is the permission notice of the original
|
27
|
+
# lib/action_controller/cgi_process.rb, not for this script.
|
28
|
+
#
|
29
|
+
# --
|
30
|
+
# Copyright (c) 2004 David Heinemeier Hansson
|
31
|
+
#
|
32
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
33
|
+
# a copy of this software and associated documentation files (the
|
34
|
+
# "Software"), to deal in the Software without restriction, including
|
35
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
36
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
37
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
38
|
+
# the following conditions:
|
39
|
+
#
|
40
|
+
# The above copyright notice and this permission notice shall be
|
41
|
+
# included in all copies or substantial portions of the Software.
|
42
|
+
#
|
43
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
44
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
45
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
46
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
47
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
48
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
49
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
50
|
+
#++
|
51
|
+
|
52
|
+
require 'forwardable'
|
53
|
+
require 'action_controller/cgi_ext/cgi_methods'
|
54
|
+
|
55
|
+
class Net::AJP13::Request
|
56
|
+
def cookies
|
57
|
+
unless @cookies
|
58
|
+
@cookies = {}
|
59
|
+
cookie_strings = self.get_fields('cookie')
|
60
|
+
cookie_strings.each do |cookie_string|
|
61
|
+
@cookies.update(CGI::Cookie::parse(cookie_string))
|
62
|
+
end if cookie_strings
|
63
|
+
@cookies.freeze
|
64
|
+
end
|
65
|
+
@cookies
|
66
|
+
end
|
67
|
+
|
68
|
+
attr_reader :output_cookies
|
69
|
+
end
|
70
|
+
|
71
|
+
# Wraps Net::AJP13::Request to adapt it to request object in rails.
|
72
|
+
class AjpRailsRequest < ActionController::AbstractRequest
|
73
|
+
DEFAULT_SESSION_OPTIONS = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.merge('session_key' => 'JSESSIONID')
|
74
|
+
|
75
|
+
extend Forwardable
|
76
|
+
|
77
|
+
def initialize(ajp_request, session_options, server_environments)
|
78
|
+
@req = ajp_request
|
79
|
+
@session_options = session_options
|
80
|
+
@server_environments = server_environments
|
81
|
+
@session_options['session_path'] ||= @server_environments['APP_LOCATION']
|
82
|
+
|
83
|
+
# simulates environment hash.
|
84
|
+
@env = self.class.instance_method(:environment).bind(self)
|
85
|
+
# Object#method is overridden by AbstractRequest#method
|
86
|
+
|
87
|
+
class << @env
|
88
|
+
def include?(key) !call(key).nil? end
|
89
|
+
alias :key? :include?
|
90
|
+
end
|
91
|
+
end
|
92
|
+
attr_reader :env
|
93
|
+
|
94
|
+
attr_accessor :session_options
|
95
|
+
|
96
|
+
def method
|
97
|
+
@req.method.downcase.to_sym
|
98
|
+
end
|
99
|
+
|
100
|
+
def environment(name)
|
101
|
+
case name
|
102
|
+
when /^\AHTTP_(\w+)\Z/
|
103
|
+
name = $1.tr('_', '-')
|
104
|
+
@req[name]
|
105
|
+
else
|
106
|
+
@req[name] or @server_environments[name]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def raw_post
|
111
|
+
if @req.body
|
112
|
+
@req.body
|
113
|
+
elsif @req.body_stream
|
114
|
+
stream = @req.body_stream
|
115
|
+
@req.body_stream = nil
|
116
|
+
@req.body = stream.read
|
117
|
+
else
|
118
|
+
''
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def path
|
123
|
+
path = @req.path
|
124
|
+
path = path.sub(%r!\A#{Regexp.escape(@server_environments['DISPATCHER_PREFIX'])}!, '') if @server_environments['DISPATCHER_PREFIX']
|
125
|
+
path = path.sub(%r!#{Regexp.escape(@server_environments['DISPATCHER_SUFFIX'])}\Z!, '') if @server_environments['DISPATCHER_SUFFIX']
|
126
|
+
path
|
127
|
+
end
|
128
|
+
|
129
|
+
def request_uri
|
130
|
+
if @request_uri
|
131
|
+
@request_uri
|
132
|
+
else
|
133
|
+
uri = path
|
134
|
+
qs = query_string
|
135
|
+
uri << '?' << qs[0] if qs
|
136
|
+
@request_uri = uri
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def_delegators :@req, :ssl?, :cookies
|
141
|
+
|
142
|
+
def server_software
|
143
|
+
val = @req.get_attributes('server_software')
|
144
|
+
val and val[0] and /([A-Za-z]+)/ =~ val[0] and $1.downcase
|
145
|
+
end
|
146
|
+
|
147
|
+
def query_string
|
148
|
+
val = @req.get_attributes('query_string')
|
149
|
+
val and val[0]
|
150
|
+
end
|
151
|
+
|
152
|
+
def query_parameters
|
153
|
+
(qs = self.query_string).blank? ? {} : CGIMethods.parse_query_parameters(qs)
|
154
|
+
end
|
155
|
+
|
156
|
+
def post_params
|
157
|
+
@post_params ||= CGI.parse(raw_post)
|
158
|
+
@post_params
|
159
|
+
end
|
160
|
+
|
161
|
+
def request_parameters
|
162
|
+
if formatted_post?
|
163
|
+
CGIMethods.parse_formatted_request_parameters(post_format, raw_post)
|
164
|
+
else
|
165
|
+
CGIMethods.parse_request_parameters(self.post_params)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def host
|
170
|
+
@req['x-forwarded-host'] ||
|
171
|
+
($1 if @req.server_name and /\A(.*):\d+\Z/ =~ @req.server_name) ||
|
172
|
+
(@req.server_name and @req.server_name.split(':').first) ||
|
173
|
+
($1 if @req['host'] and /\A(.*):\d+\Z/ =~ @req['host']) ||
|
174
|
+
(@req['host'] and @req['host'].split(':').first) ||
|
175
|
+
''
|
176
|
+
end
|
177
|
+
def port
|
178
|
+
@req['x-forwarded-host'] ? standard_port : (port_from_http_host || @req.server_port)
|
179
|
+
end
|
180
|
+
|
181
|
+
def port_from_http_host
|
182
|
+
$1.to_i if @req['host'] && /:(\d+)$/ =~ @req['host']
|
183
|
+
end
|
184
|
+
|
185
|
+
def session
|
186
|
+
unless @session
|
187
|
+
if @session_options == false
|
188
|
+
@session = Hash.new
|
189
|
+
else
|
190
|
+
stale_session_check! do
|
191
|
+
if session_options_with_string_keys['new_session'] == true
|
192
|
+
@session = new_session
|
193
|
+
else
|
194
|
+
@session = CGI::Session.new(@req, session_options_with_string_keys)
|
195
|
+
end
|
196
|
+
@session['__valid_session']
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
@session
|
201
|
+
end
|
202
|
+
|
203
|
+
def reset_session
|
204
|
+
@session.delete if CGI::Session === @session
|
205
|
+
@session = new_session
|
206
|
+
end
|
207
|
+
|
208
|
+
private
|
209
|
+
# Delete an old session if it exists then create a new one.
|
210
|
+
def new_session
|
211
|
+
if @session_options == false
|
212
|
+
Hash.new
|
213
|
+
else
|
214
|
+
CGI::Session.new(@req, session_options_with_string_keys.merge("new_session" => false)).delete rescue nil
|
215
|
+
CGI::Session.new(@req, session_options_with_string_keys.merge("new_session" => true))
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def stale_session_check!
|
220
|
+
yield
|
221
|
+
rescue ArgumentError => argument_error
|
222
|
+
if argument_error.message =~ %r{undefined class/module (\w+)}
|
223
|
+
begin
|
224
|
+
Module.const_missing($1)
|
225
|
+
rescue LoadError, NameError => const_error
|
226
|
+
raise ActionController::SessionRestoreError, <<end_msg
|
227
|
+
Session contains objects whose class definition isn't available.
|
228
|
+
Remember to require the classes for all objects kept in the session.
|
229
|
+
(Original exception: #{const_error.message} [#{const_error.class}])
|
230
|
+
end_msg
|
231
|
+
end
|
232
|
+
retry
|
233
|
+
else
|
234
|
+
raise
|
235
|
+
end
|
236
|
+
end
|
237
|
+
def session_options_with_string_keys
|
238
|
+
@session_options_with_string_keys ||= DEFAULT_SESSION_OPTIONS.merge(@session_options).inject({}) { |options, (k,v)| options[k.to_s] = v; options }
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
class AjpRailsResponse < ActionController::AbstractResponse
|
243
|
+
def to_ajp_response(extra_cookies = nil)
|
244
|
+
raise "Unrecognized status line #{headers['Status']}" unless
|
245
|
+
md = /\A(\d{3})(?: (.+))?/.match(headers['Status'])
|
246
|
+
|
247
|
+
res = md[2] ?
|
248
|
+
Net::AJP13::Response.new(md[1].to_i, :reason_phrase => md[2]) :
|
249
|
+
Net::AJP13::Response.new(md[1])
|
250
|
+
|
251
|
+
@headers.each do |key, value|
|
252
|
+
case key.downcase
|
253
|
+
when 'status'
|
254
|
+
# do nothing
|
255
|
+
when 'expires'
|
256
|
+
res.add_field(key, CGI::rfc1123_date(options.delete(key)))
|
257
|
+
when 'cookie'
|
258
|
+
case value
|
259
|
+
when String
|
260
|
+
res.add_field('Set-Cookie', value)
|
261
|
+
when CGI::Cookie
|
262
|
+
res.add_field('Set-Cookie', value.to_s)
|
263
|
+
when Array
|
264
|
+
value.each {|cookie| res.add_field('Set-Cookie', cookie) }
|
265
|
+
when Hash
|
266
|
+
value.each_value {|cookie| res.add_field('Set-Cookie', cookie) }
|
267
|
+
end
|
268
|
+
else
|
269
|
+
res.add_field(key, value.to_s) if key != 'Status'
|
270
|
+
end
|
271
|
+
end
|
272
|
+
res['content-type'] ||= 'text/html'
|
273
|
+
if extra_cookies
|
274
|
+
extra_cookies.each do |cookie|
|
275
|
+
res.add_field('Set-Cookie', cookie.to_s)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
if @body.respond_to?(:call)
|
280
|
+
buf = ''
|
281
|
+
@body.call(self, StringIO.new(buf))
|
282
|
+
res.body = buf
|
283
|
+
else
|
284
|
+
res.body = self.body
|
285
|
+
end
|
286
|
+
|
287
|
+
return res
|
288
|
+
end
|
289
|
+
end
|