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
@@ -0,0 +1,164 @@
1
+ # Rakefile for Rack. -*-ruby-*-
2
+ require 'rake/rdoctask'
3
+ require 'rake/testtask'
4
+
5
+
6
+ desc "Run all the tests"
7
+ task :default => [:test]
8
+
9
+
10
+ desc "Make an archive as .tar.gz"
11
+ task :dist => [:chmod, :changelog, :rdoc, "SPEC", "rack.gemspec"] do
12
+ FileUtils.touch("RDOX")
13
+ sh "git archive --format=tar --prefix=#{release}/ HEAD^{tree} >#{release}.tar"
14
+ sh "pax -waf #{release}.tar -s ':^:#{release}/:' RDOX SPEC ChangeLog doc rack.gemspec"
15
+ sh "gzip -f -9 #{release}.tar"
16
+ end
17
+
18
+ desc "Make an official release"
19
+ task :officialrelease do
20
+ puts "Official build for #{release}..."
21
+ sh "rm -rf stage"
22
+ sh "git clone --shared . stage"
23
+ sh "cd stage && rake officialrelease_really"
24
+ sh "mv stage/#{release}.tar.gz stage/#{release}.gem ."
25
+ end
26
+
27
+ task :officialrelease_really => [:fulltest, "RDOX", "SPEC", :dist, :gem] do
28
+ sh "sha1sum #{release}.tar.gz #{release}.gem"
29
+ end
30
+
31
+
32
+ def version
33
+ abort "You need to pass VERSION=... to build packages." unless ENV["VERSION"]
34
+ ENV["VERSION"]
35
+ end
36
+
37
+ def release
38
+ "rack-#{version}"
39
+ end
40
+
41
+ def manifest
42
+ `git ls-files`.split("\n")
43
+ end
44
+
45
+
46
+ desc "Make binaries executable"
47
+ task :chmod do
48
+ Dir["bin/*"].each { |binary| File.chmod(0775, binary) }
49
+ Dir["test/cgi/test*"].each { |binary| File.chmod(0775, binary) }
50
+ end
51
+
52
+ desc "Generate a ChangeLog"
53
+ task :changelog do
54
+ File.open("ChangeLog", "w") { |out|
55
+ `git log -z`.split("\0").map { |chunk|
56
+ author = chunk[/Author: (.*)/, 1].strip
57
+ date = chunk[/Date: (.*)/, 1].strip
58
+ desc, detail = $'.strip.split("\n", 2)
59
+ detail ||= ""
60
+ detail = detail.gsub(/.*darcs-hash:.*/, '')
61
+ detail.rstrip!
62
+ out.puts "#{date} #{author}"
63
+ out.puts " * #{desc.strip}"
64
+ out.puts detail unless detail.empty?
65
+ out.puts
66
+ }
67
+ }
68
+ end
69
+
70
+
71
+ desc "Generate RDox"
72
+ task "RDOX" do
73
+ sh "specrb -Ilib:test -a --rdox >RDOX"
74
+ end
75
+
76
+ desc "Generate Rack Specification"
77
+ task "SPEC" do
78
+ File.open("SPEC", "wb") { |file|
79
+ IO.foreach("lib/rack/lint.rb") { |line|
80
+ if line =~ /## (.*)/
81
+ file.puts $1
82
+ end
83
+ }
84
+ }
85
+ end
86
+
87
+ desc "Run all the fast tests"
88
+ task :test do
89
+ sh "specrb -Ilib:test -w #{ENV['TEST'] || '-a'} #{ENV['TESTOPTS'] || '-t "^(?!Rack::Handler|Rack::Adapter|Rack::Session::Memcache|Rack::Auth::OpenID)"'}"
90
+ end
91
+
92
+ desc "Run all the tests"
93
+ task :fulltest => [:chmod] do
94
+ sh "specrb -Ilib:test -w #{ENV['TEST'] || '-a'} #{ENV['TESTOPTS']}"
95
+ end
96
+
97
+ begin
98
+ require 'rubygems'
99
+ rescue LoadError
100
+ # Too bad.
101
+ else
102
+ task "rack.gemspec" do
103
+ spec = Gem::Specification.new do |s|
104
+ s.name = "rack"
105
+ s.version = version
106
+ s.platform = Gem::Platform::RUBY
107
+ s.summary = "a modular Ruby webserver interface"
108
+
109
+ s.description = <<-EOF
110
+ Rack provides minimal, modular and adaptable interface for developing
111
+ web applications in Ruby. By wrapping HTTP requests and responses in
112
+ the simplest way possible, it unifies and distills the API for web
113
+ servers, web frameworks, and software in between (the so-called
114
+ middleware) into a single method call.
115
+
116
+ Also see http://rack.rubyforge.org.
117
+ EOF
118
+
119
+ s.files = manifest + %w(SPEC RDOX rack.gemspec)
120
+ s.bindir = 'bin'
121
+ s.executables << 'rackup'
122
+ s.require_path = 'lib'
123
+ s.has_rdoc = true
124
+ s.extra_rdoc_files = ['README', 'SPEC', 'RDOX', 'KNOWN-ISSUES']
125
+ s.test_files = Dir['test/{test,spec}_*.rb']
126
+
127
+ s.author = 'Christian Neukirchen'
128
+ s.email = 'chneukirchen@gmail.com'
129
+ s.homepage = 'http://rack.rubyforge.org'
130
+ s.rubyforge_project = 'rack'
131
+
132
+ s.add_development_dependency 'test-spec'
133
+
134
+ s.add_development_dependency 'camping'
135
+ s.add_development_dependency 'fcgi'
136
+ s.add_development_dependency 'memcache-client'
137
+ s.add_development_dependency 'mongrel'
138
+ s.add_development_dependency 'ruby-openid', '~> 2.0.0'
139
+ s.add_development_dependency 'thin'
140
+ end
141
+
142
+ File.open("rack.gemspec", "w") { |f| f << spec.to_ruby }
143
+ end
144
+
145
+ task :gem => ["rack.gemspec", "SPEC"] do
146
+ FileUtils.touch("RDOX")
147
+ sh "gem build rack.gemspec"
148
+ end
149
+ end
150
+
151
+ desc "Generate RDoc documentation"
152
+ task :rdoc do
153
+ sh(*%w{rdoc --line-numbers --main README
154
+ --title 'Rack\ Documentation' --charset utf-8 -U -o doc} +
155
+ %w{README KNOWN-ISSUES SPEC RDOX} +
156
+ Dir["lib/**/*.rb"])
157
+ end
158
+
159
+ task :pushsite => [:rdoc] do
160
+ sh "cd site && git gc"
161
+ sh "rsync -avz doc/ chneukirchen@rack.rubyforge.org:/var/www/gforge-projects/rack/doc/"
162
+ sh "rsync -avz site/ chneukirchen@rack.rubyforge.org:/var/www/gforge-projects/rack/"
163
+ sh "cd site && git push"
164
+ end
@@ -3,7 +3,8 @@
3
3
  # Rack is freely distributable under the terms of an MIT-style license.
