22
votes

I have created a basic REST controller which makes requests using the reactive Webclient in Spring-boot 2 using netty.

@RestController
@RequestMapping("/test")
@Log4j2
public class TestController {

    private WebClient client;

    @PostConstruct
    public void setup() {

        client = WebClient.builder()
                .baseUrl("http://www.google.com/")
                .exchangeStrategies(ExchangeStrategies.withDefaults())
                .build();
    }


    @GetMapping
    public Mono<String> hello() throws URISyntaxException {
        return client.get().retrieve().bodyToMono(String.class);
    }

}

When I get a 3XX response code back I want the webclient to follow the redirect using the Location in the response and call that URI recursively until I get a non 3XX response.

The actual result I get is the 3XX response.

2
I've created an issue in Jira: jira.spring.io/browse/SPR-16277Martin Österlund
Is there a solution to this? It seems that Spring Boot 2 on the GA-release still can't follow redirects.Sven
The fix (github.com/reactor/reactor-netty/issues/235) is in netty 0.8 which will be in Spring 5.1.Martin Österlund
I better find some ugly old school coding until later this year then. 5.1 is quite some time away.Sven

2 Answers

32
votes

You need to configure the client per the docs

           WebClient.builder()
                    .clientConnector(new ReactorClientHttpConnector(
                            HttpClient.create().followRedirect(true)
                    ))
7
votes

You could make the URL parameter of your function, and recursively call it while you're getting 3XX responses. Something like this (in real implementation you would probably want to limit the number of redirects):

public Mono<String> hello(String uri) throws URISyntaxException {
    return client.get()
            .uri(uri)
            .exchange()
            .flatMap(response -> {
                if (response.statusCode().is3xxRedirection()) {
                    String redirectUrl = response.headers().header("Location").get(0);
                    return response.bodyToMono(Void.class).then(hello(redirectUrl));
                }
                return response.bodyToMono(String.class);
            }