Advertisement
Tatantyler

HTTP Caching Layer

Mar 11th, 2014
491
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.75 KB | None | 0 0
  1. local cache = {}
  2.  
  3. if fs.exists("/.http_cache") then
  4.     local stat, err = pcall(fs.delete, "/.http_cache")
  5.     if not stat then
  6.         error("Error clearing \".http_cache\".", 2)
  7.     end
  8. end
  9.  
  10. local stat, err = pcall(fs.makeDir, "/.http_cache")
  11. if not stat then
  12.     error("Error making \".http_cache\".", 2)
  13. end
  14.  
  15. local function makeFileSafe(url)
  16.     local url = string.gsub(url, "http%:%/%/", "")
  17.     url = string.gsub(url, "[%/%\\%?%%%*%:%|%\"%<%>%.% ]", "_")
  18.     return url
  19. end
  20.  
  21. local function basicGet(url, data, cacheTimeout)
  22.     cacheTimeout = cacheTimeout or 300 -- cache lifetime in seconds
  23.     local fileSafeUrl = makeFileSafe(url)
  24.     if not data then -- Don't lookup the cache on POST requests
  25.         -- Cache lookup
  26.         if (cache[fileSafeUrl]) then
  27.             if (cache[fileSafeUrl][1] == url) then
  28.                 if fs.exists(fs.combine("/.http_cache", fileSafeUrl)) and (cache[fileSafeUrl][3] >= (os.clock() - cache[fileSafeUrl][2])) then
  29.                     local stat, ret = pcall(fs.open, fs.combine("/.http_cache", fileSafeUrl), "r")
  30.                     if stat then
  31.                         ret.getResponseCode = function()
  32.                             return cache[fileSafeUrl][4]
  33.                         end
  34.                         return ret
  35.                     end
  36.                 else
  37.                     pcall(fs.delete, fs.combine("/.http_cache", fileSafeUrl))
  38.                     cache[fileSafeUrl] = nil
  39.                 end
  40.             end
  41.         end
  42.     end
  43.    
  44.     -- Network request
  45.     local req = {}
  46.     http.request(url, data)
  47.     while true do
  48.         local e, rUrl, handle = os.pullEvent()
  49.         if (e == "http_success") and (url == rUrl) then
  50.             req = handle
  51.             break
  52.         elseif (e == "http_failure") and (url == rUrl) then
  53.             return
  54.         end
  55.     end
  56.    
  57.     -- Cache writeback
  58.     local rCode = req.getResponseCode()
  59.     local data = req.readAll()
  60.     req.close()
  61.     local localHandle = fs.open(fs.combine("/.http_cache", fileSafeUrl), "w")
  62.     localHandle.write(data)
  63.     localHandle.close()
  64.     cache[fileSafeUrl] = {
  65.         url,
  66.         os.clock(),
  67.         cacheTimeout,
  68.         rCode,
  69.     }
  70.     local h = fs.open(fs.combine("/.http_cache", fileSafeUrl), "r")
  71.     h.getResponseCode = function()
  72.         return cache[fileSafeUrl][4]
  73.     end
  74.     return h
  75. end
  76.  
  77. http.get = function(url, cacheTimeout)
  78.     return basicGet(url, nil, cacheTimeout)
  79. end
  80.  
  81. http.post = function(url, data, cacheTimeout)
  82.     return basicGet(url, data, cacheTimeout)
  83. end
  84.  
  85. http.clearCache = function(url)
  86.     if url then
  87.         if cache[makeFileSafe(url)] then
  88.             cache[makeFileSafe(url)] = nil
  89.         end
  90.         if fs.exists(fs.combine("/.http_cache", makeFileSafe(url))) then
  91.             local stat, err = pcall(fs.delete, fs.combine("/.http_cache", makeFileSafe(url)))
  92.             if not stat then
  93.                 error("Error deleting cache file.", 2)
  94.             end
  95.         end
  96.     else
  97.         if fs.exists("/.http_cache") then
  98.             local stat, err = pcall(fs.delete, "/.http_cache")
  99.             if not stat then
  100.                 error("Error clearing \".http_cache\".", 2)
  101.             end
  102.         end
  103.  
  104.         local stat, err = pcall(fs.makeDir, "/.http_cache")
  105.         if not stat then
  106.             error("Error making \".http_cache\".", 2)
  107.         end
  108.         cache = {}
  109.     end
  110. end
  111.  
  112. http.selectiveClearCache = function() -- Only clear the entries that have timed out
  113.     local l = {}
  114.     for i,v in pairs(cache) do
  115.         if not (v[3] >= (os.clock() - v[2])) then
  116.             pcall(fs.delete, fs.combine("/.http_cache", i))
  117.             table.insert(l, i)
  118.         end
  119.     end
  120.     for i=1, #l do
  121.         cache[l[i]] = nil
  122.     end
  123. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement