Ruby Forum NGINX > Serving static versions of dynamic pages (non-RoR)

Posted by Ian M. Evans (Guest)
on 07.08.2008 09:41
(Received via mailing list)
As you might remember from the "fastcgi php migration" thread back in
March, the list helped solve a problem migrating our apache setup where
php ran through files with extensions (.php, .shtml) and extensionless
files (e.g. /galleries/123/72 where galleries is a php script NOT a
directory and /123/72 were the arguments or /some-event/day1/photos/12
where photos was a php script that could be located in any depth of 
subdirs)

The solutions suggested by Igor and the list have worked perfectly.
Thanks again!

I've been looking at various .conf's and have seen how they handle Rails
static caching and I'm wondering how to apply that in my non-Rails 
setup.

Sometimes after a big event we can get hammered (once even getting
listed on a Yahoo! news page) and I've thought about creating static
versions of my script pages using php and curl or something.

I'd have two situations. One where an extensioned but argument-less php
script had a cached .html version and second where an extensionless
script and its pathinfo had a cached version

1) In the first case, say I had a database hungry file at:
/tribeca-fest/winners.shtml and I created a cached version as
/tribeca-fest/winners.shtml.html am I correct in assuming that:

if (-f $request_filename.html) {
break;
}

would serve it properly?

2) The 2nd case would be a little more crazy and I'm not sure if it's
doable.

Let's say I have the extensionless file "galleries" in the root and it's
pathinfo can be:
/galleries/123/     <- an overview listing
/galleries/123/5    <- a more detailed listing
/galleries/123/5/72 <- an individual photo

I could create three cache files:
/galleries_123.html
/galleries_123_5.html
/galleries_123_5_72.html

Is there anyway for nginx to translate a request for /galleries/123/5/72
or the other two examples into their underscore seperated .html 
equivalent?

I'm thinking that handling #1 is dead easy but the problem in #2 might
be a little nuts? :-)

Thanks for any advice.
Posted by Jean-Philippe (Guest)
on 07.08.2008 13:41
(Received via mailing list)
Ian M. Evans a écrit :
> 
> 
> 1) In the first case, say I had a database hungry file at:
> /tribeca-fest/winners.shtml and I created a cached version as 
> /tribeca-fest/winners.shtml.html am I correct in assuming that:
> 
> if (-f $request_filename.html) {
> break;
> }
> 
> would serve it properly?

You have to rewrite your request for nginx to understand that it should 
serve
the cached version. Common rails recipes use :

     if (-f $request_filename/index.html)
     {
       rewrite ^(.*)$ $1/index.html break;
     }

     if (-f $request_filename.html)
     {
       rewrite ^(.*)$ $1.html break;
     }

(So it can be used for directories and files, you may want to skip the 
first part.)

> I could create three cache files:
> /galleries_123.html
> /galleries_123_5.html
> /galleries_123_5_72.html
> 
> Is there anyway for nginx to translate a request for /galleries/123/5/72 
> or the other two examples into their underscore seperated .html equivalent?

Seems tricky if you want to test the cache existence and not simply 
rewrite to
the underscored version (which could be done with a simple rewrite).

Maybe an if block like this :

if ($request_filename ~ (foo)/(bar)/(baz)) {
set $foo $1;
set $bar $2;
set $baz $3;
}

Could be used before another if block to check the local file.
Posted by Ian M. Evans (Guest)
on 07.08.2008 17:10
(Received via mailing list)
Jean-Philippe wrote:
>     if (-f $request_filename.html)
>     {
>       rewrite ^(.*)$ $1.html break;
>     }

Okay, thanks.

> Seems tricky if you want to test the cache existence and not simply 
> rewrite to the underscored version (which could be done with a simple 
> rewrite).
 > Maybe an if block like this :
 >
 > if ($request_filename ~ (foo)/(bar)/(baz)) {

Yeh, I figured the second part of the wish list would be the nutty one.
It's too bad there's not a way (unless there is and I have to read
deeper!) to string replace the pathinfo so you could just test something
like:

location /galleries {
if ($request_filename.underscoredpathinfo.html) {...etc...

I guess I may have to consider something like Varnish, though I've read
that nginx's ability to serve up static files can sometimes even be
faster than memory caches due to filesystem caching.
}
Posted by Ian M. Evans (Guest)
on 09.08.2008 06:24
(Received via mailing list)
Jean-Philippe wrote:
> Seems tricky if you want to test the cache existence and not simply 
> rewrite to the underscored version (which could be done with a simple 
> rewrite).

Right...is it correct to say that nginx can't regex replace BEFORE a
file test? That is, the logic can say:

if the request is in location /galleries rewrite and serve up
/galleries[path slashes converted to underscores].html

  but it can't say:
if the request is in location /galleries rewrite the URI to
/galleries[path slashes converted to underscores].html, check to see if
that exists and if so, serve it up?
Posted by Jean-Philippe Moal (Guest)
on 09.08.2008 15:04
(Received via mailing list)
Ian M. Evans a écrit :
> 
>  but it can't say:
> if the request is in location /galleries rewrite the URI to 
> /galleries[path slashes converted to underscores].html, check to see if 
> that exists and if so, serve it up?
> 
I don't think the location directive sets $n ($1, $2 etc...) variables 
like the
"if" directive, so the only way to do this may be using the perl module.

Otherwise you could still create your cache files using the same layout 
as your
URLs (by creating multiples directories and subdirectories).
Posted by Ian M. Evans (Guest)
on 09.08.2008 16:43
(Received via mailing list)
Jean-Philippe Moal wrote:
> Otherwise you could still create your cache files using the same layout 
> as your URLs (by creating multiples directories and subdirectories).

Ah, I had an brief inkling of that thought last night.

So I'd have my PHP cache code create different dirs and index files so
you'd have

/galleries/1  => /galleries/1/index.html
/galleries/1/27  => /galleries/1/27/index.html
/galleries/1/27/8  => /galleries/1/27/8/index.html

Since /galleries is actually a FILE in the root, not a directory, could
I create a cache dir with a galleries dir elsewhere and say something
like this:

if (-f /cache/$request_filename/index.html)
     {
       rewrite ^(.*)$ /cache/$1/index.html break;
     }

[No idea if that's the right way to do the syntax]

Also...is there any magic I'd need to do if someone added a trailing
slash so the "if" wouldn't be looking for:
/galleries/1/27/  => /galleries/1/27//index.html
                                     ^^

Thanks for helping me think this through!
Posted by Jean-Philippe Moal (Guest)
on 12.08.2008 01:23
(Received via mailing list)
Ian M. Evans a écrit :
> /galleries/1  => /galleries/1/index.html
>     }
> 
> [No idea if that's the right way to do the syntax]
> 

This should be possible, even without adding a /index.html in the 
expression
(nginx should handle this automatically thanks to the index directive).

Note that /cache here refers to a directory directly under the 
filesystem root.

> Also...is there any magic I'd need to do if someone added a trailing 
> slash so the "if" wouldn't be looking for:
> /galleries/1/27/  => /galleries/1/27//index.html
>                                     ^^

Here again nginx should handle this automatically. At least it does it 
when
doing URL processing.
Posted by Ian M. Evans (Guest)
on 12.08.2008 19:42
(Received via mailing list)
Jean-Philippe Moal wrote:
> Here again nginx should handle this automatically. At least it does it 
> when doing URL processing.

Yep, it did. Tossed the file test into my galleries location and it did
pull up an html copy I manually stuck in the right location.

Now off to look at my PHP code and write the output and then a cron to
clean up the cache every once in a while.

But first, a coffee!