Forum Discussion

krenaut's avatar
krenaut
Occasional Contributor
5 years ago
Solved

Can't execute API with swagger ui behind NGINX Plus kubernetes ingress

I am unsuccessfully trying to make Swagger UI work inside my kubernetes cluster.

 

I am running NGINX Plus as my kubernetes ingress controller.

 

The ingress is re-writing the URL path.

 

External path is /dev/hello-world/hello

Internal path is just /

 

The ingress is also terminating TLS on 443 and forwarding the request as plain HTTP on port 8080

 

Here is a sample of the request headers that are logged by my API:

Header 'host' = k8s-dev-kr.eastus.cloudapp.azure.com
Header 'x-real-ip' = 173.186.244.247
Header 'x-forwarded-for' = 173.186.244.247
Header 'x-forwarded-host' = k8s-dev-kr.eastus.cloudapp.azure.com
Header 'x-forwarded-port' = 443
Header 'x-forwarded-proto' = https
Header 'connection' = close
Header 'user-agent' = Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
Header 'accept' = */*
Header 'referer' = https://k8s-dev-kr.eastus.cloudapp.azure.com/dev/hello-world/hello/swagger-ui.html
Header 'accept-encoding' = gzip, deflate, br
Header 'accept-language' = en-US,en;q=0.9

 

I can access the swagger UI and navigate around, but I cannot execuite my API from Swagger UI.

 

When I click execute, I do not see any request hit my ingress controller, nothing is logged there.  Nor is anything logged by my API, the request does not appear to be getting to the kubernetes cluster.

 

My API is a spring boot rest application.

 

Here are my gradle dependencies to address any questions on what version I am running:

dependencies {
compile 'io.springfox:springfox-swagger2:2.9.2'
compile 'io.springfox:springfox-swagger-ui:2.9.2'
compile group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
compile group: 'commons-codec', name: 'commons-codec', version: '1.9'
compile 'org.apache.httpcomponents:httpclient:4.5.9'
compile 'org.apache.httpcomponents:httpclient-cache:4.5.9'
compile 'org.apache.httpcomponents:httpmime:4.5.9'
compile 'org.apache.httpcomponents:fluent-hc:4.5.9'
compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.13'
compile 'org.springframework.boot:spring-boot-starter-jdbc'
compile group: 'com.auth0', name: 'java-jwt', version: '3.8.1'
compile group: 'com.auth0', name: 'jwks-rsa', version: '0.8.2'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

 

Here is my SwaggerConfig class, I added the pathMapping to try to address the path re-write function of the ingress:

@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Value("${kubernetes.path}")
private String kubePath;
Logger log = LoggerFactory.getLogger(SwaggerConfig.class);
@Bean
public Docket api() {
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
// if running in kubernetes change the pathMapping
// the KUBERNETES_SERVICE_HOST environment variable is always set by kubernetes.
// So I am using it to detect that we are running on kubernetes
if (System.getenv("KUBERNETES_SERVICE_HOST") != null) {
log.debug("Kubernetes detected! Setting pathMapping to: " + kubePath);
docket.pathMapping(kubePath);
}
return docket;
}
}

 

The only error I see in my logs is a 404 not found for GET "//csrf", parameters={}

 

But I don't think that has anything to do with my problem.  I think the clientside java script is using a bad URL but, I do ot know how to tell what URL it is using.

 

Any help on this is greatly appreciated!

 

Thanks in advance!

 

Karl

  • I was able to get this working using a combination of the stand alone UI and the following code snippet in my SwaggerConfig.

     

            // if running in kubernetes change the pathMapping and force https

            // the KUBERNETES_SERVICE_HOST environment variable is always set by kubernetes.

            // So I am using it to detect that we are running on kubernetes

            // I then set the pathMapping to include the portion of the path that

            // kubernetes prepends (in this case /dev/hell-world/hello )

            // then I also force the protocol to HTTPS

            if (System.getenv("KUBERNETES_SERVICE_HOST") != null) {

                log.debug("Kubernetes detected! Setting pathMapping to: " + kubePath);

                docket.pathMapping(kubePath);

                docket.protocols(newHashSet("https"));

            }

3 Replies

    • krenaut's avatar
      krenaut
      Occasional Contributor

      It appears that the issue is the conversion from HTTPS to HTTP.  I think because the spring boot app is written and plain HTTP that must appear in the API definition somewhere.  But the reverse proxy expects HTTPS.  Is there someway I can force Swagger UI to access the API with HTTPS even tho its coded as HTTP?

      • krenaut's avatar
        krenaut
        Occasional Contributor

        I was able to get this working using a combination of the stand alone UI and the following code snippet in my SwaggerConfig.

         

                // if running in kubernetes change the pathMapping and force https

                // the KUBERNETES_SERVICE_HOST environment variable is always set by kubernetes.

                // So I am using it to detect that we are running on kubernetes

                // I then set the pathMapping to include the portion of the path that

                // kubernetes prepends (in this case /dev/hell-world/hello )

                // then I also force the protocol to HTTPS

                if (System.getenv("KUBERNETES_SERVICE_HOST") != null) {

                    log.debug("Kubernetes detected! Setting pathMapping to: " + kubePath);

                    docket.pathMapping(kubePath);

                    docket.protocols(newHashSet("https"));

                }