Clean-URL rewrite rule with nested "location" and alias directive
Ben Johnson
ben at indietorrent.org
Tue Nov 19 22:48:59 UTC 2013
On 11/19/2013 3:39 PM, Francis Daly wrote:
> On Tue, Nov 19, 2013 at 01:45:15PM -0500, Ben Johnson wrote:
>> On 11/19/2013 12:38 PM, Francis Daly wrote:
>>> On Tue, Nov 19, 2013 at 10:36:53AM -0500, Ben Johnson wrote:
>
> Hi there,
>
>>>> This works as expected, with one major exception: "clean-URL" rewriting
>>>> does not work. In other words, the homepage (/stage/) loads correctly,
>>>> but all sub-pages return a 404.
>
> Which nginx version do you use, where you get that output with the config
> snippet that you provided?
>
> I've tried 1.4.3 and 1.5.7, and I don't get /stage/ to load correctly.
>
> I suspect I'm just doing something silly.
>
Given your level of expertise, I doubt that you're doing anything wrong.
:) I'm using nginx-1.1.19, because that's what's bundled with Ubuntu
12.04 LTS. It makes sense that without the rewrite rules in-place, only
"index.php" (via /stage/) returns a 200 response and not a 404.
>> Certainly: an example URL is /stage/my-account/ . Ultimately, I would
>> like for this URL to be rewritten to
>> /stage/index.php?q=/stage/my-account/ (the file "index.php" exists on
>> the filesystem at /var/www/example.com/private/stage/web/index.php).
>
> I think that the problem may be due to the interaction between "alias"
> and "$document_root" being not-always-obvious.
>
> And $document_root is used in try_files, which is probably what you
> want for "clean URLs" -- serve the file if present, else hand it to
> a controller.
>
I think that you're exactly right. I had tried try_files first, but was
unable to get it to work given that this site a) must be accessed via a
"subdirectory" relative to the domain-root URL, and b) is comprised of
files that live in a "private" directory that is outside of the
server-root on the filesystem.
> Does the following do what you want for all cases you care about?
>
> ===
> location ^~ /stage/ {
> alias /var/www/example.com/private/stage/web/;
> index index.php index.html index.htm;
> try_files $uri $uri/ /stage//stage/index.php?q=$uri;
>
> location ~ ^/stage/(.+\.php)$ {
> alias /var/www/example.com/private/stage/web/$1;
> try_files "" / /stage/index.php?q=$uri;
> fastcgi_pass unix:/var/run/php5-fpm.sock;
> fastcgi_param HTTPS on;
> fastcgi_param SCRIPT_FILENAME $request_filename;
> include /etc/nginx/fastcgi_params;
> }
> }
> ===
>
Wow, that actually works! While I don't fully understand the try_files
magic, I didn't think try_files would ever serve the purpose because I
had read at http://wiki.nginx.org/HttpCoreModule#alias : "Note that
there is a longstanding bug that alias and try_files don't work
together" (with link to http://trac.nginx.org/nginx/ticket/97 ).
While I do realize that the above-cited Wiki is obsolete and the current
reference is at
http://nginx.org/en/docs/http/ngx_http_core_module.html#alias , the
referenced bug does not appear to have been closed.
Is the implication here that "alias" does indeed work with "try_files"
(even in my stale nginx-1.1.19 version)? At least in this particular
use-case?
There is one last trick to pull-off, which is to add very similar
clean-URL functionality for two other files (in addition to index.php),
but I am hoping that I will be able to adapt your working sample myself.
> You may want to use something other than $uri in the last argument to
> try_files, depending on how you want /stage/my-account/?key=value to
> be processed.
>
Understood; that makes sense.
> And the curious-looking try_files lines are deliberate.
>
> f
>
You are a true guru, Francis. I can't thank you enough; I've been
struggling with this for days. This is the second time that you've
come-up huge for me.
Respectfully,
-Ben
More information about the nginx
mailing list