3

In a controller I attempt to do

redirect_to @url

@url is an https url which is correctly formatted

When I do it nothing happens in the browser

Logs show that there is a redirection, but in chrome inspect I see

Request URL:https://..myurl...
Request Headers CAUTION: Provisional headers are shown.
Origin:http://localhost:3000
Referer:http://localhost:3000/cars/105
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36
Query String Parametersview sourceview URL encoded
tId:6f6bfeaf-fd47-42ae-8e43-6b7118d21b0b

The network tab shows that it was canceled..

Am I missing something? Why isn't the redirection happening?

Nick Ginanto
  • 31,090
  • 47
  • 134
  • 244

7 Answers7

1

Based on your statement that you saw the request was canceled in the network tab in Chrome, it sounds like you're trying to do this in an AJAX request. Cross-domain AJAX requests are not supported by default. If you have control over the https://..myurl... application, you can implement CORS or JSONP.

Edit

A third approach, which is what you mentioned doing in one of your comments, is to get around the restriction on cross-site redirects for AJAX requests by redirecting on the client side, after the AJAX request completes (by setting window.location). However, if your ultimate goal is to have the redirect happen transparently—as part of the AJAX request rather than after it—you will need to implement CORS or JSONP.

Community
  • 1
  • 1
Charles Treatman
  • 558
  • 3
  • 14
  • He said in a comment below that his request only work when he add remote: true – khaled_gomaa Mar 28 '14 at 09:21
  • More specifically, he said he added `remote: true` and then set `window.location` after receiving the response. In other words, he got around the cross-origin AJAX redirect issue by redirecting on the client side after the AJAX request completed. – Charles Treatman Mar 28 '14 at 15:00
  • 2
    Yes, basically the only thing that worked is doing a `remote: true` and manually setting `window.location`. From my searches, redirect_to @external_url should work, without the need to use CORS or JSONP – Nick Ginanto Mar 29 '14 at 14:48
  • 1
    What documentation have you found to indicate that an AJAX request can redirect to a different domain without CORS or JSONP (or without building a local proxy of the external URL within your application)? – Charles Treatman Mar 29 '14 at 18:48
  • 1
    my problem is that he never mentions he is trying to make an ajax request? What i got is he is trying to make normal redirect work. – khaled_gomaa Mar 29 '14 at 23:01
  • He mentioned monitoring the request in the network tab of chrome dev tools. Also, the solution he ended up with points to cross-domain AJAX as the original culprit. – Charles Treatman Mar 30 '14 at 14:58
  • The reason the mention of the network tab in Chrome dev tools is important is because that tab only shows async requests; synchronous requests (such as a link click or a form submission) do not show up in that tab. – Charles Treatman Mar 31 '14 at 18:22
0

Can you visit the page and see it in Chrome without any security warnings?

I've had css etc. not load because I was requesting it via https to a local server with a unverified certificate. It's possible Chrome is checking behind the scenes before going to the url but I don't know that for sure.

Try redirect_to https://www.google.com and see if that works.

achedeuzot
  • 4,164
  • 4
  • 41
  • 56
chrismcg
  • 1,286
  • 7
  • 11
0

I think you need to specify that the protocol you want to use is using SSL. The ActionController::Base#redirect_to method takes an options hash, one of the parameters of which is :protocol which allows you to define:

redirect_to :protocol => 'https://'

If all of your redirects are going to be done via SSL it would make sense to put this in a before_action in your controller. You could define a method like:

def redirect_via_https
  redirect_to :protocol => "https://" unless (request.ssl? || request.local?)
end

And add this to your controller:

class SpecificController
    before_action :redirect_via_https
end
Severin
  • 8,508
  • 14
  • 68
  • 117
  • That protocol option is not needed (Net::HTTP is the only class I know of requiring this). There are also `:host` and `:port` and all 3 are getting passed to `url_for`. This can be dangerous when using `params.merge` see http://blog.bmonkeys.net/2014/be-careful-with-params-merge – 2called-chaos Mar 26 '14 at 15:09
  • Also if you want to enforce SSL on _your_ page you can use Rails' [ForceSSL](http://api.rubyonrails.org/classes/ActionController/ForceSSL/ClassMethods.html) – 2called-chaos Mar 26 '14 at 15:16
