Configure nginx to statically cache certain URLs - file

I want to cache certain URLs in my app by looking up static files directly. However, the statically cached files may not exist, so I only want to redirect the request if the files exist. I imagine I can use try_files for this somehow, but so far I have not been successful in doing it right.
Here's what I tried:
location ^/(.*)/(.*)/other/stuff/(.*)/this-is-static {
try_files /static-cache/$1/$2/$3/this-is-static #app;
}
static-cache is an internal location configured in the same file. This does not appear to work as intended. What's wrong?
The closest I've gotten is this, which rewrites every request (and thus fails when the file is not cached):
location ^/(.*)/(.*)/other/stuff/(.*)/this-is-static {
rewrite ^ /static-cache/$1/$2/$3/this-is-static;
}

Did you try the ~?, I also used [^/] to avoid greedy regex
location ~ /([^/]*)/([^/]*)/other/stuff/([^/]*)/this-is-static {
try_files /static-cache/$1/$2/$3/this-is-static #app;
}
location #app {
#handle non cached files
}

Related

Nginx config to serve react app from sub-folder

I have a create-react-app that I built, created npm run dist and copied the resulting dist files to /var/www/html/build/
Here is my nginx config:
server{
listen 9095;
server_name <hostname>;
access_log /var/log/nginx/nginx.pass.access.log;
error_log /var/log/nginx/nginx.pass.error.log;
root /var/www/html/build/;
location / {
index index.html;
try_files $uri $uri/ /index.html;
}
}
With this, I can access http://hostname:9095.
What I actually need is to serve the same site with http://hostname:9095/pass (or /PASS) (and not /)
I have tried various re-write config but I can't seem to figure this out.. Help appreciated
The format of a rewrite expression is rewrite <regex> <replacement> [flag];. The simplest way to redirect /pass or /PASS to your /var/www/html/build/index.html page is as follows.
location ~* ^/pass$ {
rewrite ^/(.*)$ /index.html break;
root /var/www/html/build;
index index.html;
}
The location ~* ^/pass directive is a case-insensitive regular expression match against the /pass URI. The ^ symbol ensures the regex matches only the /pass uri, and not something like /some/dir/pass, while the $ symbol ensures a url like /password is not matched as well.
Note, however, that this regex will match /pAsS, /PAss, and /pasS. In other words, it really is case-insensitive. If you wish to match only /pass or /PASS, you should modify the regex accordingly.
Better yet, you can completely circumvent regex URI matching by using an exact URI match.
location = /pass {
...
}
Using an exact match like this speeds up request processing because regular expressions do not need to be parsed.
To match /PASS, you could then simply define another exact location match block.
location = /PASS {
...
}
This then frees up your main location block for your primary server content.
location / {
root /var/somewhere/else;
index index.html;
}
Edit: After writing this, I came across the alias directive, which also seems promising. I haven't used it myself (I've always used rewrites for this kind of thing), but it's something else to explore as well.

Send all requests to index.html except certain extensions

I'm using nginx to serve my react app and it serves me well in redirecting everything except static files to index.html with the following:
location / {
try_files $uri /index.html =404;
}
I was content with this for some time but noticed that when certain image and javascript files are not available on the server, the index.html gets served instead. This itself is not a problem.
However when a cache layer is added before the app it caches all these results since they do have 200 as status code.
What I want is to serve static files and redirect other requests to index.html when they do not end in certain extensions (.js, .css, .png, .jpg, .gif etc...)
For example
http://example.com/some/path -> /index.html
http://example.com/existing-file.doc -> /existing-file.doc
http://example.com/some/non-existing-image.png -> 404 error
So addresses like http://example.com/main.1234.js returns the js file if it exists, a 404 response otherwise, never index.html
Should I make a regular expression block, like:
location ~ \.js$|\.css$|\.png$|\.jpg$ {
what do I write here?
}
I'm not entirely sure how to best approach this.
It's perfectly valid to leave the block empty, and it will inherit the value for root and index from the surrounding block. The default action for an empty location block is similar to try_files $uri $uri/ =404;
You may also want to simplify your regular expression, for example:
location ~ \.(js|css|png|jpg)$ {
}

