Php and locations with regex (round 2)

(trying to pay attention to the data i posting…)

well, i think i found a behavior pattern with my problem about regexed
locations and php scripts.
i tried very simple tests to figure out the behavior i getting from the
server.
the case is this:
_ 2 subdirs, app1 and app2
_ 2 files in each subdir index.html (hello world) and index.php
(phpinfo)
_ 2 different locations configs, with and without regex
_ 2 different indexes en each app subdir, app1->index.php and
app2->index.html

config 1:

server {
    listen       80;
    server_name  www.beta; #somename  alias  another.alias;

access_log /var/log/nginx/beta.access.log;

    location / {
        root   /home/website/beta.ws/webroot/;
        index  index.php index.html index.htm;
    }

    location /app1/ {
        root   /home/website/beta.ws/webroot/;
        index  index.php index.html index.htm;
    }

    location /app2/ {
        root   /home/website/beta.ws/webroot/;
        index  index.html index.htm;
    }

    # pass the PHP scripts to FastCGI server listening on 

127.0.0.1:8888
#
location ~ .php$ {
fastcgi_pass 127.0.0.1:8888;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME
/home/website/beta.ws/webroot$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}

}

the behavior is as expected:

http://www.beta/app1/ => index.php’s phpinfo output
http://www.beta/app2/ => index.html’s html hello world output

http://www.beta/app1/index.php => index.php’s phpinfo output
http://www.beta/app2/index.php => index.php’s phpinfo output

until now all is ok.

now the config with a minimal regex variation:
server {
listen 80;
server_name www.beta; #somename alias another.alias;

access_log /var/log/nginx/beta.access.log;

    location / {
        root   /home/website/beta.ws/webroot/;
        index  index.php index.html index.htm;
    }

    location ~ ^/(app1)/ {
        root   /home/website/beta.ws/webroot/;
        index  index.php index.html index.htm;
    }

    location ~ ^/(app2)/ {
        root   /home/website/beta.ws/webroot/;
        index  index.html index.htm;
    }

    # pass the PHP scripts to FastCGI server listening on 

127.0.0.1:8888
#
location ~ .php$ {
fastcgi_pass 127.0.0.1:8888;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME
/home/website/beta.ws/webroot$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}

}

the behavior isn’t as expected:

http://www.beta/app1/ => BIN file to download, 13ax1epp.bin containing
the index.php source code
http://www.beta/app2/ => index.html’s html hello world output

http://www.beta/app1/index.php => index.php’s source code with a correct
mime recognition
http://www.beta/app2/index.php => index.php’s source code with a correct
mime recognition

well, it seems that as an automatic index the php file is returned with
some internal file name? with a .bin extension for download, containing
the script source code.
but if it’s called directly by the browser url it’s returned with the
correct name but without been parsed by the fastcgi.

i hope it could be of help.

is the problem so obvious (and i very distracted) that nobody answer?

Alejandro V. escribió:

On Tue, Oct 23, 2007 at 08:44:21AM -0200, Alejandro V. wrote:

_ 2 different indexes en each app subdir, app1->index.php and
location / {
root /home/website/beta.ws/webroot/;
include /etc/nginx/fastcgi_params;

        root   /home/website/beta.ws/webroot/;
        index  index.html index.htm;
    }

mime recognition
http://www.beta/app2/index.php => index.php’s source code with a correct
mime recognition

well, it seems that as an automatic index the php file is returned with
some internal file name? with a .bin extension for download, containing
the script source code.
but if it’s called directly by the browser url it’s returned with the
correct name but without been parsed by the fastcgi.

http://wiki.codemongers.com/NginxHttpCoreModule#location

Hello!

On Tue, 23 Oct 2007, Alejandro V. wrote:

is the problem so obvious (and i very distracted) that nobody answer?

It is.

According to your config (the second one) - there is no chance for nginx
to use .php location for documents located under /app1/, since regex
locations always checked in order (and ^/app1/ comes first).

There is no such thing as “internal filename”. It is what your browser
suggests to you.

Maxim D.

only a simple question about the topic:
Are regexed locations rules accumulative?
because it seems that when the two locations rules i want to be matched
are regexed ones only one is matched.

i’ll read more docs… thanks…

Alejandro V. escribió:

well, doing this work:

    location ~ /(app1|app2)/ {
        root   /home/website/beta.ws/webroot/;
        index  index.php index.html index.htm;
        fastcgi_pass   127.0.0.1:8888;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME

/home/website/beta.ws/webroot$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}

but i’m charging to php to serve all the data, dynamic and static one
(correct?)
is there a way to filter inside the location the php-cgi directives to
serve directly the static content and avoid overcharging php?
thanks.

Alejandro V. escribió:

thank’s Igor, i’ve emailed a suspect of these before receiving your
mail.
i figured it out trying to alias a php app folder.

if anyone is interested in the config to alias static and dynamic
content, i can post it.

thanks again…

Igor S. escribió:

On Tue, Oct 23, 2007 at 02:26:10PM -0200, Alejandro V. wrote:

