From 9d780f33430575863a244d47073032e6edd4dfd8 Mon Sep 17 00:00:00 2001 From: radium Date: Wed, 21 Jun 2017 16:06:52 +0530 Subject: [PATCH] Radium: BackendChallenge --- .gitignore | 1 + Startup Guide.txt | 30 ++++++++ package.json | 25 +++++++ router/router.js | 184 ++++++++++++++++++++++++++++++++++++++++++++++ server.js | 16 ++++ 5 files changed, 256 insertions(+) create mode 100644 .gitignore create mode 100644 Startup Guide.txt create mode 100644 package.json create mode 100644 router/router.js create mode 100644 server.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/Startup Guide.txt b/Startup Guide.txt new file mode 100644 index 0000000..cecbdcd --- /dev/null +++ b/Startup Guide.txt @@ -0,0 +1,30 @@ +Steps to use:- + +1. Give the following commands:- + + - npm install- To install all the dependencies + - npm start- To start the server + +2. The server is built on NodeJS so it needs to be installed to run this application. + +2. Following end points have been made:- + - /stats :- + - This end point gives all the stats about the requests made. + - It uses GET method to get all the data statistics. + + - /process :- + + - This end point uses GET,POST,PUT and DELETE methods. + - GET : This method responds with a json containing all requests made since server startup. + It also creates its own get request containing all the specified json data. + - POST : This method posts a request to the server with the specified json attributes with each request containing its own id. + + - /process/id :- + - GET : This method serves the json response for that id request. + - PUT : This method updates the requested id document with the content specified in body with x-wwww-form-urlencoded key value pairs if they are present in the json object. + - DELETE : This request deletes the requested object based on its id. + + /stats :- + - GET : This method gives all the statistics related to the requests made till the server startup as mentioned in the challenge. + + 3. A time delay of 1 second has been given to all the requests which can be changed as per requirements. diff --git a/package.json b/package.json new file mode 100644 index 0000000..ab8a162 --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "app", + "version": "1.0.0", + "description": "Create a web server with two endpoints:", + "main": "server.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "nodemon server.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/backbench/BackendChallenge.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/backbench/BackendChallenge/issues" + }, + "homepage": "https://github.com/backbench/BackendChallenge#readme", + "dependencies": { + "body-parser": "^1.17.2", + "express": "^4.15.3", + "path": "^0.12.7" + } +} diff --git a/router/router.js b/router/router.js new file mode 100644 index 0000000..29db4c4 --- /dev/null +++ b/router/router.js @@ -0,0 +1,184 @@ +module.exports=function(express,app){ + var router=express.Router(), + path=require('path'); + +var list=[]; +var get="GET",post="POST",put="PUT",del="DELETE",id=0; + +getData=(req,res,date)=>{ + + var data={ + "id":id++, + "time":date.getHours()+":"+date.getMinutes()+":"+date.getSeconds(), + "method":req.method, + "path":req.path, + "query":req.query, + "body":req.body, + "headers":req.headers, + "duration":0 + }; + return data; +} + +responseTimeoutList=(req,res,data,startTime)=>{ + setTimeout(()=>{ + data.duration=Math.abs(new Date().getSeconds()-startTime)%60; + list.push(data); + res.json(list); + },1000) +} + +responseTimeoutData=(req,res,data,startTime)=>{ + setTimeout(()=>{ + data.duration=Math.abs(new Date().getSeconds()-startTime)%60; + list.push(data); + res.json(data); + },1000) +} + + +filterListOnMethod=(method)=>{ + var getList=list.filter(l=>{ + return l.method==method + }) + return getList; +} + +no_Of_requests=(method)=>{ + var getList=filterListOnMethod(method); + return getList.length; +} + +getFromTime=(time,index)=>{ + var timeList=time.split(":"); + return parseInt(timeList[index]); +} + + +getFilteredList=(method)=>{ + var getList=filterListOnMethod(method); + if(getList.length==0)return null; + return getList; +} + +getSumList=(filterList)=>{ + if(filterList.length==0)return -1; + var sumList=filterList.map(l=>{ + return l.duration; + }); + var sum =sumList.reduce((a,b)=>{ + return a+b; + }); + sum/=sumList.length; + return sum; +} + +getAvgResTimePastHour=(method)=>{ + var getList=getFilteredList(method); + if(getList==null)return -1; + var filterList=getList.filter(l=>{ + var currHour=new Date().getHours(); + var prevHour=getFromTime(l.time,0); + var requestHour=Math.abs(currHour-prevHour); + if(requestHour<1)return l; + }); + + return getSumList(filterList); +} + +getAvgResTimePastMin=(method)=>{ + var getList=getFilteredList(method); + if(getList==null)return -1; + var filterList=getList.filter(l=>{ + var currMin=new Date().getMinutes(); + var prevMin=getFromTime(l.time,1); + var requestMin=Math.abs(currMin-prevMin); + if(requestMin<1)return l; + }); + + return getSumList(filterList); +} + +router.get('/',(req,res,next)=>{ + res.send('Welcome to the application: Try the following end points- /process , /stats'); +}) + +router.get('/process',(req,res,next)=>{ + var date=new Date(); + var startTime=date.getSeconds(); + var data=getData(req,res,date); + responseTimeoutList(req,res,data,startTime); +}) + +router.get('/process/:id',(req,res,next)=>{ + var date=new Date(); + var startTime=date.getSeconds(); + list.push(getData(req,res,date)); + var data=list.filter(l=>{ + if(l.id==req.params.id)return l; + }) + if(data==null || data.length==0)res.send('No such data for this id'); + else res.json(data); +}) + +router.post('/process',(req,res,next)=>{ + var date=new Date(); + var startTime=date.getSeconds(); + var data=getData(req,res,date); + responseTimeoutData(req,res,data,startTime); +}) +router.put('/process/:id',(req,res,next)=>{ + var date=new Date(); + var startTime=date.getSeconds(); + list=list.filter(l=>{ + if(l.id==req.params.id){ + if(req.body.id)l.id=parseInt(req.body.id); + if(req.body.time)l.time=req.body.time; + if(req.body.method)l.method=req.body.method; + if(req.body.path)l.path=req.body.path; + if(req.body.query)l.query=req.body.query; + if(req.body.duration)l.duration=req.body.duration; + } + return l; + }); + var idList=list.filter(l=>{ + if(l.id==req.params.id)return l; + }); + var data=getData(req,res,date); + responseTimeoutList(req,res,data,startTime); +}) +router.delete('/process/:id',(req,res,next)=>{ + var date=new Date(); + var startTime=date.getSeconds(); + list=list.filter(l=>{ + if(l.id!=req.params.id)return l; + }); + var data=getData(req,res,date); + responseTimeoutList(req,res,data,startTime); +}) + +router.get('/stats',(req,res,next)=>{ + +if(list==null || list.length==0)res.send('Sorry no stats available you need to make post request first'); + +var statData={ + "total requests":list.length, + "No of GET requests":no_Of_requests(get), + "No of POST requests":no_Of_requests(post), + "No of PUT requests":no_Of_requests(put), + "No of DELETE requests":no_Of_requests(del), + "Avg response time of Get request past hour":getAvgResTimePastHour(get), + "Avg response time of Post request past hour":getAvgResTimePastHour(post), + "Avg response time of Put request past hour":getAvgResTimePastHour(put), + "Avg response time of Delete request past hour":getAvgResTimePastHour(del), + "Avg response time of Get request past minute":getAvgResTimePastMin(get), + "Avg response time of Post request past minute":getAvgResTimePastMin(post), + "Avg response time of Put request past minute":getAvgResTimePastMin(put), + "Avg response time of Delete request past minute":getAvgResTimePastMin(del) +} + +res.json(statData); +}) + +app.use('/',router); +} diff --git a/server.js b/server.js new file mode 100644 index 0000000..c58829c --- /dev/null +++ b/server.js @@ -0,0 +1,16 @@ +var express=require('express'); +var path=require('path'); +var app=express(); +var bodyParser=require('body-parser'); + +app.use(bodyParser.urlencoded({extended:true})); +app.use(bodyParser.json()); + +require('./router/router.js')(express,app); + +app.listen(3000,(err)=>{ + console.log('Server running on port 3000'); +}) + + +// Kindly refer the Startup Guide.txt for details of this project