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.

Files changed (216) hide show
  1. data/Rakefile +66 -79
  2. data/bin/passenger-install-nginx-module +1 -1
  3. data/bin/passenger-memory-stats +1 -1
  4. data/bin/passenger-spawn-server +8 -2
  5. data/doc/Users guide Apache.html +33 -49
  6. data/doc/Users guide Apache.txt +28 -27
  7. data/doc/Users guide Nginx.html +9 -19
  8. data/doc/Users guide Nginx.txt +8 -20
  9. data/doc/cxxapi/Bucket_8h-source.html +1 -1
  10. data/doc/cxxapi/Configuration_8h-source.html +297 -300
  11. data/doc/cxxapi/DirectoryMapper_8h-source.html +1 -1
  12. data/doc/cxxapi/Hooks_8h-source.html +1 -1
  13. data/doc/cxxapi/annotated.html +1 -1
  14. data/doc/cxxapi/classHooks-members.html +1 -1
  15. data/doc/cxxapi/classHooks.html +1 -1
  16. data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +1 -1
  17. data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +1 -1
  18. data/doc/cxxapi/classes.html +1 -1
  19. data/doc/cxxapi/definitions_8h-source.html +1 -1
  20. data/doc/cxxapi/files.html +1 -1
  21. data/doc/cxxapi/functions.html +1 -1
  22. data/doc/cxxapi/functions_func.html +1 -1
  23. data/doc/cxxapi/graph_legend.html +1 -1
  24. data/doc/cxxapi/group__Configuration.html +1 -23
  25. data/doc/cxxapi/group__Core.html +1 -1
  26. data/doc/cxxapi/group__Hooks.html +1 -1
  27. data/doc/cxxapi/group__Support.html +1 -1
  28. data/doc/cxxapi/main.html +1 -1
  29. data/doc/cxxapi/modules.html +1 -1
  30. data/doc/users_guide_snippets/rackup_specifications.txt +4 -2
  31. data/ext/apache2/Configuration.h +0 -3
  32. data/ext/apache2/Hooks.cpp +5 -3
  33. data/ext/common/ApplicationPoolServer.h +1 -0
  34. data/ext/common/ApplicationPoolServerExecutable.cpp +5 -2
  35. data/ext/common/SpawnManager.h +1 -0
  36. data/ext/common/Utils.cpp +22 -23
  37. data/ext/common/Utils.h +32 -21
  38. data/ext/common/Version.h +31 -0
  39. data/ext/nginx/ContentHandler.c +61 -8
  40. data/ext/nginx/HelperServer.cpp +3 -0
  41. data/ext/nginx/HttpStatusExtractor.h +185 -0
  42. data/ext/nginx/StaticContentHandler.c +18 -3
  43. data/ext/nginx/config +2 -1
  44. data/ext/nginx/ngx_http_passenger_module.c +21 -15
  45. data/ext/oxt/backtrace.cpp +4 -2
  46. data/ext/oxt/spin_lock.hpp +3 -3
  47. data/lib/phusion_passenger/abstract_request_handler.rb +5 -3
  48. data/lib/phusion_passenger/admin_tools/control_process.rb +6 -1
  49. data/lib/phusion_passenger/constants.rb +2 -2
  50. data/lib/phusion_passenger/rack/application_spawner.rb +2 -1
  51. data/lib/phusion_passenger/rack/request_handler.rb +45 -35
  52. data/lib/phusion_passenger/templates/nginx/config_snippets.txt.erb +1 -1
  53. data/lib/phusion_passenger/utils.rb +13 -3
  54. data/misc/rake/cplusplus.rb +7 -0
  55. data/test/ApplicationPoolServer_ApplicationPoolTest.cpp +2 -0
  56. data/test/ApplicationPoolTest.cpp +39 -62
  57. data/test/CxxTestMain.cpp +6 -6
  58. data/test/HttpStatusExtractorTest.cpp +17 -0
  59. data/test/StandardApplicationPoolTest.cpp +2 -0
  60. data/test/UtilsTest.cpp +17 -28
  61. data/test/ruby/abstract_request_handler_spec.rb +3 -7
  62. data/test/ruby/utils_spec.rb +18 -13
  63. data/test/ruby/wsgi/application_spawner_spec.rb +5 -9
  64. data/test/stub/railsapp/app/controllers/{bar_controller_1.rb → bar_controller.rb} +0 -0
  65. data/test/stub/railsapp/app/controllers/bar_controller_1.txt +5 -0
  66. data/test/stub/railsapp/app/controllers/{bar_controller_2.rb → bar_controller_2.txt} +0 -0
  67. data/test/support/Support.h +20 -0
  68. data/test/support/config.rb +13 -0
  69. data/vendor/README +4 -3
  70. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/COPYING +1 -1
  71. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/KNOWN-ISSUES +0 -0
  72. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/README +54 -7
  73. data/vendor/rack-1.0.0-git/Rakefile +164 -0
  74. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack.rb +7 -3
  75. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/adapter/camping.rb +0 -0
  76. data/vendor/rack-1.0.0-git/lib/rack/auth/abstract/handler.rb +37 -0
  77. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/auth/abstract/request.rb +0 -0
  78. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/auth/basic.rb +0 -0
  79. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/auth/digest/md5.rb +1 -1
  80. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/auth/digest/nonce.rb +0 -0
  81. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/auth/digest/params.rb +0 -0
  82. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/auth/digest/request.rb +2 -2
  83. data/vendor/rack-1.0.0-git/lib/rack/auth/openid.rb +480 -0
  84. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/builder.rb +1 -5
  85. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/cascade.rb +0 -0
  86. data/vendor/rack-1.0.0-git/lib/rack/chunked.rb +49 -0
  87. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/commonlogger.rb +0 -0
  88. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/conditionalget.rb +4 -0
  89. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/content_length.rb +7 -3
  90. data/vendor/rack-1.0.0-git/lib/rack/content_type.rb +23 -0
  91. data/vendor/rack-1.0.0-git/lib/rack/deflater.rb +96 -0
  92. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/directory.rb +5 -2
  93. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/file.rb +4 -1
  94. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler.rb +22 -1
  95. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler/cgi.rb +7 -3
  96. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler/evented_mongrel.rb +0 -0
  97. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler/fastcgi.rb +26 -24
  98. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler/lsws.rb +7 -4
  99. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler/mongrel.rb +5 -3
  100. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler/scgi.rb +5 -3
  101. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler/swiftiplied_mongrel.rb +0 -0
  102. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler/thin.rb +3 -0
  103. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/handler/webrick.rb +11 -5
  104. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/head.rb +0 -0
  105. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/lint.rb +138 -66
  106. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/lobster.rb +0 -0
  107. data/vendor/rack-1.0.0-git/lib/rack/lock.rb +16 -0
  108. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/methodoverride.rb +0 -0
  109. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/mime.rb +4 -4
  110. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/mock.rb +42 -5
  111. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/recursive.rb +0 -0
  112. data/vendor/rack-1.0.0-git/lib/rack/reloader.rb +106 -0
  113. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/request.rb +46 -10
  114. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/response.rb +15 -3
  115. data/vendor/rack-1.0.0-git/lib/rack/rewindable_input.rb +98 -0
  116. data/vendor/rack-1.0.0-git/lib/rack/session/abstract/id.rb +142 -0
  117. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/session/cookie.rb +2 -0
  118. data/vendor/rack-1.0.0-git/lib/rack/session/memcache.rb +109 -0
  119. data/vendor/rack-1.0.0-git/lib/rack/session/pool.rb +100 -0
  120. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/showexceptions.rb +2 -1
  121. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/showstatus.rb +1 -1
  122. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/static.rb +0 -0
  123. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/urlmap.rb +12 -5
  124. data/vendor/{rack-0.9.1 → rack-1.0.0-git}/lib/rack/utils.rb +212 -65
  125. metadata +71 -170
  126. data/doc/rdoc/classes/ConditionVariable.html +0 -194
  127. data/doc/rdoc/classes/Exception.html +0 -120
  128. data/doc/rdoc/classes/GC.html +0 -113
  129. data/doc/rdoc/classes/IO.html +0 -169
  130. data/doc/rdoc/classes/PhusionPassenger.html +0 -238
  131. data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +0 -153
  132. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +0 -506
  133. data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +0 -692
  134. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerAlreadyStarted.html +0 -97
  135. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerError.html +0 -96
  136. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerNotStarted.html +0 -97
  137. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/UnknownMessage.html +0 -96
  138. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +0 -598
  139. data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +0 -140
  140. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +0 -264
  141. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess/Instance.html +0 -138
  142. data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +0 -154
  143. data/doc/rdoc/classes/PhusionPassenger/Application.html +0 -283
  144. data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +0 -172
  145. data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +0 -145
  146. data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +0 -175
  147. data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +0 -141
  148. data/doc/rdoc/classes/PhusionPassenger/InvalidPath.html +0 -92
  149. data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +0 -489
  150. data/doc/rdoc/classes/PhusionPassenger/NativeSupport.html +0 -350
  151. data/doc/rdoc/classes/PhusionPassenger/Rack.html +0 -91
  152. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +0 -185
  153. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +0 -184
  154. data/doc/rdoc/classes/PhusionPassenger/Railz.html +0 -95
  155. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +0 -419
  156. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner/Error.html +0 -98
  157. data/doc/rdoc/classes/PhusionPassenger/Railz/CGIFixed.html +0 -200
  158. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +0 -443
  159. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner/Error.html +0 -98
  160. data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +0 -154
  161. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +0 -402
  162. data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +0 -125
  163. data/doc/rdoc/classes/PhusionPassenger/Utils.html +0 -694
  164. data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +0 -140
  165. data/doc/rdoc/classes/PhusionPassenger/WSGI.html +0 -89
  166. data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +0 -188
  167. data/doc/rdoc/classes/PlatformInfo.html +0 -831
  168. data/doc/rdoc/classes/RakeExtensions.html +0 -197
  169. data/doc/rdoc/classes/Signal.html +0 -134
  170. data/doc/rdoc/created.rid +0 -1
  171. data/doc/rdoc/files/DEVELOPERS_TXT.html +0 -240
  172. data/doc/rdoc/files/README.html +0 -157
  173. data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +0 -92
  174. data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +0 -129
  175. data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +0 -131
  176. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +0 -126
  177. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +0 -130
  178. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +0 -129
  179. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +0 -122
  180. data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +0 -127
  181. data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +0 -126
  182. data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +0 -122
  183. data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +0 -134
  184. data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +0 -122
  185. data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +0 -122
  186. data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +0 -126
  187. data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +0 -122
  188. data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +0 -122
  189. data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +0 -127
  190. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +0 -133
  191. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +0 -126
  192. data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +0 -143
  193. data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +0 -126
  194. data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +0 -145
  195. data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +0 -127
  196. data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +0 -122
  197. data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +0 -161
  198. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +0 -175
  199. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +0 -129
  200. data/doc/rdoc/files/misc/rake/extensions_rb.html +0 -130
  201. data/doc/rdoc/fr_class_index.html +0 -90
  202. data/doc/rdoc/fr_file_index.html +0 -76
  203. data/doc/rdoc/fr_method_index.html +0 -195
  204. data/doc/rdoc/index.html +0 -26
  205. data/doc/rdoc/rdoc-style.css +0 -187
  206. data/vendor/rack-0.9.1/AUTHORS +0 -8
  207. data/vendor/rack-0.9.1/ChangeLog +0 -1423
  208. data/vendor/rack-0.9.1/Rakefile +0 -188
  209. data/vendor/rack-0.9.1/SPEC +0 -129
  210. data/vendor/rack-0.9.1/lib/rack/auth/abstract/handler.rb +0 -28
  211. data/vendor/rack-0.9.1/lib/rack/auth/openid.rb +0 -438
  212. data/vendor/rack-0.9.1/lib/rack/deflater.rb +0 -87
  213. data/vendor/rack-0.9.1/lib/rack/reloader.rb +0 -64
  214. data/vendor/rack-0.9.1/lib/rack/session/abstract/id.rb +0 -153
  215. data/vendor/rack-0.9.1/lib/rack/session/memcache.rb +0 -97
  216. data/vendor/rack-0.9.1/lib/rack/session/pool.rb +0 -73
@@ -34,11 +34,7 @@ module Rack
34
34
  end
35
35
 
36
36
  def use(middleware, *args, &block)
37
- @ins << if block_given?
38
- lambda { |app| middleware.new(app, *args, &block) }
39
- else
40
- lambda { |app| middleware.new(app, *args) }
41
- end
37
+ @ins << lambda { |app| middleware.new(app, *args, &block) }
42
38
  end
43
39
 
44
40
  def run(app)
@@ -0,0 +1,49 @@
1
+ require 'rack/utils'
2
+
3
+ module Rack
4
+
5
+ # Middleware that applies chunked transfer encoding to response bodies
6
+ # when the response does not include a Content-Length header.
7
+ class Chunked
8
+ include Rack::Utils
9
+
10
+ def initialize(app)
11
+ @app = app
12
+ end
13
+
14
+ def call(env)
15
+ status, headers, body = @app.call(env)
16
+ headers = HeaderHash.new(headers)
17
+
18
+ if env['HTTP_VERSION'] == 'HTTP/1.0' ||
19
+ STATUS_WITH_NO_ENTITY_BODY.include?(status) ||
20
+ headers['Content-Length'] ||
21
+ headers['Transfer-Encoding']
22
+ [status, headers.to_hash, body]
23
+ else
24
+ dup.chunk(status, headers, body)
25
+ end
26
+ end
27
+
28
+ def chunk(status, headers, body)
29
+ @body = body
30
+ headers.delete('Content-Length')
31
+ headers['Transfer-Encoding'] = 'chunked'
32
+ [status, headers.to_hash, self]
33
+ end
34
+
35
+ def each
36
+ term = "\r\n"
37
+ @body.each do |chunk|
38
+ size = bytesize(chunk)
39
+ next if size == 0
40
+ yield [size.to_s(16), term, chunk, term].join
41
+ end
42
+ yield ["0", term, "", term].join
43
+ end
44
+
45
+ def close
46
+ @body.close if @body.respond_to?(:close)
47
+ end
48
+ end
49
+ end
@@ -1,3 +1,5 @@
1
+ require 'rack/utils'
2
+
1
3
  module Rack
