Spring-hateoas: x-forwarded-host & x-forwarded-prefix headers not working after project upgrade to Spring Boot 2.1

Created on 9 Mar 2019  Â·  25Comments  Â·  Source: spring-projects/spring-hateoas

Had a working project, Spring boot / Spring data rest / Spring Hateos and after upgrade to Spring boot 2.1.3 it appears that x-forwarded-prefix and x-forwarded-host are not longer working. x-forwarded-proto and x-forwarded-port are working fine.

Broke it out into the simplest possible app demo.tar.gz to check and still couldn't get it working.

If I run

http -v GET localhost:8081

the result is

GET / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:8081
User-Agent: HTTPie/0.9.8



HTTP/1.1 200 
Content-Type: application/hal+json;charset=UTF-8
Date: Sat, 09 Mar 2019 18:21:59 GMT
Transfer-Encoding: chunked

{
    "_links": {
        "people": {
            "href": "http://localhost:8081/people{?page,size,sort}",
            "templated": true
        },
        "profile": {
            "href": "http://localhost:8081/profile"
        }
    }
}

all ok so far, however when I try

http -v GET localhost:8081 x-forwarded-proto:https x-forwarded-host:example.com:9090 x-forwarded-port:9090 x-forwarded-prefix:/api

I get

GET / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:8081
User-Agent: HTTPie/0.9.8
x-forwarded-host: example.com:9090
x-forwarded-port: 9090
x-forwarded-prefix: /api
x-forwarded-proto: https



HTTP/1.1 200 
Content-Type: application/hal+json;charset=UTF-8
Date: Sat, 09 Mar 2019 18:23:01 GMT
Transfer-Encoding: chunked

{
    "_links": {
        "people": {
            "href": "https://localhost:9090/people{?page,size,sort}",
            "templated": true
        },
        "profile": {
            "href": "https://localhost:9090/profile"
        }
    }
}

I was expecting the links to be of the form https://example.com:9090/api/profile

Most helpful comment

Okay, a little extra digging has uncovered:

1) Spring Boot doesn't currently support all the X-Forwarded-* stuff through that property setting. The docs only list X-Forwarded-For and X-Forwarded-Proto supported by the existing property. Additionally, there are issues with each container regarding these _de facto_ standard headers. Track Boot's support at => https://github.com/spring-projects/spring-boot/issues/5677

2) That being said, to enable X-Forwarded-* support, add this to your application:

@Bean
ForwardedHeaderFilter forwardedHeaderFilter() {
    return new ForwardedHeaderFilter();
}

...and Spring Boot will pick up the filter bean and register it with your Spring MVC app. (I don't have the WebFlux counterpart here).

3) Once you put in this bean, then you can do stuff like this:

curl -v localhost:8080/employees \
    -H 'X-Forwarded-Host: example.com' \
    -H 'X-Forwarded-Port: 9001'  \
    | jsonpp

...and see...

{
  "_embedded": {
    "employees": [
      {
        "id": 1,
        "name": "Bilbo Baggins",
        "role": "burglar",
        "_links": {
          "self": {
            "href": "http://example.com:9001/employees/1"
          },
          "employees": {
            "href": "http://example.com:9001/employees"
          }
        }
      },
      {
        "id": 2,
        "name": "Frodo Baggins",
        "role": "ring bearer",
        "_links": {
          "self": {
            "href": "http://example.com:9001/employees/2"
          },
          "employees": {
            "href": "http://example.com:9001/employees"
          }
        }
      }
    ]
  },
  "_links": {
    "self": {
      "href": "http://example.com:9001/employees"
    },
    "root": {
      "href": "http://example.com:9001"
    }
  }
}

Bottom line: this should be added to the reference docs so you don't have to dig around in the issues or stackoverflow to get it going.

All 25 comments

Duplicates #753.

But I'm testing with 0.25.1 which fixes 753?

Yup

https://github.com/spring-projects/spring-hateoas/commit/d885cb01dd88ec45e6a22c982dc849dd2d4844b7 is the fix backported to 0.25.x and released in 0.25.1.release.

@gregturn I'm obviously being stoopid here, but if I'm using the fixed code, and x-forwarded-proto is working fine so I am using the fixed code, why am I still seeing issues with x-forwarded-host and x-forwarded-prefix?

Spring Boot now disables forwarded header handler by default. You have to enable it.

Sure I saw that so I used server.use-forward-headers=true to do it.

And it still doesn’t work?

Unless I have done something else wrong, it only half works, proto & port are fine, but host & prefix I can't get to work

Don’t think you can include a port number with x-forwarded-host.

