nginx won't serve json file unless specifying .json in url

I have the following nginx.conf file:

server {
    listen 8080;
    server_name dummy_server;

    root /usr/share/nginx/html;

    location / {
      if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain; charset=utf-8';
        add_header 'Content-Length' 0;
        return 204;
      }

      default_type 'application/json';
      add_header 'Access-Control-Allow-Origin' '*' always;
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
      add_header 'Content-Type' 'application/json';
      if ($request_uri ~* "([^/]*$)" ) {
        set  $last_path_component  $1;
      }

      try_files $last_path_component.json $last_path_component.json =404;
    }
  }

I would like to serve healthcheck.json when localhost:8080/v1/healthcheck is requested. However, nginx refuses to serve any json file if I'm not explicitly hitting localhost:8080/v1/healthcheck.json, otherwise it logs file not found, and the response is nginx's 404 page. If I add .json at the end of the url, the file is magically found and great magic happens. I tried forcing application/json type, as well as changing the try files row to explicitly return the file I would like to return (so I've set try_files healthcheck.json =404;) all returns the same issue.

I'm quite lost.. anyone have any ideas?


This is actually an expected behavior with this config. So, what you are doing, is stripping the URL and then passing it to try_files.
But there is nothing in try_files to handle files without an extension. To do that, modify it like this

try_files $last_path_component $last_path_component.json $last_path_component.json =404;

This will allow you to serve .json files without extension. However, this will not serve the same .json file with or without extension. The try_files directive checks the existence of the files and serves them in this order. So if you have healthcheck.json and try to access it via localhost:8080/v1/healthcheckit will still fail. So you need to have healthcheck end-point to be actually without an extension on the server for it to be accessible.

If you want to handle both variations, with or without extension, you might want to strip the .json part first like this

    if ($request_uri ~ ^/([^?]*)\.json(\?.*)?$) {
         return 302 /$1$2;
    }

    try_files $uri $uri.json =404;

    }