Dingo Api中Terminate中间件无法使用的原因追寻

追了一下发现其实github上已经有人提过这个问题了。这里我只是记录一下位置和大概说说中间件的原理。

原理篇 :关键词:pipeline 网上很多原理分析,可以了解下。

dingo关键目录vendor\dingo\api\src\Routing\Adapter\Lumen.php line 218

    /**
     * Remove the global application middleware as it's run from this packages
     * Request middleware. Lumen runs middleware later in its life cycle
     * which results in some middleware being executed twice.
     *
     * @return void
     */
    protected function removeMiddlewareFromApp()
    {
        if ($this->middlewareRemoved) {
            return;
        }

        $this->middlewareRemoved = true;

        $reflection = new ReflectionClass($this->app);
        $property = $reflection->getProperty('middleware');
        $property->setAccessible(true);

        $property->setValue($this->app, []);
        $property->setAccessible(false);
    }

这个方法是为了过滤已经执行过的中间件的,直接粗暴的把中间件都过滤掉了

我现在把它改成

    /**
     * Remove the global application middleware as it's run from this packages
     * Request middleware. Lumen runs middleware later in its life cycle
     * which results in some middleware being executed twice.
     *
     * @return void
     */
    protected function removeMiddlewareFromApp()
    {
        if ($this->middlewareRemoved) {
            return;
        }

        $this->middlewareRemoved = true;

        $reflection = new ReflectionClass($this->app);
        $property = $reflection->getProperty('middleware');
        $property->setAccessible(true);
        $oldMiddlewares = $property->getValue($this->app);
        $newMiddlewares = [];
        foreach ($oldMiddlewares as $middle) {
            if ((new ReflectionClass($middle))->hasMethod('terminate') && $middle != 'Dingo\Api\Http\Middleware\Request') {
                $newMiddlewares = array_merge($newMiddlewares, [$middle]);
            }
        }
        $property->setValue($this->app, $newMiddlewares);
        $property->setAccessible(false);
    }

改了这里的话还是会有执行2次的问题,这个执行两次的问题原因在于,dingo和lumen都有去执行pipeline方法

在dingo中的方法在:\vendor\dingo\api\src\Http\Middleware\Request.php line121 这个方法的主要作用就是把request发送到dingo的router中

    /**
     * Send the request through the Dingo router.
     *
     * @param \Dingo\Api\Http\Request $request
     *
     * @return \Dingo\Api\Http\Response
     */
    protected function sendRequestThroughRouter(HttpRequest $request)
    {
        $this->app->instance('request', $request);

        return (new Pipeline($this->app))->send($request)->through($this->middleware)->then(function ($request) {
            return $this->router->dispatch($request);
        });
    }

 

在lumen中,是在这个trait目录下:\vendor\laravel\lumen-framework\src\Concerns\RoutesRequests.php

    /**
     * Dispatch the incoming request.
     *
     * @param  SymfonyRequest|null  $request
     * @return Response
     */
    public function dispatch($request = null)
    {
        list($method, $pathInfo) = $this->parseIncomingRequest($request);

        try {
            return $this->sendThroughPipeline($this->middleware, function () use ($method, $pathInfo) {
                if (isset($this->routes[$method.$pathInfo])) {
                    return $this->handleFoundRoute([true, $this->routes[$method.$pathInfo]['action'], []]);
                }

                return $this->handleDispatcherResponse(
                    $this->createDispatcher()->dispatch($method, $pathInfo)
                );
            });
        } catch (Exception $e) {
            return $this->prepareResponse($this->sendExceptionToHandler($e));
        } catch (Throwable $e) {
            return $this->prepareResponse($this->sendExceptionToHandler($e));
        }
    }


    /**
     * Send the request through the pipeline with the given callback.
     *
     * @param  array  $middleware
     * @param  \Closure  $then
     * @return mixed
     */
    protected function sendThroughPipeline(array $middleware, Closure $then)
    {
        if (count($middleware) > 0 && ! $this->shouldSkipMiddleware()) {
            return (new Pipeline($this))
                ->send($this->make('request'))
                ->through($middleware)
                ->then($then);
        }

        return $then();
    }

既然如此,dingo这里又重复的执行了一次中间件,不如直接在dingo中去掉->through($middleware)

综上所述,我们要改动dingo源码的两个地方,一就是上面我改的那个地方,二就是\vendor\dingo\api\src\Http\Middleware\Request.php line121 方法中去掉 ->through($middleware)

 

 

转载于:https://my.oschina.net/zwyang/blog/1580271

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值