swagger-api / swagger-core

Examples and server integrations for generating the Swagger API Specification, which enables easy access to your REST API
http://swagger.io
Apache License 2.0
7.39k stars 2.19k forks source link

How to fix URLs displayed in Swagger UI? #3404

Open justincranford opened 4 years ago

justincranford commented 4 years ago

I am running my APIs with servlet path /restapis, and Swagger UI with servlet path /. My auto-generated /restapis/openapi.json renders in Swagger UI, but the paths are wrong.

I am launching Jetty 9.4.22.v20191022 from a POJO. Context path is /, and there are two servlets.

  1. /restapis => Jersey 2.29.1 Servlet with init parameter (jersey.config.server.provider.classnames=io.swagger.v3.jaxrs2.integration.resources.OpenApiResource,com.example.rest.Resource1)
  2. / => Jetty Default Servlet with welcome files = {index.html}, and context base = unpacked Swagger UI 3.24.3 directory.

The unpacked index.html is modified to replace the default URL, similar to how https://github.com/swagger-api/swagger-ui/blob/master/docker/run.sh#L35 is substituting it.

In Swagger UI, I expect to see /restapis/resource1, but it shows /resource1 instead. If I use Swagger UI to try to execute that API, Swagger UI displays HTTP 404 response from the API.

webron commented 4 years ago

Which version of swagger-core do you use?

justincranford commented 4 years ago

Edit: I am using latest Swagger Core 2.1.1. I was using Swagger Core 2.1.0 which was latest at the time. No difference.

Excerpts from my pom.xml:

<dependencyManagement>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.eclipse.jetty/jetty-bom -->
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-bom</artifactId>
            <version>9.4.25.v20191220</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.glassfish.jersey/jersey-bom -->
        <dependency>
            <groupId>org.glassfish.jersey</groupId>
            <artifactId>jersey-bom</artifactId>
            <version>2.29.1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-jdk14 -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-jdk14</artifactId>
        <version>1.7.30</version>
        <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.json/javax.json-api -->
    <dependency>
        <groupId>javax.json</groupId>
        <artifactId>javax.json-api</artifactId>
        <version>1.1.4</version>
        <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.glassfish/javax.json -->
    <dependency>
        <groupId>org.glassfish</groupId>
        <artifactId>javax.json</artifactId>
        <version>1.1.4</version>
        <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.eclipse.jetty/jetty-servlet -->
    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-servlet</artifactId>
        <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.glassfish.jersey.containers/jersey-container-jetty-http -->
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-jetty-servlet</artifactId>
        <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.glassfish.jersey.inject/jersey-hk2 -->
    <dependency>
        <groupId>org.glassfish.jersey.inject</groupId>
        <artifactId>jersey-hk2</artifactId>
        <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/io.swagger.core.v3/swagger-jaxrs2 -->
    <dependency>
        <groupId>io.swagger.core.v3</groupId>
        <artifactId>swagger-jaxrs2</artifactId>
        <version>2.1.1</version>
        <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/io.swagger.core.v3/swagger-jaxrs2-servlet-initializer -->
    <dependency>
        <groupId>io.swagger.core.v3</groupId>
        <artifactId>swagger-jaxrs2-servlet-initializer</artifactId>
        <version>2.1.1</version>
        <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.webjars/swagger-ui -->
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>swagger-ui</artifactId>
        <version>3.24.3</version>
        <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/junit/junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>
Break-1T commented 1 month ago

I had a similar problem and fixed it with swagger servers(https://swagger.io/docs/specification/v3_0/api-host-and-base-path/). My application is a server that manages other servers, and to access other servers, I use a proxy. For example, to access some server, I need to make the following request: {main_server_url}/router/{server_name}/{endpoint}.  And for all that, I need one swagger instance that would display the swagger of the main server and other servers. Here are some c# code where i implement middleware that adds swagger server

app.UseSwagger(option =>
{
    option.PreSerializeFilters.Add((document, httpRequest) =>
    {
        OpenApiServer server = null;

        if (env.IsDevelopment())
        {
            server = new OpenApiServer
            {
                Url = $"{httpRequest.Scheme}://{httpRequest.Host.Value}",
                Description = "Path to access worker endpoints",
            };
        }
        else
        {
            server = new OpenApiServer
            {
                Url = "/{proxy_path}" + $"/{workerName}",
                Description = "Path to access worker endpoints",
                Variables = new Dictionary<string, OpenApiServerVariable>
                {
                    {
                        "proxy_path",
                        new OpenApiServerVariable
                        {
                            Enum = ["router", "proxy"],
                            Default = "router",
                        }
                    },
                },
            };
        }

        document.Servers.Add(server);
    });
});

I hope this will be useful in your case.