Grails重定向 - 为什么它总是绝对的?

时间:2011-03-08 18:37:03

标签: grails redirect https reverse-proxy

我有两个Jetty AppServers在Apache 2.2反向代理后面运行Grails Web App。 SSL终止由apach完成,他们将HTTP传递给Jetty AppServers。

当Grails Web应用程序执行如此重定向时

redirect(action:'index')

最终用户收到带有完整网址的HTTP 302重定向请求,该网址使用的是 http:// 协议,而不是 https://

HTTP/1.1 302 Found
Date: Tue, 08 Mar 2011 17:50:46 GMT
Server: Jetty(6.1.17)
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Location: http://hostname.domain/web/?lang=en

这很烦人,因为所有HTTP请求都被代理捕获并重定向到HTTPS请求。所以这是一次不必要的往返。

我看到两个解决方案:

  1. Apache的mod_proxy可以在将响应传递给用户之前将该Location-header重写为https://。 (可以吗?)
  2. 重定向时,Grails可能根本不使用绝对URL:Location: /web/?lang=en
  3. 我认为第一个选择有点愚蠢,对吧?

    您是否知道我如何能够发送grails来发送非绝对重定向标头(理想情况下无需切换每个重定向以使用uri:)?

    编辑目前我通过修改响应标头(a2enmod headers)在第一种方法之后找到解决方法,然后在Header edit Location ^http://(.*)$ https://$1中添加<Location> 。灵感来自this serverfault post。我仍然想知道为什么这首先是必要的。

2 个答案:

答案 0 :(得分:6)

302 redirects are required by the HTTP 1.1 RFC to be absolute,而不是相对位置。即使它在某些浏览器中有效,但这些都超出了规范,我确信如果你做了一个相对网址,某些实现将无法正常工作。

您遇到此问题的原因是因为SSL终止发生在apache上,而apache正在向Jetty发出一个vanilla HTTP请求。所以Jetty正在获得一个非常的非HTTPS请求,所以它不知道发送HTTPS响应,而不是常规的HTTP响应。如果您在Jetty中进行SSL终止,则不会出现问题(但Jetty在SSL终止时效果不佳)。

我们已经在我们的应用程序(apache / HA Proxy-&gt; Tomcat)中处理了这个问题,因为它具有硬编码响应协议的每个环境配置值(无论如何我们都需要弄乱网址,因为它是一个多租户系统有许多潜在的主机名,长篇故事...... :),但你的apache解决方案也适用。

答案 1 :(得分:0)

这个问题已经有将近 10 年的历史了。从那时起,规范已在 RFC 7231, section 7.1.2 中更新。现在允许 Location 标头中的相对引用:

<块引用>

当 [Location] 具有 相对引用([RFC3986], Section 4.2)的形式,最终 值是通过根据有效的请求 URI 解析它来计算的 ([RFC3986], Section 5)。

Grails 支持这种类型的重定向,但您在重定向时必须应用额外的 absolute: false 参数:

redirect action: 'index', absolute: false

注意:在撰写本文时,此功能(尚)不支持 servlet 上下文路径,请参阅 grails-core issue #11673