Skip to content

Commit f076f7e

Browse files
committed
cache response
Signed-off-by: cyd622 <luffywang622@gmail.com>
1 parent 53554b0 commit f076f7e

File tree

1 file changed

+194
-0
lines changed

1 file changed

+194
-0
lines changed
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
<?php
2+
/**
3+
* Description: 页面缓存中间件
4+
* Project: laravel_api
5+
* Author: Ciel (luffywang622@gmail.com)
6+
* Created on: 2019/04/03 10:53
7+
* Created by PhpStorm.
8+
*/
9+
10+
namespace Cyd622\LaravelApi\Middleware;
11+
12+
use Illuminate\Http\Request;
13+
14+
class CacheResponseMiddleware
15+
{
16+
/**
17+
* the cache tag
18+
*/
19+
const CACHE_TAG = 'PageCache';
20+
21+
/**
22+
* @var \Illuminate\Http\Request
23+
*/
24+
protected $request;
25+
26+
/**
27+
* @var \Closure
28+
*/
29+
protected $next;
30+
31+
/**
32+
* 缓存分钟
33+
*
34+
* @var int|null
35+
*/
36+
protected $minutes;
37+
38+
/**
39+
* 缓存数据
40+
*
41+
* @var array
42+
*/
43+
protected $cacheContent;
44+
45+
/**
46+
* 缓存命中状态,1为命中,0为未命中
47+
*
48+
* @var int
49+
*/
50+
protected $cacheHit = 1;
51+
52+
/**
53+
* 缓存Key
54+
*
55+
* @var string
56+
*/
57+
protected $cacheKey;
58+
59+
/**
60+
* Handle an incoming request
61+
* @param $request
62+
* @param \Closure $next
63+
* @param null $minutes
64+
*
65+
* @return mixed
66+
*/
67+
public function handle(Request $request, \Closure $next, $minutes = null)
68+
{
69+
70+
$this->prepare($request, $next, $minutes);
71+
72+
// skip cache
73+
if ($request->has('skip_cache')) {
74+
return $next($request);
75+
}
76+
77+
// flush cache
78+
if ($request->has('flush_cache')) {
79+
$this->cacheSet()->flush();
80+
return $next($request);
81+
}
82+
83+
// clear current request cache
84+
if ($request->has('clear_cache')) {
85+
$this->cacheSet()->forget($this->cacheKey);
86+
return $next($request);
87+
}
88+
89+
$this->responseCache();
90+
91+
$response = \response()->make($this->cacheContent, 200, $this->getHeaders());
92+
if ($response->isSuccessful() && !$response->headers->has('ETag')) {
93+
$response->setEtag(sha1($response->getContent()));
94+
}
95+
96+
$response->isNotModified(app('request'));
97+
return $response;
98+
}
99+
100+
/**
101+
* resolve value
102+
* @param $request
103+
* @param \Closure $next
104+
* @param null $minutes
105+
*/
106+
protected function prepare($request, \Closure $next, $minutes = null)
107+
{
108+
$this->request = $request;
109+
$this->next = $next;
110+
$this->cacheKey = $this->resolveKey();
111+
$this->minutes = $this->resolveMinutes($minutes);
112+
}
113+
114+
/**
115+
* cache this response content
116+
*/
117+
protected function responseCache()
118+
{
119+
$this->cacheContent = $this->cacheSet()->remember(
120+
$this->cacheKey,
121+
$this->minutes,
122+
function () {
123+
$this->cacheMissed();
124+
125+
/** @var \Illuminate\Http\Response $response */
126+
$response = ($this->next)($this->request);
127+
128+
// json数据是需要解析成数组格式
129+
if ($response instanceof \Illuminate\Http\JsonResponse) {
130+
return $response->getData(true);
131+
}
132+
133+
return $response->getContent();
134+
}
135+
);
136+
}
137+
138+
/**
139+
* @return array
140+
*/
141+
protected function getHeaders()
142+
{
143+
$headers = [
144+
'X-Cache' => $this->cacheHit ? 'Hit from cache' : 'Missed',
145+
'X-Cache-Key' => $this->cacheKey,
146+
'X-Cache-Expires' => now()->addMinutes($this->minutes)->format('Y-m-d H:i:s T'),
147+
];
148+
return $headers;
149+
}
150+
151+
/**
152+
* @return string
153+
*/
154+
protected function resolveKey()
155+
{
156+
$queryKeys = ['skip_cache', 'flush_cache', 'clear_cache'];
157+
$query = $this->request->except($queryKeys);
158+
return md5($this->request->url() . json_encode($query) . $this->request->server('HTTP_X_REQUESTED_WITH'));
159+
}
160+
161+
162+
/**
163+
* @return \Illuminate\Cache\CacheManager|\Illuminate\Cache\TaggedCache|\Illuminate\Foundation\Application|mixed
164+
*/
165+
protected function cacheSet()
166+
{
167+
if (\Cache::getStore() instanceof \Illuminate\Cache\TaggableStore) {
168+
return \Cache::tags(self::CACHE_TAG);
169+
}
170+
$this->cacheKey = self::CACHE_TAG . '.' . $this->cacheKey;
171+
return app('cache');
172+
}
173+
174+
/**
175+
* @param null $minutes
176+
* @return int|mixed
177+
*/
178+
protected function resolveMinutes($minutes = null)
179+
{
180+
return is_null($minutes)
181+
? $this->getDefaultMinutes()
182+
: max($this->getDefaultMinutes(), intval($minutes));
183+
}
184+
185+
protected function getDefaultMinutes()
186+
{
187+
return 10;
188+
}
189+
190+
protected function cacheMissed()
191+
{
192+
$this->cacheHit = 0;
193+
}
194+
}

0 commit comments

Comments
 (0)