{{announcement.body}}
{{announcement.title}}

REST to GraphQL in Minutes

DZone 's Guide to

REST to GraphQL in Minutes

In this article, see how to accomplish your REST to GraphQL mission without changing your codebase.

· Integration Zone ·
Free Resource

With all the madness currently going in the API world with GraphQL, you might be wondering how to migrate your existing REST APIs to GraphQL without breaking anything. This guide will help you accomplish your REST to GraphQL mission without changing your codebase so that you can REST with GraphQL (pun intended)!

REST to GraphQL

Well, GraphQL advocates have done a great job in marketing GraphQL already. Respecting their efforts, I won’t be going into details, but provide a summary:

  • GraphQL allows you to fetch multiple resources in a single request.
  • GraphQL solves the over fetching problem of REST by letting you describe your exact data needs.
  • GraphQL helps you solve the N+1 query problem on frontend by fetching related data in a single query.

What I will be touching upon in this guide instead is the aspect that most people miss while advocating GraphQL, which is, “We have already invested heavily in REST.” This means:

  • Most of our existing services are in REST
  • We are more comfortable writing REST services
  • We want to support existing clients using REST APIs

While many articles help you migrate from REST to GraphQL, they all force you to change your existing codebase or write a new one in front of your REST services.

You might also ike: Why and When to Use GraphQL

But Wait…

If it works, then don’t touch it.

Wasn’t this the first rule of programming?

Migrations can be painful, especially the magnitude of a huge codebase can be daunting. There is always a chance of breaking something.

Why Can’t We Just REST?

Let’s face the fact, we all are lazy by nature. We love simple hacks and easy solutions.

What if there was a way where you could keep your REST services as is and still get a GraphQL layer on top of it without writing any code whatsoever? Sounds like magic, right? Well, Space Cloud helps make this possible.

What Is Space Cloud?

To keep things simple, Space Cloud is an open-source platform to build, secure and scale your apps. It provides instant GraphQL and REST APIs on your database and microservices.

The coolest part about Space Cloud is that all the APIs are realtime. You can optionally subscribe to changes in the database. This functionality comes in handy while making real-time apps.

However, in this guide, our focus will be on Space Cloud's remote service module to migrate your REST services to GraphQL.

The Architecture

This is what the final architecture of GraphQL over REST looks like:


Your apps make a GraphQL query to Space Cloud, which, in turn, hits a REST endpoint on your server. Space Cloud acts as a GraphQL proxy or API gateway in this case.

As you would have noticed, Space Cloud is a separate GraphQL layer that sits on top of your REST services. The beauty of this fact is that your REST services are still intact, and you can use them directly in your existing clients. This fact lets you ship your REST service to GraphQL without breaking your older clients.

Great! We have understood what Space Cloud is and how it sits with our application. Let’s get straight to some action!

What We Will Be Building

In this guide, we will be building a simple arithmetic service which has the following endpoints:

  • Adder endpoint: POST /adder
  • Doubler endpoint: GET /doubler/:num

The adder endpoint will return the sum of two numbers that it gets from the request body. The doubler endpoint, on the other hand, will return double of the number that it receives as the URL path parameter.

Great! Let’s start building things now!

Note: Don’t worry if you get stuck somewhere. You can always ping me on this Discord server, and I will help you out personally.

Step 1: Writing a Service

Note: Even if you are reading this from your mobile right now, you can still follow this guide along just by reading.

Let’s start by writing our REST service. We are going to write our REST service in NodeJS using Express.

Note: You can write your service in any language or framework as long as it can speak HTTP since that’s the protocol Space Cloud is going to use to communicate with your REST service.

First, create a folder that serves as our working directory.

Create NPM project:

Java
 




xxxxxxxxxx
1


 
1
npm init -y



Install Express:

Java
 




xxxxxxxxxx
1


 
1
npm install --save express



Write express server

Create a file index.js and copy paste the following code:

Java
 




x


 
1
var express = require("express");
2
var app = express();
3
 
          
4
app.use(express.json());
5
 
          
6
app.post("/adder", function(req, res) {
7
  const num1 = req.body.num1;
8
  const num2 = req.body.num2;
9
  const response = { value: num1 + num2 };
10
  res.status(200).send(JSON.stringify(response));
11
});
12
 
          
13
app.get("/doubler/:num", function(req, res) {
14
  const num = Number(req.params.num);
15
  const response = { value: num * 2 };
16
  res.status(200).send(JSON.stringify(response));
17
});
18
 
          
19
var server = app.listen(8080, function () {
20
    console.log("app running on port:", server.address().port);
21
});



