Generating a REST API from a GraphQL Schema
Tags: api, rest, graphql
Published: 2019-04-04 11:17:57

---
title: Generating a REST API from a GraphQL Schema
published: true
tags: api, rest, graphql
cover_image: https://thepracticaldev.s3.amazonaws.com/i/j170aw2gsrva050dnva5.jpg
canonical_url: https://www.moesif.com/blog/technical/graphql/Generating-Rest-APIs-from-GraphQl-Schemas/
---

*[Cover image by Alexandra on Flickr](https://www.flickr.com/photos/38093695@N06/)*

Arguing about technology choices is a huge thing, [the RESTFul and GraphQL debate is an example](https://www.moesif.com/blog/technical/graphql/REST-vs-GraphQL-APIs-the-good-the-bad-the-ugly/). But sometimes there methods to unite the different ways. [Sofa](https://sofa-api.com/) is one of them that tries to united REST and GraphQL.

## Why

[REST](https://en.wikipedia.org/wiki/Representational_state_transfer) and [GraphQL](https://graphql.org/) are different approaches to build HTTP based APIs, but the opinions on which is best suited for a problem differ from developer to developer.

I don't know if one of them is superior to the other, but sometimes it can be a dealbreaker if we only provide one type of API to our customers.

Sofa allows us to automatically generate a REST API from a GraphQL schema so that we don't have to implement two APIs on our own.

## What

[Sofa](https://sofa-api.com/) is a [Node.js](https://nodejs.org/en/) package that takes a [GraphQL schema](https://graphql.org/learn/schema/) definition and creates an [Express middleware](https://expressjs.com/en/guide/using-middleware.html) from it. This middleware provides REST-API endpoints.

## How

Let's set up a small API server with the help of Sofa, GraphQL, and Express and then try to create and read messages from it.

### Implementation

First, we use npm to init a new Node.js project and install the packages.

```
$ mkdir api-server
$ cd api-server
$ npm init
$ npm i express express-graphql graphql-tools sofa-api
```

Next, we create a GraphQl schema in a new `schema.gql` file.

```graphql
type Message {
  id: ID!
  text: String!
}

type Query {
  message(id: ID!): Message
  messages: [Message!]
}

type Mutation {
  writeMessage(title: String!): Message
}

schema {
  query: Query
  mutation: Mutation
}
```

We only have a `Message` type and the corresponding types for queries and mutations.

We also need to define resolvers for each query and mutation. Let's create a new `resolver.js` file for this.

```javascript
const messages = [];

module.exports = {
  Query: {
    message: (_, { id }) => messages[id],
    messages: () => messages
  },
  Mutation: {
    writeMessage: (_, { text }) => {
      const message = { id: messages.length, text };
      messages.push(message);
      return message;
    }
  }
};
```

We use the `message` array as the data-store and its `length` to generate IDs for our messages. This will be enough since we don't have a delete mutation that could mess up the IDs.

Now, we wire that schema up with GraphQL and Sofa. We do this in a new `index.js` file.

```javascript
const fs = require("fs");
const { makeExecutableSchema } = require("graphql-tools");
const express = require("express");
const graphql = require("express-graphql");
const sofa = require("sofa-api").default;

const typeDefs = fs.readFileSync("./typeDefs.gql", "utf8");
const resolvers = require("./resolvers");

const schema = makeExecutableSchema({ typeDefs, resolvers });

const server = express();

server.use("/graphql", graphql({ schema, graphiql: true }));
server.use("/rest", sofa({ schema }));

server.listen("9999");
```

Let's go through the critical parts of this file.

First, we read the GraphQL type definition from disk and require the corresponding resolvers.

We then use the `graphql-tools` to create a schema from the resolvers and the type definition.

After that, we create an Express server and set the middlewares for the two endpoints, `/graphql` and `/rest`.

We also enable `graphiql`, the default GraphQL UI so that we can test the GraphQL endpoint in the browser.

Finally, we start a server on port `9999`.

### Usage

Let's start the server.

```
$ node .
```

And open Graphiql in the browser: [localhost:9999/graphql](http://localhost:9999/graphql)

In the text-area on the left, we can now input Queries and mutations. Let's start with a mutation since our store is empty at the moment.

```graphql
mutation {
  writeMessage(text: "my messsage") {
    id
    text
  }
}
```

We can send the message to the server with _Ctrl+Enter_.

The answer should be as following:

```json
{
  "data": {
    "writeMessage": {
      "id": "0",
      "text": "my messsage"
    }
  }
}
```

Let's do this again with a different text, to see if the IDs get counted up as expected:

```graphql
mutation {
  writeMessage(text: "another message") {
    id
    text
  }
}
```

The returned JSON should reflect the new `text` and `id`.

Let's try the queries.

First load all messages:

```graphql
query {
  messages {
    id
    text
  }
}
```

This should deliver JSON with a list of all of our messages.

Only one query missing: `message`

This time we need to provide the ID of the message we want to load.

```graphql
query {
  message(id: 1) {
    id
    text
  }
}
```

We now know that the GraphQL API works as expected, let's try the REST version.

The mutation works via a POST request; this can be done with cURL.

```
$ curl --header "Content-Type: application/json" \
  --request POST \
  --data '{"text":"REST message"}' \
  http://localhost:9999/rest/add-message
```

The queries work with GET requests so that we can use a simple link in the browser.

Listing all messages:

[localhost:9999/rest/messages](http://localhost:9999/rest/messages)

Getting one message:

[localhost:9999/rest/message/2](http://localhost:9999/rest/message/2)

## Conclusion

Sofa is certainly an interesting solution to the _REST <-> GraphQL_ divide. It leverages the fact that GraphQL requires a standardized schema and resolvers to map many concepts back to REST APIs.

This allows API creators to provide their customers with different API types while only having to maintain one code-base.

**Moesif is the most advanced API Analytics platform, supporting REST, GraphQL, Web3 JSON-RPC and more. Thousands of API developers process billions of API calls through Moesif for debugging, monitoring and discovering insights. [Learn More](https://www.moesif.com/?int_source=blog)**

---

*Originally published at [www.moesif.com](https://www.moesif.com/blog/technical/graphql/Generating-Rest-APIs-from-GraphQl-Schemas/).*