Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proxy/convert existing GraphQL API to REST

We have an existing private GraphQL server that powers our React application and would like to possibly expose a subset of the functionality as REST endpoints. This way we do not have to support 2 code bases, one for GraphQL and one for the REST APIs.

How would I take an existing GraphQL server and create a wrapper/proxy layer to expose of the schema as REST endpoints?

like image 871
Greg Svitak Avatar asked Mar 25 '17 18:03

Greg Svitak


People also ask

Can GraphQL TALK TO REST API?

GraphQL can retrieve data on top of or instead of the API management layer, but data can still be submitted through the existing REST APIs.

Can I mix GraphQL and REST?

Yes, this is possible to do. It is possible to have a mix of APIs (GraphQL and REST, for example) in a project and even to share data stores (such as databases) between the various API schema.


2 Answers

(Edit: Someone ended up building a library to do pretty much what I described below! Try it here: https://www.npmjs.com/package/rest-graphql)

I think the best way to do this is not to generate the API from the types in the schema, but to expose specific queries as endpoints. That way, you can return the exact shape of data you want to send to the client. The best part is, GraphQL already has all of the tools you need, including handling for parameters!

So for example you want to create an endpoint:

/posts/1

Let's say you want that to map onto this query:

const postByIdQuery = `
  query postById($postId: Int!) {
    post(id: $postId) {
      title
      description
      author {
        name
      }
    }
  }
`;

Then in your server-side REST API library (for example express), you could do something like:

app.get('/posts/:postId', function (req, res) {
  graphql(
    schema, // same schema as your graphql api
    postByIDQuery, // the query from above
    rootValue, context, // set these same way as for your graphql endpoint
    req.params // use the route params as variables!
  ).then((result) => {
    res.send(result);
  }).catch((error) => {
    // something to handle errors
  });;
})

If you have a lot of endpoints you want to create, I'd make a helper function, something like:

function addEndpointFromQuery(app, path, query) {
  // generates endpoint like the above sample
}

The really neat thing here is that your route params (:postId in this case) just need to match up with your declared query variables ($postId) and then they can be wired together automatically! Then you could simply call your helper function to do the above:

addEndpointFromQuery(app, '/posts/:postId', `
  query postById($postId: Int!) {
    post(id: $postId) {
      title
      description
      author {
        name
      }
    }
  }
`);

If you wanted to, you could also add an extra parameter to transform the results to fit your desired REST response format.

I think someone could build a library to do this, but it feels like it will be pretty specific to the app, with a particular response format, way of generating context, etc. So personally I would suggest writing your own helper like the above, and it could probably be done in less than 50 lines of code.

like image 193
stubailo Avatar answered Oct 21 '22 05:10

stubailo


Check out this package (graphql2rest): https://github.com/sisense/graphql2rest

You can use it to automatically generate a REST API from your existing GraphQL API - just what you need.

"GraphQL2REST is a Node.js library that reads your GraphQL schema and a user-provided manifest file and automatically generates an Express router with fully RESTful HTTP routes — a full-fledged REST API."

like image 36
bravo2020 Avatar answered Oct 21 '22 05:10

bravo2020