2
4
 
3
5
  # Middleware that enables conditional GET using If-None-Match and
@@ -24,6 +26,8 @@ module Rack
24
26
  headers = Utils::HeaderHash.new(headers)
25
27
  if etag_matches?(env, headers) || modified_since?(env, headers)
26
28
  status = 304
29
+ headers.delete('Content-Type')
30
+ headers.delete('Content-Length')
27
31
  body = []
28
32
  end
29
33
  [status, headers, body]
@@ -1,21 +1,25 @@
1
+ require 'rack/utils'
2
+
1
3
  module Rack
2
4
  # Sets the Content-Length header on responses with fixed-length bodies.
3
5
  class ContentLength
6
+ include Rack::Utils
7
+
4
8
  def initialize(app)
5
9
  @app = app
6
10
  end
7
11
 
8
12
  def call(env)
9
13
  status, headers, body = @app.call(env)
10
- headers = Utils::HeaderHash.new(headers)
14
+ headers = HeaderHash.new(headers)
11
15
 
12
- if !Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status) &&
16
+ if !STATUS_WITH_NO_ENTITY_BODY.include?(status) &&
13
17
  !headers['Content-Length'] &&
14
18
  !headers['Transfer-Encoding'] &&
15
19
  (body.respond_to?(:to_ary) || body.respond_to?(:to_str))