As you can see, the code is pretty straight forward. We have just created an HTTP server using ExpressJS that is listening on port 8080.

The server has two endpoints, as we discussed earlier:

  • Adder endpoint: We are expecting to receive two numbers - num1 and num2 from the POST body. All we are doing is returning the sum of these two numbers.
  • Doubler endpoint: We are simply returning the number that we are getting from the URL path parameter.

That’s all we need to write for this service.

Note: For migrating your existing REST services, you don’t need to write/modify any code. And if your services are already running, you can skip the next step.

Step 2: Install Space Cloud

We are using `space-cli` to run Space Cloud for us. 

Download space-cli

space-cli is the cli tool for Space Cloud. You can download a version for your particular platform:

Unzip the compressed archive.

For Linux / Mac: unzip space-cli.zip && chmod +x space-cli

For Windows: Right-click on the archive and select `extract here`.

Copy the space-cli binary to your environment path variable for global usage.

For Linux / Mac: Copy the space-cli to /usr/local/bin. You may have to use sudo depending on the permissions of your /usr/local/bin.

For Windows: Add the path of the space-cli.exe to the environment variable PATH for making space-cli accessible globally.

To make sure if the space-cli binary is installed correctly, type the following command:

For Linux / Mac: space-cli --version

For Windows: space-cli.exe --version 

This prints the space-cli version.

Run Space Cloud

We can set up all Space Cloud components (gateway and runner) via space-cli using a single command.

PowerShell
 




xxxxxxxxxx
1


 
1
space-cli setup --dev



The setup command selects Docker as a target by default and runs all the containers required to setup Space Cloud. On successful installation it generates an output similar to this one:

PowerShell
 




xxxxxxxxxx
1
17


1
INFO[0000] Setting up Space Cloud on docker.            
2
 
          
3
INFO[0000] Fetching latest Space Cloud Version         
4
 
          
5
INFO[0000] Starting container space-cloud-gateway...    
6
 
          
7
INFO[0000] Image spaceuptech/gateway:latest already exists. No need to pull it again 
8
 
          
9
INFO[0000] Starting container space-cloud-runner...     
10
 
          
11
INFO[0000] Image spaceuptech/runner:latest already exists. No need to pull it again 
12
 
          
13
INFO[0001] Space Cloud (id: "local-admin") has been successfully setup! �� 
14
 
          
15
INFO[0001] You can visit mission control at http://localhost:4122/mission-control �� 
16
 
          
17
INFO[0001] Your login credentials: [username: "local-admin"; key: "KkYr6FvgYsvr"] ��



Verify Space Cloud installation

Verify the installation by running the following docker command:

PowerShell
 







You should see an output similar to this:

PowerShell
 




xxxxxxxxxx
1


1
CONTAINER ID        IMAGE                        COMMAND             CREATED              STATUS              PORTS                                            NAMES
2
 
          
3
507ce4042486        spaceuptech/runner:latest    "./app start"       About a minute ago   Up About a minute                                                    space-cloud-runner
4
 
          
5
33a5a7a9be3a        spaceuptech/gateway:latest   "./app run"         About a minute ago   Up About a minute   0.0.0.0:4122->4122/tcp, 0.0.0.0:4126->4126/tcp   space-cloud-gateway



Step 3: Configure Space Cloud

If you exec into docker container of Space Cloud's gateway, you can see a config.yaml file generated by the gateway in the /app directory.

Space Cloud needs this config file to function. The config file is used to load various information like which databases to use, their connection strings and security rules. 

Space Cloud has it's own Mission Control (admin UI) to configure all of this quickly. 

Open Mission Control:

Head over to http://localhost:4122/mission-control to open Mission Control.

Replace localhost with the address of your Space Cloud if you are not running it locally.

Create a project:

Click on Create a Project button.

Name your project as MyProject

Hit Create Project button to create the project. 

After creating the project, the next step would be adding a database to your project.

However, we can simply skip this step as we don't need a database for this project.