Moving Cakephp 3.x application into nginx subfolder

System
nginx on Ubuntu
CakePhp 3.4.6
Problem
I'm trying to move a CakePhp application into a subfolder on the webserver.
Let's say the subfolder is called /project
and root webserver directory is under /var/www/html/
I tried something like this in the nginx default (without any success):
location /project {
alias /var/www/html/project/webroot;
try_files $uri $uri/ /project/webroot/index.php;
}
The subfolder url-suffix is always interpreted as a controller.
I am guessing that I need to set specific values in the app.php file, so cakephp knows that the url has a prefix but I haven't found a value combination that works yet.
Anybody has guidance here?
It is a combination of app.php and nginx rewrite rule:
config.php/app.php
'base' => '/project'
/etc/nginx/sites-available/default
`
location /project {
if (-f $request_filename) {
break;
}
# prevent recursion
if ($request_uri ~ /webroot/index.php) {
break;
}
rewrite ^/project$ /project/ permanent;
rewrite ^/project/webroot/(.*) /project/webroot/index.php last;
rewrite ^/project/(.*)$ /project/webroot/$1 last;
}
`

simple nginx if statement in C

I have this line of code in my /etc/nginx/sites-available/default page:
rewrite ^/(.*)/(.*) /search.php?name=$1&last=$2
It accomplished what I wanted: cleaner urls for linking
example.com/john/smith is forwarded properly to the PHP GET.
But, it also destroyed all my styling and image links.
So I would like the rewrite to occur only if the first word is neither css nor image.
But I can only find if statements for GET arguments in the url not for directoies in the url like this:
if ($args ~* "/?param1=val1&param2=val2&") {
rewrite ^ http://www.example.com/newparam/$arg_param1/$arg_param2? last;
}
After following the apache solution suggested in this comment:
"I think a better solution may be to only apply the rewrite if the requested filename doesn't exist. Take a look at this question. Redirect requests only if the file is not found? "
I converted that functionality to nginx and got:
location / {
try_files $uri $uri/ =404;
if (-f $request_filename) {
break;
}
rewrite ^/(.*)/(.*) /search.php?name=$1&last=$2
}
This makes the url rewrite only if there is no file found at the given directory path

Laravel returning root view instead of static content

I have one route:
Route::controller('/', 'HomeController');
And HomeController has one action getIndex which works correctly. However, when browsing to http://localhost:4040/public/style.css, the application returns the view from HomeController::getIndex. What gives?? Shouldn't it return the static file style.css?? I have confirmed that the CSS file does in-fact exist in the public folder.
To be clear, I'm running the app like this:
php -S localhost:4040 server.php
EDIT:
Hmmm, so the following seems to work:
1) Serve the project with:
php artisan serve
2) Reference files without the public/ prefix.
What does the php artisan serve command do so differently??
With using Route::controller(), if you look at the php artisan routes, the getIndex route has a optional parameters {one?}/{two?}/... and since that parameters have no matching pattern style.css get caught by the {one?}. This is the completely expected behavior, with index.php.
However, using php artisan serve, the server.php file gets called first.
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$uri = urldecode($uri);
$paths = require __DIR__.'/bootstrap/paths.php';
$requested = $paths['public'].$uri;
// This file allows us to emulate Apache's "mod_rewrite" functionality from the
// built-in PHP web server. This provides a convenient way to test a Laravel
// application without having installed a "real" web server software here.
if ($uri !== '/' and file_exists($requested))
{
return false;
}
require_once $paths['public'].'/index.php';
You can clearly see that it checks if the file is real in if ($uri !== '/' and file_exists($requested)), and if it is, it stops calling the index.php that may process it as a route parameter, and instead returns a real file.

Resources