Question

Nginx trowing error Error 400 Bad Request on Varnish

  • Posted on November 12, 2014
  • I3litzAsked by Ritchie

Hello, pretty weird thing is happening to one of my sites, I use Nginx 1.6.2 and everything works normal, but visitors who come from Varnish nodes (on another servers) receive some intermittent error 400 Bad Request.

If I modify my hosts file to point my domain directly to Nginx there is no error, if I pass trough Varnish as normal y get error 400 bad request (from Nginx) from time to time, so my guess is there is something wrong on Varnish.

Any Idea where to start?

Here my config: Varnish default.vcl

vcl 4.0;

backend default {
    .host = "23.23.143.32";
    .port = "80";
    .probe = {
        .url = "/";
        .timeout = 1000ms;
        .interval = 5s;
        .window = 10;
        .threshold = 8;
    }
}

backend backup {
    .host = "23.23.143.32";
    .port = "80";
    .probe = {
        .url = "/";
        .timeout = 1000ms;
        .interval = 5s;
        .window = 10;
        .threshold = 8;
    }
}

backend espejo {
    .host = "54.163.206.168";
    .port = "80";
    .probe = {
        .url = "/";
        .timeout = 1000ms;
        .interval = 5s;
        .window = 10;
        .threshold = 8;
    }
}

import directors;    # load the directors
sub vcl_init {
    new cluster1 = directors.random(); #use .random() for weight, round_robin() for equal load balancing.
    cluster1.add_backend(default,10);  #use (default,weight); with .random() ie: (default,2); (backup,1); = 2/3 to default, 1/3 to backup backend.
    cluster1.add_backend(backup,0);
}

# Routine to identify and classify a device based on User-Agent
sub identify_device {
 
  # Default to classification as a PC
  set req.http.X-Device = "pc";
 
  if (req.http.User-Agent ~ "iPad" ) {
    # The User-Agent indicates it's a iPad - so classify as a tablet
    set req.http.X-Device = "mobile-tablet";
  }
 
  elsif (req.http.User-Agent ~ "iP(hone|od)" || req.http.User-Agent ~ "Android" || req.http.User-Agent ~ "Mobile.+Firefox") {
    # The User-Agent indicates it's a iPhone, iPod or Android - so let's classify as a touch/smart phone
    set req.http.X-Device = "mobile-smart";
  }

  elsif (req.http.User-Agent ~ "SymbianOS" || req.http.User-Agent ~ "^BlackBerry" || req.http.User-Agent ~ "^SonyEricsson" || req.http.User-Agent ~ "^Nokia" || req.http.User-Agent ~ "^SAMSUNG" || req.http.User-Agent ~ "^LG") 		{
    # The User-Agent indicates that it is some other mobile devices, so let's classify it as such.
    set req.http.X-Device = "mobile-other";
  }
}

sub vcl_recv {
    call identify_device;

    # send all traffic to the cluster1 director:
    set req.backend_hint = cluster1.backend();

    if (req.http.host == "espejo.na.com") {
        set req.backend_hint = espejo;
    }
	
    if (req.method == "GET" || req.method == "HEAD") {
        return (hash);
    }

    if (req.http.User-Agent ~ "(?i)ipad") {
        return (hash);
    }

    # Add header for sending client ip to backend
    set    req.http.X-Forwarded-For = client.ip;

    # Remove has_js and CloudFlare/Google Analytics __* cookies.
    set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_[_a-z]+|has_js)=[^;]*", "");
    # Remove a ";" prefix, if present.
    set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");
 
    # Remove cookies and query string for real static files
    if (req.url ~ "^/[^?]+\.(gif|jpg|jpeg|swf|css|js|txt|flv|mp3|mp4|pdf|ico|png|gz|zip|lzma|bz2|tgz|tbz)(\?.*|)$") {
       unset req.http.cookie;
       set req.url = regsub(req.url, "\?.*$", "");
    }

    # Don't cache admin
#    if (req.url ~ "((wp-(login|admin|comments-post.php|cron.php))|login)" || req.url ~ "preview=true" || req.url ~ "xmlrpc.php" || req.url ~ "on.gamemode.es/" || req.url ~ "phpMyAdmin" || req.url ~ "foro" || req.url ~ "contactform.php") {
#        return (pass);
#    } else {
#        unset req.http.cookie;
#    }

    #Blocks some urls
    if (req.url ~ "(wp-(login|admin))|login") {
        return (synth(405, "Su computador no esta dirigido al servidor correcto, contacte a TI por ayuda."));
    }

}
 
sub vcl_backend_response {
    # Dont cache admin
    if (bereq.url ~ "(wp-(login|admin|comments-post.php|cron.php))|login" || bereq.url ~ "preview=true" || bereq.url ~ "xmlrpc.php" || bereq.url ~ "on.gamemode.es/" || bereq.url ~ "phpMyAdmin" || bereq.url ~ "foro" || bereq.url ~ "contactform.php") {
		set beresp.uncacheable = true;
        set beresp.ttl = 120s;
        return (deliver);
    } else {
        if ( beresp.ttl > 0s ) {
			unset beresp.http.set-cookie;
	    }
	    # Our cache TTL
	    set beresp.ttl = 10s;
	    set beresp.grace = 24h; 
	    return(deliver);
    }

    if (beresp.status == 404 || beresp.status >= 500) {
        set beresp.ttl   = 0s;
        set beresp.grace = 24h;
    }
}

sub vcl_hash {
# If the device has been classified as any sort of mobile device, include the User-Agent in the hash
# However, do not do this for any static assets as our web application returns the same ones for every device.
  if (!(req.url ~ ".(gif|jpg|jpeg|swf|flv|mp3|mp4|pdf|ico|png|gz|tgz|bz2)$")) {
    hash_data(req.http.X-Device);
  }
}

Show comments

Submit an answer

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Sign In or Sign Up to Answer

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Want to learn more? Join the DigitalOcean Community!

Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in Q&A, subscribe to topics of interest, and get courses and tools that will help you grow as a developer and scale your project or business.

Same problem here with nginx+varnis+ezpublish CMS.

Any idea?