HTTP Caching for Web Applications - Practical Examples of Cache Headers

The last tutorial HTTP Caching for Web Applications - Cache Headers Explained was mainly focussed on the theoretical aspects of HTTP caching. This tutorial explains caching through some examples where HTTP requests are passed between the browser and the server.

Example 1 : Content is Cached for 2 Hours

  1. Request made at time = 0 seconds

    This is the first request that the browser makes to the server. Server sends the response specifying cache time of 2 hours, also sends an ETag. Browser saves the content to its cache and saves the ETag somewhere.

    Browser request :

    GET /test.php HTTP/1.1
    Host: www.site.com
    

    Server response :

    HTTP/1.1 200 OK
    Cache-Control: max-age=7200
    ETag: "11111-11111"
    
    [HTML-CONTENT-1]
    
  2. Request made again at time = 1 hr

    Since the content is cached, and the cached copy is fresh, content is loaded from the cache without making a request to the server.

  3. Request made again at time = 2 hours, 15 min

    At this time the cache has expired. The browser validates content from the server. Note that the cache is not deleted as of now. The server informs the browser that content has not been modified. The browser extends the expiry time of the cache by 2 hours from now, and serves content from the cache.

    Browser request :

    GET /test.php HTTP/1.1
    Host: www.site.com
    If-None-Match: "11111-11111"
    

    Note that the browser passes a If-None-Match request header with the same value as the last ETag header.

    Server response :

    HTTP/1.1 304 Not Modified
    Cache-Control: max-age=7200
    ETag: "11111-11111"
    

    Note that server sends only HTTP headers and does not send the full response — it makes the process much more efficient. The browser reads the 304 HTTP response code and comes to know that content has not changed.

  4. Request made again at time = 3 hours

    The content is still cached, and is fresh. So content is loaded from the cache without making a request to the server again.

  5. Request made again at time = 5 hours

    The cache has again expired by this time. The browser validates content from the server. (The cache is not deleted as of now). The server informs the browser that content has been changed now - it sends the new response and a new ETag. The browser now deletes the old cache, and adds the new content to its cache. The expiry time of the cached copy is 2 hours from now.

    Browser request :

    GET /test.php HTTP/1.1
    Host: www.site.com
    If-None-Match: "11111-11111"
    

    Server response :

    HTTP/1.1 200 OK
    Cache-Control: max-age=7200
    ETag: "22222-22222"
    
    [HTML-CONTENT-2]
    

    Note that server sends a new response and a new ETag.

  6. Request made again at time = 6 hours

    Content is loaded from the cache.

Example 2 : Content is Cached for 2 Hours. but Re-validated Each Time

  1. Request made at time = 0 seconds

    This is the first request that the browser makes to the server. Server sends the response specifying cache time of 2 hours and re-validation flag, and also sends an ETag. Browser saves the content to its cache and saves the ETag somewhere.

    Browser request :

    GET /test.php HTTP/1.1
    Host: www.site.com
    

    Server response :

    HTTP/1.1 200 OK
    Cache-Control: max-age=7200, must-revalidate
    ETag: "11111-11111"
    
    [HTML-CONTENT-1]
    
  2. Request made again at time = 1 hr

    The content is cached, and is fresh. Yet the browser has to re-validate content from the server whether it has changed. The server informs the browser that content has not changed. The browser now loads content from its cache.

    Browser request :

    GET /test.php HTTP/1.1
    Host: www.site.com
    If-None-Match: "11111-11111"
    

    The browser passes a If-None-Match request header with the same value as the last ETag header.

    Server response :

    HTTP/1.1 304 Not Modified
    Cache-Control: max-age=7200, must-revalidate
    ETag: "11111-11111"
    
  3. Request made again at time = 2 hours, 15 min

    The cached copy has expired. Browser does not delete the cached copy, and validates content from the server. The server now responds that content has changed and sends the fresh content, with a new ETag. The browser replaces the cache, and the ETag, and then shows the new content to the user.

    Browser request :

    GET /test.php HTTP/1.1
    Host: www.site.com
    If-None-Match: "11111-11111"
    

    The browser passes a If-None-Match request header with the same value as the last ETag header.

    Server response :

    HTTP/1.1 200 OK
    Cache-Control: max-age=7200, must-revalidate
    ETag: "22222-22222"
    
    [HTML-CONTENT-2]
    

    Note that server sends a new response and a new ETag.

  4. Request made again at time = 3 hours

    The content is still cached, and is fresh. But the cache has been set to re-validation (through the previous Cache-Control header). The browser again validates content from the server. The content on the server has changed, and a new response and a new ETag is sent. The cache and ETag both are replaced and new content is shown to user.

    Browser request :

    GET /test.php HTTP/1.1
    Host: www.site.com
    If-None-Match: "22222-22222"
    

    Server response :

    HTTP/1.1 200 OK
    Cache-Control: max-age=7200, must-revalidate
    ETag: "33333-33333"
    
    [HTML-CONTENT-3]
    
  5. Request made again at time = 6 hours

    Browser makes a re-validation request. The server once again sends a fresh response. The user once again sees the new content.

    Browser request :

    GET /test.php HTTP/1.1
    Host: www.site.com
    If-None-Match: "33333-33333"
    

    Server response :

    HTTP/1.1 200 OK
    Cache-Control: max-age=7200, must-revalidate
    ETag: "44444-44444"
    
    [HTML-CONTENT-4]
    

Example 3 : Server Disallows Caching

  1. Request made at time = 0 seconds

    This is the first request that the browser makes to the server. Server sends the response specifying content should not be cached. Browser does not save the content to its cache. Response is shown to the user.

    Browser request :

    GET /test.php HTTP/1.1
    Host: www.site.com
    

    Server response :

    HTTP/1.1 200 OK
    Cache-Control: no-store
    
    [HTML-CONTENT-1]
    
  2. Request made again at time = 1 hr

    Content from the server has changed. Browser does not save content to cache. Response downloaded from the server is shown to the user.

    Browser request :

    GET /test.php HTTP/1.1
    Host: www.site.com
    

    Server response :

    HTTP/1.1 200 OK
    Cache-Control: no-store
    
    [HTML-CONTENT-2]
    
  3. Request made again at time = 2 hours, 15 min

    Content from the server has changed once again. Browser does not save content to cache. Response downloaded from the server is shown to the user.

    Browser request :

    GET /test.php HTTP/1.1
    Host: www.site.com
    

    Server response :

    HTTP/1.1 200 OK
    Cache-Control: no-store
    
    [HTML-CONTENT-3]
    
  4. Request made again at time = 3 hours

    Content from the server has not changed since the last response, yet it still sends the full response. Browser does not save content to cache. Response downloaded from the server is shown to the user.

    Browser request :

    GET /test.php HTTP/1.1
    Host: www.site.com
    

    Server response :

    HTTP/1.1 200 OK
    Cache-Control: no-store
    
    [HTML-CONTENT-3]
    
  5. Request made again at time = 6 hours

    Content from the server has not changed since the last response, yet it still sends the full response. Browser does not save content to cache. Response downloaded from the server is shown to the user.

    Browser request :

    GET /test.php HTTP/1.1
    Host: www.site.com
    

    Server response :

    HTTP/1.1 200 OK
    Cache-Control: no-store
    
    [HTML-CONTENT-3]
    

Conclusion

HTTP caching can be achieved by sending Cache-Control and ETag headers from the server or server-side script. From the browser side you don't need to do anything — everything is handled by the browser internally.

Sending the Cache-Control header is direct, however some logic is required to send a unique ETag for a unique content. The next tutorial will discuss a method through which you can create ETags using PHP.