The marmelab blog

Restful.js: A Framework Agnostic JS Client for RESTful APIs

Published on 10 March 2015 by Robin with tags popular oss

Dealing with RESTful APIs in JavaScript requires a lot of boilerplate code. The client-side primitive for HTTP communication (XMLHttpRequest) is very low level, and doesn’t support anything like a resource, a link, or an entity. A few third-party libraries give a higher level API (for instance, cujojs/rest), but so far we’ve really appreciated the expressivity and speed of Restangular, an Angular.js service that simplifies common GET, POST, DELETE, and UPDATE requests with a minimum of client code. Unfortunately, this library is heavily tied to Angular.js. j We’ve recently invested a lot in ReactJS for frontend development. As for our other developments, we decouple the frontend and backend by relying on RESTful APIs. But out of the AngularJS ecosystem, we couldn’t find a good alternative to Restangular. For that reason, I wrote a proof-of-concept for a standalone RESTful client in pure JavaScript during one of our marmelab hackdays.

But it is only recently that I was able to get some time to really work on it. I strip down the library to make it both powerful and respectful of your data - which is the main drawback of Restangular I think. If you have already used Restangular, you might have noticed that Restangular merges your API response with a lot of custom methods.

Today, my library works nicely and is ready for public release. It is not a proof-of-concept anymore. The library is called restful.js, and it is available on Github.

Let’s see some code written with restful.js:

var restful = require('restful');
var resource = restful('api.example.com', 8080);

resource.all('categories').getAll().then(function(categories) {
    var articlePromises = categories.map(function(category) {
        if (category.status() !== 200) {
            throw new Error('Invalid response');
        }
        category.data(); // will be the data returned by our API
        // category is an entity
        // that means you can chain it with other calls
        return category.one('articles', 2).get();
    });
});

In the above example, we target the categories collection. For each category retrieved from the /categories endpoint, we return the promise targeting its second article.

When you get an entity, to avoid confusion between the methods from restful.js and your API response, the response is one method call away.

I invite you to read the README on Github for a deeper dive into examples and usage.

Before leaving you with restful.js, let’s look at a simple ReactJS component dealing with a RESTful API:

 var CategoryCollection = React.createClass({
    loadCategoriesFromServer: function() {
        var self = this;

        restful('api.example.com', 8080)
            .all('categories')
            .getAll()
            .then(function(categories) {
                self.setState({
                    categories: categories
                });
            });
    },
                
    getInitialState: function() {
        return { categories: [] };
    },

    componentDidMount: function() {
        this.loadCategoriesFromServer();
    },
    
    render: function() {
        var self = this;
        var categories  = this.state.categories.map(function(category) {
            var data = category.data();

            return <li key={data.id}>{data.title}</li>;
        });

        return (
            <ul>
                {categories}
            </ul>
        );
    }
});

Each time this component is mounted, it fetches all categories, and displays them in a list. As you can see it, the code is pretty simple to write.

Do not hesitate to open issues and to submit pull requests on the Github repository. The project is young and needs real use cases feedback!

comments powered by Disqus