简体   繁体   English

从 Spring Boot 1.5.9 升级到 2.2.6 时,HATEOAS 链接中未考虑上下文路径

[英]Context Path not considered in HATEOAS links when upgrading from Spring Boot 1.5.9 to 2.2.6

I have recently upgraded an older application, based on Spring Boot, from version 1.5.9 to 2.2.6.我最近将基于 Spring Boot 的旧应用程序从版本 1.5.9 升级到 2.2.6。

Unfortunately, after upgrading, the urls generated with HATEOAS are changed.不幸的是,升级后,使用 HATEOAS 生成的 url 发生了变化。 Basically the context-path is missing from the Links now.基本上,现在链接中缺少上下文路径。

Example:例子:

Before: https://domain.test.com/service/api/endpoint
Now:    https://domain.test.com/service/endpoint

Right now I am using the following configs in application properties:现在我在应用程序属性中使用以下配置:

server.servlet.context-path: /api
server.forward-headers-strategy: FRAMEWORK
spring.data.rest.basePath: /api

(With none, the host is totally different(because of the x-forwarded-host. I have also tried with native, but same behavior) (没有,主机完全不同(因为x-forwarded-host。我也尝试过使用本机,但行为相同)

I have also created a ForwardedHeaderFilter bean.我还创建了一个ForwardedHeaderFilter bean。

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

Is there anything I can do to bypass this issue?我能做些什么来绕过这个问题吗? Am I doing something wrong?难道我做错了什么?

One alternative would be to adjust the api gateway, but this would be really complicated from a business process perspective so I would prefer a more technical approach.一种替代方法是调整 api 网关,但从业务流程的角度来看,这将非常复杂,因此我更喜欢技术性更强的方法。

Thank you !谢谢 !

As a temporary solution, until I have time to really take a deeper look, I have created a new Utility class, that takes care of adjusting the path:作为临时解决方案,在我有时间真正深入了解之前,我创建了一个新的实用程序 class,负责调整路径:

public class LinkUtil {
    private LinkUtil() {
    }

    @SneakyThrows
    public static <T> Link linkTo(T methodOn) {
        String rawPath = WebMvcLinkBuilder.linkTo(methodOn).toUri().getRawPath();
        rawPath = StringUtils.remove(rawPath, "/service");
        BasicLinkBuilder basicUri = BasicLinkBuilder.linkToCurrentMapping().slash("/api").slash(rawPath);

        return new Link(basicUri.toString());
    }
}

Where /api is the context-path.其中/api是上下文路径。

Then I use it like this:然后我像这样使用它:

Link whateverLink = LinkUtil.linkTo(methodOn(WhateverClass.class).whateverMethod(null)).withRel("whatever-rel));

@LoolKovski's temporary solution relies on an existing ServletRequest because of #linkToCurrentMapping.由于#linkToCurrentMapping,@LoolKovski 的临时解决方案依赖于现有的 ServletRequest。 Use the following code if you, too, need to eliminate that restriction:如果您也需要消除该限制,请使用以下代码:

public class LinkUtil {
    private LinkUtil() {
    }

    @SneakyThrows
    public static <T> Link linkTo(T methodOn) {
        var originalLink = WebMvcLinkBuilder.linkTo(methodOn);
        var rawPathWO = StringUtils.remove(originalLink.toUri().getRawPath(), "/service");
        return originalLink.withHref("/api" + rawPathWO);
    }
}

Actually, in my case the links are generated during one of the RestController beans' initialization, so my real code looks like the following code.实际上,在我的例子中,链接是在 RestController bean 的一个初始化期间生成的,所以我的真实代码看起来像下面的代码。 I don't need to cut-off some other path part before but only need to prepend a configured context path.我之前不需要切断其他路径部分,只需要预先配置一个配置的上下文路径。

@RestController
public class ExampleController implements ServletContextAware {

@Override
public void setServletContext(ServletContext servletContext) {
    final var executor = Executors.newSingleThreadExecutor();
    executor.submit(() -> {
        someRepository.getExamples().forEach((name, thing) -> {
            Link withRel = linkTo(methodOn(ExampleController.class).getElement(null, name, null))
                    .withSelfRel();
            withRel = withRel.withHref(servletContext.getContextPath() + withRel.toUri().getRawPath());
            thing.add(withRel);
        });
        executor.shutdown();
    });
}

@RequestMapping(path = "/{name}/", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public HttpEntity<Example> getElement(ServletWebRequest req, @PathVariable("name") String name, Principal principal) {
    [...]
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM