Not existant files passed to php backend

Hello,
I have a little problem with 0.7.11 (could be it a bug or config error
or is
it expected?).
Nginx passes *.php (matching the regexp) files to the fastcgi backend
even
they dont exist and instead of the specified error_page displays “No
input
file specified.” (which prolly comes from the php).

The response header is correct 404 though but it is still pased over to
php
backend :

Here is the difference between requesting a simple file and *.php…

wget -S http://127.0.0.1/notexists.htm
–2008-08-20 12:20:40-- http://127.0.0.1/notexists.htm
Connecting to 127.0.0.1:80 … connected.
HTTP request sent, awaiting response…
HTTP/1.1 404 Not Found
Server: nginx/0.7.11
Date: Wed, 20 Aug 2008 09:20:40 GMT
Content-Type: text/html
Content-Length: 383
Connection: close
2008-08-20 12:20:40 ERROR 404: Not Found.

wget -S http://127.0.0.1/notexists.php
–2008-08-20 12:20:44-- http://127.0.0.1/notexists.php
Connecting to 127.0.0.1:80… connected.
HTTP request sent, awaiting response…
HTTP/1.1 404 Not Found
Server: nginx/0.7.11
Date: Wed, 20 Aug 2008 09:20:44 GMT
Content-Type: text/html; charset=utf-8
Connection: close
2008-08-20 12:20:44 ERROR 404: Not Found.

The not existant php request doesnt appear also on errorlog.

The config:

http {
include mime.types;
default_type application/octet-stream;
access_log off;
sendfile on;
keepalive_timeout 0;
server {
listen 80;
server_name localhost;

    root   /data/web/root;
    index  index.php index.htm;

    error_page   404          /404.html;
    error_page   502 503 504  /404.html;

    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:1026;
        fastcgi_index  index.php;
        include        fastcgi_params;
    }
}

}

So is there a workarround to this ?

wbr
Reinis R.

Nginx passes *.php (matching the regexp) files to the fastcgi backend even
they dont exist and instead of the specified error_page displays “No input
file specified.” (which prolly comes from the php).

Igor can you give a comment on this?
Is this expected or am I gone wrong with the config?

rr

On Wednesday 20 August 2008, Reinis R. wrote:

Nginx passes *.php (matching the regexp) files to the fastcgi backend
even they dont exist and instead of the specified error_page displays “No
input file specified.” (which prolly comes from the php).

Igor can you give a comment on this?
Is this expected or am I gone wrong with the config?

rr

it is expected

if you don’t like php’s 404 page
set fastcgi_intercept_errors to on

On Wed, Aug 20, 2008 at 05:21:57PM +0300, Reinis R. wrote:

Nginx passes *.php (matching the regexp) files to the fastcgi backend even
they dont exist and instead of the specified error_page displays “No input
file specified.” (which prolly comes from the php).

Igor can you give a comment on this?
Is this expected or am I gone wrong with the config?

Yes, this is expected behaviour.

it is expected

if you don’t like php’s 404 page
set fastcgi_intercept_errors to on

I see.

Just switching from lighty where the default behaviour is first to check
the
local file ( lighttpd has an extra setting ‘check-local’ where you can
specify to look for the file on local disk rather than blindly
forwarding to
request on the fastcgi backend )

Although this is handy in case of remote fastcgi backends isnt the
majority
setups where the nginx and php (and other fastcgi processes) are on the
same
box? And as the php is the slowest component wouldnt it be more
efficient
from the performance point of view for the nginx throw the error first
rather than intercepting the error later (and maybe add a
setting/feature
(mimic to lighty) to disable the local file check)…

Anyways thx for the hint.

rr

On Wed, Aug 20, 2008 at 05:29:00PM +0200, Roxis wrote:

specify to look for the file on local disk rather than blindly forwarding

rr

you can use ngx_http_rewrite_module

if (!-f $request_filename) {
return 404;
}
fastcgi_pass …

but it’s not recommended

Although I generally do not recommend to use “if (!-f
$request_filename)”,
it’s mostly related to complex directive inside “if” block, something
like:

  if (!-f $request_filename) {
      fastcgi_pass ...
  }

but simple “return 404” in “if” block is OK.

Does multiple complex directive inside “if” block impact the
performance ?
If so, how much ?

2008/8/20 Igor S. [email protected]:

On Wednesday 20 August 2008, Reinis R. wrote:

to request on the fastcgi backend )
rr
you can use ngx_http_rewrite_module

if (!-f $request_filename) {
return 404;
}
fastcgi_pass …

but it’s not recommended

On Thu, Aug 21, 2008 at 12:01:42AM +0800, Delta Y. wrote:

Does multiple complex directive inside “if” block impact the performance ?
If so, how much ?

No, they does not impact the perfomance, but they has many limits
and drawbacks.

Although I generally do not recommend to use “if (!-f $request_filename)”,
it’s mostly related to complex directive inside “if” block, something
like:

 if (!-f $request_filename) {
     fastcgi_pass ...
 }

