Skip to main content

Improving the handling of Drupal JSON:API hyperlinks in GatsbyJS

Published on Monday 2, December 2019

I have been tracking down an interesting quirk when parsing JSON:API resources with the Drupal source plugin for GatsbyJS. I have a test environment with the JSON:API Schema module installed and was receiving errors about data in the links property. I was pretty confused because the links object is never empty and the JSON:API implementation is rock solid for Drupal.

I quick opened a fix for GatsbyJS to perform a sanity check that the response data had a links property before attempting to grab the URL for the next link. To my surprise, Michal Piechowiak of the gatsby/core team reviewed and merged my pull request only three hours after it merged! I knew this was not the final fix and that it smelled of a larger problem. Coming from my experience within Drupal and other open source, I was expecting pushback and having to make a case for the change and investigate the fix further. Nope! That sucker went in. And it felt good. 

As a maintainer myself, I'm not exactly one to "push the button" and just accept a sanity check. I would rather see the issue remain open and hopefully find the answer to the problem, deep down where it originates. However, the truth is, most people don't. Most contributors make a fix and say "works for me" and then continue on with life. Given that this pull request was a sanity check on a source plugin managed by the community, the ease of merging quick fixes makes sense.

But, I didn't stop there. I was irked that this was happening. How was the /jsonapi entrypoint returning a link to a response which did not adhere to the specification?! It turns out that the JSON:API Schema module doesn't just add a describedby link to each entity, it also adds a root schema link. So, the gatsby-source-drupal plugin was crawling /jsonapi, discovering the describedby link for /jsonapi/schema and failing.

The /jsonapi/schema response contains data which adheres to the JSON Schema specification. That means consumers of an API can understand what types of data belong for each data attribute, and validate them. This does not adhere or match to the JSON:API specification, leading to our breakage!

So, I opened another pull request to modify the gatsby-source-drupal plugin. This made a modification to skip the describedby link anytime it is encountered.

  const allData = await Promise.all(
    _.map(data.data.links, async (url, type) => {
-      if (type === `self`) return
+      if (type === `self` || type === `describedby`) return
      if (!url) return

A quick change. And again a quick merge after the weekend. That's when Michal proposed a suggestion

Question for future: not quite sure how "type" usually looks like, but maybe this could be type whitelist (only handle if link type is one we care about) instead of type blacklist (don't handle this type - "self" and "describedby" in current shape)?

So I have opened an issue – Provide disallowed links setting for the Drupal source plugin. This will allow you to configure the source plugin to skip certain hyperlinks found in the JSON:API entrypoint. This will be extra useful as the JSON:API Hypermedia module becomes regurarly used and possibly adds more links to the entrypoint.

The pull request is up https://github.com/gatsbyjs/gatsby/pull/19930