Class: Joggle::Pablotron::Cache

Inherits:
Object
  • Object
show all
Includes:
Observable
Defined in:
lib/joggle/pablotron/cache.rb

Constant Summary collapse

DEFAULTS =
{
  'user-agent' => "Pablotron-Cacher/0.0.0",
}
HEADER_DELIM =

delimiter for appending header string to url (chosen because it won’t appear in a valid url)

'://?&#'

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Observable

#fire, #on, #un

Constructor Details

#initialize(cache_store, extra_headers = nil) ⇒ Cache



15
16
17
18
# File 'lib/joggle/pablotron/cache.rb', line 15

def initialize(cache_store, extra_headers = nil)
  @extras = extra_headers
  @store = cache_store
end

Class Method Details

.urlify(base, args = nil, hash = nil) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/joggle/pablotron/cache.rb', line 20

def self.urlify(base, args = nil, hash = nil)
  ret = base

  if args && args.size > 0
    ret = base + '?' + args.map { |k, v| 
      [k, v].map { |s| CGI.escape(s.to_s) }.join('=') 
    }.join('&')
  end

  if hash
    ret << '#' + hash
  end
  
  # return result
  ret
end

Instance Method Details

#delete(url, headers = nil) ⇒ Object



111
112
113
114
# File 'lib/joggle/pablotron/cache.rb', line 111

def delete(url, headers = nil)
  key = url_key(url, headers)
  @store.delete_cached(key)
end

#get(url, headers = nil) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/joggle/pablotron/cache.rb', line 58

def get(url, headers = nil)
  ret = nil

  # create store key
  key = url_key(url, headers)

  # build headers
  opt = expand_headers(headers)

  # if we have an existing cache entry for this url,
  # then use the last-modified and etag headers
  if entry = @store.get_cached(key)
    opt.update({
      'if-modified-since' => entry['last'].to_s,
      'if-none-match'     => entry['etag'],
    })
  end

  # fetch url and handle result
  begin 
    open(url, opt) do |fh|
      ret  = fh.read

      # update store
      @store.add_cached(key, {
        'last'  => fh.last_modified.to_s || fh.meta['date'],
        'etag'  => fh.meta['etag'],
        'data'  => ret.to_s.dup,
      })

      fire('cache_updated', url, ret)
    end
  rescue OpenURI::HTTPError => err
    case err.io.status.first
    when  /^304/
      # not modified
      ret = entry['data'] 
      fire('cache_not_modified', url)
    else
      # unknown status code
      fire('cache_http_error', url, err.io.status.first, err.io.status.last)
    end
  end

  # return result
  ret
end

#has?(url, headers = nil) ⇒ Boolean



106
107
108
109
# File 'lib/joggle/pablotron/cache.rb', line 106

def has?(url, headers = nil)
  key = url_key(url, headers)
  @store.has_cached?(key)
end

#url_key(url, headers = nil) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/joggle/pablotron/cache.rb', line 41

def url_key(url, headers = nil)
  ret = url

  # append header fragment
  if headers && headers.size > 0
    # sort, concatenate, and append headers to url
    ret += HEADER_DELIM + headers.keys.map { |key| 
      key.downcase 
    }.sort.map { |k| 
      "#{k}:#{headers[k]}" 
    }.join(',')
  end

  # return results
  ret
end