The Drupal 8 RenderPipeline
Anish M. M.Adrian McDonald Tariang
Summer Interns
Date: 2017-06-08
From Request to Response
Introduction
In order to generate a response for a request, Drupal performs a sequence of steps, called the Drupal Render Pipeline. In the following slides, we will go through these steps one by one.
Request to Response
Drupal’s Request Processing
The Drupal Application
1.The Front Controller[index.php]
This is the entry point of execution where Drupal creates the Request Object from the HTTP request, processes it and and returns the response back to the browser.
1.The Front Controller[index.php]Key Components
HttpFoundationComponent of Symfony that creates an object-oriented layer from the superglobals of the PHP request.
HttpKernelAnother Symfony component used to provide a structured pipeline to render a response for the Drupal System.
Loads all the dependencies using the autoload.php file.Instantiates the DrupalKernel class.Creates a $request object of Symfony’s Request class from the component HttpFoundation.Calls the DrupalKernel::handle() method and passes the $request object as argument.
1.The Front Controller[index.php]Steps Followed
DrupalKernel::handle()
This handle() method : Calls DrupalKernel::bootEnvironment() - which sets the PHP environment variables that need to be set to ensure security.Calls DrupalKernel::initializeSettings() which locates site path and initializes the Drupal settings.Calls HttpKernel::handle() method which is a part of the Symfony component HttpKernel.
HttpKernel::handle()
Events, Event Listeners.
An event is like a notice on a bulletin board. Event Listeners are the people who wait (‘listen’) for a notice. Listeners listen for a particular kind of event, say, for a kernel.exception event. Dispatching an event is like putting it on the notice board.
When the event they are listening to is dispatched, they check whether they can perform the required action. If so, they respond to the dispatched event using the setResponse() method and stops the propagation of the event.
REQUEST event
During this event, exceptions could occur which could run its own controller (see kernel.exception) and send back a response.
The first event in the kernel.handle() method. Subscribers to the request event perform task such as:1. Format negotiation of the response data i.e. html, json.2. Controller selection to handle the request.
REQUEST event Subscribersin order of execution
Routing
Drupal’s routing system is responsible for providing an appropriate controller to a requested path.It is based on the Symfony component Routing, which uses routes.yml files present in the module directory to map the routes to controllers. The route file contains data such as the format the response is to be produced, the controller to be used, security requirements and other supporting data.
RouteBuilder::rebuild()building the route information
This workflow represents how the routes are loaded from the modules’ routing.yml files and other sources into the Drupal database.
Routing
The controller performs the business logic for the application.The routing.yml file contains one of these “controller” types:
_content_controller_form_entity[_form | _view | _list]
Which specify how the output is generated. This data is then set into the request attributes.
Routing Example
In this example, during the request event, if the URL request is as specified in `path`, the controller defined at `_form` is to be used to provide the given menu form.This YAML file also specifies that the client needs to be logged in to access the page.
colorbox.routing.yml file to the Colorbox module.
An example request:
Controller Resolution
Now, the handle() method is required to select the exact Controller using the request attributes that was set by the routing Component.
This is performed using the getController() method of a class implementing the ControllerResolverInterface of the Symfony component HttpKernel.
Resolving Controller Parameters
The given section is used to provide an array of arguments for the Controller to operate. This is performed by the Drupal System and may even include the entire request object if required.
CONTROLLER event
During this event, subscribers or listeners perform initialization or testing before the controller is allowed to be executed.The Listeners also have the privilege to change the Controller to be used if required.
Resolving Controller Parameters
The given section is used to provide an array of arguments for the Controller to operate. This is performed by the Drupal System and may even include the entire request object if required.
Calling the controller
The selected controller is now called by handle() with its arguments. The Drupal controllers return either:
The Response Object
Render Array
or other objects.
If the controller returns a response object, it moves directly to the response event without going through the view event.Render arrays and other objects are converted into Response objects through the listeners of the view event, which is dispatched after controller completion.
VIEW event
Listeners to this event, also called View Subscribers, convert render arrays and objects into Response objects by delegating the task to specified renderers to a given format. (html, json, xml).Listeners, can also use templates to provide the response object in the specified format.
Render ArraysExample:
Render Array HTML Output
Through a Content Renderer
Render Arrays
A render array is a classic Drupal structured array that provides data (probably nested) along with hints as to how it should be rendered (properties like #type).
Modules have the capability of defining “elements”, which are essentially prepackaged default render arrays. They use hook_element_info() to do this.
When #type is declared for a render array, the default properties of the element type named are loaded through the use of hook_element_info().
Render Arrays
They allow the modules to treat the content as data for as long as possible in the page generation process.
MainContentViewSubscriber
This view subscriber converts Render Arrays into Response objects. It checks whether a maincontent renderer service for the requested response format exists. If it does, it is initialized. Else, a 406 (Not Acceptable) response is generated.
Other objects may be converted by corresponding view subscribers on seeing the kernel.view event, either directly into Response objects, or into Render Arrays. In the latter case, the MainContentViewSubscriber converts it into a Response object.
RESPONSE event
During the event, final modifications are performed over the Response object such as inserting javascripts or cookies.Placeholders in the Response object are replaced through Placeholder Strategies such as BigPipe and SingleFlush.It is after this event that the Response is sent back to the Front controller through the handle() method.
SingleFlush vs BigPipeCaching
Cache, in computing, is a component that stores frequently used data so that future requests for that data can be served faster.
Frequently used / common data can be cached and loaded faster, while dynamic / personalized data is generated.
In Drupal 8, Caching is performed through cache-tags, cache-contexts and max-age.
SingleFlush vs BigPipe
By default, responses to requests are delivered in a SingleFlush method. The server generates all the content to be displayed and then dumps it to the browser screen. So, entire pages are cache-able, but not as parts of one. Here, the perceived time for loading the web page is more and user has to sometimes stare at a white screen till the full page loads.
SingleFlush vs BigPipe
An alternative to SingleFlush, is the BigPipe method. Here, the pages are sent in a way which allows the browser to display them much faster. Caching of parts of pages is possible. So, the cached parts are displayed and then the dynamic parts are added as and when received.The total time for loading the page may be the same, but the perceived time is lesser. Also, the user is provided with some workable content before the whole page is loaded.
TERMINATE event
This event is triggered after the Response object is already sent back to the client.Used to perform slower tasks such as system logging and sending emails which now would not increase response time.This is made possible by the TerminableInterface provided by the Symfony component HttpKernel.
EXCEPTION event
Triggered to handle exceptions and tailor appropriate responses to the client. For example, if the client does not have sufficient permissions or if the requested data does not exist.An exception is also thrown when no listeners to events such as request and view are triggered.
ReferencesSite Point: From Request to ResponseDrupal Render API DocumentationDrupal 8 Render Pipeline talkSymfony 2 HttpKernel ComponentDrupal API DocumentationDrupal Cache API Documentation
Credits
Wim Leers, author to material such as the render pipeline diagram and the DrupalCon talk, which have been used extensively in this presentation.Images taken from symfony.com/docs
Top Related