Nginx client_max_body_size per location block (with php frontcontroller pattern)

nginxupload

I am looking for a solution for this problem. I understand the reasoning why the setup in that question does not work, but I try to get to a solution where I can get it working.

The idea is to allow large file uploads only on certain urls. I can use a location block for this, but the problem is: I have a php frontcontroller pattern:

location ~ \.php {
    # ...
    fastcgi_pass unix:/tmp/php5-fpm.sock;
}

My total config looks like:

# ...

http {
    # ...

    client_max_body_size 512K;

    server {
        server_name example.com;
        root        /var/www/example.com/public;

        location / { 
            try_files $uri /index.php?$query_string;
        }

        location /admin/upload {
            client_max_body_size 256M;
        }

        location ~ \.php {
            # ...

            fastcgi_pass unix:/tmp/php5-fpm.sock;
        }
    }
}

As I understand, only one location block will be applied. So if I have a default request size of 512K, the 256M will never be applied since all requests are matched through the frontcontroller pattern ~ \.php.

Am I right in this case and if so, what can be configured such that visitors cannot upload anything except when they upload to admin/upload?

Best Answer

If /admin/upload path is virtual, it is possible to make it work as follows:

location / {
    try_files $uri /index.php?$args;
}

location /admin/upload {
    client_max_body_size 256M;

    include inc/php.conf;
    rewrite ^(.*)$ /index.php?$args break;
}

location ~ \.php$ {
    include inc/php.conf;
}

Not the prettiest too, but works.