colouringcode-passenger 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (170) hide show
  1. data/NEWS +129 -0
  2. data/Rakefile +2 -2
  3. data/bin/passenger-install-apache2-module +1 -0
  4. data/bin/passenger-install-nginx-module +4 -2
  5. data/ext/apache2/Hooks.cpp +4 -2
  6. data/ext/common/ApplicationPoolServer.h +1 -1
  7. data/ext/common/ApplicationPoolServerExecutable.cpp +1 -1
  8. data/ext/common/MessageChannel.h +48 -4
  9. data/ext/common/StandardApplicationPool.h +4 -2
  10. data/ext/common/Version.h +1 -1
  11. data/ext/nginx/Configuration.c +1 -1
  12. data/ext/nginx/HttpStatusExtractor.h +1 -0
  13. data/ext/nginx/ScgiRequestParser.h +1 -0
  14. data/ext/oxt/system_calls.cpp +11 -0
  15. data/ext/oxt/system_calls.hpp +2 -1
  16. data/ext/oxt/thread.hpp +97 -1
  17. data/ext/phusion_passenger/native_support.c +30 -1
  18. data/lib/phusion_passenger/constants.rb +1 -1
  19. data/lib/phusion_passenger/dependencies.rb +32 -0
  20. data/lib/phusion_passenger/message_channel.rb +45 -3
  21. data/lib/phusion_passenger/platform_info.rb +1 -1
  22. data/lib/phusion_passenger/rack/application_spawner.rb +10 -4
  23. data/lib/phusion_passenger/rack/request_handler.rb +2 -5
  24. data/lib/phusion_passenger/railz/application_spawner.rb +59 -7
  25. data/lib/phusion_passenger/utils.rb +70 -16
  26. data/{vendor/rack-1.0.0-git/lib/rack → lib/phusion_passenger/utils}/rewindable_input.rb +34 -9
  27. data/test/ApplicationPoolTest.cpp +1 -1
  28. data/test/MessageChannelTest.cpp +9 -1
  29. data/test/stub/message_channel.rb +1 -1
  30. data/test/stub/message_channel_2.rb +1 -1
  31. data/test/stub/message_channel_3.rb +2 -2
  32. metadata +43 -155
  33. data/doc/Architectural overview.html +0 -1
  34. data/doc/rdoc/classes/ConditionVariable.html +0 -194
  35. data/doc/rdoc/classes/Exception.html +0 -120
  36. data/doc/rdoc/classes/GC.html +0 -113
  37. data/doc/rdoc/classes/IO.html +0 -169
  38. data/doc/rdoc/classes/PhusionPassenger.html +0 -238
  39. data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +0 -153
  40. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +0 -517
  41. data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +0 -719
  42. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerAlreadyStarted.html +0 -97
  43. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerError.html +0 -96
  44. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerNotStarted.html +0 -97
  45. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/UnknownMessage.html +0 -96
  46. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +0 -598
  47. data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +0 -140
  48. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +0 -317
  49. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess/Instance.html +0 -138
  50. data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +0 -154
  51. data/doc/rdoc/classes/PhusionPassenger/Application.html +0 -283
  52. data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +0 -172
  53. data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +0 -145
  54. data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +0 -181
  55. data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +0 -141
  56. data/doc/rdoc/classes/PhusionPassenger/InvalidPath.html +0 -92
  57. data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +0 -489
  58. data/doc/rdoc/classes/PhusionPassenger/NativeSupport.html +0 -350
  59. data/doc/rdoc/classes/PhusionPassenger/Rack.html +0 -91
  60. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +0 -188
  61. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +0 -199
  62. data/doc/rdoc/classes/PhusionPassenger/Railz.html +0 -95
  63. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +0 -438
  64. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner/Error.html +0 -98
  65. data/doc/rdoc/classes/PhusionPassenger/Railz/CGIFixed.html +0 -200
  66. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +0 -436
  67. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner/Error.html +0 -98
  68. data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +0 -155
  69. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +0 -402
  70. data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +0 -125
  71. data/doc/rdoc/classes/PhusionPassenger/Utils.html +0 -803
  72. data/doc/rdoc/classes/PhusionPassenger/Utils/PseudoIO.html +0 -169
  73. data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +0 -140
  74. data/doc/rdoc/classes/PhusionPassenger/WSGI.html +0 -89
  75. data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +0 -188
  76. data/doc/rdoc/classes/PlatformInfo.html +0 -866
  77. data/doc/rdoc/classes/RakeExtensions.html +0 -197
  78. data/doc/rdoc/classes/Signal.html +0 -131
  79. data/doc/rdoc/created.rid +0 -1
  80. data/doc/rdoc/files/DEVELOPERS_TXT.html +0 -255
  81. data/doc/rdoc/files/README.html +0 -175
  82. data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +0 -92
  83. data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +0 -129
  84. data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +0 -129
  85. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +0 -126
  86. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +0 -128
  87. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +0 -130
  88. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +0 -122
  89. data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +0 -127
  90. data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +0 -126
  91. data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +0 -122
  92. data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +0 -134
  93. data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +0 -122
  94. data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +0 -122
  95. data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +0 -126
  96. data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +0 -120
  97. data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +0 -122
  98. data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +0 -127
  99. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +0 -133
  100. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +0 -125
  101. data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +0 -140
  102. data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +0 -126
  103. data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +0 -145
  104. data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +0 -125
  105. data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +0 -122
  106. data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +0 -159
  107. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +0 -174
  108. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +0 -129
  109. data/doc/rdoc/files/misc/rake/extensions_rb.html +0 -130
  110. data/doc/rdoc/fr_class_index.html +0 -91
  111. data/doc/rdoc/fr_file_index.html +0 -76
  112. data/doc/rdoc/fr_method_index.html +0 -205
  113. data/doc/rdoc/index.html +0 -26
  114. data/doc/rdoc/rdoc-style.css +0 -187
  115. data/vendor/README +0 -13
  116. data/vendor/README_FOR_PACKAGERS +0 -1
  117. data/vendor/rack-1.0.0-git/COPYING +0 -18
  118. data/vendor/rack-1.0.0-git/KNOWN-ISSUES +0 -18
  119. data/vendor/rack-1.0.0-git/README +0 -353
  120. data/vendor/rack-1.0.0-git/Rakefile +0 -164
  121. data/vendor/rack-1.0.0-git/lib/rack.rb +0 -90
  122. data/vendor/rack-1.0.0-git/lib/rack/adapter/camping.rb +0 -22
  123. data/vendor/rack-1.0.0-git/lib/rack/auth/abstract/handler.rb +0 -37
  124. data/vendor/rack-1.0.0-git/lib/rack/auth/abstract/request.rb +0 -37
  125. data/vendor/rack-1.0.0-git/lib/rack/auth/basic.rb +0 -58
  126. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/md5.rb +0 -124
  127. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/nonce.rb +0 -51
  128. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/params.rb +0 -55
  129. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/request.rb +0 -40
  130. data/vendor/rack-1.0.0-git/lib/rack/auth/openid.rb +0 -487
  131. data/vendor/rack-1.0.0-git/lib/rack/builder.rb +0 -63
  132. data/vendor/rack-1.0.0-git/lib/rack/cascade.rb +0 -41
  133. data/vendor/rack-1.0.0-git/lib/rack/chunked.rb +0 -49
  134. data/vendor/rack-1.0.0-git/lib/rack/commonlogger.rb +0 -52
  135. data/vendor/rack-1.0.0-git/lib/rack/conditionalget.rb +0 -47
  136. data/vendor/rack-1.0.0-git/lib/rack/content_length.rb +0 -29
  137. data/vendor/rack-1.0.0-git/lib/rack/content_type.rb +0 -23
  138. data/vendor/rack-1.0.0-git/lib/rack/deflater.rb +0 -96
  139. data/vendor/rack-1.0.0-git/lib/rack/directory.rb +0 -153
  140. data/vendor/rack-1.0.0-git/lib/rack/file.rb +0 -88
  141. data/vendor/rack-1.0.0-git/lib/rack/handler.rb +0 -69
  142. data/vendor/rack-1.0.0-git/lib/rack/handler/cgi.rb +0 -61
  143. data/vendor/rack-1.0.0-git/lib/rack/handler/evented_mongrel.rb +0 -8
  144. data/vendor/rack-1.0.0-git/lib/rack/handler/fastcgi.rb +0 -88
  145. data/vendor/rack-1.0.0-git/lib/rack/handler/lsws.rb +0 -55
  146. data/vendor/rack-1.0.0-git/lib/rack/handler/mongrel.rb +0 -84
  147. data/vendor/rack-1.0.0-git/lib/rack/handler/scgi.rb +0 -59
  148. data/vendor/rack-1.0.0-git/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  149. data/vendor/rack-1.0.0-git/lib/rack/handler/thin.rb +0 -18
  150. data/vendor/rack-1.0.0-git/lib/rack/handler/webrick.rb +0 -67
  151. data/vendor/rack-1.0.0-git/lib/rack/head.rb +0 -19
  152. data/vendor/rack-1.0.0-git/lib/rack/lint.rb +0 -537
  153. data/vendor/rack-1.0.0-git/lib/rack/lobster.rb +0 -65
  154. data/vendor/rack-1.0.0-git/lib/rack/lock.rb +0 -16
  155. data/vendor/rack-1.0.0-git/lib/rack/methodoverride.rb +0 -27
  156. data/vendor/rack-1.0.0-git/lib/rack/mime.rb +0 -204
  157. data/vendor/rack-1.0.0-git/lib/rack/mock.rb +0 -184
  158. data/vendor/rack-1.0.0-git/lib/rack/recursive.rb +0 -57
  159. data/vendor/rack-1.0.0-git/lib/rack/reloader.rb +0 -106
  160. data/vendor/rack-1.0.0-git/lib/rack/request.rb +0 -248
  161. data/vendor/rack-1.0.0-git/lib/rack/response.rb +0 -183
  162. data/vendor/rack-1.0.0-git/lib/rack/session/abstract/id.rb +0 -142
  163. data/vendor/rack-1.0.0-git/lib/rack/session/cookie.rb +0 -91
  164. data/vendor/rack-1.0.0-git/lib/rack/session/memcache.rb +0 -109
  165. data/vendor/rack-1.0.0-git/lib/rack/session/pool.rb +0 -100
  166. data/vendor/rack-1.0.0-git/lib/rack/showexceptions.rb +0 -349
  167. data/vendor/rack-1.0.0-git/lib/rack/showstatus.rb +0 -106
  168. data/vendor/rack-1.0.0-git/lib/rack/static.rb +0 -38
  169. data/vendor/rack-1.0.0-git/lib/rack/urlmap.rb +0 -55
  170. data/vendor/rack-1.0.0-git/lib/rack/utils.rb +0 -522
