Ticket #2750: fixes to HTTP caching behavior across login/logout boundaries

* now ignoring if-modified-since if we failed an etag if-none-match comparison, per spec
* now including a hash of user id/nickname in most etags, so we'll update the view properly after login/logout

For API methods, checking the API-auth'ed user. (Many change results to include things like 'you're subscribed to this user' or 'this is one of your favorites', so user info is again needed)

There'll still be some last-modified stamps that aren't including user info properly, probably.
This commit is contained in:
Brion Vibber 2010-09-20 13:42:58 -07:00
parent 2f38c9c99c
commit 64cdbe6c55
19 changed files with 50 additions and 5 deletions

View File

@ -357,6 +357,7 @@ class ApiDirectMessageAction extends ApiAuthAction
return '"' . implode( return '"' . implode(
':', ':',
array($this->arg('action'), array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(), common_language(),
strtotime($this->messages[0]->created), strtotime($this->messages[0]->created),
strtotime($this->messages[$last]->created) strtotime($this->messages[$last]->created)

View File

@ -213,6 +213,7 @@ class ApiGroupListAction extends ApiBareAuthAction
return '"' . implode( return '"' . implode(
':', ':',
array($this->arg('action'), array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(), common_language(),
$this->user->id, $this->user->id,
strtotime($this->groups[0]->created), strtotime($this->groups[0]->created),

View File

@ -204,6 +204,7 @@ class ApiGroupListAllAction extends ApiPrivateAuthAction
return '"' . implode( return '"' . implode(
':', ':',
array($this->arg('action'), array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(), common_language(),
strtotime($this->groups[0]->created), strtotime($this->groups[0]->created),
strtotime($this->groups[$last]->created)) strtotime($this->groups[$last]->created))

View File

@ -183,6 +183,7 @@ class ApiGroupMembershipAction extends ApiPrivateAuthAction
return '"' . implode( return '"' . implode(
':', ':',
array($this->arg('action'), array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(), common_language(),
$this->group->id, $this->group->id,
strtotime($this->profiles[0]->created), strtotime($this->profiles[0]->created),

View File

@ -149,6 +149,7 @@ class ApiGroupShowAction extends ApiPrivateAuthAction
return '"' . implode( return '"' . implode(
':', ':',
array($this->arg('action'), array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(), common_language(),
$this->group->id, $this->group->id,
strtotime($this->group->modified)) strtotime($this->group->modified))

View File

@ -194,6 +194,7 @@ class ApiStatusesShowAction extends ApiPrivateAuthAction
return '"' . implode( return '"' . implode(
':', ':',
array($this->arg('action'), array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(), common_language(),
$this->notice->id, $this->notice->id,
strtotime($this->notice->created)) strtotime($this->notice->created))

View File

@ -181,6 +181,7 @@ class ApiSubscriptionsAction extends ApiBareAuthAction
return '"' . implode( return '"' . implode(
':', ':',
array($this->arg('action'), array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(), common_language(),
$this->user->id, $this->user->id,
isset($this->ids_only) ? 'IDs' : 'Profiles', isset($this->ids_only) ? 'IDs' : 'Profiles',

View File

@ -259,6 +259,7 @@ class ApiTimelineFavoritesAction extends ApiBareAuthAction
return '"' . implode( return '"' . implode(
':', ':',
array($this->arg('action'), array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(), common_language(),
$this->user->id, $this->user->id,
strtotime($this->notices[0]->created), strtotime($this->notices[0]->created),

View File

@ -346,6 +346,7 @@ class ApiTimelineFriendsAction extends ApiBareAuthAction
return '"' . implode( return '"' . implode(
':', ':',
array($this->arg('action'), array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(), common_language(),
$this->user->id, $this->user->id,
strtotime($this->notices[0]->created), strtotime($this->notices[0]->created),

View File

@ -229,6 +229,7 @@ class ApiTimelineGroupAction extends ApiPrivateAuthAction
return '"' . implode( return '"' . implode(
':', ':',
array($this->arg('action'), array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(), common_language(),
$this->group->id, $this->group->id,
strtotime($this->notices[0]->created), strtotime($this->notices[0]->created),

View File

@ -254,6 +254,7 @@ class ApiTimelineHomeAction extends ApiBareAuthAction
return '"' . implode( return '"' . implode(
':', ':',
array($this->arg('action'), array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(), common_language(),
$this->user->id, $this->user->id,
strtotime($this->notices[0]->created), strtotime($this->notices[0]->created),

View File

@ -244,6 +244,7 @@ class ApiTimelineMentionsAction extends ApiBareAuthAction
return '"' . implode( return '"' . implode(
':', ':',
array($this->arg('action'), array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(), common_language(),
$this->user->id, $this->user->id,
strtotime($this->notices[0]->created), strtotime($this->notices[0]->created),

View File

@ -311,6 +311,7 @@ class ApiTimelinePublicAction extends ApiPrivateAuthAction
return '"' . implode( return '"' . implode(
':', ':',
array($this->arg('action'), array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(), common_language(),
strtotime($this->notices[0]->created), strtotime($this->notices[0]->created),
strtotime($this->notices[$last]->created)) strtotime($this->notices[$last]->created))

View File

@ -232,6 +232,7 @@ class ApiTimelineTagAction extends ApiPrivateAuthAction
return '"' . implode( return '"' . implode(
':', ':',
array($this->arg('action'), array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(), common_language(),
$this->tag, $this->tag,
strtotime($this->notices[0]->created), strtotime($this->notices[0]->created),

View File

@ -234,6 +234,7 @@ class ApiTimelineUserAction extends ApiBareAuthAction
return '"' . implode( return '"' . implode(
':', ':',
array($this->arg('action'), array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(), common_language(),
$this->user->id, $this->user->id,
strtotime($this->notices[0]->created), strtotime($this->notices[0]->created),

View File

@ -151,6 +151,7 @@ class ShownoticeAction extends OwnerDesignAction
strtotime($this->avatar->modified) : 0; strtotime($this->avatar->modified) : 0;
return 'W/"' . implode(':', array($this->arg('action'), return 'W/"' . implode(':', array($this->arg('action'),
common_user_cache_hash(),
common_language(), common_language(),
$this->notice->id, $this->notice->id,
strtotime($this->notice->created), strtotime($this->notice->created),

View File

@ -1018,17 +1018,22 @@ class Action extends HTMLOutputter // lawsuit
} }
} }
$checked = false;
if ($etag) { if ($etag) {
$if_none_match = (array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER)) ? $if_none_match = (array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER)) ?
$_SERVER['HTTP_IF_NONE_MATCH'] : null; $_SERVER['HTTP_IF_NONE_MATCH'] : null;
if ($if_none_match && $this->_hasEtag($etag, $if_none_match)) { if ($if_none_match) {
// If this check fails, ignore the if-modified-since below.
$checked = true;
if ($this->_hasEtag($etag, $if_none_match)) {
header('HTTP/1.1 304 Not Modified'); header('HTTP/1.1 304 Not Modified');
// Better way to do this? // Better way to do this?
exit(0); exit(0);
} }
} }
}
if ($lm && array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)) { if (!$checked && $lm && array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)) {
$if_modified_since = $_SERVER['HTTP_IF_MODIFIED_SINCE']; $if_modified_since = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
$ims = strtotime($if_modified_since); $ims = strtotime($if_modified_since);
if ($lm <= $ims) { if ($lm <= $ims) {

View File

@ -494,6 +494,29 @@ function common_is_real_login()
return common_logged_in() && $_SESSION['real_login']; return common_logged_in() && $_SESSION['real_login'];
} }
/**
* Get a hash portion for HTTP caching Etags and such including
* info on the current user's session. If login/logout state changes,
* or we've changed accounts, or we've renamed the current user,
* we'll get a new hash value.
*
* This should not be considered secure information.
*
* @param User $user (optional; uses common_current_user() if left out)
* @return string
*/
function common_user_cache_hash($user=false)
{
if ($user === false) {
$user = common_current_user();
}
if ($user) {
return crc32($user->id . ':' . $user->nickname);
} else {
return '0';
}
}
// get canonical version of nickname for comparison // get canonical version of nickname for comparison
function common_canonical_nickname($nickname) function common_canonical_nickname($nickname)
{ {

View File

@ -79,6 +79,7 @@ class AutocompleteAction extends Action
function etag() function etag()
{ {
return '"' . implode(':', array($this->arg('action'), return '"' . implode(':', array($this->arg('action'),
common_user_cache_hash(),
crc32($this->arg('q')), //the actual string can have funny characters in we don't want showing up in the etag crc32($this->arg('q')), //the actual string can have funny characters in we don't want showing up in the etag
$this->arg('limit'), $this->arg('limit'),
$this->lastModified())) . '"'; $this->lastModified())) . '"';