NGINX Alias path based on regex










1















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;










share|improve this question




























    1















    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;










    share|improve this question


























      1












      1








      1








      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;










      share|improve this question
















      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;







      nginx






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 14 '18 at 20:20







      jcharls

















      asked Nov 13 '18 at 11:19









      jcharlsjcharls

      62




      62






















          1 Answer
          1






          active

          oldest

          votes


















          0














          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.






          share|improve this answer

























          • Thanks, Richard. That makes sense and I think it should work but still getting the "no input file specified" message. Perhaps the rewrite rule could be missing something?

            – jcharls
            Nov 13 '18 at 12:16












          • I'm not sure if the rewrite statement is correct - where is index.php? Inside the public directory or above it?

            – Richard Smith
            Nov 13 '18 at 12:20












          • Each API has it's own /absolute/path/to/apiName/public/index.php (Laravel APPs).

            – jcharls
            Nov 13 '18 at 14:25











          • I have checked and the $product and $filename works as expected. The rewrite statement should be the responsable for the 404. I've tried this one: rewrite /api/$product/$filename /api/$product/index.php?/$filename last;

            – jcharls
            Nov 13 '18 at 14:48











          • Sorry, I confused myself. The /public/ should not appear in the rewritten URI. The first parameter to the rewrite statement needs to be a regular expression, and I use ^ as it will match anything. In the above, the URI /api/<product>/index.php will be searched for in /path/to/api/<product>/public/index.php.

            – Richard Smith
            Nov 13 '18 at 15:22










          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53279886%2fnginx-alias-path-based-on-regex%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          0














          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.






          share|improve this answer

























          • Thanks, Richard. That makes sense and I think it should work but still getting the "no input file specified" message. Perhaps the rewrite rule could be missing something?

            – jcharls
            Nov 13 '18 at 12:16












          • I'm not sure if the rewrite statement is correct - where is index.php? Inside the public directory or above it?

            – Richard Smith
            Nov 13 '18 at 12:20












          • Each API has it's own /absolute/path/to/apiName/public/index.php (Laravel APPs).

            – jcharls
            Nov 13 '18 at 14:25











          • I have checked and the $product and $filename works as expected. The rewrite statement should be the responsable for the 404. I've tried this one: rewrite /api/$product/$filename /api/$product/index.php?/$filename last;

            – jcharls
            Nov 13 '18 at 14:48











          • Sorry, I confused myself. The /public/ should not appear in the rewritten URI. The first parameter to the rewrite statement needs to be a regular expression, and I use ^ as it will match anything. In the above, the URI /api/<product>/index.php will be searched for in /path/to/api/<product>/public/index.php.

            – Richard Smith
            Nov 13 '18 at 15:22















          0














          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.






          share|improve this answer

























          • Thanks, Richard. That makes sense and I think it should work but still getting the "no input file specified" message. Perhaps the rewrite rule could be missing something?

            – jcharls
            Nov 13 '18 at 12:16












          • I'm not sure if the rewrite statement is correct - where is index.php? Inside the public directory or above it?

            – Richard Smith
            Nov 13 '18 at 12:20












          • Each API has it's own /absolute/path/to/apiName/public/index.php (Laravel APPs).

            – jcharls
            Nov 13 '18 at 14:25











          • I have checked and the $product and $filename works as expected. The rewrite statement should be the responsable for the 404. I've tried this one: rewrite /api/$product/$filename /api/$product/index.php?/$filename last;

            – jcharls
            Nov 13 '18 at 14:48











          • Sorry, I confused myself. The /public/ should not appear in the rewritten URI. The first parameter to the rewrite statement needs to be a regular expression, and I use ^ as it will match anything. In the above, the URI /api/<product>/index.php will be searched for in /path/to/api/<product>/public/index.php.

            – Richard Smith
            Nov 13 '18 at 15:22













          0












          0








          0







          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.






          share|improve this answer















          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.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 13 '18 at 15:12

























          answered Nov 13 '18 at 11:42









          Richard SmithRichard Smith

          19.7k42137




          19.7k42137












          • Thanks, Richard. That makes sense and I think it should work but still getting the "no input file specified" message. Perhaps the rewrite rule could be missing something?

            – jcharls
            Nov 13 '18 at 12:16












          • I'm not sure if the rewrite statement is correct - where is index.php? Inside the public directory or above it?

            – Richard Smith
            Nov 13 '18 at 12:20












          • Each API has it's own /absolute/path/to/apiName/public/index.php (Laravel APPs).

            – jcharls
            Nov 13 '18 at 14:25











          • I have checked and the $product and $filename works as expected. The rewrite statement should be the responsable for the 404. I've tried this one: rewrite /api/$product/$filename /api/$product/index.php?/$filename last;

            – jcharls
            Nov 13 '18 at 14:48











          • Sorry, I confused myself. The /public/ should not appear in the rewritten URI. The first parameter to the rewrite statement needs to be a regular expression, and I use ^ as it will match anything. In the above, the URI /api/<product>/index.php will be searched for in /path/to/api/<product>/public/index.php.

            – Richard Smith
            Nov 13 '18 at 15:22

















          • Thanks, Richard. That makes sense and I think it should work but still getting the "no input file specified" message. Perhaps the rewrite rule could be missing something?

            – jcharls
            Nov 13 '18 at 12:16












          • I'm not sure if the rewrite statement is correct - where is index.php? Inside the public directory or above it?

            – Richard Smith
            Nov 13 '18 at 12:20












          • Each API has it's own /absolute/path/to/apiName/public/index.php (Laravel APPs).

            – jcharls
            Nov 13 '18 at 14:25











          • I have checked and the $product and $filename works as expected. The rewrite statement should be the responsable for the 404. I've tried this one: rewrite /api/$product/$filename /api/$product/index.php?/$filename last;

            – jcharls
            Nov 13 '18 at 14:48











          • Sorry, I confused myself. The /public/ should not appear in the rewritten URI. The first parameter to the rewrite statement needs to be a regular expression, and I use ^ as it will match anything. In the above, the URI /api/<product>/index.php will be searched for in /path/to/api/<product>/public/index.php.

            – Richard Smith
            Nov 13 '18 at 15:22
















          Thanks, Richard. That makes sense and I think it should work but still getting the "no input file specified" message. Perhaps the rewrite rule could be missing something?

          – jcharls
          Nov 13 '18 at 12:16






          Thanks, Richard. That makes sense and I think it should work but still getting the "no input file specified" message. Perhaps the rewrite rule could be missing something?

          – jcharls
          Nov 13 '18 at 12:16














          I'm not sure if the rewrite statement is correct - where is index.php? Inside the public directory or above it?

          – Richard Smith
          Nov 13 '18 at 12:20






          I'm not sure if the rewrite statement is correct - where is index.php? Inside the public directory or above it?

          – Richard Smith
          Nov 13 '18 at 12:20














          Each API has it's own /absolute/path/to/apiName/public/index.php (Laravel APPs).

          – jcharls
          Nov 13 '18 at 14:25





          Each API has it's own /absolute/path/to/apiName/public/index.php (Laravel APPs).

          – jcharls
          Nov 13 '18 at 14:25













          I have checked and the $product and $filename works as expected. The rewrite statement should be the responsable for the 404. I've tried this one: rewrite /api/$product/$filename /api/$product/index.php?/$filename last;

          – jcharls
          Nov 13 '18 at 14:48





          I have checked and the $product and $filename works as expected. The rewrite statement should be the responsable for the 404. I've tried this one: rewrite /api/$product/$filename /api/$product/index.php?/$filename last;

          – jcharls
          Nov 13 '18 at 14:48













          Sorry, I confused myself. The /public/ should not appear in the rewritten URI. The first parameter to the rewrite statement needs to be a regular expression, and I use ^ as it will match anything. In the above, the URI /api/<product>/index.php will be searched for in /path/to/api/<product>/public/index.php.

          – Richard Smith
          Nov 13 '18 at 15:22





          Sorry, I confused myself. The /public/ should not appear in the rewritten URI. The first parameter to the rewrite statement needs to be a regular expression, and I use ^ as it will match anything. In the above, the URI /api/<product>/index.php will be searched for in /path/to/api/<product>/public/index.php.

          – Richard Smith
          Nov 13 '18 at 15:22

















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53279886%2fnginx-alias-path-based-on-regex%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          這個網誌中的熱門文章

          How to read a connectionString WITH PROVIDER in .NET Core?

          Node.js Script on GitHub Pages or Amazon S3

          Museum of Modern and Contemporary Art of Trento and Rovereto