【问题标题】:Redirecting to an external URL with Rails doesn't work使用 Rails 重定向到外部 URL 不起作用
【发布时间】:2014-02-05 01:03:46
【问题描述】:

在控制器中我尝试做

redirect_to @url

@url 是一个格式正确的 https url

当我这样做时,浏览器中什么也没有发生

日志显示有重定向,但在 chrome 检查中我看到了

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

网络标签显示它被取消了..

我错过了什么吗?为什么没有发生重定向?

【问题讨论】:

  • 如果添加状态码会怎样?像redirect_to url,状态:301
  • 仍然不起作用.. Chrome 检查以红色显示重定向并说它已取消..
  • Ajax 还是标准请求?
  • 如果你复制粘贴新标签中的 url 是否有效?
  • curl -I your_url.com 的输出是什么?

标签: ruby-on-rails ruby-on-rails-3 redirect


【解决方案1】:

根据您在 Chrome 的网络选项卡中看到请求已取消的声明,听起来您正试图在 AJAX 请求中执行此操作。默认不支持跨域 AJAX 请求。如果您可以控制https://..myurl... 应用程序,则可以实现CORSJSONP

编辑

第三种方法,也就是您在其中一个 cmets 中提到的做法,是通过在 AJAX 之后 AJAX 客户端重定向来绕过对 AJAX 请求的跨站点重定向的限制请求完成(通过设置window.location)。但是,如果您的最终目标是让重定向透明地发生(作为 AJAX 请求的一部分而不是在它之后),您将需要实现 CORS 或 JSONP。

【讨论】:

  • 他在下面的评论中说他的请求只有在他添加远程时才有效:true
  • 更具体地说,他说他在收到回复后添加了remote: true,然后设置了window.location。换句话说,他通过在 AJAX 请求完成后在客户端进行重定向来解决跨域 AJAX 重定向问题。
  • 是的,基本上唯一有效的方法是执行remote: true 并手动设置window.location。根据我的搜索,redirect_to @external_url 应该可以工作,无需使用 CORS 或 JSONP
  • 您发现哪些文档表明 AJAX 请求可以在没有 CORS 或 JSONP 的情况下重定向到不同的域(或者无需在您的应用程序中构建外部 URL 的本地代理)?
  • 我的问题是他从来没有提到他正在尝试发出 ajax 请求?我得到的是他正试图使正常的重定向工作。
【解决方案2】:

搜索一段时间后(注意:显示临时标题) 我认为这与某些 chrome 扩展有关,例如广告拦截器或 net-internals 引用another stackoverflow question“该消息存在是因为从未发出检索该资源的请求,因此显示的标头不是真实的。正如您引用的问题中所述,真实的标头在服务器响应时更新,但是如果请求被阻止,则没有响应。”

您可以确保所有能够阻止请求的扩展程序都被禁用,然后再试一次。

【讨论】:

  • 我看到你在不同的应用程序中都有它,这支持了我的理论,我实际上在使用广告拦截器时尝试过它,它的行为相同
【解决方案3】:

我认为您需要指定您要使用的协议是使用 SSL。 ActionController::Base#redirect_to 方法采用选项哈希,其中一个参数是 :protocol,它允许您定义:

redirect_to :protocol => 'https://'

如果您的所有重定向都将通过 SSL 完成,则将其放在控制器中的 before_action 中是有意义的。您可以定义如下方法:

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

并将其添加到您的控制器中:

class SpecificController
    before_action :redirect_via_https
end

【讨论】:

  • 不需要那个协议选项(Net::HTTP 是我知道的唯一需要这个的类)。还有:host:port,所有3 个都被传递给url_for。这在使用params.merge 时可能很危险,请参阅blog.bmonkeys.net/2014/be-careful-with-params-merge
  • 另外,如果你想在 your 页面上强制实施 SSL,你可以使用 Rails 的ForceSSL
【解决方案4】:

您可以在没有任何安全警告的情况下访问该页面并在 Chrome 中查看它吗?

我没有加载 css 等,因为我通过 https 向带有未经验证证书的本地服务器请求它。 Chrome 可能会在访问 url 之前在幕后进行检查,但我不确定。

尝试 redirect_to https://www.google.com 看看是否可行。

【讨论】:

    【解决方案5】:

    你的 rails 版本是什么,因为 redirect_to 方法适用于外部 url。

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

    有效。

    【讨论】:

    • 是的,我知道它有效,但不适合我。请查看问题 - 日志显示存在重定向。
    • 有什么特别的吗?它漂亮的香草
    • 这是否也在 Firefox 或 IE 中复制?
    【解决方案6】:

    我会建议几个故障排除步骤:

    • 尝试其他浏览器(Safari、Firefox),如果它在该浏览器上运行,则可能是 Chrome 扩展程序阻止了您访问该重定向 URL。
    • 尝试重定向到其他 URL,尝试使用和不使用 https。
    • 检查您的 Rails 操作是否为 AJAX 调用。如果是 ajax 请求,那么 redirect_to 将不起作用。

    【讨论】:

      【解决方案7】:

      我认为围绕 AJAX 的怀疑是有根据的。考虑到我们呈现给您的应用程序的狭隘观点,真的很难猜测可能会发生什么。尝试改变

      redirect_to @url
      

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

      另外,顺便说一句,考虑到重定向,@url 可能具有过多的范围。您很可能可以同样有效地使用url

      编辑:

      根据我之前忽略的信息,我确信之前的解决方案可以解决问题。基本上,一些浏览器对如何处理对 xhr 请求的响应更加严格。使用标准的 redirect_to,您可以潜在地为 xhr 请求发送“常规”响应。即使您有一个通常包含重定向代码的 *.js.rjs 或 *.js.erb 也会发生这种情况,因为 redirect_to 调用甚至会阻止该代码被执行。如果您的应用程序的 js 可以优雅地降级,那么您迟早会遇到这个问题,因为您似乎遇到过几次。我找到了几种处理基本问题的好方法。

      选项 1:

      一种方法是简单地将重定向调整为如下所示:redirect_to( @url ) unless request.xhr?,然后将适当的重定向逻辑添加到您的 *.js.erb 文件中。如果除了重定向之外还需要运行其他 javascript,则此方法很好。

      选项 2:

      另一个行之有效的解决方案是在您的应用程序控制器中添加类似这样的内容:

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

      这很好,因为您不需要筛选和修改现有代码,它可以在任何地方开始工作。另一个好处是您仍然可以将重定向限定为前一个选项,以允许更复杂的 javascript。如果您想进一步扩展该方法并使其真正为您工作,您甚至可以发疯并添加一些额外的应用程序特定选项,例如一条消息。

      选项 3:

      如果您不介意覆盖现有方法,您可以添加如下内容:

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

      但是您必须修改所有代码。

      我个人更喜欢选项 2 的变体...无论如何,希望这会有所帮助 - 祝你好运。

      【讨论】:

      • 您可能也会觉得这很有趣 - stackoverflow.com/questions/21177387/…
      • 值得注意的是,这实际上是@NickGinanto 最终得到的解决方案,只是以更“Railsy”的方式编写; page.redirect_to 将 javascript 写入在客户端设置 window.location.href 的页面。
      • @Charles - 感谢您指出这一点,我怀疑这是怎么回事,但我之前忽略了 NickGinanto 的评论,基本上证实了这一点。我根据这些信息扩展了答案。
      • 这是我能想到的最“Railsy”的处理方式......
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-05
      • 1970-01-01
      • 1970-01-01
      • 2016-05-24
      • 2012-10-01
      • 2014-08-30
      相关资源
      最近更新 更多