passenger 2.2.7 → 2.2.8

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 (160) hide show
  1. data/NEWS +40 -0
  2. data/Rakefile +1 -1
  3. data/bin/passenger-install-apache2-module +1 -0
  4. data/bin/passenger-install-nginx-module +2 -0
  5. data/doc/Architectural overview.html +173 -138
  6. data/doc/Security of user switching support.html +147 -109
  7. data/doc/Users guide Apache.html +4 -43
  8. data/doc/Users guide Nginx.html +4 -43
  9. data/doc/cxxapi/Bucket_8h-source.html +1 -1
  10. data/doc/cxxapi/Configuration_8h-source.html +1 -1
  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 -1
  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/rdoc/classes/GC.html +4 -4
  31. data/doc/rdoc/classes/PhusionPassenger.html +2 -1
  32. data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +8 -8
  33. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +26 -26
  34. data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +98 -98
  35. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +61 -61
  36. data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +4 -4
  37. data/doc/rdoc/classes/PhusionPassenger/Application.html +14 -14
  38. data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +12 -12
  39. data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +4 -4
  40. data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +12 -12
  41. data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +5 -5
  42. data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +42 -42
  43. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +33 -33
  44. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +59 -59
  45. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +3 -3
  46. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +7 -7
  47. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +23 -23
  48. data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +4 -4
  49. data/doc/rdoc/classes/PhusionPassenger/Utils.html +2 -0
  50. data/doc/rdoc/classes/PhusionPassenger/Utils/PseudoIO.html +16 -16
  51. data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +4 -4
  52. data/doc/rdoc/classes/PlatformInfo.html +1 -1
  53. data/doc/rdoc/classes/Signal.html +23 -15
  54. data/doc/rdoc/created.rid +1 -1
  55. data/doc/rdoc/files/DEVELOPERS_TXT.html +1 -1
  56. data/doc/rdoc/files/README.html +1 -1
  57. data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +1 -1
  58. data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +1 -1
  59. data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +1 -1
  60. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +1 -1
  61. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +1 -1
  62. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +1 -1
  63. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +1 -1
  64. data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +1 -1
  65. data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +1 -1
  66. data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +1 -1
  67. data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +1 -1
  68. data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +1 -1
  69. data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +1 -1
  70. data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +1 -1
  71. data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +1 -1
  72. data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +1 -1
  73. data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +1 -1
  74. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +2 -2
  75. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +2 -2
  76. data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +1 -1
  77. data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +1 -1
  78. data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +1 -1
  79. data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +1 -1
  80. data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +1 -1
  81. data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +1 -1
  82. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +9 -9
  83. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +1 -1
  84. data/doc/rdoc/files/misc/rake/extensions_rb.html +1 -1
  85. data/doc/rdoc/fr_class_index.html +2 -0
  86. data/doc/rdoc/fr_file_index.html +1 -0
  87. data/doc/rdoc/fr_method_index.html +79 -72
  88. data/ext/apache2/Hooks.cpp +4 -2
  89. data/ext/common/StandardApplicationPool.h +4 -2
  90. data/ext/common/Version.h +1 -1
  91. data/ext/nginx/Configuration.c +1 -1
  92. data/ext/oxt/system_calls.cpp +11 -0
  93. data/ext/oxt/system_calls.hpp +2 -1
  94. data/ext/oxt/thread.hpp +97 -1
  95. data/lib/phusion_passenger/constants.rb +1 -1
  96. data/lib/phusion_passenger/dependencies.rb +32 -0
  97. data/lib/phusion_passenger/platform_info.rb +1 -1
  98. data/lib/phusion_passenger/rack/application_spawner.rb +4 -4
  99. data/lib/phusion_passenger/rack/request_handler.rb +2 -5
  100. data/lib/phusion_passenger/railz/application_spawner.rb +13 -2
  101. data/lib/phusion_passenger/utils.rb +12 -4
  102. data/{vendor/rack-1.0.0-git/lib/rack → lib/phusion_passenger/utils}/rewindable_input.rb +19 -3
  103. data/test/ApplicationPoolTest.cpp +1 -1
  104. metadata +13 -59
  105. data/vendor/README +0 -13
  106. data/vendor/README_FOR_PACKAGERS +0 -1
  107. data/vendor/rack-1.0.0-git/COPYING +0 -18
  108. data/vendor/rack-1.0.0-git/KNOWN-ISSUES +0 -18
  109. data/vendor/rack-1.0.0-git/README +0 -353
  110. data/vendor/rack-1.0.0-git/Rakefile +0 -164
  111. data/vendor/rack-1.0.0-git/lib/rack.rb +0 -90
  112. data/vendor/rack-1.0.0-git/lib/rack/adapter/camping.rb +0 -22
  113. data/vendor/rack-1.0.0-git/lib/rack/auth/abstract/handler.rb +0 -37
  114. data/vendor/rack-1.0.0-git/lib/rack/auth/abstract/request.rb +0 -37
  115. data/vendor/rack-1.0.0-git/lib/rack/auth/basic.rb +0 -58
  116. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/md5.rb +0 -124
  117. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/nonce.rb +0 -51
  118. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/params.rb +0 -55
  119. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/request.rb +0 -40
  120. data/vendor/rack-1.0.0-git/lib/rack/auth/openid.rb +0 -487
  121. data/vendor/rack-1.0.0-git/lib/rack/builder.rb +0 -63
  122. data/vendor/rack-1.0.0-git/lib/rack/cascade.rb +0 -41
  123. data/vendor/rack-1.0.0-git/lib/rack/chunked.rb +0 -49
  124. data/vendor/rack-1.0.0-git/lib/rack/commonlogger.rb +0 -52
  125. data/vendor/rack-1.0.0-git/lib/rack/conditionalget.rb +0 -47
  126. data/vendor/rack-1.0.0-git/lib/rack/content_length.rb +0 -29
  127. data/vendor/rack-1.0.0-git/lib/rack/content_type.rb +0 -23
  128. data/vendor/rack-1.0.0-git/lib/rack/deflater.rb +0 -96
  129. data/vendor/rack-1.0.0-git/lib/rack/directory.rb +0 -153
  130. data/vendor/rack-1.0.0-git/lib/rack/file.rb +0 -88
  131. data/vendor/rack-1.0.0-git/lib/rack/handler.rb +0 -69
  132. data/vendor/rack-1.0.0-git/lib/rack/handler/cgi.rb +0 -61
  133. data/vendor/rack-1.0.0-git/lib/rack/handler/evented_mongrel.rb +0 -8
  134. data/vendor/rack-1.0.0-git/lib/rack/handler/fastcgi.rb +0 -88
  135. data/vendor/rack-1.0.0-git/lib/rack/handler/lsws.rb +0 -55
  136. data/vendor/rack-1.0.0-git/lib/rack/handler/mongrel.rb +0 -84
  137. data/vendor/rack-1.0.0-git/lib/rack/handler/scgi.rb +0 -59
  138. data/vendor/rack-1.0.0-git/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  139. data/vendor/rack-1.0.0-git/lib/rack/handler/thin.rb +0 -18
  140. data/vendor/rack-1.0.0-git/lib/rack/handler/webrick.rb +0 -67
  141. data/vendor/rack-1.0.0-git/lib/rack/head.rb +0 -19
  142. data/vendor/rack-1.0.0-git/lib/rack/lint.rb +0 -537
  143. data/vendor/rack-1.0.0-git/lib/rack/lobster.rb +0 -65
  144. data/vendor/rack-1.0.0-git/lib/rack/lock.rb +0 -16
  145. data/vendor/rack-1.0.0-git/lib/rack/methodoverride.rb +0 -27
  146. data/vendor/rack-1.0.0-git/lib/rack/mime.rb +0 -204
  147. data/vendor/rack-1.0.0-git/lib/rack/mock.rb +0 -184
  148. data/vendor/rack-1.0.0-git/lib/rack/recursive.rb +0 -57
  149. data/vendor/rack-1.0.0-git/lib/rack/reloader.rb +0 -106
  150. data/vendor/rack-1.0.0-git/lib/rack/request.rb +0 -248
  151. data/vendor/rack-1.0.0-git/lib/rack/response.rb +0 -183
  152. data/vendor/rack-1.0.0-git/lib/rack/session/abstract/id.rb +0 -142
  153. data/vendor/rack-1.0.0-git/lib/rack/session/cookie.rb +0 -91
  154. data/vendor/rack-1.0.0-git/lib/rack/session/memcache.rb +0 -109
  155. data/vendor/rack-1.0.0-git/lib/rack/session/pool.rb +0 -100
  156. data/vendor/rack-1.0.0-git/lib/rack/showexceptions.rb +0 -349
  157. data/vendor/rack-1.0.0-git/lib/rack/showstatus.rb +0 -106
  158. data/vendor/rack-1.0.0-git/lib/rack/static.rb +0 -38
  159. data/vendor/rack-1.0.0-git/lib/rack/urlmap.rb +0 -55
  160. data/vendor/rack-1.0.0-git/lib/rack/utils.rb +0 -522
