Request 와 Response 객체를 처리하기 위해 Slim 어플리케이션 전후에 특정 코드를 실행하는 것을 미들웨어라고 한다.
csrf 로부터 app 을 보호하거나 app 실행 전에 인증 요청을 하는 것들이 미들웨어이다.
미들웨어의 동작
미들웨어는 아래 그림처럼 Slim 어플리케이션의 중심을 둘러싸는 레이어로써 겹겹이 추가된다.
각 새로운 미들웨어 레이어는 이미 존재하는 미들웨어 레이어를 둘러싼다.
이러한 동심원의 구조로 미들웨어 레이어가 추가되면서 확장된다.
Request 와 Response 객체는 Slim 어플리케이션을 실행하기 위해, 바깥쪽에서 안쪽으로 들어온다.
먼저 가장 바깥의 미들웨어에 진입하고, 그 다음 미들웨어, 또 그 다음 미들웨어, ... 그리고 Slim 어플리케이션에 도달한다.
Slim 어플리케이션이 적절한 라우터를 전달하면, Response 객체는 다시 안쪽에서 바깥쪽으로 미들웨어 레이어를 거치며 나간다.
최종적으로 가장 바깥쪽 미들웨어를 빠져나가 HTTP 응답으로 직렬화된 Response 객체는 클라이언트에 반환된다.
미들웨어 작성법
미들웨어는 세 개의 매개변수를 받는 호출 가능한 것(함수/클래스)이다.
- \Psr\Http\Message\ServerRequestInterface - PSR7 요청 객체
- \Psr\Http\Message\ResponseInterface - PSR7 응답 객체
- callable - 호출 가능한 다음 미들웨어
여기서 중요한 것은 미들웨어가 \Psr\Http\Message\ResponseInterface 의 인스턴스를 반환해야 한다.
각 미들웨어는 다음 미들웨어를 호출하고 매개변수로 Request 와 Response 객체를 전달하는 것이 좋다.
Closure(익명 함수) 미들웨어 예제
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?php /** * Example middleware closure * * @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request * @param \Psr\Http\Message\ResponseInterface $response PSR7 response * @param callable $next Next middleware * * @return \Psr\Http\Message\ResponseInterface */ function ($request, $response, $next) { $response->getBody()->write('BEFORE'); $response = $next($request, $response); $response->getBody()->write('AFTER'); return $response; }; | cs |
호출 가능한 클래스 미들웨어 예제
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <?php class ExampleMiddleware { /** * Example middleware invokable class * * @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request * @param \Psr\Http\Message\ResponseInterface $response PSR7 response * @param callable $next Next middleware * * @return \Psr\Http\Message\ResponseInterface */ public function __invoke($request, $response, $next) { $response->getBody()->write('BEFORE'); $response = $next($request, $response); $response->getBody()->write('AFTER'); return $response; } } $subject->add( new ExampleMiddleware() ); | cs |
이 예제는 매직 __invoke() 메소드를 구현하는 호출 가능한 클래스이다.
미들웨어로 이 클래스를 사용하기 위해, $app, Route, group() 중 하나(예제는 $subject 로 표현)의 다음에 add() 함수로 사용할 수 있다.
미들웨어 추가
우리는 Slim 어플리케이션, 라우터, 라우터 그룹에 미들웨어를 추가할 것이다.
이들은 같은 미들웨어 인터페이스를 적용하고 구현한다.
Application middleware
어플리케이션 미들웨어는 모든 들어오는 HTTP 요청으로부터 호출된다.
Slim 의 app 인스턴스의 add() 메소드로 어플리케이션 미들웨어를 추가하라.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?php $app = new \Slim\App(); $app->add(function ($request, $response, $next) { $response->getBody()->write('BEFORE'); $response = $next($request, $response); $response->getBody()->write('AFTER'); return $response; }); $app->get('/', function ($req, $res, $args) { echo ' Hello '; }); $app->run(); // This would output this HTTP response body: // BEFORE Hello AFTER | cs |
Route middleware
라우트 미들웨어는 라우트가 현재 HTTP 요청 메소드 및 URI와 일치할 때만 호출된다.
라우트 미들웨어는 Slim app 의 라우팅 메소드(get(), post())를 호출한 다음에 바로 지정된다.
각 라우팅 메소드는 \Slim\Route 인스턴스를 반환하고, 이 클래스는 Slim app 인스턴스로써 같은 미들웨어 인터페이스를 제공한다.
Route 인스턴스의 add() 메소드로 라우트에 미들웨어를 추가하라.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?php $app = new \Slim\App(); $mw = function ($request, $response, $next) { $response->getBody()->write('BEFORE'); $response = $next($request, $response); $response->getBody()->write('AFTER'); return $response; }; $app->get('/', function ($req, $res, $args) { echo ' Hello '; })->add($mw); $app->run(); // This would output this HTTP response body: // BEFORE Hello AFTER | cs |
Group Middleware
모든 어플리케이션과 미들웨어를 적용할 수 있는 표준 라우트에 더하여, group() 멀티 라우트 정의 기능 또한 내부적으로 각 라우트를 허용한다.
라우트 그룹 미들웨어는 라우트가 그룹으로부터 정의된 HTTP 요청 메소드 및 URI 중 하나와 일치하면 호출된다.
콜백 내에 미들웨어를 추가하려면 group() 메소드 뒤에 add() 메소드로 설정하라.
다음은 url-핸들러 그룹에 콜백 미들웨어를 사용하는 예제이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <?php require_once __DIR__.'/vendor/autoload.php'; $app = new \Slim\App(); $app->get('/', function ($request, $response) { return $response->getBody()->write('Hello World'); }); $app->group('/utils', function () use ($app) { $app->get('/date', function ($request, $response) { return $response->getBody()->write(date('Y-m-d H:i:s')); }); $app->get('/time', function ($request, $response) { return $response->getBody()->write(time()); }); })->add(function ($request, $response, $next) { $response->getBody()->write('It is now '); $response = $next($request, $response); $response->getBody()->write('. Enjoy!'); return $response; }); // When calling the /utils/date method, output: // It is now 2015-07-06 03:11:01. Enjoy! // visiting /utils/time, output: // It is now 1436148762. Enjoy! // but visiting / (domain-root), no middleware has been assigned, output: // Hello World | cs |
WRITTEN BY
- 손가락귀신
정신 못차리면, 벌 받는다.