Gatsby: [gatsby-source-wordpress] custom api endpoints

Created on 18 Jan 2018  ·  31Comments  ·  Source: gatsbyjs/gatsby

I recently installed Gatsby and love it!

I am now working on migrating my existing site to use WP/Gatsby. As i was reading through the documentation about the gatsby-source-wordpress plugin, i came across this section. To be honest, i am not entirely sure if i understood it correctly.

Is this saying that i could create my own route and have Gatsby read it through GraphQL?

For example, if i create this route http://localhost/wp-json/foo/v2/bar and have it return an array of data. Could I then simply query that data using AllWordpressFooBar? Or am I missing something?

bug question or discussion

Most helpful comment

@jcnh74 We added a wordpress_id key to every post object that our custom endpoint returned. Something along the lines of $data['wordpress_id'] = $post->ID; assuming $data is the object you're returning.

All 31 comments

Hello @alexyoungcl
Your understanding is correct

@sebastienfi thanks, good to know.

I've created the route I mentioned above with the below snippet:

/// API TEST
add_action( 'rest_api_init', 'myplugin_register_routes' );
function myplugin_register_routes() {
    register_rest_route( 'foo/v2', 'bar', array(
        'methods'  => WP_REST_Server::READABLE,
        'callback' => 'myplugin_serve_route',
    ) );
}

function myplugin_serve_route( WP_REST_Request $request ) {
    $data = array(
        'myKey1' => 'myValue1',
        'myKey2' => 'myValue2',
        'myKey3' => 'myValue3',
        'myKey4' => 'myValue4',
    );
    return new WP_REST_Response( $data, 200 );
}

I am unable to get the data when testing it out inside of GraphiQL with AllWordPressFooBar. I get the following:

{
  "errors": [
    {
      "message": "Cannot query field \"AllWordpressFooBar\" on type \"RootQueryType\". Did you mean \"allWordpressPost\", \"allWordpressWpUsers\", \"allWordpressPage\", \"allWordpressWpMedia\", or \"allWordpressWpTypes\"?",
      "locations": [
        {
          "line": 29,
          "column": 2
        }
      ]
    }
  ]
}

It's worth mentioning that I've restarted Gatsby and can see the route outputted in the console

screen shot 2018-01-18 at 4 02 33 pm

I'm running into a similar issue.

Can you create a repro site ?
What is the output of your endpoint in JSON ?

I'm having this issue as well with a set of custom endpoints. The endpoint is validated and fetched correctly.
```
=== [ Fetching wordpress__flbuilder/v1_all ] === http://localhost/wp-json/flbuilder/v1/all
⢀ source and transform nodes -> wordpress__flbuilder/v1_all fetched : 1
Fetching the wordpress__flbuilder/v1_all took: 831.872ms

But then I get the error `GraphQLError: Cannot query field "allWordpressflbuilderall" on type "RootQueryType".`

When I connect to the endpoint via postman I get

{
"namespace": "flbuilder/v1/all",
"routes": {
"/flbuilder/v1/all": {
"namespace": "flbuilder/v1/all",
"methods": [
"GET"
],
"endpoints": [
{
"methods": [
"GET"
],
"args": {
"namespace": {
"required": false,
"default": "flbuilder/v1/all"
},
"context": {
"required": false,
"default": "view"
}
}
}
],
"_links": {
"self": "http://localhost/wp-json/flbuilder/v1/all"
}
},
"/flbuilder/v1/all/(?P\d+)": {
"namespace": "flbuilder/v1/all",
"methods": [
"GET"
],
"endpoints": [
{
"methods": [
"GET"
],
"args": []
}
]
}
},
"_links": {
"up": [
{
"href": "http://localhost/wp-json/"
}
]
}
}

```

When you access GraphiQL and try the autocompletion with Ctrl+Space, do you have anything related to flbuilder at all ?

No. nothing related to that is coming up. (thanks for the tip about cntrl-space!). However, perhaps I was going about things the wrong way. When I ran gatsby develop this time I noticed that the relevant output re the api was

Invalid route.
Route discovered : /flbuilder/v1/all
Valid route found. Will try to fetch.
Route discovered : /flbuilder/v1/all/(?P<id>\d+)

To me it appears that /all is not valid but it _is_ valid when related to a specific post. I'll have to check on that some more, but I'm not quite sure how to proceed.

Edit -- sorry. maybe I'm looking at the log wrong. it's a little unclear if the valid/invalid response is above or below the route.

@aberkow Would require a step by step debug in https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-wordpress/src/fetch.js#L181-L256

Do you know to setup a Gatsby-dev environement and contribute ? More info here : https://www.gatsbyjs.org/docs/how-to-contribute/#contributing-to-the-repo

Can you set verboseOutput: true in gatsby-config.js and post the log here ? The log may contain sensitive information, so remove any domain, user or password that it may contain..

@sebastienfi thanks! I may get some time to do a little debugging today. I'll definitely read through the contribution docs and turn on verboseOutput (I must have missed that as an option).

Well one part of the mystery is solved for me at least and it was kind of staring me in the face the whole time. It looks like gatsby is only getting responses from routes like/wp/v2/posts or /wp/v2/pages but not /wp/v2/posts/(?P<id>[\d]+) or /wp/v2/pages/(?P<id>[\d]+). I assume this is intentional because why should gatsby try to get a single page based on ID?

So far so good. But, the API endpoint for my plugin is based on returning data at the page ID level. This makes sense as far as it goes because it's for a page builder (beaver builder). So here I figure the plugin author wants to limit the response to a particular page in order to reduce the size of the request.

When I added a few console logs to gatsby-source-wordpress/fetch.js (thanks @sebastienfi) I was able to confirm all of this.

Here's the log from I got back from using verboseOutput in the plugin config.

=== [ Fetching wordpress__flbuilder/v1_all ] === http://localhost/wp-json/flbuilder/v1/all
⠁ source and transform nodes -> wordpress__flbuilder/v1_all fetched : 1
Fetching the wordpress__flbuilder/v1_all took: 909.482ms
[ { namespace: 'flbuilder/v1/all',
    routes:
     { '/flbuilder/v1/all': [Object],
       '/flbuilder/v1/all/(?P<id>\d+)': [Object] },
    _links: { up: [Array] },
    __type: 'wordpress__flbuilder/v1_all' } ] 'routeResponse'
[ { namespace: 'flbuilder/v1/all',
    routes:
     { '/flbuilder/v1/all': [Object],
       '/flbuilder/v1/all/(?P<id>\d+)': [Object] },
    _links: { up: [Array] },
    __type: 'wordpress__flbuilder/v1_all' } ] 'entities'
{ namespace: 'flbuilder/v1/all',
  methods: [ 'GET' ],
  endpoints: [ { methods: [Array], args: [Object] } ],
  _links: { self: 'http://localhost/wp-json/flbuilder/v1/all' } } 'all routes - methods'
[ 'GET' ] 'all routes'
{ namespace: { required: false, default: 'flbuilder/v1/all' },
  context: { required: false, default: 'view' } } 'all routes - args'
undefined 'routes at pages?

Note that this console.log(entities[0].routes['/flbuilder/v1/all/(?P<id>\d+)'], 'routes at pages?'); yields undefined at the end of the request where I try to get pages by an ID.

This is all kind of a long way of saying that unless someone tells me I'm way off, it's probably more useful to change the WP plugin I'm using than change gatsby. But I figured I'd report back what I found.