4
4
  # See COPYING or http://www.opensource.org/licenses/mit-license.php.
5
5
 
6
- $: << File.expand_path(File.dirname(__FILE__))
6
+ path = File.expand_path(File.dirname(__FILE__))
7
+ $:.unshift(path) unless $:.include?(path)
7
8
 
8
9
 
9
10
  # The Rack main module, serving as a namespace for all core Rack
@@ -14,7 +15,7 @@ $: << File.expand_path(File.dirname(__FILE__))
14
15
 
15
16
  module Rack
16
17
  # The Rack protocol version number implemented.
17
- VERSION = [0,1]
18
+ VERSION = [1,0]
18
19
 
19
20
  # Return the Rack protocol version as a dotted string.
20
21
  def self.version
@@ -23,14 +24,16 @@ module Rack
23
24
 
24
25
  # Return the Rack release as a dotted string.
25
26
  def self.release
26
- "0.9"
27
+ "1.0"
27
28
  end
28
29
 
29
30
  autoload :Builder, "rack/builder"
30
31
  autoload :Cascade, "rack/cascade"
32
+ autoload :Chunked, "rack/chunked"
31
33
  autoload :CommonLogger, "rack/commonlogger"
32
34
  autoload :ConditionalGet, "rack/conditionalget"
33
35
  autoload :ContentLength, "rack/content_length"
36
+ autoload :ContentType, "rack/content_type"
34
37
  autoload :File, "rack/file"
35
38
  autoload :Deflater, "rack/deflater"
36
39
  autoload :Directory, "rack/directory"
@@ -38,6 +41,7 @@ module Rack
38
41
  autoload :Handler, "rack/handler"
