alchimya / DoYouREST

A ready to use project to develop your REST API under NodeJS.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

DoYouREST

A ready to use project to develop your REST API under NodeJS.

What is this?

You can see this project as a template to develop RESTful services using the NodeJS ecosystem.
In a very easy way (through a JSON config file) you can configure:

  • Server variables such as: listening port, API routing path, clustering behaviour, headers.
  • Database variables such as: login and host params, connenciton pool, enable/disable.
  • Authentication mode: you can choose to enable/disable the authentication and you can setup it through JSON Web Token or basic-auth.
  • Socket.io: you can enable/disable this feature, that allows to implement a real-time behaviour

Basically, this project has been developed around the following Node modules:



This package also includes different test client solutions for the following environments:
  • iOS
  • Android
  • AngularJS
  • jQuery
  • PHP (TODO)
  • .NET Client (as a WPF solution)

How to install

  • cd DoYouREST/server
  • sudo npm install

Server Project Structure

——> app
—————> config
—————> controllers
—————> helpers
—————> security
———————> basicauth
———————> jwt
—————> sequelize
—————> models
—————> spec
———————> config
———————> security

where:

  • config: contains the config file and its “driver” class
  • controllers:contains all the API modules
  • helpers: contains some helper classes
  • basicauth: middleware for the basic-auth
  • jwt: middleware for the JSON Web Token authentication
  • sequelize: contains the main class to manage the db connection
  • models: put here all your sequelize models
  • spec: contain all the jasmine tests

Configuration

All the configuration settings listed below are included within the file /Config/appconfig.json

  1. Server Configuration
    Use this configuration to setup the server settings.
    You can find these information under the object server as follow:
