From ddf8c3c0f07c0ca2fa6444c4511b61fc9a5c496c Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Wed, 12 Sep 2018 15:29:37 +0300 Subject: static swagger docs --- build.gradle | 2 + juick-server/build.gradle | 60 +++++++++++++++++++--- juick-server/src/docs/index.adoc | 3 ++ .../src/main/java/com/juick/server/api/Index.java | 7 +-- .../src/main/java/com/juick/server/api/Users.java | 3 -- .../server/configuration/ApiAppConfiguration.java | 21 +------- .../java/com/juick/server/xmpp/XMPPStatusPage.java | 2 + .../server/configuration/SwaggerConfiguration.java | 28 ++++++++++ .../java/com/juick/server/tests/ServerTests.java | 12 +++++ 9 files changed, 104 insertions(+), 34 deletions(-) create mode 100644 juick-server/src/docs/index.adoc create mode 100644 juick-server/src/test/java/com/juick/server/configuration/SwaggerConfiguration.java diff --git a/build.gradle b/build.gradle index cddf71a9..638b8de7 100644 --- a/build.gradle +++ b/build.gradle @@ -5,11 +5,13 @@ buildscript { } dependencies { classpath 'com.github.ben-manes:gradle-versions-plugin:0.20.0' + classpath 'io.github.swagger2markup:swagger2markup-gradle-plugin:1.3.1' } } plugins { id 'org.springframework.boot' version '2.0.4.RELEASE' apply false id "com.moowork.node" version "1.2.0" apply false + id("org.asciidoctor.convert") version "1.5.8" apply false } allprojects { diff --git a/juick-server/build.gradle b/juick-server/build.gradle index 9e1e3d79..9217d6b3 100644 --- a/juick-server/build.gradle +++ b/juick-server/build.gradle @@ -1,6 +1,8 @@ -apply plugin: 'war' +apply plugin: 'java' apply plugin: 'org.springframework.boot' apply plugin: 'com.moowork.node' +apply plugin: 'io.github.swagger2markup' +apply plugin: 'org.asciidoctor.convert' task compileFrontend(type: YarnTask) { inputs.files(fileTree('node_modules')) @@ -11,6 +13,51 @@ task compileFrontend(type: YarnTask) { args = ['run', 'compile'] } +ext { + swaggerOutputDir = file("${buildDir}/swagger") + docsOutputDir = file("${buildDir}/docs") +} + +test { + systemProperty 'io.springfox.staticdocs.outputDir', swaggerOutputDir + outputs.dir swaggerOutputDir +} + +convertSwagger2markup { + dependsOn test + swaggerInput "${swaggerOutputDir}/swagger.json" + outputDir swaggerOutputDir + config = [ + 'swagger2markup.markupLanguage' : 'ASCIIDOC', + 'swagger2markup.pathsGroupedBy' : 'TAGS' + ] +} +task asciidocIndex (type: Copy) { + from 'src/docs' + into swaggerOutputDir + include '*.adoc' +} +asciidoctor { + dependsOn convertSwagger2markup + dependsOn asciidocIndex + sourceDir = swaggerOutputDir + sources { + include 'index.adoc', 'overview.adoc', 'definitions.adoc', 'paths.adoc' + } + attributes = [ + doctype: 'book', + toc: 'left', + toclevels: '3', + numbered: '', + sectlinks: '', + sectanchors: '', + hardbreaks: '', + src: swaggerOutputDir, + generated: docsOutputDir + ] + outputDir = docsOutputDir +} + dependencies { compile project(':juick-common') @@ -19,11 +66,7 @@ dependencies { compile ('org.springframework.boot:spring-boot-starter-security') compile ('org.springframework.boot:spring-boot-starter-jdbc') - providedRuntime("org.springframework.boot:spring-boot-starter-tomcat") - providedRuntime 'com.h2database:h2:1.4.196' - - compile 'io.springfox:springfox-swagger2:2.9.2' - compile 'io.springfox:springfox-swagger-ui:2.9.2' + compileOnly 'io.springfox:springfox-core:2.9.2' compile 'org.apache.commons:commons-email:1.5' compile 'com.github.scribejava:scribejava-apis:5.5.0' @@ -48,7 +91,8 @@ dependencies { compile 'org.flywaydb:flyway-core:5.1.4' - providedRuntime 'mysql:mysql-connector-java:5.1.45' + runtime 'mysql:mysql-connector-java:5.1.45' + runtime 'com.h2database:h2:1.4.196' runtime "commons-fileupload:commons-fileupload:1.3.3" compile 'com.github.scribejava:scribejava-apis:5.5.0' @@ -60,6 +104,8 @@ dependencies { testCompile ("org.springframework.boot:spring-boot-starter-test") testCompile ('net.sourceforge.htmlunit:htmlunit:2.32') testCompile ('org.springframework.security:spring-security-test') + + testCompile 'io.springfox:springfox-swagger2:2.9.2' } bootJar { diff --git a/juick-server/src/docs/index.adoc b/juick-server/src/docs/index.adoc new file mode 100644 index 00000000..4d492510 --- /dev/null +++ b/juick-server/src/docs/index.adoc @@ -0,0 +1,3 @@ +include::{src}/overview.adoc[] +include::{src}/paths.adoc[] +include::{src}/definitions.adoc[] \ No newline at end of file diff --git a/juick-server/src/main/java/com/juick/server/api/Index.java b/juick-server/src/main/java/com/juick/server/api/Index.java index 947ac920..56f01370 100644 --- a/juick-server/src/main/java/com/juick/server/api/Index.java +++ b/juick-server/src/main/java/com/juick/server/api/Index.java @@ -19,8 +19,6 @@ package com.juick.server.api; import com.juick.Status; import com.juick.server.WebsocketManager; -import com.juick.server.XMPPServer; -import com.juick.server.xmpp.helpers.XMPPStatus; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; @@ -28,27 +26,26 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; -import rocks.xmpp.addr.Jid; import springfox.documentation.annotations.ApiIgnore; import javax.inject.Inject; import java.net.URI; -import java.util.stream.Collectors; /** * Created by vitalyster on 25.07.2016. */ -@ApiIgnore @RestController public class Index { @Inject private WebsocketManager wsHandler; + @ApiIgnore @RequestMapping(value = { "/api/", "/ws/" }, method = RequestMethod.GET, headers = "Connection!=Upgrade") public ResponseEntity description() { URI redirectUri = ServletUriComponentsBuilder.fromCurrentRequestUri().path("/swagger-ui.html").build().toUri(); return ResponseEntity.status(HttpStatus.MOVED_PERMANENTLY).location(redirectUri).build(); } + @ApiIgnore @RequestMapping(value = "/api/status", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE, headers = "Connection!=Upgrade") public Status status() { diff --git a/juick-server/src/main/java/com/juick/server/api/Users.java b/juick-server/src/main/java/com/juick/server/api/Users.java index 7f29a327..de5c05c2 100644 --- a/juick-server/src/main/java/com/juick/server/api/Users.java +++ b/juick-server/src/main/java/com/juick/server/api/Users.java @@ -28,7 +28,6 @@ import com.juick.service.MessagesService; import com.juick.service.UserService; import com.juick.server.util.UserUtils; import com.juick.server.util.WebUtils; -import io.swagger.annotations.ApiOperation; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; @@ -51,7 +50,6 @@ public class Users { @Inject private EmailService emailService; - @ApiOperation(value = "This returns user token", notes = "Pass login and password using HTTP Basic") @RequestMapping(value = "/api/auth", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public String getAuthToken() { return userService.getHashByUID(UserUtils.getCurrentUser().getUid()); @@ -143,7 +141,6 @@ public class Users { throw new HttpNotFoundException(); } - @ApiOperation(value = "This returns detailed user info") @GetMapping("/api/info/{uname}") public UserInfo getUserInfo(@PathVariable String uname) { User user = userService.getUserByName(uname); diff --git a/juick-server/src/main/java/com/juick/server/configuration/ApiAppConfiguration.java b/juick-server/src/main/java/com/juick/server/configuration/ApiAppConfiguration.java index 19718abd..619aeff8 100644 --- a/juick-server/src/main/java/com/juick/server/configuration/ApiAppConfiguration.java +++ b/juick-server/src/main/java/com/juick/server/configuration/ApiAppConfiguration.java @@ -17,7 +17,6 @@ package com.juick.server.configuration; -import com.google.common.base.Predicates; import com.juick.server.WebsocketManager; import com.juick.server.api.rss.MessagesView; import com.juick.server.api.rss.RepliesView; @@ -25,7 +24,8 @@ import com.juick.server.xmpp.JidConverter; import com.juick.server.xmpp.iq.MessageQuery; import com.juick.server.xmpp.s2s.BasicXmppSession; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.*; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.convert.ConversionService; import org.springframework.format.support.DefaultFormattingConversionService; @@ -42,38 +42,21 @@ import org.springframework.web.socket.server.standard.ServletServerContainerFact import rocks.xmpp.core.session.Extension; import rocks.xmpp.core.session.XmppSessionConfiguration; import rocks.xmpp.core.session.debug.LogbackDebugger; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; import javax.annotation.Nonnull; import javax.inject.Inject; import java.time.Duration; -import java.util.Collections; /** * Created by aalexeev on 11/12/16. */ @Configuration @EnableAsync -@EnableSwagger2 @EnableScheduling @EnableWebSocket public class ApiAppConfiguration implements WebMvcConfigurer, WebSocketConfigurer { @Inject private WebsocketManager websocketManager; - @Bean - public Docket api() { - return new Docket(DocumentationType.SWAGGER_2) - .select() - .apis(Predicates.not(RequestHandlerSelectors.basePackage("org.springframework.boot"))) - .paths(PathSelectors.any()).build().apiInfo(new ApiInfo("Juick API", "Juick REST API Documentation", - "2.0", "https://juick.com/help/tos", null, - "AGPLv3", "https://www.gnu.org/licenses/agpl-3.0.html", Collections.emptyList())); - } @Override public void registerWebSocketHandlers(@Nonnull WebSocketHandlerRegistry registry) { diff --git a/juick-server/src/main/java/com/juick/server/xmpp/XMPPStatusPage.java b/juick-server/src/main/java/com/juick/server/xmpp/XMPPStatusPage.java index 90c8fe59..231696ec 100644 --- a/juick-server/src/main/java/com/juick/server/xmpp/XMPPStatusPage.java +++ b/juick-server/src/main/java/com/juick/server/xmpp/XMPPStatusPage.java @@ -8,6 +8,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import rocks.xmpp.addr.Jid; +import springfox.documentation.annotations.ApiIgnore; import javax.inject.Inject; import java.util.stream.Collectors; @@ -17,6 +18,7 @@ import java.util.stream.Collectors; public class XMPPStatusPage { @Inject private XMPPServer xmpp; + @ApiIgnore @RequestMapping(method = RequestMethod.GET, value = "/api/xmpp-status", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public XMPPStatus xmppStatus() { XMPPStatus status = new XMPPStatus(); diff --git a/juick-server/src/test/java/com/juick/server/configuration/SwaggerConfiguration.java b/juick-server/src/test/java/com/juick/server/configuration/SwaggerConfiguration.java new file mode 100644 index 00000000..7c03f393 --- /dev/null +++ b/juick-server/src/test/java/com/juick/server/configuration/SwaggerConfiguration.java @@ -0,0 +1,28 @@ +package com.juick.server.configuration; + +import com.google.common.base.Predicates; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +import java.util.Collections; + +@Configuration +@EnableSwagger2 +public class SwaggerConfiguration { + @Bean + public Docket api() { + return new Docket(DocumentationType.SWAGGER_2) + .host("api.juick.com") + .select() + .apis(Predicates.not(Predicates.or(RequestHandlerSelectors.basePackage("org.springframework.boot"), RequestHandlerSelectors.basePackage("com.juick.server.www")))) + .paths(PathSelectors.any()).build().apiInfo(new ApiInfo("Juick API", "Juick REST API Documentation", + "2.0", "https://juick.com/help/tos", null, + "AGPLv3", "https://www.gnu.org/licenses/agpl-3.0.html", Collections.emptyList())); + } +} diff --git a/juick-server/src/test/java/com/juick/server/tests/ServerTests.java b/juick-server/src/test/java/com/juick/server/tests/ServerTests.java index 66845cfa..13cb8d41 100644 --- a/juick-server/src/test/java/com/juick/server/tests/ServerTests.java +++ b/juick-server/src/test/java/com/juick/server/tests/ServerTests.java @@ -1651,4 +1651,16 @@ public class ServerTests { String sql = String.format("SELECT * FROM table WHERE data='%s'", Utils.encodeSphinx("';-- DROP TABLE table")); assertThat(sql, is("SELECT * FROM table WHERE data='\\';-- DROP TABLE table\'")); } + @Test + public void swaggerOutput() throws Exception { + MvcResult result = mockMvc.perform(get("/v2/api-docs") + .accept(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()) + .andReturn(); + String outputDir = System.getProperty("io.springfox.staticdocs.outputDir"); + Files.createDirectories(Paths.get(outputDir)); + BufferedWriter writer = Files.newBufferedWriter(Paths.get(outputDir, "swagger.json"), StandardCharsets.UTF_8); + writer.write(result.getResponse().getContentAsString()); + writer.flush(); + } } -- cgit v1.2.3