halorgium-actionpack 3.0.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +5179 -0
- data/MIT-LICENSE +21 -0
- data/README +409 -0
- data/lib/abstract_controller.rb +16 -0
- data/lib/abstract_controller/base.rb +158 -0
- data/lib/abstract_controller/callbacks.rb +113 -0
- data/lib/abstract_controller/exceptions.rb +12 -0
- data/lib/abstract_controller/helpers.rb +151 -0
- data/lib/abstract_controller/layouts.rb +250 -0
- data/lib/abstract_controller/localized_cache.rb +49 -0
- data/lib/abstract_controller/logger.rb +61 -0
- data/lib/abstract_controller/rendering_controller.rb +188 -0
- data/lib/action_controller.rb +72 -0
- data/lib/action_controller/base.rb +168 -0
- data/lib/action_controller/caching.rb +80 -0
- data/lib/action_controller/caching/actions.rb +163 -0
- data/lib/action_controller/caching/fragments.rb +116 -0
- data/lib/action_controller/caching/pages.rb +154 -0
- data/lib/action_controller/caching/sweeping.rb +97 -0
- data/lib/action_controller/deprecated.rb +4 -0
- data/lib/action_controller/deprecated/integration_test.rb +2 -0
- data/lib/action_controller/deprecated/performance_test.rb +1 -0
- data/lib/action_controller/dispatch/dispatcher.rb +57 -0
- data/lib/action_controller/metal.rb +129 -0
- data/lib/action_controller/metal/benchmarking.rb +73 -0
- data/lib/action_controller/metal/compatibility.rb +145 -0
- data/lib/action_controller/metal/conditional_get.rb +86 -0
- data/lib/action_controller/metal/configuration.rb +28 -0
- data/lib/action_controller/metal/cookies.rb +105 -0
- data/lib/action_controller/metal/exceptions.rb +55 -0
- data/lib/action_controller/metal/filter_parameter_logging.rb +77 -0
- data/lib/action_controller/metal/flash.rb +162 -0
- data/lib/action_controller/metal/head.rb +27 -0
- data/lib/action_controller/metal/helpers.rb +115 -0
- data/lib/action_controller/metal/hide_actions.rb +47 -0
- data/lib/action_controller/metal/http_authentication.rb +312 -0
- data/lib/action_controller/metal/layouts.rb +171 -0
- data/lib/action_controller/metal/mime_responds.rb +317 -0
- data/lib/action_controller/metal/rack_convenience.rb +27 -0
- data/lib/action_controller/metal/redirector.rb +22 -0
- data/lib/action_controller/metal/render_options.rb +103 -0
- data/lib/action_controller/metal/rendering_controller.rb +57 -0
- data/lib/action_controller/metal/request_forgery_protection.rb +108 -0
- data/lib/action_controller/metal/rescuable.rb +13 -0
- data/lib/action_controller/metal/responder.rb +200 -0
- data/lib/action_controller/metal/session.rb +15 -0
- data/lib/action_controller/metal/session_management.rb +45 -0
- data/lib/action_controller/metal/streaming.rb +188 -0
- data/lib/action_controller/metal/testing.rb +39 -0
- data/lib/action_controller/metal/url_for.rb +41 -0
- data/lib/action_controller/metal/verification.rb +130 -0
- data/lib/action_controller/middleware.rb +38 -0
- data/lib/action_controller/notifications.rb +10 -0
- data/lib/action_controller/polymorphic_routes.rb +183 -0
- data/lib/action_controller/record_identifier.rb +91 -0
- data/lib/action_controller/testing/process.rb +111 -0
- data/lib/action_controller/testing/test_case.rb +345 -0
- data/lib/action_controller/translation.rb +13 -0
- data/lib/action_controller/url_rewriter.rb +204 -0
- data/lib/action_controller/vendor/html-scanner.rb +16 -0
- data/lib/action_controller/vendor/html-scanner/html/document.rb +68 -0
- data/lib/action_controller/vendor/html-scanner/html/node.rb +537 -0
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +176 -0
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +828 -0
- data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +105 -0
- data/lib/action_controller/vendor/html-scanner/html/version.rb +11 -0
- data/lib/action_dispatch.rb +70 -0
- data/lib/action_dispatch/http/headers.rb +33 -0
- data/lib/action_dispatch/http/mime_type.rb +231 -0
- data/lib/action_dispatch/http/mime_types.rb +23 -0
- data/lib/action_dispatch/http/request.rb +539 -0
- data/lib/action_dispatch/http/response.rb +290 -0
- data/lib/action_dispatch/http/status_codes.rb +42 -0
- data/lib/action_dispatch/http/utils.rb +20 -0
- data/lib/action_dispatch/middleware/callbacks.rb +50 -0
- data/lib/action_dispatch/middleware/params_parser.rb +79 -0
- data/lib/action_dispatch/middleware/rescue.rb +26 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +208 -0
- data/lib/action_dispatch/middleware/session/cookie_store.rb +235 -0
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +47 -0
- data/lib/action_dispatch/middleware/show_exceptions.rb +143 -0
- data/lib/action_dispatch/middleware/stack.rb +116 -0
- data/lib/action_dispatch/middleware/static.rb +44 -0
- data/lib/action_dispatch/middleware/string_coercion.rb +29 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +24 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +26 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +10 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +29 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +2 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +10 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +21 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +2 -0
- data/lib/action_dispatch/routing.rb +381 -0
- data/lib/action_dispatch/routing/deprecated_mapper.rb +878 -0
- data/lib/action_dispatch/routing/mapper.rb +327 -0
- data/lib/action_dispatch/routing/route.rb +49 -0
- data/lib/action_dispatch/routing/route_set.rb +497 -0
- data/lib/action_dispatch/testing/assertions.rb +8 -0
- data/lib/action_dispatch/testing/assertions/dom.rb +35 -0
- data/lib/action_dispatch/testing/assertions/model.rb +19 -0
- data/lib/action_dispatch/testing/assertions/response.rb +145 -0
- data/lib/action_dispatch/testing/assertions/routing.rb +144 -0
- data/lib/action_dispatch/testing/assertions/selector.rb +639 -0
- data/lib/action_dispatch/testing/assertions/tag.rb +123 -0
- data/lib/action_dispatch/testing/integration.rb +504 -0
- data/lib/action_dispatch/testing/performance_test.rb +15 -0
- data/lib/action_dispatch/testing/test_request.rb +83 -0
- data/lib/action_dispatch/testing/test_response.rb +131 -0
- data/lib/action_pack.rb +24 -0
- data/lib/action_pack/version.rb +9 -0
- data/lib/action_view.rb +58 -0
- data/lib/action_view/base.rb +308 -0
- data/lib/action_view/context.rb +44 -0
- data/lib/action_view/erb/util.rb +48 -0
- data/lib/action_view/helpers.rb +62 -0
- data/lib/action_view/helpers/active_model_helper.rb +306 -0
- data/lib/action_view/helpers/ajax_helper.rb +68 -0
- data/lib/action_view/helpers/asset_tag_helper.rb +830 -0
- data/lib/action_view/helpers/atom_feed_helper.rb +198 -0
- data/lib/action_view/helpers/cache_helper.rb +39 -0
- data/lib/action_view/helpers/capture_helper.rb +168 -0
- data/lib/action_view/helpers/date_helper.rb +988 -0
- data/lib/action_view/helpers/debug_helper.rb +38 -0
- data/lib/action_view/helpers/form_helper.rb +1102 -0
- data/lib/action_view/helpers/form_options_helper.rb +600 -0
- data/lib/action_view/helpers/form_tag_helper.rb +495 -0
- data/lib/action_view/helpers/javascript_helper.rb +208 -0
- data/lib/action_view/helpers/number_helper.rb +311 -0
- data/lib/action_view/helpers/prototype_helper.rb +1309 -0
- data/lib/action_view/helpers/raw_output_helper.rb +9 -0
- data/lib/action_view/helpers/record_identification_helper.rb +20 -0
- data/lib/action_view/helpers/record_tag_helper.rb +58 -0
- data/lib/action_view/helpers/sanitize_helper.rb +259 -0
- data/lib/action_view/helpers/scriptaculous_helper.rb +226 -0
- data/lib/action_view/helpers/tag_helper.rb +151 -0
- data/lib/action_view/helpers/text_helper.rb +594 -0
- data/lib/action_view/helpers/translation_helper.rb +39 -0
- data/lib/action_view/helpers/url_helper.rb +639 -0
- data/lib/action_view/locale/en.yml +117 -0
- data/lib/action_view/paths.rb +80 -0
- data/lib/action_view/render/partials.rb +342 -0
- data/lib/action_view/render/rendering.rb +134 -0
- data/lib/action_view/safe_buffer.rb +28 -0
- data/lib/action_view/template/error.rb +101 -0
- data/lib/action_view/template/handler.rb +36 -0
- data/lib/action_view/template/handlers.rb +52 -0
- data/lib/action_view/template/handlers/builder.rb +17 -0
- data/lib/action_view/template/handlers/erb.rb +53 -0
- data/lib/action_view/template/handlers/rjs.rb +18 -0
- data/lib/action_view/template/resolver.rb +165 -0
- data/lib/action_view/template/template.rb +131 -0
- data/lib/action_view/template/text.rb +38 -0
- data/lib/action_view/test_case.rb +163 -0
- metadata +236 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
require 'digest/md5'
|
|
2
|
+
require 'active_support/core_ext/module/delegation'
|
|
3
|
+
|
|
4
|
+
module ActionDispatch # :nodoc:
|
|
5
|
+
# Represents an HTTP response generated by a controller action. One can use
|
|
6
|
+
# an ActionDispatch::Response object to retrieve the current state
|
|
7
|
+
# of the response, or customize the response. An Response object can
|
|
8
|
+
# either represent a "real" HTTP response (i.e. one that is meant to be sent
|
|
9
|
+
# back to the web browser) or a test response (i.e. one that is generated
|
|
10
|
+
# from integration tests). See CgiResponse and TestResponse, respectively.
|
|
11
|
+
#
|
|
12
|
+
# Response is mostly a Ruby on Rails framework implement detail, and
|
|
13
|
+
# should never be used directly in controllers. Controllers should use the
|
|
14
|
+
# methods defined in ActionController::Base instead. For example, if you want
|
|
15
|
+
# to set the HTTP response's content MIME type, then use
|
|
16
|
+
# ActionControllerBase#headers instead of Response#headers.
|
|
17
|
+
#
|
|
18
|
+
# Nevertheless, integration tests may want to inspect controller responses in
|
|
19
|
+
# more detail, and that's when Response can be useful for application
|
|
20
|
+
# developers. Integration test methods such as
|
|
21
|
+
# ActionDispatch::Integration::Session#get and
|
|
22
|
+
# ActionDispatch::Integration::Session#post return objects of type
|
|
23
|
+
# TestResponse (which are of course also of type Response).
|
|
24
|
+
#
|
|
25
|
+
# For example, the following demo integration "test" prints the body of the
|
|
26
|
+
# controller response to the console:
|
|
27
|
+
#
|
|
28
|
+
# class DemoControllerTest < ActionDispatch::IntegrationTest
|
|
29
|
+
# def test_print_root_path_to_console
|
|
30
|
+
# get('/')
|
|
31
|
+
# puts @response.body
|
|
32
|
+
# end
|
|
33
|
+
# end
|
|
34
|
+
class Response < Rack::Response
|
|
35
|
+
attr_accessor :request, :blank
|
|
36
|
+
attr_reader :cache_control
|
|
37
|
+
|
|
38
|
+
attr_writer :header, :sending_file
|
|
39
|
+
alias_method :headers=, :header=
|
|
40
|
+
|
|
41
|
+
def initialize
|
|
42
|
+
@status = 200
|
|
43
|
+
@header = {}
|
|
44
|
+
@cache_control = {}
|
|
45
|
+
|
|
46
|
+
@writer = lambda { |x| @body << x }
|
|
47
|
+
@block = nil
|
|
48
|
+
@length = 0
|
|
49
|
+
|
|
50
|
+
@body, @cookie = [], []
|
|
51
|
+
@sending_file = false
|
|
52
|
+
|
|
53
|
+
yield self if block_given?
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def cache_control
|
|
57
|
+
@cache_control ||= {}
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def write(str)
|
|
61
|
+
s = str.to_s
|
|
62
|
+
@writer.call s
|
|
63
|
+
str
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def status=(status)
|
|
67
|
+
@status = status.to_i
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# The response code of the request
|
|
71
|
+
def response_code
|
|
72
|
+
@status
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Returns a String to ensure compatibility with Net::HTTPResponse
|
|
76
|
+
def code
|
|
77
|
+
@status.to_s
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def message
|
|
81
|
+
StatusCodes::STATUS_CODES[@status]
|
|
82
|
+
end
|
|
83
|
+
alias_method :status_message, :message
|
|
84
|
+
|
|
85
|
+
def body
|
|
86
|
+
str = ''
|
|
87
|
+
each { |part| str << part.to_s }
|
|
88
|
+
str
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
EMPTY = " "
|
|
92
|
+
|
|
93
|
+
def body=(body)
|
|
94
|
+
@blank = true if body == EMPTY
|
|
95
|
+
@body = body.respond_to?(:to_str) ? [body] : body
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def body_parts
|
|
99
|
+
@body
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def location
|
|
103
|
+
headers['Location']
|
|
104
|
+
end
|
|
105
|
+
alias_method :redirect_url, :location
|
|
106
|
+
|
|
107
|
+
def location=(url)
|
|
108
|
+
headers['Location'] = url
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Sets the HTTP response's content MIME type. For example, in the controller
|
|
112
|
+
# you could write this:
|
|
113
|
+
#
|
|
114
|
+
# response.content_type = "text/plain"
|
|
115
|
+
#
|
|
116
|
+
# If a character set has been defined for this response (see charset=) then
|
|
117
|
+
# the character set information will also be included in the content type
|
|
118
|
+
# information.
|
|
119
|
+
attr_accessor :charset, :content_type
|
|
120
|
+
|
|
121
|
+
def last_modified
|
|
122
|
+
if last = headers['Last-Modified']
|
|
123
|
+
Time.httpdate(last)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def last_modified?
|
|
128
|
+
headers.include?('Last-Modified')
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def last_modified=(utc_time)
|
|
132
|
+
headers['Last-Modified'] = utc_time.httpdate
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def etag
|
|
136
|
+
@etag
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def etag?
|
|
140
|
+
@etag
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def etag=(etag)
|
|
144
|
+
key = ActiveSupport::Cache.expand_cache_key(etag)
|
|
145
|
+
@etag = %("#{Digest::MD5.hexdigest(key)}")
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
CONTENT_TYPE = "Content-Type"
|
|
149
|
+
|
|
150
|
+
cattr_accessor(:default_charset) { "utf-8" }
|
|
151
|
+
|
|
152
|
+
def assign_default_content_type_and_charset!
|
|
153
|
+
return if headers[CONTENT_TYPE].present?
|
|
154
|
+
|
|
155
|
+
@content_type ||= Mime::HTML
|
|
156
|
+
@charset ||= self.class.default_charset
|
|
157
|
+
|
|
158
|
+
type = @content_type.to_s.dup
|
|
159
|
+
type << "; charset=#{@charset}" unless @sending_file
|
|
160
|
+
|
|
161
|
+
headers[CONTENT_TYPE] = type
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def to_a
|
|
165
|
+
assign_default_content_type_and_charset!
|
|
166
|
+
handle_conditional_get!
|
|
167
|
+
self["Set-Cookie"] = @cookie.join("\n")
|
|
168
|
+
self["ETag"] = @etag if @etag
|
|
169
|
+
super
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
alias prepare! to_a
|
|
173
|
+
|
|
174
|
+
def each(&callback)
|
|
175
|
+
if @body.respond_to?(:call)
|
|
176
|
+
@writer = lambda { |x| callback.call(x) }
|
|
177
|
+
@body.call(self, self)
|
|
178
|
+
else
|
|
179
|
+
@body.each { |part| callback.call(part.to_s) }
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
@writer = callback
|
|
183
|
+
@block.call(self) if @block
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def write(str)
|
|
187
|
+
str = str.to_s
|
|
188
|
+
@writer.call str
|
|
189
|
+
str
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Returns the response cookies, converted to a Hash of (name => value) pairs
|
|
193
|
+
#
|
|
194
|
+
# assert_equal 'AuthorOfNewPage', r.cookies['author']
|
|
195
|
+
def cookies
|
|
196
|
+
cookies = {}
|
|
197
|
+
if header = @cookie
|
|
198
|
+
header = header.split("\n") if header.respond_to?(:to_str)
|
|
199
|
+
header.each do |cookie|
|
|
200
|
+
if pair = cookie.split(';').first
|
|
201
|
+
key, value = pair.split("=").map { |v| Rack::Utils.unescape(v) }
|
|
202
|
+
cookies[key] = value
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
cookies
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def set_cookie(key, value)
|
|
210
|
+
case value
|
|
211
|
+
when Hash
|
|
212
|
+
domain = "; domain=" + value[:domain] if value[:domain]
|
|
213
|
+
path = "; path=" + value[:path] if value[:path]
|
|
214
|
+
# According to RFC 2109, we need dashes here.
|
|
215
|
+
# N.B.: cgi.rb uses spaces...
|
|
216
|
+
expires = "; expires=" + value[:expires].clone.gmtime.
|
|
217
|
+
strftime("%a, %d-%b-%Y %H:%M:%S GMT") if value[:expires]
|
|
218
|
+
secure = "; secure" if value[:secure]
|
|
219
|
+
httponly = "; HttpOnly" if value[:httponly]
|
|
220
|
+
value = value[:value]
|
|
221
|
+
end
|
|
222
|
+
value = [value] unless Array === value
|
|
223
|
+
cookie = Rack::Utils.escape(key) + "=" +
|
|
224
|
+
value.map { |v| Rack::Utils.escape v }.join("&") +
|
|
225
|
+
"#{domain}#{path}#{expires}#{secure}#{httponly}"
|
|
226
|
+
|
|
227
|
+
@cookie << cookie
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def delete_cookie(key, value={})
|
|
231
|
+
@cookie.reject! { |cookie|
|
|
232
|
+
cookie =~ /\A#{Rack::Utils.escape(key)}=/
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
set_cookie(key,
|
|
236
|
+
{:value => '', :path => nil, :domain => nil,
|
|
237
|
+
:expires => Time.at(0) }.merge(value))
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
private
|
|
241
|
+
def handle_conditional_get!
|
|
242
|
+
if etag? || last_modified? || !@cache_control.empty?
|
|
243
|
+
set_conditional_cache_control!
|
|
244
|
+
elsif nonempty_ok_response?
|
|
245
|
+
self.etag = @body
|
|
246
|
+
|
|
247
|
+
if request && request.etag_matches?(etag)
|
|
248
|
+
self.status = 304
|
|
249
|
+
self.body = []
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
set_conditional_cache_control!
|
|
253
|
+
else
|
|
254
|
+
headers["Cache-Control"] = "no-cache"
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def nonempty_ok_response?
|
|
259
|
+
@status == 200 && string_body?
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def string_body?
|
|
263
|
+
!@blank && @body.respond_to?(:all?) && @body.all? { |part| part.is_a?(String) }
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate"
|
|
267
|
+
|
|
268
|
+
def set_conditional_cache_control!
|
|
269
|
+
control = @cache_control
|
|
270
|
+
|
|
271
|
+
if control.empty?
|
|
272
|
+
headers["Cache-Control"] = DEFAULT_CACHE_CONTROL
|
|
273
|
+
elsif @cache_control[:no_cache]
|
|
274
|
+
headers["Cache-Control"] = "no-cache"
|
|
275
|
+
else
|
|
276
|
+
extras = control[:extras]
|
|
277
|
+
max_age = control[:max_age]
|
|
278
|
+
|
|
279
|
+
options = []
|
|
280
|
+
options << "max-age=#{max_age}" if max_age
|
|
281
|
+
options << (control[:public] ? "public" : "private")
|
|
282
|
+
options << "must-revalidate" if control[:must_revalidate]
|
|
283
|
+
options.concat(extras) if extras
|
|
284
|
+
|
|
285
|
+
headers["Cache-Control"] = options.join(", ")
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'active_support/inflector'
|
|
2
|
+
|
|
3
|
+
module ActionDispatch
|
|
4
|
+
module StatusCodes #:nodoc:
|
|
5
|
+
STATUS_CODES = Rack::Utils::HTTP_STATUS_CODES.merge({
|
|
6
|
+
102 => "Processing",
|
|
7
|
+
207 => "Multi-Status",
|
|
8
|
+
226 => "IM Used",
|
|
9
|
+
422 => "Unprocessable Entity",
|
|
10
|
+
423 => "Locked",
|
|
11
|
+
424 => "Failed Dependency",
|
|
12
|
+
426 => "Upgrade Required",
|
|
13
|
+
507 => "Insufficient Storage",
|
|
14
|
+
510 => "Not Extended"
|
|
15
|
+
}).freeze
|
|
16
|
+
|
|
17
|
+
# Provides a symbol-to-fixnum lookup for converting a symbol (like
|
|
18
|
+
# :created or :not_implemented) into its corresponding HTTP status
|
|
19
|
+
# code (like 200 or 501).
|
|
20
|
+
SYMBOL_TO_STATUS_CODE = STATUS_CODES.inject({}) { |hash, (code, message)|
|
|
21
|
+
hash[ActiveSupport::Inflector.underscore(message.gsub(/ /, "")).to_sym] = code
|
|
22
|
+
hash
|
|
23
|
+
}.freeze
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
# Given a status parameter, determine whether it needs to be converted
|
|
27
|
+
# to a string. If it is a fixnum, use the STATUS_CODES hash to lookup
|
|
28
|
+
# the default message. If it is a symbol, use the SYMBOL_TO_STATUS_CODE
|
|
29
|
+
# hash to convert it.
|
|
30
|
+
def interpret_status(status)
|
|
31
|
+
case status
|
|
32
|
+
when Fixnum then
|
|
33
|
+
"#{status} #{STATUS_CODES[status]}".strip
|
|
34
|
+
when Symbol then
|
|
35
|
+
interpret_status(SYMBOL_TO_STATUS_CODE[status] ||
|
|
36
|
+
"500 Unknown Status #{status.inspect}")
|
|
37
|
+
else
|
|
38
|
+
status.to_s
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module ActionDispatch
|
|
2
|
+
module Utils
|
|
3
|
+
# TODO: Pull this into rack core
|
|
4
|
+
# http://github.com/halorgium/rack/commit/feaf071c1de743fbd10bc316830180a9af607278
|
|
5
|
+
def parse_config(config)
|
|
6
|
+
if config =~ /\.ru$/
|
|
7
|
+
cfgfile = ::File.read(config)
|
|
8
|
+
if cfgfile[/^#\\(.*)/]
|
|
9
|
+
opts.parse! $1.split(/\s+/)
|
|
10
|
+
end
|
|
11
|
+
inner_app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app",
|
|
12
|
+
nil, config
|
|
13
|
+
else
|
|
14
|
+
require config
|
|
15
|
+
inner_app = Object.const_get(::File.basename(config, '.rb').capitalize)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
module_function :parse_config
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module ActionDispatch
|
|
2
|
+
class Callbacks
|
|
3
|
+
include ActiveSupport::Callbacks
|
|
4
|
+
|
|
5
|
+
define_callbacks :call, :terminator => "result == false", :rescuable => true
|
|
6
|
+
define_callbacks :prepare, :scope => :name
|
|
7
|
+
|
|
8
|
+
# Add a preparation callback. Preparation callbacks are run before every
|
|
9
|
+
# request in development mode, and before the first request in production mode.
|
|
10
|
+
#
|
|
11
|
+
# If a symbol with a block is given, the symbol is used as an identifier.
|
|
12
|
+
# That allows to_prepare to be called again with the same identifier to
|
|
13
|
+
# replace the existing callback. Passing an identifier is a suggested
|
|
14
|
+
# practice if the code adding a preparation block may be reloaded.
|
|
15
|
+
def self.to_prepare(*args, &block)
|
|
16
|
+
if args.first.is_a?(Symbol) && block_given?
|
|
17
|
+
define_method :"__#{args.first}", &block
|
|
18
|
+
set_callback(:prepare, :"__#{args.first}")
|
|
19
|
+
else
|
|
20
|
+
set_callback(:prepare, *args, &block)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.before(*args, &block)
|
|
25
|
+
set_callback(:call, :before, *args, &block)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.after(*args, &block)
|
|
29
|
+
set_callback(:call, :after, *args, &block)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class << self
|
|
33
|
+
# DEPRECATED
|
|
34
|
+
alias_method :before_dispatch, :before
|
|
35
|
+
alias_method :after_dispatch, :after
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def initialize(app, prepare_each_request = false)
|
|
39
|
+
@app, @prepare_each_request = app, prepare_each_request
|
|
40
|
+
run_callbacks(:prepare)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def call(env)
|
|
44
|
+
run_callbacks(:call) do
|
|
45
|
+
run_callbacks(:prepare) if @prepare_each_request
|
|
46
|
+
@app.call(env)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require 'active_support/json'
|
|
2
|
+
|
|
3
|
+
module ActionDispatch
|
|
4
|
+
class ParamsParser
|
|
5
|
+
DEFAULT_PARSERS = {
|
|
6
|
+
Mime::XML => :xml_simple,
|
|
7
|
+
Mime::JSON => :json
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
def initialize(app, parsers = {})
|
|
11
|
+
@app, @parsers = app, DEFAULT_PARSERS.merge(parsers)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def call(env)
|
|
15
|
+
if params = parse_formatted_parameters(env)
|
|
16
|
+
env["action_dispatch.request.request_parameters"] = params
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
@app.call(env)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
def parse_formatted_parameters(env)
|
|
24
|
+
request = Request.new(env)
|
|
25
|
+
|
|
26
|
+
return false if request.content_length.zero?
|
|
27
|
+
|
|
28
|
+
mime_type = content_type_from_legacy_post_data_format_header(env) || request.content_type
|
|
29
|
+
strategy = @parsers[mime_type]
|
|
30
|
+
|
|
31
|
+
return false unless strategy
|
|
32
|
+
|
|
33
|
+
case strategy
|
|
34
|
+
when Proc
|
|
35
|
+
strategy.call(request.raw_post)
|
|
36
|
+
when :xml_simple, :xml_node
|
|
37
|
+
request.body.size == 0 ? {} : Hash.from_xml(request.body).with_indifferent_access
|
|
38
|
+
when :yaml
|
|
39
|
+
YAML.load(request.body)
|
|
40
|
+
when :json
|
|
41
|
+
if request.body.size == 0
|
|
42
|
+
{}
|
|
43
|
+
else
|
|
44
|
+
data = ActiveSupport::JSON.decode(request.body)
|
|
45
|
+
data = {:_json => data} unless data.is_a?(Hash)
|
|
46
|
+
data.with_indifferent_access
|
|
47
|
+
end
|
|
48
|
+
else
|
|
49
|
+
false
|
|
50
|
+
end
|
|
51
|
+
rescue Exception => e # YAML, XML or Ruby code block errors
|
|
52
|
+
logger.debug "Error occurred while parsing request parameters.\nContents:\n\n#{request.raw_post}"
|
|
53
|
+
|
|
54
|
+
raise
|
|
55
|
+
{ "body" => request.raw_post,
|
|
56
|
+
"content_type" => request.content_type,
|
|
57
|
+
"content_length" => request.content_length,
|
|
58
|
+
"exception" => "#{e.message} (#{e.class})",
|
|
59
|
+
"backtrace" => e.backtrace }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def content_type_from_legacy_post_data_format_header(env)
|
|
63
|
+
if x_post_format = env['HTTP_X_POST_DATA_FORMAT']
|
|
64
|
+
case x_post_format.to_s.downcase
|
|
65
|
+
when 'yaml'
|
|
66
|
+
return Mime::YAML
|
|
67
|
+
when 'xml'
|
|
68
|
+
return Mime::XML
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
nil
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def logger
|
|
76
|
+
defined?(Rails.logger) ? Rails.logger : Logger.new($stderr)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|