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?
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.
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.
(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.
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."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With