Support obtaining ServerWebExchange in ContextView (#6705)

#### What type of PR is this?

/kind feature
/area core
/milestone 2.20.x

#### What this PR does / why we need it:

This PR registers a ServerWebExchangeContextFilter to make ServerWebExchange available under ContextView. The usage example is as follows:

```java
Mono.deferContextual(contextView -> {
    var exchange = ServerWebExchangeContextFilter.getExchange(contextView);
    assertTrue(exchange.isPresent());
    return mono;
})
```

#### Does this PR introduce a user-facing change?

```release-note
None
```
pull/6488/head
John Niang 2024-09-26 16:43:30 +08:00 committed by GitHub
parent fd40770ebc
commit 9710201aa4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 48 additions and 1 deletions

View File

@ -26,6 +26,7 @@ import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.lang.NonNull;
import org.springframework.web.filter.reactive.ServerWebExchangeContextFilter;
import org.springframework.web.reactive.config.ResourceHandlerRegistration;
import org.springframework.web.reactive.config.ResourceHandlerRegistry;
import org.springframework.web.reactive.config.WebFluxConfigurer;
@ -252,4 +253,11 @@ public class WebFluxConfig implements WebFluxConfigurer {
return new AdditionalWebFilterChainProxy(extensionGetter);
}
@Bean
// We expect this filter to be executed before AdditionalWebFilterChainProxy
@Order(-102)
ServerWebExchangeContextFilter serverWebExchangeContextFilter() {
return new ServerWebExchangeContextFilter();
}
}

View File

@ -1,6 +1,7 @@
package run.halo.app.config;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;
import java.net.URI;
@ -18,10 +19,15 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.filter.reactive.ServerWebExchangeContextFilter;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.reactive.socket.WebSocketMessage;
import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import run.halo.app.core.endpoint.WebSocketEndpoint;
import run.halo.app.core.extension.Role;
@ -31,7 +37,10 @@ import run.halo.app.extension.Metadata;
@SpringBootTest(properties = "halo.console.location=classpath:/console/", webEnvironment =
SpringBootTest.WebEnvironment.RANDOM_PORT)
@Import(WebFluxConfigTest.WebSocketSupportTest.TestWebSocketConfiguration.class)
@Import({
WebFluxConfigTest.WebSocketSupportTest.TestWebSocketConfiguration.class,
WebFluxConfigTest.ServerWebExchangeContextFilterTest.TestConfig.class
})
@AutoConfigureWebTestClient
class WebFluxConfigTest {
@ -154,4 +163,34 @@ class WebFluxConfigTest {
.expectStatus().isNotFound();
}
}
@Nested
class ServerWebExchangeContextFilterTest {
@TestConfiguration
static class TestConfig {
@Bean
RouterFunction<ServerResponse> assertServerWebExchangeRoute() {
return RouterFunctions.route()
.GET("/assert-server-web-exchange",
request -> Mono.deferContextual(contextView -> {
var exchange = ServerWebExchangeContextFilter.getExchange(contextView);
assertTrue(exchange.isPresent());
return ServerResponse.ok().build();
}))
.build();
}
}
@Test
void shouldGetExchangeFromContextView() {
webClient.get().uri("/assert-server-web-exchange")
.exchange()
.expectStatus().isOk();
}
}
}