【问题标题】:How to get URL of the current controller method in Spring Webflux?如何在 Spring Webflux 中获取当前控制器方法的 URL?
【发布时间】:2019-08-08 23:08:06
【问题描述】:

这个问题与What's the best way to get the current URL in Spring MVC? 类似,但针对Webflux(它也可能与How to get the context of the current request in spring-webflux 有关,但这个问题更具体,所以我希望有一个解决方案)。

我想要做的是在 Webflux 控制器中获取当前 URL。例如:

@GetMapping("/greeting")
public Mono<Greeting> greeting() {
   String linkToCurrentResource = .. // How do I get this?
   Greeting greeting = new Greeting("hello",  linkToCurrentResource);
   return Mono.just(greeting);
}

如果在负载平衡器后面运行,最好 linkToCurrentResource 应该理解 X-Forwarded-??? 标头。所以在这种情况下,我希望linkToCurrentResource 类似于https://external-uri.com/api/greeting。如果这很重要,我正在使用 Netty 服务器实现。

【问题讨论】:

    标签: java spring-boot spring-webflux


    【解决方案1】:

    您可以使用ServerHttpRequest作为方法参数来获取uri:

    @RestController
    public class GreetingController {
      @GetMapping("/greeting")
      public Mono<Greeting> getGreeting(ServerHttpRequest serverHttpRequest) {
        return Mono.just(new Greeting("greeting", serverHttpRequest.getURI().toString()));
      }
    }
    

    如果在负载平衡器后面运行,最好 linkToCurrentResource 应该理解 X-Forwarded-??? 标头。

    然后你可以暴露一个ForwardedHeaderTransformer@Bean。

    来自其文档:

    从“Forwarded”和“X-Forwarded-*”标头中提取值以覆盖请求URI(即HttpRequest.getURI()),使其反映客户端发起的协议和地址。

    @Configuration
    open class MvcConfig {
        @Bean
        open fun forwardedHeaderTransformer() = ForwardedHeaderTransformer()
    }
    

    这里有一些测试:

    @ExtendWith(SpringExtension::class)
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT,
            properties = ["server.port=4333"])
    class GreetingController2Test {
        @Autowired
        private lateinit var restTemplate: TestRestTemplate
    
        @Test
        fun `should return uri`() {
            val responseEntity = restTemplate.getForEntity("/greeting", Greeting::class.java)
            val greeting = responseEntity.body!!
            assertEquals("http://localhost:4333/greeting", greeting.uri)
        }
    
        @Test
        fun `should return uri composed from forwarded-??? headers`() {
            val headers = HttpHeaders()
            headers["X-Forwarded-Host"] = "external-uri.com"
            headers["X-Forwarded-Proto"] = "https"
            headers["X-Forwarded-Prefix"] = "/prefix"
    
            val httpEntity = HttpEntity(null, headers)
            val responseEntity = restTemplate.exchange("/greeting", HttpMethod.GET, httpEntity, Greeting::class.java)
            val greeting = responseEntity.body!!
            assertEquals("https://external-uri.com/prefix/greeting", greeting.uri)
        }
    }
    

    还有Greeting.kt:

    data class Greeting(
            val g: String? = null,
            val uri: String? = null
    )
    

    【讨论】:

    • 非常感谢!我不能希望得到更好的答案。像魅力一样工作。
    猜你喜欢
    • 2018-08-23
    • 2017-10-14
    • 2015-04-29
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-04
    • 1970-01-01
    相关资源
    最近更新 更多