Class: Async::HTTP::Cache::General

Inherits:
Protocol::HTTP::Middleware
  • Object
show all
Defined in:
lib/async/http/cache/general.rb

Constant Summary collapse

CACHE_CONTROL =
'cache-control'
CONTENT_TYPE =
'content-type'
AUTHORIZATION =
'authorization'
'cookie'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, store: Store.default) ⇒ General

Returns a new instance of General.



39
40
41
42
43
44
45
# File 'lib/async/http/cache/general.rb', line 39

def initialize(app, store: Store.default)
  super(app)
  
  @count = 0
  
  @store = store
end

Instance Attribute Details

#countObject (readonly)

Returns the value of attribute count.



47
48
49
# File 'lib/async/http/cache/general.rb', line 47

def count
  @count
end

#storeObject (readonly)

Returns the value of attribute store.



48
49
50
# File 'lib/async/http/cache/general.rb', line 48

def store
  @store
end

Instance Method Details

#cacheable?(request) ⇒ Boolean

Returns:

  • (Boolean)


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
# File 'lib/async/http/cache/general.rb', line 62

def cacheable?(request)
  # We don't support caching requests which have a body:
  if request.body
    return false
  end
  
  # We can't cache upgraded requests:
  if request.protocol
    return false
  end
  
  # We only support caching GET and HEAD requests:
  unless request.method == 'GET' || request.method == 'HEAD'
    return false
  end
  
  if request.headers[AUTHORIZATION]
    return false
  end
  
  if request.headers[COOKIE]
    return false
  end
  
  # Otherwise, we can cache it:
  return true
end

#call(request) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/async/http/cache/general.rb', line 109

def call(request)
  key = self.key(request)
  
  cache_control = request.headers[CACHE_CONTROL]
  
  unless cache_control&.no_cache?
    if response = @store.lookup(key, request)
      Async.logger.debug(self) {"Cache hit for #{key}..."}
      @count += 1
      
      # Return the cached response:
      return response
    end
  end
  
  unless cache_control&.no_store?
    if cacheable?(request)
      return wrap(key, request, super)
    end
  end
  
  return super
end

#closeObject



50
51
52
53
54
# File 'lib/async/http/cache/general.rb', line 50

def close
  @store.close
ensure
  super
end

#key(request) ⇒ Object



56
57
58
59
60
# File 'lib/async/http/cache/general.rb', line 56

def key(request)
  @store.normalize(request)
  
  [request.authority, request.method, request.path]
end

#wrap(key, request, response) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/async/http/cache/general.rb', line 90

def wrap(key, request, response)
  if response.status != 200
    return response
  end
  
  if request.head? and body = response.body
    unless body.empty?
      Async.logger.warn(self) {"HEAD request resulted in non-empty body!"}
      
      return response
    end
  end
  
  return Body.wrap(response) do |response, body|
    Async.logger.debug(self) {"Updating cache for #{key}..."}
    @store.insert(key, request, Response.new(response, body))
  end
end