16
20
 
17
21
  body = [body] if body.respond_to?(:to_str) # rack 0.4 compat
18
- length = body.to_ary.inject(0) { |len, part| len + part.length }
22
+ length = body.to_ary.inject(0) { |len, part| len + bytesize(part) }
19
23
  headers['Content-Length'] = length.to_s
20
24
  end
21
25
 
@@ -0,0 +1,23 @@
1
+ require 'rack/utils'
2
+
3
+ module Rack
4
+
5
+ # Sets the Content-Type header on responses which don't have one.
6
+ #
7
+ # Builder Usage:
8
+ # use Rack::ContentType, "text/plain"
9
+ #
10
+ # When no content type argument is provided, "text/html" is assumed.
11
+ class ContentType
12
+ def initialize(app, content_type = "text/html")
13
+ @app, @content_type = app, content_type
14
+ end
15
+
16
+ def call(env)
17
+ status, headers, body = @app.call(env)
18
+ headers = Utils::HeaderHash.new(headers)
19
+ headers['Content-Type'] ||= @content_type
20
+ [status, headers.to_hash, body]
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,96 @@
1
+ require "zlib"
2
+ require "stringio"
3
+ require "time" # for Time.httpdate
4
+ require 'rack/utils'
5
+
6
+ module Rack
7
+ class Deflater
8
+ def initialize(app)
9
+ @app = app
10
+ end
11
+
12
+ def call(env)
13
+ status, headers, body = @app.call(env)
14
+ headers = Utils::HeaderHash.new(headers)
15
+
16
+ # Skip compressing empty entity body responses and responses with
17
+ # no-transform set.
18
+ if Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status) ||
19
+ headers['Cache-Control'].to_s =~ /\bno-transform\b/
20
+ return [status, headers, body]
21
+ end
22
+
23
+ request = Request.new(env)
24
+
25
+ encoding = Utils.select_best_encoding(%w(gzip deflate identity),
26
+ request.accept_encoding)
27
+
28
+ # Set the Vary HTTP header.
29
+ vary = headers["Vary"].to_s.split(",").map { |v| v.strip }
30
+ unless vary.include?("*") || vary.include?("Accept-Encoding")
31
+ headers["Vary"] = vary.push("Accept-Encoding").join(",")
32
+ end
33
+
34
+ case encoding
35
+ when "gzip"
36
+ headers['Content-Encoding'] = "gzip"
37
+ headers.delete('Content-Length')
38
+ mtime = headers.key?("Last-Modified") ?
39
+ Time.httpdate(headers["Last-Modified"]) : Time.now
40
+ [status, headers, GzipStream.new(body, mtime)]
41
+ when "deflate"
42
+ headers['Content-Encoding'] = "deflate"
43
+ headers.delete('Content-Length')
44
+ [status, headers, DeflateStream.new(body)]
45
+ when "identity"
46
+ [status, headers, body]
47
+ when nil
48
+ message = "An acceptable encoding for the requested resource #{request.fullpath} could not be found."
49
+ [406, {"Content-Type" => "text/plain", "Content-Length" => message.length.to_s}, [message]]
50
+ end
51
+ end
52
+
53
+ class GzipStream
54
+ def initialize(body, mtime)
55
+ @body = body
56
+ @mtime = mtime
57
+ end
58
+
59
+ def each(&block)
60
+ @writer = block
61
+ gzip =::Zlib::GzipWriter.new(self)
62
+ gzip.mtime = @mtime
63
+ @body.each { |part| gzip << part }
64
+ @body.close if @body.respond_to?(:close)
65
+ gzip.close
66
+ @writer = nil
67
+ end
68
+
69
+ def write(data)
70
+ @writer.call(data)
71
+ end
72
+ end
73
+
74
+ class DeflateStream
75
+ DEFLATE_ARGS = [
76
+ Zlib::DEFAULT_COMPRESSION,
77
+ # drop the zlib header which causes both Safari and IE to choke
78
+ -Zlib::MAX_WBITS,
79
+ Zlib::DEF_MEM_LEVEL,
80
+ Zlib::DEFAULT_STRATEGY
81
+ ]
82
+
83
+ def initialize(body)
84
+ @body = body
85
+ end
86
+
87
+ def each
88
+ deflater = ::Zlib::Deflate.new(*DEFLATE_ARGS)
89
+ @body.each { |part| yield deflater.deflate(part) }
90
+ @body.close if @body.respond_to?(:close)
91
+ yield deflater.finish
92
+ nil
93
+ end
94
+ end
95
+ end
96
+ end
@@ -1,4 +1,5 @@
1
1
  require 'time'
