I am using varnish 4 in front of apache. I need requests made to deutsh.de coming from headers with the preferred language es or ca (unless it also has de or en) to be redirected to spanish.es. Could somebody provide me with the appropriate syntax? Thank you
2 Answers
So I managed to put together something in the file used to start varnish:
sub vcl_recv {
if((req.http.Accept-Language !~ "de" || req.http.Accept-Language !~ "en") && (req.http.Accept-Language ~ "es" || req.http.Accept-Language ~ "ca" || req.http.Accept-Language ~ "eu"))
{
return(synth(301,"Moved Permanently"));
}
}
sub vcl_synth {
if(req.http.Accept-Language ~ "es" || req.http.Accept-Language ~ "ca" || req.http.Accept-Language ~ "eu")
{
set resp.http.Location = "http://spanish.es";
return (deliver);
}
}
...This appears to work

- 69
- 8
-
1Your if statement in the vcl_recv currently contains an AND between 2 OR statements without any brackets. This causes strange behavior. its better to just use `if(req.http.Accept-Language != "de" && req.http.Accept-Language~="en"){ }` you can set a variable that can be used to define the redirect in the synth sub vcl_recv {` if(req.http.Accept-Language != "de" && req.http.Accept-Language~="en"){ set req.http.redirectTo = "es"; return (synth(302,"Moved Temporarily"); }} sub vcl_synth{ if(req.http.redirectTo == "es"){ set resp.http.Location ="http://spanish.es"; return (deliver) }}` – Brian van Rooijen Mar 29 '16 at 07:48
I have slightly extended the proposed solution with some regex that guarantees that we dont have german or english as a higher prioritised language configured in the accept-language header.
To explain the regex I think it would be good to keep in mind how such an Accept-Language
header might look like: Accept-Language: de-DE,en-US,es
To consider the preferences of the users the used regex searches for the provided language but at the same time ensures that none of the other offered languages will be found before.
The latter is achieved somewhat cryptically with a negative look ahead expression "(^(?!de|en).)*"
to ensure that neither de, nor en appears before the "es|ca|eu" entry.
^ # line beginning
.* # any character repeated any number of times, including 0
?! # negative look-ahead assertion
Additionally I have added a check if SSL is already used to achieve the language and SSL switch in one redirect.
With the return(synth(850, "Moved permanently"));
you save one if clause in the vcl_synth which will reduce your config a lot especially when you have to do many of those language based redirects.
sub vcl_recv {
if (req.http.X-Forwarded-Proto !~ "(?i)https" && req.http.Accept-Language ~ "^((?!de|en).)*(es|ca|eu)" {
set req.http.x-redir = "https://spanish.es/" + req.url;
return(synth(850, "Moved permanently"));
}
}
sub vcl_synth {
if (resp.status == 850) {
set resp.http.Location = req.http.x-redir;
set resp.status = 301;
return (deliver);
}
}

- 629
- 12
- 14