Turn your Node.js REST API to GraphQL using Hasura Actions
Tags: node, rest, graphql, hasura
Published: 2020-07-15 15:09:30

---
title: Turn your Node.js REST API to GraphQL using Hasura Actions
published: true
date: 2020-07-14 12:25:01 UTC
tags: nodejs, rest, graphql, hasura
canonical_url: https://hasura.io/blog/turn-your-node-js-rest-api-to-graphql/
---

![](https://hasura.io/blog/content/images/2020/07/Turn-your-Node.js-REST-API-to-GraphQL-3.png)

In this post, we will look at using [Hasura Actions](https://hasura.io/docs/1.0/graphql/manual/actions/index.html) to convert your Node.js REST API to GraphQL.

Typically writing a GraphQL server from scratch will involve setting up the GraphQL schema, type definitions and wiring it up with the `resolvers` in the language/framework of choice. The hard parts about this server component is the resolver code for someone who is used to writing a REST API with `GET` or `POST` and handling `auth logic` for each type; which becomes complex as the app grows bigger.

[Hasura](https://hasura.io) reduces bulk of this complexity of setting up a GraphQL API from scratch by giving you instant [GraphQL](https://hasura.io/graphql/) CRUD for databases (currently Postgres) which should cover most of the data fetching and realtime subscription use cases.

In case of custom business logic, Hasura lets you extend the Graph through different ways. If you are comfortable writing GraphQL servers, you can totally add a custom GraphQL server as a `Remote Schema` and Hasura merges it automatically for you. In case you are looking to write a new or keep your existing REST API for the custom logic, you can do so using `Actions` which is what we will focus in this post.

## Actions

[Actions](https://hasura.io/docs/1.0/graphql/manual/actions/index.html) are a way to extend Hasura’s schema with custom business logic using custom queries and mutations. Actions can be added to Hasura to handle various use cases such as data validation, data enrichment from external sources and any other complex business logic.

![Hasura Actions](https://graphql-engine-cdn.hasura.io/console/assets/common/img/actions.png)<figcaption>Hasura Actions Architecture</figcaption>

An action can be either a query or a mutation. We will look at how to implement both.

## New REST API

In case you are starting from scratch, we will define the GraphQL types required for the Action and create a simple Express app to handle the resolver bit. Let's take the example of registering a user.

Before we begin, let's create a project on [Hasura Cloud](https://hasura.io/cloud/) to setup the Action. Click on the Deploy to Hasura button below, signup for free and create a new project.

<!--kg-card-begin: html-->[![](https://camo.githubusercontent.com/a6de317cd7d0ed4e8722684b428f72e3da614fe8/68747470733a2f2f6772617068716c2d656e67696e652d63646e2e6861737572612e696f2f696d672f6465706c6f795f746f5f6861737572612e706e67)](https://cloud.hasura.io)<!--kg-card-end: html-->

Hasura requires a Postgres database to start with. We can make use of Heroku's free Postgres database tier to try this app.

![](https://hasura.io/blog/content/images/2020/07/create-project-heroku1.png)

After signing in with Heroku, you should see the option to Create project.

![](https://hasura.io/blog/content/images/2020/07/Screenshot-2020-07-14-at-3.28.18-PM.png)<figcaption>Create a new project on Hasura Cloud</figcaption>

Once you are done creating the project, click on `Launch the Console` button on the [Projects](https://cloud.hasura.io/projects) page for the newly created project and the Hasura Console should be visible. By creating this project, you have already got a GraphQL endpoint for the Postgres database that is globally available, secure and scalable from the beginning.

Now let's head to the `Actions` tab on the Hasura Console and define the GraphQL types for our app.

![](https://hasura.io/blog/content/images/2020/07/Screenshot-2020-07-14-at-3.33.38-PM.png)<figcaption>Action Definition</figcaption>

Here we are defining the Mutation type `registerUser` which accepts the `name`, `email` and `password` arguments and returns the `id` of the user.

We can configure the handler URL later. Click on `Create` to create the Action.

Now let's verify the generated GraphQL mutation by trying out the sample mutation in GraphiQL.

```
mutation {
  registerUser(name: "Praveen", email: "praveen@hasura.io", password: "mysecretpassword") {
    id
  }
}
```

The above mutation should obviously give a `http` exception since the Handler URL has not been configured yet. But this test is to verify that Hasura generates mutations for you based on the types defined to query on the same GraphQL endpoint.

![](https://hasura.io/blog/content/images/2020/07/Screenshot-2020-07-14-at-3.53.23-PM.png)<figcaption>Try out generated mutation in GraphiQL</figcaption>

Now let's go ahead and actually define the Node.js app and try out the mutation.

### Codegen: Auto generate boilerplate code

Now head over to the Codegen tab to autogenerate the boilerplate code for your nodejs-express server. Since we are generating the API from scratch, we need the full server setup instead of just the `POST` handler.

![](https://hasura.io/blog/content/images/2020/07/Screenshot-2020-07-14-at-3.35.28-PM.png)<figcaption>Codegen for Node.js REST API</figcaption>

The console gives you options to generate code for different frameworks including but not limited to `nodejs-express`, `nodejs-zeit`, `nodejs-azure-function` etc.

Let's quickly deploy the nodejs-express app to Glitch so that we can add this request handler to the server. Click on `Try on Glitch` to remix an express app on Glitch.

Once you are done, add the generated action handler code from the Codegen tab to the `server.js` file. Finally we need to update our handler URL for the Action so that the HTTP call works.

Capture the Glitch URL which will look something like this [`https://stealth-puddle-cowl.glitch.me/`](https://stealth-puddle-cowl.glitch.me/) and add the `registerUser` endpoint that handles the mutation. So the final handler URL will look like `https://stealth-puddle-cowl.glitch.me/registerUser`.

Go back to the Modify tab of the `registerUser` Action that was created on the Hasura Console. Update the handler URL to the above one.

Finally let's try out the same mutation through GraphiQL and the connection should work returning a dummy <value> for `id`.

![](https://hasura.io/blog/content/images/2020/07/Screenshot-2020-07-14-at-4.42.06-PM.png)<figcaption>Mutation with Action Handler Configured</figcaption>

Alright! We have a working GraphQL API that is resolved using a Node.js REST API in the background.

Now you can modify your handler code as required to do any business logic; like connecting to a different API, connecting to a database (preferrably using Hasura's APIs) or using an ORM for a different databases etc. Hasura will take care of proxying the GraphQL mutation to the right REST API handler internally.

## Permissions

What about permissions? Who will be able to make this GraphQL mutation from the client? Right now, it is configured to be admin only. We can configure roles to allow other kind of users to perform this mutation.

![](https://hasura.io/blog/content/images/2020/07/Screenshot-2020-07-14-at-4.46.37-PM.png)<figcaption>Permission for Action</figcaption>

In the above example, I have created a role called `public` that is allowed to make this mutation. To read more about how the whole [Authentication and Authorization](https://hasura.io/docs/1.0/graphql/manual/auth/index.html) works with Hasura, you can checkout the docs.

## Relationship Data

Now consider that the Postgres database has `users` table. We can connect the `id` of the `registerUser` output to the `id` of the users table.

![](https://hasura.io/blog/content/images/2020/07/Screenshot-2020-07-14-at-4.54.02-PM.png)<figcaption>Relationships for Action Type to Database Table</figcaption>

The related data also conforms to the permissions defined for the respective table. (ie. users)

## Existing REST API

Now you might be wondering what if I already have a Node.js server with a bunch of endpoints written to handle some custom business logic. In that case, as long as it's a `POST` endpoint, you can just define the necessary GraphQL types and make some modifications to the way you handle request body to get it working quickly.

The request payload is of the format:

```
{
  "action": {
    "name": "<action-name>"
  },
  "input": {
    "arg1": "<value>",
    "arg2": "<value>"
  },
  "session_variables": {
    "x-hasura-user-id": "<session-user-id>",
    "x-hasura-role": "<session-user-role>"
  }
}
```

So in our example, the input arguments - name, email and password was wrapped inside an `input` object. Now if you can make necessary modifications to your existing REST API to handle this request body, your GraphQL API will work as expected :)

## Query Action

The above example showcased how to perform a GraphQL mutation. The same workflow can be extended to perform a GraphQL query which proxies to a Node.js REST API in the background. Typical use cases for query actions include computed fields, data enrichment, data transformations, fetching from multiple databases and API sources etc.

## Supported Frameworks

The REST API can be in any framework like Express.js, Next.js or serverless functions. After all, Hasura just requires a reachable POST endpoint that it can forward the query to. In case you are going to deploy the API to a serverless function, you will need to follow the format of the cloud provider.

For example, Next.js has API routes which can be deployed as serverless functions and each API route follows a format. Here's a quick example following the [Next.js function](https://github.com/hasura/hasura-actions-examples/tree/master/image-resize/functions/nextjs-api-routes) format and can be deployed to Vercel.

### Examples

Head over to [hasura-actions-examples](https://github.com/hasura/hasura-actions-examples) for more practical real world use cases like validations, payments, emails etc where a Node.js REST API was used to convert to GraphQL using Actions.

We have a [Youtube Playlist](https://www.youtube.com/playlist?list=PLTRTpHrUcSB9e9m43VKDrO0UBDQfZmW90) with a bunch of examples going over writing out a REST API in Node.js to be used via Actions. You can also check them out.

## FAQ

- How do I protect my action endpoint from being called directly?

Though the Action Endpoint is not visible to the public, it is a good practice to use a secret that can be forwarded from Hasura through headers to identify if Hasura is making the request. If not, you can reject the request with a 401 unauthorized.

- What's the best way to deploy my REST API?

Your Node.js API can be deployed on any cloud provider. If it's an express.js app, you can write multiple action endpoints using the same app and deploy one server or compose them individually into serverless functions which can be deployed on Vercel / AWS Lambda and so on. Hasura just needs a HTTP POST endpoint for each Action handler.

- Can I connect to the database inside my Node.js handler?

You can connect to the database and perform any operations. The easier way to perform read and writes to the database is to use the auto-generated GraphQL API of Hasura inside the handler. By making use of `Admin Secret` you can perform any query from the backend.

- Can I use a CLI to generate the action boilerplate code and not use the UI?

Of course! You can make use of the Hasura CLI to generate an action handler that clones the boilerplate code from the framework you choose, all from your commandline inside your Hasura project.