0

I am working on Spring Cloud and using the sample project by Josh Long at

Bootiful Microservice by Josh Long

There is an API gateway reservation-client which consumes data from the service reservation-service which provides a HATEOAS response, which then is converted to a simple JSON response.

@RestController
@RequestMapping("/reservations")
class ReservationApiGateway {

Method:

@HystrixCommand(fallbackMethod = "fallback")
@RequestMapping(method = RequestMethod.GET, value = "/names")
public Collection<String> names() {
    return this.reservationReader
            .read()
            .getContent()
            .stream()
            .map(Reservation::getReservationName)
            .collect(Collectors.toList());
}

I modify it to forward me the HATEOAS response like this.

@HystrixCommand(fallbackMethod = "fallback")
@RequestMapping(method = RequestMethod.GET, value = "/names")
public Resources<Resource<Reservation>> names() {
    return this.reservationReader
            .read();
}

This is giving me a HATEAOS response, but the links are all from the reservation-service - .

  "_links" : {

    "self" : {

      "href" : "**http://192.168.0.3:7000/reservations/1**"

    },

    "reservation" : {

      "href" : "http://192.168.0.3:7000/reservations/1"

    }

  }

How do I make sure Feign updates the links to the server and port of the API Gateway? - http://192.168.0.3:9999/reservations/1

Same response from reservation-client(same as reservation-service):

{

  "_embedded" : {

    "reservations" : [ {

      "reservationName" : "Josh",

      "_links" : {

        "self" : {

          "href" : "http://192.168.0.3:7000/reservations/1"

        },

        "reservation" : {

          "href" : "http://192.168.0.3:7000/reservations/1"

        }

      }

    }, {

      "reservationName" : "Dr. Johnson",

      "_links" : {

        "self" : {

          "href" : "http://192.168.0.3:7000/reservations/2"

        },

        "reservation" : {

          "href" : "http://192.168.0.3:7000/reservations/2"

        }

      }

    }, {

      "reservationName" : "Dr. Syer",

      "_links" : {

        "self" : {

          "href" : "http://192.168.0.3:7000/reservations/3"

        },

        "reservation" : {

          "href" : "http://192.168.0.3:7000/reservations/3"

        }

      }

    }, {

      "reservationName" : "Dr. Pollack",

      "_links" : {

        "self" : {

          "href" : "http://192.168.0.3:7000/reservations/4"

        },

        "reservation" : {

          "href" : "http://192.168.0.3:7000/reservations/4"

        }

      }

    } ]

  },

  "_links" : {

    "self" : {

      "href" : "http://192.168.0.3:7000/reservations{?page,size,sort}",

      "templated" : true

    },

    "profile" : {

      "href" : "http://192.168.0.3:7000/profile/reservations"

    },

    "search" : {

      "href" : "http://192.168.0.3:7000/reservations/search"

    }

  }

}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Anoop Hallimala
  • 625
  • 1
  • 11
  • 25

1 Answers1

0

I figured it out.

The solution was in the X-Forwarded-Host http header. X-Forwarded-Host essentially tells Spring that any HATEOS response which has this header, the host and port information in the links should be updated to what is mentioned in the X-Forwarded-Host http header.

So, in the API Gateway reservation-client code, I added this snippet which intercepts Feign's call to the backend service reservation-service and adds the http header to the request.

@Component
class LanguageRequestInterceptor implements RequestInterceptor {
    private static final String X_FORWARDED_HOST = "X-Forwarded-Host";

    @Override
    public void apply(RequestTemplate requestTemplate) {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            return;
        }
        HttpServletRequest request = requestAttributes.getRequest();
        if (request == null) {
            return;
        }

        requestTemplate.header(X_FORWARDED_HOST, "localhost:9999");
    }
}

Now, all the HATOES response has the host and port information of the API Gateway, not the backend HATEOS service.

Anoop Hallimala
  • 625
  • 1
  • 11
  • 25