I have setup varnish on a server that runs two sites on two different domains, varnish works perfect without www in front of the two domains, I have attached the vcl file in this pastebin, I guess it's a basic misconfiguration somewhere, but I can't figure out where - does anyone know of a solution?
http://pastebin.com/CF37isis
To me the configuration looks fine and you should not get any troubles with/without www. Are you sure the DNS is pointing to your varnish server for the www? Of course there's also the possibility that your application acts differently and sets extra cookies/headers on the www request.
Further you should really redirect one of the www/non-www to the other so that only one is always used but both works (can also easily be done with varnish, or also probably in your DNS providers settings).
A redirect in varnish could look something like this (do not this needs to be added in your current vcl_recv/vlc_error and you should not add new blocks):
sub vcl_recv {
if (req.http.host == "www.somedomain.com") {
set req.http.x-Redir-Url = "http://somedomain.com" + req.url;
error 750 req.http.x-Redir-Url;
}
if (req.http.host == "www.someotherdomain.com") {
set req.http.x-Redir-Url = "http://someotherdomain.com" + req.url;
error 750 req.http.x-Redir-Url;
}
}
sub vcl_error {
if (obj.status == 750) {
set obj.http.Location = obj.response;
set obj.status = 301;
return (deliver);
}
}
Related
I have Magento installation in a subfolder and a WordPress site. How can I use the same Varnish installation for two different CMS?
I have prepared the following default.vcl file code example, but not sure if I am moving in the right direction. Thanks
vcl 4.0;
if (req.url ~ "^/path/to/magento/") {
include "magento.vcl";
} elseif (req.url ~ "^/path/to/wordpress/") {
include "wordpress.vcl";
}
P.S. My Varnish version is 4.0
Before I continue, please be ware of the fact that Varnish 4 is end-of-life. Any bug or error you encounter will not be fixed and can result in unexpected behavior. The best way forward is by upgrading to Varnish 6.
That being said, you are definitely moving in the right direction. But please make sure the included logic is put inside a subroutine.
Your example code will typically live inside sub vcl_recv {}. If you have logic that belongs in other subroutines (like sub vcl_backend_response {} for example), please make sure you include that logic as well.
I'm testing a revised Varnish config and I need to see if certain URLs are hitting the cache or not. It seems not to like multiple parameters.
The Varnish config change is to not treat URLs with certain parameters as unique content. E.g.
/news/tech
/news/tech?itq=1001
/news/tech?itq=1002&ito=3553
should all be equivalent.
Scenario 1
Requesting a page that hasn't been cached yet:
curl -I 'http://example.com/news/tech'
Result:
X-Varnish-Cache: MISS
Sending the same request a second time gives this result:
X-Varnish-Cache: HIT
Scenario 2
Requesting the above URL again, but with a parameter:
curl -I 'http://example.com/news/tech?itq=1001'
That is one of the parameters to not treat as unique content.
Result:
X-Varnish-Cache: HIT
Scenario 3
Requesting with a second parameter:
curl -I 'http://example.com/news/tech?itq=1001&ito=3553'
Response:
X-Varnish-Cache: MISS
It seems like the Varnish config works for ? but not for &
Here's the relevant line in my Varnish config:
set req.url = regsuball(req.url, "([\?|\&])+(utm_campaign|utm_content|utm_medium|utm_source|utm_term|ITO|et_cid|et_rid|qs|itq|ito|itx\[idio\])=[^&\s]*&?", "\1");
I guess this is only running once, so it won't strip out multiple parameters. How would I do that?
After a bit of experimentation, I found a way to do this.
# Strip out query parameters that do not affect the page content
set req.url = regsuball(req.url, "([\?|\&])+(utm_campaign|utm_content|utm_medium|utm_source|utm_term|ITO|et_cid|et_rid|qs|itq|ito|itx\[idio\])=[^&\s]+", "\1");
# Get rid of trailing & or ?
set req.url = regsuball(req.url, "[\?|&]+$", "");
# Replace ?&
set req.url = regsub(req.url, "(\?\&)", "\?");
The 2nd and 3rd commands are just cleanup. But this does seem to work.
Implementation #thirtyish gives issues when it is used with combination of additional get parameters.
e.g. ?utm_campaign=1&utm_source=2&my_add_parameter=3 is not working.
If we change the order to ?my_add_parameter=3=utm_campaign=1&utm_source=2 is working.
And by not working I mean it generates multiple & signs in the url query.
I update the regex to fix that.
set req.url = regsuball(req.url, "[\?\&](utm_\w+|hsa_\w+|gclid|fbclid|pc)=[^&\s]+", "");
# trailing & or ?
set req.url = regsuball(req.url, "[\?|&]+$", "");
set req.url = regsub(req.url, "(\?\&)|(\&)", "\?");
I have a request from a client that they would like for me to have this happen. When a user on the web goes to http://x.x.x.x have it 301 redirect to their domain name http://www.domain.com . I have messed around with rules in URL Rewrite and I have no problem specifying the conditions to determine the request for the IP address, etc. But when I do the redirect, the site goes into a redirect loop.
My question is how can I do this ? I know this is basically redirecting to the same place, hence the loop, but is there any way to make this happen ? For SEO reasons, they don't want visitors to the site to be able to get it via the public IP.
Thanks,
Chris
//////
Ok All, Thanks to some direction and good ideas from Caner, I was able to figure it out.
Here is the ASP code I used:
<%
if Request.ServerVariables("HTTP_X_HOST") = "" then
Dim rd
rd = "http://www.xxx.com" & Request.ServerVariables("PATH_INFO")
Response.Status="301 Moved Permanently"
Response.AddHeader "Location",rd
Response.end
end if
%>
Thanks to all the suggestions!
Chris
It is a kind of tricky, but instead of configuring this on IIS, I suggest your client to add some code in their header file( header.asp file, site.master etc..);
This code can check the request; and you can reach HttpContext.Current.Request.Url.Host.
Using HttpContext.Current.Request.Url.Host, you can do a redirect.
string currentURL = HttpContext.Current.Request.Url.Host;
if(!currentURL.StartsWith("www."))
{
string newURL = HttpContext.Current.Request.Url.Host;
if(currentURL =="www.x.x.x.x")
newURL ="www.domain.com";
newURL += HttpContext.Current.Request.Url.PathAndQuery;
Response.Redirect(newURL);
}
Hope this helps.
I want to add a revision number to my static assets so when they're updated browsers will refresh them - how to force browsers reload static assets after code deployment?
Without a revision query string I can see hits in 'varnishstat', with them I see that its passing the request to the backend.
how can I cache static assets with revisions ?
Change your static assets regular expression to something like this:
if (req.url ~ "\.(jpeg|jpg|png|gif|ico|swf|js|css)(\?.*|)$") {
return (lookup);
}
it will match revisions too.
It is a strange needs but the following code should resolve your issue :
sub vcl_recv {
set req.url = regsub(req.url, "(\.(jpeg|jpg|png|gif|ico|swf|js|css))\?.*$", "\1");
}
You will need to clear varnish cache (purge/ban) every time your resource is updated in your backend.
we recently have put Varnish in front of our Drupal because the server was suffering heavy load and we are very pleased in general.
The only problem remaining is that we sometimes have an infinite redirection loop in the cached data. We have found this through our HTTP-Monitoring. We check the front page every minute. The page in the cache sometimes contains the full front page, but with a Location header set, that sends the user to the front page again.
We are not quite sure what could cause this, but also have no clue on how could track this down. Of course, the best way to handle this would be on the drupal side, but we can't really tell why this does happen.
Is there a way to log the cases when this happens? Or is it possible to detect this in varnish and mark the current cache content as invalid?
Of course, we don't want to always pass intentional redirects to the origin server, but the ones that would cause an infinite loop.
I hope to hear some ideas how we can further track this down. Many thank in advance for all kinds of hints.
I have found a workaround for this:
sub vcl_fetch {
// Fix a strange problem: HTTP 301 redirects to the same page sometimes go in$
if (beresp.http.Location == "http://" + req.http.host + req.url) {
if (req.restarts > 2) {
unset beresp.http.Location;
#set beresp.http.X-Restarts = req.restarts;
} else {
return (restart);
}
}
}
I give the backend a second (and thirhd) chance to return a proper page. If that fails as well, the Location header is removed. This works, because the proper page is served with just an additional invalid Location header.
The accepted answer by #philip updated for Varnish 4:
sub vcl_backend_response {
#Fix a strange problem: HTTP 301 redirects to the same page sometimes go in$
if (beresp.http.Location == "http://" + bereq.http.host + bereq.url) {
if (bereq.retries > 2) {
unset beresp.http.Location;
#set beresp.http.X-Restarts = bereq.retries;
} else {
return (retry);
}
}
}