grails-core icon indicating copy to clipboard operation
grails-core copied to clipboard

GrailsWebRequest.getBaseUrl() returns wrong result when "X-Forwarded-Proto" request header is present

Open ilPittiz opened this issue 9 months ago • 5 comments

Expected Behavior

No response

Actual Behaviour

WebUtils.retrieveGrailsWebRequest().getBaseUrl() does not return a consistent request base URL when:

  • X-Forwarded-Proto request header is defined
  • X-Forwarded-Port request 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

ilPittiz avatar Mar 28 '25 10:03 ilPittiz

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.

jdaugherty avatar Mar 28 '25 15:03 jdaugherty

This code was introduced in 6.1.1 https://github.com/apache/grails-core/pull/13197

jamesfredley avatar Apr 01 '25 17:04 jamesfredley

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.

ilPittiz avatar Apr 03 '25 14:04 ilPittiz

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.

jdaugherty avatar Apr 05 '25 06:04 jdaugherty

Encountered this issue aswell. I shouldn't expect a backport to Grails 6 though, should I?

SimonWoidig avatar May 12 '25 13:05 SimonWoidig

At this time, we have not planned on backporting it unless there is a strong demand.

jdaugherty avatar Jul 06 '25 21:07 jdaugherty