eac-rack 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. data/COPYING +18 -0
  2. data/KNOWN-ISSUES +21 -0
  3. data/README +399 -0
  4. data/bin/rackup +4 -0
  5. data/contrib/rack_logo.svg +111 -0
  6. data/example/lobster.ru +4 -0
  7. data/example/protectedlobster.rb +14 -0
  8. data/example/protectedlobster.ru +8 -0
  9. data/lib/rack.rb +92 -0
  10. data/lib/rack/adapter/camping.rb +22 -0
  11. data/lib/rack/auth/abstract/handler.rb +37 -0
  12. data/lib/rack/auth/abstract/request.rb +37 -0
  13. data/lib/rack/auth/basic.rb +58 -0
  14. data/lib/rack/auth/digest/md5.rb +124 -0
  15. data/lib/rack/auth/digest/nonce.rb +51 -0
  16. data/lib/rack/auth/digest/params.rb +55 -0
  17. data/lib/rack/auth/digest/request.rb +40 -0
  18. data/lib/rack/builder.rb +80 -0
  19. data/lib/rack/cascade.rb +41 -0
  20. data/lib/rack/chunked.rb +49 -0
  21. data/lib/rack/commonlogger.rb +49 -0
  22. data/lib/rack/conditionalget.rb +47 -0
  23. data/lib/rack/config.rb +15 -0
  24. data/lib/rack/content_length.rb +29 -0
  25. data/lib/rack/content_type.rb +23 -0
  26. data/lib/rack/deflater.rb +96 -0
  27. data/lib/rack/directory.rb +157 -0
  28. data/lib/rack/etag.rb +23 -0
  29. data/lib/rack/file.rb +90 -0
  30. data/lib/rack/handler.rb +88 -0
  31. data/lib/rack/handler/cgi.rb +61 -0
  32. data/lib/rack/handler/evented_mongrel.rb +8 -0
  33. data/lib/rack/handler/fastcgi.rb +89 -0
  34. data/lib/rack/handler/lsws.rb +63 -0
  35. data/lib/rack/handler/mongrel.rb +90 -0
  36. data/lib/rack/handler/scgi.rb +62 -0
  37. data/lib/rack/handler/swiftiplied_mongrel.rb +8 -0
  38. data/lib/rack/handler/thin.rb +18 -0
  39. data/lib/rack/handler/webrick.rb +69 -0
  40. data/lib/rack/head.rb +19 -0
  41. data/lib/rack/lint.rb +575 -0
  42. data/lib/rack/lobster.rb +65 -0
  43. data/lib/rack/lock.rb +16 -0
  44. data/lib/rack/logger.rb +20 -0
  45. data/lib/rack/methodoverride.rb +27 -0
  46. data/lib/rack/mime.rb +206 -0
  47. data/lib/rack/mock.rb +189 -0
  48. data/lib/rack/nulllogger.rb +18 -0
  49. data/lib/rack/recursive.rb +57 -0
  50. data/lib/rack/reloader.rb +109 -0
  51. data/lib/rack/request.rb +271 -0
  52. data/lib/rack/response.rb +149 -0
  53. data/lib/rack/rewindable_input.rb +100 -0
  54. data/lib/rack/runtime.rb +27 -0
  55. data/lib/rack/sendfile.rb +142 -0
  56. data/lib/rack/server.rb +212 -0
  57. data/lib/rack/session/abstract/id.rb +140 -0
  58. data/lib/rack/session/cookie.rb +90 -0
  59. data/lib/rack/session/memcache.rb +119 -0
  60. data/lib/rack/session/pool.rb +100 -0
  61. data/lib/rack/showexceptions.rb +349 -0
  62. data/lib/rack/showstatus.rb +106 -0
  63. data/lib/rack/static.rb +38 -0
  64. data/lib/rack/urlmap.rb +56 -0
  65. data/lib/rack/utils.rb +614 -0
  66. data/rack.gemspec +38 -0
  67. data/test/spec_rack_auth_basic.rb +73 -0
  68. data/test/spec_rack_auth_digest.rb +226 -0
  69. data/test/spec_rack_builder.rb +84 -0
  70. data/test/spec_rack_camping.rb +51 -0
  71. data/test/spec_rack_cascade.rb +48 -0
  72. data/test/spec_rack_cgi.rb +89 -0
  73. data/test/spec_rack_chunked.rb +62 -0
  74. data/test/spec_rack_commonlogger.rb +61 -0
  75. data/test/spec_rack_conditionalget.rb +41 -0
  76. data/test/spec_rack_config.rb +24 -0
  77. data/test/spec_rack_content_length.rb +43 -0
  78. data/test/spec_rack_content_type.rb +30 -0
  79. data/test/spec_rack_deflater.rb +127 -0
  80. data/test/spec_rack_directory.rb +61 -0
  81. data/test/spec_rack_etag.rb +17 -0
  82. data/test/spec_rack_fastcgi.rb +89 -0
  83. data/test/spec_rack_file.rb +75 -0
  84. data/test/spec_rack_handler.rb +43 -0
  85. data/test/spec_rack_head.rb +30 -0
  86. data/test/spec_rack_lint.rb +528 -0
  87. data/test/spec_rack_lobster.rb +45 -0
  88. data/test/spec_rack_lock.rb +38 -0
  89. data/test/spec_rack_logger.rb +21 -0
  90. data/test/spec_rack_methodoverride.rb +60 -0
  91. data/test/spec_rack_mock.rb +243 -0
  92. data/test/spec_rack_mongrel.rb +189 -0
  93. data/test/spec_rack_nulllogger.rb +13 -0
  94. data/test/spec_rack_recursive.rb +77 -0
  95. data/test/spec_rack_request.rb +545 -0
  96. data/test/spec_rack_response.rb +221 -0
  97. data/test/spec_rack_rewindable_input.rb +118 -0
  98. data/test/spec_rack_runtime.rb +35 -0
  99. data/test/spec_rack_sendfile.rb +86 -0
  100. data/test/spec_rack_session_cookie.rb +73 -0
  101. data/test/spec_rack_session_memcache.rb +273 -0
  102. data/test/spec_rack_session_pool.rb +172 -0
  103. data/test/spec_rack_showexceptions.rb +21 -0
  104. data/test/spec_rack_showstatus.rb +72 -0
  105. data/test/spec_rack_static.rb +37 -0
  106. data/test/spec_rack_thin.rb +91 -0
  107. data/test/spec_rack_urlmap.rb +215 -0
  108. data/test/spec_rack_utils.rb +554 -0
  109. data/test/spec_rack_webrick.rb +130 -0
  110. data/test/spec_rackup.rb +154 -0
  111. metadata +311 -0
