0

I am tasked with administering a web application that has a base directory with a bunch of legacy code in it, and a subdirectory of my own making with an MVC based API which we are using to slowly migrate the front end to a SPA model. The owner has gotten a wild hare up his ass and decreed that we are to move to nginx.

I have extensive experience in Apache rewrites, and it would take me about nine seconds to set this up in Apache. However, as people are quick to point out, nginx is not Apache. While I can get either section of the application to work on its own in nginx, I cannot get the API to play nice with the main application when it is in its /api/ directory.

I'm guessing that it will be some permutation of the location directive, which appears to behave similarly to in Apache. Basically, if anything hits the /api/ directory, I need to pass the remainder of the uri to /api/public/index.php with the rewrite:

^/(.*)$ public/index.php?_url=/$1;

Any help is greatly appreciated.

Existing config:

 server {
            listen          10.1.1.225:443 ssl;
            server_name dev.domain.com;
            ssl_certificate /etc/nginx/conf.d/chain.crt;
            ssl_certificate_key /etc/nginx/conf.d/4096_SSL.key;
            set $root_path '/usr/share/nginx/www';
            root $root_path/trunk;
            index index.php index.html;
            fastcgi_param ENV development;
            fastcgi_buffers 8 16k;
            fastcgi_buffer_size 32k;
            fastcgi_read_timeout 180;
            location / {
                    try_files $uri $uri/ =404;
            }

            location ^~ /api {
                    rewrite ^/(.*)$ public/index.php?_url=/$1;
            }

            fastcgi_intercept_errors off;

            location ~ \.php {
                    fastcgi_pass   unix:/var/run/php-fpm.sock;
                    fastcgi_split_path_info ^(.+\.php)(.*)$;
                    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                    include        fastcgi_params;
            }
    }

This config is ugly because I've been playing with it all day, but it should get the point across.

Peter
  • 123
  • 1
  • 1
  • 7

2 Answers2

1

You're right that nginx isn't apache, and that means that most of the places you might think of using rewrite, are inappropriate. Instead you should try to use try_files. For instance:

location /api/ {
    try_files $uri /api/public/index.php?_url=$request_uri;
}
Michael Hampton
  • 244,070
  • 43
  • 506
  • 972
  • This appears to have done the trick. I'm still learning nginx, and I do like how concise and expressive its directives are, I just wish that the boss would be a bit more pragmatic about big decisions like this. I think that he literally read a book or article about nginx over the weekend and decided that it sounded nice. Thanks again. – Peter Sep 02 '14 at 18:48
  • nginx is nice, but you'll have to unlearn a lot of Apache stuff in order to get the most mileage out of it. This won't happen overnight. :) – Michael Hampton Sep 02 '14 at 18:50
  • One quick question, I didn't notice it because of other errors, but the MVC is trying to get the ApiController, and can't find it because the request_uri still has the /api at the beginning, any way nginx can remove that when it passes the uri to the bootstrapper? I can handle it with php's substr function, but that seem inelegant. – Peter Sep 02 '14 at 19:00
  • 1
    You should have been receiving the entire URL before; this really is something the app should be handling in the front controller. – Michael Hampton Sep 02 '14 at 19:03
  • It's definitely not passing the entire thing in Apache. Guess I'll keep reading. Thanks. – Peter Sep 02 '14 at 19:21
  • this should not be the accepted answer. I'm looking for the same thing and ended with the same problem. Nginx can do this without having to replace in php. – JaseC Mar 20 '15 at 04:13
  • @JaseC I'm sure Peter will be happy to hear from you that you think it should not work for him. As for whatever problem you had, maybe nginx _can_ do this, but application logic really should not be in the web server, even if it's capable of it. This causes your app to be tied to a specific web server, makes it more difficult or even impossible to test your application routing, and probably has other problems I can't think of right now. – Michael Hampton Mar 20 '15 at 04:19
0

For others looking on this replace:

location ^~ /api {
                    rewrite ^/(.*)$ public/index.php?_url=/$1;
            }

with

rewrite ^/api(/.*)$ /api/public/index.php?_url=$1 last;
JaseC
  • 101
  • 1