About majidai

majidai is a configuration centralized nodejs web framework. It works on native node environment without installing other third party libraries.

It is released under MIT liscense.

Installation

Install the framework by using following command.
                        
npm install majidai
                        

create server.js with the following content and run "node server.js" from the same directory.

                            
const majidai = require("majidai");
const server = new majidai();
server.start();
                            

Open the browser and access to http://locahost. You will see following page.

majidai top page

※ By default, majidai listens at 80 port which can be changed by passing http.port parameter.


const config = {
    http: {
        port: 8000
    }
};
const server = new majidai(config);

OR

in one line

const server = new majidai({http: {port: 8000}});

Logging

majidai emits 2 types of events which can be used for logging purpose.

  1. stdout: it contains client information(access time,ip,http method) in json object format
  2. stderr: it contains error message
                            
const server = new majidai();

server.on('stdout', function (data) {
    console.log(data);
    // {time: '', ip: '', hostName: '', userAgent: '', referrer: '', url: '', method: ''}

    // write to file if needed
});

server.on('stderr', function (data) {
    console.error(data);
    // error content (string)

    // write to file if needed
});

server.start();
                            

Structure

This is the general style for writing code using majidai.


server.METHOD(PATH, CALLBACK)

"METHOD" denotes following 3 methods for creating a route.

  1. get : only listens for http GET method
  2. post: only listens for http POST method
  3. listen: listens for multiple http methods

"PATH" denotes a path to listen. For eg, "/", "/top",etc

majidai supports parameterized routing. string placed between "{}" in a PATH will be the key for getting data.
                                
server.get('/order/{item}/{quantity}', (request, response) => {
    // when  a request is http://〇〇/order/orange/20

    // get item name
    var itemName = request.mj.getParams("item");
    console.log(itemName);
    // oranage

    // get item quantity
    var itemQuantity  = request.mj.getParams("quantiry");
    console.log(itemQuantity);
    // 20


    // OR
    // get all data
    var getData = request.mj.getParams();
    console.log(getData);
    // { item: 'orange', quantity: '20' }

    // get value for item
    var itemName_ = getData.item;
    console.log(itemName_);
    // oranage

    // get value for quantity
    var itemQuantity_ = getData.quantity;
    console.log(itemQuantity_);
    // 20

    return "something";
});
                                
                            

It works on all 3 methods(get,post,listen).

"CALLBACK" is a function which receives request<http.IncomingMessage> and response<http.ServerResponse> object as argument. Return statement from CALLBACK will be the response.

    
function CALLBACK(request, response){
    // do something

    return "response";
}
    

it adds "mj" object to the request<http.IncomingMessage> argument of the CALLBACK, which helps to get the data sent from user in json object format.

  1. getParms : returns GET request DATA as json object.
  2. postParams: returns POST request DATA as json object.

※ request has all <http.IncomingMessage> properties and methods beside "mj" added by majidai.

it adds "mj" object to the response<http.ServerResponse> argument of the CALLBACK, which has following functions to send different types of response.

  1. text : respond plain text
  2. json: respond json object
  3. html: respond html
  4. static: respond static html file
  5. error: respond with http error code
  6. redirect: redirect to different url

※ response has all <http.ServerResponse> properties and methods beside "mj" added by majidai.


Methods

get

This method listens for http GET request for a specific path.
server.get - <path>, <callback>
parameter type description
path string path to listen request(eg, "/", "/top",etc)
callback function function to run while GET request is received to the path argument.
                            
const server = new majidai();

server.get('/top', (request, response) => {
    // do something
    // code for GET request at http://〇〇/top

    return "something";
});

server.start();
                            

post

This method listens for http POST request for a specific path.
server.post - <path>, <callback>
parameter type description
path string path to listen request(eg, "/", "/top",etc)
callback function function to run while POST request is received to the path argument.
                            
const server = new majidai();

server.post('/login', (request, response) => {
    // do something
    // code for POST request at http://〇〇/login

    return "something";
});

server.start();
                            

listen

