actionpack 2.3.2 → 2.3.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- data/CHANGELOG +5 -0
- data/Rakefile +10 -9
- data/lib/action_controller.rb +2 -7
- data/lib/action_controller/assertions/response_assertions.rb +11 -3
- data/lib/action_controller/base.rb +7 -2
- data/lib/action_controller/caching.rb +1 -1
- data/lib/action_controller/caching/actions.rb +9 -1
- data/lib/action_controller/caching/sweeper.rb +45 -0
- data/lib/action_controller/caching/sweeping.rb +0 -42
- data/lib/action_controller/failsafe.rb +40 -6
- data/lib/action_controller/flash.rb +11 -3
- data/lib/action_controller/http_authentication.rb +5 -2
- data/lib/action_controller/integration.rb +5 -12
- data/lib/action_controller/middlewares.rb +0 -1
- data/lib/action_controller/reloader.rb +34 -3
- data/lib/action_controller/request.rb +6 -2
- data/lib/action_controller/response.rb +2 -2
- data/lib/action_controller/routing/route_set.rb +2 -1
- data/lib/action_controller/streaming.rb +1 -1
- data/lib/action_controller/test_process.rb +9 -1
- data/lib/action_pack/version.rb +1 -1
- data/lib/action_view/helpers.rb +1 -1
- data/lib/action_view/helpers/asset_tag_helper.rb +21 -9
- data/lib/action_view/helpers/date_helper.rb +2 -2
- data/lib/action_view/helpers/form_helper.rb +25 -12
- data/lib/action_view/helpers/form_options_helper.rb +2 -0
- data/lib/action_view/helpers/form_tag_helper.rb +10 -4
- data/lib/action_view/helpers/number_helper.rb +1 -1
- data/lib/action_view/helpers/prototype_helper.rb +7 -7
- data/lib/action_view/helpers/scriptaculous_helper.rb +5 -5
- data/lib/action_view/helpers/text_helper.rb +3 -3
- data/lib/action_view/helpers/url_helper.rb +1 -1
- data/lib/action_view/paths.rb +1 -1
- data/lib/action_view/template.rb +22 -33
- data/test/abstract_unit.rb +1 -1
- data/test/activerecord/active_record_store_test.rb +3 -3
- data/test/controller/action_pack_assertions_test.rb +27 -0
- data/test/controller/caching_test.rb +39 -0
- data/test/controller/cookie_test.rb +10 -0
- data/test/controller/dispatcher_test.rb +9 -7
- data/test/controller/failsafe_test.rb +60 -0
- data/test/controller/filter_params_test.rb +2 -1
- data/test/controller/flash_test.rb +6 -1
- data/test/controller/http_digest_authentication_test.rb +34 -3
- data/test/controller/integration_test.rb +31 -3
- data/test/controller/redirect_test.rb +4 -1
- data/test/controller/reloader_test.rb +97 -0
- data/test/controller/render_test.rb +19 -9
- data/test/controller/request/multipart_params_parsing_test.rb +1 -62
- data/test/controller/request/test_request_test.rb +35 -0
- data/test/controller/request/url_encoded_params_parsing_test.rb +0 -38
- data/test/controller/request_test.rb +218 -230
- data/test/controller/resources_test.rb +8 -0
- data/test/controller/routing_test.rb +21 -0
- data/test/controller/send_file_test.rb +1 -1
- data/test/controller/session/cookie_store_test.rb +9 -32
- data/test/controller/test_test.rb +8 -0
- data/test/fixtures/failsafe/500.html +1 -0
- data/test/template/active_record_helper_test.rb +1 -1
- data/test/template/asset_tag_helper_test.rb +46 -0
- data/test/template/form_helper_test.rb +117 -6
- data/test/template/form_options_helper_test.rb +22 -0
- data/test/template/form_tag_helper_test.rb +23 -6
- data/test/template/prototype_helper_test.rb +11 -11
- data/test/template/template_test.rb +32 -0
- metadata +20 -63
- data/lib/action_controller/rewindable_input.rb +0 -28
- data/lib/action_controller/vendor/rack-1.0/rack.rb +0 -89
- data/lib/action_controller/vendor/rack-1.0/rack/adapter/camping.rb +0 -22
- data/lib/action_controller/vendor/rack-1.0/rack/auth/abstract/handler.rb +0 -37
- data/lib/action_controller/vendor/rack-1.0/rack/auth/abstract/request.rb +0 -37
- data/lib/action_controller/vendor/rack-1.0/rack/auth/basic.rb +0 -58
- data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/md5.rb +0 -124
- data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/nonce.rb +0 -51
- data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/params.rb +0 -55
- data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/request.rb +0 -40
- data/lib/action_controller/vendor/rack-1.0/rack/auth/openid.rb +0 -480
- data/lib/action_controller/vendor/rack-1.0/rack/builder.rb +0 -63
- data/lib/action_controller/vendor/rack-1.0/rack/cascade.rb +0 -36
- data/lib/action_controller/vendor/rack-1.0/rack/chunked.rb +0 -49
- data/lib/action_controller/vendor/rack-1.0/rack/commonlogger.rb +0 -61
- data/lib/action_controller/vendor/rack-1.0/rack/conditionalget.rb +0 -45
- data/lib/action_controller/vendor/rack-1.0/rack/content_length.rb +0 -29
- data/lib/action_controller/vendor/rack-1.0/rack/content_type.rb +0 -23
- data/lib/action_controller/vendor/rack-1.0/rack/deflater.rb +0 -85
- data/lib/action_controller/vendor/rack-1.0/rack/directory.rb +0 -153
- data/lib/action_controller/vendor/rack-1.0/rack/file.rb +0 -88
- data/lib/action_controller/vendor/rack-1.0/rack/handler.rb +0 -48
- data/lib/action_controller/vendor/rack-1.0/rack/handler/cgi.rb +0 -61
- data/lib/action_controller/vendor/rack-1.0/rack/handler/evented_mongrel.rb +0 -8
- data/lib/action_controller/vendor/rack-1.0/rack/handler/fastcgi.rb +0 -89
- data/lib/action_controller/vendor/rack-1.0/rack/handler/lsws.rb +0 -55
- data/lib/action_controller/vendor/rack-1.0/rack/handler/mongrel.rb +0 -84
- data/lib/action_controller/vendor/rack-1.0/rack/handler/scgi.rb +0 -59
- data/lib/action_controller/vendor/rack-1.0/rack/handler/swiftiplied_mongrel.rb +0 -8
- data/lib/action_controller/vendor/rack-1.0/rack/handler/thin.rb +0 -18
- data/lib/action_controller/vendor/rack-1.0/rack/handler/webrick.rb +0 -67
- data/lib/action_controller/vendor/rack-1.0/rack/head.rb +0 -19
- data/lib/action_controller/vendor/rack-1.0/rack/lint.rb +0 -462
- data/lib/action_controller/vendor/rack-1.0/rack/lobster.rb +0 -65
- data/lib/action_controller/vendor/rack-1.0/rack/lock.rb +0 -16
- data/lib/action_controller/vendor/rack-1.0/rack/methodoverride.rb +0 -27
- data/lib/action_controller/vendor/rack-1.0/rack/mime.rb +0 -204
- data/lib/action_controller/vendor/rack-1.0/rack/mock.rb +0 -160
- data/lib/action_controller/vendor/rack-1.0/rack/recursive.rb +0 -57
- data/lib/action_controller/vendor/rack-1.0/rack/reloader.rb +0 -64
- data/lib/action_controller/vendor/rack-1.0/rack/request.rb +0 -241
- data/lib/action_controller/vendor/rack-1.0/rack/response.rb +0 -179
- data/lib/action_controller/vendor/rack-1.0/rack/session/abstract/id.rb +0 -142
- data/lib/action_controller/vendor/rack-1.0/rack/session/cookie.rb +0 -91
- data/lib/action_controller/vendor/rack-1.0/rack/session/memcache.rb +0 -109
- data/lib/action_controller/vendor/rack-1.0/rack/session/pool.rb +0 -100
- data/lib/action_controller/vendor/rack-1.0/rack/showexceptions.rb +0 -349
- data/lib/action_controller/vendor/rack-1.0/rack/showstatus.rb +0 -106
- data/lib/action_controller/vendor/rack-1.0/rack/static.rb +0 -38
- data/lib/action_controller/vendor/rack-1.0/rack/urlmap.rb +0 -55
- data/lib/action_controller/vendor/rack-1.0/rack/utils.rb +0 -392
@@ -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,64 +0,0 @@
|
|
1
|
-
require 'thread'
|
2
|
-
|
3
|
-
module Rack
|
4
|
-
# Rack::Reloader checks on every request, but at most every +secs+
|
5
|
-
# seconds, if a file loaded changed, and reloads it, logging to
|
6
|
-
# rack.errors.
|
7
|
-
#
|
8
|
-
# It is recommended you use ShowExceptions to catch SyntaxErrors etc.
|
9
|
-
|
10
|
-
class Reloader
|
11
|
-
def initialize(app, secs=10)
|
12
|
-
@app = app
|
13
|
-
@secs = secs # reload every @secs seconds max
|
14
|
-
@last = Time.now
|
15
|
-
end
|
16
|
-
|
17
|
-
def call(env)
|
18
|
-
if Time.now > @last + @secs
|
19
|
-
Thread.exclusive {
|
20
|
-
reload!(env['rack.errors'])
|
21
|
-
@last = Time.now
|
22
|
-
}
|
23
|
-
end
|
24
|
-
|
25
|
-
@app.call(env)
|
26
|
-
end
|
27
|
-
|
28
|
-
def reload!(stderr=$stderr)
|
29
|
-
need_reload = $LOADED_FEATURES.find_all { |loaded|
|
30
|
-
begin
|
31
|
-
if loaded =~ /\A[.\/]/ # absolute filename or 1.9
|
32
|
-
abs = loaded
|
33
|
-
else
|
34
|
-
abs = $LOAD_PATH.map { |path| ::File.join(path, loaded) }.
|
35
|
-
find { |file| ::File.exist? file }
|
36
|
-
end
|
37
|
-
|
38
|
-
if abs
|
39
|
-
::File.mtime(abs) > @last - @secs rescue false
|
40
|
-
else
|
41
|
-
false
|
42
|
-
end
|
43
|
-
end
|
44
|
-
}
|
45
|
-
|
46
|
-
need_reload.each { |l|
|
47
|
-
$LOADED_FEATURES.delete l
|
48
|
-
}
|
49
|
-
|
50
|
-
need_reload.each { |to_load|
|
51
|
-
begin
|
52
|
-
if require to_load
|
53
|
-
stderr.puts "#{self.class}: reloaded `#{to_load}'"
|
54
|
-
end
|
55
|
-
rescue LoadError, SyntaxError => e
|
56
|
-
raise e # Possibly ShowExceptions
|
57
|
-
end
|
58
|
-
}
|
59
|
-
|
60
|
-
stderr.flush
|
61
|
-
need_reload
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
@@ -1,241 +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 self.new(env)
|
21
|
-
if self == Rack::Request
|
22
|
-
env["rack.request"] ||= super
|
23
|
-
else
|
24
|
-
super
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def initialize(env)
|
29
|
-
@env = env
|
30
|
-
end
|
31
|
-
|
32
|
-
def body; @env["rack.input"] end
|
33
|
-
def scheme; @env["rack.url_scheme"] end
|
34
|
-
def script_name; @env["SCRIPT_NAME"].to_s end
|
35
|
-
def path_info; @env["PATH_INFO"].to_s end
|
36
|
-
def port; @env["SERVER_PORT"].to_i end
|
37
|
-
def request_method; @env["REQUEST_METHOD"] end
|
38
|
-
def query_string; @env["QUERY_STRING"].to_s end
|
39
|
-
def content_length; @env['CONTENT_LENGTH'] end
|
40
|
-
def content_type; @env['CONTENT_TYPE'] end
|
41
|
-
|
42
|
-
# The media type (type/subtype) portion of the CONTENT_TYPE header
|
43
|
-
# without any media type parameters. e.g., when CONTENT_TYPE is
|
44
|
-
# "text/plain;charset=utf-8", the media-type is "text/plain".
|
45
|
-
#
|
46
|
-
# For more information on the use of media types in HTTP, see:
|
47
|
-
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
|
48
|
-
def media_type
|
49
|
-
content_type && content_type.split(/\s*[;,]\s*/, 2)[0].downcase
|
50
|
-
end
|
51
|
-
|
52
|
-
# The media type parameters provided in CONTENT_TYPE as a Hash, or
|
53
|
-
# an empty Hash if no CONTENT_TYPE or media-type parameters were
|
54
|
-
# provided. e.g., when the CONTENT_TYPE is "text/plain;charset=utf-8",
|
55
|
-
# this method responds with the following Hash:
|
56
|
-
# { 'charset' => 'utf-8' }
|
57
|
-
def media_type_params
|
58
|
-
return {} if content_type.nil?
|
59
|
-
content_type.split(/\s*[;,]\s*/)[1..-1].
|
60
|
-
collect { |s| s.split('=', 2) }.
|
61
|
-
inject({}) { |hash,(k,v)| hash[k.downcase] = v ; hash }
|
62
|
-
end
|
63
|
-
|
64
|
-
# The character set of the request body if a "charset" media type
|
65
|
-
# parameter was given, or nil if no "charset" was specified. Note
|
66
|
-
# that, per RFC2616, text/* media types that specify no explicit
|
67
|
-
# charset are to be considered ISO-8859-1.
|
68
|
-
def content_charset
|
69
|
-
media_type_params['charset']
|
70
|
-
end
|
71
|
-
|
72
|
-
def host
|
73
|
-
# Remove port number.
|
74
|
-
(@env["HTTP_HOST"] || @env["SERVER_NAME"]).gsub(/:\d+\z/, '')
|
75
|
-
end
|
76
|
-
|
77
|
-
def script_name=(s); @env["SCRIPT_NAME"] = s.to_s end
|
78
|
-
def path_info=(s); @env["PATH_INFO"] = s.to_s end
|
79
|
-
|
80
|
-
def get?; request_method == "GET" end
|
81
|
-
def post?; request_method == "POST" end
|
82
|
-
def put?; request_method == "PUT" end
|
83
|
-
def delete?; request_method == "DELETE" end
|
84
|
-
def head?; request_method == "HEAD" end
|
85
|
-
|
86
|
-
# The set of form-data media-types. Requests that do not indicate
|
87
|
-
# one of the media types presents in this list will not be eligible
|
88
|
-
# for form-data / param parsing.
|
89
|
-
FORM_DATA_MEDIA_TYPES = [
|
90
|
-
nil,
|
91
|
-
'application/x-www-form-urlencoded',
|
92
|
-
'multipart/form-data'
|
93
|
-
]
|
94
|
-
|
95
|
-
# Determine whether the request body contains form-data by checking
|
96
|
-
# the request media_type against registered form-data media-types:
|
97
|
-
# "application/x-www-form-urlencoded" and "multipart/form-data". The
|
98
|
-
# list of form-data media types can be modified through the
|
99
|
-
# +FORM_DATA_MEDIA_TYPES+ array.
|
100
|
-
def form_data?
|
101
|
-
FORM_DATA_MEDIA_TYPES.include?(media_type)
|
102
|
-
end
|
103
|
-
|
104
|
-
# Returns the data recieved in the query string.
|
105
|
-
def GET
|
106
|
-
if @env["rack.request.query_string"] == query_string
|
107
|
-
@env["rack.request.query_hash"]
|
108
|
-
else
|
109
|
-
@env["rack.request.query_string"] = query_string
|
110
|
-
@env["rack.request.query_hash"] =
|
111
|
-
Utils.parse_nested_query(query_string)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
# Returns the data recieved in the request body.
|
116
|
-
#
|
117
|
-
# This method support both application/x-www-form-urlencoded and
|
118
|
-
# multipart/form-data.
|
119
|
-
def POST
|
120
|
-
if @env["rack.request.form_input"].eql? @env["rack.input"]
|
121
|
-
@env["rack.request.form_hash"]
|
122
|
-
elsif form_data?
|
123
|
-
@env["rack.request.form_input"] = @env["rack.input"]
|
124
|
-
unless @env["rack.request.form_hash"] =
|
125
|
-
Utils::Multipart.parse_multipart(env)
|
126
|
-
form_vars = @env["rack.input"].read
|
127
|
-
|
128
|
-
# Fix for Safari Ajax postings that always append \0
|
129
|
-
form_vars.sub!(/\0\z/, '')
|
130
|
-
|
131
|
-
@env["rack.request.form_vars"] = form_vars
|
132
|
-
@env["rack.request.form_hash"] = Utils.parse_nested_query(form_vars)
|
133
|
-
|
134
|
-
begin
|
135
|
-
@env["rack.input"].rewind if @env["rack.input"].respond_to?(:rewind)
|
136
|
-
rescue Errno::ESPIPE
|
137
|
-
# Handles exceptions raised by input streams that cannot be rewound
|
138
|
-
# such as when using plain CGI under Apache
|
139
|
-
end
|
140
|
-
end
|
141
|
-
@env["rack.request.form_hash"]
|
142
|
-
else
|
143
|
-
{}
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
# The union of GET and POST data.
|
148
|
-
def params
|
149
|
-
self.put? ? self.GET : self.GET.update(self.POST)
|
150
|
-
rescue EOFError => e
|
151
|
-
self.GET
|
152
|
-
end
|
153
|
-
|
154
|
-
# shortcut for request.params[key]
|
155
|
-
def [](key)
|
156
|
-
params[key.to_s]
|
157
|
-
end
|
158
|
-
|
159
|
-
# shortcut for request.params[key] = value
|
160
|
-
def []=(key, value)
|
161
|
-
params[key.to_s] = value
|
162
|
-
end
|
163
|
-
|
164
|
-
# like Hash#values_at
|
165
|
-
def values_at(*keys)
|
166
|
-
keys.map{|key| params[key] }
|
167
|
-
end
|
168
|
-
|
169
|
-
# the referer of the client or '/'
|
170
|
-
def referer
|
171
|
-
@env['HTTP_REFERER'] || '/'
|
172
|
-
end
|
173
|
-
alias referrer referer
|
174
|
-
|
175
|
-
|
176
|
-
def cookies
|
177
|
-
return {} unless @env["HTTP_COOKIE"]
|
178
|
-
|
179
|
-
if @env["rack.request.cookie_string"] == @env["HTTP_COOKIE"]
|
180
|
-
@env["rack.request.cookie_hash"]
|
181
|
-
else
|
182
|
-
@env["rack.request.cookie_string"] = @env["HTTP_COOKIE"]
|
183
|
-
# According to RFC 2109:
|
184
|
-
# If multiple cookies satisfy the criteria above, they are ordered in
|
185
|
-
# the Cookie header such that those with more specific Path attributes
|
186
|
-
# precede those with less specific. Ordering with respect to other
|
187
|
-
# attributes (e.g., Domain) is unspecified.
|
188
|
-
@env["rack.request.cookie_hash"] =
|
189
|
-
Utils.parse_query(@env["rack.request.cookie_string"], ';,').inject({}) {|h,(k,v)|
|
190
|
-
h[k] = Array === v ? v.first : v
|
191
|
-
h
|
192
|
-
}
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
def xhr?
|
197
|
-
@env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest"
|
198
|
-
end
|
199
|
-
|
200
|
-
# Tries to return a remake of the original request URL as a string.
|
201
|
-
def url
|
202
|
-
url = scheme + "://"
|
203
|
-
url << host
|
204
|
-
|
205
|
-
if scheme == "https" && port != 443 ||
|
206
|
-
scheme == "http" && port != 80
|
207
|
-
url << ":#{port}"
|
208
|
-
end
|
209
|
-
|
210
|
-
url << fullpath
|
211
|
-
|
212
|
-
url
|
213
|
-
end
|
214
|
-
|
215
|
-
def fullpath
|
216
|
-
path = script_name + path_info
|
217
|
-
path << "?" << query_string unless query_string.empty?
|
218
|
-
path
|
219
|
-
end
|
220
|
-
|
221
|
-
def accept_encoding
|
222
|
-
@env["HTTP_ACCEPT_ENCODING"].to_s.split(/,\s*/).map do |part|
|
223
|
-
m = /^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$/.match(part) # From WEBrick
|
224
|
-
|
225
|
-
if m
|
226
|
-
[m[1], (m[2] || 1.0).to_f]
|
227
|
-
else
|
228
|
-
raise "Invalid value for Accept-Encoding: #{part.inspect}"
|
229
|
-
end
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
def ip
|
234
|
-
if addr = @env['HTTP_X_FORWARDED_FOR']
|
235
|
-
addr.split(',').last.strip
|
236
|
-
else
|
237
|
-
@env['REMOTE_ADDR']
|
238
|
-
end
|
239
|
-
end
|
240
|
-
end
|
241
|
-
end
|
@@ -1,179 +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
|
-
|
99
|
-
def finish(&block)
|
100
|
-
@block = block
|
101
|
-
|
102
|
-
if [204, 304].include?(status.to_i)
|
103
|
-
header.delete "Content-Type"
|
104
|
-
[status.to_i, header.to_hash, []]
|
105
|
-
else
|
106
|
-
[status.to_i, header.to_hash, self]
|
107
|
-
end
|
108
|
-
end
|
109
|
-
alias to_a finish # For *response
|
110
|
-
|
111
|
-
def each(&callback)
|
112
|
-
@body.each(&callback)
|
113
|
-
@writer = callback
|
114
|
-
@block.call(self) if @block
|
115
|
-
end
|
116
|
-
|
117
|
-
# Append to body and update Content-Length.
|
118
|
-
#
|
119
|
-
# NOTE: Do not mix #write and direct #body access!
|
120
|
-
#
|
121
|
-
def write(str)
|
122
|
-
s = str.to_s
|
123
|
-
@length += s.size
|
124
|
-
@writer.call s
|
125
|
-
|
126
|
-
header["Content-Length"] = @length.to_s
|
127
|
-
str
|
128
|
-
end
|
129
|
-
|
130
|
-
def close
|
131
|
-
body.close if body.respond_to?(:close)
|
132
|
-
end
|
133
|
-
|
134
|
-
def empty?
|
135
|
-
@block == nil && @body.empty?
|
136
|
-
end
|
137
|
-
|
138
|
-
alias headers header
|
139
|
-
|
140
|
-
module Helpers
|
141
|
-
def invalid?; @status < 100 || @status >= 600; end
|
142
|
-
|
143
|
-
def informational?; @status >= 100 && @status < 200; end
|
144
|
-
def successful?; @status >= 200 && @status < 300; end
|
145
|
-
def redirection?; @status >= 300 && @status < 400; end
|
146
|
-
def client_error?; @status >= 400 && @status < 500; end
|
147
|
-
def server_error?; @status >= 500 && @status < 600; end
|
148
|
-
|
149
|
-
def ok?; @status == 200; end
|
150
|
-
def forbidden?; @status == 403; end
|
151
|
-
def not_found?; @status == 404; end
|
152
|
-
|
153
|
-
def redirect?; [301, 302, 303, 307].include? @status; end
|
154
|
-
def empty?; [201, 204, 304].include? @status; end
|
155
|
-
|
156
|
-
# Headers
|
157
|
-
attr_reader :headers, :original_headers
|
158
|
-
|
159
|
-
def include?(header)
|
160
|
-
!!headers[header]
|
161
|
-
end
|
162
|
-
|
163
|
-
def content_type
|
164
|
-
headers["Content-Type"]
|
165
|
-
end
|
166
|
-
|
167
|
-
def content_length
|
168
|
-
cl = headers["Content-Length"]
|
169
|
-
cl ? cl.to_i : cl
|
170
|
-
end
|
171
|
-
|
172
|
-
def location
|
173
|
-
headers["Location"]
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
include Helpers
|
178
|
-
end
|
179
|
-
end
|