aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/CHANGELOG.md813
-rw-r--r--actionpack/actionpack.gemspec2
-rw-r--r--actionpack/lib/abstract_controller/rendering.rb4
-rw-r--r--actionpack/lib/action_controller/base.rb9
-rw-r--r--actionpack/lib/action_controller/metal/helpers.rb9
-rw-r--r--actionpack/lib/action_controller/metal/live.rb16
-rw-r--r--actionpack/lib/action_controller/metal/renderers.rb2
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb3
-rw-r--r--actionpack/lib/action_controller/metal/rescue.rb17
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb6
-rw-r--r--actionpack/lib/action_controller/renderer.rb4
-rw-r--r--actionpack/lib/action_controller/test_case.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/mime_negotiation.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb33
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb24
-rw-r--r--actionpack/lib/action_dispatch/middleware/debug_exceptions.rb20
-rw-r--r--actionpack/lib/action_dispatch/middleware/flash.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/static.rb8
-rw-r--r--actionpack/lib/action_dispatch/request/session.rb6
-rw-r--r--actionpack/lib/action_dispatch/routing.rb13
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb7
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/url_for.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/assertion_response.rb16
-rw-r--r--actionpack/lib/action_dispatch/testing/test_request.rb22
-rw-r--r--actionpack/lib/action_pack/gem_version.rb4
-rw-r--r--actionpack/test/assertions/response_assertions_test.rb2
-rw-r--r--actionpack/test/controller/flash_hash_test.rb4
-rw-r--r--actionpack/test/controller/helper_test.rb16
-rw-r--r--actionpack/test/controller/live_stream_test.rb3
-rw-r--r--actionpack/test/controller/redirect_test.rb3
-rw-r--r--actionpack/test/controller/request_forgery_protection_test.rb13
-rw-r--r--actionpack/test/controller/rescue_test.rb31
-rw-r--r--actionpack/test/controller/routing_test.rb2
-rw-r--r--actionpack/test/controller/test_case_test.rb4
-rw-r--r--actionpack/test/dispatch/debug_exceptions_test.rb89
-rw-r--r--actionpack/test/dispatch/live_response_test.rb2
-rw-r--r--actionpack/test/dispatch/request/session_test.rb26
-rw-r--r--actionpack/test/dispatch/request_test.rb31
-rw-r--r--actionpack/test/dispatch/response_test.rb33
-rw-r--r--actionpack/test/dispatch/test_request_test.rb27
41 files changed, 344 insertions, 990 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 5c856f1b36..be911b147c 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,813 +1,2 @@
-* Routing: Refactor `:action` default handling to ensure that path
- parameters are not mutated during route generation.
- *Andrew White*
-
-* Add extension synonyms `yml` and `yaml` for MIME type `application/x-yaml`.
-
- *bogdanvlviv*
-
-* Adds support for including ActionController::Cookies in API controllers.
- Previously, including the module would raise when trying to define
- a `cookies` helper method. Skip calling #helper_method if it is not
- defined -- if we don't have helpers, we needn't define one.
-
- Fixes #24304
-
- *Ryan T. Hosford*
-
-* ETags: Introduce `Response#strong_etag=` and `#weak_etag=` and analogous
- options for `fresh_when` and `stale?`. `Response#etag=` sets a weak ETag.
-
- Strong ETags are desirable when you're serving byte-for-byte identical
- responses that support Range requests, like PDFs or videos (typically
- done by reproxying the response from a backend storage service).
- Also desirable when fronted by some CDNs that support strong ETags
- only, like Akamai.
-
- *Jeremy Daer*
-
-* ETags: No longer strips quotes (") from ETag values before comparing them.
- Quotes are significant, part of the ETag. A quoted ETag and an unquoted
- one are not the same entity.
-
- *Jeremy Daer*
-
-* ETags: Support `If-None-Match: *`. Rarely useful for GET requests; meant
- to provide some optimistic concurrency control for PUT requests.
-
- *Jeremy Daer*
-
-* `ActionDispatch::ParamsParser` is deprecated and was removed from the middleware
- stack. To configure the parameter parsers use `ActionDispatch::Request.parameter_parsers=`.
-
- *tenderlove*
-
-* When a `respond_to` collector with a block doesn't have a response, then
- a `:no_content` response should be rendered. This brings the default
- rendering behavior introduced by https://github.com/rails/rails/issues/19036
- to controller methods employing `respond_to`.
-
- *Justin Coyne*
-
-* Add `ActionController::Parameters#dig` on Ruby 2.3 and greater, which
- behaves the same as `Hash#dig`.
-
- *Sean Griffin*
-
-* Add request headers in the payload of the `start_processing.action_controller`
- and `process_action.action_controller` notifications.
-
- *Gareth du Plooy*
-
-* Add `action_dispatch_integration_test` load hook. The hook can be used to
- extend `ActionDispatch::IntegrationTest` once it has been loaded.
-
- *Yuichiro Kaneko*
-
-* Update default rendering policies when the controller action did
- not explicitly indicate a response.
-
- For API controllers, the implicit render always renders "204 No Content"
- and does not account for any templates.
-
- For other controllers, the following conditions are checked:
-
- First, if a template exists for the controller action, it is rendered.
- This template lookup takes into account the action name, locales, format,
- variant, template handlers, etc. (see `render` for details).
-
- Second, if other templates exist for the controller action but is not in
- the right format (or variant, etc.), an `ActionController::UnknownFormat`
- is raised. The list of available templates is assumed to be a complete
- enumeration of all the possible formats (or variants, etc.); that is,
- having only HTML and JSON templates indicate that the controller action is
- not meant to handle XML requests.
-
- Third, if the current request is an "interactive" browser request (the user
- navigated here by entering the URL in the address bar, submitting a form,
- clicking on a link, etc. as opposed to an XHR or non-browser API request),
- `ActionView::UnknownFormat` is raised to display a helpful error
- message.
-
- Finally, it falls back to the same "204 No Content" behavior as API controllers.
-
- *Godfrey Chan*, *Jon Moss*, *Kasper Timm Hansen*, *Mike Clark*, *Matthew Draper*
-
-## Rails 5.0.0.beta3 (February 24, 2016) ##
-
-* Add "application/gzip" as a default mime type.
-
- *Mehmet Emin İNAÇ*
-
-* Add request encoding and response parsing to integration tests.
-
- What previously was:
-
- ```ruby
- require 'test_helper'
-
- class ApiTest < ActionDispatch::IntegrationTest
- test 'creates articles' do
- assert_difference -> { Article.count } do
- post articles_path(format: :json),
- params: { article: { title: 'Ahoy!' } }.to_json,
- headers: { 'Content-Type' => 'application/json' }
- end
-
- assert_equal({ 'id' => Article.last.id, 'title' => 'Ahoy!' }, JSON.parse(response.body))
- end
- end
- ```
-
- Can now be written as:
-
- ```ruby
- require 'test_helper'
-
- class ApiTest < ActionDispatch::IntegrationTest
- test 'creates articles' do
- assert_difference -> { Article.count } do
- post articles_path, params: { article: { title: 'Ahoy!' } }, as: :json
- end
-
- assert_equal({ 'id' => Article.last.id, 'title' => 'Ahoy!' }, response.parsed_body)
- end
- end
- ```
-
- Passing `as: :json` to integration test request helpers will set the format,
- content type and encode the parameters as JSON.
-
- Then on the response side, `parsed_body` will parse the body according to the
- content type the response has.
-
- Currently JSON is the only supported MIME type. Add your own with
- `ActionDispatch::IntegrationTest.register_encoder`.
-
- *Kasper Timm Hansen*
-
-* Add "image/svg+xml" as a default mime type.
-
- *DHH*
-
-## Rails 5.0.0.beta2 (February 01, 2016) ##
-
-* Add `-g` and `-c` options to `bin/rails routes`. These options return the url `name`, `verb` and
- `path` field that match the pattern or match a specific controller.
-
- Deprecate `CONTROLLER` env variable in `bin/rails routes`.
-
- See #18902.
-
- *Anton Davydov*, *Vipul A M*
-
-* Response etags to always be weak: Prefixes 'W/' to value returned by
- `ActionDispatch::Http::Cache::Response#etag=`, such that etags set in
- `fresh_when` and `stale?` are weak.
-
- Fixes #17556.
-
- *Abhishek Yadav*
-
-* Provide the name of HTTP Status code in assertions.
-
- *Sean Collins*
-
-* More explicit error message when running `rake routes`. `CONTROLLER` argument
- can now be supplied in different ways:
- `Rails::WelcomeController`, `Rails::Welcome`, `rails/welcome`.
-
- Fixes #22918.
-
- *Edouard Chin*
-
-* Allow `ActionController::Parameters` instances as an argument to URL
- helper methods. An `ArgumentError` will be raised if the passed parameters
- are not secure.
-
- Fixes #22832.
-
- *Prathamesh Sonpatki*
-
-* Add option for per-form CSRF tokens.
-
- *Greg Ose*, *Ben Toews*
-
-* Fix `ActionController::Parameters#convert_parameters_to_hashes` to return filtered
- or unfiltered values based on from where it is called, `to_h` or `to_unsafe_h`
- respectively.
-
- Fixes #22841.
-
- *Prathamesh Sonpatki*
-
-* Add `ActionController::Parameters#include?`
-
- *Justin Coyne*
-
-## Rails 5.0.0.beta1 (December 18, 2015) ##
-
-* Deprecate `redirect_to :back` in favor of `redirect_back`, which accepts a
- required `fallback_location` argument, thus eliminating the possibility of a
- `RedirectBackError`.
-
- *Derek Prior*
-
-* Add `redirect_back` method to `ActionController::Redirecting` to provide a
- way to safely redirect to the `HTTP_REFERER` if it is present, falling back
- to a provided redirect otherwise.
-
- *Derek Prior*
-
-* `ActionController::TestCase` will be moved to its own gem in Rails 5.1.
-
- With the speed improvements made to `ActionDispatch::IntegrationTest` we no
- longer need to keep two separate code bases for testing controllers. In
- Rails 5.1 `ActionController::TestCase` will be deprecated and moved into a
- gem outside of Rails source.
-
- This is a documentation deprecation so that going forward new tests will use
- `ActionDispatch::IntegrationTest` instead of `ActionController::TestCase`.
-
- *Eileen M. Uchitelle*
-
-* Add a `response_format` option to `ActionDispatch::DebugExceptions`
- to configure the format of the response when errors occur in
- development mode.
-
- If `response_format` is `:default` the debug info will be rendered
- in an HTML page. In the other hand, if the provided value is `:api`
- the debug info will be rendered in the original response format.
-
- *Jorge Bejar*
-
-* Change the `protect_from_forgery` prepend default to `false`.
-
- Per this comment
- https://github.com/rails/rails/pull/18334#issuecomment-69234050 we want
- `protect_from_forgery` to default to `prepend: false`.
-
- `protect_from_forgery` will now be inserted into the callback chain at the
- point it is called in your application. This is useful for cases where you
- want to `protect_from_forgery` after you perform required authentication
- callbacks or other callbacks that are required to run after forgery protection.
-
- If you want `protect_from_forgery` callbacks to always run first, regardless of
- position they are called in your application then you can add `prepend: true`
- to your `protect_from_forgery` call.
-
- Example:
-
- ```ruby
- protect_from_forgery prepend: true
- ```
-
- *Eileen M. Uchitelle*
-
-* In url_for, never append a question mark to the URL when the query string
- is empty anyway. (It used to do that when called like `url_for(controller:
- 'x', action: 'y', q: {})`.)
-
- *Paul Grayson*
-
-* Catch invalid UTF-8 querystring values and respond with BadRequest
-
- Check querystring params for invalid UTF-8 characters, and raise an
- ActionController::BadRequest error if present. Previously these strings
- would typically trigger errors further down the stack.
-
- *Grey Baker*
-
-* Parse RSS/ATOM responses as XML, not HTML.
-
- *Alexander Kaupanin*
-
-* Show helpful message in `BadRequest` exceptions due to invalid path
- parameter encodings.
-
- Fixes #21923.
-
- *Agis Anastasopoulos*
-
-* Add the ability of returning arbitrary headers to `ActionDispatch::Static`.
-
- Now ActionDispatch::Static can accept HTTP headers so that developers
- will have control of returning arbitrary headers like
- 'Access-Control-Allow-Origin' when a response is delivered. They can be
- configured with `#config`:
-
- Example:
-
- config.public_file_server.headers = {
- "Cache-Control" => "public, max-age=60",
- "Access-Control-Allow-Origin" => "http://rubyonrails.org"
- }
-
- *Yuki Nishijima*
-
-* Allow multiple `root` routes in same scope level. Example:
-
- Example:
-
- root 'blog#show', constraints: ->(req) { Hostname.blog_site?(req.host) }
- root 'landing#show'
-
- *Rafael Sales*
-
-* Fix regression in mounted engine named routes generation for app deployed to
- a subdirectory. `relative_url_root` was prepended to the path twice (e.g.
- "/subdir/subdir/engine_path" instead of "/subdir/engine_path")
-
- Fixes #20920. Fixes #21459.
-
- *Matthew Erhard*
-
-* `ActionDispatch::Response#new` no longer applies default headers. If you want
- default headers applied to the response object, then call
- `ActionDispatch::Response.create`. This change only impacts people who are
- directly constructing an `ActionDispatch::Response` object.
-
-* Accessing mime types via constants like `Mime::HTML` is deprecated. Please
- change code like this:
-
- Mime::HTML
-
- To this:
-
- Mime[:html]
-
- This change is so that Rails will not manage a list of constants, and fixes
- an issue where if a type isn't registered you could possibly get the wrong
- object.
-
- `Mime[:html]` is available in older versions of Rails, too, so you can
- safely change libraries and plugins and maintain compatibility with
- multiple versions of Rails.
-
-* `url_for` does not modify its arguments when generating polymorphic URLs.
-
- *Bernerd Schaefer*
-
-* Make it easier to opt in to `config.force_ssl` and `config.ssl_options` by
- making them less dangerous to try and easier to disable.
-
- SSL redirect:
- * Move `:host` and `:port` options within `redirect: { … }`. Deprecate.
- * Introduce `:status` and `:body` to customize the redirect response.
- The 301 permanent default makes it difficult to test the redirect and
- back out of it since browsers remember the 301. Test with a 302 or 307
- instead, then switch to 301 once you're confident that all is well.
-
- HTTP Strict Transport Security (HSTS):
- * Shorter max-age. Shorten the default max-age from 1 year to 180 days,
- the low end for https://www.ssllabs.com/ssltest/ grading and greater
- than the 18-week minimum to qualify for browser preload lists.
- * Disabling HSTS. Setting `hsts: false` now sets `hsts { expires: 0 }`
- instead of omitting the header. Omitting does nothing to disable HSTS
- since browsers hang on to your previous settings until they expire.
- Sending `{ hsts: { expires: 0 }}` flushes out old browser settings and
- actually disables HSTS:
- http://tools.ietf.org/html/rfc6797#section-6.1.1
- * HSTS Preload. Introduce `preload: true` to set the `preload` flag,
- indicating that your site may be included in browser preload lists,
- including Chrome, Firefox, Safari, IE11, and Edge. Submit your site:
- https://hstspreload.appspot.com
-
- *Jeremy Daer*
-
-* Update `ActionController::TestSession#fetch` to behave more like
- `ActionDispatch::Request::Session#fetch` when using non-string keys.
-
- *Jeremy Friesen*
-
-* Using strings or symbols for middleware class names is deprecated. Convert
- things like this:
-
- middleware.use "Foo::Bar"
-
- to this:
-
- middleware.use Foo::Bar
-
-* `ActionController::TestSession` now accepts a default value as well as
- a block for generating a default value based off the key provided.
-
- This fixes calls to `session#fetch` in `ApplicationController` instances that
- take more two arguments or a block from raising `ArgumentError: wrong
- number of arguments (2 for 1)` when performing controller tests.
-
- *Matthew Gerrior*
-
-* Fix `ActionController::Parameters#fetch` overwriting `KeyError` returned by
- default block.
-
- *Jonas Schuber Erlandsson*, *Roque Pinel*
-
-* `ActionController::Parameters` no longer inherits from
- `HashWithIndifferentAccess`
-
- Inheriting from `HashWithIndifferentAccess` allowed users to call any
- enumerable methods on `Parameters` object, resulting in a risk of losing the
- `permitted?` status or even getting back a pure `Hash` object instead of
- a `Parameters` object with proper sanitization.
-
- By not inheriting from `HashWithIndifferentAccess`, we are able to make
- sure that all methods that are defined in `Parameters` object will return
- a proper `Parameters` object with a correct `permitted?` flag.
-
- *Prem Sichanugrist*
-
-* Replaced `ActiveSupport::Concurrency::Latch` with `Concurrent::CountDownLatch`
- from the concurrent-ruby gem.
-
- *Jerry D'Antonio*
-
-* Add ability to filter parameters based on parent keys.
-
- # matches {credit_card: {code: "xxxx"}}
- # doesn't match {file: { code: "xxxx"}}
- config.filter_parameters += [ "credit_card.code" ]
-
- See #13897.
-
- *Guillaume Malette*
-
-* Deprecate passing first parameter as `Hash` and default status code for `head` method.
-
- *Mehmet Emin İNAÇ*
-
-* Adds`Rack::Utils::ParameterTypeError` and `Rack::Utils::InvalidParameterError`
- to the rescue_responses hash in `ExceptionWrapper` (Rack recommends
- integrators serve 400s for both of these).
-
- *Grey Baker*
-
-* Add support for API only apps.
- `ActionController::API` is added as a replacement of
- `ActionController::Base` for this kind of applications.
-
- *Santiago Pastorino*, *Jorge Bejar*
-
-* Remove `assigns` and `assert_template`. Both methods have been extracted
- into a gem at https://github.com/rails/rails-controller-testing.
-
- See #18950.
-
- *Alan Guo Xiang Tan*
-
-* `FileHandler` and `Static` middleware initializers accept `index` argument
- to configure the directory index file name. Defaults to `index` (as in
- `index.html`).
-
- See #20017.
-
- *Eliot Sykes*
-
-* Deprecate `:nothing` option for `render` method.
-
- *Mehmet Emin İNAÇ*
-
-* Fix `rake routes` not showing the right format when
- nesting multiple routes.
-
- See #18373.
-
- *Ravil Bayramgalin*
-
-* Add ability to override default form builder for a controller.
-
- class AdminController < ApplicationController
- default_form_builder AdminFormBuilder
- end
-
- *Kevin McPhillips*
-
-* For actions with no corresponding templates, render `head :no_content`
- instead of raising an error. This allows for slimmer API controller
- methods that simply work, without needing further instructions.
-
- See #19036.
-
- *Stephen Bussey*
-
-* Provide friendlier access to request variants.
-
- request.variant = :phone
- request.variant.phone? # true
- request.variant.tablet? # false
-
- request.variant = [:phone, :tablet]
- request.variant.phone? # true
- request.variant.desktop? # false
- request.variant.any?(:phone, :desktop) # true
- request.variant.any?(:desktop, :watch) # false
-
- *George Claghorn*
-
-* Fix regression where a gzip file response would have a Content-type,
- even when it was a 304 status code.
-
- See #19271.
-
- *Kohei Suzuki*
-
-* Fix handling of empty `X_FORWARDED_HOST` header in `raw_host_with_port`.
-
- Previously, an empty `X_FORWARDED_HOST` header would cause
- `Actiondispatch::Http:URL.raw_host_with_port` to return `nil`, causing
- `Actiondispatch::Http:URL.host` to raise a `NoMethodError`.
-
- *Adam Forsyth*
-
-* Allow `Bearer` as token-keyword in `Authorization-Header`.
-
- Additionally to `Token`, the keyword `Bearer` is acceptable as a keyword
- for the auth-token. The `Bearer` keyword is described in the original
- OAuth RFC and used in libraries like Angular-JWT.
-
- See #19094.
-
- *Peter Schröder*
-
-* Drop request class from `RouteSet` constructor.
-
- If you would like to use a custom request class, please subclass and implement
- the `request_class` method.
-
- *tenderlove@ruby-lang.org*
-
-* Fallback to `ENV['RAILS_RELATIVE_URL_ROOT']` in `url_for`.
-
- Fixed an issue where the `RAILS_RELATIVE_URL_ROOT` environment variable is not
- prepended to the path when `url_for` is called. If `SCRIPT_NAME` (used by Rack)
- is set, it takes precedence.
-
- Fixes #5122.
-
- *Yasyf Mohamedali*
-
-* Partitioning of routes is now done when the routes are being drawn. This
- helps to decrease the time spent filtering the routes during the first request.
-
- *Guo Xiang Tan*
-
-* Fix regression in functional tests. Responses should have default headers
- assigned.
-
- See #18423.
-
- *Jeremy Kemper*, *Yves Senn*
-
-* Deprecate `AbstractController#skip_action_callback` in favor of individual skip_callback methods
- (which can be made to raise an error if no callback was removed).
-
- *Iain Beeston*
-
-* Alias the `ActionDispatch::Request#uuid` method to `ActionDispatch::Request#request_id`.
- Due to implementation, `config.log_tags = [:request_id]` also works in substitute
- for `config.log_tags = [:uuid]`.
-
- *David Ilizarov*
-
-* Change filter on /rails/info/routes to use an actual path regexp from rails
- and not approximate javascript version. Oniguruma supports much more
- extensive list of features than javascript regexp engine.
-
- Fixes #18402.
-
- *Ravil Bayramgalin*
-
-* Non-string authenticity tokens do not raise NoMethodError when decoding
- the masked token.
-
- *Ville Lautanala*
-
-* Add `http_cache_forever` to Action Controller, so we can cache a response
- that never gets expired.
-
- *arthurnn*
-
-* `ActionController#translate` supports symbols as shortcuts.
- When a shortcut is given it also performs the lookup without the action
- name.
-
- *Max Melentiev*
-
-* Expand `ActionController::ConditionalGet#fresh_when` and `stale?` to also
- accept a collection of records as the first argument, so that the
- following code can be written in a shorter form.
-
- # Before
- def index
- @articles = Article.all
- fresh_when(etag: @articles, last_modified: @articles.maximum(:updated_at))
- end
-
- # After
- def index
- @articles = Article.all
- fresh_when(@articles)
- end
-
- *claudiob*
-
-* Explicitly ignored wildcard verbs when searching for HEAD routes before fallback
-
- Fixes an issue where a mounted rack app at root would intercept the HEAD
- request causing an incorrect behavior during the fall back to GET requests.
-
- Example:
-
- draw do
- get '/home' => 'test#index'
- mount rack_app, at: '/'
- end
- head '/home'
- assert_response :success
-
- In this case, a HEAD request runs through the routes the first time and fails
- to match anything. Then, it runs through the list with the fallback and matches
- `get '/home'`. The original behavior would match the rack app in the first pass.
-
- *Terence Sun*
-
-* Migrating xhr methods to keyword arguments syntax
- in `ActionController::TestCase` and `ActionDispatch::Integration`
-
- Old syntax:
-
- xhr :get, :create, params: { id: 1 }
-
- New syntax example:
-
- get :create, params: { id: 1 }, xhr: true
-
- *Kir Shatrov*
-
-* Migrating to keyword arguments syntax in `ActionController::TestCase` and
- `ActionDispatch::Integration` HTTP request methods.
-
- Example:
-
- post :create, params: { y: x }, session: { a: 'b' }
- get :view, params: { id: 1 }
- get :view, params: { id: 1 }, format: :json
-
- *Kir Shatrov*
-
-* Preserve default url options when generating URLs.
-
- Fixes an issue that would cause `default_url_options` to be lost when
- generating URLs with fewer positional arguments than parameters in the
- route definition.
-
- *Tekin Suleyman*
-
-* Deprecate `*_via_redirect` integration test methods.
-
- Use `follow_redirect!` manually after the request call for the same behavior.
-
- *Aditya Kapoor*
-
-* Add `ActionController::Renderer` to render arbitrary templates
- outside controller actions.
-
- Its functionality is accessible through class methods `render` and
- `renderer` of `ActionController::Base`.
-
- *Ravil Bayramgalin*
-
-* Support `:assigns` option when rendering with controllers/mailers.
-
- *Ravil Bayramgalin*
-
-* Default headers, removed in controller actions, are no longer reapplied on
- the test response.
-
- *Jonas Baumann*
-
-* Deprecate all `*_filter` callbacks in favor of `*_action` callbacks.
-
- *Rafael Mendonça França*
-
-* Allow you to pass `prepend: false` to `protect_from_forgery` to have the
- verification callback appended instead of prepended to the chain.
- This allows you to let the verification step depend on prior callbacks.
-
- Example:
-
- class ApplicationController < ActionController::Base
- before_action :authenticate
- protect_from_forgery prepend: false, unless: -> { @authenticated_by.oauth? }
-
- private
- def authenticate
- if oauth_request?
- # authenticate with oauth
- @authenticated_by = 'oauth'.inquiry
- else
- # authenticate with cookies
- @authenticated_by = 'cookie'.inquiry
- end
- end
- end
-
- *Josef Šimánek*
-
-* Remove `ActionController::HideActions`.
-
- *Ravil Bayramgalin*
-
-* Remove `respond_to`/`respond_with` placeholder methods, this functionality
- has been extracted to the `responders` gem.
-
- *Carlos Antonio da Silva*
-
-* Remove deprecated assertion files.
-
- *Rafael Mendonça França*
-
-* Remove deprecated usage of string keys in URL helpers.
-
- *Rafael Mendonça França*
-
-* Remove deprecated `only_path` option on `*_path` helpers.
-
- *Rafael Mendonça França*
-
-* Remove deprecated `NamedRouteCollection#helpers`.
-
- *Rafael Mendonça França*
-
-* Remove deprecated support to define routes with `:to` option that doesn't contain `#`.
-
- *Rafael Mendonça França*
-
-* Remove deprecated `ActionDispatch::Response#to_ary`.
-
- *Rafael Mendonça França*
-
-* Remove deprecated `ActionDispatch::Request#deep_munge`.
-
- *Rafael Mendonça França*
-
-* Remove deprecated `ActionDispatch::Http::Parameters#symbolized_path_parameters`.
-
- *Rafael Mendonça França*
-
-* Remove deprecated option `use_route` in controller tests.
-
- *Rafael Mendonça França*
-
-* Ensure `append_info_to_payload` is called even if an exception is raised.
-
- Fixes an issue where when an exception is raised in the request the additional
- payload data is not available.
-
- See #14903.
-
- *Dieter Komendera*, *Margus Pärt*
-
-* Correctly rely on the response's status code to handle calls to `head`.
-
- *Robin Dupret*
-
-* Using `head` method returns empty response_body instead
- of returning a single space " ".
-
- The old behavior was added as a workaround for a bug in an early
- version of Safari, where the HTTP headers are not returned correctly
- if the response body has a 0-length. This is been fixed since and
- the workaround is no longer necessary.
-
- Fixes #18253.
-
- *Prathamesh Sonpatki*
-
-* Fix how polymorphic routes works with objects that implement `to_model`.
-
- *Travis Grathwell*
-
-* Stop converting empty arrays in `params` to `nil`.
-
- This behavior was introduced in response to CVE-2012-2660, CVE-2012-2694
- and CVE-2013-0155
-
- ActiveRecord now issues a safe query when passing an empty array into
- a where clause, so there is no longer a need to defend against this type
- of input (any nils are still stripped from the array).
-
- *Chris Sinjakli*
-
-* Fixed usage of optional scopes in url helpers.
-
- *Alex Robbin*
-
-* Fixed handling of positional url helper arguments when `format: false`.
-
- Fixes #17819.
-
- *Andrew White*, *Tatiana Soukiassian*
-
-Please check [4-2-stable](https://github.com/rails/rails/blob/4-2-stable/actionpack/CHANGELOG.md) for previous changes.
+Please check [5-0-stable](https://github.com/rails/rails/blob/5-0-stable/actionpack/CHANGELOG.md) for previous changes.
diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec
index 66300754e3..965fafff5f 100644
--- a/actionpack/actionpack.gemspec
+++ b/actionpack/actionpack.gemspec
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
s.add_dependency 'rack', '~> 2.x'
s.add_dependency 'rack-test', '~> 0.6.3'
s.add_dependency 'rails-html-sanitizer', '~> 1.0', '>= 1.0.2'
- s.add_dependency 'rails-dom-testing', '~> 1.0', '>= 1.0.5'
+ s.add_dependency 'rails-dom-testing', '~> 2.0'
s.add_dependency 'actionview', version
s.add_development_dependency 'activemodel', version
diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb
index 9f192c54f7..a6fb0dbe1d 100644
--- a/actionpack/lib/abstract_controller/rendering.rb
+++ b/actionpack/lib/abstract_controller/rendering.rb
@@ -60,9 +60,7 @@ module AbstractController
end
DEFAULT_PROTECTED_INSTANCE_VARIABLES = Set.new %i(
- @_action_name @_response_body @_formats @_prefixes @_config
- @_view_context_class @_view_renderer @_lookup_context
- @_routes @_db_runtime
+ @_action_name @_response_body @_formats @_prefixes
)
# This method should return a hash with assigns.
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 04e5922ce8..d546d7260c 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -229,7 +229,7 @@ module ActionController
HttpAuthentication::Digest::ControllerMethods,
HttpAuthentication::Token::ControllerMethods,
- # Before callbacks should also be executed the earliest as possible, so
+ # Before callbacks should also be executed as early as possible, so
# also include them at the bottom.
AbstractController::Callbacks,
@@ -251,9 +251,10 @@ module ActionController
setup_renderer!
# Define some internal variables that should not be propagated to the view.
- PROTECTED_IVARS = AbstractController::Rendering::DEFAULT_PROTECTED_INSTANCE_VARIABLES + [
- :@_params, :@_response, :@_request,
- :@_view_runtime, :@_stream, :@_url_options, :@_action_has_layout ]
+ PROTECTED_IVARS = AbstractController::Rendering::DEFAULT_PROTECTED_INSTANCE_VARIABLES + %i(
+ @_params @_response @_request @_config @_url_options @_action_has_layout @_view_context_class
+ @_view_renderer @_lookup_context @_routes @_view_runtime @_db_runtime @_helper_proxy
+ )
def _protected_ivars # :nodoc:
PROTECTED_IVARS
diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb
index d3853e2e83..295f0cb66f 100644
--- a/actionpack/lib/action_controller/metal/helpers.rb
+++ b/actionpack/lib/action_controller/metal/helpers.rb
@@ -5,7 +5,7 @@ module ActionController
#
# In addition to using the standard template helpers provided, creating custom helpers to
# extract complicated logic or reusable functionality is strongly encouraged. By default, each controller
- # will include all helpers. These helpers are only accessible on the controller through <tt>.helpers</tt>
+ # will include all helpers. These helpers are only accessible on the controller through <tt>#helpers</tt>
#
# In previous versions of \Rails the controller will include a helper which
# matches the name of the controller, e.g., <tt>MyController</tt> will automatically
@@ -71,7 +71,7 @@ module ActionController
attrs.flatten.each { |attr| helper_method(attr, "#{attr}=") }
end
- # Provides a proxy to access helpers methods from outside the view.
+ # Provides a proxy to access helper methods from outside the view.
def helpers
@helper_proxy ||= begin
proxy = ActionView::Base.new
@@ -113,5 +113,10 @@ module ActionController
all_helpers_from_path(helpers_path)
end
end
+
+ # Provides a proxy to access helper methods from outside the view.
+ def helpers
+ @_helper_proxy ||= view_context
+ end
end
end
diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb
index 6055fde4f7..5d395cd8bd 100644
--- a/actionpack/lib/action_controller/metal/live.rb
+++ b/actionpack/lib/action_controller/metal/live.rb
@@ -163,14 +163,6 @@ module ActionController
end
end
- def each
- @response.sending!
- while str = @buf.pop
- yield str
- end
- @response.sent!
- end
-
# Write a 'close' event to the buffer; the producer/writing thread
# uses this to notify us that it's finished supplying content.
#
@@ -210,6 +202,14 @@ module ActionController
def call_on_error
@error_callback.call
end
+
+ private
+
+ def each_chunk(&block)
+ while str = @buf.pop
+ yield str
+ end
+ end
end
class Response < ActionDispatch::Response #:nodoc: all
diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb
index 90fb34e386..1735609cd9 100644
--- a/actionpack/lib/action_controller/metal/renderers.rb
+++ b/actionpack/lib/action_controller/metal/renderers.rb
@@ -103,7 +103,7 @@ module ActionController
#
# Both <tt>ActionController::Base</tt> and <tt>ActionController::API</tt>
# include <tt>ActionController::Renderers::All</tt>, making all renderers
- # avaialable in the controller. See <tt>Renderers::RENDERERS</tt> and <tt>Renderers.add</tt>.
+ # available in the controller. See <tt>Renderers::RENDERERS</tt> and <tt>Renderers.add</tt>.
#
# Since <tt>ActionController::Metal</tt> controllers cannot render, the controller
# must include <tt>AbstractController::Rendering</tt>, <tt>ActionController::Rendering</tt>,
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index 5793e28175..f7e8d06f10 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -405,7 +405,8 @@ module ActionController #:nodoc:
end
def normalize_action_path(action_path)
- action_path.split('?').first.to_s.chomp('/')
+ uri = URI.parse(action_path)
+ uri.path.chomp('/')
end
end
end
diff --git a/actionpack/lib/action_controller/metal/rescue.rb b/actionpack/lib/action_controller/metal/rescue.rb
index 0621a7368c..17f4030f25 100644
--- a/actionpack/lib/action_controller/metal/rescue.rb
+++ b/actionpack/lib/action_controller/metal/rescue.rb
@@ -1,22 +1,11 @@
module ActionController #:nodoc:
- # This module is responsible to provide `rescue_from` helpers
- # to controllers and configure when detailed exceptions must be
+ # This module is responsible for providing `rescue_from` helpers
+ # to controllers and configuring when detailed exceptions must be
# shown.
module Rescue
extend ActiveSupport::Concern
include ActiveSupport::Rescuable
- def rescue_with_handler(exception)
- if exception.cause
- handler_index = index_of_handler_for_rescue(exception) || Float::INFINITY
- cause_handler_index = index_of_handler_for_rescue(exception.cause)
- if cause_handler_index && cause_handler_index <= handler_index
- exception = exception.cause
- end
- end
- super(exception)
- end
-
# Override this method if you want to customize when detailed
# exceptions must be shown. This method is only called when
# consider_all_requests_local is false. By default, it returns
@@ -31,7 +20,7 @@ module ActionController #:nodoc:
super
rescue Exception => exception
request.env['action_dispatch.show_detailed_exceptions'] ||= show_detailed_exceptions?
- rescue_with_handler(exception) || raise(exception)
+ rescue_with_handler(exception) || raise
end
end
end
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index f9b80dd805..08049d7af8 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -43,7 +43,7 @@ module ActionController
# == Action Controller \Parameters
#
- # Allows to choose which attributes should be whitelisted for mass updating
+ # Allows you to choose which attributes should be whitelisted for mass updating
# and thus prevent accidentally exposing that which shouldn't be exposed.
# Provides two methods for this purpose: #require and #permit. The former is
# used to mark parameters as required. The latter is used to set the parameter
@@ -196,7 +196,7 @@ module ActionController
end
alias_method :to_unsafe_hash, :to_unsafe_h
- # Convert all hashes in values into parameters, then yield each pair like
+ # Convert all hashes in values into parameters, then yield each pair in
# the same way as <tt>Hash#each_pair</tt>
def each_pair(&block)
@parameters.each_pair do |key, value|
@@ -278,7 +278,7 @@ module ActionController
# params = ActionController::Parameters.new(user: { ... }, profile: { ... })
# user_params, profile_params = params.require(:user, :profile)
#
- # Otherwise, the method reraises the first exception found:
+ # Otherwise, the method re-raises the first exception found:
#
# params = ActionController::Parameters.new(user: {}, profile: {})
# user_params, profile_params = params.require(:user, :profile)
diff --git a/actionpack/lib/action_controller/renderer.rb b/actionpack/lib/action_controller/renderer.rb
index 2775a24e56..5ff4a658ad 100644
--- a/actionpack/lib/action_controller/renderer.rb
+++ b/actionpack/lib/action_controller/renderer.rb
@@ -13,11 +13,11 @@ module ActionController
#
# ApplicationController.renderer.render template: '...'
#
- # You can use a shortcut on controller to replace previous example with:
+ # You can use this shortcut in a controller, instead of the previous example:
#
# ApplicationController.render template: '...'
#
- # #render method allows you to use any options as when rendering in controller.
+ # #render allows you to use the same options that you can use when rendering in a controller.
# For example,
#
# FooController.render :action, locals: { ... }, assigns: { ... }
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index ecd21f29ce..ed2edcbe06 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -554,6 +554,8 @@ module ActionController
end
@request.query_string = ''
+ @response.sent!
+
@response
end
diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
index e9b25339dc..0a58ce2b96 100644
--- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb
+++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
@@ -164,7 +164,7 @@ module ActionDispatch
end
def format_from_path_extension
- path = @env['action_dispatch.original_path'] || @env['PATH_INFO']
+ path = get_header('action_dispatch.original_path') || get_header('PATH_INFO')
if match = path && path.match(/\.(\w+)\z/)
Mime[match.captures.first]
end
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index fa4c54701a..1515d59df3 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -68,7 +68,13 @@ module ActionDispatch # :nodoc:
alias_method :headers, :header
delegate :[], :[]=, :to => :@header
- delegate :each, :to => :@stream
+
+ def each(&block)
+ sending!
+ x = @stream.each(&block)
+ sent!
+ x
+ end
CONTENT_TYPE = "Content-Type".freeze
SET_COOKIE = "Set-Cookie".freeze
@@ -97,10 +103,10 @@ module ActionDispatch # :nodoc:
def body
@str_body ||= begin
- buf = ''
- each { |chunk| buf << chunk }
- buf
- end
+ buf = ''
+ each { |chunk| buf << chunk }
+ buf
+ end
end
def write(string)
@@ -112,10 +118,13 @@ module ActionDispatch # :nodoc:
end
def each(&block)
- @response.sending!
- x = @buf.each(&block)
- @response.sent!
- x
+ if @str_body
+ return enum_for(:each) unless block_given?
+
+ yield @str_body
+ else
+ each_chunk(&block)
+ end
end
def abort
@@ -129,6 +138,12 @@ module ActionDispatch # :nodoc:
def closed?
@closed
end
+
+ private
+
+ def each_chunk(&block)
+ @buf.each(&block) # extract into own method
+ end
end
def self.create(status = 200, header = {}, body = [], default_headers: self.default_headers)
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index 37f41ae988..7a1350a46d 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -217,7 +217,7 @@ module ActionDispatch
@protocol ||= ssl? ? 'https://' : 'http://'
end
- # Returns the \host for this request, such as "example.com".
+ # Returns the \host and port for this request, such as "example.com:8080".
#
# class Request < Rack::Request
# include ActionDispatch::Http::URL
@@ -226,6 +226,9 @@ module ActionDispatch
# req = Request.new 'HTTP_HOST' => 'example.com'
# req.raw_host_with_port # => "example.com"
#
+ # req = Request.new 'HTTP_HOST' => 'example.com:80'
+ # req.raw_host_with_port # => "example.com:80"
+ #
# req = Request.new 'HTTP_HOST' => 'example.com:8080'
# req.raw_host_with_port # => "example.com:8080"
def raw_host_with_port
@@ -236,7 +239,7 @@ module ActionDispatch
end
end
- # Returns the host for this request, such as example.com.
+ # Returns the host for this request, such as "example.com".
#
# class Request < Rack::Request
# include ActionDispatch::Http::URL
@@ -249,12 +252,16 @@ module ActionDispatch
end
# Returns a \host:\port string for this request, such as "example.com" or
- # "example.com:8080".
+ # "example.com:8080". Port is only included if it is not a default port
+ # (80 or 443)
#
# class Request < Rack::Request
# include ActionDispatch::Http::URL
# end
#
+ # req = Request.new 'HTTP_HOST' => 'example.com'
+ # req.host_with_port # => "example.com"
+ #
# req = Request.new 'HTTP_HOST' => 'example.com:80'
# req.host_with_port # => "example.com"
#
@@ -347,6 +354,17 @@ module ActionDispatch
standard_port? ? '' : ":#{port}"
end
+ # Returns the requested port, such as 8080, based on SERVER_PORT
+ #
+ # class Request < Rack::Request
+ # include ActionDispatch::Http::URL
+ # end
+ #
+ # req = Request.new 'SERVER_PORT' => '80'
+ # req.server_port # => 80
+ #
+ # req = Request.new 'SERVER_PORT' => '8080'
+ # req.server_port # => 8080
def server_port
get_header('SERVER_PORT').to_i
end
diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
index 51a471fb23..5f758d641a 100644
--- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
@@ -67,18 +67,19 @@ module ActionDispatch
log_error(request, wrapper)
if request.get_header('action_dispatch.show_detailed_exceptions')
- case @response_format
- when :api
- render_for_api_application(request, wrapper)
- when :default
- render_for_default_application(request, wrapper)
+ content_type = request.formats.first
+
+ if api_request?(content_type)
+ render_for_api_request(content_type, wrapper)
+ else
+ render_for_browser_request(request, wrapper)
end
else
raise exception
end
end
- def render_for_default_application(request, wrapper)
+ def render_for_browser_request(request, wrapper)
template = create_template(request, wrapper)
file = "rescues/#{wrapper.rescue_template}"
@@ -92,7 +93,7 @@ module ActionDispatch
render(wrapper.status_code, body, format)
end
- def render_for_api_application(request, wrapper)
+ def render_for_api_request(content_type, wrapper)
body = {
status: wrapper.status_code,
error: Rack::Utils::HTTP_STATUS_CODES.fetch(
@@ -103,7 +104,6 @@ module ActionDispatch
traces: wrapper.traces
}
- content_type = request.formats.first
to_format = "to_#{content_type.to_sym}"
if content_type && body.respond_to?(to_format)
@@ -181,5 +181,9 @@ module ActionDispatch
ActionDispatch::Routing::RoutesInspector.new(@routes_app.routes.routes)
end
end
+
+ def api_request?(content_type)
+ @response_format == :api && !content_type.html?
+ end
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/flash.rb b/actionpack/lib/action_dispatch/middleware/flash.rb
index 06038af571..80703940ed 100644
--- a/actionpack/lib/action_dispatch/middleware/flash.rb
+++ b/actionpack/lib/action_dispatch/middleware/flash.rb
@@ -133,7 +133,7 @@ module ActionDispatch
def to_session_value #:nodoc:
flashes_to_keep = @flashes.except(*@discard)
return nil if flashes_to_keep.empty?
- {'flashes' => flashes_to_keep}
+ { 'discard' => [], 'flashes' => flashes_to_keep }
end
def initialize(flashes = {}, discard = []) #:nodoc:
diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb
index 41c220236a..2c5721dc22 100644
--- a/actionpack/lib/action_dispatch/middleware/static.rb
+++ b/actionpack/lib/action_dispatch/middleware/static.rb
@@ -27,8 +27,8 @@ module ActionDispatch
# in the server's `public/` directory (see Static#call).
def match?(path)
path = ::Rack::Utils.unescape_path path
- return false unless valid_path?(path)
- path = Rack::Utils.clean_path_info path
+ return false unless ::Rack::Utils.valid_path? path
+ path = ::Rack::Utils.clean_path_info path
paths = [path, "#{path}#{ext}", "#{path}/#{@index}#{ext}"]
@@ -94,10 +94,6 @@ module ActionDispatch
false
end
end
-
- def valid_path?(path)
- path.valid_encoding? && !path.include?("\0")
- end
end
# This middleware will attempt to return the contents of a file's body from
diff --git a/actionpack/lib/action_dispatch/request/session.rb b/actionpack/lib/action_dispatch/request/session.rb
index 42890225fa..47568f6ad0 100644
--- a/actionpack/lib/action_dispatch/request/session.rb
+++ b/actionpack/lib/action_dispatch/request/session.rb
@@ -9,7 +9,7 @@ module ActionDispatch
# Singleton object used to determine if an optional param wasn't specified
Unspecified = Object.new
-
+
# Creates a session hash, merging the properties of the previous session if any
def self.create(store, req, default_options)
session_was = find req
@@ -198,6 +198,10 @@ module ActionDispatch
@delegate.merge!(other)
end
+ def each(&block)
+ to_hash.each(&block)
+ end
+
private
def load_for_read!
diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb
index 79d2f1f13c..dd6ac9db9c 100644
--- a/actionpack/lib/action_dispatch/routing.rb
+++ b/actionpack/lib/action_dispatch/routing.rb
@@ -118,11 +118,11 @@ module ActionDispatch
# controller :blog do
# get 'blog/show' => :list
# get 'blog/delete' => :delete
- # get 'blog/edit/:id' => :edit
+ # get 'blog/edit' => :edit
# end
#
# # provides named routes for show, delete, and edit
- # link_to @article.title, show_path(id: @article.id)
+ # link_to @article.title, blog_show_path(id: @article.id)
#
# == Pretty URLs
#
@@ -252,5 +252,14 @@ module ActionDispatch
SEPARATORS = %w( / . ? ) #:nodoc:
HTTP_METHODS = [:get, :head, :post, :patch, :put, :delete, :options] #:nodoc:
+
+ #:stopdoc:
+ INSECURE_URL_PARAMETERS_MESSAGE = <<-MSG.squish
+ Attempting to generate a URL from non-sanitized request parameters!
+
+ An attacker can inject malicious data into the generated URL, such as
+ changing the host. Whitelist and sanitize passed parameters to be secure.
+ MSG
+ #:startdoc:
end
end
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index faa93ecc17..8ff3b42a40 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -120,7 +120,7 @@ module ActionDispatch
if options_constraints.is_a?(Hash)
@defaults = Hash[options_constraints.find_all { |key, default|
- URL_OPTIONS.include?(key) && (String === default || Fixnum === default)
+ URL_OPTIONS.include?(key) && (String === default || Integer === default)
}].merge @defaults
@blocks = blocks
constraints.merge! options_constraints
@@ -824,7 +824,7 @@ module ActionDispatch
if options[:constraints].is_a?(Hash)
defaults = options[:constraints].select do |k, v|
- URL_OPTIONS.include?(k) && (v.is_a?(String) || v.is_a?(Fixnum))
+ URL_OPTIONS.include?(k) && (v.is_a?(String) || v.is_a?(Integer))
end
options[:defaults] = defaults.merge(options[:defaults] || {})
@@ -2088,8 +2088,7 @@ to this:
def each
node = self
- loop do
- break if node.equal? NULL
+ until node.equal? NULL
yield node
node = node.parent
end
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index c65dafe9e6..ed7130b58e 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -289,7 +289,7 @@ module ActionDispatch
if last.permitted?
args.pop.to_h
else
- raise ArgumentError, "Generating a URL from non sanitized request parameters is insecure!"
+ raise ArgumentError, ActionDispatch::Routing::INSECURE_URL_PARAMETERS_MESSAGE
end
end
helper.call self, args, options
diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb
index 28be189f93..5ee138e6c6 100644
--- a/actionpack/lib/action_dispatch/routing/url_for.rb
+++ b/actionpack/lib/action_dispatch/routing/url_for.rb
@@ -173,7 +173,7 @@ module ActionDispatch
route_name)
when ActionController::Parameters
unless options.permitted?
- raise ArgumentError.new("Generating a URL from non sanitized request parameters is insecure!")
+ raise ArgumentError.new(ActionDispatch::Routing::INSECURE_URL_PARAMETERS_MESSAGE)
end
route_name = options.delete :use_route
_routes.url_for(options.to_h.symbolize_keys.
diff --git a/actionpack/lib/action_dispatch/testing/assertion_response.rb b/actionpack/lib/action_dispatch/testing/assertion_response.rb
index 3fb81ff083..404b96bbcd 100644
--- a/actionpack/lib/action_dispatch/testing/assertion_response.rb
+++ b/actionpack/lib/action_dispatch/testing/assertion_response.rb
@@ -1,14 +1,7 @@
module ActionDispatch
- # This is a class that abstracts away an asserted response.
- # It purposely does not inherit from Response, because it doesn't need it.
- # That means it does not have headers or a body.
- #
- # As an input to the initializer, we take a Fixnum, a String, or a Symbol.
- # If it's a Fixnum or String, we figure out what its symbolized name.
- # If it's a Symbol, we figure out what its corresponding code is.
- # The resulting code will be a Fixnum, for real HTTP codes, and it will
- # be a String for the pseudo-HTTP codes, such as:
- # :success, :missing, :redirect and :error
+ # This is a class that abstracts away an asserted response. It purposely
+ # does not inherit from Response because it doesn't need it. That means it
+ # does not have headers or a body.
class AssertionResponse
attr_reader :code, :name
@@ -19,6 +12,9 @@ module ActionDispatch
error: "5XX"
}
+ # Accepts a specific response status code as an Integer (404) or String
+ # ('404') or a response status range as a Symbol pseudo-code (:success,
+ # indicating any 200-299 status code).
def initialize(code_or_name)
if code_or_name.is_a?(Symbol)
@name = code_or_name
diff --git a/actionpack/lib/action_dispatch/testing/test_request.rb b/actionpack/lib/action_dispatch/testing/test_request.rb
index ad1a7f7109..46523a8600 100644
--- a/actionpack/lib/action_dispatch/testing/test_request.rb
+++ b/actionpack/lib/action_dispatch/testing/test_request.rb
@@ -22,23 +22,23 @@ module ActionDispatch
private_class_method :default_env
def request_method=(method)
- @env['REQUEST_METHOD'] = method.to_s.upcase
+ set_header('REQUEST_METHOD', method.to_s.upcase)
end
def host=(host)
- @env['HTTP_HOST'] = host
+ set_header('HTTP_HOST', host)
end
def port=(number)
- @env['SERVER_PORT'] = number.to_i
+ set_header('SERVER_PORT', number.to_i)
end
def request_uri=(uri)
- @env['REQUEST_URI'] = uri
+ set_header('REQUEST_URI', uri)
end
def path=(path)
- @env['PATH_INFO'] = path
+ set_header('PATH_INFO', path)
end
def action=(action_name)
@@ -46,24 +46,24 @@ module ActionDispatch
end
def if_modified_since=(last_modified)
- @env['HTTP_IF_MODIFIED_SINCE'] = last_modified
+ set_header('HTTP_IF_MODIFIED_SINCE', last_modified)
end
def if_none_match=(etag)
- @env['HTTP_IF_NONE_MATCH'] = etag
+ set_header('HTTP_IF_NONE_MATCH', etag)
end
def remote_addr=(addr)
- @env['REMOTE_ADDR'] = addr
+ set_header('REMOTE_ADDR', addr)
end
def user_agent=(user_agent)
- @env['HTTP_USER_AGENT'] = user_agent
+ set_header('HTTP_USER_AGENT', user_agent)
end
def accept=(mime_types)
- @env.delete('action_dispatch.request.accepts')
- @env['HTTP_ACCEPT'] = Array(mime_types).collect(&:to_s).join(",")
+ delete_header('action_dispatch.request.accepts')
+ set_header('HTTP_ACCEPT', Array(mime_types).collect(&:to_s).join(","))
end
end
end
diff --git a/actionpack/lib/action_pack/gem_version.rb b/actionpack/lib/action_pack/gem_version.rb
index 157f401f54..d8f86630b1 100644
--- a/actionpack/lib/action_pack/gem_version.rb
+++ b/actionpack/lib/action_pack/gem_version.rb
@@ -6,9 +6,9 @@ module ActionPack
module VERSION
MAJOR = 5
- MINOR = 0
+ MINOR = 1
TINY = 0
- PRE = "beta3"
+ PRE = "alpha"
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
end
diff --git a/actionpack/test/assertions/response_assertions_test.rb b/actionpack/test/assertions/response_assertions_test.rb
index 579ce0ed29..57a67a48b5 100644
--- a/actionpack/test/assertions/response_assertions_test.rb
+++ b/actionpack/test/assertions/response_assertions_test.rb
@@ -35,7 +35,7 @@ module ActionDispatch
end
end
- def test_assert_response_fixnum
+ def test_assert_response_integer
@response = FakeResponse.new 400
assert_response 400
diff --git a/actionpack/test/controller/flash_hash_test.rb b/actionpack/test/controller/flash_hash_test.rb
index 081288ef21..f87077dd86 100644
--- a/actionpack/test/controller/flash_hash_test.rb
+++ b/actionpack/test/controller/flash_hash_test.rb
@@ -57,10 +57,10 @@ module ActionDispatch
def test_to_session_value
@hash['foo'] = 'bar'
- assert_equal({'flashes' => {'foo' => 'bar'}}, @hash.to_session_value)
+ assert_equal({ 'discard' => [], 'flashes' => { 'foo' => 'bar' } }, @hash.to_session_value)
@hash.now['qux'] = 1
- assert_equal({'flashes' => {'foo' => 'bar'}}, @hash.to_session_value)
+ assert_equal({ 'flashes' => { 'foo' => 'bar' }, 'discard' => [] }, @hash.to_session_value)
@hash.discard('foo')
assert_equal(nil, @hash.to_session_value)
diff --git a/actionpack/test/controller/helper_test.rb b/actionpack/test/controller/helper_test.rb
index feb882a2b3..ef85e141a0 100644
--- a/actionpack/test/controller/helper_test.rb
+++ b/actionpack/test/controller/helper_test.rb
@@ -207,6 +207,22 @@ class HelperTest < ActiveSupport::TestCase
assert methods.include?(:foobar)
end
+ def test_helper_proxy_in_instance
+ methods = AllHelpersController.new.helpers.methods
+
+ # Action View
+ assert_includes methods, :pluralize
+
+ # abc_helper.rb
+ assert_includes methods, :bare_a
+
+ # fun/games_helper.rb
+ assert_includes methods, :stratego
+
+ # fun/pdf_helper.rb
+ assert_includes methods, :foobar
+ end
+
def test_helper_proxy_config
AllHelpersController.config.my_var = 'smth'
diff --git a/actionpack/test/controller/live_stream_test.rb b/actionpack/test/controller/live_stream_test.rb
index a7759c080b..5977124594 100644
--- a/actionpack/test/controller/live_stream_test.rb
+++ b/actionpack/test/controller/live_stream_test.rb
@@ -246,7 +246,8 @@ module ActionController
def assert_stream_closed
assert response.stream.closed?, 'stream should be closed'
- assert response.sent?, 'stream should be sent'
+ assert response.committed?, 'response should be committed'
+ assert response.sent?, 'response should be sent'
end
def capture_log_output
diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb
index e10d4449f3..f83248402c 100644
--- a/actionpack/test/controller/redirect_test.rb
+++ b/actionpack/test/controller/redirect_test.rb
@@ -176,7 +176,6 @@ class RedirectTest < ActionController::TestCase
assert_equal "http://www.example.com", redirect_to_url
end
-
def test_relative_url_redirect_with_status
get :relative_url_redirect_with_status
assert_response 302
@@ -313,7 +312,7 @@ class RedirectTest < ActionController::TestCase
error = assert_raise(ArgumentError) do
get :redirect_to_params
end
- assert_equal "Generating a URL from non sanitized request parameters is insecure!", error.message
+ assert_equal ActionDispatch::Routing::INSECURE_URL_PARAMETERS_MESSAGE, error.message
end
def test_redirect_to_with_block
diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb
index f7dcbc1984..d56241f9cd 100644
--- a/actionpack/test/controller/request_forgery_protection_test.rb
+++ b/actionpack/test/controller/request_forgery_protection_test.rb
@@ -781,6 +781,19 @@ class PerFormTokensControllerTest < ActionController::TestCase
assert_response :success
end
+ def test_ignores_origin_during_generation
+ get :index, params: {form_path: 'https://example.com/per_form_tokens/post_one/'}
+
+ form_token = assert_presence_and_fetch_form_csrf_token
+
+ # This is required because PATH_INFO isn't reset between requests.
+ @request.env['PATH_INFO'] = '/per_form_tokens/post_one'
+ assert_nothing_raised do
+ post :post_one, params: {custom_authenticity_token: form_token}
+ end
+ assert_response :success
+ end
+
def test_ignores_trailing_slash_during_validation
get :index
diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb
index ed78f859ce..c088e5a043 100644
--- a/actionpack/test/controller/rescue_test.rb
+++ b/actionpack/test/controller/rescue_test.rb
@@ -131,22 +131,6 @@ class RescueController < ActionController::Base
def missing_template
end
- def io_error_in_view
- begin
- raise IOError.new('this is io error')
- rescue
- raise ActionView::TemplateError.new(nil)
- end
- end
-
- def zero_division_error_in_view
- begin
- raise ZeroDivisionError.new('this is zero division error')
- rescue
- raise ActionView::TemplateError.new(nil)
- end
- end
-
def exception_with_more_specific_handler_for_wrapper
raise RecordInvalid
rescue
@@ -251,17 +235,6 @@ class ControllerInheritanceRescueControllerTest < ActionController::TestCase
end
class RescueControllerTest < ActionController::TestCase
-
- def test_io_error_in_view
- get :io_error_in_view
- assert_equal 'io error', @response.body
- end
-
- def test_zero_division_error_in_view
- get :zero_division_error_in_view
- assert_equal 'action_view templater error', @response.body
- end
-
def test_rescue_handler
get :not_authorized
assert_response :forbidden
@@ -276,7 +249,6 @@ class RescueControllerTest < ActionController::TestCase
get :record_invalid
end
end
-
def test_rescue_handler_with_argument_as_string
assert_called_with @controller, :show_errors, [Exception] do
get :record_invalid_raise_as_string
@@ -314,7 +286,6 @@ class RescueControllerTest < ActionController::TestCase
get :resource_unavailable
assert_equal "RescueController::ResourceUnavailable", @response.body
end
-
def test_block_rescue_handler_with_argument_as_string
get :resource_unavailable_raise_as_string
assert_equal "RescueController::ResourceUnavailableToRescueAsString", @response.body
@@ -322,7 +293,7 @@ class RescueControllerTest < ActionController::TestCase
test 'rescue when wrapper has more specific handler than cause' do
get :exception_with_more_specific_handler_for_wrapper
- assert_response :unprocessable_entity
+ assert_response :forbidden
end
test 'rescue when cause has more specific handler than wrapper' do
diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb
index 168677829a..03bf8f8295 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -626,7 +626,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
assert_equal '/pages/boo', url_for(rs, { :controller => 'pages', :action => 'boo' })
end
- def test_route_with_fixnum_default
+ def test_route_with_integer_default
rs.draw do
get 'page(/:id)' => 'content#show_page', :id => 1
diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb
index ebcdda6074..6160b3395a 100644
--- a/actionpack/test/controller/test_case_test.rb
+++ b/actionpack/test/controller/test_case_test.rb
@@ -553,7 +553,7 @@ XML
assert_equal 'created', flash[:notice]
end
- def test_params_passing_with_fixnums
+ def test_params_passing_with_integer
get :test_params, params: {
page: { name: "Page name", month: 4, year: 2004, day: 6 }
}
@@ -565,7 +565,7 @@ XML
)
end
- def test_params_passing_with_fixnums_when_not_html_request
+ def test_params_passing_with_integers_when_not_html_request
get :test_params, params: { format: 'json', count: 999 }
parsed_params = ::JSON.parse(@response.body)
assert_equal(
diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb
index 159bf10545..5a39db145e 100644
--- a/actionpack/test/dispatch/debug_exceptions_test.rb
+++ b/actionpack/test/dispatch/debug_exceptions_test.rb
@@ -27,37 +27,37 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
env['action_dispatch.show_detailed_exceptions'] = @detailed
req = ActionDispatch::Request.new(env)
case req.path
- when "/pass"
+ when %r{/pass}
[404, { "X-Cascade" => "pass" }, self]
- when "/not_found"
+ when %r{/not_found}
raise AbstractController::ActionNotFound
- when "/runtime_error"
+ when %r{/runtime_error}
raise RuntimeError
- when "/method_not_allowed"
+ when %r{/method_not_allowed}
raise ActionController::MethodNotAllowed
- when "/unknown_http_method"
+ when %r{/unknown_http_method}
raise ActionController::UnknownHttpMethod
- when "/not_implemented"
+ when %r{/not_implemented}
raise ActionController::NotImplemented
- when "/unprocessable_entity"
+ when %r{/unprocessable_entity}
raise ActionController::InvalidAuthenticityToken
- when "/not_found_original_exception"
+ when %r{/not_found_original_exception}
begin
raise AbstractController::ActionNotFound.new
rescue
raise ActionView::Template::Error.new('template')
end
- when "/missing_template"
+ when %r{/missing_template}
raise ActionView::MissingTemplate.new(%w(foo), 'foo/index', %w(foo), false, 'mailer')
- when "/bad_request"
+ when %r{/bad_request}
raise ActionController::BadRequest
- when "/missing_keys"
+ when %r{/missing_keys}
raise ActionController::UrlGenerationError, "No route matches"
- when "/parameter_missing"
+ when %r{/parameter_missing}
raise ActionController::ParameterMissing, :missing_param_key
- when "/original_syntax_error"
+ when %r{/original_syntax_error}
eval 'broke_syntax =' # `eval` need for raise native SyntaxError at runtime
- when "/syntax_error_into_view"
+ when %r{/syntax_error_into_view}
begin
eval 'broke_syntax ='
rescue Exception
@@ -67,7 +67,7 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
{})
raise ActionView::Template::Error.new(template)
end
- when "/framework_raises"
+ when %r{/framework_raises}
method_that_raises
else
raise "puke!"
@@ -75,13 +75,6 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
end
end
- class BoomerAPI < Boomer
- def call(env)
- env['action_dispatch.show_detailed_exceptions'] = @detailed
- raise "puke!"
- end
- end
-
RoutesApp = Struct.new(:routes).new(SharedTestRoutes)
ProductionApp = ActionDispatch::DebugExceptions.new(Boomer.new(false), RoutesApp)
DevelopmentApp = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp)
@@ -212,61 +205,60 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
assert_match(/ActionController::ParameterMissing/, body)
end
- test "rescue with json error for API request" do
+ test "rescue with JSON error for JSON API request" do
@app = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :api)
- get "/", headers: { 'action_dispatch.show_exceptions' => true }
+ get "/", headers: { 'action_dispatch.show_exceptions' => true }, as: :json
assert_response 500
assert_no_match(/<header>/, body)
assert_no_match(/<body>/, body)
assert_equal "application/json", response.content_type
assert_match(/RuntimeError: puke/, body)
- get "/not_found", headers: { 'action_dispatch.show_exceptions' => true }
+ get "/not_found", headers: { 'action_dispatch.show_exceptions' => true }, as: :json
assert_response 404
assert_no_match(/<body>/, body)
assert_equal "application/json", response.content_type
assert_match(/#{AbstractController::ActionNotFound.name}/, body)
- get "/method_not_allowed", headers: { 'action_dispatch.show_exceptions' => true }
+ get "/method_not_allowed", headers: { 'action_dispatch.show_exceptions' => true }, as: :json
assert_response 405
assert_no_match(/<body>/, body)
assert_equal "application/json", response.content_type
assert_match(/ActionController::MethodNotAllowed/, body)
- get "/unknown_http_method", headers: { 'action_dispatch.show_exceptions' => true }
+ get "/unknown_http_method", headers: { 'action_dispatch.show_exceptions' => true }, as: :json
assert_response 405
assert_no_match(/<body>/, body)
assert_equal "application/json", response.content_type
assert_match(/ActionController::UnknownHttpMethod/, body)
- get "/bad_request", headers: { 'action_dispatch.show_exceptions' => true }
+ get "/bad_request", headers: { 'action_dispatch.show_exceptions' => true }, as: :json
assert_response 400
assert_no_match(/<body>/, body)
assert_equal "application/json", response.content_type
assert_match(/ActionController::BadRequest/, body)
- get "/parameter_missing", headers: { 'action_dispatch.show_exceptions' => true }
+ get "/parameter_missing", headers: { 'action_dispatch.show_exceptions' => true }, as: :json
assert_response 400
assert_no_match(/<body>/, body)
assert_equal "application/json", response.content_type
assert_match(/ActionController::ParameterMissing/, body)
end
- test "rescue with json on API request returns only allowed formats or json as a fallback" do
+ test "rescue with HTML format for HTML API request" do
@app = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :api)
- get "/index.json", headers: { 'action_dispatch.show_exceptions' => true }
- assert_response 500
- assert_equal "application/json", response.content_type
- assert_match(/RuntimeError: puke/, body)
-
get "/index.html", headers: { 'action_dispatch.show_exceptions' => true }
assert_response 500
- assert_no_match(/<header>/, body)
- assert_no_match(/<body>/, body)
- assert_equal "application/json", response.content_type
- assert_match(/RuntimeError: puke/, body)
+ assert_match(/<header>/, body)
+ assert_match(/<body>/, body)
+ assert_equal "text/html", response.content_type
+ assert_match(/puke/, body)
+ end
+
+ test "rescue with XML format for XML API requests" do
+ @app = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :api)
get "/index.xml", headers: { 'action_dispatch.show_exceptions' => true }
assert_response 500
@@ -274,6 +266,25 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
assert_match(/RuntimeError: puke/, body)
end
+ test "rescue with JSON format as fallback if API request format is not supported" do
+ begin
+ Mime::Type.register 'text/wibble', :wibble
+
+ ActionDispatch::IntegrationTest.register_encoder(:wibble,
+ param_encoder: -> params { params })
+
+ @app = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :api)
+
+ get "/index", headers: { 'action_dispatch.show_exceptions' => true }, as: :wibble
+ assert_response 500
+ assert_equal "application/json", response.content_type
+ assert_match(/RuntimeError: puke/, body)
+
+ ensure
+ Mime::Type.unregister :wibble
+ end
+ end
+
test "does not show filtered parameters" do
@app = DevelopmentApp
diff --git a/actionpack/test/dispatch/live_response_test.rb b/actionpack/test/dispatch/live_response_test.rb
index e4475f4233..de57c4be1d 100644
--- a/actionpack/test/dispatch/live_response_test.rb
+++ b/actionpack/test/dispatch/live_response_test.rb
@@ -65,7 +65,7 @@ module ActionController
latch = Concurrent::CountDownLatch.new
t = Thread.new {
- @response.stream.each do
+ @response.each do
latch.count_down
end
}
diff --git a/actionpack/test/dispatch/request/session_test.rb b/actionpack/test/dispatch/request/session_test.rb
index 7dcbcc5c21..e022e7e21e 100644
--- a/actionpack/test/dispatch/request/session_test.rb
+++ b/actionpack/test/dispatch/request/session_test.rb
@@ -114,5 +114,31 @@ module ActionDispatch
}.new
end
end
+
+ class SessionIntegrationTest < ActionDispatch::IntegrationTest
+ class MySessionApp
+ def call(env)
+ request = Rack::Request.new(env)
+ request.session['hello'] = 'Hello from MySessionApp!'
+ [ 200, {}, ['Hello from MySessionApp!'] ]
+ end
+ end
+
+ Router = ActionDispatch::Routing::RouteSet.new
+ Router.draw do
+ get '/mysessionapp' => MySessionApp.new
+ end
+
+ def app
+ @app ||= RoutedRackApp.new(Router)
+ end
+
+ def test_session_follows_rack_api_contract_1
+ get '/mysessionapp'
+ assert_response :ok
+ assert_equal 'Hello from MySessionApp!', @response.body
+ assert_equal 'Hello from MySessionApp!', session['hello']
+ end
+ end
end
end
diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb
index a4cb8ce449..8a5d85ab84 100644
--- a/actionpack/test/dispatch/request_test.rb
+++ b/actionpack/test/dispatch/request_test.rb
@@ -358,6 +358,17 @@ class RequestPort < BaseRequestTest
request = stub_request 'HTTP_HOST' => 'www.example.org:8080'
assert_equal ':8080', request.port_string
end
+
+ test "server port" do
+ request = stub_request 'SERVER_PORT' => '8080'
+ assert_equal 8080, request.server_port
+
+ request = stub_request 'SERVER_PORT' => '80'
+ assert_equal 80, request.server_port
+
+ request = stub_request 'SERVER_PORT' => ''
+ assert_equal 0, request.server_port
+ end
end
class RequestPath < BaseRequestTest
@@ -417,6 +428,11 @@ class RequestPath < BaseRequestTest
end
class RequestHost < BaseRequestTest
+ test "host without specifying port" do
+ request = stub_request 'HTTP_HOST' => 'rubyonrails.org'
+ assert_equal "rubyonrails.org", request.host_with_port
+ end
+
test "host with default port" do
request = stub_request 'HTTP_HOST' => 'rubyonrails.org:80'
assert_equal "rubyonrails.org", request.host_with_port
@@ -427,6 +443,21 @@ class RequestHost < BaseRequestTest
assert_equal "rubyonrails.org:81", request.host_with_port
end
+ test "raw without specifying port" do
+ request = stub_request 'HTTP_HOST' => 'rubyonrails.org'
+ assert_equal "rubyonrails.org", request.raw_host_with_port
+ end
+
+ test "raw host with default port" do
+ request = stub_request 'HTTP_HOST' => 'rubyonrails.org:80'
+ assert_equal "rubyonrails.org:80", request.raw_host_with_port
+ end
+
+ test "raw host with non default port" do
+ request = stub_request 'HTTP_HOST' => 'rubyonrails.org:81'
+ assert_equal "rubyonrails.org:81", request.raw_host_with_port
+ end
+
test "proxy request" do
request = stub_request 'HTTP_HOST' => 'glu.ttono.us:80'
assert_equal "glu.ttono.us", request.host_with_port
diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb
index 658e0d004b..aa90433505 100644
--- a/actionpack/test/dispatch/response_test.rb
+++ b/actionpack/test/dispatch/response_test.rb
@@ -37,6 +37,39 @@ class ResponseTest < ActiveSupport::TestCase
assert_equal "closed stream", e.message
end
+ def test_each_isnt_called_if_str_body_is_written
+ # Controller writes and reads response body
+ each_counter = 0
+ @response.body = Object.new.tap {|o| o.singleton_class.send(:define_method, :each) { |&block| each_counter += 1; block.call 'foo' } }
+ @response['X-Foo'] = @response.body
+
+ assert_equal 1, each_counter, "#each was not called once"
+
+ # Build response
+ status, headers, body = @response.to_a
+
+ assert_equal 200, status
+ assert_equal "foo", headers['X-Foo']
+ assert_equal "foo", body.each.to_a.join
+
+ # Show that #each was not called twice
+ assert_equal 1, each_counter, "#each was not called once"
+ end
+
+ def test_set_header_after_read_body_during_action
+ @response.body
+
+ # set header after the action reads back @response.body
+ @response['x-header'] = "Best of all possible worlds."
+
+ # the response can be built.
+ status, headers, body = @response.to_a
+ assert_equal 200, status
+ assert_equal "", body.body
+
+ assert_equal "Best of all possible worlds.", headers['x-header']
+ end
+
def test_read_body_during_action
@response.body = "Hello, World!"
diff --git a/actionpack/test/dispatch/test_request_test.rb b/actionpack/test/dispatch/test_request_test.rb
index 51c469a61a..3c19cbd68a 100644
--- a/actionpack/test/dispatch/test_request_test.rb
+++ b/actionpack/test/dispatch/test_request_test.rb
@@ -88,6 +88,33 @@ class TestRequestTest < ActiveSupport::TestCase
assert_equal 'GoogleBot', req.user_agent
end
+ test "setter methods" do
+ req = ActionDispatch::TestRequest.create({})
+ get = 'GET'
+
+ [
+ 'request_method=', 'host=', 'request_uri=', 'path=', 'if_modified_since=', 'if_none_match=',
+ 'remote_addr=', 'user_agent=', 'accept='
+ ].each do |method|
+ req.send(method, get)
+ end
+
+ req.port = 8080
+ req.accept = 'hello goodbye'
+
+ assert_equal(get, req.get_header('REQUEST_METHOD'))
+ assert_equal(get, req.get_header('HTTP_HOST'))
+ assert_equal(8080, req.get_header('SERVER_PORT'))
+ assert_equal(get, req.get_header('REQUEST_URI'))
+ assert_equal(get, req.get_header('PATH_INFO'))
+ assert_equal(get, req.get_header('HTTP_IF_MODIFIED_SINCE'))
+ assert_equal(get, req.get_header('HTTP_IF_NONE_MATCH'))
+ assert_equal(get, req.get_header('REMOTE_ADDR'))
+ assert_equal(get, req.get_header('HTTP_USER_AGENT'))
+ assert_nil(req.get_header('action_dispatch.request.accepts'))
+ assert_equal('hello goodbye', req.get_header('HTTP_ACCEPT'))
+ end
+
private
def assert_cookies(expected, cookie_jar)
assert_equal(expected, cookie_jar.instance_variable_get("@cookies"))