Search code examples
javaspring-bootwebserverswagger-uispringdoc

After upgrade to Spring Boot 3 and Springdoc 2, server address changes from "localhost" to "[0:0:0:0:0:0:0:1]" or "127.0.0.1"


We recently upgraded our application to Spring Boot 3 and Springdoc 2:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.0.3</version>
</parent>
...
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webflux-ui</artifactId>
    <version>2.0.2</version>
</dependency>

application.properties contain the port definition:

server.port=8096

Everything works fine, the server is listening at the same endpoints as before, but OpenApi works differently than before.

When I run SwaggerUI on the address http://localhost:8096/swagger-ui.html as usual, it generates the OpenApi definition with server address not as http://localhost:8096 as before the upgrade, but as http://[0:0:0:0:0:0:0:1]:8096. For some reason it decides to use IPv6.

When I modify application.properties to explicitly contain the server address:

server.address=localhost
server.port=8096

OpenApi now willfuly replaces it with its IPv4 address, so the server address is now http://127.0.0.1:8096.

Then I cannot test the endpoints from within SwaggerUI, because it causes CORS! (Swagger UI running in the browser at http://localhost:8096, however HTTP requests called from within the UI go to http://127.0.0.1:8096.)

I would somehow accept it and call Swagger UI via the IP address, but it is awkward, and most of all, it used to work smoothly before the upgrade.

I am running under Windows 11. For the record, I didn't do any changes in the operating system settings, and my Spring Boot 2 version still works as expected!

I came with a workaround which is functional, but I am not happy with it as it is an ugly hack:

import org.apache.commons.lang3.StringUtils;
import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class OpenApi30Config {
    @Value("${spring.profiles.active}")
    private String profile;

    @Bean
    public ServerBaseUrlCustomizer serverBaseUrlCustomizer() {
        return serverBaseUrl -> {
            if (StringUtils.contains(profile, "local")) {
                String newServerBaseUrl = StringUtils.replace(serverBaseUrl, "[0:0:0:0:0:0:0:1]", "localhost");
                newServerBaseUrl = StringUtils.replace(newServerBaseUrl, "127.0.0.1", "localhost");
                return newServerBaseUrl;
            }
            return serverBaseUrl;
        };
    }
}

Questions (strongly related):

  1. Why did Spring Boot 3 / OpenApi 2 change this behaviour?
  2. Is there a more "canonical" way to return it back to using localhost in the server address?

Solution

  • Spring Boot 3.0.4 (which uses Spring Framework 6.0.6) fixes the issue. It was a Spring regression, see https://github.com/spring-projects/spring-framework/issues/30033