39
42
  autoload :Head, "rack/head"
40
43
  autoload :Lint, "rack/lint"
44
+ autoload :Lock, "rack/lock"
41
45
  autoload :MethodOverride, "rack/methodoverride"
42
46
  autoload :Mime, "rack/mime"
43
47
  autoload :Recursive, "rack/recursive"
@@ -0,0 +1,37 @@
1
+ module Rack
2
+ module Auth
3
+ # Rack::Auth::AbstractHandler implements common authentication functionality.
4
+ #
5
+ # +realm+ should be set for all handlers.
6
+
7
+ class AbstractHandler
8
+
9
+ attr_accessor :realm
10
+
11
+ def initialize(app, realm=nil, &authenticator)
12
+ @app, @realm, @authenticator = app, realm, authenticator
13
+ end
14
+
15
+
16
+ private
17
+
18
+ def unauthorized(www_authenticate = challenge)
19
+ return [ 401,
20
+ { 'Content-Type' => 'text/plain',
21
+ 'Content-Length' => '0',
22
+ 'WWW-Authenticate' => www_authenticate.to_s },
23
+ []
24
+ ]
25
+ end
26
+
27
+ def bad_request
28
+ return [ 400,
29
+ { 'Content-Type' => 'text/plain',
30
+ 'Content-Length' => '0' },
31
+ []
32
+ ]
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -21,7 +21,7 @@ module Rack
21
21
 
22
22
  attr_writer :passwords_hashed
23
23
 
24
- def initialize(app)
24
+ def initialize(*args)
25
25
  super
26
26
  @passwords_hashed = nil
27
27
  end
@@ -8,7 +8,7 @@ module Rack
8
8
  class Request < Auth::AbstractRequest
9
9
 
10
10
  def method
11
- @env['REQUEST_METHOD']
11
+ @env['rack.methodoverride.original_method'] || @env['REQUEST_METHOD']
12
12
  end
13
13
 
14
14
  def digest?
@@ -16,7 +16,7 @@ module Rack
16
16
  end
17
17
 
18
18
  def correct_uri?
19
- @env['PATH_INFO'] == uri
19
+ (@env['SCRIPT_NAME'].to_s + @env['PATH_INFO'].to_s) == uri
20
20
  end
21
21
 
22
22
  def nonce
