spring-projects / spring-hateoas

Spring HATEOAS - Library to support implementing representations for hyper-text driven REST web services.
https://spring.io/projects/spring-hateoas
Apache License 2.0
1.03k stars 475 forks source link

Base URL for ControllerLinkBuilder #516

Open rainerfrey opened 7 years ago

rainerfrey commented 7 years ago

There are several tickets requesting to influence the URLs that the ControllerLinkBuilder creates. I'd like to propose another variation:

I'd like an option to have ControllerLinkBuilder build links with a fixed, configured base URL instead of the information extracted from the servlet request. My use case is having redundant service instances that are accessed by client side load balancing from other services within the same application. I'd like to configure that base URL as an environment property, and in my case use spring.application.name as host name as this is the service name in eureka. There's a bit more context in this Stack Overflow question.

odrotbohm commented 7 years ago

To achieve that you shouldn't have to (even want to) configure stuff in the application explicitly. If your proxy sets thee appropriate headers (X-Forwarded… et al.), Spring HATEOAS will properly generate links for you.

rainerfrey-inxmail commented 7 years ago

In that case, there is no proxy, just client side load balancing with ribbon. The use case is microservice-to-microservice communication within the same deployment environment, and I wouldn't really need a reverse proxy. I could set headers client side when making the requests (that's what I'm doing), but I feel like I shouldn't have to.

Isn't the idea that a service wants to know and link to its own canonical service url that's different from the physical instance address quite logical? To me it seems more flexible than expecting the current physical address to always be the right address to link to.

IMO the choice of both approaches would be a nice improvement for HATEOAS, it is not that essential though as there are ways around.

otrosien commented 7 years ago

+1 for being able to create relative links (it's a valid choice that fwiw doesn't break HATEOAS principles -- if browsers can follow relative links, other clients should be able to do so as well), and being able to use ControllerLinkBuilder outside of the request context.

rainerfrey commented 7 years ago

@olivergierke is there any more feedback I could provide? (seeing the waiting-for-feedback label)

rainerfrey commented 7 years ago

@olivergierke does label unlikely mean, that you are unlikely to spend time to implement this, or also unlikely you'd accept a contribution?

punkstarman commented 7 years ago

In general, I also +1 being able to use ControllerLinkBuilder outside of the request context.

In particular, here is my use-case for needing to set a base URL for ControllerLinkBuilder. In the context of microservices, even though CQRS means that queries and commands have separate pipelines, I don't think that CQRS prohibits code sharing between them. The idea I'm currently running with is to use the same *Resource classes for the REST API and event message content. I would like to include links in the resources no matter which protocol is used. However, event message generation is not always done in the context of a request. Furthermore, one of my colleagues is even floating the idea that event messages could be streamlined to contain just the self link to the resources involved, instead of the whole resource.

I did see @olivergierke 's take on link discovery between services, but I'm not convinced that search resources based on primary or secondary business keys are always possible. Plus, polling seems redundant in a CQRS architecture.

Using X-Forwarded* headers is handy in the presence of a reverse-proxy or gateway, and configuring a default base URL could still work along side this. How about the following behavior:

In the context of microservices fronted by a reverse-proxy or gateway, it seems plausible to assume that no two nodes in the application should use different base URLs in order to contact any third node.

gregturn commented 4 years ago

The original issue was about configuring a Spring HATEOAS application with a base URL. Spring Data REST already provides this, but it's mechanism is rather unique.

The conversation drifted over to relative URLs, which was solved for the use case of making web calls outside an existing one. (See #408).

Back to the subject at hand, which I think is best summarized as "make my links support an '/api' prefix", @odrotbohm is it possible to define some configuration object that that would support both WebMvcLinkBuilder/WebFluxLInkBuilder AND Web MVC/WebFlux?