Quick API server for testing

Tue Nov 29 2016 23:59:55 GMT+0100 (Central European Standard Time), Martin Smola

Quick API server for testing

When you need an API server for testing there's Total.js framework to get you up and running in minutes. If You want to know how then keep reading.

  • first of all let's create a folder and install Total.js
$ mkdir apitest
$ cd apitest
$ npm install total.js
  • now let's create index.js which will be the only file we need:
$ touch index.js
  • open the file in your favorite Sublime Text editor :)

Server

First thing we do is setup a server using framework.http:

require('total.js').http('release'); // default port 8000
// require('total.js').http('release', {port: 10000});

The above code can be used as a static file server. If You create a public folder then whatever you place in there will be accessible. e.g. ./public/favicon.ico => localhost:8000/favicon.ico.

Schema

Next we setup a schema and some properties using SchemaBuilder.

NEWSCHEMA('Product').make(function(schema) {

    schema.define('name', String, true);
    schema.define('price', Number, true);
    schema.define('description', String);

    // Query products
    schema.setQuery(function(error, options, callback) {

        // pagination
        options.page = U.parseInt(options.page) - 1;
        options.max = U.parseInt(options.max, 20);

        // if page not specified set it to 0
        if (options.page < 0)
            options.page = 0;

        // number of items to return
        var take = U.parseInt(options.max);

        // number of items to skip
        var skip = U.parseInt(options.page * options.max);

        // NOSQL is total.js embedded database
        // https://docs.totaljs.com/latest/en.html#api~Database
        var filter = NOSQL('products').find();

        filter.take(take);
        filter.skip(skip);

        if(options.sort) filter.sort(options.sort);

        filter.callback(function(err, docs, count) {

            // let's create object which will be returned
            var data = {};
            data.count = count;
            data.items = docs;
            data.limit = options.max;
            data.pages = Math.ceil(data.count / options.max) || 1;
            data.page = options.page + 1;

            callback(data);
        });

    });

    // Get single product by id
    schema.setGet(function(error, model, id, callback) {

        NOSQL('products')
            .one()
            .where('id', id)
            .callback(function(err, product){

                callback({success: !!product, data: product});

            });

    });

    // Save the product into the database
    schema.setSave(function(error, model, options, callback) {

        // if there's no id then it's an insert otherwise update
        var isNew = model.id ? false : true;

        // create id if it's new
        if(isNew) model.id = UID(); //UID returns string such as 16042321110001yfg

        NOSQL('products')
            .upsert(model) // update or insert
            .where('id', model.id)
            .callback(function() {

                callback({success: true, id: model.id});

            });
    });

    // Remove a specific product
    schema.setRemove(function(error, id, callback) {

        NOSQL('products')
            .remove()
            .where('id', id)
            .callback(function(){

                callback({success: true});

            });

    });
});

Routes

Now it's time to create some routes using F.route. In each route we use *Product flag which tells the framework we want to use the schema methods in a controller.

//       URL                  Handler   Flags                    Method
F.route('/api/products',      query,  ['*Product']);          // GET (default)
F.route('/api/products/{id}', get,    ['*Product']);          // GET (default)
F.route('/api/products',      save,   ['*Product', 'post']);  // POST
F.route('/api/products/{id}', remove, ['*Product', 'delete']);// DELETE

Controllers

Since we've specified the *Product flag we can use schema methods such as $get, $query, $save, etc..

function query() {
    // `this` is an instance of Controller
    // https://docs.totaljs.com/latest/en.html#api~FrameworkController
    var self = this;
    // $query is Schema method that we defined using `schema.setQuery(...)`
    self.$query(self.query, self.callback());
    // instead of self.callback you can supply your own callback function
    // self.$query(self.query, function(err, result){
    //      self.json(result);
    // });
}

function get(id) {
    // the id is parsed by framework from url `/api/products/{id}`
    var self = this;
    // $get is Schema method that we defined using `schema.setGet(...)`
    this.$get(id, self.callback());    
}

function save() {
    var self = this;
    // $save is Schema method that we defined using `schema.setSave(...)`
    // the $save method is available on this.body for POST request
    this.body.$save(self.callback());
    // another way to use it is
    // this.$save(this.body, self.callback());

}

function remove(id) {
    var self = this;
    // $remove is Schema method that we defined using `schema.setRemove(...)`
    this.$remove(id, self.callback());
}

Logging requests

Let's add logging for each request so we know what's going on:

F.on('request', function(req, res){
    console.log(`[${req.method}] ${req.url}`); 
    // outputs e.g. `[GET] /api/products`
});

Find the gist here index.js.

Extra

If you want it to work really quickly you can use recently added functionality NOSQL inmemory. Add it just bellow require('total.js').http('release');.

NOSQLMEMORY('products');

This will keep all documents from products collection in memory for quicker access.


Tags

Follow us

Latest blogs
Total.js Wiki v2
Fri Jan 04 2019 22:15:01 GMT+0100 (Central European Standard Time)
Total Year 2018
Thu Jan 03 2019 21:14:00 GMT+0100 (Central European Standard Time)
Total.js Code Editor v1
Fri Dec 07 2018 22:55:13 GMT+0100 (Central European Standard Time)
New release: Total.js v3.1
Fri Dec 07 2018 11:41:40 GMT+0100 (Central European Standard Time)
New CDN for Flow + Dashboard + Flowboard
Sun Nov 04 2018 09:05:03 GMT+0100 (Central European Standard Time)

Latest comments
Nice tip
Mauro Junior
Thu Sep 20 2018 21:41:02 GMT+0200 (Central European Summer Time)
Not only for Total.js. You can communicate with different websocket servers.
Peter Širka
Mon Apr 23 2018 20:08:20 GMT+0200 (Central European Summer Time)
Marko: you need to create a buffer with this codepage and write byte-to-byte string. I recommend ...
Peter Širka
Mon Apr 23 2018 20:06:21 GMT+0200 (Central European Summer Time)
Is WEBSOCKETCLIENT only for internal ws connections between totaljs apps?
Stelios Stephanua
Fri Mar 16 2018 06:04:22 GMT+0100 (Central European Standard Time)
Total.js is amazing! ;)
Leonardo Hessel
Tue Dec 19 2017 19:51:15 GMT+0100 (Central European Standard Time)

Pixabay


Read more

Total.js Wiki v2

Products: I have released a new version of Total.js Wiki. New version brings new improvements.

Fri Jan 04 2019 22:15:01 GMT+0100 (Central European Standard Time)
Total Year 2018

Business: Last year was perfect for Total.js platform. Total.js platform grows up and it has great results.

Thu Jan 03 2019 21:14:00 GMT+0100 (Central European Standard Time)
Total.js Code Editor v1

Products: Try our real-time collaboration tool for Total Developers. Code Editor offers great features for development.

Fri Dec 07 2018 22:55:13 GMT+0100 (Central European Standard Time)
New release: Total.js v3.1

News: I have released a new version of Total.js with bug fixes and with small improvements.

Fri Dec 07 2018 11:41:40 GMT+0100 (Central European Standard Time)
New CDN for Flow + Dashboard + Flowboard

News: I have changed CDN for Flow + Dashboard + Flowboard components to KeyCDN.

Sun Nov 04 2018 09:05:03 GMT+0100 (Central European Standard Time)
OpenPlatform v3

News: I have published a new version of OpenPlatform. New, better, faster, more secure and more simpler.

Mon Oct 15 2018 10:11:07 GMT+0200 (Central European Summer Time)