Fixed Incorrect "Expires" header for attachments

Yoskaldyr

Well-known member
When session starts "expires" header set to:
PHP:
      header('Expires: Thu, 19 Nov 1981 08:52:00 GMT');
So, when attachment has downloaded it always be expired.

Image proxy feature works ok (correct "expires" header)

I can manually change "expires" header on webserver side, but better if it be fixed on xenforo side.
 
There isn't a guarantee that an attachment's data never changes, though it is currently like that. As such, a far-future expires may not be appropriate. Other systems that do use a far-futures expires value all have URLs that are guaranteed to change when the data actually changes. What value are you expecting there to be?

The image proxy doesn't set any Expires header, BTW.
 
The image proxy doesn't set any Expires header, BTW.
"correct "expires" header" - I mean without it.

With expired "expires" header attachment "etag" header is useless.

May be just clear "expires" header for attachments such as for image proxy?
 
Browser not sends HTTP_IF_NONE_MATCH header if url marked as expired. So code
PHP:
    $eTag = $this->_request->getServer('HTTP_IF_NONE_MATCH');
     if ($eTag && $eTag == '"' . $attachment['attach_date'] . '"')
     {
       $this->_routeMatch->setResponseType('raw');
       return $this->responseView('XenForo_ViewPublic_Attachment_View304');
     }
is absolutely useless.
 
But if I change or clear "expires" header for attachment route on webserver side than etag header is used and 304 http code returned as well.
 
If you don't expire them and let user's browsers cache them, the attachment view counters will be wrong because then it becomes just a counter of how many unique users viewed it. You also get into other issues with proxy/cache servers keeping it.
 
If you don't expire them and let user's browsers cache them, the attachment view counters will be wrong because then it becomes just a counter of how many unique users viewed it. You also get into other issues with proxy/cache servers keeping it.
Ok, view counter must be above 304 response.

Do you look at the code in XenForo_ControllerPublic_Attachment::actionIndex or not?
Setting Etag and expired Expires headers when displaying attachment at the first time and checking HTTP_IF_NONE_MATCH at the second is useless, because browser not send HTTP_IF_NONE_MATCH if page has already expired.
 
@digitalpoint It looks like @Yoskaldyr is correct.

I think we can use Cache-Control: max-age=31556926; no-cache in XenForo_ControllerPublic_Attachment to force browsers to store cached copies indefinitely without touching Session at all because Cache-Control takes precedence over Expires if it is present (this needs to be verified). This way we tell browsers to always revalidate cache by sending HTTP request and we have complete control over caching by using Etags.

@Mike Do you think it will work this way?
 
Browser not sends HTTP_IF_NONE_MATCH header if url marked as expired. So code
PHP:
    $eTag = $this->_request->getServer('HTTP_IF_NONE_MATCH');
     if ($eTag && $eTag == '"' . $attachment['attach_date'] . '"')
     {
       $this->_routeMatch->setResponseType('raw');
       return $this->responseView('XenForo_ViewPublic_Attachment_View304');
     }
is absolutely useless.
Can you demonstrate how you've confirmed this? I've just checked in Chrome, Firefox and IE and none of them behave like that. They all send an If-None-Match header on the second request and return the 304 as expected. (If you're checking in the developer tools, you need to make sure you haven't enabled the option to force refreshes from the server.)
 
@Mike
I've double checked in various browsers and discovered, that the problem arises only when browser's local cache full. If you clear the cache, everything works fine.

But if browser cache is full, attachments doesn't get loaded into cache at all because of their Expires header (the page is already expired).

If you test this on a fresh browser with empty cache - you will never have this problem. But an average user has a great chance to not have any of the attachments in the cache at all.
 
For comparison, proxy images without Expires header stored in local cache even local cache is full (overwrite old cache entries) and all next browser requests will be with HTTP_IF_NONE_MATCH header.
 
Top Bottom