GrailsWebRequest.getBaseUrl() returns wrong result when "X-Forwarded-Proto" request header is present
Expected Behavior
No response
Actual Behaviour
WebUtils.retrieveGrailsWebRequest().getBaseUrl() does not return a consistent request base URL when:
X-Forwarded-Protorequest header is definedX-Forwarded-Portrequest header is not defined
Steps To Reproduce
Example:
curl -H 'X-Forwarded-Proto: https' https://my.domain.com/path
MyController.groovy
def debug() {
println WebUtils.retrieveGrailsWebRequest().getBaseUrl()
}
Output:
https://my.domain.com:null
There's an ambiguous logical expression at https://github.com/apache/grails-core/blob/13617a4a4a78894146f6b3b85b15e1a52e29c5b8/grails-web-common/src/main/groovy/org/grails/web/servlet/mvc/GrailsWebRequest.java#L475-L479 where
forwardedScheme= "https"forwardedPort= null
The if statement is in the form of A && B || C, while it should be A && (B || C), as forwardedPort is indeed null.
Environment Information
Not relevant
Example Application
No response
Version
Issue found on Grails 6.x
Can you please provide a sample application? There are numerous configuration settings in spring that control the proxy behavior & headers. A sample application would make sure we address this issue properly.
This code was introduced in 6.1.1 https://github.com/apache/grails-core/pull/13197
Sorry for the late feedback. Here's a small sample app, created via Grails Application Forge and edited to remove all overabundant dependencies: https://github.com/ilPittiz/GrailsWebRequest-baseUrl
To replicate the issue, run the app and execute
curl -H 'X-Forwarded-Proto: https' http://localhost:8080
It'll print as result
http://localhost:null
We identified this bug right after our IT team moved all microservices to Cloudfare CDN, that by default adds X-Forwarded-Proto header to all requests, while does not add X-Forwarded-Port header.
As a work around, you could add a filter to remove the header prior to the GrailsWebRequest creation.
I'll see about fixing this in 7.x.
Encountered this issue aswell. I shouldn't expect a backport to Grails 6 though, should I?
At this time, we have not planned on backporting it unless there is a strong demand.