This article mainly introduces about the Laravel core interpretation of response, has a certain reference value, now share to everyone, the need for friends can refer to
Response
In the first two sections we talked about the Laravel controller and the request object, and in the section of the request object we looked at how the request object was created and where the method it supported was defined. When we talk about the controller, we describe in detail how to find the Controller method for the request and then execute the handler, and in this section we will say how the execution result of the Controller method is converted to the Response object response and then returned to the client.
Create response
Let's go back to the code block where the Laravel execution route handler returns the response:
Namespace Illuminate\routing;class Router implements Registrarcontract, bindingregistrar{protected function Runro Ute (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)); } protected function Runroutewithinstack (Route $route, Request $request) {$shouldSkipMiddleware = $this- >container->bound (' middleware.disable ') && $this->container->make (' Middlewa Re.disable ') = = = true; Collects middleware $middleware for routing and controller applications = $shouldSkipMiddleware? []: $this->gatherroutemiddleware ($route); Return (new Pipeline ($this->container))->send ($request)->through ($middlew IS) ->then (function ($request) use ($route) {return $this->prepareresponse ( $request, $route->run ()); }); }}
In the section on the controller, we have already mentioned that the Runroutewithinstack
method is where the final execution of the route handler (Controller method or closure handler) is, and we can see from the above code that the result of the execution is passed to the Prepareresponse
method for Router
, and once the program flow returns to Runroute
, it executes once prepareresponse The
method gets the response object to return to the client, so let's look at the prepareresponse
method in more detail.
Class Router implements Registrarcontract, bindingregistrar{/** * Create response objects with given values * * @param \symfony\c Omponent\httpfoundation\request $request * @param mixed $response * @return \illuminate\http\response|\illumina Te\http\jsonresponse */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)->createres Ponse ($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); }}
In the above code we see three kinds of response:
Class Name |
Representation |
Psrresponseinterface (alias of Psrhttpmessageresponseinterface) |
Definition of service-side response in the PSR specification |
Illuminatehttpjsonresponse (sub-class of Symfonycomponenthttpfoundationresponse) |
Definition of the server-side JSON response in Laravel |
Illuminatehttpresponse (sub-class of Symfonycomponenthttpfoundationresponse) |
Definition of generic non-JSON response in Laravel |
prepareResponse
the logic in this can be seen, regardless of what value is returned by the route execution result, which is eventually converted to a response object by Laravel. These objects are objects of the Symfonycomponenthttpfoundationresponse class or its subclasses. From here it can be seen that the same laravel as the request response is also dependent on the components of the Symfony framework HttpFoundation
.
Let's take a look at how the Symfonycomponenthttpfoundationresponse is constructed:
namespace Symfony\component\httpfoundation;class response{public function __construct ($content = ", $status = 200 , $headers = Array ()) { $this->headers = new Responseheaderbag ($headers); $this->setcontent ($content); $this->setstatuscode ($status); $this->setprotocolversion (' 1.0 '); } Sets the content public function for the response SetContent ($content) { if (null!== $content &&!is_string ($ Content) &&!is_numeric ($content) &&!is_callable (Array ($content, ' __tostring ')) { throw new \ Unexpectedvalueexception (sprintf (' The Response content must be a string or object implementing __tostring (), '%s ' given. ' , GetType ($content))); } $this->content = (string) $content; return $this; }}
So the return value of the route handler is set to the object's content property in the Startup response object, and the value of the property is the response to the response returned to the client.
Set Response headers
The prepare
method of the object is executed after the response object is generated, and the method is defined in the Symfony\component\httpfoundation\resposne
class. Its main purpose is to fine-tune the response to comply with the http/1.1 protocol (RFC 2616).
namespace Symfony\component\httpfoundation;class response{//Revise the response before it is sent to the client so that it complies with the HTTP/1.1 protocol public Function PREPA Re (Request $request) {$headers = $this->headers; if ($this->isinformational () | | $this->isempty ()) {$this->setcontent (null); $headers->remove (' Content-type '); $headers->remove (' content-length '); } else {//Content-type based on the Request if (! $headers->has (' Content-type ')) { $format = $request->getrequestformat (); if (null!== $format && $mimeType = $request->getmimetype ($format)) {$headers->set (' Cont Ent-type ', $mimeType); }}//Fix content-type $charset = $this->charset?: ' UTF-8 '; if (! $headers->has (' Content-type ')) {$headers->set (' Content-type ', ' text/html; charset= '. $charset); } elseif (0 = = = StripoS ($headers->get (' Content-type '), ' text/') && false = = = Stripos ($headers->get (' Content-type '), ' CharSet ') {//Add the CharSet $headers->set (' Content-type ', $headers->get (' content-t Ype '). '; Charset= '. $charset); }//Fix content-length if ($headers->has (' transfer-encoding ')) {$headers->rem Ove (' Content-length '); } if ($request->ismethod (' HEAD ')) {//cf. RFC2616 14.13 $length = $headers-&G T;get (' content-length '); $this->setcontent (NULL); if ($length) {$headers->set (' content-length ', $length); }}}//Fix protocol if (' http/1.0 '! = $request->server->get (' Server_protocol ')} { $this->setprotocolversion (' 1.1 '); }//Check If we need to send extra expire info headers if (' 1.0 ' = = $this->getProtocolVersion () && false!== Strpos ($this->headers->get (' Cache-control '), ' No-cache ')) {$this- >headers->set (' pragma ', ' no-cache '); $this->headers->set (' Expires ',-1); } $this->ensureieoversslcompatibility ($request); return $this; }}
prepare
For various situations response header
, such as Content-Type
, and Content-Length
so on, these are our common header fields.
Send response
After the response is created and set up, it flows through the post operation of the Routing and Framework middleware, and in the post-operation of the middleware, the response is usually further processed, and finally the program flows back to the HTTP kernel where the HTTP kernel sends the response to the client , let's take a look at this part of the code.
Entry file Public/index.php$kernel = $app->make (illuminate\contracts\http\kernel::class); $response = $kernel Handle ( $request = Illuminate\http\request::capture ()); $response->send (); $kernel->terminate ($request, $ Response);
namespace Symfony\component\httpfoundation;class response{Public function Send () {$this->sendheaders (); $this->sendcontent (); if (function_exists (' fastcgi_finish_request ')) {fastcgi_finish_request (); } elseif (' CLI '!== php_sapi) {static::closeoutputbuffers (0, true); } return $this; }//Send headers to client public function sendheaders () {///headers has already been sent by the developer if (Headers_sent ()) {return $this; }//Headers foreach ($this->headers->allpreservecasewithoutcookies () as $name = = $values) { foreach ($values as $value) {header ($name. ': '. $value, False, $this->statuscode); }}//Status header (sprintf (' http/%s%s ', $this->version, $this->statuscode, $this->stat Ustext), True, $this->statuscode); Cookie foreach ($this->headers->getcookies () as $cookie) {if ($cookie->israw ()) {Setrawcookie ($cookie->getname (), $c Ookie->getvalue (), $cookie->getexpirestime (), $cookie->getpath (), $cookie->getdomain (), $cookie- Issecure (), $cookie->ishttponly ()); } else {Setcookie ($cookie->getname (), $cookie->getvalue (), $cookie->getexpirestime (), $cookie-> ; GetPath (), $cookie->getdomain (), $cookie->issecure (), $cookie->ishttponly ()); }} return $this; }//Send response content to client public function sendcontent () {echo $this->content; return $this; }}
send
The logic is very good to understand, the previous set of those headers set to the HTTP Response header field, the content will echo after the HTTP response is set to the principal entity. Finally, PHP sends the full HTTP response to the client.
After the send response, HTTP kernel executes method calls to the method terminate
in the Terminate middleware terminate
, and finally executes the applied termiate
method to end the entire application life cycle (from receiving the request to the end of the return response).
The above is the whole content of this article, I hope that everyone's learning has helped, more relevant content please pay attention to topic.alibabacloud.com!