Any news about this? I just run into the same problem :(

@aberkow I just tried to emulate your endpoint and maybe I found some issue - it seems we don't handle namespaces with multiple / ( flbuilder/v1/all ) and really only play nice with when there is single '/' ( wp/v2, acf/v2 )

I will try to investigate it further. But it still won't fetch your data as that endpoint expects to get id as parameter and wordpress source plugin need endpoints that return whole collection of items and not endpoints that return single item by ID. You would have to create custom endpoint for your flbuilder plugin that returns all data in one go (or maybe flbuilder data is already attached to post / page items - like acf rest plugin do).

Can you tell me if I need to have any extra plugins apart from beaver builder to reproduce your setup? It would save me some time.

@pieh absolutely! I'm using this (unsupported/undocumented) REST plugin one of the beaver builder devs wrote. https://github.com/Pross/bb-rest. It definitely works "as is". I can get responses back from postman that are what I expect at each route.

In my initial tests I had just changed the name of the endpoint from fl-builder to flbuilder. Then I was working at things from the gatsby side. But, I've been thinking about how best to change the REST plugin to deliver all the BB content without an ID. Right now, I'm not sure of the best way to go though. As you can imagine those responses might get _really_ large...

Also - apologies. I seem to not be getting notifications on this issue. I'll check back more regularly.

Right, big responses aren't the problem as this is done at build time so we can wait for that to finish - we already get one big response to fetch all posts/pages/any custom post types. It seems that linked rest plugin just returns generated html, css and js which probably won't fit nicely with gatsby though.

Ok. That all makes sense. I was trying to see if I could come up with a way to let someone build/design a page with BB and still use gatsby to handle the output. Maybe gatsby's the wrong platform for that sort of approach, but it was worth a shot! :-) Plus it was definitely instructive to learn more about how gatsby pulls WP data into graphql.

I think it's still viable option to use wordpress + beaver builder and gatsby. Just plugin that expose beaver builder data in rest api would need to return data about beaver rows / columns / modules and not output generated by beaver. It would be up to gatsby project to render dom from raw beaver builder input. It's pretty big undertaking but it's doable. Unless beaver builder changed very much since last time I used it (2 years ago) :)

I don't think the core of the project has changed too much. They just released a 2.x version and it seems _very_ similar in most regards to 1.x. I'll look into some other choices for how to do the same thing. Since this is pretty much an experiment for me right now, my timeline's pretty broad. :-) Thanks for the help!

This issue is being closed because there hasn't been any activity for at least 30 days. Feel free to open a new one if you still experience this problem 👍

Let's give folks a chance to respond on old issues before closing them out. Something like this should do it:

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications we're clearing out old issues as many of them have already been resolved with the latest updates.

Please make sure to update to the latest Gatsby version and check if that solves the issue. Let us know if that works for you by adding a comment 👍

We're experiencing this issue too. Would be fantastic if we could create our own endpoints that would be correctly parsed by this plugin.

Got it working! After some light debugging of the plugin we discovered one of the normalisers was excluding responses that didn't include a wordpress_id key in the post object. Simply adding this to our custom endpoint responses resolved the issue.

Can you go into detail how you added wordpress_id? I'm trying to get some custom endpoints to show up in the GraphQL and having some problems.

@jcnh74 We added a wordpress_id key to every post object that our custom endpoint returned. Something along the lines of $data['wordpress_id'] = $post->ID; assuming $data is the object you're returning.

@studiopda Thanks. I have a really custom endpoint that's not returning Post Objects rather details of my ACF. Something like this. /wp-json/acf/v2/fields. I thought that it would follow this conventions from the gatsby-wordpress-source Readme:

{
  allWordpress${Manufacturer}${Endpoint} {
    edges {
      node {
        id
       type
        // Put your fields here
      }
    }
  }
}

Where the ${Manufacturer} would be "Acf" and the ${Endpoint} would be my custom "Fields"?
Has anyone successfully got this to show up in GraphQL?

Thanks for your time.

@jcnh74 The wordpress_id key simply needs to return a number (doesn't need to correspond to an actual post ID to bypass this bug). Adding $data['wordpress_id'] = 1; to your endpoint should fix your issue. FYI you should also use the GraphiQL (available at: http://localhost:8000/___graphql) to inspect your modal.

@studiopda Thanks you so much! I was able to get it to show up in the GraphiQL

No worries @jcnh74. Glad you got it sorted 👍

@studiopda This is not a bug but a feature. Each node needs to have its very own ID as per GatsbyJS GraphQL implementation. This may not be the case in v2 RC. Try it out!

The discussion in this thread is super informative and has really helped me out a lot just now. Thank you to everyone who posted here! You've saved me weeks! ❤️

Thanks @hensmith ! Always nice to read positive comments 👍

@pieh absolutely! I'm using this (unsupported/undocumented) REST plugin one of the beaver builder devs wrote. https://github.com/Pross/bb-rest. It definitely works "as is". I can get responses back from postman that are what I expect at each route.

In my initial tests I had just changed the name of the endpoint from fl-builder to flbuilder. Then I was working at things from the gatsby side. But, I've been thinking about how best to change the REST plugin to deliver all the BB content without an ID. Right now, I'm not sure of the best way to go though. As you can imagine those responses might get _really_ large...

Also - apologies. I seem to not be getting notifications on this issue. I'll check back more regularly.

@aberkow were you able to read in the BB API data to the GraphQL? I have added it to the Routes but I think I need to modify the gatsby-wordpress-source plugin

Was this page helpful?
0 / 5 - 0 ratings

Related issues

KyleAMathews picture KyleAMathews  ·  3Comments

kalinchernev picture kalinchernev  ·  3Comments

andykais picture andykais  ·  3Comments

magicly picture magicly  ·  3Comments

timbrandin picture timbrandin  ·  3Comments