This method listens for multiple http methods on single path.
server.listen - <routeObj>, <callback>
parameter type description
routeObj object it is json object {method: [], path: ''} where "method" is a array of http methods and "path" is a path to listen request
callback function function to run while request is received to the path argument.
                            
const server = new majidai();

server.listen({ method: ["GET", "POST"], path: "/profile" }, (request, response) => {
    // do something
    // code for both GET request & POST request at http://〇〇/profile

    return "something";
});

server.start();
                            

Access to Data Sent By Client

getParams

request.mj.getParams - <key>?
All the data sent through GET request will be accessed through this method.
parameter type description
key string (optional) name of key whose value is to be known.

If no parameter is passed, it will return all the GET data in JSON format.


const server = new majidai();

server.get("/home", (request,response) => {
    // get the value of price when request is http://〇〇/home?price=230)
    var price = request.mj.getParams("price");
    console.log(price);
    // 230
    
    // OR
    // get all data
    var getData = request.mj.getParams();
    console.log(getData);
    // { price: '230' }
    
    // get value for price
    var price_ = getData.price;
    console.log(price);
    // 230


    return "something";
});

server.start();

it works on all types of routing including parameterized routing.


server.post("/home/{user}", (request,response) => {  
    // when POST request is received at http://〇〇/home/dakc?page=profile   

    // get all data for GET parameter
    var getData = request.mj.getParams();
    console.log(getData);
    // { page: 'profile', user: 'dakc' }

    return "something";
});    

postParams

response.mj.postParams - <key>?

This method will return the data sent as POST parameter. Data sent through x-www-form-urlencoded, application/json will be returned as json object.

parameter type description
key string (optional) key to get data

If no argument is passed, it will return all the data in JSON format.


const server = new majidai();

server.post("/home", (request,response) => {  
    // lets get the value of price (eg, <input name="price" value="2000">)
    var price = request.mj.postParams("price");

    // get all data send by POST method
    var postData = request.mj.postParams();
    // get value for id
    var idSent = postData.id;

    // do something

    return "something";
});

server.start();

※ multipart/form-data is not supported by default, but we can use other libraries.


Respond to client

text

response.mj.text - <content>,<status code>?
This method will respond as plain text.
parameter type description
content string content to respond
status code number(optional) default 200

const server = new majidai();

server.get("/", (request, response) => {
    return response.mj.text("Hello!");
});

server.start();

Returning a string from callback will also respond as plain/text.


const server = new majidai();

server.get("/", (request, response) => {
    return "Hello!";
});

server.start();

json

response.mj.json - <content>,<status code>?
This method will respond the content as json.
parameter type description
content object json object to respond
status code number(optional) default 200

const server = new majidai();

server.get("/", (request, response) => {
    return response.mj.json({id: 1, name: 'majidai'});
});

server.start();

Returning a json object from callback will also respond as application/json.


const server = new majidai();

server.get("/", (request, response) => {
    return {id: 1, name: 'majidai'};
});

server.start();

static

response.mj.static - <file path>,<status code>?
This method will respond content from static files.
parameter type description
file path string either absolute or relative path
status code number(optional) default 200

const server = new majidai();

server.get("/", (request, response) => {
    return response.mj.static("/somewhere/static/home.html");
});

server.start();

Beside this, refer to serving static for files at specific folder.

redirect

response.mj.redirect - <url>
This method will redirect to given url
parameter type description
url string url to redirect

const server = new majidai();

server.get("/", (request, response) => {
    // redirect to somewhere 
    return response.mj.redirect("/somewhere");
});

server.start();

error

response.mj.error - <error code>,<error msg>?
This method will respond error.
parameter type description
error code number error code like, 401,500,..
error msg string(optional) error content(if not set, then default http error message will be send)

const server = new majidai();

server.get("/", (request, response) => {
    // return internal server error
    return response.mj.error(500);
});

server.start();

Serve Static

By default, static serving function is set to off. By setting the "documentRoot" of "http" property to a existing directory, majidai will serve all the static files below that path.


const config = {
    directoryIndex: "index.html",   // default page to display when directory is accessed
    directoryTraversal: true,       // it will list all the files if no directoryIndex was found (Default: false)
    http: {
        documentRoot: '/var/www/html' // files below this directory will be accessible through web
    }
};
const server = new majidai(config);
server.start();

Put index.html with javascript files and css files on documentRoot directory and access to http://localhost. You will be able to see the contents of index.html.

Customize Error Page

We can customize error page by calling "customizeErrorPage" method.

server.customizeErrorPage - <callback>
This method will redirect to given url
parameter type description
callback function it receives error message as argument.Return value must be a object containing "content" and "contentType" as a property.

const server = new majidai();    

server.get("/", (request, response) => {
    // return internal server error
    return response.mj.error(500, "contact to server admin");
});

server.start();

// customize error page
server.customizeErrorPage(function(errContent) {
    // format to html
    let htmlContent = `
        <html>
        <head>
        <title>custom error</title>
        </head>
        <body>
        <h1><span style='color:#ff0000'>Woops!</span> Something Went Wrong</h1>
        <p>${errContent}</p>
        </body>
        </html>
    `;
    
    // must return a object with "contentType" and "content"
    return {
        contentType: "text/html",
        content: htmlContent
    };
});

        

setMimeType

If mimetype is not supported by default, We can Set the mimetype for file extension by using "setMimeType" method.

server.setMimeType - <ext>,<mimetype>
This method will redirect to given url
parameter type description
ext string file extension must start with dot(eg, '.gif')
mimetype string mimetype for the extension(eg, 'image/gif')

const server = new majidai();

server.setMimeType(".gif", "image/gif");

server.get("/", (request, response) => {
    // show gif image on browser
    return response.mj.static("/somewhere/something.gif");
});

server.start();

        

configuration

majidia is a configuration centralized framework. We can create a config based on environment.

Below is the default configuration. We can change the content and create different types of configuration files as per our need.
For eg,

  1. config.dev.js
  2. config.prod.js


module.exports = {
    // ===========================================
    // common configuration
    contentType: "text/plain",
    charset: "utf-8",
    maxBodySize: 100 * 1024, // byte
    directoryIndex: "index.html",
    directoryTraversal: false,
    allowedMethod: ["GET", "POST", "HEAD", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE", "PATCH"],
    responseHeader: {
        "x-frame-options": "SAMEORIGIN",
        "x-xss-protection": "0",
        "server": "majidai/2.1",
        "Access-Control-Allow-Origin": "*",
        "Accept": "*/*",
    },
    
    // ===========================================
    // http configuration
    http: {
        port: 80,
        host: "0.0.0.0",
        documentRoot: "",
        listen: true,
    },

    // ===========================================
    // https configuration
    https: {
        port: 443,
        host: "0.0.0.0",
        documentRoot: "",
        listen: false,
        http2: false,
        pfx: "",
        passphrase: "",
    },
};

        

Create https server

By default, "listen" property for https is set to "false". By changing it to "true" and passing the ssl certificate in "PKCS#12" format, we can easily create https server.
Also http2 protocol is set to off by default. We can activate it by just passing http2 attribute set to true.

        
const majidai = require("majidai");

var config = {
    https: {
        listen: true,
        documentRoot: "public",
        pfx: "ssl/certificate.pfx",
        passphrase: "p@ssword",
        http2:true
    }
};

let server = new majidai(config);

server.on('stdout', data => console.log(data));
server.on('stderr', data => console.error(data));

server.start();
        
        

sample


// import majidai 
const majidai = require("majidai");

// import configuration for dev environment
const config = require("config.dev.js"):

// create majidai server instance
const server = new majidai(config):

// show the client information on console
server.on("stdout", data => console.log(data));

// on error show on console
server.on("stderr", data => console.error(data));

// create routing that listens for GET & POST
server.listen({methods: ["GET", "POST"], path: "/order/{item}/{quantity}"}, req => {
    // get all GET data
    var getData = req.mj.getParams();

    // get all POST data
    var postData = req.mj.postParams();

    // return all data as application/json
    return {
        get: getData,
        post: postData
    }
});

// start server
server.start();

docker


docker run -it --rm -p 80:80 dakc/majidai npx /data/server.js