diff --git a/api/filters/NginxCache.php b/api/filters/NginxCache.php new file mode 100644 index 0000000..21669e1 --- /dev/null +++ b/api/filters/NginxCache.php @@ -0,0 +1,35 @@ + сколько кэшировать. + * + * Период можно задавать 2-умя путями: + * - если значение начинается с префикса @, оно задаёт абсолютное время в unix timestamp, + * до которого ответ может быть закэширован. + * - в ином случае значение интерпретируется как количество секунд, на которое необходимо + * закэшировать ответ + */ + public $rules; + + public function afterAction($action, $result) { + $rule = $this->rules[$action->id] ?? null; + if ($rule !== null) { + if (is_callable($rule)) { + $cacheTime = $rule($action); + } else { + $cacheTime = $rule; + } + + Yii::$app->response->headers->set('X-Accel-Expires', $cacheTime); + } + + return parent::afterAction($action, $result); + } + +} diff --git a/tests/codeception/api/unit/filters/NginxCacheTest.php b/tests/codeception/api/unit/filters/NginxCacheTest.php new file mode 100644 index 0000000..01f982d --- /dev/null +++ b/tests/codeception/api/unit/filters/NginxCacheTest.php @@ -0,0 +1,57 @@ +testAfterActionInternal(3600, 3600); + $this->testAfterActionInternal('@' . (time() + 30), '@' . (time() + 30)); + $this->testAfterActionInternal(function() { + return 3000; + }, 3000); + } + + private function testAfterActionInternal($ruleConfig, $expected) { + /** @var HeaderCollection|\PHPUnit_Framework_MockObject_MockObject $headers */ + $headers = $this->getMockBuilder(HeaderCollection::class) + ->setMethods(['set']) + ->getMock(); + + $headers->expects($this->once()) + ->method('set') + ->with('X-Accel-Expires', $expected); + + /** @var Request|\PHPUnit_Framework_MockObject_MockObject $request */ + $request = $this->getMockBuilder(Request::class) + ->setMethods(['getHeaders']) + ->getMock(); + + $request->expects($this->any()) + ->method('getHeaders') + ->willReturn($headers); + + Yii::$app->set('response', $request); + + /** @var Controller|\PHPUnit_Framework_MockObject_MockObject $controller */ + $controller = $this->getMockBuilder(Controller::class) + ->setConstructorArgs(['mock', Yii::$app]) + ->getMock(); + + $component = new NginxCache([ + 'rules' => [ + 'index' => $ruleConfig, + ], + ]); + + $component->afterAction(new Action('index', $controller), ''); + } + +}