nginx pretty url rewrite

Sometimes things just don’t work like they should. So it was with url rewriting using nginx 1.6 and php 5.6 through fastcgi for me, using a Symfony 2.3 project. The examples out there use all kinds of different techniques that make all kinds of assumptions.

The file I’m looking at is /etc/nginx/conf.d/ssl.conf for https and /etc/nginx/conf.d/default.conf for http. You’ll probably have fastcgi enabled (I did through php56w-fpm from webtatic on centos) and if you want nice urls like https://yourhost/yourapp/cool-link-to-this you’ll need to do some pretty url rewrite.

There are a LOT of ways of doing it, here’s what worked for me, a combination I had trouble finding online.

In the server block you’ll have your fastcgi php config, something like:
location ~ .php$ {
try_files $uri=404
}

If yours isn’t exactly like this, don’t worry, the important part is the location line. Don’t change it, just make note of it. If it’s .php$ like mine is, then this mean the last part of the URL has to end with .php or it won’t be treated as a php script. So /yourapp/app.php?blah works but /yourapp/app.php/blah does not. This is important in what rewrite rules will work for you.

If you had something like:
location ~ .php(/|$) {
Then urls like /yourapp/app.php/blah may work, but I have a feeling this is a little less secure. Notice that changing this block didn’t solve my problems, so I opted to leave it with the stricter .php$ on my server.

After this block I added my rewrite rule for my application.
location /myapp/ {
index app.php
try_files $uri $uri/ @rewriteapp;
}

location @rewriteapp {
rewrite ^/myapp(/.*)?$ /myapp/app.php?$1 last;
}

A bunch of stuff is happening here, and you’ll need a set of these for every app you want pretty urls. You could make the location just / for the root of your domain, but mine was in a subdirectory.

The first thing is that I have a trailing slash on /myapp/ in the first location block. I don’t know if this is important, but that’s how the nginx documentation lists it so that’s what I did too.

Next, the index app.php tells it that my default index is not index.php but app.php. This is because I’m using the Symfony php framework, and it uses app.php for production and app_dev.php for development. Change it to what you use in your project.

This next line was different in a lot of places on the internet. I’m not convinced I need to use the @rewriteapp convention, that I could put the destination php script right there, but I don’t have a working example of that and the @location was popular when I did my googling.

You’ll want to make sure you have both $uri and $uri/ on the try_files line, in case the user forgets to put a trailing slash, this makes /myapp and /myapp/ both work. The @rewriteapp must be a unique name, so change it for each app you make. That passes processing if it can’t match to an existing file or directory.

In the @rewriteapp section, I had to tweak things as well. The first part says to match anything with /myapp at the start of the url, with any amount of stuff following it. The next part says what to rewrite it to, in this case the specific url where the php file is exposed from the web, app.php. Notice I used a ? in app.php?$1 here, some examples use a slash, app.php/$1 but that won’t work if your fastcgi config is like mine was far above. Lastly the ‘last’ says not to process any more rules. Some people have ‘permanent’ here but that’s not correct and will lead to problems if you change your url scheme.

I don’t really know the innards of what is going on or why everything is working, but this is what I had to do to get it working, and it was different to the other answers online. So try mine, then try theirs, and if none of them work but you figure it out write your own article!

Don’t forget to be awesome.