5

My PHP app automatically detects that a request routes to the admin area via the keyword manage in the url ie:

http://example.com/manage

This directory doesn't actually exist.

The request should route to the index.php file which is does on the initial request to manage/ but any links produce a "No input file specified." error in nginx.

I need a location block that will work on a non-existent url segment.

I tried re-writing it to the main index file like so:

location /manage {
    try_files $uri $uri/ @back;
}

location @back {
    rewrite ^/manage/(.*)$ /index.php?_route_=$1 last;
}

which works fine for Apache but in Nginx this produces a 500 error.

Any suggestions would be appreciated.

UPDATE:

Full config requested in comments:

upstream myapp {
    server unix:/srv/users/serverpilot/run/myapp.php-fpm.sock;
}

server {
    listen 80;
    server_name my.domain.com;

    root /srv/users/serverpilot/apps/myapp/public;
    index index.php index.html index.htm;

    access_log /srv/users/serverpilot/log/myapp/myapp_nginx.access.log;
    error_log  /srv/users/serverpilot/log/myapp/myapp_nginx.error.log;

    location /asset {
        rewrite ^/asset/(.*)$ /public/asset/$1 break;
    }

    location /image {
        rewrite ^/image/(.*)$ /public/image/$1 break;
    }

    location / {
        try_files $uri $uri/ @front;
    }

    location @front {
        rewrite ^/(.+)$ /index.php?_route_=$1 last;
    }

    location ~ \.php$ {
        include fastcgi.conf;
        fastcgi_pass myapp;
    }
}

UPDATE:

Error log requested.

15/05/14 10:42:04 [error] 32704#0: 
*5 FastCGI sent in stderr: 
"Unable to open primary script: /srv/users/username/apps/myapp/public/manage/index.php (No such file or directory)" 
while reading response header from upstream, client: 129.349.569.789, 
server: myapp.example.com, 
request: "GET /manage/index.php?route=common/forgotten HTTP/1.1", 
upstream: "fastcgi://127.0.0.1:9002", 
host: "myapp.example.com", 
referrer: "http://myapp.example.com/manage"

UPDATE:

Requested .htaccess file:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule ^(.*)/$ /$1 [L,R=301]
    RewriteRule ^asset/(.*)$ public/asset/$1 [L,QSA]
    RewriteRule ^image/(.*)$ public/image/$1 [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !.*\.(ico|gif|jpg|jpeg|png|txt|html|woff|ttf|eot|svg|css|js)
    RewriteRule ^([^?]*) index.php?_route_=$1 [L,QSA]
</IfModule>
10
  • And where these links leads to? Commented Apr 30, 2015 at 7:46
  • BTW, if you're sure that manage directory not exist you could skip try_files and put rewrite right in first location Commented Apr 30, 2015 at 7:47
  • All urls with the keyword manage route to the admin controllers through index.php. And yes I'm sure the directory doesn't exist. Commented Apr 30, 2015 at 8:24
  • Show full nginx config. Does any other php works? Commented Apr 30, 2015 at 8:32
  • Config added to question. Yes all php works for front of application. Commented Apr 30, 2015 at 9:53

2 Answers 2

1
+50

From the error log and configuration you posted, the request for /manage/index.php?route=common/forgotten will match both the / and php location blocks.

Given how the Nginx Location Matching Order is set out, the PHP location block will always take precedence and so the request is passed to FastCGI to process and as site.com/manage/index.php does not exist, you get an error. That is, the try_files in / and the rewrite in @frontnever get into the picture at all.

What you need to do is to add a location block that has a higher position in the location matching order than the PHP location block to handle such requests.

upstream myapp {
    server unix:/srv/users/serverpilot/run/myapp.php-fpm.sock;
}

server {
    listen 80;
    server_name example.com;

    root /srv/users/serverpilot/apps/myapp/public;
    index index.php index.html index.htm;

    access_log /srv/users/serverpilot/log/myapp/myapp_nginx.access.log;
    error_log  /srv/users/serverpilot/log/myapp/myapp_nginx.error.log;

    location /asset {
        rewrite ^/asset/(.*)$ /public/asset/$1 break;
    }

    location /image {
        rewrite ^/image/(.*)$ /public/image/$1 break;
    }

    location / {
        try_files $uri $uri/ @front;
    }

    location ~ ^/manage {
        rewrite ^([^?]*)$ /index.php?_route_=$1;
    }

    location ~ \.php$ {
        include fastcgi.conf;
        fastcgi_pass myapp;
    }

    location @front {
        rewrite ^([^?]*)$ /index.php?_route_=$1;
    }
}

With this arrangement, the request will match the /, /Manage and php location blocks. /Manage and php being regex type blocks, will take precedence and among the two, /Manage, because it appears first, will take precedence and redirect accordingly.

For the redirection, the request will match the /, and php location blocks. php will take precedence and as site.com/index.php does exist, process accordingly.

PS. I notice you have _route_ in your config and route in the log. Take it that is just for testing.

**** ALTERNATIVE CONFIG ****

upstream myapp {
    server unix:/srv/users/serverpilot/run/myapp.php-fpm.sock;
}

server {
    listen 80;
    server_name example.com;

    root /srv/users/serverpilot/apps/myapp/public;
    index index.php index.html index.htm;

    access_log /srv/users/serverpilot/log/myapp/myapp_nginx.access.log;
    error_log  /srv/users/serverpilot/log/myapp/myapp_nginx.error.log;

    location ~ \.php$ {
        include fastcgi.conf;
        fastcgi_pass myapp;
    }

    location ~ ^/asset/(.*)$ {
        rewrite ^ public/asset/$1;
    }

    location ~ ^/image/(.*)$ {
        rewrite ^ public/image/$1;
    }

    location / {
        rewrite ^/(.+)/$ /$1 permanent;
        try_files $uri $uri/ @front;
    }

    location @front {
        rewrite ^/([^?]*)$ /index.php?_route_=$1;
    }   
}
Sign up to request clarification or add additional context in comments.

11 Comments

Nope this doesn't work. With both manage rewrites enabled, and with only the second one enabled, the url just loads up the normal index page. If I comment out the second manage rewrite I get a 404.
The entire url for the admin area needs to remain intact. The admin area doesn't use any url rewriting at all other than the manage segment. That segment tells the application to load the admin module. If that segment isn't present in the url, the application knows to load the front module.
@VinceK That is actually positive as it means the manage block is handling the requests now and the rewrite just needs to be right. I had thought you wanted to change incoming requests of the form, site.com/manage/ABC/XYZto site.com/index.php?_route_=ABC/XYZ which seems not to be the case. So, can you give a sample incoming request/link and what the application is expecting? With this info, it will be trivial to tweak the rewrite rule accordingly.
Absolutely. Links to the admin should be left as is example.com/manage/index.php?route=xxx/xxx&token=1234&product_id=5678 and so on. Thanks BTW for your help.
Just for clarification, the manage segment is selectable by the end user. It could be set to steve or aardvarks, whatever the user of the app wants in order to keep their admin area a secret.
|
0

It turned out to be right under my nose the whole time.

upstream myapp {
    server localhost:9002;
}

server {
    listen 80;
    server_name myapp.example.com;

    root /srv/users/serverpilot/apps/myapp/public;
    index index.html index.htm index.php;

    access_log /srv/users/serverpilot/log/myapp/myapp_nginx.access.log;
    error_log  /srv/users/serverpilot/log/myapp/myapp_nginx.error.log;

    location / {
        try_files $uri $uri/ @front;
    }

    location ~ ^/manage {
        rewrite ^/(.+)$ /index.php?_route_=$1 last;
    }

    location ~ \.php$ {
        include fastcgi.conf;
        fastcgi_pass myapp;
    }

    location @front {
        rewrite ^/(.+)$ /index.php?_route_=$1 last;
    }
}

Thanks to @Dayo for all the help.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.