@@ -0,0 +1,4 @@
1
+ require 'rack/lobster'
2
+
3
+ use Rack::ShowExceptions
4
+ run Rack::Lobster.new
@@ -0,0 +1,14 @@
1
+ require 'rack'
2
+ require 'rack/lobster'
3
+
4
+ lobster = Rack::Lobster.new
5
+
6
+ protected_lobster = Rack::Auth::Basic.new(lobster) do |username, password|
7
+ 'secret' == password
8
+ end
9
+
10
+ protected_lobster.realm = 'Lobster 2.0'
11
+
12
+ pretty_protected_lobster = Rack::ShowStatus.new(Rack::ShowExceptions.new(protected_lobster))
13
+
14
+ Rack::Handler::WEBrick.run pretty_protected_lobster, :Port => 9292
@@ -0,0 +1,8 @@
1
+ require 'rack/lobster'
2
+
3
+ use Rack::ShowExceptions
4
+ use Rack::Auth::Basic, "Lobster 2.0" do |username, password|
5
+ 'secret' == password
6
+ end
7
+
8
+ run Rack::Lobster.new
@@ -0,0 +1,92 @@
1
+ # Copyright (C) 2007, 2008, 2009, 2010 Christian Neukirchen <purl.org/net/chneukirchen>
2
+ #
3
+ # Rack is freely distributable under the terms of an MIT-style license.
4
+ # See COPYING or http://www.opensource.org/licenses/mit-license.php.
5
+
6
+ # The Rack main module, serving as a namespace for all core Rack
7
+ # modules and classes.
8
+ #
9
+ # All modules meant for use in your application are <tt>autoload</tt>ed here,
10
+ # so it should be enough just to <tt>require rack.rb</tt> in your code.
11
+
12
+ module Rack
13
+ # The Rack protocol version number implemented.
14
+ VERSION = [1,1]
15
+
16
+ # Return the Rack protocol version as a dotted string.
17
+ def self.version
18
+ VERSION.join(".")
19
+ end
20
+
21
+ # Return the Rack release as a dotted string.
22
+ def self.release
23
+ "1.1"
24
+ end
25
+
26
+ autoload :Builder, "rack/builder"
27
+ autoload :Cascade, "rack/cascade"
28
+ autoload :Chunked, "rack/chunked"
29
+ autoload :CommonLogger, "rack/commonlogger"
30
+ autoload :ConditionalGet, "rack/conditionalget"
31
+ autoload :Config, "rack/config"
32
+ autoload :ContentLength, "rack/content_length"
33
+ autoload :ContentType, "rack/content_type"
34
+ autoload :ETag, "rack/etag"
35
+ autoload :File, "rack/file"
36
+ autoload :Deflater, "rack/deflater"
37
+ autoload :Directory, "rack/directory"
38
+ autoload :ForwardRequest, "rack/recursive"
39
+ autoload :Handler, "rack/handler"
40
+ autoload :Head, "rack/head"
41
+ autoload :Lint, "rack/lint"
42
+ autoload :Lock, "rack/lock"
43
+ autoload :Logger, "rack/logger"
44
+ autoload :MethodOverride, "rack/methodoverride"
45
+ autoload :Mime, "rack/mime"
46
+ autoload :NullLogger, "rack/nulllogger"
47
+ autoload :Recursive, "rack/recursive"
48
+ autoload :Reloader, "rack/reloader"
49
+ autoload :Runtime, "rack/runtime"
50
+ autoload :Sendfile, "rack/sendfile"
51
+ autoload :Server, "rack/server"
52
+ autoload :ShowExceptions, "rack/showexceptions"
53
+ autoload :ShowStatus, "rack/showstatus"
54
+ autoload :Static, "rack/static"
55
+ autoload :URLMap, "rack/urlmap"
56
+ autoload :Utils, "rack/utils"
57
+
58
+ autoload :MockRequest, "rack/mock"
59
+ autoload :MockResponse, "rack/mock"
60
+
61
+ autoload :Request, "rack/request"
62
+ autoload :Response, "rack/response"
63
+
64
+ module Auth
65
+ autoload :Basic, "rack/auth/basic"
66
+ autoload :AbstractRequest, "rack/auth/abstract/request"
67
+ autoload :AbstractHandler, "rack/auth/abstract/handler"
68
+ module Digest
69
+ autoload :MD5, "rack/auth/digest/md5"
70
+ autoload :Nonce, "rack/auth/digest/nonce"
71
+ autoload :Params, "rack/auth/digest/params"
72
+ autoload :Request, "rack/auth/digest/request"
73
+ end
74
+ end
75
+
76
+ module Session
77
+ autoload :Cookie, "rack/session/cookie"
78
+ autoload :Pool, "rack/session/pool"
79
+ autoload :Memcache, "rack/session/memcache"
80
+ end
81
+
82
+ # *Adapters* connect Rack with third party web frameworks.
83
+ #
84
+ # Rack includes an adapter for Camping, see README for other
85
+ # frameworks supporting Rack in their code bases.
86
+ #
87
+ # Refer to the submodules for framework-specific calling details.
88
+
89
+ module Adapter
90
+ autoload :Camping, "rack/adapter/camping"
91
+ end
92
+ end
@@ -0,0 +1,22 @@
1
+ module Rack
2
+ module Adapter
3
+ class Camping
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ env["PATH_INFO"] ||= ""
10
+ env["SCRIPT_NAME"] ||= ""
11
+ controller = @app.run(env['rack.input'], env)
12
+ h = controller.headers
13
+ h.each_pair do |k,v|
14
+ if v.kind_of? URI
15
+ h[k] = v.to_s
16
+ end
17
+ end
18
+ [controller.status, controller.headers, [controller.body.to_s]]
19
+ end
20
+ end
21
+ end
22
+ end
@@ -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
@@ -0,0 +1,37 @@
1
+ module Rack
2
+ module Auth
3
+ class AbstractRequest
4
+
5
+ def initialize(env)
6
+ @env = env
7
+ end
8
+
9
+ def provided?
10
+ !authorization_key.nil?
11
+ end
12
+
13
+ def parts
14
+ @parts ||= @env[authorization_key].split(' ', 2)
15
+ end
16
+
17
+ def scheme
18
+ @scheme ||= parts.first.downcase.to_sym
19
+ end
20
+
21
+ def params
22
+ @params ||= parts.last
23
+ end
24
+
25
+
26
+ private
27
+
28
+ AUTHORIZATION_KEYS = ['HTTP_AUTHORIZATION', 'X-HTTP_AUTHORIZATION', 'X_HTTP_AUTHORIZATION']
29
+
30
+ def authorization_key
31
+ @authorization_key ||= AUTHORIZATION_KEYS.detect { |key| @env.has_key?(key) }
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,58 @@
1
+ require 'rack/auth/abstract/handler'
2
+ require 'rack/auth/abstract/request'
3
+
4
+ module Rack
5
+ module Auth
6
+ # Rack::Auth::Basic implements HTTP Basic Authentication, as per RFC 2617.
7
+ #
8
+ # Initialize with the Rack application that you want protecting,
9
+ # and a block that checks if a username and password pair are valid.
10
+ #
11
+ # See also: <tt>example/protectedlobster.rb</tt>
12
+
13
+ class Basic < AbstractHandler
14
+
15
+ def call(env)
16
+ auth = Basic::Request.new(env)
17
+
18
+ return unauthorized unless auth.provided?
19
+
20
+ return bad_request unless auth.basic?
21
+
22
+ if valid?(auth)
23
+ env['REMOTE_USER'] = auth.username
24
+
25
+ return @app.call(env)
26
+ end
27
+
28
+ unauthorized
29
+ end
30
+
31
+
32
+ private
33
+
34
+ def challenge
35
+ 'Basic realm="%s"' % realm
36
+ end
37
+
38
+ def valid?(auth)
39
+ @authenticator.call(*auth.credentials)
40
+ end
41
+
42
+ class Request < Auth::AbstractRequest
43
+ def basic?
44
+ :basic == scheme
45
+ end
46
+
47
+ def credentials
48
+ @credentials ||= params.unpack("m*").first.split(/:/, 2)
49
+ end
50
+
51
+ def username
52
+ credentials.first
53
+ end
54
+ end
55
+
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,124 @@
1
+ require 'rack/auth/abstract/handler'
2
+ require 'rack/auth/digest/request'
3
+ require 'rack/auth/digest/params'
4
+ require 'rack/auth/digest/nonce'
5
+ require 'digest/md5'
6
+
7
+ module Rack
8
+ module Auth
9
+ module Digest
10
+ # Rack::Auth::Digest::MD5 implements the MD5 algorithm version of
11
+ # HTTP Digest Authentication, as per RFC 2617.
12
+ #
13
+ # Initialize with the [Rack] application that you want protecting,
14
+ # and a block that looks up a plaintext password for a given username.
15
+ #
16
+ # +opaque+ needs to be set to a constant base64/hexadecimal string.
17
+ #
18
+ class MD5 < AbstractHandler
19
+
20
+ attr_accessor :opaque
21
+
22
+ attr_writer :passwords_hashed
23
+
24
+ def initialize(*args)
25
+ super
26
+ @passwords_hashed = nil
27
+ end
28
+
29
+ def passwords_hashed?
30
+ !!@passwords_hashed
31
+ end
32
+
33
+ def call(env)
34
+ auth = Request.new(env)
35
+
36
+ unless auth.provided?
37
+ return unauthorized
38
+ end
39
+
40
+ if !auth.digest? || !auth.correct_uri? || !valid_qop?(auth)
41
+ return bad_request
42
+ end
43
+
44
+ if valid?(auth)
45
+ if auth.nonce.stale?
46
+ return unauthorized(challenge(:stale => true))
47
+ else
48
+ env['REMOTE_USER'] = auth.username
49
+
50
+ return @app.call(env)
51
+ end
52
+ end
53
+
54
+ unauthorized
55
+ end
56
+
57
+
58
+ private
59
+
60
+ QOP = 'auth'.freeze
61
+
62
+ def params(hash = {})
63
+ Params.new do |params|
64
+ params['realm'] = realm
65
+ params['nonce'] = Nonce.new.to_s
66
+ params['opaque'] = H(opaque)
67
+ params['qop'] = QOP
68
+
69
+ hash.each { |k, v| params[k] = v }
70
+ end
71
+ end
72
+
73
+ def challenge(hash = {})
74
+ "Digest #{params(hash)}"
75
+ end
76
+
77
+ def valid?(auth)
78
+ valid_opaque?(auth) && valid_nonce?(auth) && valid_digest?(auth)
79
+ end
80
+
81
+ def valid_qop?(auth)
82
+ QOP == auth.qop
83
+ end
84
+
85
+ def valid_opaque?(auth)
86
+ H(opaque) == auth.opaque
87
+ end
88
+
89
+ def valid_nonce?(auth)
90
+ auth.nonce.valid?
91
+ end
92
+
93
+ def valid_digest?(auth)
94
+ digest(auth, @authenticator.call(auth.username)) == auth.response
95
+ end
96
+
97
+ def md5(data)
98
+ ::Digest::MD5.hexdigest(data)
99
+ end
100
+
101
+ alias :H :md5
102
+
103
+ def KD(secret, data)
104
+ H([secret, data] * ':')
105
+ end
106
+
107
+ def A1(auth, password)
108
+ [ auth.username, auth.realm, password ] * ':'
109
+ end
110
+
111
+ def A2(auth)
112
+ [ auth.method, auth.uri ] * ':'
113
+ end
114
+
115
+ def digest(auth, password)
116
+ password_hash = passwords_hashed? ? password : H(A1(auth, password))
117
+
118
+ KD(password_hash, [ auth.nonce, auth.nc, auth.cnonce, QOP, H(A2(auth)) ] * ':')
119
+ end
120
+
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,51 @@
1
+ require 'digest/md5'
2
+
3
+ module Rack
4
+ module Auth
5
+ module Digest
6
+ # Rack::Auth::Digest::Nonce is the default nonce generator for the
7
+ # Rack::Auth::Digest::MD5 authentication handler.
8
+ #
9
+ # +private_key+ needs to set to a constant string.
10
+ #
11
+ # +time_limit+ can be optionally set to an integer (number of seconds),
12
+ # to limit the validity of the generated nonces.
13
+
14
+ class Nonce
15
+
16
+ class << self
17
+ attr_accessor :private_key, :time_limit
18
+ end
19
+
20
+ def self.parse(string)
21
+ new(*string.unpack("m*").first.split(' ', 2))
22
+ end
23
+
24
+ def initialize(timestamp = Time.now, given_digest = nil)
25
+ @timestamp, @given_digest = timestamp.to_i, given_digest
26
+ end
27
+
28
+ def to_s
29
+ [([ @timestamp, digest ] * ' ')].pack("m*").strip
30
+ end
31
+
32
+ def digest
33
+ ::Digest::MD5.hexdigest([ @timestamp, self.class.private_key ] * ':')
34
+ end
35
+
36
+ def valid?
37
+ digest == @given_digest
38
+ end
39
+
40
+ def stale?
41
+ !self.class.time_limit.nil? && (@timestamp - Time.now.to_i) < self.class.time_limit
42
+ end
43
+
44
+ def fresh?
45
+ !stale?
46
+ end
47
+
48
+ end
49
+ end
50
+ end
51
+ end