diff options
Diffstat (limited to 'actionpack/lib/action_controller/metal')
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 |