• 路由处理生成响应


    index.php

    $kernel = $app->make(IlluminateContractsHttpKernel::class);
    
    //处理请求
    $response = $kernel->handle(
        //请求实例的创建
        $request = IlluminateHttpRequest::capture()
    );
    

      

    vendorlaravelframeworksrcIlluminateFoundationHttpKernel.php

        /**
         * Handle an incoming HTTP request.
         *处理一个http请求
         * @param  IlluminateHttpRequest  $request
         * @return IlluminateHttpResponse
         */
        public function handle($request)
        {
            try {
                //在请求过程中会添加CSRF保护,服务端会发送一个csrf令牌给客户端(cookie)
                $request->enableHttpMethodParameterOverride();
                //请求处理,通过路由传输请求实例
                $response = $this->sendRequestThroughRouter($request);
            } catch (Exception $e) {
                $this->reportException($e);
    
                $response = $this->renderException($request, $e);
            } catch (Throwable $e) {
                $this->reportException($e = new FatalThrowableError($e));
    
                $response = $this->renderException($request, $e);
            }
    
            $this->app['events']->dispatch(
                new EventsRequestHandled($request, $response)
            );
    
            return $response;
        }
    

      

        /**
         * Send the given request through the middleware / router.
         *
         * @param  IlluminateHttpRequest  $request
         * @return IlluminateHttpResponse
         */
        protected function sendRequestThroughRouter($request)
        {
            $this->app->instance('request', $request);
    
            Facade::clearResolvedInstance('request');
    
            //针对请求为应用程序'拔靴带' 执行bootstrap类的数组
            //在请求处理阶段共有7个环节,每一个环节由一个类来实现的
            //而且每个类都会有一个bootstrap()函数用于实现准备工作
            $this->bootstrap();
    
            return (new Pipeline($this->app))
                        ->send($request)
                        ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
                        ->then($this->dispatchToRouter());
        }
    

      

    dispatchToRouter()

        /**
         * Get the route dispatcher callback.
         *设置路由分发回调函数
         * @return Closure
         */
        protected function dispatchToRouter()
        {
            return function ($request) {
                $this->app->instance('request', $request);
    
                return $this->router->dispatch($request);
            };
        }
    

      

    vendorlaravelframeworksrcIlluminateRoutingRouter.php

        /**
         * Dispatch the request to the application.
         *
         * @param  IlluminateHttpRequest  $request
         * @return IlluminateHttpResponse|IlluminateHttpJsonResponse
         */
        public function dispatch(Request $request)
        {
            $this->currentRequest = $request;
    
            return $this->dispatchToRoute($request);
        }
    

      

    //分发请求到指定路由并返回一个响应

        public function dispatchToRoute(Request $request)
        {
            return $this->runRoute($request, $this->findRoute($request));
        }
    

      

        protected function runRoute(Request $request, Route $route)
        {
            $request->setRouteResolver(function () use ($route) {
                return $route;
            });
    
            $this->events->dispatch(new EventsRouteMatched($route, $request));
    
            return $this->prepareResponse($request,
                $this->runRouteWithinStack($route, $request)
            );
        }
    

      

    //通过实例栈启动给定的路由

     1     protected function runRouteWithinStack(Route $route, Request $request)
     2     {
     3         $shouldSkipMiddleware = $this->container->bound('middleware.disable') &&
     4                                 $this->container->make('middleware.disable') === true;
     5 
     6         $middleware = $shouldSkipMiddleware ? [] : $this->gatherRouteMiddleware($route);
     7 
     8         return (new Pipeline($this->container))
     9                         ->send($request)
    10                         ->through($middleware)
    11                         ->then(function ($request) use ($route) {
    12                             return $this->prepareResponse(
    13                                 $request, $route->run()
    14                             );
    15                         });
    16     }

    在路由信息存储实例中,通过“ $route = Sthis -> findRoute ( $request ) ; ”来查找请求对应的路由实例,

    查找主要是根据请求的方法和请求 URI 来实现对应,当查找到请求对应的路由后,请求将会传递到对应的路由中去处理

    ,即’ " $route-> run ( $ request ) "

    vendorlaravelframeworksrcIlluminateRoutingRoute.php

    执行路由动作并返回响应

     1     public function run()
     2     {
     3         $this->container = $this->container ?: new Container;
     4 
     5         try {
     6             if ($this->isControllerAction()) {
     7                 return $this->runController();
     8             }
     9 
    10             return $this->runCallable();
    11         } catch (HttpResponseException $e) {
    12             return $e->getResponse();
    13         }
    14     }

    //将请求发送到常规分发器去处理

    1     protected function runController()
    2     {
    3         return $this->controllerDispatcher()->dispatch(
    4             $this, $this->getController(), $this->getControllerMethod()
    5         );
    6     }

    在清求对应的路由中,会检测是否使用常规的控制分发器去处理,在初始的 Larave 框架中使用的是常规控制分发器,

    通过服务容器自动生成这个控制分发器,这个服务是通过服务提供者 ControUerservicoProvider 注册的,下一步将会把请求及路由中关于处理函数的信息交给控制分发器去处理,

    这里对路由中关于处理函数的信息是以控制器类名和函数名给出的,即$class和$method

    控制器的生成:

    控制器生成在控制分发器中,将会根据路由提供的响应函数信息来实例化控制器类,并调用对应的响应函数生成响应的内容部分厂.下面给出部分源码:

    vendorlaravelframeworksrcIlluminateRoutingControllerDispatcher.php

    向给定的控制器和方法发送请求。

     1     public function dispatch(Route $route, $controller, $method)
     2     {
     3         $parameters = $this->resolveClassMethodDependencies(
     4             $route->parametersWithoutNulls(), $controller, $method
     5         );
     6 
     7         if (method_exists($controller, 'callAction')) {
     8             return $controller->callAction($method, $parameters);
     9         }
    10 
    11         return $controller->{$method}(...array_values($parameters));
    12     }

    响应的生成

    vendorlaravelframeworksrcIlluminateRoutingRouter.php

        protected function runRoute(Request $request, Route $route)
        {
            $request->setRouteResolver(function () use ($route) {
                return $route;
            });
    
            $this->events->dispatch(new EventsRouteMatched($route, $request));
    
            return $this->prepareResponse($request,
                $this->runRouteWithinStack($route, $request)
            );
        }
    

      

        public function prepareResponse($request, $response)
        {
            return static::toResponse($request, $response);
        }
    

      

        public static function toResponse($request, $response)
        {
            if ($response instanceof Responsable) {
                $response = $response->toResponse($request);
            }
    
            if ($response instanceof PsrResponseInterface) {
                $response = (new HttpFoundationFactory)->createResponse($response);
            } elseif (! $response instanceof SymfonyResponse &&
                       ($response instanceof Arrayable ||
                        $response instanceof Jsonable ||
                        $response instanceof ArrayObject ||
                        $response instanceof JsonSerializable ||
                        is_array($response))) {
                $response = new JsonResponse($response);
            } elseif (! $response instanceof SymfonyResponse) {
                $response = new Response($response);
            }
    
            if ($response->getStatusCode() === Response::HTTP_NOT_MODIFIED) {
                $response->setNotModified();
            }
    
            return $response->prepare($request);
        }
    

      

    vendorsymfonyhttp-foundationResponse.php

    在发送到客户端之前准备响应

     1     public function prepare(Request $request)
     2     {
     3         $headers = $this->headers;
     4 
     5         if ($this->isInformational() || $this->isEmpty()) {
     6             $this->setContent(null);
     7             $headers->remove('Content-Type');
     8             $headers->remove('Content-Length');
     9         } else {
    10             // Content-type based on the Request
    11             if (!$headers->has('Content-Type')) {
    12                 $format = $request->getRequestFormat();
    13                 if (null !== $format && $mimeType = $request->getMimeType($format)) {
    14                     $headers->set('Content-Type', $mimeType);
    15                 }
    16             }
    17 
    18             // Fix Content-Type
    19             $charset = $this->charset ?: 'UTF-8';
    20             if (!$headers->has('Content-Type')) {
    21                 $headers->set('Content-Type', 'text/html; charset='.$charset);
    22             } elseif (0 === stripos($headers->get('Content-Type'), 'text/') && false === stripos($headers->get('Content-Type'), 'charset')) {
    23                 // add the charset
    24                 $headers->set('Content-Type', $headers->get('Content-Type').'; charset='.$charset);
    25             }
    26 
    27             // Fix Content-Length
    28             if ($headers->has('Transfer-Encoding')) {
    29                 $headers->remove('Content-Length');
    30             }
    31 
    32             if ($request->isMethod('HEAD')) {
    33                 // cf. RFC2616 14.13
    34                 $length = $headers->get('Content-Length');
    35                 $this->setContent(null);
    36                 if ($length) {
    37                     $headers->set('Content-Length', $length);
    38                 }
    39             }
    40         }
    41 
    42         // Fix protocol
    43         if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) {
    44             $this->setProtocolVersion('1.1');
    45         }
    46 
    47         // Check if we need to send extra expire info headers
    48         if ('1.0' == $this->getProtocolVersion() && false !== strpos($this->headers->get('Cache-Control'), 'no-cache')) {
    49             $this->headers->set('pragma', 'no-cache');
    50             $this->headers->set('expires', -1);
    51         }
    52 
    53         $this->ensureIEOverSSLCompatibility($request);
    54 
    55         return $this;
    56     }
  • 相关阅读:
    基本背包问题
    linux 共享内存实现
    Linux内存管理原理
    从inet_pton()看大小端字节序
    linux线程的实现
    简述memcached中的一致哈希
    c语言实现面向对象OOC
    论记忆力
    关于编程内存泄漏
    一道常考fork题挖掘
  • 原文地址:https://www.cnblogs.com/sunlong88/p/9364679.html
Copyright © 2020-2023  润新知