Search code examples
djangohttpcachingbrowser-cachehttp-caching

Odd Behaviour of Icon Caching


Consider this view that generates an ico image:

from django.http import HttpResponse
from app.somewhere import Favicon

# View URL: `/<str:colour>.ico`
def favicon( request, colour ):
    response = HttpResponse(
        Favicon.render( colour ),
        status=200
    )

    response['Content-Type'] = 'image/x-icon'
    response['Cache-Control'] = 'public, max-age=31536000'

    return response

Favicon.render() returns a valid byte stream, do not pay any attention on that.

Here is a link element in head of my HTML document:

<link rel=icon href=/7f9fa4.ico>

Now comes the question: why each time I reload the page, my browser, Chromium 73, makes a request to /7f9fa4.ico, instead of retrieving the icon from cache? If I will open /7f9fa4.ico in a new tab, first time request to the server would be sent, further my browser will retrieve an image from cache; now tell me what's wrong with the browser-caching system.


Here is a request (cookies and preferences are omitted):

GET /7f9fa4.ico HTTP/1.1
Host: localhost:8000
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36
Referer: http://localhost:8000/

And these are response headers:

HTTP/1.1 200 OK
Date: Mon, 03 Jun 2019 07:03:58 GMT
Server: WSGIServer/0.2 CPython/3.6.8
Content-Type: image/x-icon
Cache-Control: public, max-age=31536000
X-Frame-Options: SAMEORIGIN
Content-Length: 196

Console output (if it somehow could help):

[05/Jun/2019 09:17:42] "GET /7f9fa4.ico HTTP/1.1" 200 196

Also, if I will remove link element from head, browser will make requests to /favicon.ico (which in my case just mirrors /ffffff.ico) each time I reload the page with the same effect.


Solution

  • What you may find is that this request is being made to validate the cached content. I noticed that the request you sent to the server has Cache-Control: no-cache and Pragma: no-cache.

    https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Cacheability

    no-cache Forces caches to submit the request to the origin server for validation before releasing a cached copy.

    So it forces caches to submit the request for validation.

    https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Pragma#Directives

    no-cache Same as Cache-Control: no-cache. Forces caches to submit the request to the origin server for validation before releasing a cached copy.

    These state that the browser would be expected to send a request to your server for "validation" before it uses the cache icon.