@@ -1,63 +0,0 @@
1
- module Rack
2
- # Rack::Builder implements a small DSL to iteratively construct Rack
3
- # applications.
4
- #
5
- # Example:
6
- #
7
- # app = Rack::Builder.new {
8
- # use Rack::CommonLogger
9
- # use Rack::ShowExceptions
10
- # map "/lobster" do
11
- # use Rack::Lint
12
- # run Rack::Lobster.new
13
- # end
14
- # }
15
- #
16
- # Or
17
- #
18
- # app = Rack::Builder.app do
19
- # use Rack::CommonLogger
20
- # lambda { |env| [200, {'Content-Type' => 'text/plain'}, 'OK'] }
21
- # end
22
- #
23
- # +use+ adds a middleware to the stack, +run+ dispatches to an application.
24
- # You can use +map+ to construct a Rack::URLMap in a convenient way.
25
-
26
- class Builder
27
- def initialize(&block)
28
- @ins = []
29
- instance_eval(&block) if block_given?
30
- end
31
-
32
- def self.app(&block)
33
- self.new(&block).to_app
34
- end
35
-
36
- def use(middleware, *args, &block)
37
- @ins << lambda { |app| middleware.new(app, *args, &block) }
38
- end
39
-
40
- def run(app)
41
- @ins << app #lambda { |nothing| app }
42
- end
43
-
44
- def map(path, &block)
45
- if @ins.last.kind_of? Hash
46
- @ins.last[path] = self.class.new(&block).to_app
47
- else
48
- @ins << {}
49
- map(path, &block)
50
- end
51
- end
52
-
53
- def to_app
54
- @ins[-1] = Rack::URLMap.new(@ins.last) if Hash === @ins.last
55
- inner_app = @ins.last
56
- @ins[0...-1].reverse.inject(inner_app) { |a, e| e.call(a) }
57
- end
58
-
59
- def call(env)
60
- to_app.call(env)
61
- end
62
- end
63
- end
@@ -1,41 +0,0 @@
1
- module Rack
2
- # Rack::Cascade tries an request on several apps, and returns the
3
- # first response that is not 404 (or in a list of configurable
4
- # status codes).
5
-
6
- class Cascade
7
- NotFound = [404, {}, []]
8
-
9
- attr_reader :apps
10
-
11
- def initialize(apps, catch=404)
12
- @apps = []; @has_app = {}
13
- apps.each { |app| add app }
14
-
15
- @catch = {}
16
- [*catch].each { |status| @catch[status] = true }
17
- end
18
-
19
- def call(env)
20
- result = NotFound
21
-
22
- @apps.each do |app|
23
- result = app.call(env)
24
- break unless @catch.include?(result[0].to_i)
25
- end
26
-
27
- result
28
- end
29
-
30
- def add app
31
- @has_app[app] = true
32
- @apps << app
33
- end
34
-
35
- def include? app
36
- @has_app.include? app
37
- end
38
-
39
- alias_method :<<, :add
40
- end
41
- end
@@ -1,49 +0,0 @@
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,52 +0,0 @@
1
- module Rack
2
- # Rack::CommonLogger forwards every request to an +app+ given, and
3
- # logs a line in the Apache common log format to the +logger+, or
4
- # rack.errors by default.
5
- class CommonLogger
6
- # Common Log Format: http://httpd.apache.org/docs/1.3/logs.html#common
7
- # lilith.local - - [07/Aug/2006 23:58:02] "GET / HTTP/1.1" 500 -
8
- # %{%s - %s [%s] "%s %s%s %s" %d %s\n} %
9
- FORMAT = %{%s - %s [%s] "%s %s%s %s" %d %s %0.4f\n}
10
-
11
- def initialize(app, logger=nil)
12
- @app = app
13
- @logger = logger
14
- end
15
-
16
- def call(env)
17
- began_at = Time.now
18
- status, header, body = @app.call(env)
19
- log(env, status, header, began_at)
20
- [status, header, body]
21
- end
22
-
23
- private
24
-
25
- def log(env, status, header, began_at)
26
- now = Time.now
27
- length = extract_content_length(header)
28
-
29
- logger = @logger || env['rack.errors']
30
- logger.write FORMAT % [
31
- env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-",
32
- env["REMOTE_USER"] || "-",
33
- now.strftime("%d/%b/%Y %H:%M:%S"),
34
- env["REQUEST_METHOD"],
35
- env["PATH_INFO"],
36
- env["QUERY_STRING"].empty? ? "" : "?"+env["QUERY_STRING"],
37
- env["HTTP_VERSION"],
38
- status.to_s[0..3],
39
- length,
40
- now - began_at ]
41
- end
42
-
43
- def extract_content_length(headers)
44
- headers.each do |key, value|
45
- if key.downcase == 'content-length'
46
- return value.to_s == '0' ? '-' : value
47
- end
48
- end
49
- '-'
50
- end
51
- end
52
- end
@@ -1,47 +0,0 @@
1
- require 'rack/utils'
2
-
3
- module Rack
4
-
5
- # Middleware that enables conditional GET using If-None-Match and
6
- # If-Modified-Since. The application should set either or both of the
7
- # Last-Modified or Etag response headers according to RFC 2616. When
8
- # either of the conditions is met, the response body is set to be zero
9
- # length and the response status is set to 304 Not Modified.
10
- #
11
- # Applications that defer response body generation until the body's each
12
- # message is received will avoid response body generation completely when
13
- # a conditional GET matches.
14
- #
15
- # Adapted from Michael Klishin's Merb implementation:
16
- # http://github.com/wycats/merb-core/tree/master/lib/merb-core/rack/middleware/conditional_get.rb
17
- class ConditionalGet
18
- def initialize(app)
19
- @app = app
20
- end
21
-
22
- def call(env)
23
- return @app.call(env) unless %w[GET HEAD].include?(env['REQUEST_METHOD'])
24
-
25
- status, headers, body = @app.call(env)
26
- headers = Utils::HeaderHash.new(headers)
27
- if etag_matches?(env, headers) || modified_since?(env, headers)
28
- status = 304
29
- headers.delete('Content-Type')
30
- headers.delete('Content-Length')
31
- body = []
32
- end
33
- [status, headers, body]
34
- end
35
-
36
- private
37
- def etag_matches?(env, headers)
38
- etag = headers['Etag'] and etag == env['HTTP_IF_NONE_MATCH']
39
- end
40
-
41
- def modified_since?(env, headers)
42
- last_modified = headers['Last-Modified'] and
43
- last_modified == env['HTTP_IF_MODIFIED_SINCE']
44
- end
45
- end
46
-
47
- end
@@ -1,29 +0,0 @@
1
- require 'rack/utils'
2
-
3
- module Rack
4
- # Sets the Content-Length header on responses with fixed-length bodies.
5
- class ContentLength
6
- include Rack::Utils
7
-
8
- def initialize(app)
9
- @app = app
10
- end
11
-
12
- def call(env)
13
- status, headers, body = @app.call(env)
14
- headers = HeaderHash.new(headers)
15
-
16
- if !STATUS_WITH_NO_ENTITY_BODY.include?(status) &&
17
- !headers['Content-Length'] &&
18
- !headers['Transfer-Encoding'] &&
19
- (body.respond_to?(:to_ary) || body.respond_to?(:to_str))
20
-
21
- body = [body] if body.respond_to?(:to_str) # rack 0.4 compat
22
- length = body.to_ary.inject(0) { |len, part| len + bytesize(part) }
23
- headers['Content-Length'] = length.to_s
24
- end
25
-
26
- [status, headers, body]
27
- end
28
- end
29
- end
@@ -1,23 +0,0 @@
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
@@ -1,96 +0,0 @@
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,153 +0,0 @@
1
- require 'time'
2
- require 'rack/utils'
3
- require 'rack/mime'
4
-
5
- module Rack
6
- # Rack::Directory serves entries below the +root+ given, according to the
7
- # path info of the Rack request. If a directory is found, the file's contents
8
- # will be presented in an html based index. If a file is found, the env will
9
- # be passed to the specified +app+.
10
- #
11
- # If +app+ is not specified, a Rack::File of the same +root+ will be used.
12
-
13
- class Directory
14
- DIR_FILE = "<tr><td class='name'><a href='%s'>%s</a></td><td class='size'>%s</td><td class='type'>%s</td><td class='mtime'>%s</td></tr>"
15
- DIR_PAGE = <<-PAGE
16
- <html><head>
17
- <title>%s</title>
18
- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
19
- <style type='text/css'>
20
- table { width:100%%; }
21
- .name { text-align:left; }
22
- .size, .mtime { text-align:right; }
23
- .type { width:11em; }
24
- .mtime { width:15em; }
25
- </style>
26
- </head><body>
27
- <h1>%s</h1>
28
- <hr />
29
- <table>
30
- <tr>
31
- <th class='name'>Name</th>
32
- <th class='size'>Size</th>
33
- <th class='type'>Type</th>
34
- <th class='mtime'>Last Modified</th>
35
- </tr>
36
- %s
37
- </table>
38
- <hr />
39
- </body></html>
40
- PAGE
41
-
42
- attr_reader :files
43
- attr_accessor :root, :path
44
-
45
- def initialize(root, app=nil)
46
- @root = F.expand_path(root)
47
- @app = app || Rack::File.new(@root)
48
- end
49
-
50
- def call(env)
51
- dup._call(env)
52
- end
53
-
54
- F = ::File
55
-
56
- def _call(env)
57
- @env = env
58
- @script_name = env['SCRIPT_NAME']
59
- @path_info = Utils.unescape(env['PATH_INFO'])
60
-
61
- if forbidden = check_forbidden
62
- forbidden
63
- else
64
- @path = F.join(@root, @path_info)
65
- list_path
66
- end
67
- end
68
-
69
- def check_forbidden
70
- return unless @path_info.include? ".."
71
-
72
- body = "Forbidden\n"
73
- size = Rack::Utils.bytesize(body)
74
- return [403, {"Content-Type" => "text/plain","Content-Length" => size.to_s}, [body]]
75
- end
76
-
77
- def list_directory
78
- @files = [['../','Parent Directory','','','']]
79
- glob = F.join(@path, '*')
80
-
81
- Dir[glob].sort.each do |node|
82
- stat = stat(node)
83
- next unless stat
84
- basename = F.basename(node)
85
- ext = F.extname(node)
86
-
87
- url = F.join(@script_name, @path_info, basename)
88
- size = stat.size
89
- type = stat.directory? ? 'directory' : Mime.mime_type(ext)
90
- size = stat.directory? ? '-' : filesize_format(size)
91
- mtime = stat.mtime.httpdate
92
- url << '/' if stat.directory?
93
- basename << '/' if stat.directory?
94
-
95
- @files << [ url, basename, size, type, mtime ]
96
- end
97
-
98
- return [ 200, {'Content-Type'=>'text/html; charset=utf-8'}, self ]
99
- end
100
-
101
- def stat(node, max = 10)
102
- F.stat(node)
103
- rescue Errno::ENOENT, Errno::ELOOP
104
- return nil
105
- end
106
-
107
- # TODO: add correct response if not readable, not sure if 404 is the best
108
- # option
109
- def list_path
110
- @stat = F.stat(@path)
111
-
112
- if @stat.readable?
113
- return @app.call(@env) if @stat.file?
114
- return list_directory if @stat.directory?
115
- else
116
- raise Errno::ENOENT, 'No such file or directory'
117
- end
118
-
119
- rescue Errno::ENOENT, Errno::ELOOP
120
- return entity_not_found
121
- end
122
-
123
- def entity_not_found
124
- body = "Entity not found: #{@path_info}\n"
125
- size = Rack::Utils.bytesize(body)
126
- return [404, {"Content-Type" => "text/plain", "Content-Length" => size.to_s}, [body]]
127
- end
128
-
129
- def each
130
- show_path = @path.sub(/^#{@root}/,'')
131
- files = @files.map{|f| DIR_FILE % f }*"\n"
132
- page = DIR_PAGE % [ show_path, show_path , files ]
133
- page.each_line{|l| yield l }
134
- end
135
-
136
- # Stolen from Ramaze
137
-
138
- FILESIZE_FORMAT = [
139
- ['%.1fT', 1 << 40],
140
- ['%.1fG', 1 << 30],
141
- ['%.1fM', 1 << 20],
142
- ['%.1fK', 1 << 10],
143
- ]
144
-
145
- def filesize_format(int)
146
- FILESIZE_FORMAT.each do |format, size|
147
- return format % (int.to_f / size) if int >= size
148
- end
149
-
150
- int.to_s + 'B'
151
- end
152
- end
153
- end