I want to serve static HTML files with NGINX, but if the file is missing, it should load a PHP file instead and PHP should handle the content.
I've been testing several combinations of try_files
, but I can't get my head around it. I have a dummy PHP app that looks like this:
./ ../ dynamic.php index.php static/ static/static.html
Then I have a small PHP code on index like this:
<?php $path = $_SERVER['REQUEST_URI']; $pattern = '/^\/(.*)\.html$/'; $matches = []; $results = preg_match($pattern, $path, $matches); if (count($matches) > 0) { if ($matches[1] == "dynamic") { require 'dynamic.php'; } else { echo "Not found!"; } } else { echo "Index page!"; }
The results of browsing to each page should be:
http://foo.bar/ - Loads index.php http://foo.bar/static.html - Loads static/static.html http://foo.bar/dynamic.html - Loads index.php & PHP requires dynamic.php http://foo.bar/baz.html - Loads index.php with "not found" message
This is what I got in the NGINX config file:
server { listen 80; server_name .foo.bar *.foo.bar; access_log /var/log/nginx/foo.access.log; error_log /var/log/nginx/foo.error.log; root /var/www/foo; index index.php; location / { # Trying with 'try_files' here. No success. } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php5-fpm-foo.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }
I've been trying repeatedly and evidently utterly failing with this line:
try_files $uri $uri/static /index.php;
I am missing something. Help?
Configure NGINX and NGINX Plus to serve static content, with type-specific root directories, checks for file existence, and performance optimizations.
NGINX can deliver static content locally, but for dynamic content it acts as proxy in front of other servers that deliver the dynamic application content, thus keeping NGINX lean and leaving the generation of dynamic content to servers that specialize in it, such as FastCGI‑ or uwsgi‑based servers, application servers ...
The try_file directive is in the server and location blocks and specifies the files and directories in which Nginx should check for files if the request to the specified location is received. A typical try_files directive syntax is as: location / { try_files $uri $uri/ /default/index.html; }
I would use your static directory as document root. This ensures that nobody can execute /dynamic.php
directly, however, it will be forwarded to your index.php
by the named location block @php
.
This configuration example is untested!
server { index index.php; root /var/www/foo/static; server_name foo.bar *.foo.bar; location / { try_files $uri @php; } location @php { include fastcgi_params; fastcgi_pass unix:/var/run/php5-fpm-foo.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /var/www/foo/index.php; } }
listen
directive if it only contains 80 since this is the default.server_name
s should not contain a leading dot.$uri
always contains the requested URI including the leading slash (e.g. /static.html
) and nginx will prefix them with the document root upon invocation of try_files
(e.g. /var/www/foo/static.html
). Hence, you need to set your static
directory before the $uri
(e.g. /static$uri
becomes /var/www/foo/static/static.html
).fastcgi_split_path_info
because you are not using that feature.try_files
in your PHP location makes it impossible for nginx to properly forward things. A request for /dynamic.html
does not end on .php
, hence, try_files
always fails.There are a number of ways of hiding the static
directory from the URL. For example, manipulating root
, clever use of try_files
or a rewrite
.
Possibly the most obvious is this:
root /var/www/foo; location / { root /var/www/foo/static; try_files $uri /index.php; } location ~ \.php$ { ... }
so that nginx
looks in the static
folder for normal files, but the parent folder for .php
files.
What you were trying to achieve was something like this:
root /var/www/foo; location / { try_files /static$uri /index.php; } location ~ \.php$ { ... }
which will prefix /static
to any URI before testing for existence. The /index.php
must be the last element as it required processing in a different location. See this document for more.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With