Backend Development 6 min read

How to Access HttpServletRequest in Spring WebFlux Using Reactor Context

This article explains why Spring WebFlux lacks RequestContextHolder, explores the ReactorContextWebFilter solution from Spring Security, and demonstrates a custom ReactiveRequestContextFilter and helper class that store and retrieve the request via Reactor's Context for exception handling and WebClient header propagation.

Java Architecture Diary
Java Architecture Diary
Java Architecture Diary
How to Access HttpServletRequest in Spring WebFlux Using Reactor Context

Explanation

In Spring Boot Web we can obtain the

HttpServletRequest

via

RequestContextHolder

. In Spring WebFlux this feature is missing, making it difficult to retrieve the request in AOP or other scenarios.

<code>ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();</code>
<code>// Get request</code>
<code>HttpServletRequest request = requestAttributes.getRequest();</code>

We first look for a solution in

spring-security

. The

ReactorContextWebFilter

shows how security stores the context.

<code>public class ReactorContextWebFilter implements WebFilter {
    private final ServerSecurityContextRepository repository;
    public ReactorContextWebFilter(ServerSecurityContextRepository repository) {
        Assert.notNull(repository, "repository cannot be null");
        this.repository = repository;
    }
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        return chain.filter(exchange)
            .subscriberContext(c -> c.hasKey(SecurityContext.class) ? c : withSecurityContext(c, exchange));
    }
    private Context withSecurityContext(Context mainContext, ServerWebExchange exchange) {
        return mainContext.putAll(this.repository.load(exchange)
            .as(ReactiveSecurityContextHolder::withSecurityContext));
    }
}</code>

The filter uses

reactor.util.context.Context

, a ThreadLocal‑like feature introduced in Reactor 3.1.

Implementation in mica

The mica project provides a simple

ReactiveRequestContextFilter

that stores the

ServerHttpRequest

in the Reactor Context.

<code>@Configuration
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
public class ReactiveRequestContextFilter implements WebFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        return chain.filter(exchange)
            .subscriberContext(ctx -> ctx.put(ReactiveRequestContextHolder.CONTEXT_KEY, request));
    }
}</code>

The helper

ReactiveRequestContextHolder

retrieves the request from the Context.

<code>public class ReactiveRequestContextHolder {
    static final Class<ServerHttpRequest> CONTEXT_KEY = ServerHttpRequest.class;
    public static Mono<ServerHttpRequest> getRequest() {
        return Mono.subscriberContext()
            .map(ctx -> ctx.get(CONTEXT_KEY));
    }
}</code>

How to Use It

Exception handling with the stored request

<code>@ExceptionHandler(Throwable.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Mono<?> handleError(Throwable e) {
    log.error("未知异常", e);
    return ReactiveRequestContextHolder.getRequest()
        .doOnSuccess(r -> publishEvent(r, e))
        .flatMap(r -> Mono.just(R.fail(SystemCode.FAILURE)));
}
private void publishEvent(ServerHttpRequest request, Throwable error) {
    // business logic
}</code>

WebClient header propagation

<code>@GetMapping("/test")
@ResponseBody
public Mono<String> test() {
    WebClient webClient = testClient();
    return webClient.get().uri("").retrieve().bodyToMono(String.class);
}
@Bean
public WebClient testClient() {
    return WebClient.builder()
        .filter(testFilterFunction())
        .baseUrl("https://www.baidu.com")
        .build();
}
private ExchangeFilterFunction testFilterFunction() {
    return (request, next) -> ReactiveRequestContextHolder.getRequest()
        .flatMap(r -> {
            ClientRequest clientRequest = ClientRequest.from(request)
                .headers(headers -> headers.set(HttpHeaders.USER_AGENT,
                    r.getHeaders().getFirst(HttpHeaders.USER_AGENT)))
                .build();
            return next.exchange(clientRequest);
        });
}</code>

These examples demonstrate how to retrieve the original request for logging, error handling, and forwarding headers when using Spring WebFlux.

References

[1]

: https://github.com/spring-projects/spring-security/blob/master/web/src/main/java/org/springframework/security/web/server/context/ReactorContextWebFilter.java#L43

[2]

: https://projectreactor.io/docs/core/release/reference/#context

[3]

: https://www.oschina.net/question/2315449_2305069

JavaReactive ProgrammingSpring WebFluxRequestContextHolderReactor Context
Java Architecture Diary
Written by

Java Architecture Diary

Committed to sharing original, high‑quality technical articles; no fluff or promotional content.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.