0

what is your rails version, because redirect_to method is working for external urls.

class HomeController < ApplicationController
  def index
  @url = "https://facebook.com"
  redirect_to @url
end

It works.

Sourabh Upadhyay
  • 1,034
  • 11
  • 31
0

After searching a while on (CAUTION: Provisional headers are shown) I think it is related to some chrome extensions such as ad blocker or net-internals Quoting another stackoverflow question"The message is there because the request to retrieve that resource was never made, so the headers being shown are not the real thing. As explained in the issue you referenced, the real headers are updated when the server responds, but there is no response if the request was blocked."

You can make sure that all the extension that are capable of blocking requests are disabled and try it again.

Community
  • 1
  • 1
khaled_gomaa
  • 3,382
  • 21
  • 24
  • i see you have it in different apps and that supports my theory more i actually tried it while having my ad blocker and it did the same behavior – khaled_gomaa Mar 27 '14 at 15:58
0

I would suggest several troubleshooting steps:

  • Try another browser (Safari, Firefox), if it works on that browser, then perhaps a Chrome extension is blocking your visiting that redirected URL.
  • Try redirecting to other URLs, try both with and without https.
  • Check if your Rails action is an AJAX call or not. If it's an ajax request then redirect_to wouldn't work.
James Chen
  • 10,794
  • 1
  • 41
  • 38
0

I think that the suspicions around AJAX are well founded. It's really hard to guess at what might be going on, given the narrow view into your application that we are presented with. Try changing

redirect_to @url

to

if request.xhr?
  render :update do |page|
    page.redirect_to @url
  end
else
  redirect_to @url
end

Also, as an aside, @url probably has excessive scope, given the redirect. You can most likely use url just as effectively.

Edit:

In light of information I previously overlooked, I am certain that the previous solution will correct the issue. Basically, some browsers are stricter about how they handle responses to xhr requests. With a standard redirect_to, you can potentially send a "regular" response for a xhr request. This can happen even if you have a *.js.rjs or *.js.erb that would typically contain the redirect code, as the redirect_to call will prevent that code from even being executed. If you have an app that has js that gracefully degrades, there is a likelihood that you will end up running into this issue sooner or later, as you appear to have a couple of times. I've found a couple of good ways to handle the basic issue.

Option 1:

One way is to simply adjust the redirect to look like this: redirect_to( @url ) unless request.xhr?, and then add the appropriate redirection logic to your *.js.erb file. This method is nice if you have additional javascript that needs to be run, in addition to the redirect.

Option 2:

Another solution that works well is to add something like this to your application controller:

def redirect_to(args)
  if request.xhr?
    render js: "window.location = '#{ _compute_redirect_to_location args }'"
  else
    super args
  end
end

This is nice, because you don't need to sift through and modify your existing code, it just starts working everywhere. The other nice thing is that you can still qualify the redirect as the previous option, to allow for more complex javascript. You can even go crazy and add some additional application specific options, like a flash message, if you want to further extend the method and really make it work for you.

Option 3:

If you're not down with overriding existing methods, you could add something like:

def firm_redirect_to(url)
  if request.xhr?
    render js: "window.location = '#{ url }'"
  else
    redirect_to url
  end
end

But then you have to modify all of your code.

I personally prefer a variation of option 2... Anyway, hope this helps - good luck.

Brad Werth
  • 17,411
  • 10
  • 63
  • 88
  • You may find this interesting, as well - http://stackoverflow.com/questions/21177387/caution-provisional-headers-are-shown-in-chrome-debugger. – Brad Werth Mar 30 '14 at 04:40
  • It's worth noting that this is effectively the solution @NickGinanto ended up with, just written in a more "Railsy" way; `page.redirect_to` writes javascript to the page that sets `window.location.href` on the client side. – Charles Treatman Mar 30 '14 at 16:19
  • @Charles - Thanks for pointing that out, I suspected that was what was going on, but I previously overlooked the comment from NickGinanto basically confirming as much. I have expanded the answer in light of that information. – Brad Werth Mar 31 '14 at 08:27
  • And this is about the most "Railsy" way I have been able to think of to handle it... – Brad Werth Mar 31 '14 at 08:28