• 声明一个中间件
  • 定义中间件
    • 使用
    • 配置全局中间件
    • 通过注解使用
  • 应用
    • 提前拦截请求
    • 跨域设置
    • 用户JWT登陆验证

    声明一个中间件

    中间件是用于控制 请求到达 和 响应请求 的整个流程的,通常用于对请求进行过滤验证处理,当你需要对请求或响应作出对应的修改或处理,或想调整请求处理的流程时均可以使用中间件来实现。

    定义中间件

    只需要实现了 Swoft\Http\Server\Contract\MiddlewareInterface 接口均为一个合法的中间件,其中 process() 方法为该中间件逻辑处理方法。

    1. namespace App\Http\Middleware;
    2. use Psr\Http\Message\ResponseInterface;
    3. use Psr\Http\Message\ServerRequestInterface;
    4. use Psr\Http\Server\RequestHandlerInterface;
    5. use Swoft\Bean\Annotation\Mapping\Bean;
    6. use Swoft\Http\Server\Contract\MiddlewareInterface;
    7. /**
    8. * @Bean()
    9. */
    10. class ControllerMiddleware implements MiddlewareInterface
    11. {
    12. /**
    13. * Process an incoming server request.
    14. *
    15. * @param ServerRequestInterface $request
    16. * @param RequestHandlerInterface $handler
    17. *
    18. * @return ResponseInterface
    19. * @inheritdoc
    20. */
    21. public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    22. {
    23. $response = $handler->handle($request);
    24. return $response;
    25. }
    26. }

    使用

    配置全局中间件

    当你的自定义中间件需要全局请求应用,则可以考虑将此中间件作为全局中间件去使用,只需在 Bean 配置文件内配置 httpDispatcher 的 middlewares 属性,在数组中加入你的自定义中间件的命名空间地址,相关配置通常在 app/bean.php 内

    1. return [
    2. ...
    3. 'httpDispatcher'=>[
    4. 'middlewares'=>[
    5. AuthMiddleware::class,
    6. ApiMiddleware::class
    7. ]
    8. ]
    9. ...
    10. ]

    通过注解使用

    通过 @Middleware@Middlewares, 可以很方便的配置中间件到当前的 Controller 和 Action 内

    当将此注解应用于 Controller 上,则作用域为整个 Controller
    将此注解应用于 Action 上,则作用域仅为当前的 Action
    @Middleware 用于配置单个中间件
    @Middlewares 显而易见的是用于配置一组 @Middleware,按照定义顺序依次执行

    1. namespace App\Http\Controller;
    2. use App\Http\Middleware\ApiMiddleware;
    3. use App\Http\Middleware\IndexMiddleware;
    4. use App\Http\Middleware\ControllerMiddleware;
    5. use Swoft\Http\Server\Annotation\Mapping\Controller;
    6. use Swoft\Http\Server\Annotation\Mapping\Middleware;
    7. use Swoft\Http\Server\Annotation\Mapping\Middlewares;
    8. use Swoft\Http\Server\Annotation\Mapping\RequestMapping;
    9. /**
    10. * @Controller()
    11. * @Middlewares({
    12. * @Middleware(ApiMiddleware::class),
    13. * @Middleware(ControllerMiddleware::class)
    14. * })
    15. */
    16. class MiddlewareController
    17. {
    18. /**
    19. * @RequestMapping()
    20. * @Middleware(IndexMiddleware::class)
    21. */
    22. public function index(){
    23. return "MiddlewareController";
    24. }
    25. }

    应用

    提前拦截请求

    注意: 拦截要在 $handler->handle($request) 之前

    1. namespace App\Http\Middleware;
    2. use Psr\Http\Message\ResponseInterface;
    3. use Psr\Http\Message\ServerRequestInterface;
    4. use Psr\Http\Server\RequestHandlerInterface;
    5. use Swoft\Bean\Annotation\Mapping\Bean;
    6. use Swoft\Context\Context;
    7. use Swoft\Http\Server\Contract\MiddlewareInterface;
    8. /**
    9. * @Bean()
    10. */
    11. class SomeMiddleware implements MiddlewareInterface
    12. {
    13. /**
    14. * Process an incoming server request.
    15. * @param ServerRequestInterface $request
    16. * @param RequestHandlerInterface $handler
    17. * @return ResponseInterface
    18. * @inheritdoc
    19. */
    20. public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    21. {
    22. $path = $request->getUri()->getPath();
    23. if ($path === '/favicon.ico') {
    24. $response = Context::mustGet()->getResponse();
    25. return $response->withStatus(404);
    26. }
    27. return $handler->handle($request);
    28. }
    29. }

    跨域设置

    1. namespace App\Http\Middleware;
    2. use Psr\Http\Message\ResponseInterface;
    3. use Psr\Http\Message\ServerRequestInterface;
    4. use Psr\Http\Server\RequestHandlerInterface;
    5. use Swoft\Bean\Annotation\Mapping\Bean;
    6. use Swoft\Http\Server\Contract\MiddlewareInterface;
    7. /**
    8. * @Bean()
    9. */
    10. class CorsMiddleware implements MiddlewareInterface
    11. {
    12. /**
    13. * Process an incoming server request.
    14. * @param ServerRequestInterface $request
    15. * @param RequestHandlerInterface $handler
    16. * @return ResponseInterface
    17. * @inheritdoc
    18. */
    19. public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    20. {
    21. if ('OPTIONS' === $request->getMethod()) {
    22. $response = Context::mustGet()->getResponse();
    23. return $this->configResponse($response);
    24. }
    25. $response = $handler->handle($request);
    26. return $this->configResponse($response);
    27. }
    28. private function configResponse(ResponseInterface $response)
    29. {
    30. return $response
    31. ->withHeader('Access-Control-Allow-Origin', 'http://mysite')
    32. ->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
    33. ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
    34. }
    35. }

    用户JWT登陆验证

    1. namespace App\Http\Middleware;
    2. use Psr\Http\Message\ResponseInterface;
    3. use Psr\Http\Message\ServerRequestInterface;
    4. use Psr\Http\Server\RequestHandlerInterface;
    5. use Swoft\Bean\Annotation\Mapping\Bean;
    6. use Swoft\Context\Context;
    7. use Swoft\Http\Server\Contract\MiddlewareInterface;
    8. /**
    9. * @Bean()
    10. */
    11. class AuthMiddleware implements MiddlewareInterface
    12. {
    13. /**
    14. * Process an incoming server request.
    15. * @param ServerRequestInterface $request
    16. * @param RequestHandlerInterface $handler
    17. * @return ResponseInterface
    18. * @inheritdoc
    19. */
    20. public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    21. {
    22. // before request handle
    23. // 判断token
    24. $token = $request->getHeaderLine("token");
    25. $type = \config('jwt.type');
    26. $public = \config('jwt.publicKey');
    27. try {
    28. $auth = JWT::decode($token, $public, ['type' => $type]);
    29. $request->user = $auth->user;
    30. } catch (\Exception $e) {
    31. $json = ['code'=>0,'msg'=>'授权失败']
    32. $response = Context::mustGet()->getResponse();
    33. return $response->withData($json);
    34. }
    35. $response = $handler->handle($request);
    36. return $response;
    37. // after request handle
    38. }
    39. }