but simple “return 404” in “if” block is OK.

Thx…
Made a simple/generic benchmark with ‘ab’ - with
fastcgi_intercept_errors
the 404 could squeeze only like ~5k req/sec but with the if() approach
the
req/sec have gone up to arround ~15k rq/sec…

It’s not like on a regular bases someone would request non-existing
*.php
files then again the backend has a a load of stuff to do for itself to
waste
cpu-clicks on this :slight_smile:

rr

On Aug 20, 2008, at 12:04 PM, Igor S. wrote:

On Thu, Aug 21, 2008 at 12:01:42AM +0800, Delta Y. wrote:

Does multiple complex directive inside “if” block impact the
performance ?
If so, how much ?

No, they does not impact the perfomance, but they has many limits
and drawbacks.

Such as?

Our entire setup is built around these right now.

Does the following config work?
If it does, is it reasonable in your opinition?

location / {

if($geo ) {
proxy_pass http://upstream2;
}

if( $request_uri ~ .css$){
expire 3d;
}

if( $request_uri ~ .gif$ ) {
expire 1d;
}

if( $request_uri ~ .jpeg$ ) {
expire 2d;
}

if( $request_uri ~ /admin/ ) {
auth_basic “Restricted”;
auth_basic_user_file conf/htpasswd;

}

proxy_pass http://upstream;

}

2008/8/21 Igor S. [email protected]:

On Wednesday 20 August 2008, Reinis R. wrote:

if there is such in config and also on disk?

rr

after internal redirect by ngx_http_index_module
$request_filename will contain index file

simple don’t use “if (!-f $request_filename)” in “location /” block

No, they does not impact the perfomance, but they has many limits
and drawbacks.

Seems like stumbled on one of those - if (!-f $request_filename) { …
doesnt take in note index directive files…

Eg if you open http://domain.com instead of the index.php the if() is
hit
and in my case 404 returned :frowning:

Is this also expected that $request_filename doesnt containt the index
file
if there is such in config and also on disk?

rr

Roxis wrote:

On Wednesday 20 August 2008, Reinis R. wrote:

if there is such in config and also on disk?

rr

after internal redirect by ngx_http_index_module
$request_filename will contain index file

simple don’t use “if (!-f $request_filename)” in “location /” block

Yup just place it in your php location block.
location ~ .*.php$ {
if (!-f $request_filename) {
return 404;
}
fastcgi_pass 127.0.0.1:10000;
fastcgi_index index.php;
}
this is how i have been handling this without issues for sometime.

On Wed, Aug 20, 2008 at 07:28:58PM +0300, Reinis R. wrote:

if there is such in config and also on disk?
Yes, “if” (rewrite module) runs before index module, therefore “if”
tests “/”.
But if you place “if” inside “location *~ .php$” (as it was already
suggested), then “if” will test already internally redirected
“/index.php”.

Igor S. wrote:

On Wed, Aug 20, 2008 at 07:28:58PM +0300, Reinis R. wrote:

if there is such in config and also on disk?
Yes, “if” (rewrite module) runs before index module, therefore “if”
tests “/”.
But if you place “if” inside “location *~ .php$” (as it was already
suggested), then “if” will test already internally redirected
“/index.php”.

Hi Igor, just curious i am not a regex expert or anything. What is the
difference between the one you have listed here “location ~ .php$" and
then one i am currently using "location ~ .
.php$”?
Thanks

Yup just place it in your php location block.
location ~ .*.php$ {
if (!-f $request_filename) {
return 404;
}
fastcgi_pass 127.0.0.1:10000;
fastcgi_index index.php;
}
this is how i have been handling this without issues for sometime.

Thx… Works as expected.

rr

On Thu, Aug 21, 2008 at 12:24:29AM +0800, Delta Y. wrote:

expire 3d;
if( $request_uri ~ /admin/ ) {
auth_basic “Restricted”;
auth_basic_user_file conf/htpasswd;

}

proxy_pass http://upstream;

}

No, it will not work as you expect. This is the reason why I do not
recommend to use complex “if” blocks: it simply does not work as one may
expect due to internal implementation.

This was my big mistake when I had allowed some directives inside
“if” blocks. It was better to postpone it before good “if”
implementation.

And one note again: never use

if( $request_uri ~ .jpeg$ ) {

there is the best replacement:

location ~ .jpeg$ {

On Wed, Aug 20, 2008 at 08:26:55PM +0200, Rob S. wrote:

Hi Igor, just curious i am not a regex expert or anything. What is the
difference between the one you have listed here “location ~ .php$" and
then one i am currently using "location ~ .
.php$”?

There is no diffference between “.php$” and “.*.php$” regexs.
The former probably more optimal, but I’m not sure: PCRE may optimize
the later and produce the same code as for the former.

As to “location ~" vs “location ~”, the "~” is case-insensetive regex.