:wink: i tried something like this before posting the last mail, but i
think this mixture is out of context (somebody correct me please), it’s
a rewrite module directive, and fastcgi params doesn’t fit in it (yet ;).

i think i’m out of luck with the simplification/generalization of the
config directives i pretend.

thank you all, i’m learning a lot about nginx…

You may use:

  location ~ \.php$ {
      fastcgi_pass   ...
      ...
  }

  location ~ ^/(app1|app2)/ {
      root    ...
      ...
  }

It’s better do not use “if”.
Try to route request via locations only.
If you want to pass non-existent files to FastCGI/proxy it’s better to
use:

  location / {
      root   ...
      error_page 404  =  @fallback;
  }

  location @fallback {
      fastcgi_pass   ...
      ...
  }

:wink: i tried something like this before posting the last mail, but i
think this mixture is out of context (somebody correct me please), it’s
a rewrite module directive, and fastcgi params doesn’t fit in it (yet
;).

i think i’m out of luck with the simplification/generalization of the
config directives i pretend.

thank you all, i’m learning a lot about nginx…

Grzegorz N. escribió:

2007/10/23, Alejandro V. [email protected]:

well, doing this work:

    location ~ /(app1|app2)/ {
        root   /home/website/beta.ws/webroot/;
        index  index.php index.html index.htm;

if (!-f $request_filename) {

        fastcgi_pass   127.0.0.1:8888;

}

thanks.
Try wrapping fastcgi_pass in an `if’ block, like above. Please check
the variable name as I’m not 100% sure about it right now.

Best regards,
Grzegorz N.

2007/10/23, Igor S. [email protected]:

  }

This gets ugly quickly if you decide one day to e.g. pass different
php files to different fastcgi backends (running under different users
or something). Also, if I’m right, errors while serving php pages come
from the first location, so requests for /app1/nonexistent.php and
/app1/nonexistent.jpg may result in different error handling.

  location @fallback {
      fastcgi_pass   ...
      ...
  }

Why? Because the configuration inside if blocks isn’t really merged
with its parent config but overwritten (AFAIK, that’s what vanilla
nginx does; my patchset fixes that, at least for cases I care about)?
Or is there another reason? Routing dynamic content via error pages
seems hackish to me – an if block inside location looks more natural
(again, IMHO).

Oh, and BTW – given that my nginx patchset merges the configs, is
there any (other) reason to disallow certain directives inside if
blocks (those allowed in location, of course)?

BTW2, if anybody besides me is using the patchset, please upgrade :slight_smile:

Best regards,
Grzegorz N.

Igor S. escribió:

thank you all, i’m learning a lot about nginx…
root …

}

Igor, you’ll not trust me, but i remember to have proven something like
these, i think in the config test madness i missed something or didn’t
cleared the browser cache correctly and discarded those settings.
it seems to work ok!

It’s better do not use “if”.

what about conditioned rewrite rules application, the same advice?

      ...
  }

those are very elegant and powerful options to remember for other
things.
question: is the return directive (from rewite module) applicable in
this behavior to trigger @fallback?

thanks for all.

On Wed, Oct 24, 2007 at 10:31:48AM +0200, Grzegorz N. wrote:

      ...
  }

This gets ugly quickly if you decide one day to e.g. pass different
php files to different fastcgi backends (running under different users
or something). Also, if I’m right, errors while serving php pages come
from the first location, so requests for /app1/nonexistent.php and
/app1/nonexistent.jpg may result in different error handling.

I agree. I personally prefer to avoid such general locations and
try to describe more detailed locations. It seems redudant for simple
sites
with several locations, but my practice shows that sites usually grow
and these general locations become cumbersome.

      fastcgi_pass   ...
      ...
  }

Why? Because the configuration inside if blocks isn’t really merged
with its parent config but overwritten (AFAIK, that’s what vanilla
nginx does; my patchset fixes that, at least for cases I care about)?

The configuration inside if blocks is actually merged, but not for all
directives.

Or is there another reason? Routing dynamic content via error pages
seems hackish to me – an if block inside location looks more natural
(again, IMHO).

if block is hack inside nginx and this is the reason.

Oh, and BTW – given that my nginx patchset merges the configs, is
there any (other) reason to disallow certain directives inside if
blocks (those allowed in location, of course)?

Current if/rewite is ugly and I will change it, thus I do not enable
many
directives inside if block.

Igor S. escribió:

  }

/app1/nonexistent.jpg may result in different error handling.

I agree. I personally prefer to avoid such general locations and
try to describe more detailed locations. It seems redudant for simple sites
with several locations, but my practice shows that sites usually grow
and these general locations become cumbersome.

sure i agree, the use i do of this is a simple rewrites include for
specific app subdirs, and i think one location by app subdir is a little
redundant.
thanks you all, interesting concepts and knowledge are emerging form
those threads (IMHO)

On Tue, Oct 23, 2007 at 03:56:12PM -0200, Alejandro V. wrote:

  location ~ ^/(app1|app2)/ {

what about conditioned rewrite rules application, the same advice?
if has many limits.

      ...
  }

those are very elegant and powerful options to remember for other things.
question: is the return directive (from rewite module) applicable in
this behavior to trigger @fallback?

Yes.