After that, you would be directed to the overview page of your project.

That's all we need to configure as of now.

Step 4: Deploying the REST service

You can skip this step if you already have a REST service deployed.

Space Cloud can deploy only docker containers as of now. So we need to dockerize our app. We are going to take the help of space-cli to do that.

First of all, we need a docker registry that can host the docker images of our service. Run this command to spin up a docker registry locally:

PowerShell
 




xxxxxxxxxx
1


 
1
space-cli --project myproject add registry



In production, it is recommended to use a managed container registry

Now we need yo generate two files:

  • Dockerfile - To build the docker image.
  • service.yaml - The service configuration (example: resources, auto-scaling, ports) to deploy this service via Space Cloud.

space-cli has a built-in command to generate both of these automatically for us. Just run the following command:

PowerShell
 




xxxxxxxxxx
1


 
1
space-cli deploy --prepare



It is going to ask you a bunch of questions. Answer them with the following required values and leave the rest to default:

Project Id
Service Id
myproject
myapp


Great! We now have a Dockerfile and a service.yaml file. Feel free to explore and change both these files before finally deploying the service. The `service.yaml` file looks something like this:

YAML
 




xxxxxxxxxx
1
75


1
api: /v1/runner/{project}/services/{id}/{version}
2
 
          
3
type: service
4
 
          
5
meta:
6
 
          
7
  id: myapp
8
 
          
9
  project: myproject
10
 
          
11
  version: v1
12
 
          
13
spec:
14
 
          
15
  scale:
16
 
          
17
    replicas: 1
18
 
          
19
    minReplicas: 1
20
 
          
21
    maxReplicas: 100
22
 
          
23
    concurrency: 50
24
 
          
25
    mode: parallel
26
 
          
27
  labels: {}
28
 
          
29
  tasks:
30
 
          
31
  - id: myapp
32
 
          
33
    ports:
34
 
          
35
    - name: http
36
 
          
37
      protocol: http
38
 
          
39
      port: 8080
40
 
          
41
    resources:
42
 
          
43
      cpu: 250
44
 
          
45
      memory: 512
46
 
          
47
    docker:
48
 
          
49
      image: localhost:5000/myproject-myapp:v1
50
 
          
51
      cmd: []
52
 
          
53
      secret: ""
54
 
          
55
      imagePullPolicy: "pull-if-not-exists"
56
 
          
57
    env: {}
58
 
          
59
    secrets: []
60
 
          
61
    runtime: image
62
 
          
63
  affinity: []
64
 
          
65
  whitelists:
66
 
          
67
  - projectId: myproject
68
 
          
69
    service: '*'
70
 
          
71
  upstreams:
72
 
          
73
  - projectId: myproject
74
 
          
75
    service: '*'



The only step left now is building the docker image and deploying it via Space Cloud. 

We are going to use the deploy command of space-cli for that. It first builds a docker image for us using the Dockerfile (generated in the above step) and then publishes it to the docker registry. Once it's done publishing, it uses the config in service.yaml file to deploy the service via Space Cloud.

Enough of talking. Let's hit the magical command now:

PowerShell
 




xxxxxxxxxx
1


 
1
space-cli deploy



You may have to run the above command with sudo privileges if your docker is not in the sudoer group.

Verify the deployment

Checkout to the Overview tab of Deployments section in Mission Control and hit refresh. You should be able to see the service we just deployed.

Expose the service

Currently, the REST service we deployed is accessible from within the cluster only. We need to add Space Cloud Routes to expose our service to the outside world.

Let's head over to the Ingress Routing section under Microservices in Mission Control. 

Hit Create your first route to open the following form:

We'll simply redirect all non Space Cloud traffic to our service for now.

You'll need to provide the following details in the form:

Route Matching Type
Prefix
Prefix Match
/
Scheme
Service Host
Port
Weight
HTTP
myapp.myproject.svc.cluster.local
8080
100

Once you are done, hit Add.

To verify that our REST service is exposed, simply open another tab in your browser and enter:

Java
 




xxxxxxxxxx
1


 
1
http://localhost:4122/doubler/3



You should be able to see the following response on your screen:

JSON
 




xxxxxxxxxx
1


 
1
{
2
  "value": 6
3
}



