Grails 2.3.6+Nginx多域名部署重定向端口异常问题咨询
解决Grails 2.3.6+Nginx多域名场景下重定向/绝对链接带错误80端口的问题
你遇到的这个问题其实是反向代理场景下Grails无法正确识别用户实际访问的协议和端口导致的——因为Nginx把请求转发给Grails时,用的是内部端口(比如8080),而Grails默认会用这个内部端口生成绝对链接或重定向地址,就出现了{correctUrl}:80/myaction这种错误。下面给你几个针对性的解决步骤:
第一步:配置Nginx传递正确的请求头
首先要让Nginx把用户实际访问的协议、端口和域名传递给Grails,修改你的Nginx代理配置,在location块里添加以下配置:
# 传递实际访问的协议(http/https) proxy_set_header X-Forwarded-Proto $scheme; # 传递实际访问的端口 proxy_set_header X-Forwarded-Port $server_port; # 传递完整的域名(确保Grails拿到正确的多域名) proxy_set_header Host $host; # 转发请求到你的Grails应用(这里假设Grails跑在本地8080端口) proxy_pass http://127.0.0.1:8080;
这些头信息是让Grails感知用户真实访问环境的关键。
第二步:修改Grails配置,动态生成正确的serverURL
因为你移除了固定的grails.serverUrl,现在需要让Grails根据Nginx传递的头信息动态生成正确的服务器地址。在grails-app/conf/Config.groovy的生产环境配置块里添加以下代码:
environments { production { grails.serverURL = { def webRequest = org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequest.lookup() if (webRequest) { def request = webRequest.request // 优先用Nginx传递的协议, fallback到请求自身的scheme def scheme = request.getHeader('X-Forwarded-Proto') ?: request.scheme def serverName = request.serverName // 优先用Nginx传递的端口, fallback到请求自身的端口 def serverPort = request.getHeader('X-Forwarded-Port') ?: request.serverPort.toString() // 处理默认端口:http的80、https的443不需要显式在URL里写端口 def portSuffix = (scheme == 'http' && serverPort == '80') || (scheme == 'https' && serverPort == '443') ? '' : ":$serverPort" return "$scheme://$serverName$portSuffix" } // 启动时没有请求的 fallback 地址(可以根据你的需求修改) return "http://your-default-domain.com" }() } }
这段代码会在每次请求时动态计算正确的serverURL,完美适配多域名场景。
第三步:(可选)用过滤器修正请求属性
如果上面的配置还是有问题,可以在Grails里写一个全局过滤器,直接修正请求的协议和端口属性,让Grails的URL生成工具直接使用正确的值。在grails-app/conf/Filters.groovy里添加:
class ProxyHeaderFilters { def filters = { all(controller: '*', action: '*') { before = { def forwardedProto = request.getHeader('X-Forwarded-Proto') def forwardedPort = request.getHeader('X-Forwarded-Port') // 修正请求的协议 if (forwardedProto) { request.metaClass.scheme = forwardedProto } // 修正请求的端口 if (forwardedPort) { request.metaClass.serverPort = forwardedPort.toInteger() } } } } }
这个过滤器会在所有请求处理前,把Nginx传递的协议和端口绑定到当前请求对象上,这样createLink(absolute: true)或者redirect方法生成的地址就会自动使用正确的端口了。
验证效果
配置完成后重启Nginx和Grails应用,测试以下场景:
- 调用
redirect(uri: '/test', absolute: true),看是否跳转到正确的域名+路径(不带错误的80端口) - 渲染页面时使用
createLink(controller: 'home', action: 'index', absolute: true),检查生成的URL是否符合预期
内容的提问来源于stack exchange,提问作者sullivan
相关产品推荐
相关产品推荐

