代码之家  ›  专栏  ›  技术社区  ›  Johan

如何在SpringWebFlux中获取当前控制器方法的URL?

  •  0
  • Johan  · 技术社区  · 6 年前

    这个问题类似于 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-??? 如果在负载平衡器后面运行,则返回头。所以在这种情况下,我希望 链接到当前资源 https://external-uri.com/api/greeting . 如果这很重要,我将使用netty服务器实现。

    0 回复  |  直到 6 年前
        1
  •  1
  •   Denis Zavedeev Brian Kelly    6 年前

    你可以使用 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
    )