Great! We have our REST service up and running. The REST endpoints can be consumed by the outside world as well. Time to expose these REST endpoints to GraphQL. (Without writing any extra code whatsoever ��).

Step 5: Add Remote Service to Space Cloud

Head to the GraphQL API section under Microservices in Mission Control.

Click on the Add first remote service button to open the following form:

Put the service name as myapp and service URL as:

http://myapp.myproject.svc.cluster.local:8080

Once you have added the remote service, you should be able to see it in the remote services table.

Click on the View button in the Actions column to open the service page.

Click on the Add first remote endpoint button to open the following form:

Put the following adder endpoint:

  • Name: adder
  • Endpoint type: Internal
  • Method: POST
  • Path: /adder

Once again click on the Add button to add the doubler endpoint as well:

  • Name: doubler
  • Endpoint type: Internal
  • Method: GET
  • Path: /doubler/{args.num}

Note: Don’t worry about the {args.num} part now. Just make sure you have put the Method as GET.

Step 6: Query Your REST Service via GraphQL

We have added our REST service and the two endpoints as well to Space Cloud. Time to query it using our unified GraphQL API.

Head to the Explorer section:

Try running the following GraphQL query in the GraphiQL explorer:

Java
 







You should be able to see a response like this:

Java
 







On getting the above GraphQL query, Space Cloud had made the following request to your REST service:

  • Method: POST
  • Path: /adder
  • Request Body:
Java
 




xxxxxxxxxx
1


 
1
{
2
  "num1": 10,
3
  "num2": 20
4
}



This means the arguments that you pass in the GraphQL query are send as request body to your REST service.

Let’s try querying the doubler endpoint with the following GraphQL query:

Java
 







This GraphQL query is translated by SC to a REST call as follow:

Java
 




xxxxxxxxxx
1


 
1
GET /doubler/50



If you remember the endpoint which we added to Space Cloud for doubler was:

Java
 




xxxxxxxxxx
1


 
1
/doubler/{args.num}



Based on this endpoint, Space Cloud understands that it has to pick an argument num from the GraphQL query and use it as a variable to form the path /doubler/50.

On successful invocation, you should be able to see a response like this:

JSON
 







Bonus — Service Chaining

Having followed this guide till here successfully, we all deserve a well-earned bonus! Let’s see how this REST to GraphQL transition unlocks a super awesome power, Service Chaining, for us.

Let’s take a scenario where:

  • We want to sum two numbers using the adder service.
  • Double the result we got from the adder service.

The REST Way

If we were using REST in our client-side code, the above task would have looked like this:


Notice, how we are making two requests from the frontend which means twice the roundtrip time. It leads to a slow response time and poor user experience.

The GraphQL Way

Now if we switched the client from REST to GraphQL using Space Cloud, our requests will look like this:


Notice, here we are making only one GraphQL query from the frontend to the backend (Space Cloud). Space Cloud, in turn, is making two requests to your REST server to fulfil this request. However, the round trips of these requests (from Space Cloud to your server) are negligible as they are in the same network.

The GraphQL query to Space Cloud to achieve the above task will be:

JSON
 







Notice, how we are calling the doubler service after the response of adder service and passing the result of adder service to the doubler as an argument.

The response for this query will look like this:

JSON
 







As you would have guessed we got 60 as a result ((10 + 20) * 2).

Additional tip: If you wanted to query two unrelated REST services parallelly, you could have done that too in a single request like this:

JSON
 







I will leave the response part of this query to you as an assignment��.

Conclusion

First of all, give yourself a pat on the back for having followed this guide to the end.

We learned that:

  • Migrating from REST to GraphQL doesn’t require code changes.
  • We don’t need to choose between REST and GraphQL. We can support both REST and GraphQL together in the same application.
  • Using GraphQL with Space Cloud provides us with some neat networking benefits and helps you reduce your round trips.

Well, there’s a lot more you can do with Space Cloud other than migrating from REST to GraphQL (eg: cross-database joins). Give Space Cloud a star on Github if you like it. Join our Discord server if you wanna bounce off some ideas or have any questions.

Further Reading

Moving Beyond REST With GraphQL

GraphQL Benefits in a REST API, But How?

Topics:
backend, graphql, programming, rest api, restful services, software engineering, technology

Published at DZone with permission of Noorain Panjwani , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}