Running Spring Boot application with springdoc-openapi behind NGINX

Suppose you want all requests prefixed with /api to be forwarded by NGINX to spring boot. There are 2 common options:

  1. Strip out the /api prefix before sending the request to spring boot (NGINX calls this an upstream server). This is done as follows:
location ~ ^/api(/|$) {
        rewrite ^/api(/|$)(.*)$ /$2 break; 

So when a request like GET /api/foo is made when it reaches spring boot, spring boot sees a request to GET /foo.

  1. The second option is not to rewrite the URL.

The problem with option 1 is that the Swagger UI will then make XHR requests without the /api prefix and those requests will fail resulting in a broken UI. So in my case the option that has worked better is option 2. If we opt-in for option 2, we now have to tell Spring boot that all controllers should be prefixed with a base path of /api. This is easily done using following setting in application.properties:

# application.properties
server.servlet.context-path=/api

Alternatively one could use:

openapi.honeyBadgerOpenAPIDefinition.base-path=/api
springdoc.swagger-ui.path=/api/swagger-ui.html
springdoc.api-docs.path=/api/v3/api-docs

The first line has to be replaced with corresponding value in the generated Controller java code. In my case I have:

@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2025-03-21T20:08:34.471664377-07:00[America/Los_Angeles]", comments = "Generator version: 7.4.0")
@RequestMapping("${openapi.honeyBadgerOpenAPIDefinition.base-path:}")
public class QueryApiController implements QueryApi {

There is one more piece I had to do to make it work. I was terminating TLS at NGINX and this caused Swagger UI to generate XHR requests with a http prefix which then causes Mixed Content warning in the browser and breaks the UI. This is fixed by adding following NGINX directive:

proxy_set_header X-Forwarded-proto https;

and also following application.properties:

server.forward-headers-strategy=NATIVE
server.use-forward-headers=true

Alternatively this also works:

server.forward-headers-strategy=framework
server.use-forward-headers=true

I recommend adding following directives as well for best results to the NGINX conf:

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';  # the Upgrade header has no effect unless Connection 'upgrade' header is also present
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

The complete NGINX conf becomes:

location ~ ^/api(/|$) {        
        proxy_pass http://127.0.0.1:xxxx;  # Forward requests to spring boot
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';  
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-proto https; 
    }
This entry was posted in Computers, programming, Software and tagged , . Bookmark the permalink.

Leave a comment