Building Instant RESTFul API's with MongoDB and RESTHeart

Published

When you need to turn your Mongo database into a RESTFul API, RESTHeart can get you up-and-running quickly. In this article, we'll explore using RESTHeart to expose a RESTFUL API directly from a Mongo database on Compose.

Setup

Before we get started, we'll need to set up a few basic services. You can create a new MongoDB deployment on Compose by following the rough guide to composing. You'll also need to install Docker for your platform. If you're using macOS or Windows, the best way to get Docker is by installing the Docker Toolbox. On Linux, all major distributions have a package available in their package management systems.

Once you have a new MongoDB deployment on Compose, you'll need to add a database to your deployment to serve your RestHEART API. Create a new database called restheart through the MongoDB browser.

Then, create a user for the restheart database by clicking on the database in the Compose browser, selecting the Users menu and clicking the Add User button.

Running RESTHeart in Docker

RESTHeart can be run in a number of ways, but the easiest is to get use the Docker container. You can get started by pulling the RESTHeart container from the Docker Hub central container repository using the docker pull command:

docker pull softinstigate/restheart  

RestHEART uses YAML files to store configuration information so we'll need to create one to point to our new Mongo database. The default configuration file is stored in a file called restheart.yml in the /opt/restheart/etc directory of the container and assumes that you're running MongoDB in another docker container on your local machine with the name of mongodb. We'll need to update the configuration to point to our Compose MongoDB deployment. The easiest way to update those is to mount our own configuration in place of the default by using Docker Volumes.

First, let's create a new directory for our RESTHeart project. Then, create a directory within it called etc.

mkdir restheart  
cd restheart  
mkdir etc  
cd etc  

Next, copy the sample configuration file into the etc folder in a new file called restheart.yml. There are a few key differences between our sample file and the default configuration file in the docker container. Namely, we're going to point our database to Mongo on compose rather than a local Mongo URI. Search the restheart.yml file for the mongo-uri key and replace the value with the MongoDB connection string from Compose:

mongo-uri: mongodb://dbuser:secret@aws-us-east-1-portal.8.dblayer.com:15234,aws-us-east-1-portal.7.dblayer.com:15234/?authSource=restheart  

The ?authSource at the end of the URI is important: it allows us to connect to MongoDB with the user credentials from our newly created database (in this case, our restheart database). This also has the effect of scoping RestHEART so it only has access to a single database that we allow. While you can configure RESTHeart to have root access to your database, it's not recommended.

Next, we'll need to run the Docker container and tell RestHEART to use our updated configuration file. Since we can't pass in the configuration file to the docker container, we'll instead use the volume mounting capabilities of Docker to mount our configuration file (or, in our case, the entire configuration folder) in the same location as the default one. RESTHeart will automatically load our new configuration file from this location. We'll do this by running the container with a local read-only volume pointing to our new etc folder using the following command:

docker run -d -p 80:8080 --name restheart -v $PWD/etc:/opt/restheart/etc:ro softinstigate/restheart:3.0.0  

Note that this command assumes you're in root directory of your project. You can reference the container later using the name restheart. For example, to stop the container, use the following command:

docker stop restheart  

Once the container is running, you can access it by navigating to http://localhost/browser in your web browser. RESTHeart comes pre-installed with the HAL data browser, which makes verifying the installation easier.

Basic Operations

Once we have a running container with RestHEART, we can now test our new RESTful API by making an HTTP GET call to localhost.

$ curl http://localhost
{"http status code":403,"http status description":"Forbidden","message":"The MongoDB user does not have enough permissions to execute this operation."}

Initially, you will get a response with a 403 Forbidden status code. This is the desired result right now - it means that we have not given RESTHeart credentials that work on the root of our database deployment. Since we want to scope access to a specific database, we'll include the database name at the end of the URI.

$ curl http://localhost/restheart
{"_embedded":[],"_id":"restheart","_size":0,"_total_pages":0,"_returned":0}

You should now get a message back indicating that the query was executed and that there were no results. That's because our database is currently empty. Let's try adding some data to a collection in the restheart database.

Adding a Collection

Now that we have RESTHeart running successfully, let's put a document in our restheart database. RESTHeart uses the POST HTTP method to create new documents in the database. Let's try this out by creating a movies collection and adding some of our favorite movies to it.

