Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HATEOAS paths are invalid when using an API Gateway in a Spring Boot app

I have two spring boot applications where one of them is acting as an API Gateway (as discussed here Spring Example). The other which is wired into the first one is exposing a profile service using spring-data-rest (spring-data-neo4j-rest).

The first application is starting on port 8080 and is using zuul to route requests to the second as follows:

zuul:
  routes:
    profiles:
      path: /profiles/**
      url: http://localhost:8083/profiles/  

This all works fine and requests to http://localhost:8080/profiles are being served from the second app. The problem though is that the HATEOAS links in the response are incorrect. The response from calling that second service are correct:

{
    "_links": {
        "self": {
            "href": "http://localhost:8083/profiles{?page,size,sort}",
            "templated": true
        },
        "search": {
            "href": "http://localhost:8083/profiles/search"
        }
    },
    "_embedded": {
        "profiles": [
            {
                "name": "Andrew Rutter",
                "_links": {
                    "self": {
                        "href": "http://localhost:8083/profiles/0"
                    }
                }
            },
            {
                "name": "Andrew Rutter",
                "_links": {
                    "self": {
                        "href": "http://localhost:8083/profiles/1"
                    }
                }
            }
        ]
    },
    "page": {
        "size": 20,
        "totalElements": 2,
        "totalPages": 1,
        "number": 0
    }
}

But when this comes back to my API Gateway, the links are being rewritten to

{
  "name": "Andrew Rutter",
  "_links": {
    "self": {
      "href": "http://localhost:8080/profiles/profiles/0"
    }
  }
}

Which is the gateway path alias plus the actual service base Uri. Am I missing a zuul option to disable that behavior and just leave the hateoas uri in place with a host adjustment. Or is there a way for my service behind the gateway to be wired to / rather then the default resource endpoint of /profiles (in this case) which would avoid the undesirable path being added in.

Thanks!

like image 251
Andrew Rutter Avatar asked Jun 01 '15 22:06

Andrew Rutter


People also ask

What is spring boot HATEOAS?

The Spring HATEOAS project is a library of APIs that we can use to easily create REST representations that follow the principle of HATEOAS (Hypertext as the Engine of Application State).

Is Spring cloud gateway an API gateway?

Spring Cloud Gateway provides a library for building API gateways on top of Spring and Java. It provides a flexible way of routing requests based on a number of criteria, as well as focuses on cross-cutting concerns such as security, resiliency, and monitoring.


2 Answers

Zuul or Spring-Cloud adds the "X-Forwarded-Host" header to all the forwarded requests, which Spring-hateoas respects and modifies the links appropriately. To quote from Spring-Cloud docs:

The X-Forwarded-Host header added to the forwarded requests by default. To turn it off set zuul.addProxyHeaders = false. The prefix path is stripped by default, and the request to the backend picks up a header "X-Forwarded-Prefix" ("/myusers" in the examples above).

You can try the recommended fix, which is to set the zuul.addProxyHeaders=false

like image 166
Biju Kunjummen Avatar answered Oct 23 '22 09:10

Biju Kunjummen


I had exactly the same problem. Change your config as follows:

zuul:
  routes:
    profiles:
      path: /profiles/**
      url: http://localhost:8083
      stripPrefix: false

This routes all requests going to the gateway matching "/profiles/**" to your back end server "http://localhost:8083" and leaves the prefix (in your case "/profiles" since that's what matched the route).

like image 23
Alejandro Avatar answered Oct 23 '22 11:10

Alejandro