├── .gitignore
├── .php_cs
├── LICENSE
├── README.md
├── _config.yml
├── composer.json
├── renovate.json
└── src
└── Middleware
└── CacheResponse.php
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor
2 | /*.cache
3 |
--------------------------------------------------------------------------------
/.php_cs:
--------------------------------------------------------------------------------
1 | setRiskyAllowed(true)
5 | ->setRules(array(
6 | '@Symfony' => true,
7 | 'array_syntax' => array('syntax' => 'short'),
8 | 'ordered_imports' => true,
9 | 'no_useless_else' => true,
10 | 'no_useless_return' => true,
11 | 'php_unit_construct' => true,
12 | 'php_unit_strict' => true,
13 | 'yoda_style' => false,
14 | 'phpdoc_summary' => false,
15 | ))
16 | ->setFinder(
17 | PhpCsFixer\Finder::create()
18 | ->exclude('vendor')
19 | ->in(__DIR__)
20 | )
21 | ;
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 叶子坑(http://flc.ren | http://flc.io)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Laravel中间件-Response缓存
2 |
3 | [](https://packagist.org/packages/flc/laravel-middleware-cache-response)
4 | [](https://packagist.org/packages/flc/laravel-middleware-cache-response)
5 | [](https://packagist.org/packages/flc/laravel-middleware-cache-response)
6 | [](https://996.icu)
7 | [](https://github.com/996icu/996.ICU/blob/master/LICENSE)
8 |
9 | ## 功能
10 |
11 | - 支持缓存渲染后数据
12 | - 支持指定缓存过期时间(默认10分钟)
13 | - header头输出缓存命中状态、缓存Key及过期时间
14 |
15 | ## 安装
16 |
17 | ```sh
18 | composer require flc/laravel-middleware-cache-response
19 | ```
20 |
21 | ## 配置
22 |
23 | > `\app\Http\Kernel.php`文件中`$routeMiddleware`增加:
24 |
25 | ```php
26 | \Flc\Laravel\Http\Middleware\CacheResponse::class,
28 |
29 | // cache.response 命名随意,你开心就好
30 | ```
31 |
32 | ## 使用
33 |
34 | ```php
35 | middleware('cache.response');
39 |
40 | Route::get('/', function () {
41 | return view('welcome');
42 | })->middleware('cache.response:20'); // 指定缓存时间20分钟
43 | ```
44 |
45 | ## 附录
46 |
47 | **缓存规则**
48 |
49 | - 当前URL全路径md5
50 |
51 | **Headers**
52 |
53 | ```
54 | X-Cache:Missed
55 | X-Cache-Expires:2018-03-29 15:08:29 CST
56 | X-Cache-Key:6c9b19774e2c304a42d200f314d8c80b
57 | ```
58 |
59 | ## TODO
60 |
61 | - 增加`status`、`header`的支持
62 |
63 |
64 | ## 捐赠
65 |
66 | 如果你觉得本扩展对你有帮助,请捐赠以表支持,谢谢~~
67 |
68 |
69 |
70 |  微信 |
71 |  支付宝 |
72 |
73 |
74 |
75 | ## License
76 |
77 | - MIT
78 | - Anti 996
79 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "flc/laravel-middleware-cache-response",
3 | "description": "Laravel中间件-Response缓存",
4 | "keywords": ["laravel", "flc", "middleware", "cache", "response", "中间件", "缓存"],
5 | "type": "library",
6 | "license": "MIT",
7 | "require": {
8 | "php": ">=5.4.0"
9 | },
10 | "autoload": {
11 | "psr-4": {
12 | "Flc\\Laravel\\Http\\": "src/"
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "config:recommended"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/src/Middleware/CacheResponse.php:
--------------------------------------------------------------------------------
1 |
15 | *
16 | * @see http://flc.ren | http://flc.io
17 | */
18 | class CacheResponse
19 | {
20 | /**
21 | * @var \Illuminate\Http\Request
22 | */
23 | protected $request;
24 |
25 | /**
26 | * @var \Closure
27 | */
28 | protected $next;
29 |
30 | /**
31 | * 缓存分钟
32 | *
33 | * @var int|null
34 | */
35 | protected $minutes;
36 |
37 | /**
38 | * 缓存数据
39 | *
40 | * @var array
41 | */
42 | protected $responseCache;
43 |
44 | /**
45 | * 缓存命中状态,1为命中,0为未命中
46 | *
47 | * @var int
48 | */
49 | protected $cacheHit = 1;
50 |
51 | /**
52 | * 缓存Key
53 | *
54 | * @var string
55 | */
56 | protected $cacheKey;
57 |
58 | /**
59 | * Handle an incoming request
60 | *
61 | * @param \Illuminate\Http\Request $request
62 | * @param \Closure $next
63 | * @param int|null $minutes
64 | *
65 | * @return mixed
66 | */
67 | public function handle($request, Closure $next, $minutes = null)
68 | {
69 | $this->prepare($request, $next, $minutes);
70 |
71 | $this->responseCache();
72 |
73 | $response = response($this->responseCache['content']);
74 |
75 | return $this->addHeaders($response);
76 | }
77 |
78 | /**
79 | * 预备
80 | *
81 | * @return mixed
82 | */
83 | protected function prepare($request, Closure $next, $minutes = null)
84 | {
85 | $this->request = $request;
86 | $this->next = $next;
87 |
88 | // 初始化值
89 | $this->cacheKey = $this->resolveKey();
90 | $this->minutes = $this->resolveMinutes($minutes);
91 | }
92 |
93 | /**
94 | * 生成或读取Response-Cache
95 | *
96 | * @return array
97 | */
98 | protected function responseCache()
99 | {
100 | $this->responseCache = Cache::remember(
101 | $this->cacheKey,
102 | $this->minutes,
103 | function () {
104 | $this->cacheMissed();
105 |
106 | $response = ($this->next)($this->request);
107 |
108 | return $this->resolveResponseCache($response) + [
109 | 'cacheExpireAt' => Carbon::now()->addMinutes($this->minutes)->format('Y-m-d H:i:s T'),
110 | ];
111 | }
112 | );
113 |
114 | return $this->responseCache;
115 | }
116 |
117 | /**
118 | * 确定需要缓存Response的数据
119 | *
120 | * @param \Illuminate\Http\Response $response
121 | *
122 | * @return array
123 | */
124 | protected function resolveResponseCache($response)
125 | {
126 | return [
127 | 'content' => $response->getContent(),
128 | ];
129 | }
130 |
131 | /**
132 | * 追加Headers
133 | *
134 | * @param mixed
135 | */
136 | protected function addHeaders($response)
137 | {
138 | $response->headers->add(
139 | $this->getHeaders()
140 | );
141 |
142 | return $response;
143 | }
144 |
145 | /**
146 | * 返回Headers
147 | *
148 | * @return array
149 | */
150 | protected function getHeaders()
151 | {
152 | $headers = [
153 | 'X-Cache' => $this->cacheHit ? 'Hit from cache' : 'Missed',
154 | 'X-Cache-Key' => $this->cacheKey,
155 | 'X-Cache-Expires' => $this->responseCache['cacheExpireAt'],
156 | ];
157 |
158 | return $headers;
159 | }
160 |
161 | /**
162 | * 根据请求获取指定的Key
163 | *
164 | * @return string
165 | */
166 | protected function resolveKey()
167 | {
168 | return md5($this->request->fullUrl());
169 | }
170 |
171 | /**
172 | * 获取缓存的分钟
173 | *
174 | * @param int|null $minutes
175 | *
176 | * @return int
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 | /**
186 | * 返回默认的缓存时间(分钟)
187 | *
188 | * @return int
189 | */
190 | protected function getDefaultMinutes()
191 | {
192 | return 10;
193 | }
194 |
195 | /**
196 | * 缓存未命中
197 | *
198 | * @return mixed
199 | */
200 | protected function cacheMissed()
201 | {
202 | $this->cacheHit = 0;
203 | }
204 | }
205 |
--------------------------------------------------------------------------------