First, we'll create the movies collection inside our restheart database. All operations in RESTHeart are based on RESTful API calls, so creating a new document, collection, or even new databases will all consist of making HTTP calls. RESTHeart exposes the interface for adding new collections through the PUT method on the collection:

$ curl -i -H "Content-Type: application/json" -X PUT http://localhost/restheart/movies -d '{"desc": "These are some of my favorite movies"}'

RESTHeart expects to receive data in JSON format, so we first set the Content-Type to application/json. Then, we specify the PUT method and send along the collection we wish to add. Note that the URL format for our RESTHeart instance takes the following form:

http://localhost/<database>/<collection>

where <database> is the name of the database you want to operate on and <collection> is the name of the collection.

This structure can be used to retrieve data from specific locations as well. For example, to retrieve all of the collections in our restheart database, let's make a GET call to the database URL:

$ curl http://localhost/restheart
{"_embedded":[{"_id":"movies","desc":"These are some of my favorite movies","_etag":{"$oid":"588734a946e0fb000a6e8827"}}],"_id":"restheart","_size":1,"_total_pages":1,"_returned":1}

Notice how this output is different from the first time we make this call. The newly added movies collection can now be seen in the list of collections.

Using POST to Create a New Document

Following this logic, we can add a new movie to our movies collection by using the same URL scheme. To create a new document in RESTHeart, we'll send an HTTP POST call to RESTHeart and specify which collection to put the data in by using the URL. In our case, the URL looks like the following:

http://localhost/restheart/movies  

So if we wanted to add "Gone with the Wind" to our movies collection, the request would look something like the following:

$ curl -i -H "Content-Type: application/json" -X POST http://localhost/restheart/movies -d '{"title":"Gone With the Wind", "year": "MongoDB"}'

We can test that our insertion worked by sending a GET request to the same URL to list all of the documents in a collection:

$ curl http://localhost/restheart/movies
{"_embedded":[{"_id":{"$oid":"5887875ed4cf043f4cdcdf8b"},"_etag":{"$oid":"588736fc46e0fb000a6e8829"},"title":"Gone With the Wind","year":"MongoDB"}],"_id":"movies","desc":"These are some of my favorite movies","_etag":{"$oid":"588734a946e0fb000a6e8827"},"_returned":1}

Using PUT to Update a Document

Updating a document is similar to inserting a new document, and adds one more layer of specificity by adding the document ID to the URL. To update our favorite movie with a record of Academy Awards, we can use the following:

$ curl -i -H "Content-Type: application/json" -X PUT http://localhost/restheart/movies/5887875ed4cf043f4cdcdf8b -d '{"academy_awards": 10}'

You can also update all the documents in the entire collection by omitting the document id from your URL:

$ curl -i -H "Content-Type: application/json" -X PUT http://localhost/restheart/movies/ -d '{"visible": true}'

Do a GET request again to see the latest changes:

$ curl http://localhost/restheart/movies
{"_embedded":[{"_id":{"$oid":"5887875ed4cf043f4cdcdf8b"},"academy_awards":12,"_etag":{"$oid":"5887387d46e0fb000a6e882b"}}],"_id":"movies","visible":true,"_etag":{"$oid":"588738fd46e0fb000a6e882c"},"_returned":1}

More Operations

RESTHeart has a comprehensive API, but this should get you started with the basics. You can try out more API calls using the CURL utility or gain an in-depth understanding of the RESTHeart API by browsing through the latest documentation.

Conclusion

RESTHeart can be a great way to quickly expose your Mongo database directly as RESTFul API resources. Since the recommended configuration for RESTHeart uses docker containers, it can be especially convenient for teams that use Docker for deploying their applications.

As with any API, you should never expose a running instance of RESTHeart to the open Internet without strong authentication and end-to-end encryption. RESTHeart comes with several ways to configure HTTPS and authentication, and in a future article we'll show you how to secure your RESTHeart API for production. In the meantime, you can find more information on Configuring and Enabling Security in RESTHeart in the official documentation.


If you have any feedback about this or any other Compose article, drop the Compose Articles team a line at articles@compose.com. We're happy to hear from you.

Image by Pixabay User SplitShire
John O'Connor
John O'Connor is a code junky, educator, and amateur dad that loves letting the smoke out of gadgets, turning caffeine into code, and writing about it all. Love this article? Head over to John O'Connor’s author page to keep reading.

Conquer the Data Layer

Spend your time developing apps, not managing databases.