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 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
- 137 specifications (546 requirements), 0 failures
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 Rack.)
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
- * Ramaze
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 Christian Neukirchen <http://purl.org/net/chneukirchen>
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
@@ -28,7 +28,7 @@ def get_darcs_tree_version
28
28
  count = 0
29
29
  tag = "0.0"
30
30
 
31
- changes.each("\n\n") { |change|
31
+ changes.split("\n\n").each { |change|
32
32
  head, title, desc = change.split("\n", 3)
33
33
 
34
34
  if title =~ /^ \*/
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 201, 204, 304, in which case there must be none
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
@@ -0,0 +1,8 @@
1
+ require 'rack/lobster'
2
+
3
+ use Rack::ShowExceptions
4
+ use Rack::Auth::Basic do |username, password|
5
+ 'secret' == password
6
+ end
7
+
8
+ run Rack::Lobster.new
@@ -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 adapters for Camping and Rails.
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 and CGI.
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
 
@@ -1,5 +1,3 @@
1
- require 'base64'
2
-
3
1
  module Rack
4
2
  module Auth
5
3
  class AbstractRequest
@@ -45,7 +45,7 @@ module Rack
45
45
  end
46
46
 
47
47
  def credentials
48
- @credentials ||= Base64.decode64(params).split(/:/, 2)
48
+ @credentials ||= params.unpack("m*").first.split(/:/, 2)
49
49
  end
50
50
 
51
51
  def username
@@ -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(*Base64.decode64(string).split(' ', 2))
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
- Base64.encode64([ @timestamp, digest ] * ' ').strip
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