@@ -1,57 +0,0 @@
1
- require 'uri'
2
-
3
- module Rack
4
- # Rack::ForwardRequest gets caught by Rack::Recursive and redirects
5
- # the current request to the app at +url+.
6
- #
7
- # raise ForwardRequest.new("/not-found")
8
- #
9
-
10
- class ForwardRequest < Exception
11
- attr_reader :url, :env
12
-
13
- def initialize(url, env={})
14
- @url = URI(url)
15
- @env = env
16
-
17
- @env["PATH_INFO"] = @url.path
18
- @env["QUERY_STRING"] = @url.query if @url.query
19
- @env["HTTP_HOST"] = @url.host if @url.host
20
- @env["HTTP_PORT"] = @url.port if @url.port
21
- @env["rack.url_scheme"] = @url.scheme if @url.scheme
22
-
23
- super "forwarding to #{url}"
24
- end
25
- end
26
-
27
- # Rack::Recursive allows applications called down the chain to
28
- # include data from other applications (by using
29
- # <tt>rack['rack.recursive.include'][...]</tt> or raise a
30
- # ForwardRequest to redirect internally.
31
-
32
- class Recursive
33
- def initialize(app)
34
- @app = app
35
- end
36
-
37
- def call(env)
38
- @script_name = env["SCRIPT_NAME"]
39
- @app.call(env.merge('rack.recursive.include' => method(:include)))
40
- rescue ForwardRequest => req
41
- call(env.merge(req.env))
42
- end
43
-
44
- def include(env, path)
45
- unless path.index(@script_name) == 0 && (path[@script_name.size] == ?/ ||
46
- path[@script_name.size].nil?)
47
- raise ArgumentError, "can only include below #{@script_name}, not #{path}"
48
- end
49
-
50
- env = env.merge("PATH_INFO" => path, "SCRIPT_NAME" => @script_name,
51
- "REQUEST_METHOD" => "GET",
52
- "CONTENT_LENGTH" => "0", "CONTENT_TYPE" => "",
53
- "rack.input" => StringIO.new(""))
54
- @app.call(env)
55
- end
56
- end
57
- end
@@ -1,106 +0,0 @@
1
- # Copyright (c) 2009 Michael Fellinger m.fellinger@gmail.com
2
- # All files in this distribution are subject to the terms of the Ruby license.
3
-
4
- require 'pathname'
5
-
6
- module Rack
7
-
8
- # High performant source reloader
9
- #
10
- # This class acts as Rack middleware.
11
- #
12
- # What makes it especially suited for use in a production environment is that
13
- # any file will only be checked once and there will only be made one system
14
- # call stat(2).
15
- #
16
- # Please note that this will not reload files in the background, it does so
17
- # only when actively called.
18
- #
19
- # It is performing a check/reload cycle at the start of every request, but
20
- # also respects a cool down time, during which nothing will be done.
21
- class Reloader
22
- def initialize(app, cooldown = 10, backend = Stat)
23
- @app = app
24
- @cooldown = cooldown
25
- @last = (Time.now - cooldown)
26
- @cache = {}
27
- @mtimes = {}
28
-
29
- extend backend
30
- end
31
-
32
- def call(env)
33
- if @cooldown and Time.now > @last + @cooldown
34
- if Thread.list.size > 1
35
- Thread.exclusive{ reload! }
36
- else
37
- reload!
38
- end
39
-
40
- @last = Time.now
41
- end
42
-
43
- @app.call(env)
44
- end
45
-
46
- def reload!(stderr = $stderr)
47
- rotation do |file, mtime|
48
- previous_mtime = @mtimes[file] ||= mtime
49
- safe_load(file, mtime, stderr) if mtime > previous_mtime
50
- end
51
- end
52
-
53
- # A safe Kernel::load, issuing the hooks depending on the results
54
- def safe_load(file, mtime, stderr = $stderr)
55
- load(file)
56
- stderr.puts "#{self.class}: reloaded `#{file}'"
57
- file
58
- rescue LoadError, SyntaxError => ex
59
- stderr.puts ex
60
- ensure
61
- @mtimes[file] = mtime
62
- end
63
-
64
- module Stat
65
- def rotation
66
- files = [$0, *$LOADED_FEATURES].uniq
67
- paths = ['./', *$LOAD_PATH].uniq
68
-
69
- files.map{|file|
70
- next if file =~ /\.(so|bundle)$/ # cannot reload compiled files
71
-
72
- found, stat = figure_path(file, paths)
73
- next unless found and stat and mtime = stat.mtime
74
-
75
- @cache[file] = found
76
-
77
- yield(found, mtime)
78
- }.compact
79
- end
80
-
81
- # Takes a relative or absolute +file+ name, a couple possible +paths+ that
82
- # the +file+ might reside in. Returns the full path and File::Stat for the
83
- # path.
84
- def figure_path(file, paths)
85
- found = @cache[file]
86
- found = file if !found and Pathname.new(file).absolute?
87
- found, stat = safe_stat(found)
88
- return found, stat if found
89
-
90
- paths.each do |possible_path|
91
- path = ::File.join(possible_path, file)
92
- found, stat = safe_stat(path)
93
- return ::File.expand_path(found), stat if found
94
- end
95
- end
96
-
97
- def safe_stat(file)
98
- return unless file
99
- stat = ::File.stat(file)
100
- return file, stat if stat.file?
101
- rescue Errno::ENOENT, Errno::ENOTDIR
102
- @cache.delete(file) and false
103
- end
104
- end
105
- end
106
- end
@@ -1,248 +0,0 @@
1
- require 'rack/utils'
2
-
3
- module Rack
4
- # Rack::Request provides a convenient interface to a Rack
5
- # environment. It is stateless, the environment +env+ passed to the
6
- # constructor will be directly modified.
7
- #
8
- # req = Rack::Request.new(env)
9
- # req.post?
10
- # req.params["data"]
11
- #
12
- # The environment hash passed will store a reference to the Request object
13
- # instantiated so that it will only instantiate if an instance of the Request
14
- # object doesn't already exist.
15
-
16
- class Request
17
- # The environment of the request.
18
- attr_reader :env
19
-
20
- def initialize(env)
21
- @env = env
22
- end
23
-
24
- def body; @env["rack.input"] end
25
- def scheme; @env["rack.url_scheme"] end
26
- def script_name; @env["SCRIPT_NAME"].to_s end
27
- def path_info; @env["PATH_INFO"].to_s end
28
- def port; @env["SERVER_PORT"].to_i end
29
- def request_method; @env["REQUEST_METHOD"] end
30
- def query_string; @env["QUERY_STRING"].to_s end
31
- def content_length; @env['CONTENT_LENGTH'] end
32
- def content_type; @env['CONTENT_TYPE'] end
33
- def session; @env['rack.session'] ||= {} end
34
- def session_options; @env['rack.session.options'] ||= {} end
35
-
36
- # The media type (type/subtype) portion of the CONTENT_TYPE header
37
- # without any media type parameters. e.g., when CONTENT_TYPE is
38
- # "text/plain;charset=utf-8", the media-type is "text/plain".
39
- #
40
- # For more information on the use of media types in HTTP, see:
41
- # http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
42
- def media_type
43
- content_type && content_type.split(/\s*[;,]\s*/, 2).first.downcase
44
- end
45
-
46
- # The media type parameters provided in CONTENT_TYPE as a Hash, or
47
- # an empty Hash if no CONTENT_TYPE or media-type parameters were
48
- # provided. e.g., when the CONTENT_TYPE is "text/plain;charset=utf-8",
49
- # this method responds with the following Hash:
50
- # { 'charset' => 'utf-8' }
51
- def media_type_params
52
- return {} if content_type.nil?
53
- content_type.split(/\s*[;,]\s*/)[1..-1].
54
- collect { |s| s.split('=', 2) }.
55
- inject({}) { |hash,(k,v)| hash[k.downcase] = v ; hash }
56
- end
57
-
58
- # The character set of the request body if a "charset" media type
59
- # parameter was given, or nil if no "charset" was specified. Note
60
- # that, per RFC2616, text/* media types that specify no explicit
61
- # charset are to be considered ISO-8859-1.
62
- def content_charset
63
- media_type_params['charset']
64
- end
65
-
66
- def host
67
- # Remove port number.
68
- (@env["HTTP_HOST"] || @env["SERVER_NAME"]).gsub(/:\d+\z/, '')
69
- end
70
-
71
- def script_name=(s); @env["SCRIPT_NAME"] = s.to_s end
72
- def path_info=(s); @env["PATH_INFO"] = s.to_s end
73
-
74
- def get?; request_method == "GET" end
75
- def post?; request_method == "POST" end
76
- def put?; request_method == "PUT" end
77
- def delete?; request_method == "DELETE" end
78
- def head?; request_method == "HEAD" end
79
-
80
- # The set of form-data media-types. Requests that do not indicate
81
- # one of the media types presents in this list will not be eligible
82
- # for form-data / param parsing.
83
- FORM_DATA_MEDIA_TYPES = [
84
- nil,
85
- 'application/x-www-form-urlencoded',
86
- 'multipart/form-data'
87
- ]
88
-
89
- # The set of media-types. Requests that do not indicate
90
- # one of the media types presents in this list will not be eligible
91
- # for param parsing like soap attachments or generic multiparts
92
- PARSEABLE_DATA_MEDIA_TYPES = [
93
- 'multipart/related',
94
- 'multipart/mixed'
95
- ]
96
-
97
- # Determine whether the request body contains form-data by checking
98
- # the request media_type against registered form-data media-types:
99
- # "application/x-www-form-urlencoded" and "multipart/form-data". The
100
- # list of form-data media types can be modified through the
101
- # +FORM_DATA_MEDIA_TYPES+ array.
102
- def form_data?
103
- FORM_DATA_MEDIA_TYPES.include?(media_type)
104
- end
105
-
106
- # Determine whether the request body contains data by checking
107
- # the request media_type against registered parse-data media-types
108
- def parseable_data?
109
- PARSEABLE_DATA_MEDIA_TYPES.include?(media_type)
110
- end
111
-
112
- # Returns the data recieved in the query string.
113
- def GET
114
- if @env["rack.request.query_string"] == query_string
115
- @env["rack.request.query_hash"]
116
- else
117
- @env["rack.request.query_string"] = query_string
118
- @env["rack.request.query_hash"] =
119
- Utils.parse_nested_query(query_string)
120
- end
121
- end
122
-
123
- # Returns the data recieved in the request body.
124
- #
125
- # This method support both application/x-www-form-urlencoded and
126
- # multipart/form-data.
127
- def POST
128
- if @env["rack.input"].nil?
129
- raise "Missing rack.input"
130
- elsif @env["rack.request.form_input"].eql? @env["rack.input"]
131
- @env["rack.request.form_hash"]
132
- elsif form_data? || parseable_data?
133
- @env["rack.request.form_input"] = @env["rack.input"]
134
- unless @env["rack.request.form_hash"] =
135
- Utils::Multipart.parse_multipart(env)
136
- form_vars = @env["rack.input"].read
137
-
138
- # Fix for Safari Ajax postings that always append \0
139
- form_vars.sub!(/\0\z/, '')
140
-
141
- @env["rack.request.form_vars"] = form_vars
142
- @env["rack.request.form_hash"] = Utils.parse_nested_query(form_vars)
143
-
144
- @env["rack.input"].rewind
145
- end
146
- @env["rack.request.form_hash"]
147
- else
148
- {}
149
- end
150
- end
151
-
152
- # The union of GET and POST data.
153
- def params
154
- self.put? ? self.GET : self.GET.update(self.POST)
155
- rescue EOFError => e
156
- self.GET
157
- end
158
-
159
- # shortcut for request.params[key]
160
- def [](key)
161
- params[key.to_s]
162
- end
163
-
164
- # shortcut for request.params[key] = value
165
- def []=(key, value)
166
- params[key.to_s] = value
167
- end
168
-
169
- # like Hash#values_at
170
- def values_at(*keys)
171
- keys.map{|key| params[key] }
172
- end
173
-
174
- # the referer of the client or '/'
175
- def referer
176
- @env['HTTP_REFERER'] || '/'
177
- end
178
- alias referrer referer
179
-
180
-
181
- def cookies
182
- return {} unless @env["HTTP_COOKIE"]
183
-
184
- if @env["rack.request.cookie_string"] == @env["HTTP_COOKIE"]
185
- @env["rack.request.cookie_hash"]
186
- else
187
- @env["rack.request.cookie_string"] = @env["HTTP_COOKIE"]
188
- # According to RFC 2109:
189
- # If multiple cookies satisfy the criteria above, they are ordered in
190
- # the Cookie header such that those with more specific Path attributes
191
- # precede those with less specific. Ordering with respect to other
192
- # attributes (e.g., Domain) is unspecified.
193
- @env["rack.request.cookie_hash"] =
194
- Utils.parse_query(@env["rack.request.cookie_string"], ';,').inject({}) {|h,(k,v)|
195
- h[k] = Array === v ? v.first : v
196
- h
197
- }
198
- end
199
- end
200
-
201
- def xhr?
202
- @env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest"
203
- end
204
-
205
- # Tries to return a remake of the original request URL as a string.
206
- def url
207
- url = scheme + "://"
208
- url << host
209
-
210
- if scheme == "https" && port != 443 ||
211
- scheme == "http" && port != 80
212
- url << ":#{port}"
213
- end
214
-
215
- url << fullpath
216
-
217
- url
218
- end
219
-
220
- def path
221
- script_name + path_info
222
- end
223
-
224
- def fullpath
225
- query_string.empty? ? path : "#{path}?#{query_string}"
226
- end
227
-
228
- def accept_encoding
229
- @env["HTTP_ACCEPT_ENCODING"].to_s.split(/,\s*/).map do |part|
230
- m = /^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$/.match(part) # From WEBrick
231
-
232
- if m
233
- [m[1], (m[2] || 1.0).to_f]
234
- else
235
- raise "Invalid value for Accept-Encoding: #{part.inspect}"
236
- end
237
- end
238
- end
239
-
240
- def ip
241
- if addr = @env['HTTP_X_FORWARDED_FOR']
242
- addr.split(',').last.strip
243
- else
244
- @env['REMOTE_ADDR']
245
- end
246
- end
247
- end
248
- end
@@ -1,183 +0,0 @@
1
- require 'rack/request'
2
- require 'rack/utils'
3
-
4
- module Rack
5
- # Rack::Response provides a convenient interface to create a Rack
6
- # response.
7
- #
8
- # It allows setting of headers and cookies, and provides useful
9
- # defaults (a OK response containing HTML).
10
- #
11
- # You can use Response#write to iteratively generate your response,
12
- # but note that this is buffered by Rack::Response until you call
13
- # +finish+. +finish+ however can take a block inside which calls to
14
- # +write+ are syncronous with the Rack response.
15
- #
16
- # Your application's +call+ should end returning Response#finish.
17
-
18
- class Response
19
- attr_accessor :length
20
-
21
- def initialize(body=[], status=200, header={}, &block)
22
- @status = status
23
- @header = Utils::HeaderHash.new({"Content-Type" => "text/html"}.
24
- merge(header))
25
-
26
- @writer = lambda { |x| @body << x }
27
- @block = nil
28
- @length = 0
29
-
30
- @body = []
31
-
32
- if body.respond_to? :to_str
33
- write body.to_str
34
- elsif body.respond_to?(:each)
35
- body.each { |part|
36
- write part.to_s
37
- }
38
- else
39
- raise TypeError, "stringable or iterable required"
40
- end
41
-
42
- yield self if block_given?
43
- end
44
-
45
- attr_reader :header
46
- attr_accessor :status, :body
47
-
48
- def [](key)
49
- header[key]
50
- end
51
-
52
- def []=(key, value)
53
- header[key] = value
54
- end
55
-
56
- def set_cookie(key, value)
57
- case value
58
- when Hash
59
- domain = "; domain=" + value[:domain] if value[:domain]
60
- path = "; path=" + value[:path] if value[:path]
61
- # According to RFC 2109, we need dashes here.
62
- # N.B.: cgi.rb uses spaces...
63
- expires = "; expires=" + value[:expires].clone.gmtime.
64
- strftime("%a, %d-%b-%Y %H:%M:%S GMT") if value[:expires]
65
- secure = "; secure" if value[:secure]
66
- httponly = "; HttpOnly" if value[:httponly]
67
- value = value[:value]
68
- end
69
- value = [value] unless Array === value
70
- cookie = Utils.escape(key) + "=" +
71
- value.map { |v| Utils.escape v }.join("&") +
72
- "#{domain}#{path}#{expires}#{secure}#{httponly}"
73
-
74
- case self["Set-Cookie"]
75
- when Array
76
- self["Set-Cookie"] << cookie
77
- when String
78
- self["Set-Cookie"] = [self["Set-Cookie"], cookie]
79
- when nil
80
- self["Set-Cookie"] = cookie
81
- end
82
- end
83
-
84
- def delete_cookie(key, value={})
85
- unless Array === self["Set-Cookie"]
86
- self["Set-Cookie"] = [self["Set-Cookie"]].compact
87
- end
88
-
89
- self["Set-Cookie"].reject! { |cookie|
90
- cookie =~ /\A#{Utils.escape(key)}=/
91
- }
92
-
93
- set_cookie(key,
94
- {:value => '', :path => nil, :domain => nil,
95
- :expires => Time.at(0) }.merge(value))
96
- end
97
-
98
- def redirect(target, status=302)
99
- self.status = status
100
- self["Location"] = target
101
- end
102
-
103
- def finish(&block)
104
- @block = block
105
-
106
- if [204, 304].include?(status.to_i)
107
- header.delete "Content-Type"
108
- [status.to_i, header.to_hash, []]
109
- else
110
- [status.to_i, header.to_hash, self]
111
- end
112
- end
113
- alias to_a finish # For *response
114
-
115
- def each(&callback)
116
- @body.each(&callback)
117
- @writer = callback
118
- @block.call(self) if @block
119
- end
120
-
121
- # Append to body and update Content-Length.
122
- #
123
- # NOTE: Do not mix #write and direct #body access!
124
- #
125
- def write(str)
126
- s = str.to_s
127
- @length += Rack::Utils.bytesize(s)
128
- @writer.call s
129
-
130
- header["Content-Length"] = @length.to_s
131
- str
132
- end
133
-
134
- def close
135
- body.close if body.respond_to?(:close)
136
- end
137
-
138
- def empty?
139
- @block == nil && @body.empty?
140
- end
141
-
142
- alias headers header
143
-
144
- module Helpers
145
- def invalid?; @status < 100 || @status >= 600; end
146
-
147
- def informational?; @status >= 100 && @status < 200; end
148
- def successful?; @status >= 200 && @status < 300; end
149
- def redirection?; @status >= 300 && @status < 400; end
150
- def client_error?; @status >= 400 && @status < 500; end
151
- def server_error?; @status >= 500 && @status < 600; end
152
-
153
- def ok?; @status == 200; end
154
- def forbidden?; @status == 403; end
155
- def not_found?; @status == 404; end
156
-
157
- def redirect?; [301, 302, 303, 307].include? @status; end
158
- def empty?; [201, 204, 304].include? @status; end
159
-
160
- # Headers
161
- attr_reader :headers, :original_headers
162
-
163
- def include?(header)
164
- !!headers[header]
165
- end
166
-
167
- def content_type
168
- headers["Content-Type"]
169
- end
170
-
171
- def content_length
172
- cl = headers["Content-Length"]
173
- cl ? cl.to_i : cl
174
- end
175
-
176
- def location
177
- headers["Location"]
178
- end
179
- end
180
-
181
- include Helpers
182
- end
183
- end