SpringFox and Swagger UI - How to document the /login Endpoint

Viewed 2324

I have added SpringFox dependencies to my Spring Boot project and when I open the swagger-ui.html page I can see the documentation for the RestControllers which I have created myself and I do see documentation for:

  • basic-error-controller
  • default

The "default" tab contains the description for /api/login/ endpoint but I cannot find documentation on how to configure this /api/login endpoint to:

  • Change the endpoint path from /api/login to /login
  • Specify the body of HTTP Request to contain a sample JSON Model which should have two fields: email and password.

I use Spring Security and the /login endpoint accepts: email and password for user to be able to login.

How can I add documentation to a default /login endpoint?

1 Answers

Try configure a class like this to personalize your login.

package application.swagger;

import application.user.dto.UserLoginDTO;
import com.fasterxml.classmate.TypeResolver;
import java.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import springfox.documentation.builders.OperationBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiDescription;
import springfox.documentation.service.ResponseMessage;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.ApiListingScannerPlugin;
import springfox.documentation.spi.service.contexts.DocumentationContext;
import springfox.documentation.spring.web.readers.operation.CachingOperationNameGenerator;
import springfox.documentation.swagger.common.SwaggerPluginSupport;

@Component
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER)
@Slf4j
public class SwaggerLoginListingScanner implements ApiListingScannerPlugin {

  // tag::api-listing-plugin[]
  private final CachingOperationNameGenerator operationNames;

  /**
   * @param operationNames - CachingOperationNameGenerator is a component bean
   *                       that is available to be autowired
   */
  public SwaggerLoginListingScanner(
    CachingOperationNameGenerator operationNames
  ) { //<9>
    this.operationNames = operationNames;
  }

  @Override
  public List<ApiDescription> apply(DocumentationContext context) {
    return new ArrayList<>(
      Arrays.asList(
        new ApiDescription(
          null,
          "/api/login",
          "login",
          Collections.singletonList(
            new OperationBuilder(operationNames)
              .summary("login")
              .tags(Set.of("jwt-authentication-filter"))
              .authorizations(new ArrayList<>())
              .position(1)
              .codegenMethodNameStem("loginPost")
              .method(HttpMethod.POST)
              .notes("This is a login method")
              .parameters(
                Arrays.asList(
                  new ParameterBuilder()
                    .description("Login Parameter")
                    .type(new TypeResolver().resolve(UserLoginDTO.class))
                    .name("userLogin")
                    .parameterType("body")
                    .parameterAccess("access")
                    .required(true)
                    .modelRef(new ModelRef("UserLoginDTO"))
                    .build()
                )
              )
              .responseMessages(responseMessages())
              .responseModel(new ModelRef(("UserToken")))
              .build()
          ),
          false
        )
      )
    );
  }

  /**
   * @return Set of response messages that overide the default/global response messages
   */
  private Set<ResponseMessage> responseMessages() { //<8>
    return Set.of(
      new ResponseMessageBuilder()
        .code(200)
        .responseModel(new ModelRef("UserToken"))
        .build(),
      new ResponseMessageBuilder()
        .code(401)
        .responseModel(new ModelRef("ApiError"))
        .build(),
      new ResponseMessageBuilder()
        .code(403)
        .responseModel(new ModelRef("ApiError"))
        .build(),
      new ResponseMessageBuilder()
        .code(404)
        .responseModel(new ModelRef("ApiError"))
        .build()
    );
  }

  // tag::api-listing-plugin[]

  @Override
  public boolean supports(DocumentationType delimiter) {
    return DocumentationType.SWAGGER_2.equals(delimiter);
  }
}

Related