I want to use ESI in Varnish to combine content from different sides.
Every side is a small micro service with a small frontend snippet.
ESI should construct the page with the different snippets.
I'll be using Varnish 4.0.5.
As long I'll use it for content from my side its works fine.
<html>
<body>
<esi:include src="/hello"/> <!-- works -->
<esi:include src="http://www.example.org/index.html"/> <!-- doesn't works -->
</body>
</html>
Here's my vcl
vcl 4.0;
backend default {
.host = "localhost";
.port = "8080";
}
sub vcl_recv {
# Only a single backend
set req.backend_hint= default;
# Setting http headers for backend
set req.http.X-Forwarded-For = client.ip;
# Unset headers that might cause us to cache duplicate infos
unset req.http.Accept-Language;
unset req.http.User-Agent;
# drop cookies and params from static assets
if (req.url ~ "\.(gif|jpg|jpeg|swf|ttf|css|js|flv|mp3|mp4|pdf|ico|png)(\?.*|)$") {
unset req.http.cookie;
set req.url = regsub(req.url, "\?.*$", "");
}
# drop tracking params
if (req.url ~ "\?(utm_(campaign|medium|source|term)|adParams|client|cx|eid|fbid|feed|ref(id|src)?|v(er|iew))=") {
set req.url = regsub(req.url, "\?.*$", "");
}
}
sub vcl_backend_response {
set beresp.do_esi = true;
}
I'll get the following result in the browser
hello
Cannot GET /index.html
When I define the external host also in the VCL
backend otherbackend {
.host = "www.example.org";
.port = "80";
}
and
sub vcl_recv {
# Only a single backend
set req.backend_hint= default;
if (req.http.host == "www.example.org") {
set req.backend_hint = otherbackend;
}
I'll get some content from the external site (static assets will no be served and therefore leads to an error in the browser)
Question
- Is there a way to get content from an external site without defining every external site as a backend?
Related
I am new to varnish cache.i have a website xyz.com and i want cache homepage first only so how to start with varnish and how will the vcl file look like for homepage cache only.
Please help.
Here's some basic VCL code that will cache the homepage explicitly and rely on the built-in VCL behavior for all other requests.
vcl 4.1;
backend default {
.host = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
if((req.method == "GET" || req.method == "HEAD") && req.url == "/") {
return(hash);
}
}
I have a Varnish cache setup in front of my application. I want some routes to be not cached, but completely passed through to other service.
I need to preserve headers like X-Forwarded-For so underlying service won't notice anything.
I've tried "pipe" configuration but it didn't worked as I excepted.
I'm looking for complete config section.
Config I've tried looked like:
backend blog {
.host = "127.0.0.1";
.port = "8083";
}
sub vcl_recv {
if (req.url ~ "^/blog/") {
set req.backend_hint = blog;
return (pipe);
} else {
set req.backend_hint = default;
}
}
You're looking for return(pass), which will not serve the content from the cache and connect directly to the backend.
The return(pipe) logic is only useful if you're unsure whether or not the incoming request is actually an HTTP request. By piping a request, you take away all notion of HTTP and reduce the data to plain TCP.
Thanks to return(pass) all headers are maintained.
Here's an updated version of your code example:
vcl 4.1;
backend blog {
.host = "127.0.0.1";
.port = "8083";
}
sub vcl_recv {
if (req.url ~ "^/blog/") {
set req.backend_hint = blog;
return (pass);
} else {
set req.backend_hint = default;
}
}
Since a little while I am using Varnish Cache solutions and as long as the configuration was more or less the same as it was after the installation everything worked out very well.
But now I like to do a little bit more with Varnish. Currently I am using the following setup for my servers :
Visitors -> CloudFlare -> HaProxy -> Varnish (separate servers) -> Apache2 Content.
What I like to know is how am I able to make the right vcl script to accept let's say an incoming request from ip A on port B and redirect this to ip C on port D. (And this more than once.)
Example :
Default.Varnish works well like this:
DAEMON_OPTS="-a :8085,:8087 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-s malloc,768m"
But now about the Varnish.Default :
backend default_1 { .host = "11.22.333.444"; .port = "8885"; }
backend default_2 { .host = "11.22.333.444"; .port = "8887"; }
And I tried something like this :
sub vcl_recv {
if (server.port == 8885) { set req.backend = default_1; }
if (server.port == 8887) { set req.backend = default_2; }
}
(Please be aware of the fact that both requests are going to the
same outgoing server. Only the port is different!)
Someone who knows enough from Varnish already knows what I want I guess. I just like to use Varnish to proxy separate 'channels' based on different ports.
Try to check Varnish bind port, not backend port
sub vcl_recv {
if (server.port == 8085) { set req.backend = default_1; }
if (server.port == 8087) { set req.backend = default_2; }
}
I would like to route subdomains in varnish using regex capture. Here is my attempt:
backend gitlab {
.host = "127.0.0.1";
.port = "82";
}
backend jenkins {
.host = "127.0.0.1";
.port = "83";
}
sub vcl_recv {
if (req.http.host ~ "^((gitlab|jenkins|ruby))\.") {
set req.backend = $1;
return(pass);
}
error 405 "No service.";
}
How can this kind of construct be achieved in VCL? I'd rather not use a less elegant "if-then" pattern.
You can not refer to a backend with a string. The VCL compiler doesn't support it. You might be able to write a special director (a vmod) that does the work for you, but this would require you to bring out your copy of K&R and start digging around in the Varnish source tree.
It would not surprise me if somebody will write a VMOD to do something like this some day. It will be very useful.
Actually my set up looks like this.
cluster.com - 192.168.0.200 (varnish/port 80)
example.com - 192.168.0.100 (apache,namebased vhost/8080 - backendname - website)
yyy.com - 192.168.0.100 (apache,namebased vhost/8080 -backendname - api)
cluster.com is the varnish server and front-end connections coming to this and rewrite to other defined back-ends (round-robin based balancing)
backend website {
.host = "example.com";
.port = "8080";
}
backend api {
.host = "yyy.com";
.port = "8080";
}
director clust round-robin {
{ .backend = api; }
{ .backend = website; }
}
sub vcl_recv {
set req.backend = clust;
if (req.request)
{
return(pass);
}
}
when i hit the cluster.com , it is always going to example.com, but what i need to do is first request go to example.com second request yyy.com and so on...when i add another server (different host/different IP say 192.168.0.111/zzz.com, and a different backend) , it goes like this
first request - example.com
second request - examplee.com
third request - zzz.com
but i can change the default behavior by setting up set req.host = yyy.com and then it will goes to
first request - yyy.com
second request - yyy.com
third request - zzz.com
this is something to do with the host-header forwarding to the correct back-end. how should i add that functionality to the vcl_recv ?
appreciate your help on this, this is working perfectly with other servers (different servers, not with namebased vhosts)
You don't need to worry about Host headers, since varnish backend selection doesn't use it.
So, you only need a backend declaration for 192.168.0.100:8080 (since Apache will take care of named virtual hosts). NOTE: The host header in request should contain a defined Apache ServerName/ServerAlias
So if 192.168.0.111 can resolve both example.com and yyy.com but 192.168.0.100 can't resolve zzz.com , you only need to deal with backend choosing:
# As both your defined backends resolve to the same IP and port,
#you only need to define ONE backend instead of two
backend website_and_api {
# Which resolves both example.com and yyy.com
.host = "192.168.0.100";
.port = "8080";
}
# The server you add later on
backend third {
# Which resolves all example.com, yyy.com and zzz.com
.host = "192.168.0.111";
.port = "8080";
}
director clust round-robin {
#Backends that resolve both example.com and yyy.com
{ .backend = website_and_api; }
{ .backend = third; }
}
sub vcl_rec {
# Set the default backend, I'll choose two since it resolves most domains
set req.backend = third;
# Choose clust if the domain is appropiate
if ( req.http.host ~ "example.com"
|| req.http.host ~ "yyy.com") {
set req.backend = clust;
}
# Any return must be done below here
# ...
}
PS: VCL edited and expanded trying to clarify a bit
This will work fine given:
The client pass the correct Host header in the request (example.com|yyy.com|zzz.com)
Server 192.168.0.100 is correctly set up to handle Named virtual hosting:
Apache resolves example.com:8080
Apache resolves yyy.com:8080
Apache gives a sensible default for 192.168.0.100:8080
Server 192.168.0.111 is correctly set up to handle Named virtual hosting:
Apache resolves example.com:8080
Apache resolves yyy.com:8080
Apache resolves zzz.com:8080
Apache gives a sensible default for 192.168.0.100:8080
Your VCL code don't mess received Host header (don't set it to another thing)