jcharls
jcharls

Reputation: 51

NGINX Alias path based on regex

I'm trying to add a new location block with an alias directive that are based on a dynamic URI to access different APIs. Right now I can do this manually adding each location block but was wondering if it could be mapped by using REGEX.

The problem is that it's returning a 404 error. I'm running a laravel sub app in a different folder on my server.

Any clues?

**

WORKING MANUALLY

location /api/product {
    alias /path/to/api/product/public;
    try_files $uri $uri/ @rewrite;

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_param SCRIPT_FILENAME $request_filename;
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
    }
}

location @rewrite {
    rewrite /api/product/(.*)$ /api/product/index.php?/$1 last;
}

ERROR 404 / No input file specified

location ~ /api/(.*) {
    alias /path/to/api/$1/public;
    try_files $uri $uri/ @rewrite;

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_param SCRIPT_FILENAME $request_filename;
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
    }
}

location @rewrite {
    rewrite /api/(.*)/(.*)$ /api/$1/index.php?/$2 last;
}

MORE TESTS

A

URL: app.tdl/api/tweets

Result: 'Index of /api/tweets/'

Output of $request_filename: /home/vagrant/code/Gateway/modules/tweets/app

location /api/tweets {
  alias /home/vagrant/code/Gateway/modules/tweets/app;
  autoindex on;
}

B

URL: app.tdl/api/tweets

Result: Nginx's 404

Output of $apiName: tweets

Output of $request_filename: /home/vagrant/code/Gateway/modules/tweets/app

location ~ "/api/(?<apiName>[^/]+)" {
  alias "/home/vagrant/code/Gateway/modules/$apiName/app" ;
  autoindex on;
}

Upvotes: 5

Views: 5387

Answers (1)

Richard Smith
Richard Smith

Reputation: 49692

alias inside a regular expression location requires the full path to the file to be captured. See the documentation for details.

Also, your existing capture is too greedy.

You may encounter problems using try_files with alias due to this long standing issue, you may want to replace it with an if block.

For example:

location ~ ^/api/(?<product>[^/]+)/(?<filename>.*)$ {
    alias /path/to/api/$product/public/$filename;

    if (!-e $request_filename) { 
        rewrite ^ /api/$product/index.php?/$filename last;
    }

    location ~ \.php$ {
        if (!-f $request_filename) { return 404; }
        ...
    }
}

Regular expression location blocks are evaluated in order. This block needs to be placed above any conflicting regular expression location block, such as another location ~ \.php$ block at the server block level.

The second if block is to avoid passing uncontrolled requests to PHP. See this caution on the use of if.

Upvotes: 10

Related Questions