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