Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nginx to serve static page before dynamic

Tags:

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?

like image 211
Apollo Avatar asked Apr 22 '16 21:04

Apollo


People also ask

Can Nginx be used for serving static content?

Configure NGINX and NGINX Plus to serve static content, with type-specific root directories, checks for file existence, and performance optimizations.

Can Nginx serve dynamic content?

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 ...

What is Try_files in nginx?

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; }


2 Answers

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;     } } 
  1. You don't need the listen directive if it only contains 80 since this is the default.
  2. The server_names should not contain a leading dot.
  3. The $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).
  4. You don't need fastcgi_split_path_info because you are not using that feature.
  5. Your 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.
like image 170
Fleshgrinder Avatar answered Sep 18 '22 21:09

Fleshgrinder


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.

like image 27
Richard Smith Avatar answered Sep 19 '22 21:09

Richard Smith