Webflux how to set cookie from inside stream

Viewed 3162

I would like to know how could I set cookie from ServerResponse body.

I found few solutions but these are saving cookie from outside body function like this.

ServerResponse.BodyBuilder response = ServerResponse.ok();
response.cookie(ResponseCookie.from("mycookie", "myVal").build());
return response.body(Mono.just("Welcome"), String.class);

This saves cookie and this solution is fine if we do not have dynamic cookie value. Now I would like to write the cookie value which is coming from db.

like this.

return response.body(
                Mono.just(101)
                        .flatMap(i ->
                            userRepository
                                    .findById(i)
                                    .map(user -> {
                                        Long time = user.getLastLoginTime();
                                        // set time as cookie,
                                        // I would like to save cookie from here
                                        return user.getEmail();
                                    })
                        )
                , String.class);

So how can i save cookie from inside map function and since i am returning stream, webflux will auto subscribe it until then my stream is not executed.

1 Answers

Define your controller's method signature with a ServerWebExchange parameter like so:

public Mono<String> cookieSetter(ServerWebExchange exchange)

...you can then use exchange.getResponse().addCookie() anywhere in the reactive chain. (I'd do that as a dedicated side-effect however rather than bundling it in a single map call.) So you could do something like:

return response.body(
        Mono.just(101)
                .flatMap(i ->
                        userRepository
                                .findById(i)
                                .doOnNext(user -> {
                                    exchange.getResponse().addCookie(ResponseCookie.from("time", user.getLastLoginTime())
                                            .httpOnly(true)
                                            .build());
                                })
                                .map(User::getEmail)
                )
        , String.class);
Related