@@ -0,0 +1,480 @@
1
+ # AUTHOR: blink <blinketje@gmail.com>; blink#ruby-lang@irc.freenode.net
2
+
3
+ gem 'ruby-openid', '~> 2' if defined? Gem
4
+ require 'rack/request'
5
+ require 'rack/utils'
6
+ require 'rack/auth/abstract/handler'
7
+ require 'uri'
8
+ require 'openid' #gem
9
+ require 'openid/extension' #gem
10
+ require 'openid/store/memory' #gem
11
+
12
+ module Rack
13
+ class Request
14
+ def openid_request
15
+ @env['rack.auth.openid.request']
16
+ end
17
+
18
+ def openid_response
19
+ @env['rack.auth.openid.response']
20
+ end
21
+ end
22
+
23
+ module Auth
24
+
25
+ # Rack::Auth::OpenID provides a simple method for setting up an OpenID
26
+ # Consumer. It requires the ruby-openid library from janrain to operate,
27
+ # as well as a rack method of session management.
28
+ #
29
+ # The ruby-openid home page is at http://openidenabled.com/ruby-openid/.
30
+ #
31
+ # The OpenID specifications can be found at
32
+ # http://openid.net/specs/openid-authentication-1_1.html
33
+ # and
34
+ # http://openid.net/specs/openid-authentication-2_0.html. Documentation
35
+ # for published OpenID extensions and related topics can be found at
36
+ # http://openid.net/developers/specs/.
37
+ #
38
+ # It is recommended to read through the OpenID spec, as well as
39
+ # ruby-openid's documentation, to understand what exactly goes on. However
40
+ # a setup as simple as the presented examples is enough to provide
41
+ # Consumer functionality.
42
+ #
43
+ # This library strongly intends to utilize the OpenID 2.0 features of the
44
+ # ruby-openid library, which provides OpenID 1.0 compatiblity.
45
+ #
46
+ # NOTE: Due to the amount of data that this library stores in the
47
+ # session, Rack::Session::Cookie may fault.
48
+
49
+ class OpenID
50
+
51
+ class NoSession < RuntimeError; end
52
+ class BadExtension < RuntimeError; end
53
+ # Required for ruby-openid
54
+ ValidStatus = [:success, :setup_needed, :cancel, :failure]
55
+
56
+ # = Arguments
57
+ #
58
+ # The first argument is the realm, identifying the site they are trusting
59
+ # with their identity. This is required, also treated as the trust_root
60
+ # in OpenID 1.x exchanges.
61
+ #
62
+ # The optional second argument is a hash of options.
63
+ #
64
+ # == Options
65
+ #
66
+ # <tt>:return_to</tt> defines the url to return to after the client
67
+ # authenticates with the openid service provider. This url should point
68
+ # to where Rack::Auth::OpenID is mounted. If <tt>:return_to</tt> is not
69
+ # provided, return_to will be the current url which allows flexibility
70
+ # with caveats.
71
+ #
72
+ # <tt>:session_key</tt> defines the key to the session hash in the env.
73
+ # It defaults to 'rack.session'.
74
+ #
75
+ # <tt>:openid_param</tt> defines at what key in the request parameters to
76
+ # find the identifier to resolve. As per the 2.0 spec, the default is
77
+ # 'openid_identifier'.
78
+ #
79
+ # <tt>:store</tt> defined what OpenID Store to use for persistant
80
+ # information. By default a Store::Memory will be used.
81
+ #
82
+ # <tt>:immediate</tt> as true will make initial requests to be of an
83
+ # immediate type. This is false by default. See OpenID specification
84
+ # documentation.
85
+ #
86
+ # <tt>:extensions</tt> should be a hash of openid extension
87
+ # implementations. The key should be the extension main module, the value
88
+ # should be an array of arguments for extension::Request.new.
89
+ # The hash is iterated over and passed to #add_extension for processing.
90
+ # Please see #add_extension for further documentation.
91
+ #
92
+ # == Examples
93
+ #
94
+ # simple_oid = OpenID.new('http://mysite.com/')
95
+ #
96
+ # return_oid = OpenID.new('http://mysite.com/', {
97
+ # :return_to => 'http://mysite.com/openid'
98
+ # })
99
+ #
100
+ # complex_oid = OpenID.new('http://mysite.com/',
101
+ # :immediate => true,
102
+ # :extensions => {
103
+ # ::OpenID::SReg => [['email'],['nickname']]
104
+ # }
105
+ # )
106
+ #
107
+ # = Advanced
108
+ #
109
+ # Most of the functionality of this library is encapsulated such that
110
+ # expansion and overriding functions isn't difficult nor tricky.
111
+ # Alternately, to avoid opening up singleton objects or subclassing, a
112
+ # wrapper rack middleware can be composed to act upon Auth::OpenID's
113
+ # responses. See #check and #finish for locations of pertinent data.
114
+ #
115
+ # == Responses
116
+ #
117
+ # To change the responses that Auth::OpenID returns, override the methods
118
+ # #redirect, #bad_request, #unauthorized, #access_denied, and
119
+ # #foreign_server_failure.
120
+ #
121
+ # Additionally #confirm_post_params is used when the URI would exceed
122
+ # length limits on a GET request when doing the initial verification
123
+ # request.
124
+ #
125
+ # == Processing
126
+ #
127
+ # To change methods of processing completed transactions, override the
128
+ # methods #success, #setup_needed, #cancel, and #failure. Please ensure
129
+ # the returned object is a rack compatible response.
130
+ #
131
+ # The first argument is an OpenID::Response, the second is a
132
+ # Rack::Request of the current request, the last is the hash used in
133
+ # ruby-openid handling, which can be found manually at
134
+ # env['rack.session'][:openid].
135
+ #
136
+ # This is useful if you wanted to expand the processing done, such as
137
+ # setting up user accounts.
138
+ #
139
+ # oid_app = Rack::Auth::OpenID.new realm, :return_to => return_to
140
+ # def oid_app.success oid, request, session
141
+ # user = Models::User[oid.identity_url]
142
+ # user ||= Models::User.create_from_openid oid
143
+ # request['rack.session'][:user] = user.id
144
+ # redirect MyApp.site_home
145
+ # end
146
+ #
147
+ # site_map['/openid'] = oid_app
148
+ # map = Rack::URLMap.new site_map
149
+ # ...
150
+
151
+ def initialize(realm, options={})
152
+ realm = URI(realm)
153
+ raise ArgumentError, "Invalid realm: #{realm}" \
154
+ unless realm.absolute? \
155
+ and realm.fragment.nil? \
156
+ and realm.scheme =~ /^https?$/ \
157
+ and realm.host =~ /^(\*\.)?#{URI::REGEXP::PATTERN::URIC_NO_SLASH}+/
158
+ realm.path = '/' if realm.path.empty?
159
+ @realm = realm.to_s
160
+
161
+ if ruri = options[:return_to]
162
+ ruri = URI(ruri)
163
+ raise ArgumentError, "Invalid return_to: #{ruri}" \
164
+ unless ruri.absolute? \
165
+ and ruri.scheme =~ /^https?$/ \
166
+ and ruri.fragment.nil?
167
+ raise ArgumentError, "return_to #{ruri} not within realm #{realm}" \
168
+ unless self.within_realm?(ruri)
169
+ @return_to = ruri.to_s
170
+ end
171
+
172
+ @session_key = options[:session_key] || 'rack.session'
173
+ @openid_param = options[:openid_param] || 'openid_identifier'
174
+ @store = options[:store] || ::OpenID::Store::Memory.new
175
+ @immediate = !!options[:immediate]
176
+
177
+ @extensions = {}
178
+ if extensions = options.delete(:extensions)
179
+ extensions.each do |ext, args|
180
+ add_extension ext, *args
181
+ end
182
+ end
183
+
184
+ # Undocumented, semi-experimental
185
+ @anonymous = !!options[:anonymous]
186
+ end
187
+
188
+ attr_reader :realm, :return_to, :session_key, :openid_param, :store,
189
+ :immediate, :extensions
190
+
191
+ # Sets up and uses session data at <tt>:openid</tt> within the session.
192
+ # Errors in this setup will raise a NoSession exception.
193
+ #
194
+ # If the parameter 'openid.mode' is set, which implies a followup from
195
+ # the openid server, processing is passed to #finish and the result is
196
+ # returned. However, if there is no appropriate openid information in the
197
+ # session, a 400 error is returned.
198
+ #
199
+ # If the parameter specified by <tt>options[:openid_param]</tt> is
200
+ # present, processing is passed to #check and the result is returned.
201
+ #
202
+ # If neither of these conditions are met, #unauthorized is called.
203
+
204
+ def call(env)
205
+ env['rack.auth.openid'] = self
206
+ env_session = env[@session_key]
207
+ unless env_session and env_session.is_a?(Hash)
208
+ raise NoSession, 'No compatible session'
209
+ end
210
+ # let us work in our own namespace...
211
+ session = (env_session[:openid] ||= {})
212
+ unless session and session.is_a?(Hash)
213
+ raise NoSession, 'Incompatible openid session'
214
+ end
215
+
216
+ request = Rack::Request.new(env)
217
+ consumer = ::OpenID::Consumer.new(session, @store)
218
+
219
+ if mode = request.GET['openid.mode']
220
+ if session.key?(:openid_param)
221
+ finish(consumer, session, request)
222
+ else
223
+ bad_request
224
+ end
225
+ elsif request.GET[@openid_param]
226
+ check(consumer, session, request)
227
+ else
228
+ unauthorized
229
+ end
230
+ end
231
+
232
+ # As the first part of OpenID consumer action, #check retrieves the data
233
+ # required for completion.
234
+ #
235
+ # If all parameters fit within the max length of a URI, a 303 redirect
236
+ # will be returned. Otherwise #confirm_post_params will be called.
237
+ #
238
+ # Any messages from OpenID's request are logged to env['rack.errors']
239
+ #
240
+ # <tt>env['rack.auth.openid.request']</tt> is the openid checkid request
241
+ # instance.
242
+ #
243
+ # <tt>session[:openid_param]</tt> is set to the openid identifier
244
+ # provided by the user.
245
+ #
246
+ # <tt>session[:return_to]</tt> is set to the return_to uri given to the
247
+ # identity provider.
248
+
249
+ def check(consumer, session, req)
250
+ oid = consumer.begin(req.GET[@openid_param], @anonymous)
251
+ req.env['rack.auth.openid.request'] = oid
252
+ req.env['rack.errors'].puts(oid.message)
253
+ p oid if $DEBUG
254
+
255
+ ## Extension support
256
+ extensions.each do |ext,args|
257
+ oid.add_extension(ext::Request.new(*args))
258
+ end
259
+
260
+ session[:openid_param] = req.GET[openid_param]
261
+ return_to_uri = return_to ? return_to : req.url
262
+ session[:return_to] = return_to_uri
263
+ immediate = session.key?(:setup_needed) ? false : immediate
264
+
265
+ if oid.send_redirect?(realm, return_to_uri, immediate)
266
+ uri = oid.redirect_url(realm, return_to_uri, immediate)
267
+ redirect(uri)
268
+ else
269
+ confirm_post_params(oid, realm, return_to_uri, immediate)
270
+ end
271
+ rescue ::OpenID::DiscoveryFailure => e
272
+ # thrown from inside OpenID::Consumer#begin by yadis stuff
273
+ req.env['rack.errors'].puts([e.message, *e.backtrace]*"\n")
274
+ return foreign_server_failure
275
+ end
276
+
277
+ # This is the final portion of authentication.
278
+ # If successful, a redirect to the realm is be returned.
279
+ # Data gathered from extensions are stored in session[:openid] with the
280
+ # extension's namespace uri as the key.
281
+ #
282
+ # Any messages from OpenID's response are logged to env['rack.errors']
283
+ #
284
+ # <tt>env['rack.auth.openid.response']</tt> will contain the openid
285
+ # response.
286
+
287
+ def finish(consumer, session, req)
288
+ oid = consumer.complete(req.GET, req.url)
289
+ req.env['rack.auth.openid.response'] = oid
290
+ req.env['rack.errors'].puts(oid.message)
291
+ p oid if $DEBUG
292
+
293
+ raise unless ValidStatus.include?(oid.status)
294
+ __send__(oid.status, oid, req, session)
295
+ end
296
+
297
+ # The first argument should be the main extension module.
298
+ # The extension module should contain the constants:
299
+ # * class Request, should have OpenID::Extension as an ancestor
300
+ # * class Response, should have OpenID::Extension as an ancestor
301
+ # * string NS_URI, which defining the namespace of the extension
302
+ #
303
+ # All trailing arguments will be passed to extension::Request.new in
304
+ # #check.
305
+ # The openid response will be passed to
306
+ # extension::Response#from_success_response, #get_extension_args will be
307
+ # called on the result to attain the gathered data.
308
+ #
309
+ # This method returns the key at which the response data will be found in
310
+ # the session, which is the namespace uri by default.
311
+
312
+ def add_extension(ext, *args)
313
+ raise BadExtension unless valid_extension?(ext)
314
+ extensions[ext] = args
315
+ return ext::NS_URI
316
+ end
317
+
318
+ # Checks the validitity, in the context of usage, of a submitted
319
+ # extension.
320
+
321
+ def valid_extension?(ext)
322
+ if not %w[NS_URI Request Response].all?{|c| ext.const_defined?(c) }
323
+ raise ArgumentError, 'Extension is missing constants.'
324
+ elsif not ext::Response.respond_to?(:from_success_response)
325
+ raise ArgumentError, 'Response is missing required method.'
326
+ end
327
+ return true
328
+ rescue
329
+ return false
330
+ end
331
+
332
+ # Checks the provided uri to ensure it'd be considered within the realm.
333
+ # is currently not compatible with wildcard realms.
334
+
335
+ def within_realm? uri
336
+ uri = URI.parse(uri.to_s)
337
+ realm = URI.parse(self.realm)
338
+ return false unless uri.absolute?
339
+ return false unless uri.path[0, realm.path.size] == realm.path
340
+ return false unless uri.host == realm.host or realm.host[/^\*\./]
341
+ # for wildcard support, is awkward with URI limitations
342
+ realm_match = Regexp.escape(realm.host).
343
+ sub(/^\*\./,"^#{URI::REGEXP::PATTERN::URIC_NO_SLASH}+.")+'$'
344
+ return false unless uri.host.match(realm_match)
345
+ return true
346
+ end
347
+ alias_method :include?, :within_realm?
348
+
349
+ protected
350
+
351
+ ### These methods define some of the boilerplate responses.
352
+
353
+ # Returns an html form page for posting to an Identity Provider if the
354
+ # GET request would exceed the upper URI length limit.
355
+
356
+ def confirm_post_params(oid, realm, return_to, immediate)
357
+ Rack::Response.new.finish do |r|
358
+ r.write '<html><head><title>Confirm...</title></head><body>'
359
+ r.write oid.form_markup(realm, return_to, immediate)
360
+ r.write '</body></html>'
361
+ end
362
+ end
363
+
364
+ # Returns a 303 redirect with the destination of that provided by the
365
+ # argument.
366
+
367
+ def redirect(uri)
368
+ [ 303, {'Content-Length'=>'0', 'Content-Type'=>'text/plain',
369
+ 'Location' => uri},
370
+ [] ]
371
+ end
372
+
373
+ # Returns an empty 400 response.
374
+
375
+ def bad_request
376
+ [ 400, {'Content-Type'=>'text/plain', 'Content-Length'=>'0'},
377
+ [''] ]
378
+ end
379
+
380
+ # Returns a basic unauthorized 401 response.
381
+
382
+ def unauthorized
383
+ [ 401, {'Content-Type' => 'text/plain', 'Content-Length' => '13'},
384
+ ['Unauthorized.'] ]
385
+ end
386
+
387
+ # Returns a basic access denied 403 response.
388
+
389
+ def access_denied
390
+ [ 403, {'Content-Type' => 'text/plain', 'Content-Length' => '14'},
391
+ ['Access denied.'] ]
392
+ end
393
+
394
+ # Returns a 503 response to be used if communication with the remote
395
+ # OpenID server fails.
396
+
397
+ def foreign_server_failure
398
+ [ 503, {'Content-Type'=>'text/plain', 'Content-Length' => '23'},
399
+ ['Foreign server failure.'] ]
400
+ end
401
+
402
+ private
403
+
404
+ ### These methods are called after a transaction is completed, depending
405
+ # on its outcome. These should all return a rack compatible response.
406
+ # You'd want to override these to provide additional functionality.
407
+
408
+ # Called to complete processing on a successful transaction.
409
+ # Within the openid session, :openid_identity and :openid_identifier are
410
+ # set to the user friendly and the standard representation of the
411
+ # validated identity. All other data in the openid session is cleared.
412
+
413
+ def success(oid, request, session)
414
+ session.clear
415
+ session[:openid_identity] = oid.display_identifier
416
+ session[:openid_identifier] = oid.identity_url
417
+ extensions.keys.each do |ext|
418
+ label = ext.name[/[^:]+$/].downcase
419
+ response = ext::Response.from_success_response(oid)
420
+ session[label] = response.data
421
+ end
422
+ redirect(realm)
423
+ end
424
+
425
+ # Called if the Identity Provider indicates further setup by the user is
426
+ # required.
427
+ # The identifier is retrived from the openid session at :openid_param.
428
+ # And :setup_needed is set to true to prevent looping.
429
+
430
+ def setup_needed(oid, request, session)
431
+ identifier = session[:openid_param]
432
+ session[:setup_needed] = true
433
+ redirect req.script_name + '?' + openid_param + '=' + identifier
434
+ end
435
+
436
+ # Called if the user indicates they wish to cancel identification.
437
+ # Data within openid session is cleared.
438
+
439
+ def cancel(oid, request, session)
440
+ session.clear
441
+ access_denied
442
+ end
443
+
444
+ # Called if the Identity Provider indicates the user is unable to confirm
445
+ # their identity. Data within the openid session is left alone, in case
446
+ # of swarm auth attacks.
447
+
448
+ def failure(oid, request, session)
449
+ unauthorized
450
+ end
451
+ end
452
+
453
+ # A class developed out of the request to use OpenID as an authentication
454
+ # middleware. The request will be sent to the OpenID instance unless the
455
+ # block evaluates to true. For example in rackup, you can use it as such:
456
+ #
457
+ # use Rack::Session::Pool
458
+ # use Rack::Auth::OpenIDAuth, realm, openid_options do |env|
459
+ # env['rack.session'][:authkey] == a_string
460
+ # end
461
+ # run RackApp
462
+ #
463
+ # Or simply:
464
+ #
465
+ # app = Rack::Auth::OpenIDAuth.new app, realm, openid_options, &auth
466
+
467
+ class OpenIDAuth < Rack::Auth::AbstractHandler
468
+ attr_reader :oid
469
+ def initialize(app, realm, options={}, &auth)
470
+ @oid = OpenID.new(realm, options)
471
+ super(app, &auth)
472
+ end
473
+
474
+ def call(env)
475
+ to = auth.call(env) ? @app : @oid
476
+ to.call env
477
+ end
478
+ end
479
+ end
480
+ end