Howto display Swagger-ui in between API endPoints?

179 views
Skip to first unread message

Henrik Helmø Larsen

unread,
Jul 9, 2015, 4:17:31 AM7/9/15
to swagger-sw...@googlegroups.com
I have found Swagger.io very usefull and have just started to incorporate it in our API. I have though encountered a problem:
How can I have the Swagger-ui endPoint in between my API endPoins:

My API is in the root of the following domain: api.companyname.com/...

I want Swagger-ui to be displayed if api.companyname.com/api-docs is requested by the browser.

I am using JAX-RS and extending the Application class:

@ApplicationPath("/")
public class RESTApplication extends Application {

    public RESTApplication() {
        BeanConfig beanConfig = new BeanConfig();
        beanConfig.setVersion("1.0.0");
        beanConfig.setSchemes(new String[]{"http"});
        beanConfig.setHost("api.companyname.com");
        beanConfig.setBasePath("/");
        beanConfig.setResourcePackage("com.companyname.rest.services");
        beanConfig.setScan(true);
    }

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> resources = new HashSet();
        resources.add(com.companyname.rest.services.ReviewsService.class);
        //...
        resources.add(io.swagger.jaxrs.listing.ApiListingResource.class);
        resources.add(io.swagger.jaxrs.listing.SwaggerSerializers.class);
        return resources;
    }
}


Here I add the @ApplicationPath("/") so the basePath of the API is the root ("/"). This prevents my server (JBoss) from serving the api-docs folder - as it thinks it is an API call. When calling the api-docs I get the following error:
09:08:28,666 WARN  [org.jboss.resteasy.core.ExceptionHandler] (http-/0.0.0.0:80-1) failed to execute: javax.ws.rs.NotFoundException: Could not find resource for full path: http://api.companyname.com/api-docs

I have tried to use Patters in @ApplicationPath(...) but that doesn't work...

What I am looking for is a way to tell the application that all API request should be treated normally except when api.companyname.com/api-docs is called - in this case the normal (static) swagger-ui html page should be returned...

I am hoping someone else has had the same problem and found a way to solve it...

Henrik Helmø Larsen

unread,
Jul 10, 2015, 4:27:49 AM7/10/15
to swagger-sw...@googlegroups.com
Solved it myself by supplying the webpages through the API (I use the API as a passthrough):

@Path("/api-docs")
@Produces( "text/html,text/css,text/javascript,image/png" )
public class ApiDocs {
    public static final String PETSTORE = "http://petstore.swagger.io/v2/swagger.json";
    @GET
    @Path("/{rest : .+}")
    public InputStream getReviews(@PathParam("rest") String rest) {
        String error;
        String webRootPath = {folder in filesystem where swagger-ui is stored};

        try {
            FileInputStream fi = new FileInputStream(new File(webRootPath + "\\api-docs\\" + rest));
            if ("index.html".equals(rest.toLowerCase())) {
                try {
                    String fileString = inputStream2String(fi);
                    if (fileString != null && !fileString.isEmpty()) {
                        if (fileString.contains(PETSTORE)) {
                            fileString = fileString.replaceFirst(PETSTORE, "https://" + {your API host address} + "/swagger.json");
                            return new ByteArrayInputStream(fileString.getBytes());
                        } else {
                            error = "Could not find: " + PETSTORE + " in index.html";
                        }
                    } else {
                        error = "Empty index.html";
                    }
                }catch(IOException ioException) {
                    error = "Error while reading index.html: " + ioException.getMessage();
                }
            } else {
                return fi;
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            error = e.getMessage();
        }

        return new ByteArrayInputStream(("Swagger-ui setup is not valid: " + webRootPath + (error != null ? " - " + error : "")).getBytes());
    }

    @GET
    public Response getIndex() {
        return Response.temporaryRedirect(URI.create("/api-docs/index.html")).build();
    }

    public String inputStream2String(InputStream in) throws IOException {
        StringBuffer out = new StringBuffer();
        byte[] b = new byte[4096];
        for (int i; (i = in.read(b)) != -1;) {
            out.append(new String(b, 0, i));
        }
        return out.toString();
    }

Reply all
Reply to author
Forward
0 new messages