I am using fastcgi caching, and would like to specify which URLs the cache should be active on.
I use a rewrite rule to determine which controller file to access, and set any query parameters dynamically
I want to specify URLs in which the cache is activated, and those in which it is inactive, this is my code:
server {
listen 80;
server_name domain.com;
root /home/site/wwwroot;
set %skip_cache 1; #this is the variable that I want to set to 0 on specific URLS
location / {
try_files $uri $uri/ $uri.html #php;
}
location #php {
rewrite ^(/[^/]+)$ $1.php last;
rewrite ^(/[^/]+)/(.*)$ $1.php?q=$2 last;
}
location /user/ {
set $skip_cache 0;
}
location /objects/ {
set $skip_cache 0;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
fastcgi_split_path_info ^(.+?\.php)(/.*)?$;
fastcgi_connect_timeout 300;
...etc...
#cache parameters
fastcgi_param FASTCGI_CACHE 1;
fastcgi_cache cfcache;
fastcgi_cache_valid 30s;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
add_header X-FastCGI-Cache $upstream_cache_status;
}
as you can see, the variable $skip_cache is set to 1 by default, and I would like to white list URLs for caching.
An example I would like cached is domain.com, domain.com/user/123 and domain.com/objects/456
Currently, if I browse to /user/123, the result is a 404 error, as I believe that location block with the variable setting is being used exclusively.
If you want to set a variable based on the original request, you should use a map directive with the $request_uri variable. See this document for details.
For example:
map $request_uri $skip_cache {
default 1;
~^/user/ 0;
~^/objects/ 0;
}
server {
...
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
...
}
Related
I'm trying to use both vue.js and Django with nginx. The issue is, that it still redirect my /subscriptions/ url to Django. Removing the '/' rule would make it work though. Is there a way to "skip" Django when the url matches 'custom'?
Basically, I would like to specify which links would be used with vue, and the rest with Django.
location = /custom/ {
root /home/django/project/frontend/dist;
index /index.html;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/django/project/project.sock;
}
The following will serve the files inside /home/django/project/frontend/dist/ if the path of the request starts with '/custom/'
location /custom/ {
root /home/django/project/frontend/dist/;
index /index.html;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/django/project/project.sock;
}
Here's the solution. For some reason it needs 2 slashes in the root.
root /home/django/tradeium/frontend/dist//;
index index.html;
location / {
include proxy_params;
proxy_pass http://unix:/home/django/project/project.sock;
}
location = /custom/ {
try_files $uri $uri/ index.html;
}
I'm looking for a dynamic solution to handle pretty permalinks of multiple WordPress sites (nodes) installed in subdirectories.
The sites are accessible using URLs like this (I use cluster and node to denote the structure, but they're different for every case, but they always follow the same structure, and nodes are the directories that contain the WordPress root files):
https://www.domain.tld/cluster1/node1/
And what I'm trying to avoid is to create one rule per node like this:
location /cluster1/node1/ {
try_files $uri $uri/ /cluster1/node1/index.php$is_args$args;
}
location /cluster2/node2/ {
try_files $uri $uri/ /cluster2/node2/index.php$is_args$args;
}
location /cluster3/node3/ {
try_files $uri $uri/ /cluster3/node3/index.php$is_args$args;
}
location /cluster4/node4/ {
try_files $uri $uri/ /cluster4/node4/index.php$is_args$args;
}
That works, but there are over 43 nodes (constantly changes). So, I've tried the following:
location /([^/]+)/([^/]+)/ {
try_files $uri $uri/ /$1/$2/index.php$is_args$args;
}
Shows the homepage correctly, but shows a 404 for the pages of the nodes (like https://www.domain.tld/cluster1/node1/page/) (rendered by Nginx not WordPress).
location ~ ^/([^/]+)/([^/]+)/ {
try_files $uri $uri/ /$1/$2/index.php$is_args$args;
}
But that makes the PHP file being downloaded as a file called download.
location ~ /([^/]+)/([^/]+)/ {
try_files $uri $uri/ /$1/$2/index.php$is_args$args;
}
The same as the previous.
location ^~ /([^/]+)/([^/]+)/ {
try_files $uri $uri/ /$1/$2/index.php$is_args$args;
}
This makes the homepage of that node download the same as the previous attempt, but shows a 404 for the pages of the nodes (like https://www.domain.tld/cluster1/node1/page/) (rendered by Nginx not WordPress).
Any clue of why none of the above works? Any suggestion on how to make it work?
Thanks everyone!
You need to use a regular expression location block to capture the parameters for the internal redirection to the correct index.php handler. The regular expression location is declared using the ~ or ~* modifiers. See this document for details.
The regular expressions are evaluated in order, so the location for \.php$ must be placed above the location you are inserting. Otherwise, the PHP file will be downloaded instead of being executed.
For example:
location ~ \.php$ {
...
}
location ~ ^/([^/]+)/([^/]+)/ {
try_files $uri $uri/ /$1/$2/index.php$is_args$args;
}
I've a SPA (Single Page Application) site, let's say under https://example.com and an API for it under https://api.example.com
I want to serve server rendered content for specific useragents like googlebot, facebookexternalhit, etc.
So, if user goes to https://example.com/brandon/things it will get served SPA, but if bot goes to the same URL it will get served server rendered page with all proper meta and open graph tags.
My server rendered pages with proper matching are under https://api.example.com/ssr/
So for example if bot hits https://example.com/brandon/things it should get content from https://api.example.com/ssr/brandon/things
I almost got it working with nginx proxy_pass if statement to the Django application (which returns server rendered output) but unfortunately there's one edge case that makes it behave weirdly.
My implementation:
server {
listen 80;
server_name example.com; # url of SPA
index index.html;
root /srv/example_spa/public/dist; # directory of SPA index.html
# $ssr variable that tells if we should use server side rendered page
set $ssr 0;
if ($http_user_agent ~* "googlebot|yahoo|bingbot|baiduspider|yandex|yeti|yodaobot|gigabot|ia_archiver|facebookexternalhit|facebot|twitterbot|developers\.google\.com|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator|redditbot") {
set $ssr 1;
}
# location block that serves proxy_pass when the $ssr matches
# or if the $ssr doesn't match it serves SPA application index.html
location / {
if ($ssr = 1) {
proxy_pass http://127.0.0.1:9505/ssr$uri$is_args$args;
}
try_files $uri /index.html;
}
}
But there's the problem:
Everything works dandy and sweet, except one case.
User hits https://example.com/brandon/things/ and he gets SPA index.html - perfect.
User hits https://example.com/brandon/things and he gets SPA index.html - perfect.
Bot hits https://example.com/brandon/things/ and he gets server rendered page - perfect.
Bot hits https://example.com/brandon/things (without appended slash) and he gets redirected (301) to https://example.com/ssr/brandon/things - BAD BAD BAD
I've tried to make it work for couple of hours now without luck.
What would you suggest? I know if in nginx is evil, but I don't know how to make it work without it...
Any help is appreciated
You need to alter the redirects for proxy_pass
location / {
proxy_redirect http://127.0.0.1/ssr/ http://$host/ssr/;
proxy_redirect /ssr/ /;
if ($ssr = 1) {
proxy_pass http://127.0.0.1:9505/ssr$uri$is_args$args;
}
try_files $uri /index.html;
}
It turns out this was issue with my Django application redirect. I thought I had "APPEND_SLASH" option disabled, but it was enabled and made redirect when there was no slash. And it redirected without changing the host to https://api.example.com, but only URI part. Hence my confusion.
And I actually found two ways to fix that.
First, just use rewrite to append slash when there isn't one.
location / {
if ($ssr = 1) {
rewrite ^([^.]*[^/])$ $1/ permanent;
proxy_pass http://127.0.0.1:9505/ssr$uri$is_args$args;
}
try_files $uri /index.html;
}
Second, modify proxy_pass to always add / slash after $uri part and server side render application url config to accept two slashes at the end //'. It's a little hacky but has no side effects and works as it should.
Nginx config:
location / {
if ($ssr = 1) {
proxy_pass http://127.0.0.1:9505/ssr$uri/$is_args$args;
}
try_files $uri /index.html;
}
Django URL regex:
r'^ssr/(?P<username>[\w-]+)/(?P<slug>[\w-]+)(/|//)$'
I have a RESTful server. I serve my static files with Nginx. I want the root url ( www.website.com, www.website.com/ ) to point to a static html file, and EVERY other request to be redirected to my RESTful server. What I have:
location / {
proxy_pass http://localhost:5000/;
}
location /static {
autoindex on;
alias "some location";
}
location /media {
autoindex on;
alias "some location";
}
What I need: a directive that redirects only the Root URL (not everything like /).
Nginx location directive has = modifier for that.
location = / {
# only request to '/' gets here
}
location / {
# all other goes here
}
I am new to Nginx..and need to setup some redirects
We are launching our latest code, and what to redirect all instance of the sites
for eg:-
https://woi.com/movies
https://woi.com/movies/Fear
https://woi.com/videos
https://woi.com/videos/Captain
to
https://woi.tv/#!/movies
https://woi.tv/#!/movies/Fear
https://woi.tv/#!/videos
https://woi.tv/#!/videos/Captain
I have made changes in Nginx.conf file:-
Http
{
...
location /movies {
rewrite ^.* https://$woi.tv/movies permanent;
}
location /movies/ {
rewrite ^.* https://$woi.tv/movies/ permanent;
}
location /videos {
rewrite ^.* https://$woi.tv/videos permanent;
}
location /videos/ {
rewrite ^.* https://$woi.tv/videos/ permanent;
}
}
I dont know if I am right. But the above is not working.
Please help me.
If you want to redirect all unconditionally you can try something like this, not sure if the # can be written in a redirect or not, but you can try.
server {
listen 443 ssl;
server_name example.com;
root /path/to/root;
index index.php; # or whatever index
# ssl settings
location = / {
# the non redirecting settings
try_files $uri $uri/;
}
location / {
# the remaining of the site, we should redirect here
return 301 $scheme://$http_host#!$request_uri;
}
}
EDIT:
On a second thought I think this would break the assets, so I think the redirect should be as a fall back
location / {
try_files $uri #redirect;
}
location #redirect {
return 301 $scheme://$http_host#!$request_uri;
}