passenger 2.2.1 → 2.2.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- data/Rakefile +66 -79
- data/bin/passenger-install-nginx-module +1 -1
- data/bin/passenger-memory-stats +1 -1
- data/bin/passenger-spawn-server +8 -2
- data/doc/Users guide Apache.html +33 -49
- data/doc/Users guide Apache.txt +28 -27
- data/doc/Users guide Nginx.html +9 -19
- data/doc/Users guide Nginx.txt +8 -20
- data/doc/cxxapi/Bucket_8h-source.html +1 -1
- data/doc/cxxapi/Configuration_8h-source.html +297 -300
- data/doc/cxxapi/DirectoryMapper_8h-source.html +1 -1
- data/doc/cxxapi/Hooks_8h-source.html +1 -1
- data/doc/cxxapi/annotated.html +1 -1
- data/doc/cxxapi/classHooks-members.html +1 -1
- data/doc/cxxapi/classHooks.html +1 -1
- data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +1 -1
- data/doc/cxxapi/classes.html +1 -1
- data/doc/cxxapi/definitions_8h-source.html +1 -1
- data/doc/cxxapi/files.html +1 -1
- data/doc/cxxapi/functions.html +1 -1
- data/doc/cxxapi/functions_func.html +1 -1
- data/doc/cxxapi/graph_legend.html +1 -1
- data/doc/cxxapi/group__Configuration.html +1 -23
- data/doc/cxxapi/group__Core.html +1 -1
- data/doc/cxxapi/group__Hooks.html +1 -1
- data/doc/cxxapi/group__Support.html +1 -1
- data/doc/cxxapi/main.html +1 -1
- data/doc/cxxapi/modules.html +1 -1
- data/doc/users_guide_snippets/rackup_specifications.txt +4 -2
- data/ext/apache2/Configuration.h +0 -3
- data/ext/apache2/Hooks.cpp +5 -3
- data/ext/common/ApplicationPoolServer.h +1 -0
- data/ext/common/ApplicationPoolServerExecutable.cpp +5 -2
- data/ext/common/SpawnManager.h +1 -0
- data/ext/common/Utils.cpp +22 -23
- data/ext/common/Utils.h +32 -21
- data/ext/common/Version.h +31 -0
- data/ext/nginx/ContentHandler.c +61 -8
- data/ext/nginx/HelperServer.cpp +3 -0
- data/ext/nginx/HttpStatusExtractor.h +185 -0
- data/ext/nginx/StaticContentHandler.c +18 -3
- data/ext/nginx/config +2 -1
- data/ext/nginx/ngx_http_passenger_module.c +21 -15
- data/ext/oxt/backtrace.cpp +4 -2
- data/ext/oxt/spin_lock.hpp +3 -3
- data/lib/phusion_passenger/abstract_request_handler.rb +5 -3
- data/lib/phusion_passenger/admin_tools/control_process.rb +6 -1
- data/lib/phusion_passenger/constants.rb +2 -2
- data/lib/phusion_passenger/rack/application_spawner.rb +2 -1
- data/lib/phusion_passenger/rack/request_handler.rb +45 -35
- data/lib/phusion_passenger/templates/nginx/config_snippets.txt.erb +1 -1
- data/lib/phusion_passenger/utils.rb +13 -3
- data/misc/rake/cplusplus.rb +7 -0
- data/test/ApplicationPoolServer_ApplicationPoolTest.cpp +2 -0
- data/test/ApplicationPoolTest.cpp +39 -62
- data/test/CxxTestMain.cpp +6 -6
- data/test/HttpStatusExtractorTest.cpp +17 -0
- data/test/StandardApplicationPoolTest.cpp +2 -0
- data/test/UtilsTest.cpp +17 -28
- data/test/ruby/abstract_request_handler_spec.rb +3 -7
- data/test/ruby/utils_spec.rb +18 -13
- data/test/ruby/wsgi/application_spawner_spec.rb +5 -9
- data/test/stub/railsapp/app/controllers/{bar_controller_1.rb → bar_controller.rb} +0 -0
- data/test/stub/railsapp/app/controllers/bar_controller_1.txt +5 -0
- data/test/stub/railsapp/app/controllers/{bar_controller_2.rb → bar_controller_2.txt} +0 -0
- data/test/support/Support.h +20 -0
- data/test/support/config.rb +13 -0
- data/vendor/README +4 -3
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/COPYING +1 -1
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/KNOWN-ISSUES +0 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/README +54 -7
- data/vendor/rack-1.0.0-git/Rakefile +164 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack.rb +7 -3
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/adapter/camping.rb +0 -0
- data/vendor/rack-1.0.0-git/lib/rack/auth/abstract/handler.rb +37 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/auth/abstract/request.rb +0 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/auth/basic.rb +0 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/auth/digest/md5.rb +1 -1
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/auth/digest/nonce.rb +0 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/auth/digest/params.rb +0 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/auth/digest/request.rb +2 -2
- data/vendor/rack-1.0.0-git/lib/rack/auth/openid.rb +480 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/builder.rb +1 -5
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/cascade.rb +0 -0
- data/vendor/rack-1.0.0-git/lib/rack/chunked.rb +49 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/commonlogger.rb +0 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/conditionalget.rb +4 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/content_length.rb +7 -3
- data/vendor/rack-1.0.0-git/lib/rack/content_type.rb +23 -0
- data/vendor/rack-1.0.0-git/lib/rack/deflater.rb +96 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/directory.rb +5 -2
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/file.rb +4 -1
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler.rb +22 -1
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler/cgi.rb +7 -3
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler/evented_mongrel.rb +0 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler/fastcgi.rb +26 -24
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler/lsws.rb +7 -4
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler/mongrel.rb +5 -3
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler/scgi.rb +5 -3
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler/swiftiplied_mongrel.rb +0 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler/thin.rb +3 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler/webrick.rb +11 -5
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/head.rb +0 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/lint.rb +138 -66
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/lobster.rb +0 -0
- data/vendor/rack-1.0.0-git/lib/rack/lock.rb +16 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/methodoverride.rb +0 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/mime.rb +4 -4
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/mock.rb +42 -5
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/recursive.rb +0 -0
- data/vendor/rack-1.0.0-git/lib/rack/reloader.rb +106 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/request.rb +46 -10
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/response.rb +15 -3
- data/vendor/rack-1.0.0-git/lib/rack/rewindable_input.rb +98 -0
- data/vendor/rack-1.0.0-git/lib/rack/session/abstract/id.rb +142 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/session/cookie.rb +2 -0
- data/vendor/rack-1.0.0-git/lib/rack/session/memcache.rb +109 -0
- data/vendor/rack-1.0.0-git/lib/rack/session/pool.rb +100 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/showexceptions.rb +2 -1
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/showstatus.rb +1 -1
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/static.rb +0 -0
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/urlmap.rb +12 -5
- data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/utils.rb +212 -65
- metadata +71 -170
- data/doc/rdoc/classes/ConditionVariable.html +0 -194
- data/doc/rdoc/classes/Exception.html +0 -120
- data/doc/rdoc/classes/GC.html +0 -113
- data/doc/rdoc/classes/IO.html +0 -169
- data/doc/rdoc/classes/PhusionPassenger.html +0 -238
- data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +0 -153
- data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +0 -506
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +0 -692
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerAlreadyStarted.html +0 -97
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerError.html +0 -96
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerNotStarted.html +0 -97
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer/UnknownMessage.html +0 -96
- data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +0 -598
- data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +0 -140
- data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +0 -264
- data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess/Instance.html +0 -138
- data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +0 -154
- data/doc/rdoc/classes/PhusionPassenger/Application.html +0 -283
- data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +0 -172
- data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +0 -145
- data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +0 -175
- data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +0 -141
- data/doc/rdoc/classes/PhusionPassenger/InvalidPath.html +0 -92
- data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +0 -489
- data/doc/rdoc/classes/PhusionPassenger/NativeSupport.html +0 -350
- data/doc/rdoc/classes/PhusionPassenger/Rack.html +0 -91
- data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +0 -185
- data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +0 -184
- data/doc/rdoc/classes/PhusionPassenger/Railz.html +0 -95
- data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +0 -419
- data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner/Error.html +0 -98
- data/doc/rdoc/classes/PhusionPassenger/Railz/CGIFixed.html +0 -200
- data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +0 -443
- data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner/Error.html +0 -98
- data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +0 -154
- data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +0 -402
- data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +0 -125
- data/doc/rdoc/classes/PhusionPassenger/Utils.html +0 -694
- data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +0 -140
- data/doc/rdoc/classes/PhusionPassenger/WSGI.html +0 -89
- data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +0 -188
- data/doc/rdoc/classes/PlatformInfo.html +0 -831
- data/doc/rdoc/classes/RakeExtensions.html +0 -197
- data/doc/rdoc/classes/Signal.html +0 -134
- data/doc/rdoc/created.rid +0 -1
- data/doc/rdoc/files/DEVELOPERS_TXT.html +0 -240
- data/doc/rdoc/files/README.html +0 -157
- data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +0 -92
- data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +0 -129
- data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +0 -131
- data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +0 -126
- data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +0 -130
- data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +0 -129
- data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +0 -122
- data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +0 -127
- data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +0 -126
- data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +0 -122
- data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +0 -134
- data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +0 -122
- data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +0 -122
- data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +0 -126
- data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +0 -122
- data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +0 -122
- data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +0 -127
- data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +0 -133
- data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +0 -126
- data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +0 -143
- data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +0 -126
- data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +0 -145
- data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +0 -127
- data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +0 -122
- data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +0 -161
- data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +0 -175
- data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +0 -129
- data/doc/rdoc/files/misc/rake/extensions_rb.html +0 -130
- data/doc/rdoc/fr_class_index.html +0 -90
- data/doc/rdoc/fr_file_index.html +0 -76
- data/doc/rdoc/fr_method_index.html +0 -195
- data/doc/rdoc/index.html +0 -26
- data/doc/rdoc/rdoc-style.css +0 -187
- data/vendor/rack-0.9.1/AUTHORS +0 -8
- data/vendor/rack-0.9.1/ChangeLog +0 -1423
- data/vendor/rack-0.9.1/Rakefile +0 -188
- data/vendor/rack-0.9.1/SPEC +0 -129
- data/vendor/rack-0.9.1/lib/rack/auth/abstract/handler.rb +0 -28
- data/vendor/rack-0.9.1/lib/rack/auth/openid.rb +0 -438
- data/vendor/rack-0.9.1/lib/rack/deflater.rb +0 -87
- data/vendor/rack-0.9.1/lib/rack/reloader.rb +0 -64
- data/vendor/rack-0.9.1/lib/rack/session/abstract/id.rb +0 -153
- data/vendor/rack-0.9.1/lib/rack/session/memcache.rb +0 -97
- data/vendor/rack-0.9.1/lib/rack/session/pool.rb +0 -73
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'lsapi'
|
2
|
-
|
2
|
+
require 'rack/content_length'
|
3
|
+
|
3
4
|
module Rack
|
4
5
|
module Handler
|
5
6
|
class LSWS
|
@@ -9,12 +10,14 @@ module Rack
|
|
9
10
|
end
|
10
11
|
end
|
11
12
|
def self.serve(app)
|
13
|
+
app = Rack::ContentLength.new(app)
|
14
|
+
|
12
15
|
env = ENV.to_hash
|
13
16
|
env.delete "HTTP_CONTENT_LENGTH"
|
14
17
|
env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
|
15
18
|
env.update({"rack.version" => [0,1],
|
16
|
-
"rack.input" =>
|
17
|
-
"rack.errors" =>
|
19
|
+
"rack.input" => StringIO.new($stdin.read.to_s),
|
20
|
+
"rack.errors" => $stderr,
|
18
21
|
"rack.multithread" => false,
|
19
22
|
"rack.multiprocess" => true,
|
20
23
|
"rack.run_once" => false,
|
@@ -34,7 +37,7 @@ module Rack
|
|
34
37
|
def self.send_headers(status, headers)
|
35
38
|
print "Status: #{status}\r\n"
|
36
39
|
headers.each { |k, vs|
|
37
|
-
vs.each { |v|
|
40
|
+
vs.split("\n").each { |v|
|
38
41
|
print "#{k}: #{v}\r\n"
|
39
42
|
}
|
40
43
|
}
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'mongrel'
|
2
2
|
require 'stringio'
|
3
|
+
require 'rack/content_length'
|
4
|
+
require 'rack/chunked'
|
3
5
|
|
4
6
|
module Rack
|
5
7
|
module Handler
|
@@ -33,7 +35,7 @@ module Rack
|
|
33
35
|
end
|
34
36
|
|
35
37
|
def initialize(app)
|
36
|
-
@app = app
|
38
|
+
@app = Rack::Chunked.new(Rack::ContentLength.new(app))
|
37
39
|
end
|
38
40
|
|
39
41
|
def process(request, response)
|
@@ -45,7 +47,7 @@ module Rack
|
|
45
47
|
|
46
48
|
env.update({"rack.version" => [0,1],
|
47
49
|
"rack.input" => request.body || StringIO.new(""),
|
48
|
-
"rack.errors" =>
|
50
|
+
"rack.errors" => $stderr,
|
49
51
|
|
50
52
|
"rack.multithread" => true,
|
51
53
|
"rack.multiprocess" => false, # ???
|
@@ -63,7 +65,7 @@ module Rack
|
|
63
65
|
response.send_status(nil)
|
64
66
|
|
65
67
|
headers.each { |k, vs|
|
66
|
-
vs.each { |v|
|
68
|
+
vs.split("\n").each { |v|
|
67
69
|
response.header[k] = v
|
68
70
|
}
|
69
71
|
}
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'scgi'
|
2
2
|
require 'stringio'
|
3
|
+
require 'rack/content_length'
|
4
|
+
require 'rack/chunked'
|
3
5
|
|
4
6
|
module Rack
|
5
7
|
module Handler
|
@@ -14,7 +16,7 @@ module Rack
|
|
14
16
|
end
|
15
17
|
|
16
18
|
def initialize(settings = {})
|
17
|
-
@app = settings[:app]
|
19
|
+
@app = Rack::Chunked.new(Rack::ContentLength.new(settings[:app]))
|
18
20
|
@log = Object.new
|
19
21
|
def @log.info(*args); end
|
20
22
|
def @log.error(*args); end
|
@@ -32,7 +34,7 @@ module Rack
|
|
32
34
|
env["SCRIPT_NAME"] = ""
|
33
35
|
env.update({"rack.version" => [0,1],
|
34
36
|
"rack.input" => StringIO.new(input_body),
|
35
|
-
"rack.errors" =>
|
37
|
+
"rack.errors" => $stderr,
|
36
38
|
|
37
39
|
"rack.multithread" => true,
|
38
40
|
"rack.multiprocess" => true,
|
@@ -44,7 +46,7 @@ module Rack
|
|
44
46
|
begin
|
45
47
|
socket.write("Status: #{status}\r\n")
|
46
48
|
headers.each do |k, vs|
|
47
|
-
vs.each {|v| socket.write("#{k}: #{v}\r\n")}
|
49
|
+
vs.split("\n").each { |v| socket.write("#{k}: #{v}\r\n")}
|
48
50
|
end
|
49
51
|
socket.write("\r\n")
|
50
52
|
body.each {|s| socket.write(s)}
|
File without changes
|
@@ -1,9 +1,12 @@
|
|
1
1
|
require "thin"
|
2
|
+
require "rack/content_length"
|
3
|
+
require "rack/chunked"
|
2
4
|
|
3
5
|
module Rack
|
4
6
|
module Handler
|
5
7
|
class Thin
|
6
8
|
def self.run(app, options={})
|
9
|
+
app = Rack::Chunked.new(Rack::ContentLength.new(app))
|
7
10
|
server = ::Thin::Server.new(options[:Host] || '0.0.0.0',
|
8
11
|
options[:Port] || 8080,
|
9
12
|
app)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'webrick'
|
2
2
|
require 'stringio'
|
3
|
+
require 'rack/content_length'
|
3
4
|
|
4
5
|
module Rack
|
5
6
|
module Handler
|
@@ -14,7 +15,7 @@ module Rack
|
|
14
15
|
|
15
16
|
def initialize(server, app)
|
16
17
|
super server
|
17
|
-
@app = app
|
18
|
+
@app = Rack::ContentLength.new(app)
|
18
19
|
end
|
19
20
|
|
20
21
|
def service(req, res)
|
@@ -23,7 +24,7 @@ module Rack
|
|
23
24
|
|
24
25
|
env.update({"rack.version" => [0,1],
|
25
26
|
"rack.input" => StringIO.new(req.body.to_s),
|
26
|
-
"rack.errors" =>
|
27
|
+
"rack.errors" => $stderr,
|
27
28
|
|
28
29
|
"rack.multithread" => true,
|
29
30
|
"rack.multiprocess" => false,
|
@@ -35,16 +36,21 @@ module Rack
|
|
35
36
|
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
|
36
37
|
env["QUERY_STRING"] ||= ""
|
37
38
|
env["REQUEST_PATH"] ||= "/"
|
38
|
-
|
39
|
+
if env["PATH_INFO"] == ""
|
40
|
+
env.delete "PATH_INFO"
|
41
|
+
else
|
42
|
+
path, n = req.request_uri.path, env["SCRIPT_NAME"].length
|
43
|
+
env["PATH_INFO"] = path[n, path.length-n]
|
44
|
+
end
|
39
45
|
|
40
46
|
status, headers, body = @app.call(env)
|
41
47
|
begin
|
42
48
|
res.status = status.to_i
|
43
49
|
headers.each { |k, vs|
|
44
50
|
if k.downcase == "set-cookie"
|
45
|
-
res.cookies.concat vs.
|
51
|
+
res.cookies.concat vs.split("\n")
|
46
52
|
else
|
47
|
-
vs.each { |v|
|
53
|
+
vs.split("\n").each { |v|
|
48
54
|
res[k] = v
|
49
55
|
}
|
50
56
|
end
|
File without changes
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'rack/utils'
|
2
|
+
|
1
3
|
module Rack
|
2
4
|
# Rack::Lint validates your application and the requests and
|
3
5
|
# responses according to the Rack spec.
|
@@ -86,7 +88,9 @@ module Rack
|
|
86
88
|
## within the application. This may be an
|
87
89
|
## empty string, if the request URL targets
|
88
90
|
## the application root and does not have a
|
89
|
-
## trailing slash.
|
91
|
+
## trailing slash. This value may be
|
92
|
+
## percent-encoded when I originating from
|
93
|
+
## a URL.
|
90
94
|
|
91
95
|
## <tt>QUERY_STRING</tt>:: The portion of the request URL that
|
92
96
|
## follows the <tt>?</tt>, if any. May be
|
@@ -107,19 +111,48 @@ module Rack
|
|
107
111
|
## In addition to this, the Rack environment must include these
|
108
112
|
## Rack-specific variables:
|
109
113
|
|
110
|
-
## <tt>rack.version</tt>:: The Array [0
|
114
|
+
## <tt>rack.version</tt>:: The Array [1,0], representing this version of Rack.
|
111
115
|
## <tt>rack.url_scheme</tt>:: +http+ or +https+, depending on the request URL.
|
112
116
|
## <tt>rack.input</tt>:: See below, the input stream.
|
113
117
|
## <tt>rack.errors</tt>:: See below, the error stream.
|
114
118
|
## <tt>rack.multithread</tt>:: true if the application object may be simultaneously invoked by another thread in the same process, false otherwise.
|
115
119
|
## <tt>rack.multiprocess</tt>:: true if an equivalent application object may be simultaneously invoked by another process, false otherwise.
|
116
120
|
## <tt>rack.run_once</tt>:: true if the server expects (but does not guarantee!) that the application will only be invoked this one time during the life of its containing process. Normally, this will only be true for a server based on CGI (or something similar).
|
121
|
+
##
|
122
|
+
|
123
|
+
## Additional environment specifications have approved to
|
124
|
+
## standardized middleware APIs. None of these are required to
|
125
|
+
## be implemented by the server.
|
126
|
+
|
127
|
+
## <tt>rack.session</tt>:: A hash like interface for storing request session data.
|
128
|
+
## The store must implement:
|
129
|
+
if session = env['rack.session']
|
130
|
+
## store(key, value) (aliased as []=);
|
131
|
+
assert("session #{session.inspect} must respond to store and []=") {
|
132
|
+
session.respond_to?(:store) && session.respond_to?(:[]=)
|
133
|
+
}
|
134
|
+
|
135
|
+
## fetch(key, default = nil) (aliased as []);
|
136
|
+
assert("session #{session.inspect} must respond to fetch and []") {
|
137
|
+
session.respond_to?(:fetch) && session.respond_to?(:[])
|
138
|
+
}
|
139
|
+
|
140
|
+
## delete(key);
|
141
|
+
assert("session #{session.inspect} must respond to delete") {
|
142
|
+
session.respond_to?(:delete)
|
143
|
+
}
|
144
|
+
|
145
|
+
## clear;
|
146
|
+
assert("session #{session.inspect} must respond to clear") {
|
147
|
+
session.respond_to?(:clear)
|
148
|
+
}
|
149
|
+
end
|
117
150
|
|
118
151
|
## The server or the application can store their own data in the
|
119
152
|
## environment, too. The keys must contain at least one dot,
|
120
153
|
## and should be prefixed uniquely. The prefix <tt>rack.</tt>
|
121
|
-
## is reserved for use with the Rack core distribution and
|
122
|
-
## not be used otherwise.
|
154
|
+
## is reserved for use with the Rack core distribution and other
|
155
|
+
## accepted specifications and must not be used otherwise.
|
123
156
|
##
|
124
157
|
|
125
158
|
%w[REQUEST_METHOD SERVER_NAME SERVER_PORT
|
@@ -198,9 +231,12 @@ module Rack
|
|
198
231
|
end
|
199
232
|
|
200
233
|
## === The Input Stream
|
234
|
+
##
|
235
|
+
## The input stream is an IO-like object which contains the raw HTTP
|
236
|
+
## POST data. If it is a file then it must be opened in binary mode.
|
201
237
|
def check_input(input)
|
202
|
-
## The input stream must respond to +gets+, +each+ and +
|
203
|
-
[:gets, :each, :read].each { |method|
|
238
|
+
## The input stream must respond to +gets+, +each+, +read+ and +rewind+.
|
239
|
+
[:gets, :each, :read, :rewind].each { |method|
|
204
240
|
assert("rack.input #{input} does not respond to ##{method}") {
|
205
241
|
input.respond_to? method
|
206
242
|
}
|
@@ -218,10 +254,6 @@ module Rack
|
|
218
254
|
@input.size
|
219
255
|
end
|
220
256
|
|
221
|
-
def rewind
|
222
|
-
@input.rewind
|
223
|
-
end
|
224
|
-
|
225
257
|
## * +gets+ must be called without arguments and return a string,
|
226
258
|
## or +nil+ on EOF.
|
227
259
|
def gets(*args)
|
@@ -233,21 +265,44 @@ module Rack
|
|
233
265
|
v
|
234
266
|
end
|
235
267
|
|
236
|
-
## * +read+
|
237
|
-
##
|
268
|
+
## * +read+ behaves like IO#read. Its signature is <tt>read([length, [buffer]])</tt>.
|
269
|
+
## If given, +length+ must be an non-negative Integer (>= 0) or +nil+, and +buffer+ must
|
270
|
+
## be a String and may not be nil. If +length+ is given and not nil, then this method
|
271
|
+
## reads at most +length+ bytes from the input stream. If +length+ is not given or nil,
|
272
|
+
## then this method reads all data until EOF.
|
273
|
+
## When EOF is reached, this method returns nil if +length+ is given and not nil, or ""
|
274
|
+
## if +length+ is not given or is nil.
|
275
|
+
## If +buffer+ is given, then the read data will be placed into +buffer+ instead of a
|
276
|
+
## newly created String object.
|
238
277
|
def read(*args)
|
239
278
|
assert("rack.input#read called with too many arguments") {
|
240
|
-
args.size <=
|
279
|
+
args.size <= 2
|
241
280
|
}
|
242
|
-
if args.size
|
243
|
-
assert("rack.input#read called with non-integer
|
244
|
-
args.first.kind_of?
|
281
|
+
if args.size >= 1
|
282
|
+
assert("rack.input#read called with non-integer and non-nil length") {
|
283
|
+
args.first.kind_of?(Integer) || args.first.nil?
|
284
|
+
}
|
285
|
+
assert("rack.input#read called with a negative length") {
|
286
|
+
args.first.nil? || args.first >= 0
|
245
287
|
}
|
246
288
|
end
|
289
|
+
if args.size >= 2
|
290
|
+
assert("rack.input#read called with non-String buffer") {
|
291
|
+
args[1].kind_of?(String)
|
292
|
+
}
|
293
|
+
end
|
294
|
+
|
247
295
|
v = @input.read(*args)
|
248
|
-
|
296
|
+
|
297
|
+
assert("rack.input#read didn't return nil or a String") {
|
249
298
|
v.nil? or v.instance_of? String
|
250
299
|
}
|
300
|
+
if args[0].nil?
|
301
|
+
assert("rack.input#read(nil) returned nil on EOF") {
|
302
|
+
!v.nil?
|
303
|
+
}
|
304
|
+
end
|
305
|
+
|
251
306
|
v
|
252
307
|
end
|
253
308
|
|
@@ -261,6 +316,23 @@ module Rack
|
|
261
316
|
yield line
|
262
317
|
}
|
263
318
|
end
|
319
|
+
|
320
|
+
## * +rewind+ must be called without arguments. It rewinds the input
|
321
|
+
## stream back to the beginning. It must not raise Errno::ESPIPE:
|
322
|
+
## that is, it may not be a pipe or a socket. Therefore, handler
|
323
|
+
## developers must buffer the input data into some rewindable object
|
324
|
+
## if the underlying input stream is not rewindable.
|
325
|
+
def rewind(*args)
|
326
|
+
assert("rack.input#rewind called with arguments") { args.size == 0 }
|
327
|
+
assert("rack.input#rewind raised Errno::ESPIPE") {
|
328
|
+
begin
|
329
|
+
@input.rewind
|
330
|
+
true
|
331
|
+
rescue Errno::ESPIPE
|
332
|
+
false
|
333
|
+
end
|
334
|
+
}
|
335
|
+
end
|
264
336
|
|
265
337
|
## * +close+ must never be called on the input stream.
|
266
338
|
def close(*args)
|
@@ -312,13 +384,14 @@ module Rack
|
|
312
384
|
|
313
385
|
## === The Status
|
314
386
|
def check_status(status)
|
315
|
-
##
|
387
|
+
## This is an HTTP status. When parsed as integer (+to_i+), it must be
|
388
|
+
## greater than or equal to 100.
|
316
389
|
assert("Status must be >=100 seen as integer") { status.to_i >= 100 }
|
317
390
|
end
|
318
391
|
|
319
392
|
## === The Headers
|
320
393
|
def check_headers(header)
|
321
|
-
## The header must respond to each
|
394
|
+
## The header must respond to +each+, and yield values of key and value.
|
322
395
|
assert("headers object should respond to #each, but doesn't (got #{header.class} as headers)") {
|
323
396
|
header.respond_to? :each
|
324
397
|
}
|
@@ -336,16 +409,14 @@ module Rack
|
|
336
409
|
## but only contain keys that consist of
|
337
410
|
## letters, digits, <tt>_</tt> or <tt>-</tt> and start with a letter.
|
338
411
|
assert("invalid header name: #{key}") { key =~ /\A[a-zA-Z][a-zA-Z0-9_-]*\z/ }
|
339
|
-
|
340
|
-
## The values of the header must
|
341
|
-
assert("header
|
342
|
-
"'#{key}'
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
}
|
348
|
-
## and not contain characters below 037.
|
412
|
+
|
413
|
+
## The values of the header must be Strings,
|
414
|
+
assert("a header value must be a String, but the value of " +
|
415
|
+
"'#{key}' is a #{value.class}") { value.kind_of? String }
|
416
|
+
## consisting of lines (for multiple header values, e.g. multiple
|
417
|
+
## <tt>Set-Cookie</tt> values) seperated by "\n".
|
418
|
+
value.split("\n").each { |item|
|
419
|
+
## The lines must not contain characters below 037.
|
349
420
|
assert("invalid header value #{key}: #{item.inspect}") {
|
350
421
|
item !~ /[\000-\037]/
|
351
422
|
}
|
@@ -373,65 +444,49 @@ module Rack
|
|
373
444
|
|
374
445
|
## === The Content-Length
|
375
446
|
def check_content_length(status, headers, env)
|
376
|
-
chunked_response = false
|
377
|
-
headers.each { |key, value|
|
378
|
-
if key.downcase == 'transfer-encoding'
|
379
|
-
chunked_response = value.downcase != 'identity'
|
380
|
-
end
|
381
|
-
}
|
382
|
-
|
383
447
|
headers.each { |key, value|
|
384
448
|
if key.downcase == 'content-length'
|
385
|
-
## There must be a <tt>Content-Length</tt
|
386
|
-
## +Status+ is 1xx, 204 or 304
|
387
|
-
## given.
|
449
|
+
## There must not be a <tt>Content-Length</tt> header when the
|
450
|
+
## +Status+ is 1xx, 204 or 304.
|
388
451
|
assert("Content-Length header found in #{status} response, not allowed") {
|
389
452
|
not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i
|
390
453
|
}
|
391
454
|
|
392
|
-
assert('Content-Length header should not be used if body is chunked') {
|
393
|
-
not chunked_response
|
394
|
-
}
|
395
|
-
|
396
455
|
bytes = 0
|
397
456
|
string_body = true
|
398
457
|
|
399
|
-
@body.
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
bytes += (part.respond_to?(:bytesize) ? part.bytesize : part.size)
|
406
|
-
}
|
458
|
+
if @body.respond_to?(:to_ary)
|
459
|
+
@body.each { |part|
|
460
|
+
unless part.kind_of?(String)
|
461
|
+
string_body = false
|
462
|
+
break
|
463
|
+
end
|
407
464
|
|
408
|
-
|
409
|
-
assert("Response body was given for HEAD request, but should be empty") {
|
410
|
-
bytes == 0
|
465
|
+
bytes += Rack::Utils.bytesize(part)
|
411
466
|
}
|
412
|
-
|
413
|
-
if
|
414
|
-
assert("
|
415
|
-
|
467
|
+
|
468
|
+
if env["REQUEST_METHOD"] == "HEAD"
|
469
|
+
assert("Response body was given for HEAD request, but should be empty") {
|
470
|
+
bytes == 0
|
416
471
|
}
|
472
|
+
else
|
473
|
+
if string_body
|
474
|
+
assert("Content-Length header was #{value}, but should be #{bytes}") {
|
475
|
+
value == bytes.to_s
|
476
|
+
}
|
477
|
+
end
|
417
478
|
end
|
418
479
|
end
|
419
480
|
|
420
481
|
return
|
421
482
|
end
|
422
483
|
}
|
423
|
-
|
424
|
-
if [ String, Array ].include?(@body.class) && !chunked_response
|
425
|
-
assert('No Content-Length header found') {
|
426
|
-
Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i
|
427
|
-
}
|
428
|
-
end
|
429
484
|
end
|
430
485
|
|
431
486
|
## === The Body
|
432
487
|
def each
|
433
488
|
@closed = false
|
434
|
-
## The Body must respond to
|
489
|
+
## The Body must respond to +each+
|
435
490
|
@body.each { |part|
|
436
491
|
## and must only yield String values.
|
437
492
|
assert("Body yielded non-string value #{part.inspect}") {
|
@@ -440,9 +495,26 @@ module Rack
|
|
440
495
|
yield part
|
441
496
|
}
|
442
497
|
##
|
443
|
-
##
|
498
|
+
## The Body itself should not be an instance of String, as this will
|
499
|
+
## break in Ruby 1.9.
|
500
|
+
##
|
501
|
+
## If the Body responds to +close+, it will be called after iteration.
|
444
502
|
# XXX howto: assert("Body has not been closed") { @closed }
|
445
503
|
|
504
|
+
|
505
|
+
##
|
506
|
+
## If the Body responds to +to_path+, it must return a String
|
507
|
+
## identifying the location of a file whose contents are identical
|
508
|
+
## to that produced by calling +each+; this may be used by the
|
509
|
+
## server as an alternative, possibly more efficient way to
|
510
|
+
## transport the response.
|
511
|
+
|
512
|
+
if @body.respond_to?(:to_path)
|
513
|
+
assert("The file identified by body.to_path does not exist") {
|
514
|
+
::File.exist? @body.to_path
|
515
|
+
}
|
516
|
+
end
|
517
|
+
|
446
518
|
##
|
447
519
|
## The Body commonly is an Array of Strings, the application
|
448
520
|
## instance itself, or a File-like object.
|