rack 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rack might be problematic. Click here for more details.
- data/AUTHORS +3 -1
- data/RDOX +19 -1
- data/README +39 -6
- data/Rakefile +1 -1
- data/SPEC +2 -2
- data/bin/rackup +4 -0
- data/example/protectedlobster.ru +8 -0
- data/lib/rack.rb +12 -6
- data/lib/rack/auth/abstract/request.rb +0 -2
- data/lib/rack/auth/basic.rb +1 -1
- data/lib/rack/auth/digest/nonce.rb +2 -3
- data/lib/rack/auth/openid.rb +111 -0
- data/lib/rack/builder.rb +8 -4
- data/lib/rack/file.rb +3 -1
- data/lib/rack/handler/fastcgi.rb +3 -1
- data/lib/rack/handler/lsws.rb +52 -0
- data/lib/rack/handler/scgi.rb +57 -0
- data/lib/rack/lint.rb +5 -5
- data/lib/rack/request.rb +9 -2
- data/lib/rack/response.rb +9 -3
- data/lib/rack/session/cookie.rb +2 -4
- data/lib/rack/session/pool.rb +82 -0
- data/lib/rack/showexceptions.rb +1 -1
- data/lib/rack/urlmap.rb +6 -8
- data/lib/rack/utils.rb +21 -0
- data/test/cgi/lighttpd.conf +1 -1
- data/test/cgi/test.ru +1 -1
- data/test/spec_rack_auth_basic.rb +4 -3
- data/test/spec_rack_auth_digest.rb +4 -2
- data/test/spec_rack_builder.rb +50 -0
- data/test/spec_rack_cgi.rb +14 -8
- data/test/spec_rack_fastcgi.rb +14 -8
- data/test/spec_rack_file.rb +8 -0
- data/test/spec_rack_lint.rb +3 -3
- data/test/spec_rack_request.rb +32 -0
- data/test/spec_rack_response.rb +10 -2
- data/test/spec_rack_session_pool.rb +37 -0
- data/test/spec_rack_urlmap.rb +18 -12
- metadata +12 -3
data/AUTHORS
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
* Christian Neukirchen <chneukirchen@gmail.com>
|
2
|
-
* Rails adapter: Christoffer Sawicki <christoffer.sawicki@gmail.com>
|
3
2
|
* HTTP authentication: Tim Fletcher <twoggle@gmail.com>
|
4
3
|
* Cookie sessions, Static handler: Luc Heinrich <luc@honk-honk.com>
|
4
|
+
* Pool sessions, OpenID authentication: blink <blinketje@gmail.com>
|
5
|
+
* LiteSpeed handler: Adrian Madrid
|
6
|
+
* SCGI handler: Jeremy Evans
|
5
7
|
* Official Logo: Armin Ronacher
|
data/RDOX
CHANGED
@@ -16,6 +16,11 @@
|
|
16
16
|
* should return 400 Bad Request if incorrect uri given
|
17
17
|
* should return 400 Bad Request if different auth scheme used
|
18
18
|
|
19
|
+
== Rack::Builder
|
20
|
+
* chains apps by default
|
21
|
+
* has implicit #to_app
|
22
|
+
* supports blocks on use
|
23
|
+
|
19
24
|
== Rack::Adapter::Camping
|
20
25
|
* works with GET
|
21
26
|
* works with POST
|
@@ -26,6 +31,7 @@
|
|
26
31
|
* should fail if empty
|
27
32
|
|
28
33
|
== Rack::Handler::CGI
|
34
|
+
* startup (empty)
|
29
35
|
* should respond
|
30
36
|
* should be a lighttpd
|
31
37
|
* should have rack headers
|
@@ -33,12 +39,14 @@
|
|
33
39
|
* should have CGI headers on POST
|
34
40
|
* should support HTTP auth
|
35
41
|
* should set status
|
42
|
+
* shutdown
|
36
43
|
|
37
44
|
== Rack::CommonLogger
|
38
45
|
* should log to rack.errors by default
|
39
46
|
* should log to anything with <<
|
40
47
|
|
41
48
|
== Rack::Handler::FastCGI
|
49
|
+
* startup (empty)
|
42
50
|
* should respond
|
43
51
|
* should be a lighttpd
|
44
52
|
* should have rack headers
|
@@ -46,9 +54,11 @@
|
|
46
54
|
* should have CGI headers on POST
|
47
55
|
* should support HTTP auth
|
48
56
|
* should set status
|
57
|
+
* shutdown
|
49
58
|
|
50
59
|
== Rack::File
|
51
60
|
* serves files
|
61
|
+
* serves files with URL encoded filenames
|
52
62
|
* does not allow directory traversal
|
53
63
|
* 404s if it can't find the file
|
54
64
|
|
@@ -118,6 +128,7 @@
|
|
118
128
|
* can cache, but invalidates the cache
|
119
129
|
* can figure out if called via XHR
|
120
130
|
* can parse cookies
|
131
|
+
* parses cookies according to RFC 2109
|
121
132
|
* provides setters
|
122
133
|
* provides the original env
|
123
134
|
* can restore the URL
|
@@ -125,12 +136,14 @@
|
|
125
136
|
* can parse multipart form data
|
126
137
|
* can parse big multipart form data
|
127
138
|
* can detect invalid multipart form data
|
139
|
+
* does conform to the Rack spec
|
128
140
|
|
129
141
|
== Rack::Response
|
130
142
|
* has sensible default values
|
131
143
|
* can be written to
|
132
144
|
* can set and read headers
|
133
145
|
* can set cookies
|
146
|
+
* formats the Cookie expiration date accordingly to RFC 2109
|
134
147
|
* can delete cookies
|
135
148
|
* has a useful constructor
|
136
149
|
* has a constructor that can take a block
|
@@ -145,6 +158,11 @@
|
|
145
158
|
* survives broken cookies
|
146
159
|
* barks on too big cookies
|
147
160
|
|
161
|
+
== Rack::Session::Pool
|
162
|
+
* creates a new cookie
|
163
|
+
* loads from a cookie
|
164
|
+
* survives broken cookies
|
165
|
+
|
148
166
|
== Rack::ShowExceptions
|
149
167
|
* catches exceptions
|
150
168
|
|
@@ -186,4 +204,4 @@
|
|
186
204
|
* should set status
|
187
205
|
* should provide a .run
|
188
206
|
|
189
|
-
|
207
|
+
151 specifications, 2 empty (598 requirements), 0 failures
|
data/README
CHANGED
@@ -13,10 +13,17 @@ which all Rack applications should conform to.
|
|
13
13
|
|
14
14
|
The included *handlers* connect all kinds of web servers to Rack:
|
15
15
|
* Mongrel
|
16
|
-
* Mongrel/Swiftcore (require it before
|
16
|
+
* Mongrel/Swiftcore (require it before requiring rack)
|
17
17
|
* WEBrick
|
18
18
|
* FCGI
|
19
19
|
* CGI
|
20
|
+
* SCGI
|
21
|
+
* LiteSpeed
|
22
|
+
|
23
|
+
These web servers include Rack handlers in their distributions:
|
24
|
+
* Ebb
|
25
|
+
* Fuzed
|
26
|
+
* Thin
|
20
27
|
|
21
28
|
Any valid Rack app will run the same on all these handlers, without
|
22
29
|
changing anything.
|
@@ -25,13 +32,22 @@ changing anything.
|
|
25
32
|
|
26
33
|
The included *adapters* connect Rack with existing Ruby web frameworks:
|
27
34
|
* Camping
|
28
|
-
* Rails (alpha)
|
29
|
-
* more to come soon, ...
|
30
35
|
|
31
36
|
These frameworks include Rack adapters in their distributions:
|
32
|
-
*
|
37
|
+
* Coset
|
38
|
+
* Halcyon
|
33
39
|
* Maveric
|
40
|
+
* Merb
|
34
41
|
* Racktools::SimpleApplication
|
42
|
+
* Ramaze
|
43
|
+
* Sinatra
|
44
|
+
* Vintage
|
45
|
+
|
46
|
+
Ruby on Rails can be run with the adapter included with Thin, which
|
47
|
+
will be merged into a later Rack version.
|
48
|
+
|
49
|
+
Current links to these projects can be found at
|
50
|
+
http://ramaze.net/#other-frameworks
|
35
51
|
|
36
52
|
== Available middleware
|
37
53
|
|
@@ -42,7 +58,7 @@ applications needs using middleware, for example:
|
|
42
58
|
* Rack::ShowException, for catching unhandled exceptions and
|
43
59
|
presenting them in a nice and helpful way with clickable backtrace.
|
44
60
|
* Rack::File, for serving static files.
|
45
|
-
* ...
|
61
|
+
* ...many others!
|
46
62
|
|
47
63
|
All these components use the same interface, which is described in
|
48
64
|
detail in the Rack specification. You can choose to use them exactly
|
@@ -110,6 +126,18 @@ at my site:
|
|
110
126
|
* Bug fixes in the Camping adapter.
|
111
127
|
* Removed Rails adapter, was too alpha.
|
112
128
|
|
129
|
+
* February 26th, 2008: Third public release 0.3.
|
130
|
+
* LiteSpeed handler, by Adrian Madrid.
|
131
|
+
* SCGI handler, by Jeremy Evans.
|
132
|
+
* Pool sessions, by blink.
|
133
|
+
* OpenID authentication, by blink.
|
134
|
+
* :Port and :File options for opening FastCGI sockets, by blink.
|
135
|
+
* Last-Modified HTTP header for Rack::File, by blink.
|
136
|
+
* Rack::Builder#use now accepts blocks, by Corey Jewett.
|
137
|
+
(See example/protectedlobster.ru)
|
138
|
+
* HTTP status 201 can contain a Content-Type and a body now.
|
139
|
+
* Many bugfixes, especially related to Cookie handling.
|
140
|
+
|
113
141
|
== Contact
|
114
142
|
|
115
143
|
Please mail bugs, suggestions and patches to
|
@@ -124,11 +152,16 @@ You are also welcome to join the #rack channel on irc.freenode.net.
|
|
124
152
|
|
125
153
|
* Michael Fellinger, for the helpful discussion, bugfixes and a better
|
126
154
|
Rack::Request interface.
|
155
|
+
* Adrian Madrid, for the LiteSpeed handler.
|
127
156
|
* Christoffer Sawicki, for the Rails adapter.
|
128
157
|
* Tim Fletcher, for the HTTP authentication code.
|
158
|
+
* Luc Heinrich for the Cookie sessions, the static file handler and bugfixes.
|
159
|
+
* blink for the Pool sessions, OpenID support, various tweaks, and bugreports.
|
129
160
|
* Armin Ronacher, for the logo and racktools.
|
130
161
|
* Aredridel, for bug fixing.
|
131
162
|
* Gary Wright, for proposing a better Rack::Response interface.
|
163
|
+
* Jonathan Buch, for improvements regarding Rack::Response.
|
164
|
+
* Armin Röhrl, for tracking down bugs in the Cookie generator.
|
132
165
|
* Alexander Kellett for testing the Gem and reviewing the announce.
|
133
166
|
* Marcus Rückert, for help with configuring and debugging lighttpd.
|
134
167
|
* The WSGI team for the well-done and documented work they've done and
|
@@ -136,7 +169,7 @@ You are also welcome to join the #rack channel on irc.freenode.net.
|
|
136
169
|
|
137
170
|
== Copyright
|
138
171
|
|
139
|
-
Copyright (C) 2007
|
172
|
+
Copyright (C) 2007, 2008 Christian Neukirchen <http://purl.org/net/chneukirchen>
|
140
173
|
|
141
174
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
142
175
|
of this software and associated documentation files (the "Software"), to
|
data/Rakefile
CHANGED
data/SPEC
CHANGED
@@ -74,7 +74,7 @@ There are the following restrictions:
|
|
74
74
|
* <tt>rack.url_scheme</tt> must either be +http+ or +https+.
|
75
75
|
* There must be a valid input stream in <tt>rack.input</tt>.
|
76
76
|
* There must be a valid error stream in <tt>rack.errors</tt>.
|
77
|
-
* The <tt>REQUEST_METHOD</tt> must be one of +GET+, +POST+,
|
77
|
+
* The <tt>REQUEST_METHOD</tt> must be one of +GET+, +POST+, +PUT+,
|
78
78
|
+DELETE+, +HEAD+, +OPTIONS+, +TRACE+.
|
79
79
|
* The <tt>SCRIPT_NAME</tt>, if non-empty, must start with <tt>/</tt>
|
80
80
|
* The <tt>PATH_INFO</tt>, if non-empty, must start with <tt>/</tt>
|
@@ -115,7 +115,7 @@ The values passed on #each must be Strings
|
|
115
115
|
and not contain characters below 037.
|
116
116
|
=== The Content-Type
|
117
117
|
There must be a <tt>Content-Type</tt>, except when the
|
118
|
-
+Status+ is
|
118
|
+
+Status+ is 204 or 304, in which case there must be none
|
119
119
|
given.
|
120
120
|
=== The Body
|
121
121
|
The Body must respond to #each
|
data/bin/rackup
CHANGED
@@ -98,6 +98,10 @@ when nil
|
|
98
98
|
# Guess.
|
99
99
|
if ENV.include?("PHP_FCGI_CHILDREN")
|
100
100
|
server = Rack::Handler::FastCGI
|
101
|
+
|
102
|
+
# We already speak FastCGI
|
103
|
+
options.delete :File
|
104
|
+
options.delete :Port
|
101
105
|
elsif ENV.include?("REQUEST_METHOD")
|
102
106
|
server = Rack::Handler::CGI
|
103
107
|
else
|
data/lib/rack.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2007 Christian Neukirchen <purl.org/net/chneukirchen>
|
1
|
+
# Copyright (C) 2007, 2008 Christian Neukirchen <purl.org/net/chneukirchen>
|
2
2
|
#
|
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.
|
@@ -13,10 +13,10 @@ $: << File.expand_path(File.dirname(__FILE__))
|
|
13
13
|
# so it should be enough just to <tt>require rack.rb</tt> in your code.
|
14
14
|
|
15
15
|
module Rack
|
16
|
-
# The Rack version number.
|
16
|
+
# The Rack protocol version number implemented.
|
17
17
|
VERSION = [0,1]
|
18
18
|
|
19
|
-
# Return the Rack version as a dotted string.
|
19
|
+
# Return the Rack protocol version as a dotted string.
|
20
20
|
def self.version
|
21
21
|
VERSION.join(".")
|
22
22
|
end
|
@@ -45,6 +45,7 @@ module Rack
|
|
45
45
|
autoload :Basic, "rack/auth/basic"
|
46
46
|
autoload :AbstractRequest, "rack/auth/abstract/request"
|
47
47
|
autoload :AbstractHandler, "rack/auth/abstract/handler"
|
48
|
+
autoload :OpenID, "rack/auth/openid"
|
48
49
|
module Digest
|
49
50
|
autoload :MD5, "rack/auth/digest/md5"
|
50
51
|
autoload :Nonce, "rack/auth/digest/nonce"
|
@@ -55,22 +56,25 @@ module Rack
|
|
55
56
|
|
56
57
|
module Session
|
57
58
|
autoload :Cookie, "rack/session/cookie"
|
59
|
+
autoload :Pool, "rack/session/pool"
|
60
|
+
autoload :Memcache, "rack/session/memcache"
|
58
61
|
end
|
59
62
|
|
60
63
|
# *Adapters* connect Rack with third party web frameworks.
|
61
64
|
#
|
62
|
-
# Rack includes
|
65
|
+
# Rack includes an adapter for Camping, see README for other
|
66
|
+
# frameworks supporting Rack in their code bases.
|
63
67
|
#
|
64
68
|
# Refer to the submodules for framework-specific calling details.
|
65
69
|
|
66
70
|
module Adapter
|
67
71
|
autoload :Camping, "rack/adapter/camping"
|
68
|
-
autoload :Rails, "rack/adapter/rails"
|
69
72
|
end
|
70
73
|
|
71
74
|
# *Handlers* connect web servers with Rack.
|
72
75
|
#
|
73
|
-
# Rack includes Handlers for Mongrel, WEBrick, FastCGI
|
76
|
+
# Rack includes Handlers for Mongrel, WEBrick, FastCGI, CGI, SCGI
|
77
|
+
# and LiteSpeed.
|
74
78
|
#
|
75
79
|
# Handlers usually are activated by calling <tt>MyHandler.run(myapp)</tt>.
|
76
80
|
# A second optional hash can be passed to include server-specific
|
@@ -81,6 +85,8 @@ module Rack
|
|
81
85
|
autoload :FastCGI, "rack/handler/fastcgi"
|
82
86
|
autoload :Mongrel, "rack/handler/mongrel"
|
83
87
|
autoload :WEBrick, "rack/handler/webrick"
|
88
|
+
autoload :LSWS, "rack/handler/lsws"
|
89
|
+
autoload :SCGI, "rack/handler/scgi"
|
84
90
|
end
|
85
91
|
end
|
86
92
|
|
data/lib/rack/auth/basic.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'base64'
|
2
1
|
require 'digest/md5'
|
3
2
|
|
4
3
|
module Rack
|
@@ -19,7 +18,7 @@ module Rack
|
|
19
18
|
end
|
20
19
|
|
21
20
|
def self.parse(string)
|
22
|
-
new(*
|
21
|
+
new(*string.unpack("m*").first.split(' ', 2))
|
23
22
|
end
|
24
23
|
|
25
24
|
def initialize(timestamp = Time.now, given_digest = nil)
|
@@ -27,7 +26,7 @@ module Rack
|
|
27
26
|
end
|
28
27
|
|
29
28
|
def to_s
|
30
|
-
|
29
|
+
[([ @timestamp, digest ] * ' ')].pack("m*").strip
|
31
30
|
end
|
32
31
|
|
33
32
|
def digest
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# AUTHOR: blink <blinketje@gmail.com>; blink#ruby-lang@irc.freenode.net
|
2
|
+
|
3
|
+
require 'rack/auth/abstract/handler'
|
4
|
+
require 'openid'
|
5
|
+
|
6
|
+
module Rack
|
7
|
+
module Auth
|
8
|
+
# Rack::Auth::OpenID provides a simple method for permitting openid
|
9
|
+
# based logins. It requires the ruby-openid lib from janrain to operate,
|
10
|
+
# as well as some method of session management of a Hash type.
|
11
|
+
#
|
12
|
+
# After a transaction, the response status object is stored in the
|
13
|
+
# environment at rack.auth.openid.status, which can be used in the
|
14
|
+
# followup block or in a wrapping application to accomplish
|
15
|
+
# additional data maniipulation.
|
16
|
+
#
|
17
|
+
# NOTE: Due to the amount of data that ruby-openid stores in the session,
|
18
|
+
# Rack::Session::Cookie may fault.
|
19
|
+
#
|
20
|
+
# A hash of data is stored in the session hash at the key of :openid.
|
21
|
+
# The fully canonicalized identity url is stored within at 'identity'.
|
22
|
+
# Extension data from 'openid.sreg.nickname' would be stored as
|
23
|
+
# { 'nickname' => value }.
|
24
|
+
#
|
25
|
+
# NOTE: To my knowledge there is no collision at this point from storage
|
26
|
+
# of this manner, if there is please let me know so I may adjust this app
|
27
|
+
# to cope.
|
28
|
+
class OpenID < AbstractHandler
|
29
|
+
# Required for ruby-openid
|
30
|
+
OIDStore = ::OpenID::MemoryStore.new
|
31
|
+
|
32
|
+
# A Hash of options is taken as it's single initializing
|
33
|
+
# argument. String keys are taken to be openid protocol
|
34
|
+
# extension namespaces.
|
35
|
+
#
|
36
|
+
# For example: 'sreg' => { 'required' => # 'nickname' }
|
37
|
+
#
|
38
|
+
# Other keys are taken as options for Rack::Auth::OpenID, normally Symbols.
|
39
|
+
# Only :return is required. :trust is highly recommended to be set.
|
40
|
+
#
|
41
|
+
# * :return defines the url to return to after the client authenticates
|
42
|
+
# with the openid service provider. Should point to where this app is
|
43
|
+
# mounted. (ex: 'http://mysite.com/openid')
|
44
|
+
# * :trust defines the url identifying the site they are actually logging
|
45
|
+
# into. (ex: 'http://mysite.com/')
|
46
|
+
# * :session_key defines the key to the session hash in the env.
|
47
|
+
# (by default it uses 'rack.session')
|
48
|
+
def initialize(options={})
|
49
|
+
raise ArgumentError, 'No return url provided.' unless options[:return]
|
50
|
+
warn 'No trust url provided.' unless options[:trust]
|
51
|
+
options[:trust] ||= options[:return]
|
52
|
+
|
53
|
+
@options = {
|
54
|
+
:session_key => 'rack.session'
|
55
|
+
}.merge(options)
|
56
|
+
end
|
57
|
+
|
58
|
+
def call(env)
|
59
|
+
request = Rack::Request.new env
|
60
|
+
return no_session unless session = request.env[@options[:session_key]]
|
61
|
+
resp = if request.GET['openid.mode']
|
62
|
+
finish session, request.GET, env
|
63
|
+
elsif request.GET['openid_url']
|
64
|
+
check session, request.GET['openid_url'], env
|
65
|
+
else
|
66
|
+
bad_request
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def check(session, oid_url, env)
|
71
|
+
consumer = ::OpenID::Consumer.new session, OIDStore
|
72
|
+
oid = consumer.begin oid_url
|
73
|
+
return auth_fail unless oid.status == ::OpenID::SUCCESS
|
74
|
+
@options.each do |ns,s|
|
75
|
+
next unless ns.is_a? String
|
76
|
+
s.each {|k,v| oid.add_extension_arg(ns, k, v) }
|
77
|
+
end
|
78
|
+
r_url = @options.fetch :return do |k| request.url end
|
79
|
+
t_url = @options.fetch :trust
|
80
|
+
env['rack.auth.openid.status'] = oid
|
81
|
+
return 303, {'Location'=>oid.redirect_url( t_url, r_url )}, []
|
82
|
+
end
|
83
|
+
|
84
|
+
def finish(session, params, env)
|
85
|
+
consumer = ::OpenID::Consumer.new session, OIDStore
|
86
|
+
oid = consumer.complete params
|
87
|
+
return bad_login unless oid.status == ::OpenID::SUCCESS
|
88
|
+
session[:openid] = {'identity' => oid.identity_url}
|
89
|
+
@options.each do |ns,s|
|
90
|
+
next unless ns.is_a? String
|
91
|
+
oid.extension_response(ns).each{|k,v| session[k]=v }
|
92
|
+
end
|
93
|
+
env['rack.auth.openid.status'] = oid
|
94
|
+
return 303, {'Location'=>@options[:trust]}, []
|
95
|
+
end
|
96
|
+
|
97
|
+
def no_session
|
98
|
+
@options.
|
99
|
+
fetch :no_session, [500,{'Content-Type'=>'text/plain'},'No session available.']
|
100
|
+
end
|
101
|
+
def auth_fail
|
102
|
+
@options.
|
103
|
+
fetch :auth_fail, [500, {'Content-Type'=>'text/plain'},'Foreign server failure.']
|
104
|
+
end
|
105
|
+
def bad_login
|
106
|
+
@options.
|
107
|
+
fetch :bad_login, [401, {'Content-Type'=>'text/plain'},'Identification has failed.']
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|