nginxandroid-deep-link

Nginx conf for serving .well-known/assetslist.json for android deep links


I have an nginx conf as below through which i am trying to serve the /.well-known/assetslist.json file for Android deeplinks. The location block for it is not honored and the application deployed under the same sub-domain ends up handling the request. I want the url https://app.myapp.in/.well-known/assetslist.json to serve out of home/ubuntu/well-known directory

server {
    server_name app.myapp.in;  # Replace with your domain or IP


    location  ^~ /.well-known/ {
default_type application/json;
    allow all;
    auth_basic off;
    #alias /home/ubuntu/well-known;
    add_header "Access-Control-Allow-Origin"  *;
    add_header "Access-Control-Allow-Origin"  "$http_origin";
    add_header "Access-Control-Allow-Methods" "GET, POST, OPTIONS, HEAD";
    add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept";
    root /home/ubuntu/well-known;
    log_not_found  off;}


        root /home/ubuntu/app.myapp.in;
    index index.html;


    location / {
        try_files $uri $uri/ /index.html;
    }

    error_page 404 /404.html;

    access_log /var/log/nginx/static_site_access.log;
    error_log /var/log/nginx/static_site_error.log;

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/app.myapp.in/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/app.myapp.in/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {
    if ($host = app.fitshield.in) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80;
    server_name app.myapp.in;
    return 404; # managed by Certbot


}

Solution

  • You are incorrect in stating that "location block for it is not honored". I believe you may not fully understand the proper usage of the root and alias directives. Let me explain what happens when your nginx instance receives the incoming request for /.well-known/assetslist.json.

    1. Your location block

      location ~^ /.well-known/ {
          ...
          root /home/ubuntu/well-known;
      }
      

      selected to handle the request. Nginx then checks whether the file (or directory) /home/ubuntu/well-known/.well-known/assetslist.json exists. Since (I suppose) it does not, it returns a 404 Not Found HTTP error.

    2. The directive

      error_page 404 /404.html;
      

      takes effect, rewriting the request URI to /404.html.

    3. Nginx searches for the most appropriate location block for the rewritten URI and selects the

      location / {
          try_files $uri $uri/ /index.html;
      }
      

      to process it.

    4. Nginx checks whether /home/ubuntu/app.myapp.in/404.html file (or directory) exists. Since (I suppose) it does not, nginx falls back to /index.html, rewriting the request URI to /index.html.

    5. Nginx again selects the same location block:

      location / {
          try_files $uri $uri/ /index.html;
      }
      

      to handle the request.

    6. Finally, since /home/ubuntu/app.myapp.in/index.html exists, its content is returned as the response body.

    How can you fix this? Either rename the /home/ubuntu/well-known directory to /home/ubuntu/.well-known and use the root directive like this (recommended):

    location ~^ /.well-known/ {
        ...
        root /home/ubuntu;
    }
    

    Or, if renaming is not an option, use the alias directive correctly:

    location ~^ /.well-known/ {
        ...
        alias /home/ubuntu/well-known/;
    }
    

    (Note: The trailing slash matters!)