Nginx/Boost setup - logins only working on second Try

Events happening in the community are now at Drupal community events on www.drupal.org.
ArgetlamX's picture

I've set up a D7 site with Nginx and to accelerate the site Boost as well. I've used the config by omega8cc though not using aegir/barracuda - wanted it to be a bit easier at the beginning.
Now whenver users want to log in to the site the on the first log in (site is running in https completely), after entering their username and password they get thrown back to the same page without success - username and password field empty. So apparently Boost didn't recognize the post correctly, serving a cached page.
However, when the user tries to login again - he succeeds.

I couldn't find any info regarding this sprecific problem on the nginx group or in the boost issue tracker, however i found an article on using nginx/boost and apache http://www.howtoforge.com/how-to-speed-up-drupal-7.7-with-boost-and-nginx-debian-squeeze-p2 with one interesting info:
in modules/user/user.module around line 2190 the author sets the following cookie:

[...]
function user_authenticate($name, $password) {
  $uid = FALSE;
  if (!empty($name) && !empty($password)) {
    $account = user_load_by_name($name);
    if ($account) {
      // Allow alternate password hashing schemes.
      require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc');
      if (user_check_password($password, $account)) {
        // Successful authentication.
        $uid = $account->uid;

//CHANGE HERE
        if ($uid && !isset($_COOKIE['DRUPAL_UID'])) {
           setcookie('DRUPAL_UID', $uid, $_SERVER['REQUEST_TIME'] + ini_get('session.cookie_lifetime'), ini_get('session.cookie_path'), ini_get('session.cookie_domain'));
        }
// END CHANGE

        // Update user to new password scheme if needed.
        if (user_needs_new_hash($account)) {
          user_save($account, array('pass' => $password));
        }
      }
    }
  }
  return $uid;
}
[...]

and in the boost module at modules/boost/boost.module line 544 he changes the following:

//setcookie(BOOST_COOKIE, '0', $expires, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), ini_get('session.cookie_secure') == '1');
    setcookie(BOOST_COOKIE, '', $expires, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), ini_get('session.cookie_secure') == '1');

After changing these bits users can log in to the site on first try. However, I'm not too fond of this solution as it is a core hack.
Maybe someone has an idea where to look for a hint or an idea for an implementation without fiddling with the core.

Comments

We experienced this problem

Dashu's picture

We experienced this problem as well, sadly, the only solution we could find was the one described here.
I would be VERY interested in a solution which does not require any core hacking.

It is well known that a vital ingredient of success is not knowing, that what you're attempting can't be done. - Terry Pratchett

The Drupal 7 version of Boost

brianmercer's picture

The Drupal 7 version of Boost hasn't had a stable release and it doesn't look like it has a developer working on it.

Is the fix from 30th Nov. the

Dashu's picture

Is the fix from 30th Nov. the one we should use for solving our problem ? Because the Issue related to that particular commit does not seem related to our problem.

It is well known that a vital ingredient of success is not knowing, that what you're attempting can't be done. - Terry Pratchett

The DRUPAL_UID

perusio's picture

cookie is completely unecessary. You can burst the cache using something like:

map $http_cookie $no_cache {
    default 0;
     ~SESS  1;
}

map $request_method $no_cache {
    default 0;
    POST 1;
}

Then in your @cache location just set:

location @cache {

    ## Error page handler for the case where $no_cache is 1. POST
    ## request or authenticated.
    error_page 418 = @no_cache;

    ## If $no_cache is 1 then it means that either we have a session
    ## cookie or that the request method is POST. So serve the dynamic
    ## page.
    if ($no_cache) {
        return 418; # I'm a teapot/I can't get no cachifaction
    }

    # Now for some header tweaking. We use a date that differs
    # from stock Drupal. Everyone seems to be using their
    # birthdate. Why go against the grain?
    add_header Expires "Tue, 13 Jun 1977 03:45:00 GMT";
    # We bypass all delays in the post-check and pre-check
    # parameters of Cache-Control. Both set to 0.
    add_header Cache-Control "must-revalidate, post-check=0, pre-check=0";
    # Funny...perhaps. Egocentric? Damn right!;
    add_header X-Header "Boost Helás Avril 1.0";

    # We try each boost URI in succession, if every one of them
    # fails then relay to Drupal.
    try_files /cache/normal/$host${uri}${args}.html /cache/perm/$host${uri}.css /cache/perm/$host${uri}_.js /cache/$host/0$uri.html /cache/$host/0${uri}/index.html /index.php?q=$uri&$args;
}

## We need another named location for the rewrite to work otherwise we
## get the unclean URLs in all their glory.
location @no_cache {
    try_files $uri /index.php?q=$uri&$args;
}

This excerpt is from my config.

I must be think but I've been

abisma's picture

I must be thick but I've been searching for a couple of days and I cannot find out where/how I should find map_cache.conf... I guess the answer is really simple but I cannot find it.

Thanks a lot in advance!

AFAIK

perusio's picture

this is not in Barracuda but rather here. You can use directly on Barracuda though.

thanks, I had found that but

abisma's picture

thanks, I had found that but nowhere do I find where that file should go and how it's supposed to be read by whatever will read it (nginx?)

Cheers

found it: "include

abisma's picture

found it: "include map_cache.conf;"

Sorry! :-)

Use Barracuda/Octopus and get it fixed on the fly!

omega8cc's picture

This has been fixed in BOA recently (in HEAD) even better - we are still checking also for Boost specific cookie DRUPAL_UID, but instead of checking also/or for Drupal specific/standard cookie, we are checking for BOA specific cookie OctopusNoCacheID, like below:

###
### Boost compatible cache check.
###
location @cache {
  if ( $request_method !~ ^(?:GET|HEAD)$ ) {
    return 405;
  }
  if ( $http_cookie ~ (?:DRUPAL_UID|OctopusNoCacheID) ) {
    return 405;
  }
  error_page 405 = @drupal;
  add_header Expires "Tue, 24 Jan 1984 08:00:00 GMT";
  add_header Cache-Control "must-revalidate, post-check=0, pre-check=0";
  add_header X-Header "Boost Citrus 1.9";
  charset    utf-8;
  try_files  /cache/$device/$host${uri}_$args.html @drupal;
}

The nice side-effect here is that it deactivates Boost cache for the visitor or user on the fly, automatically (for 5 minutes) - after any POST request, for all Ubercart-like sites, for all sites accessed via HTTPS and for all sites accessed with "dev" in the subdomain, so it fixes even more issues in a one step.

Why not use map or

perusio's picture

do something like:

if ($request_method = POST) {
    return 405;
}

No regexes required :)

EDIT: Ah yes, I'm assuming you don't have the WebDAV module compiled in. Just in case you have. This will do:

map $request_method $no_cache {
   default 1;
   HEAD 0;
   GET 0;
}

I've succesfully

ArgetlamX's picture

used perusio's "map $request_method" suggestion and it's working fine.

Thanks for the help all!

Nginx

Group organizers

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: