Skip to content

Commit 5a07d0f

Browse files
http-server with data-structures is developed.
1 parent c5297f3 commit 5a07d0f

File tree

10 files changed

+273
-0
lines changed

10 files changed

+273
-0
lines changed

submissions/amashoshyna/port-sniffer/README.md

Whitespace-only changes.

submissions/amashoshyna/port-sniffer/index.js

Whitespace-only changes.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Stack & LinkedList http-server implementation.
2+
## Run server
3+
`node server.js` creates server on `localhost:3000`
4+
## Stack
5+
1. Push: `POST /stack`\
6+
Accepts JSON: `{ "add": <int> or <str> }`
7+
1. Pop: `DELETE /stack`\
8+
Removes item from the top and return its value.
9+
10+
## LinkedList
11+
12+
1. Show list: `GET /linked-list`\
13+
Shows current LinkedList values.
14+
1. Insert/Remove: `PATCH /linked-list`\
15+
Accepts JSON: `{ "add": <int> or <str>, "successor": <int> or <str>, "remove": <int> or <str> }`\
16+
Inserts `'add'` before each `'successor'` if provided, appends to list's head otherwise.\
17+
Removes `'remove'` values.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
const readBody = req =>
2+
new Promise(resolve => {
3+
const chunks = [];
4+
5+
req.on('data', chunk => {
6+
chunks.push(chunk);
7+
});
8+
9+
req.on('end', () => {
10+
resolve(Buffer.concat(chunks));
11+
});
12+
});
13+
14+
const parseJson = async req => readBody(req).then(JSON.parse);
15+
16+
const validValueCondition = value =>
17+
Number.isFinite(value) || typeof value === 'string';
18+
19+
const parsedBodyValues = req =>
20+
parseJson(req).then(body =>
21+
Object.keys(body).reduce((acc, key) => {
22+
if (['add', 'successor', 'remove'].includes(key)) {
23+
if (!validValueCondition(body[key]))
24+
throw SyntaxError(
25+
`'${body[key]}' should be of type 'string' or 'number'.`
26+
);
27+
return { ...acc, [key]: body[key] };
28+
}
29+
return acc;
30+
}, {})
31+
);
32+
33+
module.exports = parsedBodyValues;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
const LinkedList = require('../structures/linked-list');
2+
const parsedBodyValues = require('../request-handler');
3+
4+
class LinkedListRouter {
5+
constructor() {
6+
this.linkedList = new LinkedList();
7+
this.routes = {
8+
'GET /linked-list': this.getLinkedListRoute.bind(this),
9+
'PATCH /linked-list': this.patchLinkedListRoute.bind(this)
10+
};
11+
}
12+
13+
getLinkedListRoute(req, res) {
14+
res.statusCode = 200;
15+
res.end(this.linkedList.showList().toString());
16+
}
17+
18+
patchLinkedListRoute(req, res) {
19+
return parsedBodyValues(req, res)
20+
.then(({ add, successor, remove }) => {
21+
if (add && successor) {
22+
this.linkedList.insertBeforeSuccessors(add, successor);
23+
} else if (add) {
24+
this.linkedList.unshift(add);
25+
} else if (remove) {
26+
this.linkedList.removeValue(remove);
27+
}
28+
res.statusCode = 200;
29+
res.end(this.linkedList.showList().toString());
30+
})
31+
.catch(error => {
32+
res.statusCode = 400;
33+
res.end(error.toString());
34+
});
35+
}
36+
}
37+
38+
module.exports = LinkedListRouter;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
const Stack = require('../structures/stack');
2+
const parsedBodyValues = require('../request-handler');
3+
4+
class StackRouter {
5+
constructor() {
6+
this.stack = new Stack();
7+
this.routes = {
8+
'POST /stack': this.postStackRoute.bind(this),
9+
'DELETE /stack': this.deleteStackRoute.bind(this)
10+
};
11+
}
12+
13+
async postStackRoute(req, res) {
14+
return parsedBodyValues(req)
15+
.then(({ add }) => {
16+
this.stack.push(add);
17+
res.statusCode = 201;
18+
res.end(this.stack.showStack().toString());
19+
})
20+
.catch(error => {
21+
res.statusCode = 400;
22+
res.end(error.toString());
23+
});
24+
}
25+
26+
deleteStackRoute(req, res) {
27+
const removedNode = this.stack.pop();
28+
if (removedNode) {
29+
res.statusCode = 200;
30+
res.end(removedNode.value.toString());
31+
} else {
32+
res.statusCode = 404;
33+
res.end('Stack is empty.');
34+
}
35+
}
36+
}
37+
38+
module.exports = StackRouter;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const http = require('http');
2+
3+
const StackRouter = require('./routers/stack-router');
4+
const LinkedListRouter = require('./routers/linked-list-router');
5+
6+
const routes = {
7+
...new StackRouter().routes,
8+
...new LinkedListRouter().routes
9+
};
10+
11+
const noRouteFound = (req, res) => {
12+
res.statusCode = 404;
13+
res.end('Requested resource not found.');
14+
};
15+
16+
const server = http.createServer((req, res) => {
17+
const route = `${req.method} ${req.url}`;
18+
const handler = routes[route] || noRouteFound;
19+
handler(req, res);
20+
});
21+
22+
server.listen(3000);
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
const Node = require('./node');
2+
3+
module.exports = class LinkedList {
4+
constructor() {
5+
this.head = null;
6+
this.tail = null;
7+
this.length = 0;
8+
}
9+
10+
pop() {
11+
if (!this.head) return null;
12+
let currentNode = this.head;
13+
let newTail = currentNode;
14+
while (currentNode.next) {
15+
newTail = currentNode;
16+
currentNode = currentNode.next;
17+
}
18+
this.tail = newTail;
19+
this.tail.next = null;
20+
this.length -= 1;
21+
if (this.length === 0) {
22+
this.head = null;
23+
this.tail = null;
24+
}
25+
return currentNode;
26+
}
27+
28+
shift() {
29+
if (!this.head) return null;
30+
const oldHead = this.head;
31+
this.head = oldHead.next;
32+
this.length -= 1;
33+
if (this.length === 0) {
34+
this.tail = null;
35+
}
36+
return oldHead;
37+
}
38+
39+
unshift(value) {
40+
const newNode = new Node(value);
41+
if (!this.head) {
42+
this.head = newNode;
43+
this.tail = newNode;
44+
} else {
45+
newNode.next = this.head;
46+
this.head = newNode;
47+
}
48+
this.length += 1;
49+
return this;
50+
}
51+
52+
insertBeforeSuccessors(value, successor) {
53+
let previousNode = null;
54+
let currentNode = this.head;
55+
56+
while (currentNode) {
57+
if (currentNode.value === successor) {
58+
const newNode = new Node(value);
59+
if (previousNode) previousNode.next = newNode;
60+
else this.head = newNode;
61+
newNode.next = currentNode;
62+
}
63+
64+
previousNode = currentNode;
65+
currentNode = currentNode.next;
66+
}
67+
}
68+
69+
removeValue(removeValue) {
70+
let previousNode = null;
71+
let currentNode = this.head;
72+
73+
while (currentNode) {
74+
if (currentNode.value === removeValue) {
75+
if (previousNode) {
76+
currentNode = currentNode.next;
77+
previousNode.next = currentNode;
78+
} else {
79+
this.head = currentNode.next;
80+
currentNode = this.head;
81+
}
82+
}
83+
84+
while (currentNode && currentNode.value !== removeValue) {
85+
previousNode = currentNode;
86+
currentNode = currentNode.next;
87+
}
88+
}
89+
}
90+
91+
showList() {
92+
const values = [];
93+
let currentNode = this.head;
94+
while (currentNode) {
95+
values.push(currentNode.value);
96+
currentNode = currentNode.next;
97+
}
98+
return values;
99+
}
100+
};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = class Node {
2+
constructor(value) {
3+
this.value = value;
4+
this.next = null;
5+
}
6+
};
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
const LinkedList = require('./linked-list');
2+
3+
module.exports = class Stack {
4+
constructor() {
5+
this.linkedList = new LinkedList();
6+
}
7+
8+
push(value) {
9+
return this.linkedList.unshift(value);
10+
}
11+
12+
pop() {
13+
return this.linkedList.shift();
14+
}
15+
16+
showStack() {
17+
return this.linkedList.showList().reverse();
18+
}
19+
};

0 commit comments

Comments
 (0)