我使用Spring HATEOAS构建和访问REST服务。该服务使用eureka服务器注册,我使用Ribbon(通过@LoadBalanced RestTemplate
)来调用它。
默认情况下,会对已解析实例的主机名(在Host
标头中)发出请求。这导致Spring HATEOAS中的LinkBuilder为该主机生成链接。当Ribbon发出跟踪链接的请求时,它会尝试再次在eureka中查找链接主机名,当然没有结果。
解决这种情况的最佳水平是什么?收到带有第一个结果的链接后,我想将以下请求直接指向同一个服务实例是可以接受的,我仍然觉得对符号服务名称的所有请求都会更好。
是否可以将Ribbon配置为在Host标头中使用该服务名称发出请求(假设目标服务中没有虚拟主机,这似乎是一个有效的假设)?
否则是否可以在HATEOAS中为链接构建器设置规范的基本URL? (将所有链接定义为完整字符串对我来说是不可接受的)
我现在的解决方案/解决方法是在请求根资源时显式设置X-Forwarded-Host
标头。这有效,但有点冗长和繁琐。
Traverson traverson = new Traverson(URI.create("http://photo-store/"), MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON_UTF8, MediaTypes.HAL_JSON).setRestOperations(imageService);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("X-Forwarded-Host", "photo-store");
String original = this.traverson.follow("image:original").withHeaders(httpHeaders).asTemplatedLink().expand(photoId).getHref();
(旁边的问题:我可以像这样重写Host
标题,还是在Ribbon或RestTemplate中对它进行特殊处理?)
我觉得应该有一个更具声明性或约定或配置的方式来处理这个问题。有吗?
答案 0 :(得分:1)
我也面临同样的问题。我通过添加拦截器来解决它,它为每个请求添加了X-Forwarded-Host标头。
@Bean
@LoadBalanced
RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setInterceptors(singletonList((ClientHttpRequestInterceptor) (request, body, execution) -> {
request.getHeaders().add("X-Forwarded-Host", request.getURI().getHost());
return execution.execute(request, body);
}));
return restTemplate;
}
答案 1 :(得分:0)
我正在使用我自己的linkBuilder,它从属性中获取服务的名称并将其用作主机名。这是非常基本的,但是易于使用和实现。如果您想使用整个春季的风俗链接发现魔术酱,则需要做更多的事情。但是现在我正在寻找自己更适合Spring Hateoas 1.x的解决方案,所以也许我很快就会找到一个更好的答案。
快速而肮脏的方式:
@Component
public class MyLinkBuilder {
@Value("${spring.application.name}")
private String servicename;
public Link getLink(String path) {
String root = "http://" + servicename;
return new Link(root + path);
}
public Link getLink(String path, String rel) {
return getLink(path, LinkRelation.of(rel));
}
public Link getLink(String path, LinkRelation rel) {
String root = "http://" + servicename;
return new Link(root + path, rel);
}
}