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.
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.
※ 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);
const server = new majidai({http: {port: 8000}});
majidai emits 2 types of events which can be used for logging purpose.
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();
This is the general style for writing code using majidai.
server.METHOD(PATH, CALLBACK)
"METHOD" denotes following 3 methods for creating a route.
"PATH" denotes a path to listen. For eg, "/", "/top",etc
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.
※ 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.
※ response has all <http.ServerResponse> properties and methods beside "mj" added by majidai.
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();
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();
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();
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";
});
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.
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();
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();
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.
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();
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();
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.
We can customize error page by calling "customizeErrorPage" method.
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
};
});
If mimetype is not supported by default, We can Set the mimetype for file extension by using "setMimeType" method.
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();
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,
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: "",
},
};
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();
// 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 run -it --rm -p 80:80 dakc/majidai npx /data/server.js