Skip to content

Commit

Permalink
http-server with data-structures is developed.
Browse files Browse the repository at this point in the history
  • Loading branch information
apalamarchuk-aqa committed Oct 29, 2019
1 parent c5297f3 commit 54cd56f
Show file tree
Hide file tree
Showing 8 changed files with 273 additions and 0 deletions.
17 changes: 17 additions & 0 deletions submissions/assmass13/data-structures/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Stack & LinkedList http-server implementation.
## Run server
`node server.js` creates server on `localhost:3000`
## Stack
1. Push: `POST /stack`\
Accepts JSON: `{ "add": <int> or <str> }`
1. Pop: `DELETE /stack`\
Removes item from the top and return its value.

## LinkedList

1. Show list: `GET /linked-list`\
Shows current LinkedList values.
1. Insert/Remove: `PATCH /linked-list`\
Accepts JSON: `{ "add": <int> or <str>, "successor": <int> or <str>, "remove": <int> or <str> }`\
Inserts `'add'` before each `'successor'` if provided, appends to list's head otherwise.\
Removes `'remove'` values.
33 changes: 33 additions & 0 deletions submissions/assmass13/data-structures/request-handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const readBody = req =>
new Promise(resolve => {
const chunks = [];

req.on('data', chunk => {
chunks.push(chunk);
});

req.on('end', () => {
resolve(Buffer.concat(chunks));
});
});

const parseJson = async req => readBody(req).then(JSON.parse);

const validValueCondition = value =>
Number.isFinite(value) || typeof value === 'string';

const parsedBodyValues = req =>
parseJson(req).then(body =>
Object.keys(body).reduce((acc, key) => {
if (['add', 'successor', 'remove'].includes(key)) {
if (!validValueCondition(body[key]))
throw SyntaxError(
`'${body[key]}' should be of type 'string' or 'number'.`
);
return { ...acc, [key]: body[key] };
}
return acc;
}, {})
);

module.exports = parsedBodyValues;
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const LinkedList = require('../structures/linked-list');
const parsedBodyValues = require('../request-handler');

class LinkedListRouter {
constructor() {
this.linkedList = new LinkedList();
this.routes = {
'GET /linked-list': this.getLinkedListRoute.bind(this),
'PATCH /linked-list': this.patchLinkedListRoute.bind(this)
};
}

getLinkedListRoute(req, res) {
res.statusCode = 200;
res.end(this.linkedList.showList().toString());
}

patchLinkedListRoute(req, res) {
return parsedBodyValues(req, res)
.then(({ add, successor, remove }) => {
if (add && successor) {
this.linkedList.insertBeforeSuccessors(add, successor);
} else if (add) {
this.linkedList.unshift(add);
} else if (remove) {
this.linkedList.removeValue(remove);
}
res.statusCode = 200;
res.end(this.linkedList.showList().toString());
})
.catch(error => {
res.statusCode = 400;
res.end(error.toString());
});
}
}

module.exports = LinkedListRouter;
38 changes: 38 additions & 0 deletions submissions/assmass13/data-structures/routers/stack-router.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const Stack = require('../structures/stack');
const parsedBodyValues = require('../request-handler');

class StackRouter {
constructor() {
this.stack = new Stack();
this.routes = {
'POST /stack': this.postStackRoute.bind(this),
'DELETE /stack': this.deleteStackRoute.bind(this)
};
}

async postStackRoute(req, res) {
return parsedBodyValues(req)
.then(({ add }) => {
this.stack.push(add);
res.statusCode = 201;
res.end(this.stack.showStack().toString());
})
.catch(error => {
res.statusCode = 400;
res.end(error.toString());
});
}

deleteStackRoute(req, res) {
const removedNode = this.stack.pop();
if (removedNode) {
res.statusCode = 200;
res.end(removedNode.value.toString());
} else {
res.statusCode = 404;
res.end('Stack is empty.');
}
}
}

module.exports = StackRouter;
22 changes: 22 additions & 0 deletions submissions/assmass13/data-structures/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const http = require('http');

const StackRouter = require('./routers/stack-router');
const LinkedListRouter = require('./routers/linked-list-router');

const routes = {
...new StackRouter().routes,
...new LinkedListRouter().routes
};

const noRouteFound = (req, res) => {
res.statusCode = 404;
res.end('Requested resource not found.');
};

const server = http.createServer((req, res) => {
const route = `${req.method} ${req.url}`;
const handler = routes[route] || noRouteFound;
handler(req, res);
});

server.listen(3000);
100 changes: 100 additions & 0 deletions submissions/assmass13/data-structures/structures/linked-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
const Node = require('./node');

module.exports = class LinkedList {
constructor() {
this.head = null;
this.tail = null;
this.length = 0;
}

pop() {
if (!this.head) return null;
let currentNode = this.head;
let newTail = currentNode;
while (currentNode.next) {
newTail = currentNode;
currentNode = currentNode.next;
}
this.tail = newTail;
this.tail.next = null;
this.length -= 1;
if (this.length === 0) {
this.head = null;
this.tail = null;
}
return currentNode;
}

shift() {
if (!this.head) return null;
const oldHead = this.head;
this.head = oldHead.next;
this.length -= 1;
if (this.length === 0) {
this.tail = null;
}
return oldHead;
}

unshift(value) {
const newNode = new Node(value);
if (!this.head) {
this.head = newNode;
this.tail = newNode;
} else {
newNode.next = this.head;
this.head = newNode;
}
this.length += 1;
return this;
}

insertBeforeSuccessors(value, successor) {
let previousNode = null;
let currentNode = this.head;

while (currentNode) {
if (currentNode.value === successor) {
const newNode = new Node(value);
if (previousNode) previousNode.next = newNode;
else this.head = newNode;
newNode.next = currentNode;
}

previousNode = currentNode;
currentNode = currentNode.next;
}
}

removeValue(removeValue) {
let previousNode = null;
let currentNode = this.head;

while (currentNode) {
if (currentNode.value === removeValue) {
if (previousNode) {
currentNode = currentNode.next;
previousNode.next = currentNode;
} else {
this.head = currentNode.next;
currentNode = this.head;
}
}

while (currentNode && currentNode.value !== removeValue) {
previousNode = currentNode;
currentNode = currentNode.next;
}
}
}

showList() {
const values = [];
let currentNode = this.head;
while (currentNode) {
values.push(currentNode.value);
currentNode = currentNode.next;
}
return values;
}
};
6 changes: 6 additions & 0 deletions submissions/assmass13/data-structures/structures/node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = class Node {
constructor(value) {
this.value = value;
this.next = null;
}
};
19 changes: 19 additions & 0 deletions submissions/assmass13/data-structures/structures/stack.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const LinkedList = require('./linked-list');

module.exports = class Stack {
constructor() {
this.linkedList = new LinkedList();
}

push(value) {
return this.linkedList.unshift(value);
}

pop() {
return this.linkedList.shift();
}

showStack() {
return this.linkedList.showList().reverse();
}
};

0 comments on commit 54cd56f

Please sign in to comment.