2
+ require 'rack/utils'
2
3
  require 'rack/mime'
3
4
 
4
5
  module Rack
@@ -69,7 +70,7 @@ table { width:100%%; }
69
70
  return unless @path_info.include? ".."
70
71
 
71
72
  body = "Forbidden\n"
72
- size = body.respond_to?(:bytesize) ? body.bytesize : body.size
73
+ size = Rack::Utils.bytesize(body)
73
74
  return [403, {"Content-Type" => "text/plain","Content-Length" => size.to_s}, [body]]
74
75
  end
75
76
 
@@ -88,6 +89,8 @@ table { width:100%%; }
88
89
  type = stat.directory? ? 'directory' : Mime.mime_type(ext)
89
90
  size = stat.directory? ? '-' : filesize_format(size)
90
91
  mtime = stat.mtime.httpdate
92
+ url << '/' if stat.directory?
93
+ basename << '/' if stat.directory?
91
94
 
92
95
  @files << [ url, basename, size, type, mtime ]
93
96
  end
@@ -119,7 +122,7 @@ table { width:100%%; }
119
122
 
120
123
  def entity_not_found
121
124
  body = "Entity not found: #{@path_info}\n"
122
- size = body.respond_to?(:bytesize) ? body.bytesize : body.size
125
+ size = Rack::Utils.bytesize(body)
123
126
  return [404, {"Content-Type" => "text/plain", "Content-Length" => size.to_s}, [body]]
