From f302079d97b5c139b56f1acd2d516be52351c4fe Mon Sep 17 00:00:00 2001 From: Zachary Scott Date: Sun, 23 Feb 2014 20:19:15 +1100 Subject: :scissors: This commit also addresses rails/docrails#169 and rails/rails#14159 --- actionpack/lib/action_dispatch/middleware/cookies.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index 18e64704f6..8b05cd6e11 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -74,7 +74,7 @@ module ActionDispatch # # domain: nil # Does not sets cookie domain. (default) # domain: :all # Allow the cookie for the top most level - # domain and subdomains. + # # domain and subdomains. # # * :expires - The time at which this cookie expires, as a \Time object. # * :secure - Whether this cookie is only transmitted to HTTPS servers. -- cgit v1.2.3 From 9af4258186027e5a80bd5a0c821862378e1492ad Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 28 Feb 2014 11:57:15 -0800 Subject: set the error callback to a nice default in case nobody set an error callback and an error happens --- actionpack/lib/action_controller/metal/live.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb index fdf4ef293d..5ef4f6ccda 100644 --- a/actionpack/lib/action_controller/metal/live.rb +++ b/actionpack/lib/action_controller/metal/live.rb @@ -108,7 +108,7 @@ module ActionController class Buffer < ActionDispatch::Response::Buffer #:nodoc: def initialize(response) - @error_callback = nil + @error_callback = lambda { true } super(response, SizedQueue.new(10)) end -- cgit v1.2.3 From 30d21dfcb7fafe49b3805b8249454485a90097b6 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 28 Feb 2014 15:22:35 -0800 Subject: live controllers should have live responses detect the type of controller we're testing and return the right type of response based on that controller. This allows us to stop doing the weird sleep thing. --- actionpack/lib/action_controller/metal/live.rb | 16 +++++++++++++-- actionpack/lib/action_controller/test_case.rb | 28 ++++++++++++++++++++------ 2 files changed, 36 insertions(+), 8 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb index 5ef4f6ccda..fba17746c0 100644 --- a/actionpack/lib/action_controller/metal/live.rb +++ b/actionpack/lib/action_controller/metal/live.rb @@ -107,8 +107,11 @@ module ActionController end class Buffer < ActionDispatch::Response::Buffer #:nodoc: + include MonitorMixin + def initialize(response) @error_callback = lambda { true } + @cv = new_cond super(response, SizedQueue.new(10)) end @@ -128,8 +131,17 @@ module ActionController end def close - super - @buf.push nil + synchronize do + super + @buf.push nil + @cv.broadcast + end + end + + def await_close + synchronize do + @cv.wait_until { @closed } + end end def on_error(&block) diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 8650b75400..33a5858766 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -258,6 +258,17 @@ module ActionController end end + class LiveTestResponse < Live::Response + def recycle! + @body = nil + initialize + end + + def body + @body ||= super + end + end + # Methods #destroy and #load! are overridden to avoid calling methods on the # @store object, which does not exist for the TestSession class. class TestSession < Rack::Session::Abstract::SessionHash #:nodoc: @@ -583,13 +594,14 @@ module ActionController end def setup_controller_request_and_response - @request = build_request - @response = build_response - @response.request = @request - @controller = nil unless defined? @controller + response_klass = TestResponse + if klass = self.class.controller_class + if klass < ActionController::Live + response_klass = LiveTestResponse + end unless @controller begin @controller = klass.new @@ -599,6 +611,10 @@ module ActionController end end + @request = build_request + @response = build_response response_klass + @response.request = @request + if @controller @controller.request = @request @controller.params = {} @@ -609,8 +625,8 @@ module ActionController TestRequest.new end - def build_response - TestResponse.new + def build_response(klass) + klass.new end included do -- cgit v1.2.3 From a7b059ec7f25c16beeacf2c545d2be593ed0388b Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 28 Feb 2014 15:39:08 -0800 Subject: use built-in exception handling in live controllers when an exception happens in an action before the response has been committed, then we should re-raise the exception in the main thread. This lets us reuse the existing exception handling. --- actionpack/lib/action_controller/metal/live.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb index fba17746c0..d60f1b0d44 100644 --- a/actionpack/lib/action_controller/metal/live.rb +++ b/actionpack/lib/action_controller/metal/live.rb @@ -203,6 +203,7 @@ module ActionController t1 = Thread.current locals = t1.keys.map { |key| [key, t1[key]] } + error = nil # This processes the action in a child thread. It lets us return the # response code and headers back up the rack stack, and still process # the body in parallel with sending data to the client @@ -217,8 +218,9 @@ module ActionController begin super(name) rescue => e - @_response.status = 500 unless @_response.committed? - @_response.status = 400 if e.class == ActionController::BadRequest + unless @_response.committed? + error = e + end begin @_response.stream.write(ActionView::Base.streaming_completion_on_exception) if request.format == :html @_response.stream.call_on_error @@ -234,6 +236,7 @@ module ActionController } @_response.await_commit + raise error if error end def log_error(exception) -- cgit v1.2.3 From b11ebf1d80e4fb124f0ce0448cea30988256da59 Mon Sep 17 00:00:00 2001 From: Erik Michaels-Ober Date: Fri, 28 Feb 2014 22:41:49 -0800 Subject: Replace map.flatten(1) with flat_map --- actionpack/lib/action_dispatch/journey/formatter.rb | 4 ++-- actionpack/lib/action_dispatch/journey/gtg/transition_table.rb | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/journey/formatter.rb b/actionpack/lib/action_dispatch/journey/formatter.rb index 4410c1b5d5..57f0963731 100644 --- a/actionpack/lib/action_dispatch/journey/formatter.rb +++ b/actionpack/lib/action_dispatch/journey/formatter.rb @@ -121,9 +121,9 @@ module ActionDispatch def possibles(cache, options, depth = 0) cache.fetch(:___routes) { [] } + options.find_all { |pair| cache.key?(pair) - }.map { |pair| + }.flat_map { |pair| possibles(cache[pair], options, depth + 1) - }.flatten(1) + } end # Returns +true+ if no missing keys are present, otherwise +false+. diff --git a/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb b/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb index 5a79059ed6..a5b19fcf06 100644 --- a/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb +++ b/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb @@ -120,11 +120,11 @@ module ActionDispatch end def transitions - @string_states.map { |from, hash| + @string_states.flat_map { |from, hash| hash.map { |s, to| [from, s, to] } - }.flatten(1) + @regexp_states.map { |from, hash| + } + @regexp_states.flat_map { |from, hash| hash.map { |s, to| [from, s, to] } - }.flatten(1) + } end private -- cgit v1.2.3 From 38594b35275a431ccf2fdc10be7219685aeed487 Mon Sep 17 00:00:00 2001 From: Shuhei Kagawa Date: Mon, 3 Mar 2014 22:39:15 +0900 Subject: Add spaces to deep_munge log message. --- actionpack/lib/action_controller/log_subscriber.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/log_subscriber.rb b/actionpack/lib/action_controller/log_subscriber.rb index e920a33765..b1acca2435 100644 --- a/actionpack/lib/action_controller/log_subscriber.rb +++ b/actionpack/lib/action_controller/log_subscriber.rb @@ -54,9 +54,9 @@ module ActionController end def deep_munge(event) - message = "Value for params[:#{event.payload[:keys].join('][:')}] was set"\ - "to nil, because it was one of [], [null] or [null, null, ...]."\ - "Go to http://guides.rubyonrails.org/security.html#unsafe-query-generation"\ + message = "Value for params[:#{event.payload[:keys].join('][:')}] was set "\ + "to nil, because it was one of [], [null] or [null, null, ...]. "\ + "Go to http://guides.rubyonrails.org/security.html#unsafe-query-generation "\ "for more information."\ debug(message) -- cgit v1.2.3 From 817fe31196dd59ee31f71ef1740122b6759cf16d Mon Sep 17 00:00:00 2001 From: Erik Michaels-Ober Date: Mon, 3 Mar 2014 19:23:12 -0800 Subject: Replace map.flatten with flat_map in actionpack --- actionpack/lib/action_dispatch/journey/gtg/builder.rb | 6 +++--- actionpack/lib/action_dispatch/journey/gtg/simulator.rb | 2 +- actionpack/lib/action_dispatch/journey/gtg/transition_table.rb | 8 ++++---- actionpack/lib/action_dispatch/journey/nfa/dot.rb | 4 ++-- actionpack/lib/action_dispatch/journey/nfa/simulator.rb | 2 +- actionpack/lib/action_dispatch/journey/nfa/transition_table.rb | 10 +++++----- actionpack/lib/action_dispatch/journey/path/pattern.rb | 4 ++-- 7 files changed, 18 insertions(+), 18 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/journey/gtg/builder.rb b/actionpack/lib/action_dispatch/journey/gtg/builder.rb index 7d2791714b..450588cda6 100644 --- a/actionpack/lib/action_dispatch/journey/gtg/builder.rb +++ b/actionpack/lib/action_dispatch/journey/gtg/builder.rb @@ -27,7 +27,7 @@ module ActionDispatch marked[s] = true # mark s s.group_by { |state| symbol(state) }.each do |sym, ps| - u = ps.map { |l| followpos(l) }.flatten + u = ps.flat_map { |l| followpos(l) } next if u.empty? if u.uniq == [DUMMY] @@ -90,7 +90,7 @@ module ActionDispatch firstpos(node.left) end when Nodes::Or - node.children.map { |c| firstpos(c) }.flatten.uniq + node.children.flat_map { |c| firstpos(c) }.uniq when Nodes::Unary firstpos(node.left) when Nodes::Terminal @@ -105,7 +105,7 @@ module ActionDispatch when Nodes::Star firstpos(node.left) when Nodes::Or - node.children.map { |c| lastpos(c) }.flatten.uniq + node.children.flat_map { |c| lastpos(c) }.uniq when Nodes::Cat if nullable?(node.right) lastpos(node.left) | lastpos(node.right) diff --git a/actionpack/lib/action_dispatch/journey/gtg/simulator.rb b/actionpack/lib/action_dispatch/journey/gtg/simulator.rb index 58ad803841..254c2befc4 100644 --- a/actionpack/lib/action_dispatch/journey/gtg/simulator.rb +++ b/actionpack/lib/action_dispatch/journey/gtg/simulator.rb @@ -31,7 +31,7 @@ module ActionDispatch return if acceptance_states.empty? - memos = acceptance_states.map { |x| tt.memo(x) }.flatten.compact + memos = acceptance_states.flat_map { |x| tt.memo(x) }.compact MatchData.new(memos) end diff --git a/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb b/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb index a5b19fcf06..e6212b1ee2 100644 --- a/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb +++ b/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb @@ -114,8 +114,8 @@ module ActionDispatch end def states - ss = @string_states.keys + @string_states.values.map(&:values).flatten - rs = @regexp_states.keys + @regexp_states.values.map(&:values).flatten + ss = @string_states.keys + @string_states.values.flat_map(&:values) + rs = @regexp_states.keys + @regexp_states.values.flat_map(&:values) (ss + rs).uniq end @@ -143,11 +143,11 @@ module ActionDispatch def move_regexp(t, a) return [] if t.empty? - t.map { |s| + t.flat_map { |s| if states = @regexp_states[s] states.map { |re, v| re === a ? v : nil } end - }.flatten.compact.uniq + }.compact.uniq end def move_string(t, a) diff --git a/actionpack/lib/action_dispatch/journey/nfa/dot.rb b/actionpack/lib/action_dispatch/journey/nfa/dot.rb index 5c33a872e5..47bf76bdbf 100644 --- a/actionpack/lib/action_dispatch/journey/nfa/dot.rb +++ b/actionpack/lib/action_dispatch/journey/nfa/dot.rb @@ -16,9 +16,9 @@ module ActionDispatch # end # " #{n.object_id} [label=\"#{label}\", shape=box];" #} - #memo_edges = memos.map { |k, memos| + #memo_edges = memos.flat_map { |k, memos| # (memos || []).map { |v| " #{k} -> #{v.object_id};" } - #}.flatten.uniq + #}.uniq <<-eodot digraph nfa { diff --git a/actionpack/lib/action_dispatch/journey/nfa/simulator.rb b/actionpack/lib/action_dispatch/journey/nfa/simulator.rb index 5b40da6569..b23270db3c 100644 --- a/actionpack/lib/action_dispatch/journey/nfa/simulator.rb +++ b/actionpack/lib/action_dispatch/journey/nfa/simulator.rb @@ -34,7 +34,7 @@ module ActionDispatch return if acceptance_states.empty? - memos = acceptance_states.map { |x| tt.memo(x) }.flatten.compact + memos = acceptance_states.flat_map { |x| tt.memo(x) }.compact MatchData.new(memos) end diff --git a/actionpack/lib/action_dispatch/journey/nfa/transition_table.rb b/actionpack/lib/action_dispatch/journey/nfa/transition_table.rb index a3017aeea1..66e414213a 100644 --- a/actionpack/lib/action_dispatch/journey/nfa/transition_table.rb +++ b/actionpack/lib/action_dispatch/journey/nfa/transition_table.rb @@ -42,7 +42,7 @@ module ActionDispatch end def states - (@table.keys + @table.values.map(&:keys).flatten).uniq + (@table.keys + @table.values.flat_map(&:keys)).uniq end # Returns a generalized transition graph with reduced states. The states @@ -93,7 +93,7 @@ module ActionDispatch # Returns set of NFA states to which there is a transition on ast symbol # +a+ from some state +s+ in +t+. def following_states(t, a) - Array(t).map { |s| inverted[s][a] }.flatten.uniq + Array(t).flat_map { |s| inverted[s][a] }.uniq end # Returns set of NFA states to which there is a transition on ast symbol @@ -107,7 +107,7 @@ module ActionDispatch end def alphabet - inverted.values.map(&:keys).flatten.compact.uniq.sort_by { |x| x.to_s } + inverted.values.flat_map(&:keys).compact.uniq.sort_by { |x| x.to_s } end # Returns a set of NFA states reachable from some NFA state +s+ in set @@ -131,9 +131,9 @@ module ActionDispatch end def transitions - @table.map { |to, hash| + @table.flat_map { |to, hash| hash.map { |from, sym| [from, sym, to] } - }.flatten(1) + } end private diff --git a/actionpack/lib/action_dispatch/journey/path/pattern.rb b/actionpack/lib/action_dispatch/journey/path/pattern.rb index d37aa1fbe5..fb155e516f 100644 --- a/actionpack/lib/action_dispatch/journey/path/pattern.rb +++ b/actionpack/lib/action_dispatch/journey/path/pattern.rb @@ -53,9 +53,9 @@ module ActionDispatch end def optional_names - @optional_names ||= spec.grep(Nodes::Group).map { |group| + @optional_names ||= spec.grep(Nodes::Group).flat_map { |group| group.grep(Nodes::Symbol) - }.flatten.map { |n| n.name }.uniq + }.map { |n| n.name }.uniq end class RegexpOffsets < Journey::Visitors::Visitor # :nodoc: -- cgit v1.2.3 From 67584c6ae37c88f8abba6f4fbdeedc7c1a6dfa1b Mon Sep 17 00:00:00 2001 From: "John Barton (joho)" Date: Wed, 5 Mar 2014 11:24:51 +1100 Subject: Make CSRF failure logging optional/configurable. Added the log_warning_on_csrf_failure option to ActionController::RequestForgeryProtection which is on by default. --- .../lib/action_controller/metal/request_forgery_protection.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index c88074d4c6..e3b1f5ae7c 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -68,6 +68,10 @@ module ActionController #:nodoc: config_accessor :allow_forgery_protection self.allow_forgery_protection = true if allow_forgery_protection.nil? + # Controls whether a CSRF failure logs a warning. On by default. + config_accessor :log_warning_on_csrf_failure + self.log_warning_on_csrf_failure = true + helper_method :form_authenticity_token helper_method :protect_against_forgery? end @@ -193,7 +197,9 @@ module ActionController #:nodoc: mark_for_same_origin_verification! if !verified_request? - logger.warn "Can't verify CSRF token authenticity" if logger + if logger && log_warning_on_csrf_failure + logger.warn "Can't verify CSRF token authenticity" + end handle_unverified_request end end -- cgit v1.2.3 From ed88a601f7b37de0f89b64249aaeed884faed836 Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Fri, 28 Feb 2014 19:39:22 -0500 Subject: Do note remove `Content-Type` when `render :body` `render :body` should just not set the `Content-Type` header. By removing the header, it breaks the compatibility with other parts. After this commit, `render :body` will returns `text/html` content type, sets by default from `ActionDispatch::Response`, and it will preserve the overridden content type if you override it. Fixes #14197, #14238 This partially reverts commit 3047376870d4a7adc7ff15c3cb4852e073c8f1da. --- actionpack/lib/action_controller/metal/rack_delegation.rb | 4 ++-- actionpack/lib/action_controller/metal/rendering.rb | 4 +--- actionpack/lib/action_dispatch/http/response.rb | 13 +------------ 3 files changed, 4 insertions(+), 17 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/metal/rack_delegation.rb b/actionpack/lib/action_controller/metal/rack_delegation.rb index e1bee9e60c..bdf6e88699 100644 --- a/actionpack/lib/action_controller/metal/rack_delegation.rb +++ b/actionpack/lib/action_controller/metal/rack_delegation.rb @@ -5,8 +5,8 @@ module ActionController module RackDelegation extend ActiveSupport::Concern - delegate :headers, :status=, :location=, :content_type=, :no_content_type=, - :status, :location, :content_type, :no_content_type, :to => "@_response" + delegate :headers, :status=, :location=, :content_type=, + :status, :location, :content_type, :to => "@_response" def dispatch(action, request) set_response!(request) diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb index 3c4ef596c7..93e7d6954c 100644 --- a/actionpack/lib/action_controller/metal/rendering.rb +++ b/actionpack/lib/action_controller/metal/rendering.rb @@ -45,9 +45,7 @@ module ActionController def _process_format(format, options = {}) super - if options[:body] - self.headers.delete "Content-Type" - elsif options[:plain] + if options[:plain] self.content_type = Mime::TEXT else self.content_type ||= format.to_s diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index f14ca1ea44..2c6bcf7b7b 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -63,8 +63,6 @@ module ActionDispatch # :nodoc: # content you're giving them, so we need to send that along. attr_accessor :charset - attr_accessor :no_content_type # :nodoc: - CONTENT_TYPE = "Content-Type".freeze SET_COOKIE = "Set-Cookie".freeze LOCATION = "Location".freeze @@ -305,17 +303,8 @@ module ActionDispatch # :nodoc: !@sending_file && @charset != false end - def remove_content_type! - headers.delete CONTENT_TYPE - end - def rack_response(status, header) - if no_content_type - remove_content_type! - else - assign_default_content_type_and_charset!(header) - end - + assign_default_content_type_and_charset!(header) handle_conditional_get! header[SET_COOKIE] = header[SET_COOKIE].join("\n") if header[SET_COOKIE].respond_to?(:join) -- cgit v1.2.3 From 2dd2fcf89673afbcf95240ecebaf34826a195164 Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Tue, 18 Feb 2014 16:13:23 -0500 Subject: Introduce `Rails.gem_version` This method return `Gem::Version.new(Rails.version)`, suggesting a more reliable way to perform version comparison. Example: Rails.version #=> "4.1.2" Rails.gem_version #=> # Rails.version > "4.1.10" #=> false Rails.gem_version > Gem::Version.new("4.1.10") #=> true Gem::Requirement.new("~> 4.1.2") =~ Rails.gem_version #=> true This was originally introduced as `.version` by @charliesome in #8501 but got reverted in #10002 since it was not backward compatible. Also, updating template for `rake update_versions`. --- actionpack/lib/action_pack/gem_version.rb | 15 +++++++++++++++ actionpack/lib/action_pack/version.rb | 11 ++++------- 2 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 actionpack/lib/action_pack/gem_version.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_pack/gem_version.rb b/actionpack/lib/action_pack/gem_version.rb new file mode 100644 index 0000000000..beaf35d3da --- /dev/null +++ b/actionpack/lib/action_pack/gem_version.rb @@ -0,0 +1,15 @@ +module ActionPack + # Returns the version of the currently loaded ActionPack as a Gem::Version + def self.gem_version + Gem::Version.new VERSION::STRING + end + + module VERSION + MAJOR = 4 + MINOR = 2 + TINY = 0 + PRE = "alpha" + + STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") + end +end diff --git a/actionpack/lib/action_pack/version.rb b/actionpack/lib/action_pack/version.rb index 75fb0d9532..7088cd2760 100644 --- a/actionpack/lib/action_pack/version.rb +++ b/actionpack/lib/action_pack/version.rb @@ -1,11 +1,8 @@ +require_relative 'gem_version' + module ActionPack - # Returns the version of the currently loaded ActionPack as a Gem::Version + # Returns the version of the currently loaded ActionPack as a Gem::Version def self.version - Gem::Version.new "4.2.0.alpha" - end - - module VERSION #:nodoc: - MAJOR, MINOR, TINY, PRE = ActionPack.version.segments - STRING = ActionPack.version.to_s + gem_version end end -- cgit v1.2.3 From ed0fb4ae7ea28cf3eecce6ec02650bcffc7c7657 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Sun, 2 Mar 2014 14:02:25 +0200 Subject: Move setting :scope_level_resource to resource_scope Originally with_scope_level was exclusively for managing scope levels with resources, however it is now used for other things so it makes more sense to move the responsibility for setting the :scope_level_resource to the resource_scope method. This eliminates repeatedly setting it to the same resource as each resource method scope is evaluated. --- actionpack/lib/action_dispatch/routing/mapper.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 0b762aa9a4..5da6582b15 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1558,21 +1558,21 @@ module ActionDispatch end end - def with_scope_level(kind, resource = parent_resource) + def with_scope_level(kind) old, @scope[:scope_level] = @scope[:scope_level], kind - old_resource, @scope[:scope_level_resource] = @scope[:scope_level_resource], resource yield ensure @scope[:scope_level] = old - @scope[:scope_level_resource] = old_resource end def resource_scope(kind, resource) #:nodoc: - with_scope_level(kind, resource) do - scope(parent_resource.resource_scope) do - yield - end + old_resource, @scope[:scope_level_resource] = @scope[:scope_level_resource], resource + + with_scope_level(kind) do + scope(parent_resource.resource_scope) { yield } end + ensure + @scope[:scope_level_resource] = old_resource end def nested_options #:nodoc: -- cgit v1.2.3 From dcc91a04a177466516dac12abc358c590743fa71 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Sun, 2 Mar 2014 20:19:04 +0200 Subject: Only use shallow nested scope when depth is > 1 By tracking the depth of resource nesting we can push the need for nested shallow scoping to only those routes that are nested more than one deep. This allows us to keep the fix for #12498 and fix the regression in #14224. Fixes #14224. --- actionpack/lib/action_dispatch/routing/mapper.rb | 43 +++++++++++++----------- 1 file changed, 23 insertions(+), 20 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 5da6582b15..314b966bb0 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1323,8 +1323,10 @@ module ActionDispatch end with_scope_level(:member) do - scope(parent_resource.member_scope) do - yield + if shallow? + shallow_scope(parent_resource.member_scope) { yield } + else + scope(parent_resource.member_scope) { yield } end end end @@ -1347,16 +1349,8 @@ module ActionDispatch end with_scope_level(:nested) do - if shallow? - with_exclusive_scope do - if @scope[:shallow_path].blank? - scope(parent_resource.nested_scope, nested_options) { yield } - else - scope(@scope[:shallow_path], :as => @scope[:shallow_prefix]) do - scope(parent_resource.nested_scope, nested_options) { yield } - end - end - end + if shallow? && nesting_depth > 1 + shallow_scope(parent_resource.nested_scope, nested_options) { yield } else scope(parent_resource.nested_scope, nested_options) { yield } end @@ -1567,11 +1561,13 @@ module ActionDispatch def resource_scope(kind, resource) #:nodoc: old_resource, @scope[:scope_level_resource] = @scope[:scope_level_resource], resource + @nesting.push(resource) with_scope_level(kind) do scope(parent_resource.resource_scope) { yield } end ensure + @nesting.pop @scope[:scope_level_resource] = old_resource end @@ -1584,6 +1580,10 @@ module ActionDispatch options end + def nesting_depth #:nodoc: + @nesting.size + end + def param_constraint? #:nodoc: @scope[:constraints] && @scope[:constraints][parent_resource.param].is_a?(Regexp) end @@ -1596,18 +1596,20 @@ module ActionDispatch flag && resource_method_scope? && CANONICAL_ACTIONS.include?(action.to_s) end - def shallow_scoping? #:nodoc: - shallow? && @scope[:scope_level] == :member + def shallow_scope(path, options = {}) #:nodoc: + old_name_prefix, old_path = @scope[:as], @scope[:path] + @scope[:as], @scope[:path] = @scope[:shallow_prefix], @scope[:shallow_path] + + scope(path, options) { yield } + ensure + @scope[:as], @scope[:path] = old_name_prefix, old_path end def path_for_action(action, path) #:nodoc: - prefix = shallow_scoping? ? - "#{@scope[:shallow_path]}/#{parent_resource.shallow_scope}" : @scope[:path] - if canonical_action?(action, path.blank?) - prefix.to_s + @scope[:path].to_s else - "#{prefix}/#{action_path(action, path)}" + "#{@scope[:path]}/#{action_path(action, path)}" end end @@ -1645,7 +1647,7 @@ module ActionDispatch when :new [prefix, :new, name_prefix, member_name] when :member - [prefix, shallow_scoping? ? @scope[:shallow_prefix] : name_prefix, member_name] + [prefix, name_prefix, member_name] when :root [name_prefix, collection_name, prefix] else @@ -1786,6 +1788,7 @@ module ActionDispatch @set = set @scope = { :path_names => @set.resources_path_names } @concerns = {} + @nesting = [] end include Base -- cgit v1.2.3 From 8711086f5a2e73cd068434a5fafef258ba9f4fe1 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Mon, 3 Mar 2014 20:19:17 +0200 Subject: Pull namespace defaults out of the options hash If a developer has specified either :path or :as in the options hash then these should be used as the defaults for :shallow_path and :shallow_prefix. Fixes #14241. --- actionpack/lib/action_dispatch/routing/mapper.rb | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 314b966bb0..1ad419ec80 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -792,9 +792,16 @@ module ActionDispatch # end def namespace(path, options = {}) path = path.to_s - options = { :path => path, :as => path, :module => path, - :shallow_path => path, :shallow_prefix => path }.merge!(options) - scope(options) { yield } + + defaults = { + module: path, + path: options.fetch(:path, path), + as: options.fetch(:as, path), + shallow_path: options.fetch(:path, path), + shallow_prefix: options.fetch(:as, path) + } + + scope(defaults.merge!(options)) { yield } end # === Parameter Restriction -- cgit v1.2.3 From af4c9b78ff1c967cc1aaef14d34205ef92db8134 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Sat, 8 Mar 2014 19:49:11 +0000 Subject: Copy shallow options from normal options when using scope If the options :shallow_prefix and :shallow_path are not set in the scope options then copy them from the normal :as and :path options if they are set. --- actionpack/lib/action_dispatch/routing/mapper.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 1ad419ec80..357829e59f 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -708,7 +708,8 @@ module ActionDispatch options[:constraints] ||= {} unless shallow? - options[:shallow_path] = options[:path] if args.any? + options[:shallow_path] ||= options[:path] if options.key?(:path) + options[:shallow_prefix] ||= options[:as] if options.key?(:as) end if options[:constraints].is_a?(Hash) -- cgit v1.2.3 From 0d191baa823414a900ef7362359cb6fc87be1d38 Mon Sep 17 00:00:00 2001 From: Lauro Caetano Date: Wed, 5 Mar 2014 19:12:02 -0300 Subject: [ci skip] Add documentation for original_fullpath. --- actionpack/lib/action_dispatch/http/request.rb | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 1318c62fbe..daa06e96e6 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -152,6 +152,13 @@ module ActionDispatch Http::Headers.new(@env) end + # Returns a +String+ with the last requested path including their params. + # + # # get '/foo' + # request.original_fullpath # => '/foo' + # + # # get '/foo?bar' + # request.original_fullpath # => '/foo?bar' def original_fullpath @original_fullpath ||= (env["ORIGINAL_FULLPATH"] || fullpath) end -- cgit v1.2.3 From 77a09218f697676f8a05f06eeb5c89a26419d489 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 12 Mar 2014 16:07:04 -0700 Subject: only write the jar if the response isn't committed when streaming responses, we need to make sure the cookie jar is written to the headers before returning up the stack. This commit introduces a new method on the response object that writes the cookie jar to the headers as the response is committed. The middleware and test framework will not write the cookie headers if the response has already been committed. fixes #14352 --- actionpack/lib/action_controller/metal/live.rb | 12 ++++++++---- actionpack/lib/action_controller/test_case.rb | 16 +++++++++++++++- actionpack/lib/action_dispatch/http/response.rb | 4 ++++ .../lib/action_dispatch/middleware/cookies.rb | 21 ++++++++++++++++----- 4 files changed, 43 insertions(+), 10 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb index d60f1b0d44..43cf9b9723 100644 --- a/actionpack/lib/action_controller/metal/live.rb +++ b/actionpack/lib/action_controller/metal/live.rb @@ -177,13 +177,17 @@ module ActionController end end - def commit! - headers.freeze + private + + def finalize_response super + jar = request.cookie_jar + # The response can be committed multiple times + jar.write self unless jar.committed? + jar.commit! + headers.freeze end - private - def build_buffer(response, body) buf = Live::Buffer.new response body.each { |part| buf.write part } diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 33a5858766..009f83861d 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -267,6 +267,18 @@ module ActionController def body @body ||= super end + + # Was the response successful? + alias_method :success?, :successful? + + # Was the URL not found? + alias_method :missing?, :not_found? + + # Were we redirected? + alias_method :redirect?, :redirection? + + # Was there a server-side error? + alias_method :error?, :server_error? end # Methods #destroy and #load! are overridden to avoid calling methods on the @@ -583,7 +595,9 @@ module ActionController @controller.process(name) if cookies = @request.env['action_dispatch.cookies'] - cookies.write(@response) + unless cookies.committed? + cookies.write(@response) + end end @response.prepare! diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 2c6bcf7b7b..b5454f519f 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -140,6 +140,7 @@ module ActionDispatch # :nodoc: def commit! synchronize do + finalize_response @committed = true @cv.broadcast end @@ -273,6 +274,9 @@ module ActionDispatch # :nodoc: private + def finalize_response + end + def merge_default_headers(original, default) return original unless default.respond_to?(:merge) diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index 8b05cd6e11..c0039fa3f5 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -237,6 +237,15 @@ module ActionDispatch @secure = secure @options = options @cookies = {} + @committed = false + end + + def committed?; @committed; end + + def commit! + @committed = true + @set_cookies.freeze + @delete_cookies.freeze end def each(&block) @@ -336,8 +345,8 @@ module ActionDispatch end def recycle! #:nodoc: - @set_cookies.clear - @delete_cookies.clear + @set_cookies = {} + @delete_cookies = {} end mattr_accessor :always_write_cookie @@ -551,9 +560,11 @@ module ActionDispatch status, headers, body = @app.call(env) if cookie_jar = env['action_dispatch.cookies'] - cookie_jar.write(headers) - if headers[HTTP_HEADER].respond_to?(:join) - headers[HTTP_HEADER] = headers[HTTP_HEADER].join("\n") + unless cookie_jar.committed? + cookie_jar.write(headers) + if headers[HTTP_HEADER].respond_to?(:join) + headers[HTTP_HEADER] = headers[HTTP_HEADER].join("\n") + end end end -- cgit v1.2.3 From c0a783610f5cf77050a55ad70b2cd2cf657bffe3 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 12 Mar 2014 16:21:01 -0700 Subject: just ask the response for the commit status, we do not need to ask the jar --- actionpack/lib/action_controller/metal/live.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb index 43cf9b9723..fe63cf2b98 100644 --- a/actionpack/lib/action_controller/metal/live.rb +++ b/actionpack/lib/action_controller/metal/live.rb @@ -183,7 +183,7 @@ module ActionController super jar = request.cookie_jar # The response can be committed multiple times - jar.write self unless jar.committed? + jar.write self unless committed? jar.commit! headers.freeze end -- cgit v1.2.3 From 3df07d093a1e4207caa63fd2e3b67599211f5800 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 12 Mar 2014 17:40:08 -0700 Subject: use the body proxy to freeze headers avoid freezing the headers until the web server has actually read data from the body proxy. Once the webserver has read data, then we should throw an error if someone tries to set a header --- actionpack/lib/action_controller/metal/live.rb | 10 +++++-- actionpack/lib/action_controller/test_case.rb | 2 +- actionpack/lib/action_dispatch/http/response.rb | 37 +++++++++++++++++++++---- 3 files changed, 41 insertions(+), 8 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb index fe63cf2b98..41b997a755 100644 --- a/actionpack/lib/action_controller/metal/live.rb +++ b/actionpack/lib/action_controller/metal/live.rb @@ -125,9 +125,11 @@ module ActionController end def each + @response.sending! while str = @buf.pop yield str end + @response.sent! end def close @@ -179,12 +181,16 @@ module ActionController private - def finalize_response + def before_committed super jar = request.cookie_jar # The response can be committed multiple times jar.write self unless committed? - jar.commit! + end + + def before_sending + super + request.cookie_jar.commit! headers.freeze end diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 009f83861d..e9166d8747 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -595,7 +595,7 @@ module ActionController @controller.process(name) if cookies = @request.env['action_dispatch.cookies'] - unless cookies.committed? + unless @response.committed? cookies.write(@response) end end diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index b5454f519f..3d27ff2b24 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -91,7 +91,10 @@ module ActionDispatch # :nodoc: end def each(&block) - @buf.each(&block) + @response.sending! + x = @buf.each(&block) + @response.sent! + x end def close @@ -118,6 +121,8 @@ module ActionDispatch # :nodoc: @blank = false @cv = new_cond @committed = false + @sending = false + @sent = false @content_type = nil @charset = nil @@ -138,18 +143,37 @@ module ActionDispatch # :nodoc: end end + def await_sent + synchronize { @cv.wait_until { @sent } } + end + def commit! synchronize do - finalize_response + before_committed @committed = true @cv.broadcast end end - def committed? - @committed + def sending! + synchronize do + before_sending + @sending = true + @cv.broadcast + end end + def sent! + synchronize do + @sent = true + @cv.broadcast + end + end + + def sending?; synchronize { @sending }; end + def committed?; synchronize { @committed }; end + def sent?; synchronize { @sent }; end + # Sets the HTTP status code. def status=(status) @status = Rack::Utils.status_code(status) @@ -274,7 +298,10 @@ module ActionDispatch # :nodoc: private - def finalize_response + def before_committed + end + + def before_sending end def merge_default_headers(original, default) -- cgit v1.2.3