aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller/metal
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_controller/metal')
-rw-r--r--actionpack/lib/action_controller/metal/compatibility.rb98
-rw-r--r--actionpack/lib/action_controller/metal/configuration.rb28
-rw-r--r--actionpack/lib/action_controller/metal/head.rb1
-rw-r--r--actionpack/lib/action_controller/metal/helpers.rb4
-rw-r--r--actionpack/lib/action_controller/metal/hide_actions.rb10
-rw-r--r--actionpack/lib/action_controller/metal/http_authentication.rb50
-rw-r--r--actionpack/lib/action_controller/metal/implicit_render.rb21
-rw-r--r--actionpack/lib/action_controller/metal/instrumentation.rb2
-rw-r--r--actionpack/lib/action_controller/metal/rack_delegation.rb5
-rw-r--r--actionpack/lib/action_controller/metal/redirecting.rb1
-rw-r--r--actionpack/lib/action_controller/metal/renderers.rb2
-rw-r--r--actionpack/lib/action_controller/metal/rendering.rb68
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb45
-rw-r--r--actionpack/lib/action_controller/metal/session_management.rb36
-rw-r--r--actionpack/lib/action_controller/metal/streaming.rb67
-rw-r--r--actionpack/lib/action_controller/metal/testing.rb1
-rw-r--r--actionpack/lib/action_controller/metal/url_for.rb167
17 files changed, 166 insertions, 440 deletions
diff --git a/actionpack/lib/action_controller/metal/compatibility.rb b/actionpack/lib/action_controller/metal/compatibility.rb
index a1cfa32d4d..ab8d87b2c4 100644
--- a/actionpack/lib/action_controller/metal/compatibility.rb
+++ b/actionpack/lib/action_controller/metal/compatibility.rb
@@ -2,26 +2,23 @@ module ActionController
module Compatibility
extend ActiveSupport::Concern
- include AbstractController::Compatibility
-
class ::ActionController::ActionControllerError < StandardError #:nodoc:
end
+ module ClassMethods
+ end
+
# Temporary hax
included do
::ActionController::UnknownAction = ::AbstractController::ActionNotFound
::ActionController::DoubleRenderError = ::AbstractController::DoubleRenderError
- cattr_accessor :session_options
- self.session_options = {}
-
- cattr_accessor :relative_url_root
- self.relative_url_root = ENV['RAILS_RELATIVE_URL_ROOT']
+ # ROUTES TODO: This should be handled by a middleware and route generation
+ # should be able to handle SCRIPT_NAME
+ self.config.relative_url_root = ENV['RAILS_RELATIVE_URL_ROOT']
class << self
delegate :default_charset=, :to => "ActionDispatch::Response"
- delegate :resources_path_names, :to => "ActionController::Routing::Routes"
- delegate :resources_path_names=, :to => "ActionController::Routing::Routes"
end
# cattr_reader :protected_instance_variables
@@ -32,31 +29,17 @@ module ActionController
@before_filter_chain_aborted @_headers @_params
@_response)
- # Controls the resource action separator
- cattr_accessor :resource_action_separator
- self.resource_action_separator = "/"
-
- cattr_accessor :use_accept_header
- self.use_accept_header = true
+ def rescue_action(env)
+ raise env["action_dispatch.rescue.exception"]
+ end
self.page_cache_directory = defined?(Rails.public_path) ? Rails.public_path : ""
-
- # Prepends all the URL-generating helpers from AssetHelper. This makes it possible to easily move javascripts, stylesheets,
- # and images to a dedicated asset server away from the main web server. Example:
- # ActionController::Base.asset_host = "http://assets.example.com"
- cattr_accessor :asset_host
-
- cattr_accessor :ip_spoofing_check
- self.ip_spoofing_check = true
-
- cattr_accessor :trusted_proxies
end
# For old tests
def initialize_template_class(*) end
def assign_shortcuts(*) end
- # TODO: Remove this after we flip
def template
@template ||= view_context
end
@@ -66,52 +49,20 @@ module ActionController
super
end
- module ClassMethods
- def consider_all_requests_local
- ActiveSupport::Deprecation.warn "ActionController::Base.consider_all_requests_local is deprecated, " <<
- "use Rails.application.config.consider_all_requests_local instead"
- Rails.application.config.consider_all_requests_local
- end
-
- def consider_all_requests_local=(value)
- ActiveSupport::Deprecation.warn "ActionController::Base.consider_all_requests_local= is no longer effective. " <<
- "Please configure it on your application with config.consider_all_requests_local="
- Rails.application.config.consider_all_requests_local = value
- end
-
- def allow_concurrency
- ActiveSupport::Deprecation.warn "ActionController::Base.allow_concurrency is deprecated, " <<
- "use Rails.application.config.allow_concurrency instead"
- Rails.application.config.allow_concurrency
- end
-
- def allow_concurrency=(value)
- ActiveSupport::Deprecation.warn "ActionController::Base.allow_concurrency= is no longer effective. " <<
- "Please configure it on your application with config.allow_concurrency="
- Rails.application.config.allow_concurrency = value
- end
-
- def rescue_action(env)
- raise env["action_dispatch.rescue.exception"]
- end
-
- # Defines the storage option for cached fragments
- def cache_store=(store_option)
- @@cache_store = ActiveSupport::Cache.lookup_store(store_option)
- end
- end
-
- delegate :consider_all_requests_local, :consider_all_requests_local=,
- :allow_concurrency, :allow_concurrency=, :to => :"self.class"
-
- def render_to_body(options)
- if options.is_a?(Hash) && options.key?(:template)
- options[:template].sub!(/^\//, '')
+ def _normalize_options(options)
+ if options[:action] && options[:action].to_s.include?(?/)
+ ActiveSupport::Deprecation.warn "Giving a path to render :action is deprecated. " <<
+ "Please use render :template instead", caller
+ options[:template] = options.delete(:action)
end
options[:text] = nil if options.delete(:nothing) == true
options[:text] = " " if options.key?(:text) && options[:text].nil?
+ super
+ end
+ def render_to_body(options)
+ options[:template].sub!(/^\//, '') if options.key?(:template)
super || " "
end
@@ -126,18 +77,5 @@ module ActionController
def performed?
response_body
end
-
- # ==== Request only view path switching ====
- def append_view_path(path)
- view_paths.push(*path)
- end
-
- def prepend_view_path(path)
- view_paths.unshift(*path)
- end
-
- def view_paths
- view_context.view_paths
- end
end
end
diff --git a/actionpack/lib/action_controller/metal/configuration.rb b/actionpack/lib/action_controller/metal/configuration.rb
deleted file mode 100644
index 5c829853b7..0000000000
--- a/actionpack/lib/action_controller/metal/configuration.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-module ActionController
- module Configuration
- extend ActiveSupport::Concern
-
- def config
- @config ||= self.class.config
- end
-
- def config=(config)
- @config = config
- end
-
- module ClassMethods
- def default_config
- @default_config ||= {}
- end
-
- def config
- self.config ||= default_config
- end
-
- def config=(config)
- @config = ActiveSupport::OrderedHash.new
- @config.merge!(config)
- end
- end
- end
-end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/metal/head.rb b/actionpack/lib/action_controller/metal/head.rb
index 37be8b3999..a5c9910d68 100644
--- a/actionpack/lib/action_controller/metal/head.rb
+++ b/actionpack/lib/action_controller/metal/head.rb
@@ -1,6 +1,7 @@
module ActionController
module Head
extend ActiveSupport::Concern
+
include ActionController::UrlFor
# Return a response that has no content (merely headers). The options
diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb
index 1b5a4c3080..8efe01e37b 100644
--- a/actionpack/lib/action_controller/metal/helpers.rb
+++ b/actionpack/lib/action_controller/metal/helpers.rb
@@ -86,7 +86,7 @@ module ActionController
end
private
- # Overwrite _modules_for_helpers to accept :all as argument, which loads
+ # Overwrite modules_for_helpers to accept :all as argument, which loads
# all helpers in helpers_dir.
#
# ==== Parameters
@@ -95,7 +95,7 @@ module ActionController
# ==== Returns
# Array[Module]:: A normalized list of modules for the list of
# helpers provided.
- def _modules_for_helpers(args)
+ def modules_for_helpers(args)
args += all_application_helpers if args.delete(:all)
super(args)
end
diff --git a/actionpack/lib/action_controller/metal/hide_actions.rb b/actionpack/lib/action_controller/metal/hide_actions.rb
index e893acffdf..3358d80c35 100644
--- a/actionpack/lib/action_controller/metal/hide_actions.rb
+++ b/actionpack/lib/action_controller/metal/hide_actions.rb
@@ -15,10 +15,8 @@ module ActionController
# Overrides AbstractController::Base#action_method? to return false if the
# action name is in the list of hidden actions.
- def action_method?(action_name)
- self.class.visible_action?(action_name) do
- !self.class.hidden_actions.include?(action_name) && super
- end
+ def method_for_action(action_name)
+ self.class.visible_action?(action_name) && super
end
module ClassMethods
@@ -31,13 +29,13 @@ module ActionController
end
def inherited(klass)
- klass.instance_variable_set("@visible_actions", {})
+ klass.class_eval { @visible_actions = {} }
super
end
def visible_action?(action_name)
return @visible_actions[action_name] if @visible_actions.key?(action_name)
- @visible_actions[action_name] = yield
+ @visible_actions[action_name] = !hidden_actions.include?(action_name)
end
# Overrides AbstractController::Base#action_methods to remove any methods
diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index 0f35a7c040..6ec788f302 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -124,7 +124,7 @@ module ActionController
end
def authenticate(request, &login_procedure)
- unless authorization(request).blank?
+ unless request.authorization.blank?
login_procedure.call(*user_name_and_password(request))
end
end
@@ -133,15 +133,8 @@ module ActionController
decode_credentials(request).split(/:/, 2)
end
- def authorization(request)
- request.env['HTTP_AUTHORIZATION'] ||
- request.env['X-HTTP_AUTHORIZATION'] ||
- request.env['X_HTTP_AUTHORIZATION'] ||
- request.env['REDIRECT_X_HTTP_AUTHORIZATION']
- end
-
def decode_credentials(request)
- ActiveSupport::Base64.decode64(authorization(request).split(' ', 2).last || '')
+ ActiveSupport::Base64.decode64(request.authorization.split(' ', 2).last || '')
end
def encode_credentials(user_name, password)
@@ -165,7 +158,7 @@ module ActionController
# Authenticate with HTTP Digest, returns true or false
def authenticate_with_http_digest(realm = "Application", &password_procedure)
- HttpAuthentication::Digest.authenticate(request, realm, &password_procedure)
+ HttpAuthentication::Digest.authenticate(config.secret, request, realm, &password_procedure)
end
# Render output including the HTTP Digest authentication header
@@ -175,30 +168,23 @@ module ActionController
end
# Returns false on a valid response, true otherwise
- def authenticate(request, realm, &password_procedure)
- authorization(request) && validate_digest_response(request, realm, &password_procedure)
- end
-
- def authorization(request)
- request.env['HTTP_AUTHORIZATION'] ||
- request.env['X-HTTP_AUTHORIZATION'] ||
- request.env['X_HTTP_AUTHORIZATION'] ||
- request.env['REDIRECT_X_HTTP_AUTHORIZATION']
+ def authenticate(secret_key, request, realm, &password_procedure)
+ request.authorization && validate_digest_response(secret_key, request, realm, &password_procedure)
end
# Returns false unless the request credentials response value matches the expected value.
# First try the password as a ha1 digest password. If this fails, then try it as a plain
# text password.
- def validate_digest_response(request, realm, &password_procedure)
+ def validate_digest_response(secret_key, request, realm, &password_procedure)
credentials = decode_credentials_header(request)
- valid_nonce = validate_nonce(request, credentials[:nonce])
+ valid_nonce = validate_nonce(secret_key, request, credentials[:nonce])
- if valid_nonce && realm == credentials[:realm] && opaque == credentials[:opaque]
+ if valid_nonce && realm == credentials[:realm] && opaque(secret_key) == credentials[:opaque]
password = password_procedure.call(credentials[:username])
return false unless password
method = request.env['rack.methodoverride.original_method'] || request.env['REQUEST_METHOD']
- uri = credentials[:uri][0,1] == '/' ? request.request_uri : request.url
+ uri = credentials[:uri][0,1] == '/' ? request.fullpath : request.url
[true, false].any? do |password_is_ha1|
expected = expected_response(method, uri, credentials, password, password_is_ha1)
@@ -226,7 +212,7 @@ module ActionController
end
def decode_credentials_header(request)
- decode_credentials(authorization(request))
+ decode_credentials(request.authorization)
end
def decode_credentials(header)
@@ -238,6 +224,9 @@ module ActionController
end
def authentication_header(controller, realm)
+ secret_key = controller.config.secret
+ nonce = self.nonce(secret_key)
+ opaque = opaque(secret_key)
controller.headers["WWW-Authenticate"] = %(Digest realm="#{realm}", qop="auth", algorithm=MD5, nonce="#{nonce}", opaque="#{opaque}")
end
@@ -280,7 +269,7 @@ module ActionController
# The nonce is opaque to the client. Composed of Time, and hash of Time with secret
# key from the Rails session secret generated upon creation of project. Ensures
# the time cannot be modified by client.
- def nonce(time = Time.now)
+ def nonce(secret_key, time = Time.now)
t = time.to_i
hashed = [t, secret_key]
digest = ::Digest::MD5.hexdigest(hashed.join(":"))
@@ -292,21 +281,16 @@ module ActionController
# Can be much shorter if the Stale directive is implemented. This would
# allow a user to use new nonce without prompting user again for their
# username and password.
- def validate_nonce(request, value, seconds_to_timeout=5*60)
+ def validate_nonce(secret_key, request, value, seconds_to_timeout=5*60)
t = ActiveSupport::Base64.decode64(value).split(":").first.to_i
- nonce(t) == value && (t - Time.now.to_i).abs <= seconds_to_timeout
+ nonce(secret_key, t) == value && (t - Time.now.to_i).abs <= seconds_to_timeout
end
# Opaque based on random generation - but changing each request?
- def opaque()
+ def opaque(secret_key)
::Digest::MD5.hexdigest(secret_key)
end
- # Set in /initializers/session_store.rb, and loaded even if sessions are not in use.
- def secret_key
- ActionController::Base.session_options[:secret]
- end
-
end
end
end
diff --git a/actionpack/lib/action_controller/metal/implicit_render.rb b/actionpack/lib/action_controller/metal/implicit_render.rb
new file mode 100644
index 0000000000..282dcf66b3
--- /dev/null
+++ b/actionpack/lib/action_controller/metal/implicit_render.rb
@@ -0,0 +1,21 @@
+module ActionController
+ module ImplicitRender
+ def send_action(*)
+ ret = super
+ default_render unless response_body
+ ret
+ end
+
+ def default_render
+ render
+ end
+
+ def method_for_action(action_name)
+ super || begin
+ if template_exists?(action_name.to_s, _prefix)
+ "default_render"
+ end
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/metal/instrumentation.rb b/actionpack/lib/action_controller/metal/instrumentation.rb
index 85035dc09c..d69de65f28 100644
--- a/actionpack/lib/action_controller/metal/instrumentation.rb
+++ b/actionpack/lib/action_controller/metal/instrumentation.rb
@@ -20,7 +20,7 @@ module ActionController
:params => request.filtered_parameters,
:formats => request.formats.map(&:to_sym),
:method => request.method,
- :path => (request.request_uri rescue "unknown")
+ :path => (request.fullpath rescue "unknown")
}
ActiveSupport::Notifications.instrument("action_controller.start_processing", raw_payload.dup)
diff --git a/actionpack/lib/action_controller/metal/rack_delegation.rb b/actionpack/lib/action_controller/metal/rack_delegation.rb
index bb55383631..37106733cb 100644
--- a/actionpack/lib/action_controller/metal/rack_delegation.rb
+++ b/actionpack/lib/action_controller/metal/rack_delegation.rb
@@ -6,14 +6,11 @@ module ActionController
extend ActiveSupport::Concern
included do
- delegate :session, :to => "@_request"
delegate :headers, :status=, :location=, :content_type=,
:status, :location, :content_type, :to => "@_response"
- attr_internal :request
end
- def dispatch(action, env)
- @_request = ActionDispatch::Request.new(env)
+ def dispatch(action, request)
@_response = ActionDispatch::Response.new
@_response.request = request
super
diff --git a/actionpack/lib/action_controller/metal/redirecting.rb b/actionpack/lib/action_controller/metal/redirecting.rb
index faf0589fd2..25e4e18493 100644
--- a/actionpack/lib/action_controller/metal/redirecting.rb
+++ b/actionpack/lib/action_controller/metal/redirecting.rb
@@ -11,6 +11,7 @@ module ActionController
extend ActiveSupport::Concern
include AbstractController::Logger
+ include ActionController::RackDelegation
include ActionController::UrlFor
# Redirects the browser to the target specified in +options+. This parameter can take one of three forms:
diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb
index 639b508746..49d3d6b466 100644
--- a/actionpack/lib/action_controller/metal/renderers.rb
+++ b/actionpack/lib/action_controller/metal/renderers.rb
@@ -19,7 +19,7 @@ module ActionController
<<-RUBY_EVAL
if options.key?(:#{name})
_process_options(options)
- return _render_option_#{name}(options[:#{name}], options)
+ return _render_option_#{name}(options.delete(:#{name}), options)
end
RUBY_EVAL
end
diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb
index 0aae9f8579..f892bd9b91 100644
--- a/actionpack/lib/action_controller/metal/rendering.rb
+++ b/actionpack/lib/action_controller/metal/rendering.rb
@@ -2,68 +2,54 @@ module ActionController
module Rendering
extend ActiveSupport::Concern
- included do
- include AbstractController::Rendering
- include AbstractController::LocalizedCache
- end
+ include ActionController::RackDelegation
+ include AbstractController::Rendering
- def process_action(*)
- self.formats = request.formats.map {|x| x.to_sym}
+ def process(*)
+ self.formats = request.formats.map { |x| x.to_sym }
super
end
def render(*args)
- if response_body
- raise ::AbstractController::DoubleRenderError
- end
-
- args << {} unless args.last.is_a?(Hash)
- super(*args)
- self.content_type ||= args.last[:_template].mime_type.to_s
- response_body
- end
-
- def render_to_body(options)
- _process_options(options)
+ raise ::AbstractController::DoubleRenderError if response_body
super
+ response_body
end
private
- def _render_partial(options)
- options[:partial] = action_name if options[:partial] == true
- options[:_details] = {:formats => formats}
- super
+ def _normalize_args(action=nil, options={}, &blk)
+ options = super
+ options[:update] = blk if block_given?
+ options
end
- def format_for_text
- formats.first
+ def _normalize_options(options)
+ if options.key?(:text) && options[:text].respond_to?(:to_text)
+ options[:text] = options[:text].to_text
+ end
+
+ if options[:status]
+ options[:status] = Rack::Utils.status_code(options[:status])
+ end
+
+ super
end
def _process_options(options)
status, content_type, location = options.values_at(:status, :content_type, :location)
+
self.status = status if status
self.content_type = content_type if content_type
self.headers["Location"] = url_for(location) if location
- end
- def _normalize_options(action=nil, options={}, &blk)
- case action
- when NilClass
- when Hash
- options = super(action.delete(:action), action)
- when String, Symbol
- options = super
- else
- options.merge! :partial => action
- end
-
- if options[:status]
- options[:status] = Rack::Utils.status_code(options[:status])
- end
+ super
+ end
- options[:update] = blk if block_given?
- options
+ def _with_template_hook(template)
+ super
+ self.content_type ||= template.mime_type.to_s
end
+
end
end
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index 276c703307..39a809657b 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -12,11 +12,10 @@ module ActionController #:nodoc:
included do
# Sets the token parameter name for RequestForgery. Calling +protect_from_forgery+
# sets it to <tt>:authenticity_token</tt> by default.
- cattr_accessor :request_forgery_protection_token
+ config.request_forgery_protection_token ||= :authenticity_token
# Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode.
- class_attribute :allow_forgery_protection
- self.allow_forgery_protection = true
+ config.allow_forgery_protection ||= true
helper_method :form_authenticity_token
helper_method :protect_against_forgery?
@@ -80,9 +79,47 @@ module ActionController #:nodoc:
self.request_forgery_protection_token ||= :authenticity_token
before_filter :verify_authenticity_token, options
end
+
+ def request_forgery_protection_token
+ config.request_forgery_protection_token
+ end
+
+ def request_forgery_protection_token=(val)
+ config.request_forgery_protection_token = val
+ end
+
+ def allow_forgery_protection
+ config.allow_forgery_protection
+ end
+
+ def allow_forgery_protection=(val)
+ config.allow_forgery_protection = val
+ end
end
protected
+
+ def protect_from_forgery(options = {})
+ self.request_forgery_protection_token ||= :authenticity_token
+ before_filter :verify_authenticity_token, options
+ end
+
+ def request_forgery_protection_token
+ config.request_forgery_protection_token
+ end
+
+ def request_forgery_protection_token=(val)
+ config.request_forgery_protection_token = val
+ end
+
+ def allow_forgery_protection
+ config.allow_forgery_protection
+ end
+
+ def allow_forgery_protection=(val)
+ config.allow_forgery_protection = val
+ end
+
# The actual before_filter that is used. Modify this to change how you handle unverified requests.
def verify_authenticity_token
verified_request? || raise(ActionController::InvalidAuthenticityToken)
@@ -109,7 +146,7 @@ module ActionController #:nodoc:
end
def protect_against_forgery?
- self.class.allow_forgery_protection
+ config.allow_forgery_protection
end
end
end
diff --git a/actionpack/lib/action_controller/metal/session_management.rb b/actionpack/lib/action_controller/metal/session_management.rb
index d70f40ce7a..91d89ff9a4 100644
--- a/actionpack/lib/action_controller/metal/session_management.rb
+++ b/actionpack/lib/action_controller/metal/session_management.rb
@@ -2,44 +2,8 @@ module ActionController #:nodoc:
module SessionManagement #:nodoc:
extend ActiveSupport::Concern
- include ActionController::Configuration
-
module ClassMethods
- # Set the session store to be used for keeping the session data between requests.
- # By default, sessions are stored in browser cookies (<tt>:cookie_store</tt>),
- # but you can also specify one of the other included stores (<tt>:active_record_store</tt>,
- # <tt>:mem_cache_store</tt>, or your own custom class.
- def session_store=(store)
- if store == :active_record_store
- self.session_store = ActiveRecord::SessionStore
- else
- @@session_store = store.is_a?(Symbol) ?
- ActionDispatch::Session.const_get(store.to_s.camelize) :
- store
- end
- end
-
- # Returns the session store class currently used.
- def session_store
- if defined? @@session_store
- @@session_store
- else
- ActionDispatch::Session::CookieStore
- end
- end
-
- def session=(options = {})
- self.session_store = nil if options.delete(:disabled)
- session_options.merge!(options)
- end
- def session(*args)
- ActiveSupport::Deprecation.warn(
- "Disabling sessions for a single controller has been deprecated. " +
- "Sessions are now lazy loaded. So if you don't access them, " +
- "consider them off. You can still modify the session cookie " +
- "options with request.session_options.", caller)
- end
end
end
end
diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb
index 8f03b8bb17..753af3dc58 100644
--- a/actionpack/lib/action_controller/metal/streaming.rb
+++ b/actionpack/lib/action_controller/metal/streaming.rb
@@ -9,18 +9,13 @@ module ActionController #:nodoc:
DEFAULT_SEND_FILE_OPTIONS = {
:type => 'application/octet-stream'.freeze,
:disposition => 'attachment'.freeze,
- :stream => true,
- :buffer_size => 4096,
- :x_sendfile => false
}.freeze
- X_SENDFILE_HEADER = 'X-Sendfile'.freeze
-
protected
- # Sends the file, by default streaming it 4096 bytes at a time. This way the
- # whole file doesn't need to be read into memory at once. This makes it
- # feasible to send even large files. You can optionally turn off streaming
- # and send the whole file at once.
+ # Sends the file. This uses a server-appropriate method (such as X-Sendfile)
+ # via the Rack::Sendfile middleware. The header to use is set via
+ # config.action_dispatch.x_sendfile_header, and defaults to "X-Sendfile".
+ # Your server can also configure this for you by setting the X-Sendfile-Type header.
#
# Be careful to sanitize the path parameter if it is coming from a web
# page. <tt>send_file(params[:path])</tt> allows a malicious user to
@@ -31,24 +26,12 @@ module ActionController #:nodoc:
# Defaults to <tt>File.basename(path)</tt>.
# * <tt>:type</tt> - specifies an HTTP content type. Defaults to 'application/octet-stream'. You can specify
# either a string or a symbol for a registered type register with <tt>Mime::Type.register</tt>, for example :json
- # * <tt>:length</tt> - used to manually override the length (in bytes) of the content that
- # is going to be sent to the client. Defaults to <tt>File.size(path)</tt>.
# * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
# Valid values are 'inline' and 'attachment' (default).
- # * <tt>:stream</tt> - whether to send the file to the user agent as it is read (+true+)
- # or to read the entire file before sending (+false+). Defaults to +true+.
- # * <tt>:buffer_size</tt> - specifies size (in bytes) of the buffer used to stream the file.
- # Defaults to 4096.
# * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'.
# * <tt>:url_based_filename</tt> - set to +true+ if you want the browser guess the filename from
# the URL, which is necessary for i18n filenames on certain browsers
# (setting <tt>:filename</tt> overrides this option).
- # * <tt>:x_sendfile</tt> - uses X-Sendfile to send the file when set to +true+. This is currently
- # only available with Lighttpd/Apache2 and specific modules installed and activated. Since this
- # uses the web server to send the file, this may lower memory consumption on your server and
- # it will not block your application for further requests.
- # See http://blog.lighttpd.net/articles/2006/07/02/x-sendfile and
- # http://tn123.ath.cx/mod_xsendfile/ for details. Defaults to +false+.
#
# The default Content-Type and Content-Disposition headers are
# set to download arbitrary binary files in as many browsers as
@@ -81,29 +64,16 @@ module ActionController #:nodoc:
def send_file(path, options = {}) #:doc:
raise MissingFile, "Cannot read file #{path}" unless File.file?(path) and File.readable?(path)
- options[:length] ||= File.size(path)
options[:filename] ||= File.basename(path) unless options[:url_based_filename]
send_file_headers! options
- @performed_render = false
-
if options[:x_sendfile]
- head options[:status], X_SENDFILE_HEADER => path
- else
- if options[:stream]
- # TODO : Make render :text => proc {} work with the new base
- render :status => options[:status], :text => Proc.new { |response, output|
- len = options[:buffer_size] || 4096
- File.open(path, 'rb') do |file|
- while buf = file.read(len)
- output.write(buf)
- end
- end
- }
- else
- File.open(path, 'rb') { |file| render :status => options[:status], :text => file.read }
- end
+ ActiveSupport::Deprecation.warn(":x_sendfile is no longer needed in send_file", caller)
end
+
+ self.status = options[:status] || 200
+ self.content_type = options[:content_type] if options.key?(:content_type)
+ self.response_body = File.open(path, "rb")
end
# Sends the given binary data to the browser. This method is similar to
@@ -138,32 +108,35 @@ module ActionController #:nodoc:
# data to the browser, then use <tt>render :text => proc { ... }</tt>
# instead. See ActionController::Base#render for more information.
def send_data(data, options = {}) #:doc:
- send_file_headers! options.merge(:length => data.bytesize)
- render :status => options[:status], :text => data
+ send_file_headers! options.dup
+ render options.slice(:status, :content_type).merge(:text => data)
end
private
def send_file_headers!(options)
options.update(DEFAULT_SEND_FILE_OPTIONS.merge(options))
- [:length, :type, :disposition].each do |arg|
+ [:type, :disposition].each do |arg|
raise ArgumentError, ":#{arg} option required" if options[arg].nil?
end
- disposition = options[:disposition].dup || 'attachment'
+ if options.key?(:length)
+ ActiveSupport::Deprecation.warn("You do not need to provide the file's length", caller)
+ end
- disposition <<= %(; filename="#{options[:filename]}") if options[:filename]
+ disposition = options[:disposition]
+ disposition += %(; filename="#{options[:filename]}") if options[:filename]
content_type = options[:type]
if content_type.is_a?(Symbol)
- raise ArgumentError, "Unknown MIME type #{options[:type]}" unless Mime::EXTENSION_LOOKUP.key?(content_type.to_s)
- self.content_type = Mime::Type.lookup_by_extension(content_type.to_s)
+ extension = Mime[content_type]
+ raise ArgumentError, "Unknown MIME type #{options[:type]}" unless extension
+ self.content_type = extension
else
self.content_type = content_type
end
headers.merge!(
- 'Content-Length' => options[:length].to_s,
'Content-Disposition' => disposition,
'Content-Transfer-Encoding' => 'binary'
)
diff --git a/actionpack/lib/action_controller/metal/testing.rb b/actionpack/lib/action_controller/metal/testing.rb
index 707ad968f4..4b8c452d50 100644
--- a/actionpack/lib/action_controller/metal/testing.rb
+++ b/actionpack/lib/action_controller/metal/testing.rb
@@ -13,7 +13,6 @@ module ActionController
if cookies = @_request.env['action_dispatch.cookies']
cookies.write(@_response)
end
- @_response.body ||= self.response_body
@_response.prepare!
set_test_assigns
ret
diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb
index 4f3ad07be5..10c7ca9021 100644
--- a/actionpack/lib/action_controller/metal/url_for.rb
+++ b/actionpack/lib/action_controller/metal/url_for.rb
@@ -1,165 +1,20 @@
-require 'active_support/core_ext/class/attribute'
-require 'active_support/core_ext/module/attribute_accessors'
-
module ActionController
- # In <b>routes.rb</b> one defines URL-to-controller mappings, but the reverse
- # is also possible: an URL can be generated from one of your routing definitions.
- # URL generation functionality is centralized in this module.
- #
- # See ActionController::Routing and ActionController::Resources for general
- # information about routing and routes.rb.
- #
- # <b>Tip:</b> If you need to generate URLs from your models or some other place,
- # then ActionController::UrlFor is what you're looking for. Read on for
- # an introduction.
- #
- # == URL generation from parameters
- #
- # As you may know, some functions - such as ActionController::Base#url_for
- # and ActionView::Helpers::UrlHelper#link_to, can generate URLs given a set
- # of parameters. For example, you've probably had the chance to write code
- # like this in one of your views:
- #
- # <%= link_to('Click here', :controller => 'users',
- # :action => 'new', :message => 'Welcome!') %>
- #
- # #=> Generates a link to: /users/new?message=Welcome%21
- #
- # link_to, and all other functions that require URL generation functionality,
- # actually use ActionController::UrlFor under the hood. And in particular,
- # they use the ActionController::UrlFor#url_for method. One can generate
- # the same path as the above example by using the following code:
- #
- # include UrlFor
- # url_for(:controller => 'users',
- # :action => 'new',
- # :message => 'Welcome!',
- # :only_path => true)
- # # => "/users/new?message=Welcome%21"
- #
- # Notice the <tt>:only_path => true</tt> part. This is because UrlFor has no
- # information about the website hostname that your Rails app is serving. So if you
- # want to include the hostname as well, then you must also pass the <tt>:host</tt>
- # argument:
- #
- # include UrlFor
- # url_for(:controller => 'users',
- # :action => 'new',
- # :message => 'Welcome!',
- # :host => 'www.example.com') # Changed this.
- # # => "http://www.example.com/users/new?message=Welcome%21"
- #
- # By default, all controllers and views have access to a special version of url_for,
- # that already knows what the current hostname is. So if you use url_for in your
- # controllers or your views, then you don't need to explicitly pass the <tt>:host</tt>
- # argument.
- #
- # For convenience reasons, mailers provide a shortcut for ActionController::UrlFor#url_for.
- # So within mailers, you only have to type 'url_for' instead of 'ActionController::UrlFor#url_for'
- # in full. However, mailers don't have hostname information, and what's why you'll still
- # have to specify the <tt>:host</tt> argument when generating URLs in mailers.
- #
- #
- # == URL generation for named routes
- #
- # UrlFor also allows one to access methods that have been auto-generated from
- # named routes. For example, suppose that you have a 'users' resource in your
- # <b>routes.rb</b>:
- #
- # map.resources :users
- #
- # This generates, among other things, the method <tt>users_path</tt>. By default,
- # this method is accessible from your controllers, views and mailers. If you need
- # to access this auto-generated method from other places (such as a model), then
- # you can do that by including ActionController::UrlFor in your class:
- #
- # class User < ActiveRecord::Base
- # include ActionController::UrlFor
- #
- # def base_uri
- # user_path(self)
- # end
- # end
- #
- # User.find(1).base_uri # => "/users/1"
- #
module UrlFor
extend ActiveSupport::Concern
- included do
- ActionController::Routing::Routes.install_helpers(self)
-
- # Including in a class uses an inheritable hash. Modules get a plain hash.
- if respond_to?(:class_attribute)
- class_attribute :default_url_options
- else
- mattr_accessor :default_url_options
- end
+ include ActionDispatch::Routing::UrlFor
- self.default_url_options = {}
+ def url_options
+ super.reverse_merge(
+ :host => request.host_with_port,
+ :protocol => request.protocol,
+ :_path_segments => request.symbolized_path_parameters
+ ).merge(:script_name => request.script_name)
end
- # Overwrite to implement a number of default options that all url_for-based methods will use. The default options should come in
- # the form of a hash, just like the one you would use for url_for directly. Example:
- #
- # def default_url_options(options)
- # { :project => @project.active? ? @project.url_name : "unknown" }
- # end
- #
- # As you can infer from the example, this is mostly useful for situations where you want to centralize dynamic decisions about the
- # urls as they stem from the business domain. Please note that any individual url_for call can always override the defaults set
- # by this method.
- def default_url_options(options = nil)
- self.class.default_url_options
- end
-
- def rewrite_options(options) #:nodoc:
- if options.delete(:use_defaults) != false && (defaults = default_url_options(options))
- defaults.merge(options)
- else
- options
- end
- end
-
- # Generate a url based on the options provided, default_url_options and the
- # routes defined in routes.rb. The following options are supported:
- #
- # * <tt>:only_path</tt> - If true, the relative url is returned. Defaults to +false+.
- # * <tt>:protocol</tt> - The protocol to connect to. Defaults to 'http'.
- # * <tt>:host</tt> - Specifies the host the link should be targeted at.
- # If <tt>:only_path</tt> is false, this option must be
- # provided either explicitly, or via +default_url_options+.
- # * <tt>:port</tt> - Optionally specify the port to connect to.
- # * <tt>:anchor</tt> - An anchor name to be appended to the path.
- # * <tt>:skip_relative_url_root</tt> - If true, the url is not constructed using the
- # +relative_url_root+ set in ActionController::Base.relative_url_root.
- # * <tt>:trailing_slash</tt> - If true, adds a trailing slash, as in "/archive/2009/"
- #
- # Any other key (<tt>:controller</tt>, <tt>:action</tt>, etc.) given to
- # +url_for+ is forwarded to the Routes module.
- #
- # Examples:
- #
- # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :port=>'8080' # => 'http://somehost.org:8080/tasks/testing'
- # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :anchor => 'ok', :only_path => true # => '/tasks/testing#ok'
- # url_for :controller => 'tasks', :action => 'testing', :trailing_slash=>true # => 'http://somehost.org/tasks/testing/'
- # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :number => '33' # => 'http://somehost.org/tasks/testing?number=33'
- def url_for(options = {})
- options ||= {}
- case options
- when String
- options
- when Hash
- _url_rewriter.rewrite(rewrite_options(options))
- else
- polymorphic_url(options)
- end
- end
-
- protected
-
- def _url_rewriter
- ActionController::UrlRewriter
+ def _router
+ raise "In order to use #url_for, you must include the helpers of a particular " \
+ "router. For instance, `include Rails.application.routes.url_helpers"
end
end
-end
+end \ No newline at end of file