"server":{
    "port":8080,
    "apiRoute":"/api",
    "isCluster":true,
    "headers":[
      {"name":"Access-Control-Allow-Origin","value":"*"},
      {"name":"Access-Control-Allow-Headers","value":"Origin, X-Requested-With, Content-Type, Accept"},
      {"name":"Access-Control-Allow-Methods","value":"GET,PUT,POST,DELETE,OPTIONS"}
    ]

where:

  • port: is the port where the server is listening
  • apiRoute: is the base routing path to access to the api (eg http://localhost:8080/api/customers)
  • isCluster: by setting this value to true the Node app will be clustered and you will take advantage of multi-core systems (here a good tutorial about the node clustering http://stackabuse.com/setting-up-a-node-js-cluster/ and here the official documentation https://nodejs.org/api/cluster.html).
  • headers:put here all the response headers that you want to use, for example to enable the cross-origin resource sharing.
  1. Database Configuration

Within the scripts folder of this package, you can find the DoYouRest.sql file, that allows to create a test database. If you will setup the doyourest database into your MySql environment, you will be able to use the test api included into the api-sequelize-test,js module (/sequelize/customers and /sequelize/customers/id).
Use this configuration to setup the MySql settings.
You can find these information under the object database as follow:
"database":{
    "name":"doyourest",
    "user":"your_mysql_user",
    "password":"your_mysql_password",
    "host":"localhost",
    "port":3306,
    "connectionPool":100,
    "isEnabled":true,
    "type":0
  }

where:

  • name: the name of your database
  • user: the user name to login into you database
  • password: the password to login into you database
  • host: the host of your MySql instance
  • port:listening port of your MySql
  • connectionPool:setup here the conneciton pool (if you are not familiar with conenciton pool see here https://en.wikipedia.org/wiki/Connection_pool)
  • isEnabled: set this param to false if you don't want to use and to connect to the database.
  • type: 0 to enable sequelize as database engine, 1 to use mysql module driver. If you want to extend the database capabilities, you can add a different database driver (e.g. mssql for SQL Server), add a new member enum (database-enums.js) and manage it with a custom class. As examples see the mysql-driver.js and sequelize-driver.js classes.
  1. Auth Configuration
    Use this configuration to specify the kind of authentication that you want to use (basich-auth or JSON Web Token) and to enable/disable this behaviour.
    You can find this information under the object authentication as follow:
"authentication":{
    "isEnabled":true,
    "type":1,
    "expirationToken":1440,
    "jwt":{
      "cryptography":1,
      "symmetricKey":"my_super_top_secret_key!!!",
      "asymmetricPivateKey":"./security/private.key",
      "asymmetricPublicKey":"./security/public.pem"
    }
  }

where:

  • isEnabled: enable/disable the authentication for all http request
  • type: 0 to enable the basic-authentication, 1 for the JSON Web Token.
  • expirationToken: use this param (minutes) to limit the lifetime of the token
  • jwt.cryptography: represents the kind of cryptography that you want to use for the token: 0 for a symmetric cryptography with a key, 1 to use a cryptography based on a public/private key pair.
  • jwt.symmetricKey:key used encrypt/decrypt the token.
  • jwt.asymmetricPivateKey: a private key to sign the token with the RS256 algorithm
  • jwt.asymmetricPublicKey: a public key used to decrypt the token.

For this purpose, the user list granted to access, are stored into the configuration file (./security/securityusers.json), but is intended that you can use a different approach.
To do this you need to customize the AuthUser() class (./security/security-users.js).
If you enable the JSON Web Token, before each request you have to obtain a token (http://yourserver:port/token) and then you have to send it (as a JSON boby, request params or x-access-token) for each API request.

ScreenShot


To request a token you have to send a POST with a JSON body with an user name and a password as folow: ```javascript { "uid":"my_uid_1", "pwd":"my_pwd_1" } ``` As response you will recevive a JSON body as follow:
{
  "success": true,
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1c2VybmFtZSI6Im15X3VpZF8xIiwicGFzc3dvcmQiOiJteV9wd2RfMSIsImlhdCI6MTQ1MzY2MTkyM30.M4yuuEsrruQgOcRdgFgDS5ohBvq38Gnd5fVJQYiKs6inQzQLqMYfECjokM-MH0uNc7vpuSKUVt1uzQKd478taLlOZFxkLphKaSXezDTu9TpLPk8FXuosel-rYfSSTgJKF4YPIo9raCEBueScA7p3YIS6-ySF-cyPVb8JZicE6WKIYQ4xICB4QeTa2YxTB4sCVEFsIhOiroAtifAphlBaMd0uF1A5w7iGcw0v9hc4nvT6fDEdqIf_4oVrIjt9dhu0JGJ1PTZ_2A91aVCei3jodNLmQr72UB9B339qppM3UuSVzXkj81PxIN-UJbRqMDEYXKM_YODEf2I0d4-2aTaWwg"
}

For further details see the clients included with this package.

  1. Socket.io Configuration
    Use this configuration to setup the socket.io settings.
    You can find these information under the object socketio as follow:
"socketio":{
    "isEnabled":true
  }

where:

  • isEnabled: enable/disable the socket.io behaviour.

Why did I use Socket.io for RESTFul web services?
Well, I think that it should be useful to implement a real-time communication with other "actors" in a more complex architecture.
Imagine a similar scenario:

ScreenShot

In this scenario a mobile application executes for example a login through a web api.
The server, through Socket.io, will dispatch a signal that a new client is logged-in, to all the clients (e.g. a web client monitor) connected to the server through an instance of socket.io.
In this way you can monitor all the activities and actions of each client (e.g. mobile devices) connected to the server.
Imagine that you have a mobile app with a “check-in” function like Facebook.
The mobile device sends a request through a web api, sending latitude and longitude of its current position.
The server will recevive these data and will dispatch, for example, these information to a web client, connected to the server with socket.io, that can show these information on a map.

ScreenShot

How to start the server

You have just to execute under node the server.js module

How to create your custom API

With this package, is quite easy to add a new REST resource module to define your custom API.
All the API are included into the controllers folder.
To create a new REST resource module you have to open the file /controllers/index.js and to add the following directive:

app.use('/you_routing_path', require('./your_api_module_definition'));

where: you_routing_path: defines the route of the api (e.g. /api/customers) your_api_module_definition:is your custom js module that contains your REST definitions for the http verbs tha you want to implement.

API Examples

Within the controllers folder tu can find, as example purpose, the following API modules:

  • api-basic-test.js: this module shows how to implement the basic operation for a GET and a POST with the router of ExpressJS framework.

The routing of this module (see /controllers/index.js) is mapped as /apiRoute/test
There are three resources consumable as:
GET /apiRoute/test
GET /apiRoute/test/id
POST /apiRoute/test
  • api-sequelize-test.js: this module shows how to implement an API by querying data to the doyourest database by using sequelize.

There are two kind of data query: by ORM Model and by SQL String.
The routing of this module (see /controllers/index.js) is mapped as /apiRoute/sequelize.
There are three resources consumable as:
POST /apiRoute/sequelize/query/table:will executed a SELECT * on the table passed with the request path
POST /apiRoute/sequelize/customers:will load all the records of the customers table (see doyourest sample db)
POST /apiRoute/sequelize/customers/id:will load the record of the customers table filtered by the id passed with the request path
  • api-mysql-test.js: this module shows how to implement an API by querying data to the doyourest database by using the mysql driver and sequelize. Try to switch the type parameter on the database config params to test the two database drivers.

The routing of this module (see /controllers/index.js) is mapped as /apiRoute/mysql.
There is one resource consumable as:
POST /apiRoute/mysql/query/table:will executed a SELECT * on the table passed with the request path.
  • api-socketio-test.js: this module shows how to emit a signal through socket.io after performing an operation.

The routing of this module (see /controllers/index.js) is mapped as /apiRoute/geolocation.
There are two resources consumable as:
POST /apiRoute/geolocation/checkin/
POST /apiRoute/geolocation/checkout/

Tests

I developed some useful tests by using jasmine-node (https://github.com/mhevery/jasmine-node). All the tests are included into the spec folder. To run the tests you have to use the command

jasmine-node file_name-spec.js

For example to run the jwt-get-spec under the ./spec/security folder you have to type:

jasmine-node ./security/jwt-get-spec.js

Example:

describe('TOKEN GET',function(){

    it("/token with no body params, should respond with 401 status code", function(done) {
        request({
            url: TestHelper.makeBaseUrl() + '/token',
            method: 'POST'
        }, function(error, response, body){
            expect(response.statusCode).toBe(401);
            done();
        });
    });

    it("/token with a wrong user, should respond with 401 status code", function(done) {
        request({
            url: TestHelper.makeBaseUrl() + '/token',
            method: 'POST',
            json:{
                uid:"fake_user",
                pwd:"fake_password"
            }
        }, function(error, response, body){
            expect(response.statusCode).toBe(401);
            done();
        });
    });

    it("/token with a valid user, should respond with 200 status code", function(done) {
        request({
            url: TestHelper.makeBaseUrl() + '/token',
            method: 'POST',
            json:{
                uid:"my_uid_1",
                pwd:"my_pwd_1"
            }
        }, function(error, response, body){
            expect(response.statusCode).toBe(200);
            expect(body.token).toBeDefined();
            expect(body.token).not.toBeNull();
            done();
        });
    });

});

Clients

All the clients included with this package, are just an example of how to consume a RESTful sevrice under different environments and with different programming languages.
When in a client folder you will find a package.json file (e.g. Angular and jQuery), it means that you have to install it through npm.

  • iOS: the http request happens, asynchronously, through NSMutableURLRequest and NSURLSession, see L3SDKJWARequest.swift class (https://github.com/alchimya/iOS-JSON-API).
  • Android: the http request happens, asynchronously, through AsyncHttpClient (http://loopj.com/android-async-http/), see RequestHandler.java class.
  • Angular: the http request happens, asynchronously, through the $http service. The reuqested token will be stored in a $scope variable, see MainController.js controller.
  • jQuery: the http request happens, asynchronously, through thejQuery.ajax() method, see HttpRequest.js class. The reuqested token will be stored in to the body DOM element through the jQuery.data() method, see MainController.js.
  • .NET (WPF Solution): the http request happens, asynchronously, through the HttpClient, see HttpAsyncRequest.cs class.
  • PHP:...is coming...sorry!

Conclusion

Enjoy!

About

A ready to use project to develop your REST API under NodeJS.


Languages

Language:JavaScript 37.6%Language:C# 26.6%Language:Swift 19.5%Language:Java 10.0%Language:HTML 3.5%Language:CSS 2.8%