diff --git a/include/ajax.config.php b/include/ajax.config.php
index bf4174fe8e6ff53150f8fe77fff541010b4f0e37..938625ff1307f272abb9dff4aae65f1654455235 100644
--- a/include/ajax.config.php
+++ b/include/ajax.config.php
@@ -42,7 +42,10 @@ class ConfigAjaxAPI extends AjaxController {
             'html_thread'     => (bool) $cfg->isHtmlThreadEnabled(),
         );
 
-        return $this->json_encode($config);
+        $config = $this->json_encode($config);
+        Http::cacheable(md5($config), $cfg->lastModified());
+
+        return $config;
     }
 }
 ?>
diff --git a/include/class.config.php b/include/class.config.php
index acd72ca3066f160618fad11970a93d7aa17f1372..e692adb2f04a4c6215f22f89ef08efb272a9f7f7 100644
--- a/include/class.config.php
+++ b/include/class.config.php
@@ -174,6 +174,11 @@ class OsticketConfig extends Config {
         return true;
     }
 
+    function lastModified() {
+        return max(array_map(array('parent', 'lastModified'),
+            array_keys($this->config)));
+    }
+
     function isHelpDeskOffline() {
         return !$this->isOnline();
     }
diff --git a/include/class.file.php b/include/class.file.php
index 8acd7e42949f0c097bcb75d11c35823a224b013c..d3f8393b6be57498183d555130b7b984d88aaaf5 100644
--- a/include/class.file.php
+++ b/include/class.file.php
@@ -136,19 +136,8 @@ class AttachmentFile {
         return true;
     }
 
-    function makeCacheable($ttl=3600) {
-        // Thanks, http://stackoverflow.com/a/1583753/1025836
-        $last_modified = Misc::db2gmtime($this->lastModified());
-        header("Last-Modified: ".date('D, d M y H:i:s', $last_modified)." GMT", false);
-        header('ETag: "'.$this->getHash().'"');
-        header("Cache-Control: private, max-age=$ttl");
-        header('Expires: ' . gmdate(DATE_RFC822, time() + $ttl)." GMT");
-        header('Pragma: private');
-        if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified ||
-            @trim($_SERVER['HTTP_IF_NONE_MATCH']) == $this->getHash()) {
-                header("HTTP/1.1 304 Not Modified");
-                exit();
-        }
+    function makeCacheable($ttl=86400) {
+        Http::cacheable($this->getHash(), $this->lastModified(), $ttl);
     }
 
     function display($scale=false) {
diff --git a/include/class.http.php b/include/class.http.php
index e8d6788cf964c5f257a7a1c2887c6dfa4854d631..3aea32b6e93029e541bf0d0c9fd28bef15b20dc3 100644
--- a/include/class.http.php
+++ b/include/class.http.php
@@ -53,6 +53,21 @@ class Http {
         exit;
     }
 
+    function cacheable($etag, $modified, $ttl=3600) {
+        // Thanks, http://stackoverflow.com/a/1583753/1025836
+        $last_modified = Misc::db2gmtime($modified);
+        header("Last-Modified: ".date('D, d M y H:i:s', $last_modified)." GMT", false);
+        header('ETag: "'.$etag.'"');
+        header("Cache-Control: private, max-age=$ttl");
+        header('Expires: ' . gmdate(DATE_RFC822, time() + $ttl)." GMT");
+        header('Pragma: private');
+        if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified ||
+            @trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) {
+                header("HTTP/1.1 304 Not Modified");
+                exit();
+        }
+    }
+
     function download($filename, $type, $data=null) {
         header('Pragma: public');
         header('Expires: 0');