APIs in Drupal 8: the Services Module

Web services and APIs (application programming interfaces) are hot topics among Web developers -- for two good reasons.

Many developers now want to expose content and features on their site via Web services or APIs.

It's getting easier to take advantage of these services. Drupal 8, for example, now has this capability in core. And some contributed modules are attempting to make it even better.

This is why Acquia and Palantir.net, the Chicago-based Web strategy, development, and design firm, have been working together on a Web services series. The latest installment, by Acquia's Kyle Browning (number 4 in the series) focuses on the Services module.

Larry "Crell" Garfield, Palantir.net's Senior Architect and Community Lead (Larry also led the Drupal 8 Web Services Initiative), kicked off the series with three strong blog posts. The first one, hosted right here in the Acquia Developer Center, was titled, Web Services 101. In it Larry took a broad view of what we mean when we talk about "Web services."

In Part 2, Larry advanced the series with a post entitled, D8FTW: REST-aware Routing. In that installment, Larry continued his comprehensive explanation of exactly what Web services are, providing a necessary foundation for readers to approach the Web services developments new to Drupal 8.

Larry's latest, over on the Palantir.net blog, is titled simply, D8FTW: REST in Core, and introduces a trio of modules in Drupal 8 core that enable push-button support for offering up content as a Web service .

So we're rollin'! And now Kyle Browning, from Acquia, is advancing the series another step, with post #4. The topic is the Drupal 8 Services module. Kyle is a co-maintainer of the Services module.

Coming next, btw: another post, on a new module, RELAXed Web Services, by Dick Olsson and Tim Milwood.

But that's getting ahead of the story. Let's focus on the latest chapter from Kyle: on the Drupal 8 Services module. Take it away, Kyle.

The Drupal 8 Services Module

Looking at “redoing REST,” processes like serialization, and the urge to develop less page-centric call processes, you get a general idea of how Drupal 8 addresses the need for better connections to a vast HTTP ecosystem.

But there’s also the Drupal Services module, which includes changes designed to augment the other work that developers have put in. It uses a non-REST way of handling requests which might be of importance to some developers.

How is that really different from core?

The main goal of these upgraded services is to make it easier for developers to expose data that is not typical for REST, because sometimes developers don’t always build APIs that way. Services 4.x leverages a lot of what core did for serialization, but also adds the ability to accept header content negotiation. We agree that the Vary header for different browsers is not stable and in core that matters when you’re a browser. For an API, most of these calls would be done from some type of client that is not a browser so we aimed to accept content headers. That being said you can still use ?_format=json if you want to.

Putting the API behind a centralized URL provides sampling capabilities. So instead of the REST and core idea of /node/one, we have moved everything behind /api/entity/one to create entity-based and entity-driven approaches to building non-REST APIs.

The centralized URL also allows you to write custom VCL strategies and gives you another place to do so. Along with these capabilities, if you write your own serializer, services will automatically pick it up and allow you to use it.

It accepts authorization/authentication that core provides, so that CSRF, session auth, and others that developers build will work directly with the Services module.

Configuration

Another new function in Drupal 8 Services — and new in core to — is the configuration entities. In a slightly different structured way than core, we wanted to provide a very easy way to get in and update even Drupal settings.. So accessing and updating configuration entities has been simplified for ease of use.

In Drupal 8, the annotations become the important aspect of creating custom “resources,” which are now called “ServiceDefinitions.” We can define the methods you want to use, such as an ID and whether it’s translatable. You can also use response codes for successes and failures, and we also provide an intercept so you can control the access in a custom manner. If your access is denied, nothing beyond the routing layer will be input. Using Symfony in Drupal 8 allows you to drop right in, and not have to load any context or controllers. This fast-tracks performance. Something in Drupal 7 Services we could not do at all because we had to full bootstrap.

Process Request Method

Additionally, Drupal 8 Services now includes “Process Request Method,” usually just another way to get an entity. In the ServicesDefintion called EntityGet, we are just loading an entity and returning it directly. Most of these improvements come out of core context, making users/entities just context-aware. Once you put in your code and return whatever you want, services will handle the serialization cleanly. In these ServiceDefinition's, you can also throw your exceptions and return your response codes that you like.

All throughout this functionality, we still respect core users’ caching policies. For the underscore format, we didn’t want to override what core really decided, in terms of what’s best. You can still pass the URL parameter and no content negotiation headers to get your response. For the caching policies, if you hit a URL that’s already been used, you’ll get returned to the cache response.

When creating a block in Services, it usually begins with viewing a list of all blocks. After grabbing a block, it passes in the block ID and produces a response to generate the configuration. This capability allows you to create configuration entities from Services. A powerful component of this is the ability to pull out the view, call view results, and get them back via Services. There are some caveats with displaying HTML, but largely we can do it with JSON.

Finally, I wanted to mention our respect for permissions. Infinitely better than in Drupal 7 it respects Core Drupal 8 in ways we just could not do in Drupal 7 — looking at you field permissions —.

All these improvements, upgrades, and additions were conceived to build upon the performance and usability demonstrated in Drupal 7, but from the viewpoint and world of Drupal 8. We hope the Services module in Drupal 8 helps you develop, expose data, build blocks, access configuration entities -- and its use lets your clients get whatever they want.

In this series, we’ve explained how the new Drupal is designed to be REST-accommodating, but not REST-exclusive, and how we have responded to modern trends on data handling, Web service provisions, and all of the big changes going on with Internet development.

Now, see for yourself how Drupal 8 enables a more meaningful architecture.