路由处理生成响应

index.php

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

//处理请求
$response = $kernel->handle(
    //请求实例的创建
    $request = Illuminate\Http\Request::capture()
);

  

\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php

    /**
     * Handle an incoming HTTP request.
     *处理一个http请求
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    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 Events\RequestHandled($request, $response)
        );

        return $response;
    }

  

    /**
     * Send the given request through the middleware / router.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    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);
        };
    }

  

vendor\laravel\framework\src\Illuminate\Routing\Router.php

    /**
     * Dispatch the request to the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse
     */
    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 Events\RouteMatched($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 ) "

 

vendor\laravel\framework\src\Illuminate\Routing\Route.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

 

控制器的生成:

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

vendor\laravel\framework\src\Illuminate\Routing\ControllerDispatcher.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     }

 

响应的生成

\vendor\laravel\framework\src\Illuminate\Routing\Router.php

    protected function runRoute(Request $request, Route $route)
    {
        $request->setRouteResolver(function () use ($route) {
            return $route;
        });

        $this->events->dispatch(new Events\RouteMatched($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);
    }

  

vendor\symfony\http-foundation\Response.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     }

 

转载于:https://www.cnblogs.com/sunlong88/p/9364679.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值