124
127
  end
125
128
 
@@ -1,4 +1,5 @@
1
1
  require 'time'
2
+ require 'rack/utils'
2
3
  require 'rack/mime'
3
4
 
4
5
  module Rack
@@ -12,6 +13,8 @@ module Rack
12
13
  attr_accessor :root
13
14
  attr_accessor :path
14
15
 
16
+ alias :to_path :path
17
+
15
18
  def initialize(root)
16
19
  @root = root
17
20
  end
@@ -57,7 +60,7 @@ module Rack
57
60
  body = self
58
61
  else
59
62
  body = [F.read(@path)]
60
- size = body.first.size
63
+ size = Utils.bytesize(body.first)
61
64
  end
62
65
 
63
66
  [200, {
@@ -10,16 +10,37 @@ module Rack
10
10
  module Handler
11
11
  def self.get(server)
12
12
  return unless server
13
+ server = server.to_s
13
14
 
14
15
  if klass = @handlers[server]
15
16
  obj = Object
16
17
  klass.split("::").each { |x| obj = obj.const_get(x) }
17
18
  obj
18
19
  else
19
- Rack::Handler.const_get(server.capitalize)
20
+ try_require('rack/handler', server)
21
+ const_get(server)
20
22
  end
21
23
  end
22
24
 
25
+ # Transforms server-name constants to their canonical form as filenames,
26
+ # then tries to require them but silences the LoadError if not found
27
+ #
28
+ # Naming convention:
29
+ #
30
+ # Foo # => 'foo'
31
+ # FooBar # => 'foo_bar.rb'
32
+ # FooBAR # => 'foobar.rb'
33
+ # FOObar # => 'foobar.rb'
34
+ # FOOBAR # => 'foobar.rb'
35
+ # FooBarBaz # => 'foo_bar_baz.rb'
36
+ def self.try_require(prefix, const_name)
37
+ file = const_name.gsub(/^[A-Z]+/) { |pre| pre.downcase }.
38
+ gsub(/[A-Z]+[^A-Z]/, '_\&').downcase
39
+
40
+ require(::File.join(prefix, file))
41
+ rescue LoadError
42
+ end
43
+
23
44
  def self.register(server, klass)
24
45
  @handlers ||= {}
25
46
  @handlers[server] = klass
@@ -1,3 +1,5 @@
1
+ require 'rack/content_length'
2
+
1
3
  module Rack
2
4
  module Handler
3
5
  class CGI
@@ -6,14 +8,16 @@ module Rack
6
8
  end
7
9
 
8
10
  def self.serve(app)
11
+ app = ContentLength.new(app)
12
+
9
13
  env = ENV.to_hash
10
14
  env.delete "HTTP_CONTENT_LENGTH"
11
15
 
12
16
  env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
13
17
 
14
18
  env.update({"rack.version" => [0,1],
15
- "rack.input" => STDIN,
16
- "rack.errors" => STDERR,
19
+ "rack.input" => $stdin,
20
+ "rack.errors" => $stderr,
17
21
 
18
22
  "rack.multithread" => false,
19
23
  "rack.multiprocess" => true,
@@ -38,7 +42,7 @@ module Rack
38
42
  def self.send_headers(status, headers)
39
43
  STDOUT.print "Status: #{status}\r\n"
40
44
  headers.each { |k, vs|
41
- vs.each { |v|
45
+ vs.split("\n").each { |v|
42
46
  STDOUT.print "#{k}: #{v}\r\n"
43
47
  }
44
48
  }
@@ -1,5 +1,17 @@
1
1
  require 'fcgi'
2
2
  require 'socket'
3
+ require 'rack/content_length'
4
+ require 'rack/rewindable_input'
5
+
6
+ class FCGI::Stream
7
+ alias _rack_read_without_buffer read
8
+
9
+ def read(n, buffer=nil)
10
+ buf = _rack_read_without_buffer n
11
+ buffer.replace(buf.to_s) if buffer
12
+ buf
13
+ end
14
+ end
3
15
 
4
16
  module Rack
5
17
  module Handler
@@ -12,32 +24,18 @@ module Rack
12
24
  }
13
25
  end
14
26
 
15
- module ProperStream # :nodoc:
16
- def each # This is missing by default.
17
- while line = gets
18
- yield line
19
- end
20
- end
21
-
22
- def read(*args)
23
- if args.empty?
24
- super || "" # Empty string on EOF.
25
- else
26
- super
27
- end
28
- end
29
- end
30
-
31
27
  def self.serve(request, app)
28
+ app = Rack::ContentLength.new(app)
29
+
32
30
  env = request.env
33
31
  env.delete "HTTP_CONTENT_LENGTH"
34
32
 
35
- request.in.extend ProperStream
36
-
37
33
  env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
34
+
35
+ rack_input = RewindableInput.new(request.in)
38
36
 
39
37
  env.update({"rack.version" => [0,1],
40
- "rack.input" => request.in,
38
+ "rack.input" => rack_input,
41
39
  "rack.errors" => request.err,
42
40
 
43
41
  "rack.multithread" => false,
@@ -54,12 +52,16 @@ module Rack
54
52
  env.delete "CONTENT_TYPE" if env["CONTENT_TYPE"] == ""
55
53
  env.delete "CONTENT_LENGTH" if env["CONTENT_LENGTH"] == ""
56
54
 
57
- status, headers, body = app.call(env)
58
55
  begin
59
- send_headers request.out, status, headers
60
- send_body request.out, body
56
+ status, headers, body = app.call(env)
57
+ begin
58
+ send_headers request.out, status, headers
59
+ send_body request.out, body
60
+ ensure
61
+ body.close if body.respond_to? :close
62
+ end
61
63
  ensure
62
- body.close if body.respond_to? :close
64
+ rack_input.close
63
65
  request.finish
64
66
  end
65
67
  end
@@ -67,7 +69,7 @@ module Rack
67
69
  def self.send_headers(out, status, headers)
68
70
  out.print "Status: #{status}\r\n"
69
71
  headers.each { |k, vs|
70
- vs.each { |v|
72
+ vs.split("\n").each { |v|
71
73
  out.print "#{k}: #{v}\r\n"
72
74
  }
73
75
  }