5

I am trying to configure nginx to serve static and PHP files. The config I have isn't working. I want the following local folder structure:

src/static/  -> contains HTML, CSS, JS, images etc
src/api/     -> contains PHP files for a small REST service

If I visit http://mysite.local I want to be served files from the /static folder. If I visit http://mysite.local/api I want to be served the API PHP files. I want the requests to the api to be re-written and sent to an index.php file.

Some examples:

http://mysite.local/test.html                   -> served from src/static/test.html
http://mysite.local/images/something.png        -> served from src/static/images/something.png
http://mysite.local/css/style.css               -> served from src/static/css/style.css

http://mysite.local/api/users                   -> served from src/api/index.php?users
http://mysite.local/api/users/bob               -> served from src/api/index.php?users/bob
http://mysite.local/api/biscuits/chocolate/10   -> served from src/api/index.php?biscuits/chocolate/10

The below config works for static files but not for the api files. I get a 404 error back if I visit one of the API paths.

server {
    listen       80;
    server_name  mysite.local;
    access_log   /var/log/nginx/mysite.access.log main;
    error_log    /var/log/nginx/mysite.error.log debug;


    location / {
        index index.html;
        root /var/www/mysite/src/static;
        try_files $uri $uri/ =404;
    }

    location /api {
        index index.php;
        root /var/www/mysite/src/api;
        try_files $uri $uri/ /index.php?$query_string;

        location ~ \.php$ {
            try_files      $uri = 404;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }
    }
}

1 Answer 1

4

The initial problem is the root directive in the location /api block, which should not include the location component as this gets appended as part of the URI, so:

location /api {
    root /var/www/mysite/src;
    ...
}

will result in a local path of /var/www/mysite/src/api/index.php when presented with the URI /api/index.php. See this document for details.

The try_files rule does not rewrite the URI as you specify in your example. If you really need the final path of the URI to be presented as a query string to /api/index.php you will need to use rewrite.

The simplest solution (if you do not need to serve static content from that location) is to replace your try_files with:

location /api {
    ...
    rewrite ^/api/(.*)$ /api/index.php?$1 last;

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

Otherwise, use a named location:

location /api {
    ...
    try_files $uri $uri/ @rewrite;

    location ~ \.php$ { ... }
}
location @rewrite {
    rewrite ^/api/(.*)$ /api/index.php?$1 last;
}

See this and this for details.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the very helpful answer. The main problem was the definition of the root in the /api location block.

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.