Yh I wondered about that but I think I just copied what I was getting from Spring Cloud Gateway (I'll have a look at that tomorrow and maybe raise something against that project) but with or without the port appended host doesn't work for me

And what I did have was working with Spring Boot 2.0, and associated version of Spring Cloud

To be precise, it's Spring Framework 5.1 and Spring HATEOAS 0.25.1/1.0.0 that requires this shift.

Yes and I my upgrade from Spring Boot 2.0.x to 2.1.3 has picked up Spring Framework 5.1 and Spring HATEOAS 0.25.1 which is when I noticed this issue.

I tried looking at the code and I wonder if it's the use of URIComponentsBuilder rather that the Servlet version that might be the issue as the former seems to still be accessing x-forwarded-* headers directly where the later explicitly mentions the forwarded headers centralisation in 5.1. But I'm no where near sure, just an idea.

Unfortunately, I have the same issue with spring-data-rest. The x-forwarded-prefix was set in the request but spring-data-rest does not render it in the response.

Spring Boot 2.1.3 -> Spring Data Rest Starter

I need to add server.use-forward-headers=true and then only x-forwarded-host (host:port) is rendered in the hypermedia document. If I do not set the property the x-forwarded headers are ignored.

@patbaumgartner did you actually see the host, not just the port, change in the SDR produced JSON after 2.1.3?

@RobMaskell I saw in SDR the host and the port changing. Which is fine. I am missing the x-forwarded-prefix which was not added to the SDR output.

I am using SDR with a Spring Cloud Netfilx Zuul setup and there the prefix was in the past by default the microservice name.

@patbaumgartner
I have had the same problem. The solution was to use the ForwardedHeaderFilter. You have to register it with the @Bean annotation.

@Bean public Filter forwardedHeaderFilter() { return new ForwardedHeaderFilter(); }

https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/web.html#filters-forwarded-headers --> "There are security considerations..."

@GoldenToast well I'll try it but that is what I thought the property I switched on above would do

@GoldenToast this fixed the problem for me, thanks alot!

@GoldenToast Thanks yes manual creation of that bean makes it work.

@gregturn I looked for auto config in Spring Boot, or anything in Spring itself for ForwardedHeaderFilter possibly based off the property server.use-forward-headers and there was nothing. So the question then becomes, in my example why were Proto and Port being changed at all... without the bean it should have been ignoring all the x-forwarded-* headers.

I still think something is slightly wrong here.

Okay, a little extra digging has uncovered:

1) Spring Boot doesn't currently support all the X-Forwarded-* stuff through that property setting. The docs only list X-Forwarded-For and X-Forwarded-Proto supported by the existing property. Additionally, there are issues with each container regarding these _de facto_ standard headers. Track Boot's support at => https://github.com/spring-projects/spring-boot/issues/5677

2) That being said, to enable X-Forwarded-* support, add this to your application:

@Bean
ForwardedHeaderFilter forwardedHeaderFilter() {
    return new ForwardedHeaderFilter();
}

...and Spring Boot will pick up the filter bean and register it with your Spring MVC app. (I don't have the WebFlux counterpart here).

3) Once you put in this bean, then you can do stuff like this:

curl -v localhost:8080/employees \
    -H 'X-Forwarded-Host: example.com' \
    -H 'X-Forwarded-Port: 9001'  \
    | jsonpp

...and see...

{
  "_embedded": {
    "employees": [
      {
        "id": 1,
        "name": "Bilbo Baggins",
        "role": "burglar",
        "_links": {
          "self": {
            "href": "http://example.com:9001/employees/1"
          },
          "employees": {
            "href": "http://example.com:9001/employees"
          }
        }
      },
      {
        "id": 2,
        "name": "Frodo Baggins",
        "role": "ring bearer",
        "_links": {
          "self": {
            "href": "http://example.com:9001/employees/2"
          },
          "employees": {
            "href": "http://example.com:9001/employees"
          }
        }
      }
    ]
  },
  "_links": {
    "self": {
      "href": "http://example.com:9001/employees"
    },
    "root": {
      "href": "http://example.com:9001"
    }
  }
}

Bottom line: this should be added to the reference docs so you don't have to dig around in the issues or stackoverflow to get it going.

x-forwarded-port defo working now as well but fair enough, thanks for the extra investigation, I guess this ticket will help for now

We've added a section to the reference documentation with #886 covering the header forwarding and the setup required to make it work again. Although currently only documented on master – i.e. for 1.0 – this should work on 0.25 as well. Feel free to comment suggestions for enhancements but bear in mind that we want to include as little information as possible as the actualy mechanism of activation is in Spring Framework / Spring Boot and we want to avoid repeating too much of it to avoid the information to diverge.

Does it pass the X-Forwarded-Prefix as it is used by Spring Cloud Netflix
Zuul? This header is not documented.

On Fri, 22 Mar 2019, 17:35 Oliver Drotbohm, notifications@github.com
wrote:

We've added a section to the reference documentation
https://docs.spring.io/spring-hateoas/docs/current-SNAPSHOT/reference/html/#server.link-builder.forwarded-headers
covering the header forwarding and the setup required to make it work
again. Although currently only documented on master – i.e. for 1.0 – this
should work on 0.25 as well. Feel free to comment suggestions for
enhancements but bear in mind that we want to include as little information
as possible as the actualy mechanism of activation is in Spring Framework /
Spring Boot and we want to avoid repeating too much of it to avoid the
information to diverge.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/spring-projects/spring-hateoas/issues/862#issuecomment-475690223,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAY0_DLPyhX97mU-fvqo4AGAwo2x_0BVks5vZQZrgaJpZM4bm1Jk
.

That's on purpose. We don't want to actively document in Spring HATEOAS something maintained in the Spring Framework.

You can open ForwardedHeaderFilter/ForwardedHeaderTransformer in your IDE and see the headers currently supported by Spring Framework.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

odrotbohm picture odrotbohm  Â·  3Comments

odrotbohm picture odrotbohm  Â·  6Comments

ingogriebsch picture ingogriebsch  Â·  6Comments

jbcpollak picture jbcpollak  Â·  8Comments

KenErikson picture KenErikson  Â·  3Comments