Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redirects in engine routes works strange #7977

Closed
wildchild opened this issue Oct 17, 2012 · 17 comments
Closed

Redirects in engine routes works strange #7977

wildchild opened this issue Oct 17, 2012 · 17 comments
Assignees
Labels

Comments

@wildchild
Copy link
Contributor

Assuming engine routes:

Pages::Engine.routes.draw do
  namespace :admin do
    root to: redirect("/admin/map")

    resource :map
  end
end

And an application:

Rails.application.routes.draw do
  mount Pages::Engine => "/pages"
end

GET "/pages/admin" should redirect to "/pages/admin/map", but redirecting to "/admin/map"

This works in plain rails apps, thus I think, that engines should behave the same way.

@pixeltrix
Copy link
Contributor

Does the following working in a plain application

Rails.application.routes.draw do
  namespace :pages do
    namespace :admin
      root to: redirect("/admin/map")
      resource :map
    end
  end
end

I haven't checked but I think /pages/admin will redirect to /admin/map - can you check this please.

@wildchild
Copy link
Contributor Author

@pixeltrix, yes, it redirects to /admin/map.

@pixeltrix
Copy link
Contributor

The following should work for engine routes:

Pages::Engine.routes.draw do
  namespace :admin do
    root to: redirect do |params, request|
      "#{request.script_name}/admin/map"
    end

    resource :map
  end
end

There's an argument that it should automatically prepend the SCRIPT_NAME to take account of situation where the Rails application is running in a subdirectory on the web server. However this would be a breaking change so it would be Rails 4+ only.

/cc @tenderlove @rafaelfranca @josevalim what do you think? Should we automatically prepend the SCRIPT_NAME by default and require a custom block to break out of it?

@ghost ghost assigned pixeltrix Oct 18, 2012
@wildchild
Copy link
Contributor Author

However this would be a breaking change so it would be Rails 4+ only.

Rails 4 is on the way, what is a decision about it?

@wildchild
Copy link
Contributor Author

@pixeltrix, could you shed some light?

@rafaelfranca
Copy link
Member

@pixeltrix if we automatically prepend the SCRIPT_NAME how will be the block code to remove it?

@pixeltrix
Copy link
Contributor

@rafaelfranca that's the problem - I've got the code and tests to fix this but can't think of a good way to break out of the SCRIPT_NAME constraints.

@JonRowe
Copy link
Contributor

JonRowe commented Sep 22, 2013

Any progress on how to remove the SCRIPT_NAME blocker?

@JonRowe
Copy link
Contributor

JonRowe commented Sep 22, 2013

Although given Rails 4 has shipped, is this now even feasible to change?

@pixeltrix
Copy link
Contributor

@JonRowe it'd be feasible for merging to master but I still don't have a good way of redirecting to a url outside of SCRIPT_NAME so we'd be switching one problem for another. I did think that by restricting it to path redirects and option redirects and requiring a full url for custom redirects would work but on second thoughts it's non-obvious - at least with the current behaviour it's consistent.

One possible solution is to support relative paths so if the redirect returns a url starting with '/' it's treated as an absolute url and 'path/to/action' would have the SCRIPT_NAME prepended - wdyt?

@JonRowe
Copy link
Contributor

JonRowe commented Sep 23, 2013

I think it's kind of counter intuitive to not take account of script_name (even though it's consistent), simply because an engine is designed to be mounted on another endpoint and thus is most likly to want consistent paths relative to it's own root.

However I like the idea of /path generating from the Rails root, and engine/path being relative to the engine. That makes sense as a starting slash means "absolute" path in most interpretations :)

@pixeltrix
Copy link
Contributor

@rafaelfranca wdyt? By using paths starting with a slash to indicate an absolute path then it should be backwards compatible.

@rafaelfranca
Copy link
Member

@pixeltrix I like this approach. 👍 from my side

pixeltrix added a commit that referenced this issue Oct 10, 2013
Example:
    # application routes.rb
    mount BlogEngine => '/blog'

    # engine routes.rb
    get '/admin' => redirect('admin/dashboard')

This now redirects to the path `/blog/admin/dashboard`, whereas before it
would've generated an invalid url because there would be no slash between
the host name and the path. It also allows redirects to work where the
application is deployed to a subdirectory of a website.

Fixes #7977
(cherry picked from commit 9dbd208)

Conflicts:
	actionpack/CHANGELOG.md
@Systho
Copy link

Systho commented Nov 21, 2013

How are we supposed to redirect_to engine root path ? I've tried redirect_to '' and redirect_to '/' but both redirect to app root

@pixeltrix
Copy link
Contributor

I would guess that redirect '' should work - I'll look at fixing it

@pixeltrix pixeltrix reopened this Nov 22, 2013
@vikassy
Copy link

vikassy commented Dec 24, 2013

I think we need to change

path && !path.empty? && path[0] != '/' => path && (path.empty? || path[0] != '/')

in https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/redirection.rb#L58

I tried this out, but I got 1 failing test(i.e test_redirect_hash_with_domain_and_path) where

expected => "http://www.example-documentation.com" and actual => "http://www.example-documentation.com/"

Should that be a problem?? @pixeltrix

pixeltrix added a commit that referenced this issue Jan 1, 2014
Example:

    # application routes.rb
    mount BlogEngine => '/blog'

    # engine routes.rb
    get '/welcome' => redirect('')

This now redirects to the path `/blog`, whereas before it would redirect
to the application root path. In the case of a path redirect or a custom
redirect if the path returned contains a host then the path is treated as
absolute. Similarly for option redirects, if the options hash returned
contains a `:host` or `:domain` key then the path is treated as absolute.

Fixes #7977

(cherry picked from commit b64bac4)
@tmandry
Copy link

tmandry commented Apr 20, 2014

For anyone arriving via Google, the correct code to do this in Rails 3 is

    root(to: redirect do |params, request|
      "#{request.script_name}/admin/map"
    end)

(note the necessary parentheses), or

    root to: redirect { |params, request| "#{request.script_name}/admin/map" }

which I find much cleaner.

tomas-stefano added a commit to ministryofjustice/fb-metadata-presenter that referenced this issue Nov 27, 2020
The editor uses '/services/:service_id/preview' as base url.

The problem redirecting to '/text-first' is that this url doesn't
exist on the editor (only '/services/:service_id/preview/text-first')

Add a suggestion from rails/rails#7977
makes work as expected

also using request.env['PATH_INFO'] works instead of request.path (which
was '/services/:service_id/preview/text-first')
tomas-stefano added a commit to ministryofjustice/fb-metadata-presenter that referenced this issue Dec 1, 2020
There are some caveats of using the request.referer:

  The editor uses '/services/:service_id/preview' as base url.

  The problem redirecting to '/text-first' is that this url doesn't
  exist on the editor (only '/services/:service_id/preview/text-first')

  Adding he request.script_name as suggested here:
  rails/rails#7977 makes the redirection
  to work as expected

Also using request.env['PATH_INFO'] (which is 'text-first'
works instead of request.path (which was
'/services/:service_id/preview/text-first')

I tried to add a current page as hidden field but also has some
drawbacks so I rollback.

Remove spring: This is not need on the dummy app because we don't need t
o dummy app to be quick reloading as we don't often change the app, only
the gem

Now the post request expect a page.url which is the current page.

Example:

You are on the first page and submit the form:

        The app will make a POST /reserved/first-page/answers
        and then redirect to /second-page.

Then when you are on the second page and submit the form:

        The app will make a POST /reserved/second-page/answers
        and then redirect to next page.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants