Slim Framework 매뉴얼 컨셉 미들웨어

미들웨어

Slim 애플리케이션 코드를 실행하여 요청 및 응답 개체를 원하는 대로 조작할 수 있습니다. 이것을 미들웨어라고 합니다. 왜 이런 일을 하고 싶어하죠? 아마도 당신은 사이트 간 요청 위조로부터 당신의 앱을 보호하기를 원할 것이다. 앱을 실행하기 전에 요청을 인증해야 할 수도 있습니다. 미들웨어는 이러한 시나리오에 적합합니다.

미들웨어란 무엇인가?

미들웨어는 PSR-15 미들웨어 인터페이스를 구현합니다.

  1. Psr\Http\Message\ServerRequestInterface – PSR-7 요청 개체
  2. Psr\Http\Server\RequestHandlerInterface – PSR-15 요청 핸들러 개체

이것은 이 객체들에 적합한 모든 것을 할 수 있습니다. 유일한 하드 요구 사항은 미들웨어는 Psr\Http\Message\ResponseInterface 를 반환해야 한다 (MUST) .각 미들웨어는 다음 미들웨어를 호출하여 요청 개체를 인수로 전달합니다.(SHOULD)

미들웨어는 어떻게 작동합니까?

프레임워크마다 미들웨어를 다르게 사용합니다. Slim은 핵심 애플리케이션을 둘러싸고 있는 동심 계층으로 미들웨어를 추가합니다. 각각의 새로운 미들웨어 레이어는 기존의 미들웨어 레이어를 둘러싸고 있습니다. 미들웨어 층이 추가되면서 동심원 구조가 바깥으로 확장됩니다.

마지막으로 추가된 미들웨어 계층이 가장 먼저 실행됩니다.

Slim 애플리케이션을 실행하면 요청 개체가 미들웨어 구조를 외부에서 통과합니다. 먼저 가장 바깥쪽의 미들웨어로 들어간 다음, 가장 바깥쪽의 미들웨어로 들어가야 Slim 애플리케이션 자체에 도달할 수 있습니다. Slim 응용프로그램이 적절한 경로를 발송한 후 결과 Response 오브젝트는 Slim 응용프로그램을 종료하고 미들웨어 구조를 내부에서 아래로 통과시킵니다. 궁극적으로 최종 응답 오브젝트는 가장 바깥쪽 미들웨어를 종료하고 원시 HTTP 응답으로 직렬화되며 HTTP 클라이언트로 반환된다. 미들웨어 프로세스 흐름을 보여주는 다이어그램은 다음과 같습니다.

Middleware architecture

미들웨어는 어떻게 쓰나요?

미들웨어는 Request 개체와 RequestHandler 개체의 두 가지 인수를 허용하는 호출식입니다. 각 미들웨어는 Psr\Http\Message\ResponseInterface 인스턴스를 반환 해야한다.(MUST)

클로저 미들웨어 예

이 미들웨어 예는 클로저입니다.

<?php
  
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Factory\AppFactory;
use Slim\Psr7\Response;
​
require __DIR__ . '/../vendor/autoload.php';
​
$app = AppFactory::create();
​
/**
 * Example middleware closure
 *
 * @param  ServerRequest  $request PSR-7 request
 * @param  RequestHandler $handler PSR-15 request handler
 *
 * @return Response
 */
$beforeMiddleware = function (Request $request, RequestHandler $handler) {
    $response = $handler->handle($request);
    $existingContent = (string) $response->getBody();
​
    $response = new Response();
    $response->getBody()->write('BEFORE' . $existingContent);
​
    return $response;
};
​
$afterMiddleware = function ($request, $handler) {
    $response = $handler->handle($request);
    $response->getBody()->write('AFTER');
    return $response;
};
​
$app->add($beforeMiddleware);
$app->add($afterMiddleware);
​
// ...
​
$app->run();

Invokable 클래스 미들웨어 예

이 예제 미들웨어는 호출할 수 없는 마법 메소드인 ‘__invoke()’ 방법을 이용해 구현하는 클래스입니다.

<?php

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Psr7\Response;
​
class ExampleBeforeMiddleware
{
    /**
     * Example middleware invokable class
     *
     * @param  ServerRequest  $request PSR-7 request
     * @param  RequestHandler $handler PSR-15 request handler
     *
     * @return Response
     */
    public function __invoke(Request $request, RequestHandler $handler): Response
    {
        $response = $handler->handle($request);
        $existingContent = (string) $response->getBody();
    
        $response = new Response();
        $response->getBody()->write('BEFORE' . $existingContent);
    
        return $response;
    }
}
<?php
  
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
​
class ExampleAfterMiddleware
{
    /**
     * Example middleware invokable class
     *
     * @param  ServerRequest  $request PSR-7 request
     * @param  RequestHandler $handler PSR-15 request handler
     *
     * @return Response
     */
    public function __invoke(Request $request, RequestHandler $handler): Response
    {
        $response = $handler->handle($request);
        $response->getBody()->write('AFTER');
        return $response;
    }
}

이러한 클래스를 미들웨어로 사용하려면 아래 코드에 설명된 대로 add(new ExampleMiddleware()); 를 사용하거나 $app 뒤에 경로 매핑 메서드 get(), post(), put(), patch(), delete(), option(), any() 또는 group() 에 함수 체인을 사용하면 됩니다.

<?php
  
use Slim\Factory\AppFactory;
​
require __DIR__ . '/../vendor/autoload.php';
​
$app = AppFactory::create();
​
// Add Middleware On App
$app->add(new ExampleMiddleware());
​
// Add Middleware On Route
$app->get('/', function () { ... })->add(new ExampleMiddleware());
​
// Add Middleware On Group
$app->group('/', function () { ... })->add(new ExampleMiddleware());
​
// ...
​
$app->run();

미들웨어를 추가하려면 어떻게 해야 하나요?

Slim 프로그램, 개별 Slim 프로그램 경로 또는 경로 그룹에 미들웨어를 추가할 수 있습니다. 모든 시나리오는 동일한 미들웨어를 수용하고 동일한 미들웨어 인터페이스를 구현합니다.

응용 프로그램 미들웨어

모든 수신 HTTP 요청에 대해 응용 프로그램 미들웨어가 호출됩니다. Slim 애플리케이션 인스턴스의 add() 메서드를 사용하여 애플리케이션 미들웨어를 추가합니다. 이 예는 위의 Closure 미들웨어 예를 추가합니다.

<?php
  
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Factory\AppFactory;
use Slim\Psr7\Response;
​
require __DIR__ . '/../vendor/autoload.php';
​
$app = AppFactory::create();
​
$app->add(function (Request $request, RequestHandler $handler) {
    $response = $handler->handle($request);
    $existingContent = (string) $response->getBody();
​
    $response = new Response();
    $response->getBody()->write('BEFORE ' . $existingContent);
​
    return $response;
});
​
$app->add(function (Request $request, RequestHandler $handler) {
    $response = $handler->handle($request);
    $response->getBody()->write(' AFTER');
    return $response;
});
​
$app->get('/', function (Request $request, Response $response, $args) {
    $response->getBody()->write('Hello World');
    return $response;
});
​
$app->run();

그러면 다음과 같은 HTTP 응답 본문이 출력됩니다.

BEFORE Hello World AFTER

경로 미들웨어 (Route middleware)

경로 미들웨어(Route middleware)는 해당 경로가 현재 HTTP 요청 메서드 및 URI와 일치하는 경우에만 호출됩니다. 경로 미들웨어는 Slim 응용 프로그램의 라우팅 메서드(예: get() 또는 post())를 호출한 후 즉시 지정됩니다. 각 라우팅 메서드는 \Slim\Route 인스턴스를 반환합니다. 이 클래스는 Slim 응용 프로그램 인스턴스와 동일한 미들웨어 인터페이스를 제공합니다. 경로 인스턴스의 add() 메서드를 사용하여 경로에 미들웨어를 추가합니다. 이 예는 위의 Closure 미들웨어 예를 추가합니다.

<?php
  
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Factory\AppFactory;
​
require __DIR__ . '/../vendor/autoload.php';
​
$app = AppFactory::create();
​
$mw = function (Request $request, RequestHandler $handler) {
    $response = $handler->handle($request);
    $response->getBody()->write('World');
​
    return $response;
};
​
$app->get('/', function (Request $request, Response $response, $args) {
    $response->getBody()->write('Hello ');
​
    return $response;
})->add($mw);
​
$app->run();

그러면 다음과 같은 HTTP 응답 본문이 출력됩니다.

Hello World

그룹 미들웨어

전반적인 응용프로그램과 미들웨어를 수용할 수 있는 표준 경로 외에도 group() 다중 경로 정의 기능은 내부적으로 개별 경로를 허용합니다. 라우트 그룹 미들웨어가 호출됩니다* 라우트가 그룹의 정의된 HTTP 요청 메서드 및 URI 중 하나와 일치하는 경우에만 호출됩니다. 콜백 내에 미들웨어를 추가하고 group() 메서드 뒤에 add() 체인을 연결하여 전체 그룹 미들웨어를 설정하려면 다음과 같이 하십시오.

샘플 응용 프로그램, URL 핸들러 그룹에서 콜백 미들웨어 사용

<?php
  
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Factory\AppFactory;
use Slim\Routing\RouteCollectorProxy;
​
require __DIR__ . '/../vendor/autoload.php';
​
$app = AppFactory::create();
​
$app->get('/', function (Request $request, Response $response) {
    $response->getBody()->write('Hello World');
    return $response;
});
​
$app->group('/utils', function (RouteCollectorProxy $group) {
    $group->get('/date', function (Request $request, Response $response) {
        $response->getBody()->write(date('Y-m-d H:i:s'));
        return $response;
    });
    
    $group->get('/time', function (Request $request, Response $response) {
        $response->getBody()->write((string)time());
        return $response;
    });
})->add(function (Request $request, RequestHandler $handler) use ($app) {
    $response = $handler->handle($request);
    $dateOrTime = (string) $response->getBody();
​
    $response = $app->getResponseFactory()->createResponse();
    $response->getBody()->write('It is now ' . $dateOrTime . '. Enjoy!');
​
    return $response;
});
​
$app->run();

/utils/date 메서드를 호출할 때 아래와 유사한 문자열을 출력합니다.

It is now 2015-07-06 03:11:01. Enjoy!

/utils/time를 방문하면 아래와 유사한 문자열을 출력합니다.

It is now 1436148762. Enjoy!

그러나 미들웨어가 할당되지 않았기 때문에 */ (도메인-루트)를 방문하면 다음 출력이 생성될 것으로 예상됩니다.

Hello World

미들웨어에서 변수 전달

미들웨어에서 속성을 전달하는 가장 쉬운 방법은 요청의 속성을 사용하는 것입니다.

미들웨어에서 변수 설정:

$request = $request->withAttribute('foo', 'bar');

경로 콜백의 변수 가져오기:

$foo = $request->getAttribute('foo');

사용 가능한 미들웨어 찾기

당신의 필요를 충족시킬 수 있는 PSR-15 미들웨어 클래스가 이미 작성되어 있을 것입니다. 검색해야 할 비공식 목록이 몇 가지 있습니다.