22
33import io .swagger .v3 .oas .models .Components ;
44import io .swagger .v3 .oas .models .OpenAPI ;
5+ import io .swagger .v3 .oas .models .PathItem ;
6+ import io .swagger .v3 .oas .models .Paths ;
57import io .swagger .v3 .oas .models .info .Info ;
68import io .swagger .v3 .oas .models .security .SecurityRequirement ;
79import io .swagger .v3 .oas .models .security .SecurityScheme ;
810import io .swagger .v3 .oas .models .servers .Server ;
911import io .swagger .v3 .oas .models .servers .ServerVariable ;
1012import io .swagger .v3 .oas .models .servers .ServerVariables ;
13+ import io .swagger .v3 .oas .models .tags .Tag ;
1114import org .lowcoder .sdk .config .CommonConfig ;
15+ import org .springdoc .api .OpenApiCustomiser ;
1216import org .springframework .beans .factory .annotation .Autowired ;
1317import org .springframework .beans .factory .annotation .Value ;
1418import org .springframework .context .annotation .Bean ;
1519import org .springframework .context .annotation .Configuration ;
1620
1721import java .util .Arrays ;
22+ import java .util .Comparator ;
23+ import java .util .Map ;
24+ import java .util .TreeMap ;
1825
1926@ Configuration
2027public class OpenAPIDocsConfiguration {
28+
2129 @ Autowired
2230 private CommonConfig commonConfig ;
2331
2432 @ Value ("${server.port:8080}" )
2533 private int serverPort ;
26-
34+
2735 @ Value ("${spring.webflux.base-path:/}" )
2836 private String contextPath ;
29-
30- @ Bean
31- OpenAPI customizeOpenAPI () {
3237
38+ /**
39+ * Configures the core OpenAPI spec including servers, security and info.
40+ */
41+ @ Bean
42+ public OpenAPI customizeOpenAPI () {
3343 final String securitySchemeName = commonConfig .getCookieName ();
3444
3545 return new OpenAPI ()
36- .info (new Info ()
37- .title ("Lowcoder Open Rest API" )
38- .version (commonConfig .getApiVersion ()))
39- /*.addServersItem(new Server()
40- .url(createLocalServerUrl("localhost", serverPort, contextPath))
41- .description("Local development API service")
42- ) */
43- .addServersItem (createCustomServer ())
44- .addServersItem (new Server ()
45- .url ("https://api-service.lowcoder.cloud/" )
46- .description ("Lowcoder Community Edition: Public Cloud API Access" )
47- )
48- .addSecurityItem (new SecurityRequirement ()
49- .addList (securitySchemeName )).components (new Components ()
50- /* .addSecuritySchemes(
51- securitySchemeName,
52- new SecurityScheme()
53- .name(securitySchemeName)
54- .type(SecurityScheme.Type.HTTP) // HTTP-based authentication
55- .scheme("cookie") // Specify the authentication scheme as "cookie"
56- .description("Cookie-based authentication. Please ensure the client sends cookies with each request after authentication.")
57- ) */
58- .addSecuritySchemes (
59- "API Key" ,
60- new SecurityScheme ()
61- .name ("Authorization" )
62- .type (SecurityScheme .Type .APIKEY )
63- .in (SecurityScheme .In .HEADER )
64- .scheme ("bearer" )
65- .bearerFormat ("JWT" )
66- .description ("API Key Authentication with a Bearer token. Copy your API Key and prefix it here with 'Bearer ' (e.g. 'Bearer eyJhbGciO...'" )
67- )
68- );
46+ .info (new Info ()
47+ .title ("Lowcoder Open Rest API" )
48+ .version (commonConfig .getApiVersion ()))
49+ .addServersItem (createCustomServer ())
50+ .addServersItem (new Server ()
51+ .url ("https://api-service.lowcoder.cloud/" )
52+ .description ("Lowcoder Community Edition: Public Cloud API Access" ))
53+ .addSecurityItem (new SecurityRequirement ().addList (securitySchemeName ))
54+ .components (new Components ()
55+ .addSecuritySchemes ("API Key" , new SecurityScheme ()
56+ .name ("Authorization" )
57+ .type (SecurityScheme .Type .APIKEY )
58+ .in (SecurityScheme .In .HEADER )
59+ .scheme ("bearer" )
60+ .bearerFormat ("JWT" )
61+ .description ("API Key Authentication with a Bearer token. Copy your API Key and prefix it here with 'Bearer ' (e.g. 'Bearer eyJhbGciO...')" )));
6962 }
70-
71-
72- /* private static String createLocalServerUrl(String domain, int port, String contextPath)
73- {
74- StringBuilder sb = new StringBuilder("http");
75-
76- if (port == 443)
77- {
78- sb.append("s");
79- }
80- sb.append("://").append(domain);
8163
82- if (port != 80 && port != 443)
83- {
84- sb.append(":").append(port);
85- }
86- sb.append(contextPath);
87-
88- return sb.toString();
89- } */
90-
91- private Server createCustomServer ()
92- {
93- String url = "{scheme}://{domain}:{port}{basePath}" ;
94-
95- Server server = new Server ()
96- .description ("Lowcoder Self-hosted Installation API Access" )
97- .url (url )
98- .variables (new ServerVariables ()
99- .addServerVariable ("scheme" , new ServerVariable ()
100- ._default ("http" )
101- .description ("HTTP scheme" )
102- ._enum (Arrays .asList ("http" , "https" )))
103- .addServerVariable ("domain" , new ServerVariable ()
104- .description ("Lowcoder IP address or domain" )
105- ._default ("localhost" ))
106- .addServerVariable ("port" , new ServerVariable ()
107- .description ("Port" )
108- ._default ("3000" ))
109- .addServerVariable ("basePath" , new ServerVariable ()
110- .description ("Base path" )
111- ._default (contextPath ))
112- );
113- return server ;
64+ /**
65+ * Creates a dynamic server entry using server variables.
66+ */
67+ private Server createCustomServer () {
68+ String url = "{scheme}://{domain}:{port}{basePath}" ;
69+
70+ return new Server ()
71+ .description ("Lowcoder Self-hosted Installation API Access" )
72+ .url (url )
73+ .variables (new ServerVariables ()
74+ .addServerVariable ("scheme" , new ServerVariable ()
75+ ._default ("http" )
76+ .description ("HTTP scheme" )
77+ ._enum (Arrays .asList ("http" , "https" )))
78+ .addServerVariable ("domain" , new ServerVariable ()
79+ .description ("Lowcoder IP address or domain" )
80+ ._default ("localhost" ))
81+ .addServerVariable ("port" , new ServerVariable ()
82+ .description ("Port" )
83+ ._default ("3000" ))
84+ .addServerVariable ("basePath" , new ServerVariable ()
85+ .description ("Base path" )
86+ ._default (contextPath )));
87+ }
88+
89+ /**
90+ * Customizes the OpenAPI spec at runtime to sort tags and paths.
91+ */
92+ @ Bean
93+ public OpenApiCustomiser sortOpenApiSpec () {
94+ return openApi -> {
95+ // Sort tags alphabetically
96+ if (openApi .getTags () != null ) {
97+ openApi .getTags ().sort (Comparator .comparing (Tag ::getName ));
98+ }
99+
100+ // Sort paths alphabetically by their URL
101+ if (openApi .getPaths () != null ) {
102+ Map <String , PathItem > sorted = new TreeMap <>(openApi .getPaths ());
103+ Paths sortedPaths = new Paths ();
104+ sorted .forEach (sortedPaths ::addPathItem );
105+ openApi .setPaths (sortedPaths );
106+ }
107+ };
114108 }
115- }
109+ }
0 commit comments